• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/netifd/system-linux.c

  1 /*
  2  * netifd - network interface daemon
  3  * Copyright (C) 2012 Felix Fietkau <nbd@openwrt.org>
  4  * Copyright (C) 2013 Jo-Philipp Wich <jow@openwrt.org>
  5  * Copyright (C) 2013 Steven Barth <steven@midlink.org>
  6  * Copyright (C) 2014 Gioacchino Mazzurco <gio@eigenlab.org>
  7  * Copyright (C) 2017 Matthias Schiffer <mschiffer@universe-factory.net>
  8  * Copyright (C) 2018 Hans Dedecker <dedeckeh@gmail.com>
  9  *
 10  * This program is free software; you can redistribute it and/or modify
 11  * it under the terms of the GNU General Public License version 2
 12  * as published by the Free Software Foundation
 13  *
 14  * This program is distributed in the hope that it will be useful,
 15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 17  * GNU General Public License for more details.
 18  */
 19 #define _GNU_SOURCE
 20 #define SYSTEM_IMPL
 21 
 22 #include <sys/socket.h>
 23 #include <sys/ioctl.h>
 24 #include <sys/stat.h>
 25 #include <sys/syscall.h>
 26 
 27 #include <net/if.h>
 28 #include <net/if_arp.h>
 29 
 30 #include <limits.h>
 31 #include <netdb.h>
 32 #include <arpa/inet.h>
 33 #include <netinet/in.h>
 34 #include <netinet/ether.h>
 35 
 36 #include <linux/rtnetlink.h>
 37 #include <linux/neighbour.h>
 38 #include <linux/sockios.h>
 39 #include <linux/ip.h>
 40 #include <linux/if_addr.h>
 41 #include <linux/if_link.h>
 42 #include <linux/if_vlan.h>
 43 #include <linux/if_bridge.h>
 44 #include <linux/if_tunnel.h>
 45 #include <linux/ip6_tunnel.h>
 46 #include <linux/ethtool.h>
 47 #include <linux/fib_rules.h>
 48 #include <linux/veth.h>
 49 #include <linux/version.h>
 50 
 51 #include <sched.h>
 52 
 53 #include "ethtool-modes.h"
 54 
 55 #ifndef RTN_FAILED_POLICY
 56 #define RTN_FAILED_POLICY 12
 57 #endif
 58 
 59 #ifndef IFA_F_NOPREFIXROUTE
 60 #define IFA_F_NOPREFIXROUTE 0x200
 61 #endif
 62 
 63 #ifndef IFA_FLAGS
 64 #define IFA_FLAGS (IFA_MULTICAST + 1)
 65 #endif
 66 
 67 #include <string.h>
 68 #include <fcntl.h>
 69 #include <glob.h>
 70 #include <time.h>
 71 #include <unistd.h>
 72 
 73 #include <netlink/msg.h>
 74 #include <netlink/attr.h>
 75 #include <netlink/socket.h>
 76 #include <netlink/genl/genl.h>
 77 #include <netlink/genl/ctrl.h>
 78 #include <libubox/uloop.h>
 79 
 80 #include <linux/ethtool_netlink.h>
 81 
 82 #include "netifd.h"
 83 #include "device.h"
 84 #include "system.h"
 85 #include "utils.h"
 86 
 87 struct event_socket {
 88         struct uloop_fd uloop;
 89         struct nl_sock *sock;
 90         int bufsize;
 91 };
 92 
 93 static int sock_ioctl = -1;
 94 static struct nl_sock *sock_rtnl = NULL;
 95 static struct nl_sock *sock_genl = NULL;
 96 static int ethtool_family = -1;
 97 
 98 static int cb_rtnl_event(struct nl_msg *msg, void *arg);
 99 static void handle_hotplug_event(struct uloop_fd *u, unsigned int events);
100 static int system_add_proto_tunnel(const char *name, const uint8_t proto,
101                                         const unsigned int link, struct blob_attr **tb);
102 
103 static char dev_buf[256];
104 static const char *proc_path = "/proc";
105 static const char *sysfs_path = "/sys";
106 
107 struct netdev_type {
108         unsigned short id;
109         const char *name;
110 };
111 
112 static const struct netdev_type netdev_types[] = {
113         {ARPHRD_NETROM, "netrom"},
114         {ARPHRD_ETHER, "ethernet"},
115         {ARPHRD_EETHER, "eethernet"},
116         {ARPHRD_AX25, "ax25"},
117         {ARPHRD_PRONET, "pronet"},
118         {ARPHRD_CHAOS, "chaos"},
119         {ARPHRD_IEEE802, "ieee802"},
120         {ARPHRD_ARCNET, "arcnet"},
121         {ARPHRD_APPLETLK, "appletlk"},
122         {ARPHRD_DLCI, "dlci"},
123         {ARPHRD_ATM, "atm"},
124         {ARPHRD_METRICOM, "metricom"},
125         {ARPHRD_IEEE1394, "ieee1394"},
126         {ARPHRD_EUI64, "eui64"},
127         {ARPHRD_INFINIBAND, "infiniband"},
128         {ARPHRD_SLIP, "slip"},
129         {ARPHRD_CSLIP, "cslip"},
130         {ARPHRD_SLIP6, "slip6"},
131         {ARPHRD_CSLIP6, "cslip6"},
132         {ARPHRD_RSRVD, "rsrvd"},
133         {ARPHRD_ADAPT, "adapt"},
134         {ARPHRD_ROSE, "rose"},
135         {ARPHRD_X25, "x25"},
136         {ARPHRD_HWX25, "hwx25"},
137         {ARPHRD_PPP, "ppp"},
138         {ARPHRD_CISCO, "cisco"},
139         {ARPHRD_LAPB, "lapb"},
140         {ARPHRD_DDCMP, "ddcmp"},
141         {ARPHRD_RAWHDLC, "rawhdlc"},
142         {ARPHRD_TUNNEL, "tunnel"},
143         {ARPHRD_TUNNEL6, "tunnel6"},
144         {ARPHRD_FRAD, "frad"},
145         {ARPHRD_SKIP, "skip"},
146         {ARPHRD_LOOPBACK, "loopback"},
147         {ARPHRD_LOCALTLK, "localtlk"},
148         {ARPHRD_FDDI, "fddi"},
149         {ARPHRD_BIF, "bif"},
150         {ARPHRD_SIT, "sit"},
151         {ARPHRD_IPDDP, "ipddp"},
152         {ARPHRD_IPGRE, "ipgre"},
153         {ARPHRD_PIMREG,"pimreg"},
154         {ARPHRD_HIPPI, "hippi"},
155         {ARPHRD_ASH, "ash"},
156         {ARPHRD_ECONET, "econet"},
157         {ARPHRD_IRDA, "irda"},
158         {ARPHRD_FCPP, "fcpp"},
159         {ARPHRD_FCAL, "fcal"},
160         {ARPHRD_FCPL, "fcpl"},
161         {ARPHRD_FCFABRIC, "fcfabric"},
162         {ARPHRD_IEEE80211, "ieee80211"},
163         {ARPHRD_IEEE80211_PRISM, "ie80211-prism"},
164         {ARPHRD_IEEE80211_RADIOTAP, "ieee80211-radiotap"},
165 #ifdef ARPHRD_PHONET
166         {ARPHRD_PHONET, "phonet"},
167 #endif
168 #ifdef ARPHRD_PHONET_PIPE
169         {ARPHRD_PHONET_PIPE, "phonet-pipe"},
170 #endif
171         {ARPHRD_IEEE802154, "ieee802154"},
172         {ARPHRD_VOID, "void"},
173         {ARPHRD_NONE, "none"}
174 };
175 
176 static void
177 handler_nl_event(struct uloop_fd *u, unsigned int events)
178 {
179         struct event_socket *ev = container_of(u, struct event_socket, uloop);
180         int ret;
181 
182         ret = nl_recvmsgs_default(ev->sock);
183         if (ret >= 0)
184                 return;
185 
186         switch (-ret) {
187         case NLE_NOMEM:
188                 /* Increase rx buffer size on netlink socket */
189                 ev->bufsize *= 2;
190                 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
191                         goto abort;
192 
193                 /* Request full dump since some info got dropped */
194                 struct rtgenmsg msg = { .rtgen_family = AF_UNSPEC };
195                 nl_send_simple(ev->sock, RTM_GETLINK, NLM_F_DUMP, &msg, sizeof(msg));
196                 break;
197 
198         default:
199                 goto abort;
200         }
201         return;
202 
203 abort:
204         uloop_fd_delete(&ev->uloop);
205         return;
206 }
207 
208 static void
209 nl_udebug_cb(void *priv, struct nl_msg *msg)
210 {
211         struct nlmsghdr *nlh = nlmsg_hdr(msg);
212 
213         udebug_netlink_msg(priv, nlmsg_get_proto(msg), nlh, nlh->nlmsg_len);
214 }
215 
216 static struct nl_sock *
217 create_socket(int protocol, int groups)
218 {
219         struct nl_sock *sock;
220 
221         sock = nl_socket_alloc();
222         if (!sock)
223                 return NULL;
224 
225         if (groups)
226                 nl_join_groups(sock, groups);
227 
228         if (nl_connect(sock, protocol)) {
229                 nl_socket_free(sock);
230                 return NULL;
231         }
232 
233         nl_socket_set_tx_debug_cb(sock, nl_udebug_cb, &udb_nl);
234         nl_socket_set_rx_debug_cb(sock, nl_udebug_cb, &udb_nl);
235 
236         return sock;
237 }
238 
239 static bool
240 create_raw_event_socket(struct event_socket *ev, int protocol, int groups,
241                         uloop_fd_handler cb, int flags)
242 {
243         ev->sock = create_socket(protocol, groups);
244         if (!ev->sock)
245                 return false;
246 
247         ev->uloop.fd = nl_socket_get_fd(ev->sock);
248         ev->uloop.cb = cb;
249         if (uloop_fd_add(&ev->uloop, ULOOP_READ|flags))
250                 return false;
251 
252         return true;
253 }
254 
255 static bool
256 create_event_socket(struct event_socket *ev, int protocol,
257                     int (*cb)(struct nl_msg *msg, void *arg))
258 {
259         if (!create_raw_event_socket(ev, protocol, 0, handler_nl_event, ULOOP_ERROR_CB))
260                 return false;
261 
262         /* Install the valid custom callback handler */
263         nl_socket_modify_cb(ev->sock, NL_CB_VALID, NL_CB_CUSTOM, cb, NULL);
264 
265         /* Disable sequence number checking on event sockets */
266         nl_socket_disable_seq_check(ev->sock);
267 
268         /* Increase rx buffer size to 65K on event sockets */
269         ev->bufsize = 65535;
270         if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
271                 return false;
272 
273         return true;
274 }
275 
276 static bool
277 create_hotplug_event_socket(struct event_socket *ev, int protocol,
278                             void (*cb)(struct uloop_fd *u, unsigned int events))
279 {
280         if (!create_raw_event_socket(ev, protocol, 1, cb, ULOOP_ERROR_CB))
281                 return false;
282 
283         /* Increase rx buffer size to 65K on event sockets */
284         ev->bufsize = 65535;
285         if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
286                 return false;
287 
288         return true;
289 }
290 
291 static bool
292 system_rtn_aton(const char *src, unsigned int *dst)
293 {
294         char *e;
295         unsigned int n;
296 
297         if (!strcmp(src, "local"))
298                 n = RTN_LOCAL;
299         else if (!strcmp(src, "nat"))
300                 n = RTN_NAT;
301         else if (!strcmp(src, "broadcast"))
302                 n = RTN_BROADCAST;
303         else if (!strcmp(src, "anycast"))
304                 n = RTN_ANYCAST;
305         else if (!strcmp(src, "multicast"))
306                 n = RTN_MULTICAST;
307         else if (!strcmp(src, "prohibit"))
308                 n = RTN_PROHIBIT;
309         else if (!strcmp(src, "unreachable"))
310                 n = RTN_UNREACHABLE;
311         else if (!strcmp(src, "blackhole"))
312                 n = RTN_BLACKHOLE;
313         else if (!strcmp(src, "xresolve"))
314                 n = RTN_XRESOLVE;
315         else if (!strcmp(src, "unicast"))
316                 n = RTN_UNICAST;
317         else if (!strcmp(src, "throw"))
318                 n = RTN_THROW;
319         else if (!strcmp(src, "failed_policy"))
320                 n = RTN_FAILED_POLICY;
321         else {
322                 n = strtoul(src, &e, 0);
323                 if (!e || *e || e == src || n > 255)
324                         return false;
325         }
326 
327         *dst = n;
328         return true;
329 }
330 
331 static bool
332 system_tos_aton(const char *src, unsigned *dst)
333 {
334         char *e;
335 
336         *dst = strtoul(src, &e, 16);
337         if (e == src || *e || *dst > 255)
338                 return false;
339 
340         return true;
341 }
342 
343 int system_init(void)
344 {
345         static struct event_socket rtnl_event;
346         static struct event_socket hotplug_event;
347 
348         sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0);
349         system_fd_set_cloexec(sock_ioctl);
350 
351         /* Prepare socket for routing / address control */
352         sock_rtnl = create_socket(NETLINK_ROUTE, 0);
353         if (!sock_rtnl)
354                 return -1;
355 
356         /* Prepare genetlink socket for ethtool PSE control (optional) */
357         sock_genl = nl_socket_alloc();
358         if (sock_genl) {
359                 if (genl_connect(sock_genl) == 0) {
360                         ethtool_family = genl_ctrl_resolve(sock_genl, "ethtool");
361                         if (ethtool_family < 0) {
362                                 nl_socket_free(sock_genl);
363                                 sock_genl = NULL;
364                         }
365                 } else {
366                         nl_socket_free(sock_genl);
367                         sock_genl = NULL;
368                 }
369         }
370 
371         if (!create_event_socket(&rtnl_event, NETLINK_ROUTE, cb_rtnl_event))
372                 return -1;
373 
374         if (!create_hotplug_event_socket(&hotplug_event, NETLINK_KOBJECT_UEVENT,
375                                          handle_hotplug_event))
376                 return -1;
377 
378         /* Receive network link events form kernel */
379         nl_socket_add_membership(rtnl_event.sock, RTNLGRP_LINK);
380 
381         return 0;
382 }
383 
384 static void write_file(const char *path, const char *val)
385 {
386         int fd;
387 
388         fd = open(path, O_WRONLY);
389         if (fd < 0)
390                 return;
391 
392         if (write(fd, val, strlen(val))) {}
393         close(fd);
394 }
395 
396 static int read_file(const char *path, char *buf, const size_t buf_sz)
397 {
398         int fd = -1, ret = -1;
399 
400         fd = open(path, O_RDONLY);
401         if (fd < 0)
402                 goto out;
403 
404         ssize_t len = read(fd, buf, buf_sz - 1);
405         if (len < 0)
406                 goto out;
407 
408         ret = buf[len] = 0;
409 
410 out:
411         if (fd >= 0)
412                 close(fd);
413 
414         return ret;
415 }
416 
417 
418 static const char *
419 dev_sysctl_path(const char *prefix, const char *ifname, const char *file)
420 {
421         snprintf(dev_buf, sizeof(dev_buf), "%s/sys/net/%s/%s/%s", proc_path, prefix, ifname, file);
422 
423         return dev_buf;
424 }
425 
426 static const char *
427 dev_sysfs_path(const char *ifname, const char *file)
428 {
429         snprintf(dev_buf, sizeof(dev_buf), "%s/class/net/%s/%s", sysfs_path, ifname, file);
430 
431         return dev_buf;
432 }
433 
434 static void
435 system_set_dev_sysctl(const char *prefix, const char *file, const char *ifname,
436                       const char *val)
437 {
438         write_file(dev_sysctl_path(prefix, ifname, file), val);
439 }
440 
441 static int
442 system_get_dev_sysctl(const char *prefix, const char *file, const char *ifname,
443                       char *buf, size_t buf_sz)
444 {
445         return read_file(dev_sysctl_path(prefix, ifname, file), buf, buf_sz);
446 }
447 
448 static void
449 system_set_dev_sysfs(const char *file, const char *ifname, const char *val)
450 {
451         if (!val)
452                 return;
453 
454         write_file(dev_sysfs_path(ifname, file), val);
455 }
456 
457 static void
458 system_set_dev_sysfs_int(const char *file, const char *ifname, int val)
459 {
460         char buf[16];
461 
462         snprintf(buf, sizeof(buf), "%d", val);
463         system_set_dev_sysfs(file, ifname, buf);
464 }
465 
466 static int
467 system_get_dev_sysfs(const char *file, const char *ifname, char *buf, size_t buf_sz)
468 {
469         return read_file(dev_sysfs_path(ifname, file), buf, buf_sz);
470 }
471 
472 static void system_set_disable_ipv6(struct device *dev, const char *val)
473 {
474         system_set_dev_sysctl("ipv6/conf", "disable_ipv6", dev->ifname, val);
475 }
476 
477 static void system_set_ip6segmentrouting(struct device *dev, const char *val)
478 {
479         system_set_dev_sysctl("ipv6/conf", "seg6_enabled", dev->ifname, val);
480 }
481 
482 static void system_set_rpfilter(struct device *dev, const char *val)
483 {
484         system_set_dev_sysctl("ipv4/conf", "rp_filter", dev->ifname, val);
485 }
486 
487 static void system_set_acceptlocal(struct device *dev, const char *val)
488 {
489         system_set_dev_sysctl("ipv4/conf", "accept_local", dev->ifname, val);
490 }
491 
492 static void system_set_igmpversion(struct device *dev, const char *val)
493 {
494         system_set_dev_sysctl("ipv4/conf", "force_igmp_version", dev->ifname, val);
495 }
496 
497 static void system_set_mldversion(struct device *dev, const char *val)
498 {
499         system_set_dev_sysctl("ipv6/conf", "force_mld_version", dev->ifname, val);
500 }
501 
502 static void system_set_neigh4reachabletime(struct device *dev, const char *val)
503 {
504         system_set_dev_sysctl("ipv4/neigh", "base_reachable_time_ms", dev->ifname, val);
505 }
506 
507 static void system_set_neigh6reachabletime(struct device *dev, const char *val)
508 {
509         system_set_dev_sysctl("ipv6/neigh", "base_reachable_time_ms", dev->ifname, val);
510 }
511 
512 static void system_set_neigh4gcstaletime(struct device *dev, const char *val)
513 {
514         system_set_dev_sysctl("ipv4/neigh", "gc_stale_time", dev->ifname, val);
515 }
516 
517 static void system_set_neigh6gcstaletime(struct device *dev, const char *val)
518 {
519         system_set_dev_sysctl("ipv6/neigh", "gc_stale_time", dev->ifname, val);
520 }
521 
522 static void system_set_neigh4locktime(struct device *dev, const char *val)
523 {
524         system_set_dev_sysctl("ipv4/neigh", "locktime", dev->ifname, val);
525 }
526 
527 static void system_set_dadtransmits(struct device *dev, const char *val)
528 {
529         system_set_dev_sysctl("ipv6/conf", "dad_transmits", dev->ifname, val);
530 }
531 
532 static void system_set_sendredirects(struct device *dev, const char *val)
533 {
534         system_set_dev_sysctl("ipv4/conf", "send_redirects", dev->ifname, val);
535 }
536 
537 static void system_set_drop_v4_unicast_in_l2_multicast(struct device *dev, const char *val)
538 {
539         system_set_dev_sysctl("ipv4/conf", "drop_unicast_in_l2_multicast", dev->ifname, val);
540 }
541 
542 static void system_set_drop_v6_unicast_in_l2_multicast(struct device *dev, const char *val)
543 {
544         system_set_dev_sysctl("ipv6/conf", "drop_unicast_in_l2_multicast", dev->ifname, val);
545 }
546 
547 static void system_set_drop_gratuitous_arp(struct device *dev, const char *val)
548 {
549         system_set_dev_sysctl("ipv4/conf", "drop_gratuitous_arp", dev->ifname, val);
550 }
551 
552 static void system_set_drop_unsolicited_na(struct device *dev, const char *val)
553 {
554         system_set_dev_sysctl("ipv6/conf", "drop_unsolicited_na", dev->ifname, val);
555 }
556 
557 static void system_set_arp_accept(struct device *dev, const char *val)
558 {
559         system_set_dev_sysctl("ipv4/conf", "arp_accept", dev->ifname, val);
560 }
561 
562 static void system_bridge_set_multicast_to_unicast(struct device *dev, const char *val)
563 {
564         system_set_dev_sysfs("brport/multicast_to_unicast", dev->ifname, val);
565 }
566 
567 static void system_bridge_set_multicast_fast_leave(struct device *dev, const char *val)
568 {
569         system_set_dev_sysfs("brport/multicast_fast_leave", dev->ifname, val);
570 }
571 
572 static void system_bridge_set_hairpin_mode(struct device *dev, const char *val)
573 {
574         system_set_dev_sysfs("brport/hairpin_mode", dev->ifname, val);
575 }
576 
577 static void system_bridge_set_proxyarp_wifi(struct device *dev, const char *val)
578 {
579         system_set_dev_sysfs("brport/proxyarp_wifi", dev->ifname, val);
580 }
581 
582 static void system_bridge_set_bpdu_filter(struct device *dev, const char *val)
583 {
584         system_set_dev_sysfs("brport/bpdu_filter", dev->ifname, val);
585 }
586 
587 static void system_bridge_set_isolated(struct device *dev, const char *val)
588 {
589         system_set_dev_sysfs("brport/isolated", dev->ifname, val);
590 }
591 
592 static void system_bridge_set_multicast_router(struct device *dev, const char *val)
593 {
594         system_set_dev_sysfs("brport/multicast_router", dev->ifname, val);
595 }
596 
597 void system_bridge_set_stp_state(struct device *dev, bool val)
598 {
599         const char *valstr = val ? "1" : "";
600 
601         system_set_dev_sysfs("bridge/stp_state", dev->ifname, valstr);
602 }
603 
604 static void system_bridge_set_learning(struct device *dev, const char *val)
605 {
606         system_set_dev_sysfs("brport/learning", dev->ifname, val);
607 }
608 
609 static void system_bridge_set_unicast_flood(struct device *dev, const char *val)
610 {
611         system_set_dev_sysfs("brport/unicast_flood", dev->ifname, val);
612 }
613 
614 static void system_bridge_set_broadcast_flood(struct device *dev, const char *val)
615 {
616         system_set_dev_sysfs("brport/broadcast_flood", dev->ifname, val);
617 }
618 
619 static int system_get_disable_ipv6(struct device *dev, char *buf, const size_t buf_sz)
620 {
621         return system_get_dev_sysctl("ipv6/conf", "disable_ipv6",
622                                      dev->ifname, buf, buf_sz);
623 }
624 
625 static int system_get_ip6segmentrouting(struct device *dev, char *buf, const size_t buf_sz)
626 {
627         return system_get_dev_sysctl("ipv6/conf", "seg6_enabled",
628                                      dev->ifname, buf, buf_sz);
629 }
630 
631 static int system_get_rpfilter(struct device *dev, char *buf, const size_t buf_sz)
632 {
633         return system_get_dev_sysctl("ipv4/conf", "rp_filter",
634                                      dev->ifname, buf, buf_sz);
635 }
636 
637 static int system_get_acceptlocal(struct device *dev, char *buf, const size_t buf_sz)
638 {
639         return system_get_dev_sysctl("ipv4/conf", "accept_local",
640                                      dev->ifname, buf, buf_sz);
641 }
642 
643 static int system_get_igmpversion(struct device *dev, char *buf, const size_t buf_sz)
644 {
645         return system_get_dev_sysctl("ipv4/conf", "force_igmp_version",
646                                      dev->ifname, buf, buf_sz);
647 }
648 
649 static int system_get_mldversion(struct device *dev, char *buf, const size_t buf_sz)
650 {
651         return system_get_dev_sysctl("ipv6/conf", "force_mld_version",
652                                      dev->ifname, buf, buf_sz);
653 }
654 
655 static int system_get_neigh4reachabletime(struct device *dev, char *buf, const size_t buf_sz)
656 {
657         return system_get_dev_sysctl("ipv4/neigh", "base_reachable_time_ms",
658                                      dev->ifname, buf, buf_sz);
659 }
660 
661 static int system_get_neigh6reachabletime(struct device *dev, char *buf, const size_t buf_sz)
662 {
663         return system_get_dev_sysctl("ipv6/neigh", "base_reachable_time_ms",
664                                      dev->ifname, buf, buf_sz);
665 }
666 
667 static int system_get_neigh4gcstaletime(struct device *dev, char *buf, const size_t buf_sz)
668 {
669         return system_get_dev_sysctl("ipv4/neigh", "gc_stale_time",
670                                      dev->ifname, buf, buf_sz);
671 }
672 
673 static int system_get_neigh6gcstaletime(struct device *dev, char *buf, const size_t buf_sz)
674 {
675         return system_get_dev_sysctl("ipv6/neigh", "gc_stale_time",
676                         dev->ifname, buf, buf_sz);
677 }
678 
679 static int system_get_neigh4locktime(struct device *dev, char *buf, const size_t buf_sz)
680 {
681         return system_get_dev_sysctl("ipv4/neigh", "locktime",
682                         dev->ifname, buf, buf_sz);
683 }
684 
685 static int system_get_dadtransmits(struct device *dev, char *buf, const size_t buf_sz)
686 {
687         return system_get_dev_sysctl("ipv6/conf", "dad_transmits",
688                         dev->ifname, buf, buf_sz);
689 }
690 
691 static int system_get_sendredirects(struct device *dev, char *buf, const size_t buf_sz)
692 {
693         return system_get_dev_sysctl("ipv4/conf", "send_redirects",
694                         dev->ifname, buf, buf_sz);
695 }
696 
697 
698 static int system_get_drop_v4_unicast_in_l2_multicast(struct device *dev, char *buf, const size_t buf_sz)
699 {
700         return system_get_dev_sysctl("ipv4/conf", "drop_unicast_in_l2_multicast",
701                         dev->ifname, buf, buf_sz);
702 }
703 
704 static int system_get_drop_v6_unicast_in_l2_multicast(struct device *dev, char *buf, const size_t buf_sz)
705 {
706         return system_get_dev_sysctl("ipv6/conf", "drop_unicast_in_l2_multicast",
707                         dev->ifname, buf, buf_sz);
708 }
709 
710 static int system_get_drop_gratuitous_arp(struct device *dev, char *buf, const size_t buf_sz)
711 {
712         return system_get_dev_sysctl("ipv4/conf", "drop_gratuitous_arp",
713                         dev->ifname, buf, buf_sz);
714 }
715 
716 static int system_get_drop_unsolicited_na(struct device *dev, char *buf, const size_t buf_sz)
717 {
718         return system_get_dev_sysctl("ipv6/conf", "drop_unsolicited_na",
719                         dev->ifname, buf, buf_sz);
720 }
721 
722 static int system_get_arp_accept(struct device *dev, char *buf, const size_t buf_sz)
723 {
724         return system_get_dev_sysctl("ipv4/conf", "arp_accept",
725                         dev->ifname, buf, buf_sz);
726 }
727 
728 static int
729 system_device_ifreq(struct ifreq *ifr, const char *ifname, int cmd)
730 {
731         memset(ifr, 0, sizeof(*ifr));
732         strncpy(ifr->ifr_name, ifname, sizeof(ifr->ifr_name) - 1);
733         return ioctl(sock_ioctl, cmd, ifr);
734 }
735 
736 #ifndef IFF_LOWER_UP
737 #define IFF_LOWER_UP    0x10000
738 #endif
739 
740 static void
741 system_device_update_state(struct device *dev, unsigned int flags)
742 {
743         unsigned int ifindex = system_if_resolve(dev);
744 
745         if (dev->type == &simple_device_type) {
746                 if (dev->external)
747                         device_set_disabled(dev, !(flags & IFF_UP));
748 
749                 device_set_present(dev, ifindex > 0);
750         }
751         device_set_link(dev, flags & IFF_LOWER_UP ? true : false);
752 }
753 
754 /* Evaluate netlink messages */
755 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
756 {
757         struct nlmsghdr *nh = nlmsg_hdr(msg);
758         struct ifinfomsg *ifi = NLMSG_DATA(nh);
759         struct nlattr *nla[__IFLA_MAX];
760         struct device *dev;
761         unsigned int flags;
762 
763         if (nh->nlmsg_type != RTM_NEWLINK && nh->nlmsg_type != RTM_DELLINK)
764                 return 0;
765 
766         if (ifi->ifi_family != AF_UNSPEC)
767                 return 0;
768 
769         if (nlmsg_parse(nh, sizeof(struct ifinfomsg), nla, __IFLA_MAX - 1, NULL))
770                 return 0;
771 
772         if (!nla[IFLA_IFNAME])
773                 return 0;
774 
775         dev = device_find(nla_data(nla[IFLA_IFNAME]));
776         if (!dev)
777                 return 0;
778 
779         flags = (nh->nlmsg_type == RTM_DELLINK) ? 0 : ifi->ifi_flags;
780         system_device_update_state(dev, flags);
781         return 0;
782 }
783 
784 static void
785 handle_hotplug_msg(char *data, int size)
786 {
787         const char *subsystem = NULL, *interface = NULL, *interface_old = NULL;
788         char *cur, *end, *sep;
789         int skip;
790         bool add;
791 
792         if (!strncmp(data, "add@", 4) || !strncmp(data, "move@", 5))
793                 add = true;
794         else if (!strncmp(data, "remove@", 7))
795                 add = false;
796         else
797                 return;
798 
799         skip = strlen(data) + 1;
800         end = data + size;
801 
802         for (cur = data + skip; cur < end; cur += skip) {
803                 skip = strlen(cur) + 1;
804 
805                 sep = strchr(cur, '=');
806                 if (!sep)
807                         continue;
808 
809                 *sep = 0;
810                 if (!strcmp(cur, "INTERFACE"))
811                         interface = sep + 1;
812                 else if (!strcmp(cur, "SUBSYSTEM")) {
813                         subsystem = sep + 1;
814                         if (strcmp(subsystem, "net") != 0)
815                                 return;
816                 } else if (!strcmp(cur, "DEVPATH_OLD")) {
817                         interface_old = strrchr(sep + 1, '/');
818                         if (interface_old)
819                                 interface_old++;
820                 }
821         }
822 
823         if (!subsystem || !interface)
824                 return;
825 
826         if (interface_old)
827                 device_hotplug_event(interface_old, false);
828 
829         device_hotplug_event(interface, add);
830 }
831 
832 static void
833 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
834 {
835         struct event_socket *ev = container_of(u, struct event_socket, uloop);
836         struct sockaddr_nl nla;
837         unsigned char *buf = NULL;
838         int size;
839 
840         while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
841                 if (nla.nl_pid == 0)
842                         handle_hotplug_msg((char *) buf, size);
843 
844                 free(buf);
845         }
846 
847         switch (-size) {
848         case 0:
849                 return;
850 
851         case NLE_NOMEM:
852                 /* Increase rx buffer size on netlink socket */
853                 ev->bufsize *= 2;
854                 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
855                         goto abort;
856                 break;
857 
858         default:
859                 goto abort;
860         }
861         return;
862 
863 abort:
864         uloop_fd_delete(&ev->uloop);
865         return;
866 }
867 
868 static int system_rtnl_call(struct nl_msg *msg)
869 {
870         int ret;
871 
872         ret = nl_send_auto_complete(sock_rtnl, msg);
873         nlmsg_free(msg);
874 
875         if (ret < 0)
876                 return ret;
877 
878         return nl_wait_for_ack(sock_rtnl);
879 }
880 
881 static struct nl_msg *__system_ifinfo_msg(int af, int index, const char *ifname, uint16_t type, uint16_t flags)
882 {
883         struct nl_msg *msg;
884         struct ifinfomsg iim = {
885                 .ifi_family = af,
886                 .ifi_index = index,
887         };
888 
889         msg = nlmsg_alloc_simple(type, flags | NLM_F_REQUEST);
890         if (!msg)
891                 return NULL;
892 
893         nlmsg_append(msg, &iim, sizeof(iim), 0);
894         if (ifname)
895                 nla_put_string(msg, IFLA_IFNAME, ifname);
896 
897         return msg;
898 }
899 
900 static struct nl_msg *system_ifinfo_msg(const char *ifname, uint16_t type, uint16_t flags)
901 {
902         return __system_ifinfo_msg(AF_UNSPEC, 0, ifname, type, flags);
903 }
904 
905 static int system_link_del(const char *ifname)
906 {
907         struct nl_msg *msg;
908 
909         msg = system_ifinfo_msg(ifname, RTM_DELLINK, 0);
910         if (!msg)
911                 return -1;
912 
913         return system_rtnl_call(msg);
914 }
915 
916 int system_bridge_delbr(struct device *bridge)
917 {
918         return system_link_del(bridge->ifname);
919 }
920 
921 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
922 {
923         struct ifreq ifr;
924 
925         memset(&ifr, 0, sizeof(ifr));
926         if (dev)
927                 ifr.ifr_ifindex = dev->ifindex;
928         else
929                 ifr.ifr_data = data;
930         strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name) - 1);
931         return ioctl(sock_ioctl, cmd, &ifr);
932 }
933 
934 static bool system_is_bridge(const char *name)
935 {
936         struct stat st;
937 
938         return stat(dev_sysfs_path(name, "bridge"), &st) >= 0;
939 }
940 
941 static char *system_get_bridge(const char *name, char *buf, int buflen)
942 {
943         char *path;
944         ssize_t len = -1;
945         glob_t gl;
946 
947         snprintf(buf, buflen, "%s/devices/virtual/net/*/brif/%s/bridge", sysfs_path, name);
948         if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
949                 return NULL;
950 
951         if (gl.gl_pathc > 0)
952                 len = readlink(gl.gl_pathv[0], buf, buflen);
953 
954         globfree(&gl);
955 
956         if (len < 0)
957                 return NULL;
958 
959         buf[len] = 0;
960         path = strrchr(buf, '/');
961         if (!path)
962                 return NULL;
963 
964         return path + 1;
965 }
966 
967 static void
968 system_bridge_set_wireless(struct device *bridge, struct device *dev)
969 {
970         bool mcast_to_ucast = dev->wireless_ap;
971         bool hairpin;
972 
973         if (dev->settings.flags & DEV_OPT_MULTICAST_TO_UNICAST)
974                 mcast_to_ucast = dev->settings.multicast_to_unicast;
975         else if (bridge->settings.flags & DEV_OPT_MULTICAST_TO_UNICAST &&
976                  !bridge->settings.multicast_to_unicast)
977                 mcast_to_ucast = false;
978 
979         hairpin = mcast_to_ucast || dev->wireless_proxyarp;
980         if (dev->wireless_isolate)
981                 hairpin = false;
982 
983         system_bridge_set_multicast_to_unicast(dev, mcast_to_ucast ? "1" : "");
984         system_bridge_set_hairpin_mode(dev, hairpin ? "1" : "");
985         system_bridge_set_proxyarp_wifi(dev, dev->wireless_proxyarp ? "1" : "");
986 }
987 
988 int system_bridge_addif(struct device *bridge, struct device *dev)
989 {
990         char buf[64];
991         char *oldbr;
992         int tries = 0;
993         int ret;
994 
995 
996         for (tries = 0; tries < 3; tries++) {
997                 ret = 0;
998                 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
999                 if (oldbr) {
1000                         if (!strcmp(oldbr, bridge->ifname))
1001                                 break;
1002 
1003                         /* still enslaved in a stale bridge; detach first to avoid EBUSY */
1004                         system_bridge_if(oldbr, dev, SIOCBRDELIF, NULL);
1005                 }
1006 
1007                 ret = system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
1008                 if (!ret)
1009                         break;
1010 
1011                 D(SYSTEM, "Failed to add device '%s' to bridge '%s' (tries=%d): %s",
1012                   dev->ifname, bridge->ifname, tries, strerror(errno));
1013         }
1014 
1015         if (dev->wireless)
1016                 system_bridge_set_wireless(bridge, dev);
1017 
1018         if (dev->settings.flags & DEV_OPT_MULTICAST_ROUTER) {
1019                 snprintf(buf, sizeof(buf), "%u", dev->settings.multicast_router);
1020                 system_bridge_set_multicast_router(dev, buf);
1021         }
1022 
1023         if (dev->settings.flags & DEV_OPT_MULTICAST_FAST_LEAVE &&
1024             dev->settings.multicast_fast_leave)
1025                 system_bridge_set_multicast_fast_leave(dev, "1");
1026 
1027         if (dev->settings.flags & DEV_OPT_LEARNING &&
1028             !dev->settings.learning)
1029                 system_bridge_set_learning(dev, "");
1030 
1031         if (dev->settings.flags & DEV_OPT_UNICAST_FLOOD &&
1032             !dev->settings.unicast_flood)
1033                 system_bridge_set_unicast_flood(dev, "");
1034 
1035         if (dev->settings.flags & DEV_OPT_BROADCAST_FLOOD &&
1036             !dev->settings.broadcast_flood)
1037                 system_bridge_set_broadcast_flood(dev, "");
1038 
1039         if (dev->settings.flags & DEV_OPT_ISOLATE &&
1040             dev->settings.isolate)
1041                 system_bridge_set_isolated(dev, "1");
1042 
1043         if (dev->bpdu_filter)
1044                 system_bridge_set_bpdu_filter(dev, dev->bpdu_filter ? "1" : "");
1045 
1046         return ret;
1047 }
1048 
1049 int system_bridge_delif(struct device *bridge, struct device *dev)
1050 {
1051         return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
1052 }
1053 
1054 int system_bridge_vlan(const char *iface, uint16_t vid, int16_t vid_end, bool add, unsigned int vflags)
1055 {
1056         struct bridge_vlan_info vinfo = { .vid = vid, };
1057         unsigned short flags = 0;
1058         struct nlattr *afspec;
1059         struct nl_msg *nlm;
1060         int index;
1061         int ret = 0;
1062 
1063         index = if_nametoindex(iface);
1064         if (!index)
1065                 return -1;
1066 
1067         nlm = __system_ifinfo_msg(PF_BRIDGE, index, NULL, add ? RTM_SETLINK : RTM_DELLINK, 0);
1068         if (!nlm)
1069                 return -1;
1070 
1071         if (vflags & BRVLAN_F_SELF)
1072                 flags |= BRIDGE_FLAGS_SELF;
1073 
1074         if (vflags & BRVLAN_F_PVID)
1075                 vinfo.flags |= BRIDGE_VLAN_INFO_PVID;
1076 
1077         if (vflags & BRVLAN_F_UNTAGGED)
1078                 vinfo.flags |= BRIDGE_VLAN_INFO_UNTAGGED;
1079 
1080         afspec = nla_nest_start(nlm, IFLA_AF_SPEC);
1081         if (!afspec) {
1082                 ret = -ENOMEM;
1083                 goto failure;
1084         }
1085 
1086         if (flags)
1087                 nla_put_u16(nlm, IFLA_BRIDGE_FLAGS, flags);
1088 
1089         if (vid_end > vid)
1090                 vinfo.flags |= BRIDGE_VLAN_INFO_RANGE_BEGIN;
1091 
1092         nla_put(nlm, IFLA_BRIDGE_VLAN_INFO, sizeof(vinfo), &vinfo);
1093 
1094         if (vid_end > vid) {
1095                 vinfo.flags &= ~BRIDGE_VLAN_INFO_RANGE_BEGIN;
1096                 vinfo.flags |= BRIDGE_VLAN_INFO_RANGE_END;
1097                 vinfo.vid = vid_end;
1098                 nla_put(nlm, IFLA_BRIDGE_VLAN_INFO, sizeof(vinfo), &vinfo);
1099         }
1100 
1101         nla_nest_end(nlm, afspec);
1102 
1103         return system_rtnl_call(nlm);
1104 
1105 failure:
1106         nlmsg_free(nlm);
1107         return ret;
1108 }
1109 
1110 int system_vrf_addvrf(struct device *vrf, unsigned int table)
1111 {
1112         struct nlattr *linkinfo, *data;
1113         struct nl_msg *msg;
1114         int rv;
1115 
1116         msg = system_ifinfo_msg(vrf->ifname, RTM_NEWLINK, NLM_F_CREATE | NLM_F_EXCL);
1117         if (!msg)
1118                 return -1;
1119 
1120         if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1121                 goto nla_put_failure;
1122 
1123         nla_put_string(msg, IFLA_INFO_KIND, "vrf");
1124 
1125         if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1126                 goto nla_put_failure;
1127 
1128         nla_put_u32(msg, IFLA_VRF_TABLE, table);
1129 
1130         nla_nest_end(msg, data);
1131         nla_nest_end(msg, linkinfo);
1132 
1133         rv = system_rtnl_call(msg);
1134         if (rv)
1135                 D(SYSTEM, "Error adding vrf '%s': %d\n", vrf->ifname, rv);
1136 
1137         return rv;
1138 
1139 nla_put_failure:
1140         nlmsg_free(msg);
1141         return -ENOMEM;
1142 }
1143 
1144 int system_vrf_delvrf(struct device *vrf)
1145 {
1146         return system_link_del(vrf->ifname);
1147 }
1148 
1149 static char *system_get_vrf(const char *name, char *buf, int buflen)
1150 {
1151         char master[PATH_MAX];
1152         char *path;
1153         ssize_t len = -1;
1154 
1155         if (snprintf(master, sizeof(master), "%s/devices/virtual/net/%s/master", sysfs_path, name) <= 0)
1156                 return NULL;
1157 
1158         len = readlink(master, buf, buflen);
1159         if (len < 0)
1160                 return NULL;
1161 
1162         buf[len] = 0;
1163         path = strrchr(buf, '/');
1164         if (!path)
1165                 return NULL;
1166 
1167         return path + 1;
1168 }
1169 
1170 static int
1171 system_vrf_if(int vrf_index, struct device *dev)
1172 {
1173         struct nl_msg *msg;
1174 
1175         msg = __system_ifinfo_msg(AF_UNSPEC, dev->ifindex, NULL, RTM_SETLINK, NLM_F_REQUEST);
1176         if (!msg)
1177                 return -1;
1178 
1179         nla_put_u32(msg, IFLA_MASTER, vrf_index);
1180         return system_rtnl_call(msg);
1181 }
1182 
1183 int system_vrf_addif(struct device *vrf, struct device *dev)
1184 {
1185         char *oldvrf;
1186         int tries;
1187         int ret;
1188 
1189         for (tries = 0; tries < 3; tries++) {
1190                 ret = 0;
1191                 oldvrf = system_get_vrf(dev->ifname, dev_buf, sizeof(dev_buf));
1192                 if (oldvrf && !strcmp(oldvrf, vrf->ifname))
1193                         break;
1194 
1195                 ret = system_vrf_if(vrf->ifindex, dev);
1196                 if (!ret)
1197                         break;
1198 
1199                 D(SYSTEM, "Failed to add device '%s' to vrf '%s' (tries=%d): %s\n",
1200                   dev->ifname, vrf->ifname, tries, strerror(errno));
1201         }
1202 
1203         return ret;
1204 }
1205 
1206 int system_vrf_delif(struct device *vrf, struct device *dev)
1207 {
1208         return system_vrf_if(0, dev);
1209 }
1210 
1211 void system_tcp_l3mdev(bool enable)
1212 {
1213         system_set_dev_sysctl("ipv4", "tcp_l3mdev_accept", ".", enable ? "1" : "");
1214 }
1215 
1216 void system_udp_l3mdev(bool enable)
1217 {
1218         system_set_dev_sysctl("ipv4", "udp_l3mdev_accept", ".", enable ? "1" : "");
1219 }
1220 
1221 int system_bonding_set_device(struct device *dev, struct bonding_config *cfg)
1222 {
1223         const char *ifname = dev->ifname;
1224         struct blob_attr *cur;
1225         char op = cfg ? '+' : '-';
1226         char buf[64];
1227         size_t rem;
1228 
1229         snprintf(dev_buf, sizeof(dev_buf), "%s/class/net/bonding_masters", sysfs_path);
1230         snprintf(buf, sizeof(buf), "%c%s", op, ifname);
1231         write_file(dev_buf, buf);
1232 
1233         if (!cfg)
1234                 return 0;
1235 
1236         system_set_dev_sysfs("bonding/mode", ifname, bonding_policy_str[cfg->policy]);
1237 
1238         system_set_dev_sysfs_int("bonding/all_slaves_active", ifname, cfg->all_ports_active);
1239 
1240         if (cfg->policy == BONDING_MODE_BALANCE_XOR ||
1241             cfg->policy == BONDING_MODE_BALANCE_TLB ||
1242             cfg->policy == BONDING_MODE_8023AD)
1243                 system_set_dev_sysfs("bonding/xmit_hash_policy", ifname, cfg->xmit_hash_policy);
1244 
1245         if (cfg->policy == BONDING_MODE_8023AD) {
1246                 system_set_dev_sysfs("bonding/ad_actor_system", ifname, cfg->ad_actor_system);
1247                 system_set_dev_sysfs_int("bonding/ad_actor_sys_prio", ifname, cfg->ad_actor_sys_prio);
1248                 system_set_dev_sysfs("bonding/ad_select", ifname, cfg->ad_select);
1249                 system_set_dev_sysfs("bonding/lacp_rate", ifname, cfg->lacp_rate);
1250                 system_set_dev_sysfs_int("bonding/min_links", ifname, cfg->min_links);
1251         }
1252 
1253         if (cfg->policy == BONDING_MODE_BALANCE_RR)
1254                 system_set_dev_sysfs_int("bonding/packets_per_slave", ifname, cfg->packets_per_port);
1255 
1256         if (cfg->policy == BONDING_MODE_BALANCE_TLB ||
1257             cfg->policy == BONDING_MODE_BALANCE_ALB)
1258                 system_set_dev_sysfs_int("bonding/lp_interval", ifname, cfg->lp_interval);
1259 
1260         if (cfg->policy == BONDING_MODE_BALANCE_TLB)
1261                 system_set_dev_sysfs_int("bonding/tlb_dynamic_lb", ifname, cfg->dynamic_lb);
1262         system_set_dev_sysfs_int("bonding/resend_igmp", ifname, cfg->resend_igmp);
1263         system_set_dev_sysfs_int("bonding/num_grat_arp", ifname, cfg->num_peer_notif);
1264         system_set_dev_sysfs("bonding/primary_reselect", ifname, cfg->primary_reselect);
1265         system_set_dev_sysfs("bonding/fail_over_mac", ifname, cfg->failover_mac);
1266 
1267         system_set_dev_sysfs_int((cfg->monitor_arp ?
1268                                   "bonding/arp_interval" :
1269                                   "bonding/miimon"), ifname, cfg->monitor_interval);
1270 
1271         blobmsg_for_each_attr(cur, cfg->arp_target, rem) {
1272                 snprintf(buf, sizeof(buf), "+%s", blobmsg_get_string(cur));
1273                 system_set_dev_sysfs("bonding/arp_ip_target", ifname, buf);
1274         }
1275 
1276         system_set_dev_sysfs_int("bonding/arp_all_targets", ifname, cfg->arp_all_targets);
1277         if (cfg->policy < BONDING_MODE_8023AD)
1278                 system_set_dev_sysfs("bonding/arp_validate", ifname, cfg->arp_validate);
1279         system_set_dev_sysfs_int("bonding/use_carrier", ifname, cfg->use_carrier);
1280         if (!cfg->monitor_arp && cfg->monitor_interval) {
1281                 system_set_dev_sysfs_int("bonding/updelay", ifname, cfg->updelay);
1282                 system_set_dev_sysfs_int("bonding/downdelay", ifname, cfg->downdelay);
1283         }
1284 
1285         return 0;
1286 }
1287 
1288 int system_bonding_set_port(struct device *dev, struct device *port, bool add, bool primary)
1289 {
1290         const char *port_name = port->ifname;
1291         const char op_ch = add ? '+' : '-';
1292         char buf[IFNAMSIZ + 1];
1293 
1294         snprintf(buf, sizeof(buf), "%c%s", op_ch, port_name);
1295         system_if_down(port);
1296         system_set_dev_sysfs("bonding/slaves", dev->ifname, buf);
1297         system_if_up(port);
1298 
1299         if (primary)
1300                 system_set_dev_sysfs("bonding/primary", dev->ifname,
1301                                      add ? port_name : "");
1302 
1303         return 0;
1304 }
1305 
1306 int system_if_resolve(struct device *dev)
1307 {
1308         struct ifreq ifr;
1309 
1310         if (system_device_ifreq(&ifr, dev->ifname, SIOCGIFINDEX))
1311                 return 0;
1312 
1313         return ifr.ifr_ifindex;
1314 }
1315 
1316 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
1317 {
1318         struct ifreq ifr;
1319 
1320         if (system_device_ifreq(&ifr, ifname, SIOCGIFFLAGS))
1321                 return -1;
1322 
1323         ifr.ifr_flags |= add;
1324         ifr.ifr_flags &= ~rem;
1325         return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
1326 }
1327 
1328 struct clear_data {
1329         struct nl_msg *msg;
1330         struct device *dev;
1331         int type;
1332         int size;
1333         int af;
1334         struct nl_msg **del;
1335         int n_del;
1336 };
1337 
1338 
1339 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
1340 {
1341         struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
1342 
1343         return (long)ifa->ifa_index == ifindex;
1344 }
1345 
1346 static bool check_route(struct nlmsghdr *hdr, int ifindex)
1347 {
1348         struct rtmsg *r = NLMSG_DATA(hdr);
1349         struct nlattr *tb[__RTA_MAX];
1350 
1351         if (r->rtm_protocol == RTPROT_KERNEL &&
1352             r->rtm_family == AF_INET6)
1353                 return false;
1354 
1355         nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
1356         if (!tb[RTA_OIF])
1357                 return false;
1358 
1359         return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
1360 }
1361 
1362 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
1363 {
1364         return true;
1365 }
1366 
1367 static bool check_neigh(struct nlmsghdr *hdr, int ifindex)
1368 {
1369         struct ndmsg *ndm = NLMSG_DATA(hdr);
1370 
1371         if (ndm->ndm_ifindex != ifindex)
1372                 return false;
1373 
1374         /* only clear entries netifd could have installed itself */
1375         return (ndm->ndm_state & NUD_PERMANENT) || (ndm->ndm_flags & NTF_PROXY);
1376 }
1377 
1378 static int cb_clear_event(struct nl_msg *msg, void *arg)
1379 {
1380         struct clear_data *clr = arg;
1381         struct nlmsghdr *hdr = nlmsg_hdr(msg);
1382         bool (*cb)(struct nlmsghdr *, int ifindex);
1383         struct nl_msg **tmp, *del;
1384         const char *obj_name;
1385         int type;
1386 
1387         switch(clr->type) {
1388         case RTM_GETADDR:
1389                 type = RTM_DELADDR;
1390                 if (hdr->nlmsg_type != RTM_NEWADDR)
1391                         return NL_SKIP;
1392 
1393                 cb = check_ifaddr;
1394                 break;
1395         case RTM_GETROUTE:
1396                 type = RTM_DELROUTE;
1397                 if (hdr->nlmsg_type != RTM_NEWROUTE)
1398                         return NL_SKIP;
1399 
1400                 cb = check_route;
1401                 break;
1402         case RTM_GETRULE:
1403                 type = RTM_DELRULE;
1404                 if (hdr->nlmsg_type != RTM_NEWRULE)
1405                         return NL_SKIP;
1406 
1407                 cb = check_rule;
1408                 break;
1409         case RTM_GETNEIGH:
1410                 type = RTM_DELNEIGH;
1411                 if (hdr->nlmsg_type != RTM_NEWNEIGH)
1412                         return NL_SKIP;
1413 
1414                 cb = check_neigh;
1415                 break;
1416         default:
1417                 return NL_SKIP;
1418         }
1419 
1420         if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
1421                 return NL_SKIP;
1422 
1423         obj_name = type == RTM_DELADDR ? "an address" :
1424                    type == RTM_DELNEIGH ? "a neighbor" : "a route";
1425         if (type == RTM_DELRULE)
1426                 D(SYSTEM, "Remove a rule");
1427         else
1428                 D(SYSTEM, "Remove %s from device %s",
1429                   obj_name, clr->dev->ifname);
1430 
1431         /*
1432          * Queue the deletion instead of sending it while the dump is still
1433          * being received: a kernel error reply to a request sent with the
1434          * dump's sequence number aborts the dump processing and desyncs the
1435          * socket's sequence accounting
1436          */
1437         del = nlmsg_convert(hdr);
1438         if (!del)
1439                 return NL_SKIP;
1440 
1441         hdr = nlmsg_hdr(del);
1442         hdr->nlmsg_type = type;
1443         hdr->nlmsg_flags = NLM_F_REQUEST;
1444         hdr->nlmsg_seq = NL_AUTO_SEQ;
1445 
1446         tmp = realloc(clr->del, (clr->n_del + 1) * sizeof(*clr->del));
1447         if (!tmp) {
1448                 nlmsg_free(del);
1449                 return NL_SKIP;
1450         }
1451 
1452         clr->del = tmp;
1453         clr->del[clr->n_del++] = del;
1454 
1455         return NL_SKIP;
1456 }
1457 
1458 static int
1459 cb_finish_event(struct nl_msg *msg, void *arg)
1460 {
1461         int *pending = arg;
1462         *pending = 0;
1463         return NL_STOP;
1464 }
1465 
1466 static int
1467 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1468 {
1469         int *pending = arg;
1470         *pending = err->error;
1471         return NL_STOP;
1472 }
1473 
1474 static void
1475 system_if_clear_entries(struct device *dev, int type, int af)
1476 {
1477         struct clear_data clr;
1478         struct nl_cb *cb;
1479         struct rtmsg rtm = {
1480                 .rtm_family = af,
1481                 .rtm_flags = RTM_F_CLONED,
1482         };
1483         struct ndmsg ndm = {
1484                 .ndm_family = af,
1485         };
1486         void *req = &rtm;
1487         int flags = NLM_F_DUMP;
1488         int n_dumps = 1;
1489         int pending;
1490 
1491         clr.af = af;
1492         clr.dev = dev;
1493         clr.type = type;
1494         clr.del = NULL;
1495         clr.n_del = 0;
1496         switch (type) {
1497         case RTM_GETADDR:
1498         case RTM_GETRULE:
1499                 clr.size = sizeof(struct rtgenmsg);
1500                 break;
1501         case RTM_GETROUTE:
1502                 clr.size = sizeof(struct rtmsg);
1503                 break;
1504         case RTM_GETNEIGH:
1505                 req = &ndm;
1506                 clr.size = sizeof(struct ndmsg);
1507                 /* the kernel dumps proxy entries only when asked for them */
1508                 n_dumps = 2;
1509                 break;
1510         default:
1511                 return;
1512         }
1513 
1514         cb = nl_cb_alloc(NL_CB_DEFAULT);
1515         if (!cb)
1516                 return;
1517 
1518         nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
1519         nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
1520         nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
1521 
1522         for (int i = 0; i < n_dumps; i++) {
1523                 ndm.ndm_flags = i ? NTF_PROXY : 0;
1524 
1525                 clr.msg = nlmsg_alloc_simple(type, flags);
1526                 if (!clr.msg)
1527                         break;
1528 
1529                 nlmsg_append(clr.msg, req, clr.size, 0);
1530 
1531                 if (nl_send_auto_complete(sock_rtnl, clr.msg) < 0) {
1532                         nlmsg_free(clr.msg);
1533                         break;
1534                 }
1535 
1536                 pending = 1;
1537                 while (pending > 0)
1538                         if (nl_recvmsgs(sock_rtnl, cb) < 0)
1539                                 break;
1540 
1541                 nlmsg_free(clr.msg);
1542         }
1543 
1544         for (int i = 0; i < clr.n_del; i++) {
1545                 int err = system_rtnl_call(clr.del[i]);
1546 
1547                 if (err)
1548                         D(SYSTEM, "Error deleting kernel entry: %d", err);
1549         }
1550         free(clr.del);
1551 
1552         nl_cb_put(cb);
1553 }
1554 
1555 /*
1556  * Clear bridge (membership) state and bring down device
1557  */
1558 void system_if_clear_state(struct device *dev)
1559 {
1560         static char buf[256];
1561         char *bridge;
1562         device_set_ifindex(dev, system_if_resolve(dev));
1563 
1564         if (dev->external || !dev->ifindex)
1565                 return;
1566 
1567         system_if_flags(dev->ifname, 0, IFF_UP);
1568 
1569         if (system_is_bridge(dev->ifname)) {
1570                 D(SYSTEM, "Delete existing bridge named '%s'", dev->ifname);
1571                 system_bridge_delbr(dev);
1572                 return;
1573         }
1574 
1575         bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
1576         if (bridge) {
1577                 D(SYSTEM, "Remove device '%s' from bridge '%s'", dev->ifname, bridge);
1578                 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
1579         }
1580 
1581         system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
1582         system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
1583         system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
1584         system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
1585         system_if_clear_entries(dev, RTM_GETNEIGH, AF_INET);
1586         system_if_clear_entries(dev, RTM_GETNEIGH, AF_INET6);
1587         system_set_disable_ipv6(dev, "");
1588 }
1589 
1590 static inline unsigned long
1591 sec_to_jiffies(int val)
1592 {
1593         return (unsigned long) val * 100;
1594 }
1595 
1596 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
1597 {
1598         struct nlattr *linkinfo, *data;
1599         struct nl_msg *msg;
1600         uint64_t val;
1601         int rv;
1602 
1603         msg = system_ifinfo_msg(bridge->ifname, RTM_NEWLINK, NLM_F_CREATE | NLM_F_EXCL);
1604         if (!msg)
1605                 return -1;
1606 
1607         if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1608                 goto nla_put_failure;
1609 
1610         nla_put_string(msg, IFLA_INFO_KIND, "bridge");
1611 
1612         if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1613                 goto nla_put_failure;
1614 
1615         nla_put_u32(msg, IFLA_BR_STP_STATE, cfg->stp);
1616         nla_put_u32(msg, IFLA_BR_FORWARD_DELAY, sec_to_jiffies(cfg->forward_delay));
1617         nla_put_u8(msg, IFLA_BR_MCAST_SNOOPING, !!cfg->igmp_snoop);
1618         nla_put_u8(msg, IFLA_BR_MCAST_QUERIER, !!cfg->multicast_querier);
1619         nla_put_u32(msg, IFLA_BR_MCAST_HASH_MAX, cfg->hash_max);
1620 
1621         if (bridge->settings.flags & DEV_OPT_MULTICAST_ROUTER)
1622                 nla_put_u8(msg, IFLA_BR_MCAST_ROUTER, !!bridge->settings.multicast_router);
1623 
1624         if (cfg->flags & BRIDGE_OPT_ROBUSTNESS) {
1625                 nla_put_u32(msg, IFLA_BR_MCAST_STARTUP_QUERY_CNT, cfg->robustness);
1626                 nla_put_u32(msg, IFLA_BR_MCAST_LAST_MEMBER_CNT, cfg->robustness);
1627         }
1628 
1629         if (cfg->flags & BRIDGE_OPT_QUERY_INTERVAL)
1630                 nla_put_u64(msg, IFLA_BR_MCAST_QUERY_INTVL, cfg->query_interval);
1631 
1632         if (cfg->flags & BRIDGE_OPT_QUERY_RESPONSE_INTERVAL)
1633                 nla_put_u64(msg, IFLA_BR_MCAST_QUERY_RESPONSE_INTVL, cfg->query_response_interval);
1634 
1635         if (cfg->flags & BRIDGE_OPT_LAST_MEMBER_INTERVAL)
1636                 nla_put_u64(msg, IFLA_BR_MCAST_LAST_MEMBER_INTVL, cfg->last_member_interval);
1637 
1638         if (cfg->flags & BRIDGE_OPT_ROBUSTNESS ||
1639             cfg->flags & BRIDGE_OPT_QUERY_INTERVAL ||
1640             cfg->flags & BRIDGE_OPT_QUERY_RESPONSE_INTERVAL) {
1641                 val = cfg->robustness * cfg->query_interval +
1642                         cfg->query_response_interval;
1643 
1644                 nla_put_u64(msg, IFLA_BR_MCAST_MEMBERSHIP_INTVL, val);
1645 
1646                 val -= cfg->query_response_interval / 2;
1647 
1648                 nla_put_u64(msg, IFLA_BR_MCAST_QUERIER_INTVL, val);
1649         }
1650 
1651         if (cfg->flags & BRIDGE_OPT_QUERY_INTERVAL) {
1652                 val = cfg->query_interval / 4;
1653 
1654                 nla_put_u64(msg, IFLA_BR_MCAST_STARTUP_QUERY_INTVL, val);
1655         }
1656 
1657         nla_put_u8(msg, IFLA_BR_VLAN_FILTERING, !!cfg->vlan_filtering);
1658         nla_put_u16(msg, IFLA_BR_PRIORITY, cfg->priority);
1659         nla_put_u32(msg, IFLA_BR_HELLO_TIME, sec_to_jiffies(cfg->hello_time));
1660         nla_put_u32(msg, IFLA_BR_MAX_AGE, sec_to_jiffies(cfg->max_age));
1661 
1662         if (cfg->flags & BRIDGE_OPT_AGEING_TIME)
1663                 nla_put_u32(msg, IFLA_BR_AGEING_TIME, sec_to_jiffies(cfg->ageing_time));
1664 
1665         nla_nest_end(msg, data);
1666         nla_nest_end(msg, linkinfo);
1667 
1668         rv = system_rtnl_call(msg);
1669         if (rv)
1670                 D(SYSTEM, "Error adding bridge '%s': %d", bridge->ifname, rv);
1671 
1672         return rv;
1673 
1674 nla_put_failure:
1675         nlmsg_free(msg);
1676         return -ENOMEM;
1677 }
1678 
1679 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
1680 {
1681         struct nl_msg *msg;
1682         struct nlattr *linkinfo, *data;
1683         size_t i;
1684         int rv;
1685         static const struct {
1686                 const char *name;
1687                 enum macvlan_mode val;
1688         } modes[] = {
1689                 { "private", MACVLAN_MODE_PRIVATE },
1690                 { "vepa", MACVLAN_MODE_VEPA },
1691                 { "bridge", MACVLAN_MODE_BRIDGE },
1692                 { "passthru", MACVLAN_MODE_PASSTHRU },
1693         };
1694 
1695         msg = system_ifinfo_msg(macvlan->ifname, RTM_NEWLINK, NLM_F_CREATE | NLM_F_EXCL);
1696         if (!msg)
1697                 return -1;
1698 
1699         if (cfg->flags & MACVLAN_OPT_MACADDR)
1700                 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
1701         nla_put_u32(msg, IFLA_LINK, dev->ifindex);
1702 
1703         if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1704                 goto nla_put_failure;
1705 
1706         nla_put_string(msg, IFLA_INFO_KIND, "macvlan");
1707 
1708         if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1709                 goto nla_put_failure;
1710 
1711         if (cfg->mode) {
1712                 for (i = 0; i < ARRAY_SIZE(modes); i++) {
1713                         if (strcmp(cfg->mode, modes[i].name) != 0)
1714                                 continue;
1715 
1716                         nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
1717                         break;
1718                 }
1719         }
1720 
1721         nla_nest_end(msg, data);
1722         nla_nest_end(msg, linkinfo);
1723 
1724         rv = system_rtnl_call(msg);
1725         if (rv)
1726                 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d", macvlan->ifname, dev->ifname, rv);
1727 
1728         return rv;
1729 
1730 nla_put_failure:
1731         nlmsg_free(msg);
1732         return -ENOMEM;
1733 }
1734 
1735 int system_link_netns_move(struct device *dev, int netns_fd, const char *target_ifname)
1736 {
1737         struct nl_msg *msg;
1738         int index;
1739 
1740         if (!dev)
1741                 return -1;
1742 
1743         index = system_if_resolve(dev);
1744         msg = __system_ifinfo_msg(AF_UNSPEC, index, target_ifname, RTM_NEWLINK, 0);
1745         if (!msg)
1746                 return -1;
1747 
1748         nla_put_u32(msg, IFLA_NET_NS_FD, netns_fd);
1749         return system_rtnl_call(msg);
1750 }
1751 
1752 int system_macvlan_del(struct device *macvlan)
1753 {
1754         return system_link_del(macvlan->ifname);
1755 }
1756 
1757 int system_netns_open(const pid_t target_ns)
1758 {
1759         char pid_net_path[PATH_MAX];
1760 
1761         snprintf(pid_net_path, sizeof(pid_net_path), "/proc/%u/ns/net", target_ns);
1762 
1763         return open(pid_net_path, O_RDONLY);
1764 }
1765 
1766 int system_netns_set(int netns_fd)
1767 {
1768         return setns(netns_fd, CLONE_NEWNET);
1769 }
1770 
1771 int system_veth_add(struct device *veth, struct veth_config *cfg)
1772 {
1773         struct nl_msg *msg;
1774         struct ifinfomsg empty_iim = {0,};
1775         struct nlattr *linkinfo, *data, *veth_info;
1776         int rv;
1777 
1778         msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1779 
1780         if (!msg)
1781                 return -1;
1782 
1783         nlmsg_append(msg, &empty_iim, sizeof(empty_iim), 0);
1784 
1785         if (cfg->flags & VETH_OPT_MACADDR)
1786                 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
1787         nla_put_string(msg, IFLA_IFNAME, veth->ifname);
1788 
1789         if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1790                 goto nla_put_failure;
1791 
1792         nla_put_string(msg, IFLA_INFO_KIND, "veth");
1793 
1794         if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1795                 goto nla_put_failure;
1796 
1797         if (!(veth_info = nla_nest_start(msg, VETH_INFO_PEER)))
1798                 goto nla_put_failure;
1799 
1800         nlmsg_append(msg, &empty_iim, sizeof(empty_iim), 0);
1801 
1802         if (cfg->flags & VETH_OPT_PEER_NAME)
1803                 nla_put_string(msg, IFLA_IFNAME, cfg->peer_name);
1804         if (cfg->flags & VETH_OPT_PEER_MACADDR)
1805                 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->peer_macaddr), cfg->peer_macaddr);
1806 
1807         nla_nest_end(msg, veth_info);
1808         nla_nest_end(msg, data);
1809         nla_nest_end(msg, linkinfo);
1810 
1811         rv = system_rtnl_call(msg);
1812         if (rv) {
1813                 if (cfg->flags & VETH_OPT_PEER_NAME)
1814                         D(SYSTEM, "Error adding veth '%s' with peer '%s': %d", veth->ifname, cfg->peer_name, rv);
1815                 else
1816                         D(SYSTEM, "Error adding veth '%s': %d", veth->ifname, rv);
1817         }
1818 
1819         return rv;
1820 
1821 nla_put_failure:
1822         nlmsg_free(msg);
1823         return -ENOMEM;
1824 }
1825 
1826 int system_veth_del(struct device *veth)
1827 {
1828         return system_link_del(veth->ifname);
1829 }
1830 
1831 static int system_vlan(struct device *dev, int id)
1832 {
1833         struct vlan_ioctl_args ifr = {
1834                 .cmd = SET_VLAN_NAME_TYPE_CMD,
1835                 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
1836         };
1837 
1838         if (ioctl(sock_ioctl, SIOCSIFVLAN, &ifr) < 0)
1839                 return -1;
1840 
1841         if (id < 0) {
1842                 ifr.cmd = DEL_VLAN_CMD;
1843                 ifr.u.VID = 0;
1844         } else {
1845                 ifr.cmd = ADD_VLAN_CMD;
1846                 ifr.u.VID = id;
1847         }
1848         strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
1849         return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
1850 }
1851 
1852 int system_vlan_add(struct device *dev, int id)
1853 {
1854         return system_vlan(dev, id);
1855 }
1856 
1857 int system_vlan_del(struct device *dev)
1858 {
1859         return system_vlan(dev, -1);
1860 }
1861 
1862 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
1863 {
1864         struct nl_msg *msg;
1865         struct nlattr *linkinfo, *data, *qos;
1866         struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
1867         struct vlan_qos_mapping *elem;
1868         struct ifla_vlan_qos_mapping nl_qos_map;
1869         int rv;
1870 
1871         msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1872 
1873         if (!msg)
1874                 return -1;
1875 
1876         nlmsg_append(msg, &iim, sizeof(iim), 0);
1877         nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
1878         nla_put_u32(msg, IFLA_LINK, dev->ifindex);
1879 
1880         if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1881                 goto nla_put_failure;
1882 
1883         nla_put_string(msg, IFLA_INFO_KIND, "vlan");
1884 
1885         if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1886                 goto nla_put_failure;
1887 
1888         nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
1889 
1890 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
1891         nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
1892 #else
1893         if(cfg->proto == VLAN_PROTO_8021AD)
1894                 netifd_log_message(L_WARNING, "%s Your kernel is older than linux 3.10.0, 802.1ad is not supported defaulting to 802.1q", vlandev->type->name);
1895 #endif
1896 
1897         if (!(qos = nla_nest_start(msg, IFLA_VLAN_INGRESS_QOS)))
1898                 goto nla_put_failure;
1899 
1900         vlist_simple_for_each_element(&cfg->ingress_qos_mapping_list, elem, node) {
1901                 nl_qos_map.from = elem->from;
1902                 nl_qos_map.to = elem->to;
1903                 nla_put(msg, IFLA_VLAN_QOS_MAPPING, sizeof(nl_qos_map), &nl_qos_map);
1904         }
1905         nla_nest_end(msg, qos);
1906 
1907         if (!(qos = nla_nest_start(msg, IFLA_VLAN_EGRESS_QOS)))
1908                 goto nla_put_failure;
1909 
1910         vlist_simple_for_each_element(&cfg->egress_qos_mapping_list, elem, node) {
1911                 nl_qos_map.from = elem->from;
1912                 nl_qos_map.to = elem->to;
1913                 nla_put(msg, IFLA_VLAN_QOS_MAPPING, sizeof(nl_qos_map), &nl_qos_map);
1914         }
1915         nla_nest_end(msg, qos);
1916 
1917         nla_nest_end(msg, data);
1918         nla_nest_end(msg, linkinfo);
1919 
1920         rv = system_rtnl_call(msg);
1921         if (rv)
1922                 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d", vlandev->ifname, dev->ifname, rv);
1923 
1924         return rv;
1925 
1926 nla_put_failure:
1927         nlmsg_free(msg);
1928         return -ENOMEM;
1929 }
1930 
1931 int system_vlandev_del(struct device *vlandev)
1932 {
1933         return system_link_del(vlandev->ifname);
1934 }
1935 
1936 #if LINUX_VERSION_CODE >= KERNEL_VERSION(6,1,0)
1937 struct if_get_master_data {
1938         int ifindex;
1939         int master_ifindex;
1940         int pending;
1941 };
1942 
1943 static void if_get_master_dsa_linkinfo_attr(struct if_get_master_data *data,
1944                                struct rtattr *attr)
1945 {
1946         struct rtattr *cur;
1947         int rem = RTA_PAYLOAD(attr);
1948 
1949         for (cur = RTA_DATA(attr); RTA_OK(cur, rem); cur = RTA_NEXT(cur, rem)) {
1950                 if (cur->rta_type != IFLA_DSA_MASTER)
1951                         continue;
1952 
1953                 data->master_ifindex = *(__u32 *)RTA_DATA(cur);
1954         }
1955 }
1956 
1957 static void if_get_master_linkinfo_attr(struct if_get_master_data *data,
1958                                struct rtattr *attr)
1959 {
1960         struct rtattr *cur;
1961         int rem = RTA_PAYLOAD(attr);
1962 
1963         for (cur = RTA_DATA(attr); RTA_OK(cur, rem); cur = RTA_NEXT(cur, rem)) {
1964                 if (cur->rta_type != IFLA_INFO_KIND && cur->rta_type != IFLA_INFO_DATA)
1965                         continue;
1966 
1967                 if (cur->rta_type == IFLA_INFO_KIND && strcmp("dsa", (char *)RTA_DATA(cur)))
1968                         break;
1969 
1970                 if (cur->rta_type == IFLA_INFO_DATA)
1971                         if_get_master_dsa_linkinfo_attr(data, cur);
1972         }
1973 }
1974 
1975 static int cb_if_get_master_valid(struct nl_msg *msg, void *arg)
1976 {
1977         struct nlmsghdr *nh = nlmsg_hdr(msg);
1978         struct ifinfomsg *ifi = NLMSG_DATA(nh);
1979         struct if_get_master_data *data = (struct if_get_master_data *)arg;
1980         struct rtattr *attr;
1981         int rem;
1982 
1983         if (nh->nlmsg_type != RTM_NEWLINK)
1984                 return NL_SKIP;
1985 
1986         if (ifi->ifi_family != AF_UNSPEC)
1987                 return NL_SKIP;
1988 
1989         if (ifi->ifi_index != data->ifindex)
1990                 return NL_SKIP;
1991 
1992         attr = IFLA_RTA(ifi);
1993         rem = nh->nlmsg_len - NLMSG_LENGTH(sizeof(*ifi));
1994 
1995         while (RTA_OK(attr, rem)) {
1996                 if (attr->rta_type == IFLA_LINKINFO)
1997                         if_get_master_linkinfo_attr(data, attr);
1998 
1999                 attr = RTA_NEXT(attr, rem);
2000         }
2001 
2002         return NL_OK;
2003 }
2004 
2005 static int cb_if_get_master_ack(struct nl_msg *msg, void *arg)
2006 {
2007         struct if_get_master_data *data = (struct if_get_master_data *)arg;
2008         data->pending = 0;
2009         return NL_STOP;
2010 }
2011 
2012 static int cb_if_get_master_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
2013 {
2014         struct if_get_master_data *data = (struct if_get_master_data *)arg;
2015         data->pending = 0;
2016         return NL_STOP;
2017 }
2018 
2019 static int system_if_get_master_ifindex(struct device *dev)
2020 {
2021         struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
2022         struct nl_msg *msg;
2023         struct ifinfomsg ifi = {
2024                 .ifi_family = AF_UNSPEC,
2025                 .ifi_index = 0,
2026         };
2027         struct if_get_master_data data = {
2028                 .ifindex = if_nametoindex(dev->ifname),
2029                 .master_ifindex = -1,
2030                 .pending = 1,
2031         };
2032         int ret = -1;
2033 
2034         if (!cb)
2035                 return ret;
2036 
2037         msg = nlmsg_alloc_simple(RTM_GETLINK, NLM_F_REQUEST);
2038         if (!msg)
2039                 goto out;
2040 
2041         if (nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
2042             nla_put_string(msg, IFLA_IFNAME, dev->ifname))
2043                 goto free;
2044 
2045         nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_get_master_valid, &data);
2046         nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_get_master_ack, &data);
2047         nl_cb_err(cb, NL_CB_CUSTOM, cb_if_get_master_error, &data);
2048 
2049         ret = nl_send_auto_complete(sock_rtnl, msg);
2050         if (ret < 0)
2051                 goto free;
2052 
2053         while (data.pending > 0)
2054                 if (nl_recvmsgs(sock_rtnl, cb) < 0)
2055                         break;
2056 
2057         ret = data.master_ifindex;
2058 
2059 free:
2060         nlmsg_free(msg);
2061 out:
2062         nl_cb_put(cb);
2063         return ret;
2064 }
2065 
2066 static void system_refresh_orig_macaddr(struct device *dev, struct device_settings *s)
2067 {
2068         struct ifreq ifr;
2069 
2070         memset(&ifr, 0, sizeof(ifr));
2071         strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
2072 
2073         if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0)
2074                 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
2075 }
2076 
2077 static void system_set_master(struct device *dev, int master_ifindex)
2078 {
2079         struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2080         struct nl_msg *nlm;
2081 
2082         nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST);
2083         if (!nlm)
2084                 return;
2085 
2086         nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2087         nla_put_string(nlm, IFLA_IFNAME, dev->ifname);
2088 
2089         struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2090         if (!linkinfo)
2091                 goto failure;
2092 
2093         nla_put_string(nlm, IFLA_INFO_KIND, "dsa");
2094         struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2095         if (!infodata)
2096                 goto failure;
2097 
2098         nla_put_u32(nlm, IFLA_DSA_MASTER, master_ifindex);
2099 
2100         nla_nest_end(nlm, infodata);
2101         nla_nest_end(nlm, linkinfo);
2102 
2103         system_rtnl_call(nlm);
2104 
2105         return;
2106 
2107 failure:
2108         nlmsg_free(nlm);
2109 }
2110 #endif
2111 
2112 static void ethtool_link_mode_clear_bit(__s8 nwords, int nr, __u32 *mask)
2113 {
2114         if (nr < 0)
2115                 return;
2116 
2117         if (nr >= (nwords * 32))
2118                 return;
2119 
2120         mask[nr / 32] &= ~(1U << (nr % 32));
2121 }
2122 
2123 static bool ethtool_link_mode_test_bit(__s8 nwords, int nr, const __u32 *mask)
2124 {
2125         if (nr < 0)
2126                 return false;
2127 
2128         if (nr >= (nwords * 32))
2129                 return false;
2130 
2131         return !!(mask[nr / 32] & (1U << (nr % 32)));
2132 }
2133 
2134 static int
2135 system_get_ethtool_gro(struct device *dev)
2136 {
2137         struct ethtool_value ecmd;
2138         struct ifreq ifr = {
2139                 .ifr_data = (caddr_t)&ecmd,
2140         };
2141 
2142         memset(&ecmd, 0, sizeof(ecmd));
2143         ecmd.cmd = ETHTOOL_GGRO;
2144         strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
2145 
2146         if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr))
2147                 return -1;
2148 
2149         return ecmd.data;
2150 }
2151 
2152 static void
2153 system_set_ethtool_gro(struct device *dev, struct device_settings *s)
2154 {
2155         struct ethtool_value ecmd;
2156         struct ifreq ifr = {
2157                 .ifr_data = (caddr_t)&ecmd,
2158         };
2159 
2160         memset(&ecmd, 0, sizeof(ecmd));
2161         ecmd.cmd = ETHTOOL_SGRO;
2162         ecmd.data = s->gro;
2163         strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
2164 
2165         ioctl(sock_ioctl, SIOCETHTOOL, &ifr);
2166 }
2167 
2168 static void
2169 system_set_ethtool_pause(struct device *dev, struct device_settings *s)
2170 {
2171         struct ethtool_pauseparam pp;
2172         struct ifreq ifr = {
2173                 .ifr_data = (caddr_t)&pp,
2174         };
2175 
2176         strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
2177         memset(&pp, 0, sizeof(pp));
2178         pp.cmd = ETHTOOL_GPAUSEPARAM;
2179         if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr))
2180                 return;
2181 
2182         if (s->flags & DEV_OPT_RXPAUSE || s->flags & DEV_OPT_TXPAUSE) {
2183                 pp.autoneg = AUTONEG_DISABLE;
2184 
2185                 if (s->flags & DEV_OPT_PAUSE) {
2186                         if (s->flags & DEV_OPT_RXPAUSE)
2187                                 pp.rx_pause = s->rxpause && s->pause;
2188                         else
2189                                 pp.rx_pause = s->pause;
2190 
2191                         if (s->flags & DEV_OPT_TXPAUSE)
2192                                 pp.tx_pause = s->txpause && s->pause;
2193                         else
2194                                 pp.tx_pause = s->pause;
2195                 } else {
2196                         if (s->flags & DEV_OPT_RXPAUSE)
2197                                 pp.rx_pause = s->rxpause;
2198 
2199                         if (s->flags & DEV_OPT_TXPAUSE)
2200                                 pp.tx_pause = s->txpause;
2201                 }
2202 
2203                 if (s->flags & DEV_OPT_ASYM_PAUSE &&
2204                     !s->asym_pause && (pp.rx_pause != pp.tx_pause))
2205                         pp.rx_pause = pp.tx_pause = false;
2206         } else {
2207                 pp.autoneg = AUTONEG_ENABLE;
2208                 /* Pause and Asym_Pause advertising bits will be set via
2209                  * ETHTOOL_SLINKSETTINGS in system_set_ethtool_settings()
2210                  */
2211         }
2212 
2213         pp.cmd = ETHTOOL_SPAUSEPARAM;
2214         ioctl(sock_ioctl, SIOCETHTOOL, &ifr);
2215 }
2216 
2217 static void
2218 system_set_ethtool_eee_settings(struct device *dev, struct device_settings *s)
2219 {
2220         struct ethtool_eee eeecmd;
2221         struct ifreq ifr = {
2222                 .ifr_data = (caddr_t)&eeecmd,
2223         };
2224 
2225         memset(&eeecmd, 0, sizeof(eeecmd));
2226         eeecmd.cmd = ETHTOOL_SEEE;
2227         eeecmd.eee_enabled = s->eee;
2228         strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
2229 
2230         if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) != 0)
2231                 netifd_log_message(L_WARNING, "cannot set eee %d for device %s", s->eee, dev->ifname);
2232 }
2233 
2234 /*
2235  * PSE (Power Sourcing Equipment) genetlink functions
2236  * Uses ethtool netlink interface to get/set PoE port configuration
2237  */
2238 struct pse_reply_data {
2239         bool valid;
2240         /* IEEE 802.3 Clause 33 (standard PoE) */
2241         uint32_t c33_admin_state;
2242         uint32_t c33_pw_status;
2243         uint32_t c33_pw_class;
2244         uint32_t c33_actual_pw;
2245         uint32_t c33_avail_pw_limit;
2246         /* IEEE 802.3 PoDL (Power over Data Line, e.g. single-pair Ethernet) */
2247         uint32_t podl_admin_state;
2248         uint32_t podl_pw_status;
2249         /* Port priority for power budget management */
2250         uint32_t pse_prio_max;
2251         uint32_t pse_prio;
2252 };
2253 
2254 static int cb_pse_get_reply(struct nl_msg *msg, void *arg)
2255 {
2256         struct pse_reply_data *data = arg;
2257         struct nlmsghdr *nlh = nlmsg_hdr(msg);
2258         struct nlattr *tb[ETHTOOL_A_PSE_MAX + 1];
2259         struct genlmsghdr *ghdr;
2260 
2261         if (nlh->nlmsg_type != ethtool_family)
2262                 return NL_SKIP;
2263 
2264         ghdr = nlmsg_data(nlh);
2265         if (nla_parse(tb, ETHTOOL_A_PSE_MAX, genlmsg_attrdata(ghdr, 0),
2266                       genlmsg_attrlen(ghdr, 0), NULL) < 0)
2267                 return NL_SKIP;
2268 
2269         data->valid = true;
2270 
2271         if (tb[ETHTOOL_A_C33_PSE_ADMIN_STATE])
2272                 data->c33_admin_state = nla_get_u32(tb[ETHTOOL_A_C33_PSE_ADMIN_STATE]);
2273         if (tb[ETHTOOL_A_C33_PSE_PW_D_STATUS])
2274                 data->c33_pw_status = nla_get_u32(tb[ETHTOOL_A_C33_PSE_PW_D_STATUS]);
2275         if (tb[ETHTOOL_A_C33_PSE_PW_CLASS])
2276                 data->c33_pw_class = nla_get_u32(tb[ETHTOOL_A_C33_PSE_PW_CLASS]);
2277         if (tb[ETHTOOL_A_C33_PSE_ACTUAL_PW])
2278                 data->c33_actual_pw = nla_get_u32(tb[ETHTOOL_A_C33_PSE_ACTUAL_PW]);
2279         if (tb[ETHTOOL_A_C33_PSE_AVAIL_PW_LIMIT])
2280                 data->c33_avail_pw_limit = nla_get_u32(tb[ETHTOOL_A_C33_PSE_AVAIL_PW_LIMIT]);
2281         if (tb[ETHTOOL_A_PODL_PSE_ADMIN_STATE])
2282                 data->podl_admin_state = nla_get_u32(tb[ETHTOOL_A_PODL_PSE_ADMIN_STATE]);
2283         if (tb[ETHTOOL_A_PODL_PSE_PW_D_STATUS])
2284                 data->podl_pw_status = nla_get_u32(tb[ETHTOOL_A_PODL_PSE_PW_D_STATUS]);
2285 #ifdef HAVE_ETHTOOL_A_PSE_PRIO
2286         if (tb[ETHTOOL_A_PSE_PRIO_MAX])
2287                 data->pse_prio_max = nla_get_u32(tb[ETHTOOL_A_PSE_PRIO_MAX]);
2288         if (tb[ETHTOOL_A_PSE_PRIO])
2289                 data->pse_prio = nla_get_u32(tb[ETHTOOL_A_PSE_PRIO]);
2290 #endif
2291 
2292         return NL_OK;
2293 }
2294 
2295 struct pse_get_cb_data {
2296         struct pse_reply_data *data;
2297         int pending;
2298         int err;
2299 };
2300 
2301 static int cb_pse_get_ack(struct nl_msg *msg, void *arg)
2302 {
2303         struct pse_get_cb_data *cb_data = arg;
2304         cb_data->pending = 0;
2305         return NL_STOP;
2306 }
2307 
2308 static int cb_pse_get_error(struct sockaddr_nl *nla, struct nlmsgerr *nlerr, void *arg)
2309 {
2310         struct pse_get_cb_data *cb_data = arg;
2311         cb_data->pending = 0;
2312         cb_data->err = nlerr->error;
2313         return NL_STOP;
2314 }
2315 
2316 static int cb_pse_get_valid_wrapper(struct nl_msg *msg, void *arg)
2317 {
2318         struct pse_get_cb_data *cb_data = arg;
2319         return cb_pse_get_reply(msg, cb_data->data);
2320 }
2321 
2322 static int system_pse_get(struct device *dev, struct pse_reply_data *data)
2323 {
2324         struct nl_msg *msg;
2325         struct nlattr *hdr;
2326         struct nl_cb *cb;
2327         struct pse_get_cb_data cb_data;
2328         int ret;
2329 
2330         memset(data, 0, sizeof(*data));
2331 
2332         if (!sock_genl || ethtool_family < 0) {
2333                 return -EOPNOTSUPP;
2334         }
2335 
2336         cb = nl_cb_alloc(NL_CB_DEFAULT);
2337         if (!cb)
2338                 return -ENOMEM;
2339 
2340         msg = nlmsg_alloc();
2341         if (!msg) {
2342                 nl_cb_put(cb);
2343                 return -ENOMEM;
2344         }
2345 
2346         if (!genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, ethtool_family,
2347                          0, 0, ETHTOOL_MSG_PSE_GET, 1)) {
2348                 nlmsg_free(msg);
2349                 nl_cb_put(cb);
2350                 return -ENOMEM;
2351         }
2352 
2353         hdr = nla_nest_start(msg, ETHTOOL_A_PSE_HEADER);
2354         if (!hdr) {
2355                 nlmsg_free(msg);
2356                 nl_cb_put(cb);
2357                 return -ENOMEM;
2358         }
2359         nla_put_string(msg, ETHTOOL_A_HEADER_DEV_NAME, dev->ifname);
2360         nla_nest_end(msg, hdr);
2361 
2362         cb_data.data = data;
2363         cb_data.pending = 1;
2364         cb_data.err = 0;
2365 
2366         nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_pse_get_valid_wrapper, &cb_data);
2367         nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_pse_get_ack, &cb_data);
2368         nl_cb_err(cb, NL_CB_CUSTOM, cb_pse_get_error, &cb_data);
2369 
2370         ret = nl_send_auto_complete(sock_genl, msg);
2371         nlmsg_free(msg);
2372         if (ret < 0) {
2373                 nl_cb_put(cb);
2374                 return ret;
2375         }
2376 
2377         while (cb_data.pending > 0) {
2378                 ret = nl_recvmsgs(sock_genl, cb);
2379                 if (ret < 0) {
2380                         cb_data.pending = 0;
2381                         cb_data.err = ret;
2382                 }
2383         }
2384 
2385         nl_cb_put(cb);
2386 
2387         if (cb_data.err) {
2388                 return cb_data.err;
2389         }
2390 
2391         return data->valid ? 0 : -EOPNOTSUPP;
2392 }
2393 
2394 struct pse_set_cb_data {
2395         int pending;
2396         int err;
2397 };
2398 
2399 static int cb_pse_set_ack(struct nl_msg *msg, void *arg)
2400 {
2401         struct pse_set_cb_data *cb_data = arg;
2402         cb_data->pending = 0;
2403         return NL_STOP;
2404 }
2405 
2406 static int cb_pse_set_error(struct sockaddr_nl *nla, struct nlmsgerr *nlerr, void *arg)
2407 {
2408         struct pse_set_cb_data *cb_data = arg;
2409         cb_data->pending = 0;
2410         cb_data->err = nlerr->error;
2411         return NL_STOP;
2412 }
2413 
2414 static int system_pse_set(struct device *dev, struct device_settings *s)
2415 {
2416         struct nl_msg *msg;
2417         struct nlattr *hdr;
2418         struct nl_cb *cb;
2419         struct pse_set_cb_data cb_data;
2420         int ret;
2421 
2422         /* Early return if no PSE settings requested */
2423         if (!(s->flags & (DEV_OPT_PSE | DEV_OPT_PSE_PODL |
2424                           DEV_OPT_PSE_POWER_LIMIT | DEV_OPT_PSE_PRIORITY)))
2425                 return 0;
2426 
2427         if (!sock_genl || ethtool_family < 0) {
2428                 netifd_log_message(L_WARNING, "PSE: genetlink not available for %s", dev->ifname);
2429                 return -EOPNOTSUPP;
2430         }
2431 
2432         cb = nl_cb_alloc(NL_CB_DEFAULT);
2433         if (!cb)
2434                 return -ENOMEM;
2435 
2436         msg = nlmsg_alloc();
2437         if (!msg) {
2438                 nl_cb_put(cb);
2439                 return -ENOMEM;
2440         }
2441 
2442         if (!genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, ethtool_family,
2443                          0, 0, ETHTOOL_MSG_PSE_SET, 1)) {
2444                 nlmsg_free(msg);
2445                 nl_cb_put(cb);
2446                 return -ENOMEM;
2447         }
2448 
2449         hdr = nla_nest_start(msg, ETHTOOL_A_PSE_HEADER);
2450         if (!hdr) {
2451                 nlmsg_free(msg);
2452                 nl_cb_put(cb);
2453                 return -ENOMEM;
2454         }
2455         nla_put_string(msg, ETHTOOL_A_HEADER_DEV_NAME, dev->ifname);
2456         nla_nest_end(msg, hdr);
2457 
2458         if (s->flags & DEV_OPT_PSE)
2459                 nla_put_u32(msg, ETHTOOL_A_C33_PSE_ADMIN_CONTROL,
2460                             s->pse ? ETHTOOL_C33_PSE_ADMIN_STATE_ENABLED :
2461                                      ETHTOOL_C33_PSE_ADMIN_STATE_DISABLED);
2462 
2463         if (s->flags & DEV_OPT_PSE_PODL)
2464                 nla_put_u32(msg, ETHTOOL_A_PODL_PSE_ADMIN_CONTROL,
2465                             s->pse_podl ? ETHTOOL_PODL_PSE_ADMIN_STATE_ENABLED :
2466                                           ETHTOOL_PODL_PSE_ADMIN_STATE_DISABLED);
2467 
2468         if (s->flags & DEV_OPT_PSE_POWER_LIMIT)
2469                 nla_put_u32(msg, ETHTOOL_A_C33_PSE_AVAIL_PW_LIMIT, s->pse_power_limit);
2470 
2471 #ifdef HAVE_ETHTOOL_A_PSE_PRIO
2472         if (s->flags & DEV_OPT_PSE_PRIORITY)
2473                 nla_put_u32(msg, ETHTOOL_A_PSE_PRIO, s->pse_priority);
2474 #endif
2475 
2476         cb_data.pending = 1;
2477         cb_data.err = 0;
2478 
2479         nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_pse_set_ack, &cb_data);
2480         nl_cb_err(cb, NL_CB_CUSTOM, cb_pse_set_error, &cb_data);
2481 
2482         ret = nl_send_auto_complete(sock_genl, msg);
2483         nlmsg_free(msg);
2484         if (ret < 0) {
2485                 netifd_log_message(L_WARNING, "PSE: send failed for %s: %d", dev->ifname, ret);
2486                 nl_cb_put(cb);
2487                 return ret;
2488         }
2489 
2490         while (cb_data.pending > 0) {
2491                 ret = nl_recvmsgs(sock_genl, cb);
2492                 if (ret < 0) {
2493                         cb_data.pending = 0;
2494                         cb_data.err = ret;
2495                 }
2496         }
2497 
2498         nl_cb_put(cb);
2499 
2500         if (cb_data.err) {
2501                 netifd_log_message(L_WARNING, "PSE: set failed for %s: %d", dev->ifname, cb_data.err);
2502                 return cb_data.err;
2503         }
2504 
2505         return 0;
2506 }
2507 
2508 static void
2509 system_set_ethtool_settings(struct device *dev, struct device_settings *s)
2510 {
2511         struct {
2512                 struct ethtool_link_settings req;
2513                 __u32 link_mode_data[3 * 127];
2514         } ecmd;
2515         struct ifreq ifr = {
2516                 .ifr_data = (caddr_t)&ecmd,
2517         };
2518         size_t i;
2519         __s8 nwords;
2520         __u32 *supported, *advertising;
2521 
2522         system_set_ethtool_pause(dev, s);
2523 
2524         if (s->flags & DEV_OPT_EEE)
2525                 system_set_ethtool_eee_settings(dev, s);
2526 
2527         /* Apply PSE (PoE) settings if configured */
2528         if (s->flags & (DEV_OPT_PSE | DEV_OPT_PSE_PODL | DEV_OPT_PSE_POWER_LIMIT | DEV_OPT_PSE_PRIORITY))
2529                 system_pse_set(dev, s);
2530 
2531         /* Avoid a rmw ioctl call if nothing needs to be changed. */
2532         if (!(s->flags & (DEV_OPT_AUTONEG | DEV_OPT_SPEED | DEV_OPT_DUPLEX | DEV_OPT_PAUSE | DEV_OPT_ASYM_PAUSE)))
2533                 return;
2534 
2535         memset(&ecmd, 0, sizeof(ecmd));
2536         ecmd.req.cmd = ETHTOOL_GLINKSETTINGS;
2537         strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
2538 
2539         if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) < 0 ||
2540             ecmd.req.link_mode_masks_nwords >= 0 ||
2541             ecmd.req.cmd != ETHTOOL_GLINKSETTINGS)
2542                 return;
2543 
2544         ecmd.req.link_mode_masks_nwords = -ecmd.req.link_mode_masks_nwords;
2545 
2546         if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) < 0 ||
2547             ecmd.req.link_mode_masks_nwords <= 0 ||
2548             ecmd.req.cmd != ETHTOOL_GLINKSETTINGS)
2549                 return;
2550 
2551         nwords = ecmd.req.link_mode_masks_nwords;
2552         supported = &ecmd.link_mode_data[0];
2553         advertising = &ecmd.link_mode_data[nwords];
2554         memcpy(advertising, supported, sizeof(__u32) * nwords);
2555 
2556         for (i = 0; i < ARRAY_SIZE(ethtool_modes); i++) {
2557                 if (s->flags & DEV_OPT_DUPLEX) {
2558                         if (s->duplex)
2559                                 ethtool_link_mode_clear_bit(nwords, ethtool_modes[i].bit_half, advertising);
2560                         else
2561                                 ethtool_link_mode_clear_bit(nwords, ethtool_modes[i].bit_full, advertising);
2562                 }
2563                 if (!(s->flags & DEV_OPT_SPEED) ||
2564                     s->speed == ethtool_modes[i].speed)
2565                         continue;
2566 
2567                 ethtool_link_mode_clear_bit(nwords, ethtool_modes[i].bit_full, advertising);
2568                 ethtool_link_mode_clear_bit(nwords, ethtool_modes[i].bit_half, advertising);
2569         }
2570 
2571         if (s->flags & DEV_OPT_PAUSE)
2572                 if (!s->pause)
2573                         ethtool_link_mode_clear_bit(nwords, ETHTOOL_LINK_MODE_Pause_BIT, advertising);
2574 
2575         if (s->flags & DEV_OPT_ASYM_PAUSE)
2576                 if (!s->asym_pause)
2577                         ethtool_link_mode_clear_bit(nwords, ETHTOOL_LINK_MODE_Asym_Pause_BIT, advertising);
2578 
2579         if (s->flags & DEV_OPT_AUTONEG) {
2580                 ecmd.req.autoneg = s->autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE;
2581                 if (!s->autoneg) {
2582                         if (s->flags & DEV_OPT_SPEED)
2583                                 ecmd.req.speed = s->speed;
2584 
2585                         if (s->flags & DEV_OPT_DUPLEX)
2586                                 ecmd.req.duplex = s->duplex ? DUPLEX_FULL : DUPLEX_HALF;
2587                 }
2588         }
2589 
2590         ecmd.req.cmd = ETHTOOL_SLINKSETTINGS;
2591         ioctl(sock_ioctl, SIOCETHTOOL, &ifr);
2592 }
2593 
2594 static void
2595 system_set_ethtool_settings_after_up(struct device *dev, struct device_settings *s)
2596 {
2597         if (s->flags & DEV_OPT_GRO)
2598                 system_set_ethtool_gro(dev, s);
2599 }
2600 
2601 void
2602 system_if_get_settings(struct device *dev, struct device_settings *s)
2603 {
2604         struct ifreq ifr;
2605         char buf[10];
2606         int ret;
2607 
2608         memset(&ifr, 0, sizeof(ifr));
2609         strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
2610 
2611         if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
2612                 s->mtu = ifr.ifr_mtu;
2613                 s->flags |= DEV_OPT_MTU;
2614         }
2615 
2616         s->mtu6 = system_update_ipv6_mtu(dev, 0);
2617         if (s->mtu6 > 0)
2618                 s->flags |= DEV_OPT_MTU6;
2619 
2620         if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
2621                 s->txqueuelen = ifr.ifr_qlen;
2622                 s->flags |= DEV_OPT_TXQUEUELEN;
2623         }
2624 
2625         if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
2626                 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
2627                 s->flags |= DEV_OPT_MACADDR;
2628         }
2629 
2630         if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
2631                 s->ipv6 = !strtoul(buf, NULL, 0);
2632                 s->flags |= DEV_OPT_IPV6;
2633         }
2634 
2635         if (!system_get_ip6segmentrouting(dev, buf, sizeof(buf))) {
2636                 s->ip6segmentrouting = strtoul(buf, NULL, 0);
2637                 s->flags |= DEV_OPT_IP6SEGMENTROUTING;
2638         }
2639 
2640         if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
2641                 s->promisc = ifr.ifr_flags & IFF_PROMISC;
2642                 s->flags |= DEV_OPT_PROMISC;
2643 
2644                 s->multicast = ifr.ifr_flags & IFF_MULTICAST;
2645                 s->flags |= DEV_OPT_MULTICAST;
2646         }
2647 
2648         if (!system_get_rpfilter(dev, buf, sizeof(buf))) {
2649                 s->rpfilter = strtoul(buf, NULL, 0);
2650                 s->flags |= DEV_OPT_RPFILTER;
2651         }
2652 
2653         if (!system_get_acceptlocal(dev, buf, sizeof(buf))) {
2654                 s->acceptlocal = strtoul(buf, NULL, 0);
2655                 s->flags |= DEV_OPT_ACCEPTLOCAL;
2656         }
2657 
2658         if (!system_get_igmpversion(dev, buf, sizeof(buf))) {
2659                 s->igmpversion = strtoul(buf, NULL, 0);
2660                 s->flags |= DEV_OPT_IGMPVERSION;
2661         }
2662 
2663         if (!system_get_mldversion(dev, buf, sizeof(buf))) {
2664                 s->mldversion = strtoul(buf, NULL, 0);
2665                 s->flags |= DEV_OPT_MLDVERSION;
2666         }
2667 
2668         if (!system_get_neigh4reachabletime(dev, buf, sizeof(buf))) {
2669                 s->neigh4reachabletime = strtoul(buf, NULL, 0);
2670                 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
2671         }
2672 
2673         if (!system_get_neigh6reachabletime(dev, buf, sizeof(buf))) {
2674                 s->neigh6reachabletime = strtoul(buf, NULL, 0);
2675                 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
2676         }
2677 
2678         if (!system_get_neigh4locktime(dev, buf, sizeof(buf))) {
2679                 s->neigh4locktime = strtol(buf, NULL, 0);
2680                 s->flags |= DEV_OPT_NEIGHLOCKTIME;
2681         }
2682 
2683         if (!system_get_neigh4gcstaletime(dev, buf, sizeof(buf))) {
2684                 s->neigh4gcstaletime = strtoul(buf, NULL, 0);
2685                 s->flags |= DEV_OPT_NEIGHGCSTALETIME;
2686         }
2687 
2688         if (!system_get_neigh6gcstaletime(dev, buf, sizeof(buf))) {
2689                 s->neigh6gcstaletime = strtoul(buf, NULL, 0);
2690                 s->flags |= DEV_OPT_NEIGHGCSTALETIME;
2691         }
2692 
2693         if (!system_get_dadtransmits(dev, buf, sizeof(buf))) {
2694                 s->dadtransmits = strtoul(buf, NULL, 0);
2695                 s->flags |= DEV_OPT_DADTRANSMITS;
2696         }
2697 
2698         if (!system_get_sendredirects(dev, buf, sizeof(buf))) {
2699                 s->sendredirects = strtoul(buf, NULL, 0);
2700                 s->flags |= DEV_OPT_SENDREDIRECTS;
2701         }
2702 
2703         if (!system_get_drop_v4_unicast_in_l2_multicast(dev, buf, sizeof(buf))) {
2704                 s->drop_v4_unicast_in_l2_multicast = strtoul(buf, NULL, 0);
2705                 s->flags |= DEV_OPT_DROP_V4_UNICAST_IN_L2_MULTICAST;
2706         }
2707 
2708         if (!system_get_drop_v6_unicast_in_l2_multicast(dev, buf, sizeof(buf))) {
2709                 s->drop_v6_unicast_in_l2_multicast = strtoul(buf, NULL, 0);
2710                 s->flags |= DEV_OPT_DROP_V6_UNICAST_IN_L2_MULTICAST;
2711         }
2712 
2713         if (!system_get_drop_gratuitous_arp(dev, buf, sizeof(buf))) {
2714                 s->drop_gratuitous_arp = strtoul(buf, NULL, 0);
2715                 s->flags |= DEV_OPT_DROP_GRATUITOUS_ARP;
2716         }
2717 
2718         if (!system_get_drop_unsolicited_na(dev, buf, sizeof(buf))) {
2719                 s->drop_unsolicited_na = strtoul(buf, NULL, 0);
2720                 s->flags |= DEV_OPT_DROP_UNSOLICITED_NA;
2721         }
2722 
2723         if (!system_get_arp_accept(dev, buf, sizeof(buf))) {
2724                 s->arp_accept = strtoul(buf, NULL, 0);
2725                 s->flags |= DEV_OPT_ARP_ACCEPT;
2726         }
2727 
2728         ret = system_get_ethtool_gro(dev);
2729         if (ret >= 0) {
2730                 s->gro = ret;
2731                 s->flags |= DEV_OPT_GRO;
2732         }
2733 
2734 #if LINUX_VERSION_CODE >= KERNEL_VERSION(6,1,0)
2735         ret = system_if_get_master_ifindex(dev);
2736         if (ret >= 0) {
2737                 s->master_ifindex = ret;
2738                 s->flags |= DEV_OPT_MASTER;
2739         }
2740 #endif
2741 }
2742 
2743 void
2744 system_if_apply_settings(struct device *dev, struct device_settings *s, uint64_t apply_mask)
2745 {
2746         struct ifreq ifr;
2747         char buf[12];
2748 
2749         apply_mask &= s->flags;
2750 
2751         if (apply_mask & DEV_OPT_MASTER) {
2752 #if LINUX_VERSION_CODE >= KERNEL_VERSION(6,1,0)
2753                 system_set_master(dev, s->master_ifindex);
2754                 if (!(apply_mask & (DEV_OPT_MACADDR | DEV_OPT_DEFAULT_MACADDR)) || dev->external)
2755                         system_refresh_orig_macaddr(dev, &dev->orig_settings);
2756 #else
2757                 netifd_log_message(L_WARNING, "%s Your kernel is older than linux 6.1.0, changing DSA port conduit is not supported!", dev->ifname);
2758 #endif
2759         }
2760 
2761         memset(&ifr, 0, sizeof(ifr));
2762         strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
2763         if (apply_mask & DEV_OPT_MTU) {
2764                 ifr.ifr_mtu = s->mtu;
2765                 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
2766                         s->flags &= ~DEV_OPT_MTU;
2767         }
2768         if (apply_mask & DEV_OPT_MTU6) {
2769                 system_update_ipv6_mtu(dev, s->mtu6);
2770         }
2771         if (apply_mask & DEV_OPT_TXQUEUELEN) {
2772                 ifr.ifr_qlen = s->txqueuelen;
2773                 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
2774                         s->flags &= ~DEV_OPT_TXQUEUELEN;
2775         }
2776         if ((apply_mask & (DEV_OPT_MACADDR | DEV_OPT_DEFAULT_MACADDR)) && !dev->external) {
2777                 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
2778                 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
2779                 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
2780                         s->flags &= ~DEV_OPT_MACADDR;
2781         }
2782         if (apply_mask & DEV_OPT_IPV6)
2783                 system_set_disable_ipv6(dev, s->ipv6 ? "" : "1");
2784         if (s->flags & DEV_OPT_IP6SEGMENTROUTING & apply_mask) {
2785                 struct device dummy = {
2786                         .ifname = "all",
2787                 };
2788                 bool ip6segmentrouting = device_check_ip6segmentrouting();
2789 
2790                 system_set_ip6segmentrouting(dev, s->ip6segmentrouting ? "1" : "");
2791                 system_set_ip6segmentrouting(&dummy, ip6segmentrouting ? "1" : "");
2792         }
2793         if (apply_mask & DEV_OPT_PROMISC) {
2794                 if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
2795                                     !s->promisc ? IFF_PROMISC : 0) < 0)
2796                         s->flags &= ~DEV_OPT_PROMISC;
2797         }
2798         if (apply_mask & DEV_OPT_RPFILTER) {
2799                 snprintf(buf, sizeof(buf), "%u", s->rpfilter);
2800                 system_set_rpfilter(dev, buf);
2801         }
2802         if (apply_mask & DEV_OPT_ACCEPTLOCAL)
2803                 system_set_acceptlocal(dev, s->acceptlocal ? "1" : "");
2804         if (apply_mask & DEV_OPT_IGMPVERSION) {
2805                 snprintf(buf, sizeof(buf), "%u", s->igmpversion);
2806                 system_set_igmpversion(dev, buf);
2807         }
2808         if (apply_mask & DEV_OPT_MLDVERSION) {
2809                 snprintf(buf, sizeof(buf), "%u", s->mldversion);
2810                 system_set_mldversion(dev, buf);
2811         }
2812         if (apply_mask & DEV_OPT_NEIGHREACHABLETIME) {
2813                 snprintf(buf, sizeof(buf), "%u", s->neigh4reachabletime);
2814                 system_set_neigh4reachabletime(dev, buf);
2815                 snprintf(buf, sizeof(buf), "%u", s->neigh6reachabletime);
2816                 system_set_neigh6reachabletime(dev, buf);
2817         }
2818         if (apply_mask & DEV_OPT_NEIGHLOCKTIME) {
2819                 snprintf(buf, sizeof(buf), "%d", s->neigh4locktime);
2820                 system_set_neigh4locktime(dev, buf);
2821         }
2822         if (apply_mask & DEV_OPT_NEIGHGCSTALETIME) {
2823                 snprintf(buf, sizeof(buf), "%u", s->neigh4gcstaletime);
2824                 system_set_neigh4gcstaletime(dev, buf);
2825                 snprintf(buf, sizeof(buf), "%u", s->neigh6gcstaletime);
2826                 system_set_neigh6gcstaletime(dev, buf);
2827         }
2828         if (apply_mask & DEV_OPT_DADTRANSMITS) {
2829                 snprintf(buf, sizeof(buf), "%u", s->dadtransmits);
2830                 system_set_dadtransmits(dev, buf);
2831         }
2832         if (apply_mask & DEV_OPT_MULTICAST) {
2833                 if (system_if_flags(dev->ifname, s->multicast ? IFF_MULTICAST : 0,
2834                                     !s->multicast ? IFF_MULTICAST : 0) < 0)
2835                         s->flags &= ~DEV_OPT_MULTICAST;
2836         }
2837         if (apply_mask & DEV_OPT_SENDREDIRECTS)
2838                 system_set_sendredirects(dev, s->sendredirects ? "1" : "");
2839         if (apply_mask & DEV_OPT_DROP_V4_UNICAST_IN_L2_MULTICAST)
2840                 system_set_drop_v4_unicast_in_l2_multicast(dev, s->drop_v4_unicast_in_l2_multicast ? "1" : "");
2841         if (apply_mask & DEV_OPT_DROP_V6_UNICAST_IN_L2_MULTICAST)
2842                 system_set_drop_v6_unicast_in_l2_multicast(dev, s->drop_v6_unicast_in_l2_multicast ? "1" : "");
2843         if (apply_mask & DEV_OPT_DROP_GRATUITOUS_ARP)
2844                 system_set_drop_gratuitous_arp(dev, s->drop_gratuitous_arp ? "1" : "");
2845         if (apply_mask & DEV_OPT_DROP_UNSOLICITED_NA)
2846                 system_set_drop_unsolicited_na(dev, s->drop_unsolicited_na ? "1" : "");
2847         if (apply_mask & DEV_OPT_ARP_ACCEPT)
2848                 system_set_arp_accept(dev, s->arp_accept ? "1" : "");
2849         if (apply_mask & (DEV_OPT_SPEED | DEV_OPT_DUPLEX |
2850                           DEV_OPT_PAUSE | DEV_OPT_ASYM_PAUSE |
2851                           DEV_OPT_RXPAUSE | DEV_OPT_TXPAUSE |
2852                           DEV_OPT_AUTONEG | DEV_OPT_EEE |
2853                           DEV_OPT_PSE | DEV_OPT_PSE_PODL |
2854                           DEV_OPT_PSE_POWER_LIMIT | DEV_OPT_PSE_PRIORITY))
2855                 system_set_ethtool_settings(dev, s);
2856 }
2857 
2858 void system_if_apply_settings_after_up(struct device *dev, struct device_settings *s)
2859 {
2860         system_set_ethtool_settings_after_up(dev, s);
2861 }
2862 
2863 int system_if_up(struct device *dev)
2864 {
2865         return system_if_flags(dev->ifname, IFF_UP, 0);
2866 }
2867 
2868 int system_if_down(struct device *dev)
2869 {
2870         return system_if_flags(dev->ifname, 0, IFF_UP);
2871 }
2872 
2873 bool system_if_is_point_to_point(struct device *dev)
2874 {
2875         struct ifreq ifr = {};
2876 
2877         strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
2878         if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) < 0)
2879                 return false;
2880 
2881         return ifr.ifr_flags & IFF_POINTOPOINT;
2882 }
2883 
2884 struct if_check_data {
2885         struct device *dev;
2886         int pending;
2887         int ret;
2888 };
2889 
2890 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
2891 {
2892         struct nlmsghdr *nh = nlmsg_hdr(msg);
2893         struct ifinfomsg *ifi = NLMSG_DATA(nh);
2894         struct if_check_data *chk = (struct if_check_data *)arg;
2895 
2896         if (nh->nlmsg_type != RTM_NEWLINK)
2897                 return NL_SKIP;
2898 
2899         system_device_update_state(chk->dev, ifi->ifi_flags);
2900         return NL_OK;
2901 }
2902 
2903 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
2904 {
2905         struct if_check_data *chk = (struct if_check_data *)arg;
2906         chk->pending = 0;
2907         return NL_STOP;
2908 }
2909 
2910 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
2911 {
2912         struct if_check_data *chk = (struct if_check_data *)arg;
2913 
2914         if (chk->dev->type == &simple_device_type)
2915                 device_set_present(chk->dev, false);
2916         device_set_link(chk->dev, false);
2917         chk->pending = err->error;
2918 
2919         return NL_STOP;
2920 }
2921 
2922 struct bridge_vlan_check_data {
2923         struct device *check_dev;
2924         int ifindex;
2925         int ret;
2926         bool pending;
2927 };
2928 
2929 static void bridge_vlan_check_port(struct bridge_vlan_check_data *data,
2930                                    struct bridge_vlan_port *port,
2931                                    struct bridge_vlan_info *vinfo)
2932 {
2933         uint16_t flags = 0, diff, mask;
2934 
2935         if (port->flags & BRVLAN_F_PVID)
2936                 flags |= BRIDGE_VLAN_INFO_PVID;
2937         if (port->flags & BRVLAN_F_UNTAGGED)
2938                 flags |= BRIDGE_VLAN_INFO_UNTAGGED;
2939 
2940         diff = vinfo->flags ^ flags;
2941         mask = BRVLAN_F_UNTAGGED | (flags & BRIDGE_VLAN_INFO_PVID);
2942         if (diff & mask) {
2943                 data->ret = 1;
2944                 data->pending = false;
2945         }
2946 
2947         port->check = 1;
2948 }
2949 
2950 static void bridge_vlan_check_attr(struct bridge_vlan_check_data *data,
2951                                    struct rtattr *attr)
2952 {
2953         struct bridge_vlan_hotplug_port *port;
2954         struct bridge_vlan_info *vinfo;
2955         struct bridge_vlan *vlan;
2956         struct rtattr *cur;
2957         int rem = RTA_PAYLOAD(attr);
2958         int i;
2959 
2960         for (cur = RTA_DATA(attr); RTA_OK(cur, rem); cur = RTA_NEXT(cur, rem)) {
2961                 if (cur->rta_type != IFLA_BRIDGE_VLAN_INFO)
2962                         continue;
2963 
2964                 vinfo = RTA_DATA(cur);
2965                 vlan = vlist_find(&data->check_dev->vlans, &vinfo->vid, vlan, node);
2966                 if (!vlan) {
2967                         data->ret = 1;
2968                         data->pending = false;
2969                         return;
2970                 }
2971 
2972                 for (i = 0; i < vlan->n_ports; i++)
2973                         if (!vlan->ports[i].check)
2974                                 bridge_vlan_check_port(data, &vlan->ports[i], vinfo);
2975 
2976                 list_for_each_entry(port, &vlan->hotplug_ports, list)
2977                         if (!port->port.check)
2978                                 bridge_vlan_check_port(data, &port->port, vinfo);
2979         }
2980 }
2981 
2982 static int bridge_vlan_check_cb(struct nl_msg *msg, void *arg)
2983 {
2984         struct bridge_vlan_check_data *data = arg;
2985         struct nlmsghdr *nh = nlmsg_hdr(msg);
2986         struct ifinfomsg *ifi = NLMSG_DATA(nh);
2987         struct rtattr *attr;
2988         int rem;
2989 
2990         if (nh->nlmsg_type != RTM_NEWLINK)
2991                 return NL_SKIP;
2992 
2993         if (ifi->ifi_family != AF_BRIDGE)
2994                 return NL_SKIP;
2995 
2996         if (ifi->ifi_index != data->ifindex)
2997                 return NL_SKIP;
2998 
2999         attr = IFLA_RTA(ifi);
3000         rem = nh->nlmsg_len - NLMSG_LENGTH(sizeof(*ifi));
3001         while (RTA_OK(attr, rem)) {
3002                 if (attr->rta_type == IFLA_AF_SPEC)
3003                         bridge_vlan_check_attr(data, attr);
3004 
3005                 attr = RTA_NEXT(attr, rem);
3006         }
3007 
3008         return NL_SKIP;
3009 }
3010 
3011 static int bridge_vlan_ack_cb(struct nl_msg *msg, void *arg)
3012 {
3013         struct bridge_vlan_check_data *data = arg;
3014         data->pending = false;
3015         return NL_STOP;
3016 }
3017 
3018 static int bridge_vlan_error_cb(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
3019 {
3020         struct bridge_vlan_check_data *data = arg;
3021         data->pending = false;
3022         return NL_STOP;
3023 }
3024 
3025 int system_bridge_vlan_check(struct device *dev, char *ifname)
3026 {
3027         struct bridge_vlan_check_data data = {
3028                 .check_dev = dev,
3029                 .ifindex = if_nametoindex(ifname),
3030                 .ret = -1,
3031                 .pending = true,
3032         };
3033         static struct ifinfomsg ifi = {
3034                 .ifi_family = AF_BRIDGE
3035         };
3036         static struct rtattr ext_req = {
3037                 .rta_type = IFLA_EXT_MASK,
3038                 .rta_len = RTA_LENGTH(sizeof(uint32_t)),
3039         };
3040         uint32_t filter = RTEXT_FILTER_BRVLAN;
3041         struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
3042         struct bridge_vlan *vlan;
3043         struct nl_msg *msg;
3044         int i;
3045 
3046         if (!data.ifindex)
3047                 return 0;
3048 
3049         msg = nlmsg_alloc_simple(RTM_GETLINK, NLM_F_DUMP);
3050 
3051         if (nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
3052                 nlmsg_append(msg, &ext_req, sizeof(ext_req), NLMSG_ALIGNTO) ||
3053                 nlmsg_append(msg, &filter, sizeof(filter), 0))
3054                 goto free;
3055 
3056         vlist_for_each_element(&dev->vlans, vlan, node) {
3057                 struct bridge_vlan_hotplug_port *port;
3058 
3059                 for (i = 0; i < vlan->n_ports; i++) {
3060                         if (!strcmp(vlan->ports[i].ifname, ifname))
3061                                 vlan->ports[i].check = 0;
3062                         else
3063                                 vlan->ports[i].check = -1;
3064                 }
3065 
3066                 list_for_each_entry(port, &vlan->hotplug_ports, list) {
3067                         if (!strcmp(port->port.ifname, ifname))
3068                                 port->port.check = 0;
3069                         else
3070                                 port->port.check = -1;
3071                 }
3072         }
3073 
3074         nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, bridge_vlan_check_cb, &data);
3075         nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, bridge_vlan_ack_cb, &data);
3076         nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, bridge_vlan_ack_cb, &data);
3077         nl_cb_err(cb, NL_CB_CUSTOM, bridge_vlan_error_cb, &data);
3078 
3079         if (nl_send_auto_complete(sock_rtnl, msg) < 0)
3080                 goto free;
3081 
3082         data.ret = 0;
3083         while (data.pending)
3084                 if (nl_recvmsgs(sock_rtnl, cb) < 0)
3085                         break;
3086 
3087         vlist_for_each_element(&dev->vlans, vlan, node) {
3088                 struct bridge_vlan_hotplug_port *port;
3089 
3090                 for (i = 0; i < vlan->n_ports; i++) {
3091                         if (!vlan->ports[i].check) {
3092                                 data.ret = 1;
3093                                 break;
3094                         }
3095                 }
3096 
3097                 list_for_each_entry(port, &vlan->hotplug_ports, list) {
3098                         if (!port->port.check) {
3099                                 data.ret = 1;
3100                                 break;
3101                         }
3102                 }
3103         }
3104 
3105 free:
3106         nlmsg_free(msg);
3107         nl_cb_put(cb);
3108         return data.ret;
3109 }
3110 
3111 int system_if_check(struct device *dev)
3112 {
3113         struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
3114         struct nl_msg *msg;
3115         struct ifinfomsg ifi = {
3116                 .ifi_family = AF_UNSPEC,
3117                 .ifi_index = 0,
3118         };
3119         struct if_check_data chk = {
3120                 .dev = dev,
3121                 .pending = 1,
3122         };
3123         int ret = 1;
3124 
3125         if (!cb)
3126                 return ret;
3127 
3128         msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
3129         if (!msg)
3130                 goto out;
3131 
3132         if (nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
3133             nla_put_string(msg, IFLA_IFNAME, dev->ifname))
3134                 goto free;
3135 
3136         nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
3137         nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
3138         nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
3139 
3140         ret = nl_send_auto_complete(sock_rtnl, msg);
3141         if (ret < 0)
3142                 goto free;
3143 
3144         while (chk.pending > 0)
3145                 if (nl_recvmsgs(sock_rtnl, cb) < 0)
3146                         break;
3147 
3148         ret = chk.pending;
3149 
3150 free:
3151         nlmsg_free(msg);
3152 out:
3153         nl_cb_put(cb);
3154         return ret;
3155 }
3156 
3157 struct device *
3158 system_if_get_parent(struct device *dev)
3159 {
3160         char buf[64], *devname;
3161         int ifindex, iflink;
3162 
3163         if (system_get_dev_sysfs("iflink", dev->ifname, buf, sizeof(buf)) < 0)
3164                 return NULL;
3165 
3166         iflink = strtoul(buf, NULL, 0);
3167         ifindex = system_if_resolve(dev);
3168         if (!iflink || iflink == ifindex)
3169                 return NULL;
3170 
3171         devname = if_indextoname(iflink, buf);
3172         if (!devname)
3173                 return NULL;
3174 
3175         return device_get(devname, true);
3176 }
3177 
3178 static bool
3179 read_string_file(int dir_fd, const char *file, char *buf, int size)
3180 {
3181         bool ret = false;
3182         char *c;
3183         int fd, len;
3184 
3185         fd = openat(dir_fd, file, O_RDONLY);
3186         if (fd < 0)
3187                 return false;
3188 
3189 retry:
3190         len = read(fd, buf, size - 1);
3191         if (len < 0) {
3192                 if (errno == EINTR)
3193                         goto retry;
3194         } else if (len > 0) {
3195                         buf[len] = 0;
3196 
3197                         c = strchr(buf, '\n');
3198                         if (c)
3199                                 *c = 0;
3200 
3201                         ret = true;
3202         }
3203 
3204         close(fd);
3205 
3206         return ret;
3207 }
3208 
3209 static bool
3210 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
3211 {
3212         char buf[64];
3213         bool ret = false;
3214 
3215         ret = read_string_file(dir_fd, file, buf, sizeof(buf));
3216         if (ret)
3217                 *val = strtoull(buf, NULL, 0);
3218 
3219         return ret;
3220 }
3221 
3222 bool
3223 system_if_force_external(const char *ifname)
3224 {
3225         struct stat s;
3226 
3227         return stat(dev_sysfs_path(ifname, "phy80211"), &s) == 0;
3228 }
3229 
3230 static const char *
3231 system_netdevtype_name(unsigned short dev_type)
3232 {
3233         size_t i;
3234 
3235         for (i = 0; i < ARRAY_SIZE(netdev_types); i++) {
3236                 if (netdev_types[i].id == dev_type)
3237                         return netdev_types[i].name;
3238         }
3239 
3240         /* the last key is used by default */
3241         i = ARRAY_SIZE(netdev_types) - 1;
3242 
3243         return netdev_types[i].name;
3244 }
3245 
3246 static void
3247 system_add_devtype(struct blob_buf *b, const char *ifname)
3248 {
3249         char buf[100];
3250         bool found = false;
3251 
3252         if (!system_get_dev_sysfs("uevent", ifname, buf, sizeof(buf))) {
3253                 const char *info = "DEVTYPE=";
3254                 char *context = NULL;
3255                 const char *line = strtok_r(buf, "\r\n", &context);
3256 
3257                 while (line != NULL) {
3258                         const char *index = strstr(line, info);
3259 
3260                         if (index != NULL) {
3261                                 blobmsg_add_string(b, "devtype", index + strlen(info));
3262                                 found = true;
3263                                 break;
3264                         }
3265 
3266                         line = strtok_r(NULL, "\r\n", &context);
3267                 }
3268         }
3269 
3270         if (!found) {
3271                 unsigned short number = 0;
3272                 const char *name = NULL;
3273 
3274                 if (!system_get_dev_sysfs("type", ifname, buf, sizeof(buf))) {
3275                         number = strtoul(buf, NULL, 0);
3276                         name = system_netdevtype_name(number);
3277                         blobmsg_add_string(b, "devtype", name);
3278                 }
3279         }
3280 }
3281 
3282 #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
3283 
3284 static int32_t
3285 ethtool_feature_count(const char *ifname)
3286 {
3287         struct {
3288                 struct ethtool_sset_info hdr;
3289                 uint32_t buf;
3290         } req = {
3291                 .hdr = {
3292                         .cmd = ETHTOOL_GSSET_INFO,
3293                         .sset_mask = 1 << ETH_SS_FEATURES
3294                 }
3295         };
3296 
3297         struct ifreq ifr = {
3298                 .ifr_data = (void *)&req
3299         };
3300 
3301         strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1);
3302 
3303         if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) != 0)
3304                 return -1;
3305 
3306         if (!req.hdr.sset_mask)
3307                 return 0;
3308 
3309         return req.buf;
3310 }
3311 
3312 static int32_t
3313 ethtool_feature_index(const char *ifname, const char *keyname)
3314 {
3315         struct ethtool_gstrings *feature_names;
3316         struct ifreq ifr = { 0 };
3317         int32_t n_features;
3318         uint32_t i;
3319 
3320         n_features = ethtool_feature_count(ifname);
3321 
3322         if (n_features <= 0)
3323                 return -1;
3324 
3325         feature_names = calloc(1, sizeof(*feature_names) + n_features * ETH_GSTRING_LEN);
3326 
3327         if (!feature_names)
3328                 return -1;
3329 
3330         feature_names->cmd = ETHTOOL_GSTRINGS;
3331         feature_names->string_set = ETH_SS_FEATURES;
3332         feature_names->len = n_features;
3333 
3334         strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1);
3335         ifr.ifr_data = (void *)feature_names;
3336 
3337         if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) != 0) {
3338                 free(feature_names);
3339 
3340                 return -1;
3341         }
3342 
3343         for (i = 0; i < feature_names->len; i++)
3344                 if (!strcmp((char *)&feature_names->data[i * ETH_GSTRING_LEN], keyname))
3345                         break;
3346 
3347         if (i >= feature_names->len)
3348                 i = -1;
3349 
3350         free(feature_names);
3351 
3352         return i;
3353 }
3354 
3355 static bool
3356 ethtool_feature_value(const char *ifname, const char *keyname)
3357 {
3358         struct ethtool_get_features_block *feature_block;
3359         struct ethtool_gfeatures *feature_values;
3360         struct ifreq ifr = { 0 };
3361         int32_t feature_idx;
3362         bool active;
3363 
3364         feature_idx = ethtool_feature_index(ifname, keyname);
3365 
3366         if (feature_idx < 0)
3367                 return false;
3368 
3369         feature_values = calloc(1,
3370                 sizeof(*feature_values) +
3371                 sizeof(feature_values->features[0]) * (feature_idx / 32 + 1));
3372 
3373         if (!feature_values)
3374                 return false;
3375 
3376         feature_values->cmd = ETHTOOL_GFEATURES;
3377         feature_values->size = feature_idx / 32 + 1;
3378 
3379         strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1);
3380         ifr.ifr_data = (void *)feature_values;
3381 
3382         if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) != 0) {
3383                 free(feature_values);
3384 
3385                 return false;
3386         }
3387 
3388         feature_block = &feature_values->features[feature_idx / 32];
3389         active = feature_block->active & (1U << feature_idx % 32);
3390 
3391         free(feature_values);
3392 
3393         return active;
3394 }
3395 
3396 static void
3397 system_add_link_mode_name(struct blob_buf *b, int i, bool half)
3398 {
3399         char *buf;
3400 
3401         /* allocate string buffer large enough for the mode name and a suffix
3402          * "-F" or "-H" indicating full duplex or half duplex.
3403          */
3404         buf = blobmsg_alloc_string_buffer(b, NULL, strlen(ethtool_modes[i].name) + 3);
3405         if (!buf)
3406                 return;
3407 
3408         strcpy(buf, ethtool_modes[i].name);
3409         if (half)
3410                 strcat(buf, "-H");
3411         else
3412                 strcat(buf, "-F");
3413 
3414         blobmsg_add_string_buffer(b);
3415 }
3416 
3417 static void
3418 system_add_link_modes(__s8 nwords, struct blob_buf *b, __u32 *mask)
3419 {
3420         size_t i;
3421 
3422         for (i = 0; i < ARRAY_SIZE(ethtool_modes); i++) {
3423                 if (ethtool_link_mode_test_bit(nwords, ethtool_modes[i].bit_half, mask))
3424                         system_add_link_mode_name(b, i, true);
3425 
3426                 if (ethtool_link_mode_test_bit(nwords, ethtool_modes[i].bit_full, mask))
3427                         system_add_link_mode_name(b, i, false);
3428         }
3429 }
3430 
3431 static void
3432 system_add_pause_modes(__s8 nwords, struct blob_buf *b, __u32 *mask)
3433 {
3434         if (ethtool_link_mode_test_bit(nwords, ETHTOOL_LINK_MODE_Pause_BIT, mask))
3435                 blobmsg_add_string(b, NULL, "pause");
3436 
3437         if (ethtool_link_mode_test_bit(nwords, ETHTOOL_LINK_MODE_Asym_Pause_BIT, mask))
3438                 blobmsg_add_string(b, NULL, "asym_pause");
3439 }
3440 
3441 
3442 static void
3443 system_add_ethtool_pause_an(struct blob_buf *b, __s8 nwords,
3444                             __u32 *advertising, __u32 *lp_advertising)
3445 {
3446         bool an_rx = false, an_tx = false;
3447         void *d;
3448 
3449         d = blobmsg_open_array(b, "negotiated");
3450 
3451         /* Work out negotiated pause frame usage per
3452          * IEEE 802.3-2005 table 28B-3.
3453          */
3454         if (ethtool_link_mode_test_bit(nwords,
3455                                        ETHTOOL_LINK_MODE_Pause_BIT,
3456                                        advertising) &&
3457             ethtool_link_mode_test_bit(nwords,
3458                                        ETHTOOL_LINK_MODE_Pause_BIT,
3459                                        lp_advertising)) {
3460                 an_tx = true;
3461                 an_rx = true;
3462         } else if (ethtool_link_mode_test_bit(nwords,
3463                                               ETHTOOL_LINK_MODE_Asym_Pause_BIT,
3464                                               advertising) &&
3465                    ethtool_link_mode_test_bit(nwords,
3466                                               ETHTOOL_LINK_MODE_Asym_Pause_BIT,
3467                                               lp_advertising)) {
3468                 if (ethtool_link_mode_test_bit(nwords,
3469                                                ETHTOOL_LINK_MODE_Pause_BIT,
3470                                                advertising))
3471                         an_rx = true;
3472                 else if (ethtool_link_mode_test_bit(nwords,
3473                                                     ETHTOOL_LINK_MODE_Pause_BIT,
3474                                                     lp_advertising))
3475                         an_tx = true;
3476         }
3477         if (an_rx)
3478                 blobmsg_add_string(b, NULL, "rx");
3479 
3480         if (an_tx)
3481                 blobmsg_add_string(b, NULL, "tx");
3482 
3483         blobmsg_close_array(b, d);
3484 }
3485 
3486 static void
3487 system_get_ethtool_pause(struct device *dev, bool *rx_pause, bool *tx_pause, bool *pause_autoneg)
3488 {
3489         struct ethtool_pauseparam pp;
3490         struct ifreq ifr = {
3491                 .ifr_data = (caddr_t)&pp,
3492         };
3493 
3494         strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
3495         memset(&pp, 0, sizeof(pp));
3496         pp.cmd = ETHTOOL_GPAUSEPARAM;
3497 
3498         /* may fail */
3499         if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == -1) {
3500                 *pause_autoneg = true;
3501                 return;
3502         }
3503 
3504         *rx_pause = pp.rx_pause;
3505         *tx_pause = pp.tx_pause;
3506         *pause_autoneg = pp.autoneg;
3507 }
3508 
3509 int
3510 system_if_dump_info(struct device *dev, struct blob_buf *b)
3511 {
3512         __u32 *supported, *advertising, *lp_advertising;
3513         bool rx_pause = false, tx_pause = false, pause_autoneg;
3514         struct {
3515                 struct ethtool_link_settings req;
3516                 __u32 link_mode_data[3 * 127];
3517         } ecmd;
3518         struct ifreq ifr = {
3519                 .ifr_data = (caddr_t)&ecmd,
3520         };
3521         __s8 nwords;
3522         void *c, *d;
3523         char *s;
3524 
3525         system_get_ethtool_pause(dev, &rx_pause, &tx_pause, &pause_autoneg);
3526 
3527         memset(&ecmd, 0, sizeof(ecmd));
3528         ecmd.req.cmd = ETHTOOL_GLINKSETTINGS;
3529         strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
3530 
3531         if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) < 0 ||
3532             ecmd.req.link_mode_masks_nwords >= 0 ||
3533             ecmd.req.cmd != ETHTOOL_GLINKSETTINGS)
3534                 return -EOPNOTSUPP;
3535 
3536         ecmd.req.link_mode_masks_nwords = -ecmd.req.link_mode_masks_nwords;
3537 
3538         if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) < 0 ||
3539             ecmd.req.link_mode_masks_nwords <= 0 ||
3540             ecmd.req.cmd != ETHTOOL_GLINKSETTINGS)
3541                 return -EIO;
3542 
3543         nwords = ecmd.req.link_mode_masks_nwords;
3544         supported = &ecmd.link_mode_data[0];
3545         advertising = &ecmd.link_mode_data[nwords];
3546         lp_advertising = &ecmd.link_mode_data[2 * nwords];
3547 
3548         c = blobmsg_open_array(b, "link-advertising");
3549         system_add_link_modes(nwords, b, advertising);
3550         blobmsg_close_array(b, c);
3551 
3552         c = blobmsg_open_array(b, "link-partner-advertising");
3553         system_add_link_modes(nwords, b, lp_advertising);
3554         blobmsg_close_array(b, c);
3555 
3556         c = blobmsg_open_array(b, "link-supported");
3557         system_add_link_modes(nwords, b, supported);
3558         blobmsg_close_array(b, c);
3559 
3560         if (ethtool_validate_speed(ecmd.req.speed) &&
3561             (ecmd.req.speed != (__u32)SPEED_UNKNOWN) &&
3562             (ecmd.req.speed != 0)) {
3563                 s = blobmsg_alloc_string_buffer(b, "speed", 10);
3564                 snprintf(s, 8, "%d%c", ecmd.req.speed,
3565                         ecmd.req.duplex == DUPLEX_HALF ? 'H' : 'F');
3566                 blobmsg_add_string_buffer(b);
3567         }
3568         blobmsg_add_u8(b, "autoneg", !!ecmd.req.autoneg);
3569 
3570         c = blobmsg_open_table(b, "flow-control");
3571         blobmsg_add_u8(b, "autoneg", pause_autoneg);
3572 
3573         d = blobmsg_open_array(b, "supported");
3574         system_add_pause_modes(nwords, b, supported);
3575         blobmsg_close_array(b, d);
3576 
3577         if (pause_autoneg) {
3578                 d = blobmsg_open_array(b, "link-advertising");
3579                 system_add_pause_modes(nwords, b, advertising);
3580                 blobmsg_close_array(b, d);
3581         }
3582 
3583         d = blobmsg_open_array(b, "link-partner-advertising");
3584         system_add_pause_modes(nwords, b, lp_advertising);
3585         blobmsg_close_array(b, d);
3586 
3587         if (pause_autoneg) {
3588                 system_add_ethtool_pause_an(b, nwords, advertising,
3589                                             lp_advertising);
3590         } else {
3591                 d = blobmsg_open_array(b, "selected");
3592                 if (rx_pause)
3593                         blobmsg_add_string(b, NULL, "rx");
3594 
3595                 if (tx_pause)
3596                         blobmsg_add_string(b, NULL, "tx");
3597 
3598                 blobmsg_close_array(b, d);
3599         }
3600 
3601         blobmsg_close_table(b, c);
3602 
3603         blobmsg_add_u8(b, "hw-tc-offload",
3604                 ethtool_feature_value(dev->ifname, "hw-tc-offload"));
3605 
3606         system_add_devtype(b, dev->ifname);
3607 
3608         /* Add PSE (PoE) status if available */
3609         {
3610                 struct pse_reply_data pse_data;
3611                 if (system_pse_get(dev, &pse_data) == 0) {
3612                         void *pse_tbl = blobmsg_open_table(b, "pse");
3613 
3614                         /* C33 (Clause 33 PoE) status */
3615                         if (pse_data.c33_admin_state) {
3616                                 const char *state = "unknown";
3617                                 switch (pse_data.c33_admin_state) {
3618                                 case ETHTOOL_C33_PSE_ADMIN_STATE_DISABLED:
3619                                         state = "disabled";
3620                                         break;
3621                                 case ETHTOOL_C33_PSE_ADMIN_STATE_ENABLED:
3622                                         state = "enabled";
3623                                         break;
3624                                 }
3625                                 blobmsg_add_string(b, "c33-admin-state", state);
3626                         }
3627 
3628                         if (pse_data.c33_pw_status) {
3629                                 const char *status = "unknown";
3630                                 switch (pse_data.c33_pw_status) {
3631                                 case ETHTOOL_C33_PSE_PW_D_STATUS_DISABLED:
3632                                         status = "disabled";
3633                                         break;
3634                                 case ETHTOOL_C33_PSE_PW_D_STATUS_SEARCHING:
3635                                         status = "searching";
3636                                         break;
3637                                 case ETHTOOL_C33_PSE_PW_D_STATUS_DELIVERING:
3638                                         status = "delivering";
3639                                         break;
3640                                 case ETHTOOL_C33_PSE_PW_D_STATUS_TEST:
3641                                         status = "test";
3642                                         break;
3643                                 case ETHTOOL_C33_PSE_PW_D_STATUS_FAULT:
3644                                         status = "fault";
3645                                         break;
3646                                 case ETHTOOL_C33_PSE_PW_D_STATUS_OTHERFAULT:
3647                                         status = "otherfault";
3648                                         break;
3649                                 }
3650                                 blobmsg_add_string(b, "c33-power-status", status);
3651                         }
3652 
3653                         if (pse_data.c33_pw_class)
3654                                 blobmsg_add_u32(b, "c33-power-class", pse_data.c33_pw_class);
3655 
3656                         if (pse_data.c33_actual_pw)
3657                                 blobmsg_add_u32(b, "c33-actual-power", pse_data.c33_actual_pw);
3658 
3659                         if (pse_data.c33_avail_pw_limit)
3660                                 blobmsg_add_u32(b, "c33-available-power-limit", pse_data.c33_avail_pw_limit);
3661 
3662                         /* PoDL (Power over Data Line) status */
3663                         if (pse_data.podl_admin_state) {
3664                                 const char *state = "unknown";
3665                                 switch (pse_data.podl_admin_state) {
3666                                 case ETHTOOL_PODL_PSE_ADMIN_STATE_DISABLED:
3667                                         state = "disabled";
3668                                         break;
3669                                 case ETHTOOL_PODL_PSE_ADMIN_STATE_ENABLED:
3670                                         state = "enabled";
3671                                         break;
3672                                 }
3673                                 blobmsg_add_string(b, "podl-admin-state", state);
3674                         }
3675 
3676                         if (pse_data.podl_pw_status) {
3677                                 const char *status = "unknown";
3678                                 switch (pse_data.podl_pw_status) {
3679                                 case ETHTOOL_PODL_PSE_PW_D_STATUS_DISABLED:
3680                                         status = "disabled";
3681                                         break;
3682                                 case ETHTOOL_PODL_PSE_PW_D_STATUS_SEARCHING:
3683                                         status = "searching";
3684                                         break;
3685                                 case ETHTOOL_PODL_PSE_PW_D_STATUS_DELIVERING:
3686                                         status = "delivering";
3687                                         break;
3688                                 case ETHTOOL_PODL_PSE_PW_D_STATUS_SLEEP:
3689                                         status = "sleep";
3690                                         break;
3691                                 case ETHTOOL_PODL_PSE_PW_D_STATUS_IDLE:
3692                                         status = "idle";
3693                                         break;
3694                                 case ETHTOOL_PODL_PSE_PW_D_STATUS_ERROR:
3695                                         status = "error";
3696                                         break;
3697                                 }
3698                                 blobmsg_add_string(b, "podl-power-status", status);
3699                         }
3700 
3701                         /* Priority settings */
3702                         if (pse_data.pse_prio_max)
3703                                 blobmsg_add_u32(b, "priority-max", pse_data.pse_prio_max);
3704 
3705                         if (pse_data.pse_prio)
3706                                 blobmsg_add_u32(b, "priority", pse_data.pse_prio);
3707 
3708                         blobmsg_close_table(b, pse_tbl);
3709                 }
3710         }
3711 
3712         return 0;
3713 }
3714 
3715 int
3716 system_if_dump_stats(struct device *dev, struct blob_buf *b)
3717 {
3718         const char *const counters[] = {
3719                 "collisions",     "rx_frame_errors",   "tx_compressed",
3720                 "multicast",      "rx_length_errors",  "tx_dropped",
3721                 "rx_bytes",       "rx_missed_errors",  "tx_errors",
3722                 "rx_compressed",  "rx_over_errors",    "tx_fifo_errors",
3723                 "rx_crc_errors",  "rx_packets",        "tx_heartbeat_errors",
3724                 "rx_dropped",     "tx_aborted_errors", "tx_packets",
3725                 "rx_errors",      "tx_bytes",          "tx_window_errors",
3726                 "rx_fifo_errors", "tx_carrier_errors",
3727         };
3728         int stats_dir;
3729         size_t i;
3730         uint64_t val = 0;
3731 
3732         stats_dir = open(dev_sysfs_path(dev->ifname, "statistics"), O_DIRECTORY);
3733         if (stats_dir < 0)
3734                 return -1;
3735 
3736         for (i = 0; i < ARRAY_SIZE(counters); i++)
3737                 if (read_uint64_file(stats_dir, counters[i], &val))
3738                         blobmsg_add_u64(b, counters[i], val);
3739 
3740         close(stats_dir);
3741         return 0;
3742 }
3743 
3744 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
3745 {
3746         bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
3747         int alen = v4 ? 4 : 16;
3748         unsigned int flags = 0;
3749         struct ifaddrmsg ifa = {
3750                 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
3751                 .ifa_prefixlen = addr->mask,
3752                 .ifa_index = dev->ifindex,
3753         };
3754 
3755         struct nl_msg *msg;
3756         if (cmd == RTM_NEWADDR)
3757                 flags |= NLM_F_CREATE | NLM_F_REPLACE;
3758 
3759         msg = nlmsg_alloc_simple(cmd, flags);
3760         if (!msg)
3761                 return -1;
3762 
3763         nlmsg_append(msg, &ifa, sizeof(ifa), 0);
3764         nla_put(msg, IFA_LOCAL, alen, &addr->addr);
3765         if (v4) {
3766                 if (addr->broadcast)
3767                         nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
3768                 if (addr->point_to_point)
3769                         nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
3770         } else {
3771                 time_t now = system_get_rtime();
3772                 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
3773 
3774                 if (addr->preferred_until) {
3775                         int64_t preferred = addr->preferred_until - now;
3776                         if (preferred < 0)
3777                                 preferred = 0;
3778                         else if (preferred > UINT32_MAX)
3779                                 preferred = UINT32_MAX;
3780 
3781                         cinfo.ifa_prefered = preferred;
3782                 }
3783 
3784                 if (addr->valid_until) {
3785                         int64_t valid = addr->valid_until - now;
3786                         if (valid <= 0) {
3787                                 nlmsg_free(msg);
3788                                 return -1;
3789                         }
3790                         else if (valid > UINT32_MAX)
3791                                 valid = UINT32_MAX;
3792 
3793                         cinfo.ifa_valid = valid;
3794                 }
3795 
3796                 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
3797 
3798                 if (cmd == RTM_NEWADDR && (addr->flags & DEVADDR_OFFLINK) &&
3799                     !system_if_is_point_to_point(dev))
3800                         nla_put_u32(msg, IFA_FLAGS, IFA_F_NOPREFIXROUTE);
3801         }
3802 
3803         return system_rtnl_call(msg);
3804 }
3805 
3806 int system_add_address(struct device *dev, struct device_addr *addr)
3807 {
3808         return system_addr(dev, addr, RTM_NEWADDR);
3809 }
3810 
3811 int system_del_address(struct device *dev, struct device_addr *addr)
3812 {
3813         return system_addr(dev, addr, RTM_DELADDR);
3814 }
3815 
3816 static int system_neigh(struct device *dev, struct device_neighbor *neighbor, int cmd)
3817 {
3818         int alen = ((neighbor->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
3819         unsigned int flags = 0;
3820         struct ndmsg ndm = {
3821                 .ndm_family = (alen == 4) ? AF_INET : AF_INET6,
3822                 .ndm_ifindex = dev->ifindex,
3823                 .ndm_state = NUD_PERMANENT,
3824                 .ndm_flags = (neighbor->proxy ? NTF_PROXY : 0) | (neighbor->router ? NTF_ROUTER : 0),
3825         };
3826         struct nl_msg *msg;
3827 
3828         if (cmd == RTM_NEWNEIGH)
3829                 flags |= NLM_F_CREATE | NLM_F_REPLACE;
3830 
3831         msg = nlmsg_alloc_simple(cmd, flags);
3832 
3833         if (!msg)
3834                 return -1;
3835 
3836         nlmsg_append(msg, &ndm, sizeof(ndm), 0);
3837 
3838         nla_put(msg, NDA_DST, alen, &neighbor->addr);
3839         if (neighbor->flags & DEVNEIGH_MAC)
3840                 nla_put(msg, NDA_LLADDR, sizeof(neighbor->macaddr), &neighbor->macaddr);
3841 
3842 
3843         return system_rtnl_call(msg);
3844 }
3845 
3846 int system_add_neighbor(struct device *dev, struct device_neighbor *neighbor)
3847 {
3848         return system_neigh(dev, neighbor, RTM_NEWNEIGH);
3849 }
3850 
3851 int system_del_neighbor(struct device *dev, struct device_neighbor *neighbor)
3852 {
3853         return system_neigh(dev, neighbor, RTM_DELNEIGH);
3854 }
3855 
3856 static int system_rt(struct device *dev, struct device_route *route, int cmd)
3857 {
3858         int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
3859         bool have_gw;
3860         unsigned int flags = 0;
3861 
3862         if (alen == 4)
3863                 have_gw = !!route->nexthop.in.s_addr;
3864         else
3865                 have_gw = route->nexthop.in6.s6_addr32[0] ||
3866                         route->nexthop.in6.s6_addr32[1] ||
3867                         route->nexthop.in6.s6_addr32[2] ||
3868                         route->nexthop.in6.s6_addr32[3];
3869 
3870         unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
3871                         ? route->table : RT_TABLE_MAIN;
3872 
3873         struct rtmsg rtm = {
3874                 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
3875                 .rtm_dst_len = route->mask,
3876                 .rtm_src_len = route->sourcemask,
3877                 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
3878                 .rtm_protocol = (route->flags & DEVROUTE_PROTO) ? route->proto : RTPROT_STATIC,
3879                 .rtm_scope = RT_SCOPE_NOWHERE,
3880                 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
3881                 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
3882         };
3883         struct nl_msg *msg;
3884 
3885         if (cmd == RTM_NEWROUTE) {
3886                 flags |= NLM_F_CREATE | NLM_F_REPLACE;
3887 
3888                 if (!dev) { /* Add null-route */
3889                         rtm.rtm_scope = RT_SCOPE_UNIVERSE;
3890                         rtm.rtm_type = RTN_UNREACHABLE;
3891                 }
3892                 else
3893                         rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
3894         }
3895 
3896         if (route->flags & DEVROUTE_TYPE) {
3897                 rtm.rtm_type = route->type;
3898                 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
3899                         if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
3900                             rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
3901                                 rtm.rtm_table = RT_TABLE_LOCAL;
3902                 }
3903 
3904                 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT) {
3905                         rtm.rtm_scope = RT_SCOPE_HOST;
3906                 } else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
3907                                 rtm.rtm_type == RTN_ANYCAST) {
3908                         rtm.rtm_scope = RT_SCOPE_LINK;
3909                 } else if (rtm.rtm_type == RTN_BLACKHOLE || rtm.rtm_type == RTN_UNREACHABLE ||
3910                                 rtm.rtm_type == RTN_PROHIBIT || rtm.rtm_type == RTN_FAILED_POLICY ||
3911                                 rtm.rtm_type == RTN_THROW) {
3912                         rtm.rtm_scope = RT_SCOPE_UNIVERSE;
3913                         dev = NULL;
3914                 }
3915         }
3916 
3917         if (route->flags & DEVROUTE_NODEV)
3918                 dev = NULL;
3919 
3920         msg = nlmsg_alloc_simple(cmd, flags);
3921         if (!msg)
3922                 return -1;
3923 
3924         nlmsg_append(msg, &rtm, sizeof(rtm), 0);
3925 
3926         if (route->mask)
3927                 nla_put(msg, RTA_DST, alen, &route->addr);
3928 
3929         if (route->sourcemask) {
3930                 if (rtm.rtm_family == AF_INET)
3931                         nla_put(msg, RTA_PREFSRC, alen, &route->source);
3932                 else
3933                         nla_put(msg, RTA_SRC, alen, &route->source);
3934         }
3935 
3936         if (route->metric > 0)
3937                 nla_put_u32(msg, RTA_PRIORITY, route->metric);
3938 
3939         if (have_gw)
3940                 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
3941 
3942         if (dev)
3943                 nla_put_u32(msg, RTA_OIF, dev->ifindex);
3944 
3945         if (table >= 256)
3946                 nla_put_u32(msg, RTA_TABLE, table);
3947 
3948         if (route->flags & DEVROUTE_MTU) {
3949                 struct nlattr *metrics;
3950 
3951                 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
3952                         goto nla_put_failure;
3953 
3954                 nla_put_u32(msg, RTAX_MTU, route->mtu);
3955 
3956                 nla_nest_end(msg, metrics);
3957         }
3958 
3959         return system_rtnl_call(msg);
3960 
3961 nla_put_failure:
3962         nlmsg_free(msg);
3963         return -ENOMEM;
3964 }
3965 
3966 int system_add_route(struct device *dev, struct device_route *route)
3967 {
3968         return system_rt(dev, route, RTM_NEWROUTE);
3969 }
3970 
3971 int system_del_route(struct device *dev, struct device_route *route)
3972 {
3973         return system_rt(dev, route, RTM_DELROUTE);
3974 }
3975 
3976 int system_flush_routes(void)
3977 {
3978         const char *names[] = { "ipv4", "ipv6" };
3979         size_t i;
3980         int fd;
3981 
3982         for (i = 0; i < ARRAY_SIZE(names); i++) {
3983                 snprintf(dev_buf, sizeof(dev_buf), "%s/sys/net/%s/route/flush", proc_path, names[i]);
3984                 fd = open(dev_buf, O_WRONLY);
3985                 if (fd < 0)
3986                         continue;
3987 
3988                 if (write(fd, "-1", 2)) {}
3989                 close(fd);
3990         }
3991         return 0;
3992 }
3993 
3994 bool system_resolve_rt_type(const char *type, unsigned int *id)
3995 {
3996         return system_rtn_aton(type, id);
3997 }
3998 
3999 bool system_resolve_rt_proto(const char *type, unsigned int *id)
4000 {
4001         FILE *f;
4002         char *e, buf[128];
4003         unsigned int n, proto = 256;
4004         n = strtoul(type, &e, 0);
4005         if (!*e && e != type)
4006                 proto = n;
4007         else if (!strcmp(type, "unspec"))
4008                 proto = RTPROT_UNSPEC;
4009         else if (!strcmp(type, "kernel"))
4010                 proto = RTPROT_KERNEL;
4011         else if (!strcmp(type, "boot"))
4012                 proto = RTPROT_BOOT;
4013         else if (!strcmp(type, "static"))
4014                 proto = RTPROT_STATIC;
4015         else if ((f = fopen("/etc/iproute2/rt_protos", "r")) != NULL) {
4016                 while (fgets(buf, sizeof(buf) - 1, f) != NULL) {
4017                         if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
4018                                 continue;
4019 
4020                         n = strtoul(e, NULL, 10);
4021                         e = strtok(NULL, " \t\n");
4022 
4023                         if (e && !strcmp(e, type)) {
4024                                 proto = n;
4025                                 break;
4026                         }
4027                 }
4028                 fclose(f);
4029         }
4030 
4031         if (proto > 255)
4032                 return false;
4033 
4034         *id = proto;
4035         return true;
4036 }
4037 
4038 bool system_resolve_rt_table(const char *name, unsigned int *id)
4039 {
4040         FILE *f;
4041         char *e, buf[128];
4042         unsigned int n, table = RT_TABLE_UNSPEC;
4043 
4044         /* first try to parse table as number */
4045         if ((n = strtoul(name, &e, 0)) > 0 && !*e)
4046                 table = n;
4047 
4048         /* handle well known aliases */
4049         else if (!strcmp(name, "default"))
4050                 table = RT_TABLE_DEFAULT;
4051         else if (!strcmp(name, "main"))
4052                 table = RT_TABLE_MAIN;
4053         else if (!strcmp(name, "local"))
4054                 table = RT_TABLE_LOCAL;
4055 
4056         /* try to look up name in /etc/iproute2/rt_tables */
4057         else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
4058         {
4059                 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
4060                 {
4061                         if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
4062                                 continue;
4063 
4064                         n = strtoul(e, NULL, 10);
4065                         e = strtok(NULL, " \t\n");
4066 
4067                         if (e && !strcmp(e, name))
4068                         {
4069                                 table = n;
4070                                 break;
4071                         }
4072                 }
4073 
4074                 fclose(f);
4075         }
4076 
4077         if (table == RT_TABLE_UNSPEC)
4078                 return false;
4079 
4080         *id = table;
4081         return true;
4082 }
4083 
4084 bool system_is_default_rt_table(unsigned int id)
4085 {
4086         return (id == RT_TABLE_MAIN);
4087 }
4088 
4089 bool system_resolve_rpfilter(const char *filter, unsigned int *id)
4090 {
4091         char *e;
4092         unsigned int n;
4093 
4094         if (!strcmp(filter, "strict"))
4095                 n = 1;
4096         else if (!strcmp(filter, "loose"))
4097                 n = 2;
4098         else {
4099                 n = strtoul(filter, &e, 0);
4100                 if (*e || e == filter || n > 2)
4101                         return false;
4102         }
4103 
4104         *id = n;
4105         return true;
4106 }
4107 
4108 static int system_iprule(struct iprule *rule, int cmd)
4109 {
4110         int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
4111 
4112         struct nl_msg *msg;
4113         struct rtmsg rtm = {
4114                 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
4115                 .rtm_protocol = RTPROT_STATIC,
4116                 .rtm_scope = RT_SCOPE_UNIVERSE,
4117                 .rtm_table = RT_TABLE_UNSPEC,
4118                 .rtm_type = RTN_UNSPEC,
4119                 .rtm_flags = 0,
4120         };
4121 
4122         if (cmd == RTM_NEWRULE)
4123                 rtm.rtm_type = RTN_UNICAST;
4124 
4125         if (rule->invert)
4126                 rtm.rtm_flags |= FIB_RULE_INVERT;
4127 
4128         if (rule->flags & IPRULE_SRC)
4129                 rtm.rtm_src_len = rule->src_mask;
4130 
4131         if (rule->flags & IPRULE_DEST)
4132                 rtm.rtm_dst_len = rule->dest_mask;
4133 
4134         if (rule->flags & IPRULE_TOS)
4135                 rtm.rtm_tos = rule->tos;
4136 
4137         if (rule->flags & IPRULE_LOOKUP) {
4138                 if (rule->lookup < 256)
4139                         rtm.rtm_table = rule->lookup;
4140         }
4141 
4142         if (rule->flags & IPRULE_ACTION)
4143                 rtm.rtm_type = rule->action;
4144         else if (rule->flags & IPRULE_GOTO)
4145                 rtm.rtm_type = FR_ACT_GOTO;
4146         else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
4147                 rtm.rtm_type = FR_ACT_NOP;
4148 
4149         msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
4150 
4151         if (!msg)
4152                 return -1;
4153 
4154         nlmsg_append(msg, &rtm, sizeof(rtm), 0);
4155 
4156         if (rule->flags & IPRULE_IN)
4157                 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
4158 
4159         if (rule->flags & IPRULE_OUT)
4160                 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
4161 
4162         if (rule->flags & IPRULE_SRC)
4163                 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
4164 
4165         if (rule->flags & IPRULE_DEST)
4166                 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
4167 
4168         if (rule->flags & IPRULE_PRIORITY)
4169                 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
4170         else
4171                 nla_put_u32(msg, FRA_PRIORITY, rule->order);
4172 
4173         if (rule->flags & IPRULE_FWMARK)
4174                 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
4175 
4176         if (rule->flags & IPRULE_FWMASK)
4177                 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
4178 
4179         if (rule->flags & IPRULE_LOOKUP) {
4180                 if (rule->lookup >= 256)
4181                         nla_put_u32(msg, FRA_TABLE, rule->lookup);
4182         }
4183 
4184         if (rule->flags & IPRULE_SUP_PREFIXLEN)
4185                 nla_put_u32(msg, FRA_SUPPRESS_PREFIXLEN, rule->sup_prefixlen);
4186 
4187         if (rule->flags & IPRULE_UIDRANGE) {
4188                 struct fib_rule_uid_range uidrange = {
4189                         .start = rule->uidrange_start,
4190                         .end = rule->uidrange_end
4191                 };
4192 
4193                 nla_put(msg, FRA_UID_RANGE, sizeof(uidrange), &uidrange);
4194         }
4195 
4196         if (rule->flags & IPRULE_GOTO)
4197                 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
4198 
4199         if (rule->flags & IPRULE_IPPROTO)
4200                 nla_put_u8(msg, FRA_IP_PROTO, rule->ipproto);
4201 
4202         if (rule->flags & IPRULE_SPORT) {
4203                 struct fib_rule_port_range sportrange = {
4204                         .start = rule->sport_start,
4205                         .end = rule->sport_end
4206                 };
4207 
4208                 nla_put(msg, FRA_SPORT_RANGE, sizeof(sportrange), &sportrange);
4209         }
4210 
4211         if (rule->flags & IPRULE_DPORT) {
4212                 struct fib_rule_port_range dportrange = {
4213                         .start = rule->dport_start,
4214                         .end = rule->dport_end
4215                 };
4216 
4217                 nla_put(msg, FRA_DPORT_RANGE, sizeof(dportrange), &dportrange);
4218         }
4219 
4220         return system_rtnl_call(msg);
4221 }
4222 
4223 int system_add_iprule(struct iprule *rule)
4224 {
4225         return system_iprule(rule, RTM_NEWRULE);
4226 }
4227 
4228 int system_del_iprule(struct iprule *rule)
4229 {
4230         return system_iprule(rule, RTM_DELRULE);
4231 }
4232 
4233 int system_flush_iprules(void)
4234 {
4235         int rv = 0;
4236         struct iprule rule;
4237 
4238         system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
4239         system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
4240 
4241         memset(&rule, 0, sizeof(rule));
4242 
4243 
4244         rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
4245 
4246         rule.priority = 0;
4247         rule.lookup = RT_TABLE_LOCAL;
4248         rv |= system_iprule(&rule, RTM_NEWRULE);
4249 
4250         rule.priority = 32766;
4251         rule.lookup = RT_TABLE_MAIN;
4252         rv |= system_iprule(&rule, RTM_NEWRULE);
4253 
4254         rule.priority = 32767;
4255         rule.lookup = RT_TABLE_DEFAULT;
4256         rv |= system_iprule(&rule, RTM_NEWRULE);
4257 
4258 
4259         rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
4260 
4261         rule.priority = 0;
4262         rule.lookup = RT_TABLE_LOCAL;
4263         rv |= system_iprule(&rule, RTM_NEWRULE);
4264 
4265         rule.priority = 32766;
4266         rule.lookup = RT_TABLE_MAIN;
4267         rv |= system_iprule(&rule, RTM_NEWRULE);
4268 
4269         return rv;
4270 }
4271 
4272 bool system_resolve_iprule_action(const char *action, unsigned int *id)
4273 {
4274         return system_rtn_aton(action, id);
4275 }
4276 
4277 bool system_resolve_iprule_ipproto(const char *name, unsigned int *id)
4278 {
4279         char *e;
4280         struct protoent *ent;
4281         unsigned int n, ipproto = 0;
4282 
4283         if ((n = strtoul(name, &e, 0)) > 0 && *e == '\0')
4284                 ipproto = n;
4285         else {
4286                 ent = getprotobyname(name);
4287 
4288                 if (ent)
4289                         ipproto = ent->p_proto;
4290                 else
4291                         return false;
4292         }
4293 
4294         *id = ipproto;
4295         return true;
4296 }
4297 
4298 time_t system_get_rtime(void)
4299 {
4300         struct timespec ts;
4301         struct timeval tv;
4302 
4303         if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
4304                 return ts.tv_sec;
4305 
4306         if (gettimeofday(&tv, NULL) == 0)
4307                 return tv.tv_sec;
4308 
4309         return 0;
4310 }
4311 
4312 #ifndef IP_DF
4313 #define IP_DF       0x4000
4314 #endif
4315 
4316 static int tunnel_ioctl(const char *name, int cmd, void *p)
4317 {
4318         struct ifreq ifr;
4319 
4320         memset(&ifr, 0, sizeof(ifr));
4321         strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name) - 1);
4322         ifr.ifr_ifru.ifru_data = p;
4323         return ioctl(sock_ioctl, cmd, &ifr);
4324 }
4325 
4326 #ifdef IFLA_IPTUN_MAX
4327 static int system_add_ip6_tunnel(const char *name, const unsigned int link,
4328                                  struct blob_attr **tb)
4329 {
4330         struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
4331                                 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
4332         struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
4333         struct blob_attr *cur;
4334         int ret = 0, ttl = 0;
4335 
4336         if (!nlm)
4337                 return -1;
4338 
4339         nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
4340         nla_put_string(nlm, IFLA_IFNAME, name);
4341 
4342         if (link)
4343                 nla_put_u32(nlm, IFLA_LINK, link);
4344 
4345         struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
4346         if (!linkinfo) {
4347                 ret = -ENOMEM;
4348                 goto failure;
4349         }
4350 
4351         nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
4352         struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
4353         if (!infodata) {
4354                 ret = -ENOMEM;
4355                 goto failure;
4356         }
4357 
4358         if (link)
4359                 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
4360 
4361         if ((cur = tb[TUNNEL_ATTR_TTL]))
4362                 ttl = blobmsg_get_u32(cur);
4363 
4364         nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
4365         nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
4366 
4367         struct in6_addr in6buf;
4368         if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
4369                 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
4370                         ret = -EINVAL;
4371                         goto failure;
4372                 }
4373                 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
4374         }
4375 
4376         if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
4377                 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
4378                         ret = -EINVAL;
4379                         goto failure;
4380                 }
4381                 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
4382         }
4383 
4384         if ((cur = tb[TUNNEL_ATTR_DATA])) {
4385                 struct blob_attr *tb_data[__IPIP6_DATA_ATTR_MAX];
4386                 uint32_t tun_flags = IP6_TNL_F_IGN_ENCAP_LIMIT;
4387 
4388                 blobmsg_parse_attr(ipip6_data_attr_list.params, __IPIP6_DATA_ATTR_MAX,
4389                                    tb_data, cur);
4390 
4391                 if ((cur = tb_data[IPIP6_DATA_ENCAPLIMIT])) {
4392                         char *str = blobmsg_get_string(cur);
4393 
4394                         if (strcmp(str, "ignore")) {
4395                                 char *e;
4396                                 unsigned encap_limit = strtoul(str, &e, 0);
4397 
4398                                 if (e == str || *e || encap_limit > 255) {
4399                                         ret = -EINVAL;
4400                                         goto failure;
4401                                 }
4402 
4403                                 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, encap_limit);
4404                                 tun_flags &= ~IP6_TNL_F_IGN_ENCAP_LIMIT;
4405                         }
4406                 }
4407 
4408 #ifdef IFLA_IPTUN_FMR_MAX
4409                 if ((cur = tb_data[IPIP6_DATA_FMRS])) {
4410                         struct blob_attr *rcur;
4411                         unsigned rrem, fmrcnt = 0;
4412                         struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
4413 
4414                         if (!fmrs) {
4415                                 ret = -ENOMEM;
4416                                 goto failure;
4417                         }
4418 
4419                         blobmsg_for_each_attr(rcur, cur, rrem) {
4420                                 struct blob_attr *tb_fmr[__FMR_DATA_ATTR_MAX], *tb_cur;
4421                                 struct in6_addr ip6prefix;
4422                                 struct in_addr ip4prefix;
4423                                 unsigned ip4len = 32, ip6len = 128, ealen, offset;
4424 
4425                                 blobmsg_parse_attr(fmr_data_attr_list.params, __FMR_DATA_ATTR_MAX,
4426                                                    tb_fmr, rcur);
4427 
4428                                 if (!(tb_cur = tb_fmr[FMR_DATA_PREFIX6]) ||
4429                                                 !parse_ip_and_netmask(AF_INET6,
4430                                                         blobmsg_data(tb_cur), &ip6prefix,
4431                                                         &ip6len)) {
4432                                         ret = -EINVAL;
4433                                         goto failure;
4434                                 }
4435 
4436                                 if (!(tb_cur = tb_fmr[FMR_DATA_PREFIX4]) ||
4437                                                 !parse_ip_and_netmask(AF_INET,
4438                                                         blobmsg_data(tb_cur), &ip4prefix,
4439                                                         &ip4len)) {
4440                                         ret = -EINVAL;
4441                                         goto failure;
4442                                 }
4443 
4444                                 if (!(tb_cur = tb_fmr[FMR_DATA_EALEN])) {
4445                                         ret = -EINVAL;
4446                                         goto failure;
4447                                 }
4448                                 ealen = blobmsg_get_u32(tb_cur);
4449                                 if (ealen > 255) {
4450                                         ret = -EINVAL;
4451                                         goto failure;
4452                                 }
4453 
4454                                 if (!(tb_cur = tb_fmr[FMR_DATA_OFFSET])) {
4455                                         ret = -EINVAL;
4456                                         goto failure;
4457                                 }
4458                                 offset = blobmsg_get_u32(tb_cur);
4459                                 if (offset > 255) {
4460                                         ret = -EINVAL;
4461                                         goto failure;
4462                                 }
4463 
4464                                 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
4465                                 if (!rule) {
4466                                         ret = -ENOMEM;
4467                                         goto failure;
4468                                 }
4469 
4470                                 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
4471                                 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
4472                                 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
4473                                 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
4474                                 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
4475                                 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
4476 
4477                                 nla_nest_end(nlm, rule);
4478                         }
4479 
4480                         nla_nest_end(nlm, fmrs);
4481                 }
4482 #endif
4483                 if (tun_flags)
4484                         nla_put_u32(nlm, IFLA_IPTUN_FLAGS, tun_flags);
4485         }
4486 
4487         nla_nest_end(nlm, infodata);
4488         nla_nest_end(nlm, linkinfo);
4489 
4490         return system_rtnl_call(nlm);
4491 
4492 failure:
4493         nlmsg_free(nlm);
4494         return ret;
4495 }
4496 #endif
4497 
4498 #ifdef IFLA_IPTUN_MAX
4499 #define IP6_FLOWINFO_TCLASS     htonl(0x0FF00000)
4500 static int system_add_gre_tunnel(const char *name, const char *kind,
4501                                  const unsigned int link, struct blob_attr **tb, bool v6)
4502 {
4503         struct nl_msg *nlm;
4504         struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
4505         struct blob_attr *cur;
4506         uint32_t ikey = 0, okey = 0, flowinfo = 0, flags6 = IP6_TNL_F_IGN_ENCAP_LIMIT;
4507         uint16_t iflags = 0, oflags = 0;
4508         uint8_t tos = 0;
4509         int ret = 0, ttl = 0;
4510         unsigned encap_limit = 0;
4511 
4512         nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
4513         if (!nlm)
4514                 return -1;
4515 
4516         nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
4517         nla_put_string(nlm, IFLA_IFNAME, name);
4518 
4519         struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
4520         if (!linkinfo) {
4521                 ret = -ENOMEM;
4522                 goto failure;
4523         }
4524 
4525         nla_put_string(nlm, IFLA_INFO_KIND, kind);
4526         struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
4527         if (!infodata) {
4528                 ret = -ENOMEM;
4529                 goto failure;
4530         }
4531 
4532         if (link)
4533                 nla_put_u32(nlm, IFLA_GRE_LINK, link);
4534 
4535         if ((cur = tb[TUNNEL_ATTR_TTL]))
4536                 ttl = blobmsg_get_u32(cur);
4537 
4538         if ((cur = tb[TUNNEL_ATTR_TOS])) {
4539                 char *str = blobmsg_get_string(cur);
4540                 if (strcmp(str, "inherit")) {
4541                         unsigned uval;
4542 
4543                         if (!system_tos_aton(str, &uval)) {
4544                                 ret = -EINVAL;
4545                                 goto failure;
4546                         }
4547 
4548                         if (v6)
4549                                 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
4550                         else
4551                                 tos = uval;
4552                 } else {
4553                         if (v6)
4554                                 flags6 |= IP6_TNL_F_USE_ORIG_TCLASS;
4555                         else
4556                                 tos = 1;
4557                 }
4558         }
4559 
4560         if ((cur = tb[TUNNEL_ATTR_DATA])) {
4561                 struct blob_attr *tb_data[__GRE_DATA_ATTR_MAX];
4562 
4563                 blobmsg_parse_attr(gre_data_attr_list.params, __GRE_DATA_ATTR_MAX,
4564                                    tb_data, cur);
4565 
4566                 if ((cur = tb_data[GRE_DATA_IKEY])) {
4567                         if ((ikey = blobmsg_get_u32(cur)))
4568                                 iflags |= GRE_KEY;
4569                 }
4570 
4571                 if ((cur = tb_data[GRE_DATA_OKEY])) {
4572                         if ((okey = blobmsg_get_u32(cur)))
4573                                 oflags |= GRE_KEY;
4574                 }
4575 
4576                 if ((cur = tb_data[GRE_DATA_ICSUM])) {
4577                         if (blobmsg_get_bool(cur))
4578                                 iflags |= GRE_CSUM;
4579                 }
4580 
4581                 if ((cur = tb_data[GRE_DATA_OCSUM])) {
4582                         if (blobmsg_get_bool(cur))
4583                                 oflags |= GRE_CSUM;
4584                 }
4585 
4586                 if ((cur = tb_data[GRE_DATA_ISEQNO])) {
4587                         if (blobmsg_get_bool(cur))
4588                                 iflags |= GRE_SEQ;
4589                 }
4590 
4591                 if ((cur = tb_data[GRE_DATA_OSEQNO])) {
4592                         if (blobmsg_get_bool(cur))
4593                                 oflags |= GRE_SEQ;
4594                 }
4595 
4596                 if ((cur = tb_data[GRE_DATA_ENCAPLIMIT])) {
4597                         char *str = blobmsg_get_string(cur);
4598 
4599                         if (strcmp(str, "ignore")) {
4600                                 char *e;
4601 
4602                                 encap_limit = strtoul(str, &e, 0);
4603 
4604                                 if (e == str || *e || encap_limit > 255) {
4605                                         ret = -EINVAL;
4606                                         goto failure;
4607                                 }
4608 
4609                                 flags6 &= ~IP6_TNL_F_IGN_ENCAP_LIMIT;
4610                         }
4611                 }
4612         }
4613 
4614         if (v6) {
4615                 struct in6_addr in6buf;
4616                 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
4617                         if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
4618                                 ret = -EINVAL;
4619                                 goto failure;
4620                         }
4621                         nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
4622                 }
4623 
4624                 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
4625                         if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
4626                                 ret = -EINVAL;
4627                                 goto failure;
4628                         }
4629                         nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
4630                 }
4631 
4632                 if (!(flags6 & IP6_TNL_F_IGN_ENCAP_LIMIT))
4633                         nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, encap_limit);
4634 
4635                 if (flowinfo)
4636                         nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
4637 
4638                 if (flags6)
4639                         nla_put_u32(nlm, IFLA_GRE_FLAGS, flags6);
4640 
4641                 if (!ttl)
4642                         ttl = 64;
4643         } else {
4644                 struct in_addr inbuf;
4645                 bool set_df = true;
4646 
4647                 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
4648                         if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
4649                                 ret = -EINVAL;
4650                                 goto failure;
4651                         }
4652                         nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
4653                 }
4654 
4655                 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
4656                         if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
4657                                 ret = -EINVAL;
4658                                 goto failure;
4659                         }
4660                         nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
4661 
4662                         if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
4663                                 /* okey/ikey are kept in host order and converted
4664                                  * via htonl() when added to the message */
4665                                 if (!okey) {
4666                                         okey = ntohl(inbuf.s_addr);
4667                                         oflags |= GRE_KEY;
4668                                 }
4669 
4670                                 if (!ikey) {
4671                                         ikey = ntohl(inbuf.s_addr);
4672                                         iflags |= GRE_KEY;
4673                                 }
4674                         }
4675                 }
4676 
4677                 if ((cur = tb[TUNNEL_ATTR_DF]))
4678                         set_df = blobmsg_get_bool(cur);
4679 
4680                 if (!set_df) {
4681                         /* ttl != 0 and nopmtudisc are incompatible */
4682                         if (ttl) {
4683                                 ret = -EINVAL;
4684                                 goto failure;
4685                         }
4686                 } else if (!ttl)
4687                         ttl = 64;
4688 
4689                 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
4690 
4691                 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
4692         }
4693 
4694         if (ttl)
4695                 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
4696 
4697         if (oflags)
4698                 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
4699 
4700         if (iflags)
4701                 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
4702 
4703         if (okey)
4704                 nla_put_u32(nlm, IFLA_GRE_OKEY, htonl(okey));
4705 
4706         if (ikey)
4707                 nla_put_u32(nlm, IFLA_GRE_IKEY, htonl(ikey));
4708 
4709         nla_nest_end(nlm, infodata);
4710         nla_nest_end(nlm, linkinfo);
4711 
4712         return system_rtnl_call(nlm);
4713 
4714 failure:
4715         nlmsg_free(nlm);
4716         return ret;
4717 }
4718 #endif
4719 
4720 #ifdef IFLA_VTI_MAX
4721 static int system_add_vti_tunnel(const char *name, const char *kind,
4722                                  const unsigned int link, struct blob_attr **tb, bool v6)
4723 {
4724         struct nl_msg *nlm;
4725         struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
4726         struct blob_attr *cur;
4727         int ret = 0;
4728 
4729         nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
4730         if (!nlm)
4731                 return -1;
4732 
4733         nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
4734         nla_put_string(nlm, IFLA_IFNAME, name);
4735 
4736         struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
4737         if (!linkinfo) {
4738                 ret = -ENOMEM;
4739                 goto failure;
4740         }
4741 
4742         nla_put_string(nlm, IFLA_INFO_KIND, kind);
4743         struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
4744         if (!infodata) {
4745                 ret = -ENOMEM;
4746                 goto failure;
4747         }
4748 
4749         if (link)
4750                 nla_put_u32(nlm, IFLA_VTI_LINK, link);
4751 
4752         if (v6) {
4753                 struct in6_addr in6buf;
4754                 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
4755                         if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
4756                                 ret = -EINVAL;
4757                                 goto failure;
4758                         }
4759                         nla_put(nlm, IFLA_VTI_LOCAL, sizeof(in6buf), &in6buf);
4760                 }
4761 
4762                 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
4763                         if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
4764                                 ret = -EINVAL;
4765                                 goto failure;
4766                         }
4767                         nla_put(nlm, IFLA_VTI_REMOTE, sizeof(in6buf), &in6buf);
4768                 }
4769 
4770         } else {
4771                 struct in_addr inbuf;
4772 
4773                 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
4774                         if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
4775                                 ret = -EINVAL;
4776                                 goto failure;
4777                         }
4778                         nla_put(nlm, IFLA_VTI_LOCAL, sizeof(inbuf), &inbuf);
4779                 }
4780 
4781                 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
4782                         if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
4783                                 ret = -EINVAL;
4784                                 goto failure;
4785                         }
4786                         nla_put(nlm, IFLA_VTI_REMOTE, sizeof(inbuf), &inbuf);
4787                 }
4788 
4789         }
4790 
4791         if ((cur = tb[TUNNEL_ATTR_DATA])) {
4792                 struct blob_attr *tb_data[__VTI_DATA_ATTR_MAX];
4793                 uint32_t ikey = 0, okey = 0;
4794 
4795                 blobmsg_parse_attr(vti_data_attr_list.params, __VTI_DATA_ATTR_MAX,
4796                                    tb_data, cur);
4797 
4798                 if ((cur = tb_data[VTI_DATA_IKEY])) {
4799                         if ((ikey = blobmsg_get_u32(cur)))
4800                                 nla_put_u32(nlm, IFLA_VTI_IKEY, htonl(ikey));
4801                 }
4802 
4803                 if ((cur = tb_data[VTI_DATA_OKEY])) {
4804                         if ((okey = blobmsg_get_u32(cur)))
4805                                 nla_put_u32(nlm, IFLA_VTI_OKEY, htonl(okey));
4806                 }
4807         }
4808 
4809         nla_nest_end(nlm, infodata);
4810         nla_nest_end(nlm, linkinfo);
4811 
4812         return system_rtnl_call(nlm);
4813 
4814 failure:
4815         nlmsg_free(nlm);
4816         return ret;
4817 }
4818 #endif
4819 
4820 #ifdef IFLA_XFRM_MAX
4821 static int system_add_xfrm_tunnel(const char *name, const char *kind,
4822                                  const unsigned int link, struct blob_attr **tb)
4823 {
4824         struct nl_msg *nlm;
4825         struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
4826         struct blob_attr *cur;
4827         int ret = 0;
4828 
4829         nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
4830         if (!nlm)
4831                 return -1;
4832 
4833         nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
4834         nla_put_string(nlm, IFLA_IFNAME, name);
4835 
4836         struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
4837         if (!linkinfo) {
4838                 ret = -ENOMEM;
4839                 goto failure;
4840         }
4841 
4842         nla_put_string(nlm, IFLA_INFO_KIND, kind);
4843         struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
4844         if (!infodata) {
4845                 ret = -ENOMEM;
4846                 goto failure;
4847         }
4848 
4849         if (link)
4850                 nla_put_u32(nlm, IFLA_XFRM_LINK, link);
4851 
4852         if ((cur = tb[TUNNEL_ATTR_DATA])) {
4853                 struct blob_attr *tb_data[__XFRM_DATA_ATTR_MAX];
4854                 uint32_t if_id = 0;
4855 
4856                 blobmsg_parse_attr(xfrm_data_attr_list.params, __XFRM_DATA_ATTR_MAX,
4857                                    tb_data, cur);
4858 
4859                 if ((cur = tb_data[XFRM_DATA_IF_ID])) {
4860                         if ((if_id = blobmsg_get_u32(cur)))
4861                                 nla_put_u32(nlm, IFLA_XFRM_IF_ID, if_id);
4862                 }
4863 
4864         }
4865 
4866         nla_nest_end(nlm, infodata);
4867         nla_nest_end(nlm, linkinfo);
4868 
4869         return system_rtnl_call(nlm);
4870 
4871 failure:
4872         nlmsg_free(nlm);
4873         return ret;
4874 }
4875 #endif
4876 
4877 #ifdef IFLA_VXLAN_MAX
4878 static void system_vxlan_map_bool_attr(struct nl_msg *msg, struct blob_attr **tb_data, int attrtype, int vxlandatatype, bool invert) {
4879         struct blob_attr *cur;
4880         if ((cur = tb_data[vxlandatatype])) {
4881                 bool val = blobmsg_get_bool(cur);
4882                 if (invert)
4883                         val = !val;
4884 
4885                 if (attrtype == IFLA_VXLAN_GBP) {
4886                         if (val)
4887                                 nla_put_flag(msg, attrtype);
4888                         return;
4889                 }
4890 
4891                 nla_put_u8(msg, attrtype, val);
4892         }
4893 }
4894 
4895 static int system_add_vxlan(const char *name, const unsigned int link, struct blob_attr **tb, bool v6)
4896 {
4897         struct blob_attr *tb_data[__VXLAN_DATA_ATTR_MAX];
4898         struct nl_msg *msg;
4899         struct nlattr *linkinfo, *data;
4900         struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
4901         struct blob_attr *cur;
4902         int ret = 0;
4903 
4904         if ((cur = tb[TUNNEL_ATTR_DATA]))
4905                 blobmsg_parse_attr(vxlan_data_attr_list.params, __VXLAN_DATA_ATTR_MAX,
4906                                    tb_data, cur);
4907         else
4908                 return -EINVAL;
4909 
4910         msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
4911 
4912         if (!msg)
4913                 return -1;
4914 
4915         nlmsg_append(msg, &iim, sizeof(iim), 0);
4916 
4917         nla_put_string(msg, IFLA_IFNAME, name);
4918 
4919         if ((cur = tb_data[VXLAN_DATA_ATTR_MACADDR])) {
4920                 struct ether_addr *ea = ether_aton(blobmsg_get_string(cur));
4921                 if (!ea) {
4922                         ret = -EINVAL;
4923                         goto failure;
4924                 }
4925 
4926                 nla_put(msg, IFLA_ADDRESS, ETH_ALEN, ea);
4927         }
4928 
4929         if ((cur = tb[TUNNEL_ATTR_MTU])) {
4930                 uint32_t mtu = blobmsg_get_u32(cur);
4931                 nla_put_u32(msg, IFLA_MTU, mtu);
4932         }
4933 
4934         if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO))) {
4935                 ret = -ENOMEM;
4936                 goto failure;
4937         }
4938 
4939         nla_put_string(msg, IFLA_INFO_KIND, "vxlan");
4940 
4941         if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) {
4942                 ret = -ENOMEM;
4943                 goto failure;
4944         }
4945 
4946         if (link)
4947                 nla_put_u32(msg, IFLA_VXLAN_LINK, link);
4948 
4949         if ((cur = tb_data[VXLAN_DATA_ATTR_ID])) {
4950                 uint32_t id = blobmsg_get_u32(cur);
4951                 if (id >= (1u << 24)) {
4952                         ret = -EINVAL;
4953                         goto failure;
4954                 }
4955 
4956                 nla_put_u32(msg, IFLA_VXLAN_ID, id);
4957         }
4958 
4959         if (v6) {
4960                 struct in6_addr in6buf;
4961                 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
4962                         if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
4963                                 ret = -EINVAL;
4964                                 goto failure;
4965                         }
4966                         nla_put(msg, IFLA_VXLAN_LOCAL6, sizeof(in6buf), &in6buf);
4967                 }
4968 
4969                 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
4970                         if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
4971                                 ret = -EINVAL;
4972                                 goto failure;
4973                         }
4974                         nla_put(msg, IFLA_VXLAN_GROUP6, sizeof(in6buf), &in6buf);
4975                 }
4976         } else {
4977                 struct in_addr inbuf;
4978 
4979                 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
4980                         if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
4981                                 ret = -EINVAL;
4982                                 goto failure;
4983                         }
4984                         nla_put(msg, IFLA_VXLAN_LOCAL, sizeof(inbuf), &inbuf);
4985                 }
4986 
4987                 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
4988                         if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
4989                                 ret = -EINVAL;
4990                                 goto failure;
4991                         }
4992                         nla_put(msg, IFLA_VXLAN_GROUP, sizeof(inbuf), &inbuf);
4993                 }
4994         }
4995 
4996         uint32_t port = 4789;
4997         if ((cur = tb_data[VXLAN_DATA_ATTR_PORT])) {
4998                 port = blobmsg_get_u32(cur);
4999                 if (port < 1 || port > 65535) {
5000                         ret = -EINVAL;
5001                         goto failure;
5002                 }
5003         }
5004         nla_put_u16(msg, IFLA_VXLAN_PORT, htons(port));
5005 
5006         if ((cur = tb_data[VXLAN_DATA_ATTR_SRCPORTMIN])) {
5007                 struct ifla_vxlan_port_range srcports = {0,0};
5008 
5009                 uint32_t low = blobmsg_get_u32(cur);
5010                 if (low < 1 || low > 65535 - 1) {
5011                         ret = -EINVAL;
5012                         goto failure;
5013                 }
5014 
5015                 srcports.low = htons((uint16_t) low);
5016                 srcports.high = htons((uint16_t) (low+1));
5017 
5018                 if ((cur = tb_data[VXLAN_DATA_ATTR_SRCPORTMAX])) {
5019                         uint32_t high = blobmsg_get_u32(cur);
5020                         if (high < 1 || high > 65535) {
5021                                 ret = -EINVAL;
5022                                 goto failure;
5023                         }
5024 
5025                         if (high > low)
5026                                 srcports.high = htons((uint16_t) high);
5027                 }
5028 
5029                 nla_put(msg, IFLA_VXLAN_PORT_RANGE, sizeof(srcports), &srcports);
5030         }
5031 
5032         system_vxlan_map_bool_attr(msg, tb_data, IFLA_VXLAN_UDP_CSUM, VXLAN_DATA_ATTR_TXCSUM, false);
5033         system_vxlan_map_bool_attr(msg, tb_data, IFLA_VXLAN_UDP_ZERO_CSUM6_RX, VXLAN_DATA_ATTR_RXCSUM, true);
5034         system_vxlan_map_bool_attr(msg, tb_data, IFLA_VXLAN_UDP_ZERO_CSUM6_TX, VXLAN_DATA_ATTR_TXCSUM, true);
5035         system_vxlan_map_bool_attr(msg, tb_data, IFLA_VXLAN_LEARNING, VXLAN_DATA_ATTR_LEARNING, false);
5036         system_vxlan_map_bool_attr(msg, tb_data, IFLA_VXLAN_RSC , VXLAN_DATA_ATTR_RSC, false);
5037         system_vxlan_map_bool_attr(msg, tb_data, IFLA_VXLAN_PROXY , VXLAN_DATA_ATTR_PROXY, false);
5038         system_vxlan_map_bool_attr(msg, tb_data, IFLA_VXLAN_L2MISS , VXLAN_DATA_ATTR_L2MISS, false);
5039         system_vxlan_map_bool_attr(msg, tb_data, IFLA_VXLAN_L3MISS , VXLAN_DATA_ATTR_L3MISS, false);
5040         system_vxlan_map_bool_attr(msg, tb_data, IFLA_VXLAN_GBP , VXLAN_DATA_ATTR_GBP, false);
5041 
5042         if ((cur = tb_data[VXLAN_DATA_ATTR_AGEING])) {
5043                 uint32_t ageing = blobmsg_get_u32(cur);
5044                 nla_put_u32(msg, IFLA_VXLAN_AGEING, ageing);
5045         }
5046 
5047         if ((cur = tb_data[VXLAN_DATA_ATTR_LIMIT])) {
5048                 uint32_t maxaddress = blobmsg_get_u32(cur);
5049                 nla_put_u32(msg, IFLA_VXLAN_LIMIT, maxaddress);
5050         }
5051 
5052         if ((cur = tb[TUNNEL_ATTR_TOS])) {
5053                 char *str = blobmsg_get_string(cur);
5054                 unsigned tos = 1;
5055 
5056                 if (strcmp(str, "inherit")) {
5057                         if (!system_tos_aton(str, &tos)) {
5058                                 ret = -EINVAL;
5059                                 goto failure;
5060                         }
5061                 }
5062 
5063                 nla_put_u8(msg, IFLA_VXLAN_TOS, tos);
5064         }
5065 
5066         if ((cur = tb[TUNNEL_ATTR_TTL])) {
5067                 uint32_t ttl = blobmsg_get_u32(cur);
5068                 if (ttl < 1 || ttl > 255) {
5069                         ret = -EINVAL;
5070                         goto failure;
5071                 }
5072 
5073                 nla_put_u8(msg, IFLA_VXLAN_TTL, ttl);
5074         }
5075 
5076         nla_nest_end(msg, data);
5077         nla_nest_end(msg, linkinfo);
5078 
5079         ret = system_rtnl_call(msg);
5080         if (ret)
5081                 D(SYSTEM, "Error adding vxlan '%s': %d", name, ret);
5082 
5083         return ret;
5084 
5085 failure:
5086         nlmsg_free(msg);
5087         return ret;
5088 }
5089 #endif
5090 
5091 static int system_add_sit_tunnel(const char *name, const unsigned int link, struct blob_attr **tb)
5092 {
5093         struct blob_attr *cur;
5094         int ret = 0;
5095 
5096         if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
5097                 return -1;
5098 
5099 #ifdef SIOCADD6RD
5100         if ((cur = tb[TUNNEL_ATTR_DATA])) {
5101                 struct blob_attr *tb_data[__SIXRD_DATA_ATTR_MAX];
5102                 unsigned int mask;
5103                 struct ip_tunnel_6rd p6;
5104 
5105                 blobmsg_parse_attr(sixrd_data_attr_list.params, __SIXRD_DATA_ATTR_MAX,
5106                                    tb_data, cur);
5107 
5108                 memset(&p6, 0, sizeof(p6));
5109 
5110                 if ((cur = tb_data[SIXRD_DATA_PREFIX])) {
5111                         if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
5112                                                 &p6.prefix, &mask) || mask > 128) {
5113                                 ret = -EINVAL;
5114                                 goto failure;
5115                         }
5116 
5117                         p6.prefixlen = mask;
5118                 }
5119 
5120                 if ((cur = tb_data[SIXRD_DATA_RELAY_PREFIX])) {
5121                         if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
5122                                                 &p6.relay_prefix, &mask) || mask > 32) {
5123                                 ret = -EINVAL;
5124                                 goto failure;
5125                         }
5126 
5127                         p6.relay_prefixlen = mask;
5128                 }
5129 
5130                 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
5131                         ret = -1;
5132                         goto failure;
5133                 }
5134         }
5135 #endif
5136 
5137         return ret;
5138 
5139 failure:
5140         system_link_del(name);
5141         return ret;
5142 }
5143 
5144 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
5145 {
5146         struct blob_attr *cur;
5147         bool set_df = true;
5148         struct ip_tunnel_parm p  = {
5149                 .link = link,
5150                 .iph = {
5151                         .version = 4,
5152                         .ihl = 5,
5153                         .protocol = proto,
5154                 }
5155         };
5156 
5157         if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
5158                         inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
5159                 return -EINVAL;
5160 
5161         if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
5162                         inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
5163                 return -EINVAL;
5164 
5165         if ((cur = tb[TUNNEL_ATTR_DF]))
5166                 set_df = blobmsg_get_bool(cur);
5167 
5168         if ((cur = tb[TUNNEL_ATTR_TTL]))
5169                 p.iph.ttl = blobmsg_get_u32(cur);
5170 
5171         if ((cur = tb[TUNNEL_ATTR_TOS])) {
5172                 char *str = blobmsg_get_string(cur);
5173                 if (strcmp(str, "inherit")) {
5174                         unsigned uval;
5175 
5176                         if (!system_tos_aton(str, &uval))
5177                                 return -EINVAL;
5178 
5179                         p.iph.tos = uval;
5180                 } else
5181                         p.iph.tos = 1;
5182         }
5183 
5184         p.iph.frag_off = set_df ? htons(IP_DF) : 0;
5185         /* ttl !=0 and nopmtudisc are incompatible */
5186         if (p.iph.ttl && p.iph.frag_off == 0)
5187                 return -EINVAL;
5188 
5189         strncpy(p.name, name, sizeof(p.name) - 1);
5190 
5191         switch (p.iph.protocol) {
5192         case IPPROTO_IPIP:
5193                 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
5194         case IPPROTO_IPV6:
5195                 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
5196         default:
5197                 break;
5198         }
5199         return -1;
5200 }
5201 
5202 int system_del_ip_tunnel(const struct device *dev)
5203 {
5204         return system_link_del(dev->ifname);
5205 }
5206 
5207 int system_update_ipv6_mtu(struct device *dev, int mtu)
5208 {
5209         int ret = -1;
5210         char buf[64];
5211         int fd;
5212 
5213         fd = open(dev_sysctl_path("ipv6/conf", dev->ifname, "mtu"), O_RDWR);
5214         if (fd < 0)
5215                 return ret;
5216 
5217         if (!mtu) {
5218                 ssize_t len = read(fd, buf, sizeof(buf) - 1);
5219                 if (len < 0)
5220                         goto out;
5221 
5222                 buf[len] = 0;
5223                 ret = atoi(buf);
5224         } else {
5225                 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) > 0)
5226                         ret = mtu;
5227         }
5228 
5229 out:
5230         close(fd);
5231         return ret;
5232 }
5233 
5234 int system_add_ip_tunnel(const struct device *dev, struct blob_attr *attr)
5235 {
5236         struct blob_attr *tb[__TUNNEL_ATTR_MAX];
5237         struct blob_attr *cur;
5238         const char *str;
5239 
5240         blobmsg_parse_attr(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb, attr);
5241 
5242         system_link_del(dev->ifname);
5243 
5244         if (!(cur = tb[TUNNEL_ATTR_TYPE]))
5245                 return -EINVAL;
5246         str = blobmsg_data(cur);
5247 
5248         unsigned int ttl = 0;
5249         if ((cur = tb[TUNNEL_ATTR_TTL])) {
5250                 ttl = blobmsg_get_u32(cur);
5251                 if (ttl > 255)
5252                         return -EINVAL;
5253         }
5254 
5255         unsigned int link = 0;
5256         if ((cur = tb[TUNNEL_ATTR_LINK])) {
5257                 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
5258                 if (!iface)
5259                         return -EINVAL;
5260 
5261                 if (iface->l3_dev.dev)
5262                         link = iface->l3_dev.dev->ifindex;
5263         }
5264 
5265         if (!strcmp(str, "sit"))
5266                 return system_add_sit_tunnel(dev->ifname, link, tb);
5267 #ifdef IFLA_IPTUN_MAX
5268         else if (!strcmp(str, "ipip6")) {
5269                 return system_add_ip6_tunnel(dev->ifname, link, tb);
5270         } else if (!strcmp(str, "greip")) {
5271                 return system_add_gre_tunnel(dev->ifname, "gre", link, tb, false);
5272         } else if (!strcmp(str, "gretapip"))  {
5273                 return system_add_gre_tunnel(dev->ifname, "gretap", link, tb, false);
5274         } else if (!strcmp(str, "greip6")) {
5275                 return system_add_gre_tunnel(dev->ifname, "ip6gre", link, tb, true);
5276         } else if (!strcmp(str, "gretapip6")) {
5277                 return system_add_gre_tunnel(dev->ifname, "ip6gretap", link, tb, true);
5278 #ifdef IFLA_VTI_MAX
5279         } else if (!strcmp(str, "vtiip")) {
5280                 return system_add_vti_tunnel(dev->ifname, "vti", link, tb, false);
5281         } else if (!strcmp(str, "vtiip6")) {
5282                 return system_add_vti_tunnel(dev->ifname, "vti6", link, tb, true);
5283 #endif
5284 #ifdef IFLA_XFRM_MAX
5285         } else if (!strcmp(str, "xfrm")) {
5286                 return system_add_xfrm_tunnel(dev->ifname, "xfrm", link, tb);
5287 #endif
5288 #ifdef IFLA_VXLAN_MAX
5289         } else if(!strcmp(str, "vxlan")) {
5290                 return system_add_vxlan(dev->ifname, link, tb, false);
5291         } else if(!strcmp(str, "vxlan6")) {
5292                 return system_add_vxlan(dev->ifname, link, tb, true);
5293 #endif
5294 #endif
5295         } else if (!strcmp(str, "ipip")) {
5296                 return system_add_proto_tunnel(dev->ifname, IPPROTO_IPIP, link, tb);
5297         }
5298         else
5299                 return -EINVAL;
5300 
5301         return 0;
5302 }
5303 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt