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

Sources/netifd/system-linux.c

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

This page was automatically generated by LXR 0.3.1.  •  OpenWrt