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

This page was automatically generated by LXR 0.3.1.  •  OpenWrt