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

Sources/netifd/system-linux.c

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

This page was automatically generated by LXR 0.3.1.  •  OpenWrt