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

This page was automatically generated by LXR 0.3.1.  •  OpenWrt