• 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         memset(&ecmd, 0, sizeof(ecmd));
2452         ecmd.req.cmd = ETHTOOL_GLINKSETTINGS;
2453         strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
2454 
2455         if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) < 0 ||
2456             ecmd.req.link_mode_masks_nwords >= 0 ||
2457             ecmd.req.cmd != ETHTOOL_GLINKSETTINGS)
2458                 return;
2459 
2460         ecmd.req.link_mode_masks_nwords = -ecmd.req.link_mode_masks_nwords;
2461 
2462         if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) < 0 ||
2463             ecmd.req.link_mode_masks_nwords <= 0 ||
2464             ecmd.req.cmd != ETHTOOL_GLINKSETTINGS)
2465                 return;
2466 
2467         nwords = ecmd.req.link_mode_masks_nwords;
2468         supported = &ecmd.link_mode_data[0];
2469         advertising = &ecmd.link_mode_data[nwords];
2470         memcpy(advertising, supported, sizeof(__u32) * nwords);
2471 
2472         for (i = 0; i < ARRAY_SIZE(ethtool_modes); i++) {
2473                 if (s->flags & DEV_OPT_DUPLEX) {
2474                         if (s->duplex)
2475                                 ethtool_link_mode_clear_bit(nwords, ethtool_modes[i].bit_half, advertising);
2476                         else
2477                                 ethtool_link_mode_clear_bit(nwords, ethtool_modes[i].bit_full, advertising);
2478                 }
2479                 if (!(s->flags & DEV_OPT_SPEED) ||
2480                     s->speed == ethtool_modes[i].speed)
2481                         continue;
2482 
2483                 ethtool_link_mode_clear_bit(nwords, ethtool_modes[i].bit_full, advertising);
2484                 ethtool_link_mode_clear_bit(nwords, ethtool_modes[i].bit_half, advertising);
2485         }
2486 
2487         if (s->flags & DEV_OPT_PAUSE)
2488                 if (!s->pause)
2489                         ethtool_link_mode_clear_bit(nwords, ETHTOOL_LINK_MODE_Pause_BIT, advertising);
2490 
2491         if (s->flags & DEV_OPT_ASYM_PAUSE)
2492                 if (!s->asym_pause)
2493                         ethtool_link_mode_clear_bit(nwords, ETHTOOL_LINK_MODE_Asym_Pause_BIT, advertising);
2494 
2495         if (s->flags & DEV_OPT_AUTONEG) {
2496                 ecmd.req.autoneg = s->autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE;
2497                 if (!s->autoneg) {
2498                         if (s->flags & DEV_OPT_SPEED)
2499                                 ecmd.req.speed = s->speed;
2500 
2501                         if (s->flags & DEV_OPT_DUPLEX)
2502                                 ecmd.req.duplex = s->duplex ? DUPLEX_FULL : DUPLEX_HALF;
2503                 }
2504         }
2505 
2506         ecmd.req.cmd = ETHTOOL_SLINKSETTINGS;
2507         ioctl(sock_ioctl, SIOCETHTOOL, &ifr);
2508 }
2509 
2510 static void
2511 system_set_ethtool_settings_after_up(struct device *dev, struct device_settings *s)
2512 {
2513         if (s->flags & DEV_OPT_GRO)
2514                 system_set_ethtool_gro(dev, s);
2515 }
2516 
2517 void
2518 system_if_get_settings(struct device *dev, struct device_settings *s)
2519 {
2520         struct ifreq ifr;
2521         char buf[10];
2522         int ret;
2523 
2524         memset(&ifr, 0, sizeof(ifr));
2525         strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
2526 
2527         if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
2528                 s->mtu = ifr.ifr_mtu;
2529                 s->flags |= DEV_OPT_MTU;
2530         }
2531 
2532         s->mtu6 = system_update_ipv6_mtu(dev, 0);
2533         if (s->mtu6 > 0)
2534                 s->flags |= DEV_OPT_MTU6;
2535 
2536         if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
2537                 s->txqueuelen = ifr.ifr_qlen;
2538                 s->flags |= DEV_OPT_TXQUEUELEN;
2539         }
2540 
2541         if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
2542                 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
2543                 s->flags |= DEV_OPT_MACADDR;
2544         }
2545 
2546         if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
2547                 s->ipv6 = !strtoul(buf, NULL, 0);
2548                 s->flags |= DEV_OPT_IPV6;
2549         }
2550 
2551         if (!system_get_ip6segmentrouting(dev, buf, sizeof(buf))) {
2552                 s->ip6segmentrouting = strtoul(buf, NULL, 0);
2553                 s->flags |= DEV_OPT_IP6SEGMENTROUTING;
2554         }
2555 
2556         if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
2557                 s->promisc = ifr.ifr_flags & IFF_PROMISC;
2558                 s->flags |= DEV_OPT_PROMISC;
2559 
2560                 s->multicast = ifr.ifr_flags & IFF_MULTICAST;
2561                 s->flags |= DEV_OPT_MULTICAST;
2562         }
2563 
2564         if (!system_get_rpfilter(dev, buf, sizeof(buf))) {
2565                 s->rpfilter = strtoul(buf, NULL, 0);
2566                 s->flags |= DEV_OPT_RPFILTER;
2567         }
2568 
2569         if (!system_get_acceptlocal(dev, buf, sizeof(buf))) {
2570                 s->acceptlocal = strtoul(buf, NULL, 0);
2571                 s->flags |= DEV_OPT_ACCEPTLOCAL;
2572         }
2573 
2574         if (!system_get_igmpversion(dev, buf, sizeof(buf))) {
2575                 s->igmpversion = strtoul(buf, NULL, 0);
2576                 s->flags |= DEV_OPT_IGMPVERSION;
2577         }
2578 
2579         if (!system_get_mldversion(dev, buf, sizeof(buf))) {
2580                 s->mldversion = strtoul(buf, NULL, 0);
2581                 s->flags |= DEV_OPT_MLDVERSION;
2582         }
2583 
2584         if (!system_get_neigh4reachabletime(dev, buf, sizeof(buf))) {
2585                 s->neigh4reachabletime = strtoul(buf, NULL, 0);
2586                 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
2587         }
2588 
2589         if (!system_get_neigh6reachabletime(dev, buf, sizeof(buf))) {
2590                 s->neigh6reachabletime = strtoul(buf, NULL, 0);
2591                 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
2592         }
2593 
2594         if (!system_get_neigh4locktime(dev, buf, sizeof(buf))) {
2595                 s->neigh4locktime = strtol(buf, NULL, 0);
2596                 s->flags |= DEV_OPT_NEIGHLOCKTIME;
2597         }
2598 
2599         if (!system_get_neigh4gcstaletime(dev, buf, sizeof(buf))) {
2600                 s->neigh4gcstaletime = strtoul(buf, NULL, 0);
2601                 s->flags |= DEV_OPT_NEIGHGCSTALETIME;
2602         }
2603 
2604         if (!system_get_neigh6gcstaletime(dev, buf, sizeof(buf))) {
2605                 s->neigh6gcstaletime = strtoul(buf, NULL, 0);
2606                 s->flags |= DEV_OPT_NEIGHGCSTALETIME;
2607         }
2608 
2609         if (!system_get_dadtransmits(dev, buf, sizeof(buf))) {
2610                 s->dadtransmits = strtoul(buf, NULL, 0);
2611                 s->flags |= DEV_OPT_DADTRANSMITS;
2612         }
2613 
2614         if (!system_get_sendredirects(dev, buf, sizeof(buf))) {
2615                 s->sendredirects = strtoul(buf, NULL, 0);
2616                 s->flags |= DEV_OPT_SENDREDIRECTS;
2617         }
2618 
2619         if (!system_get_drop_v4_unicast_in_l2_multicast(dev, buf, sizeof(buf))) {
2620                 s->drop_v4_unicast_in_l2_multicast = strtoul(buf, NULL, 0);
2621                 s->flags |= DEV_OPT_DROP_V4_UNICAST_IN_L2_MULTICAST;
2622         }
2623 
2624         if (!system_get_drop_v6_unicast_in_l2_multicast(dev, buf, sizeof(buf))) {
2625                 s->drop_v6_unicast_in_l2_multicast = strtoul(buf, NULL, 0);
2626                 s->flags |= DEV_OPT_DROP_V6_UNICAST_IN_L2_MULTICAST;
2627         }
2628 
2629         if (!system_get_drop_gratuitous_arp(dev, buf, sizeof(buf))) {
2630                 s->drop_gratuitous_arp = strtoul(buf, NULL, 0);
2631                 s->flags |= DEV_OPT_DROP_GRATUITOUS_ARP;
2632         }
2633 
2634         if (!system_get_drop_unsolicited_na(dev, buf, sizeof(buf))) {
2635                 s->drop_unsolicited_na = strtoul(buf, NULL, 0);
2636                 s->flags |= DEV_OPT_DROP_UNSOLICITED_NA;
2637         }
2638 
2639         if (!system_get_arp_accept(dev, buf, sizeof(buf))) {
2640                 s->arp_accept = strtoul(buf, NULL, 0);
2641                 s->flags |= DEV_OPT_ARP_ACCEPT;
2642         }
2643 
2644         ret = system_get_ethtool_gro(dev);
2645         if (ret >= 0) {
2646                 s->gro = ret;
2647                 s->flags |= DEV_OPT_GRO;
2648         }
2649 
2650 #if LINUX_VERSION_CODE >= KERNEL_VERSION(6,1,0)
2651         ret = system_if_get_master_ifindex(dev);
2652         if (ret >= 0) {
2653                 s->master_ifindex = ret;
2654                 s->flags |= DEV_OPT_MASTER;
2655         }
2656 #endif
2657 }
2658 
2659 void
2660 system_if_apply_settings(struct device *dev, struct device_settings *s, uint64_t apply_mask)
2661 {
2662         struct ifreq ifr;
2663         char buf[12];
2664 
2665         apply_mask &= s->flags;
2666 
2667         if (apply_mask & DEV_OPT_MASTER) {
2668 #if LINUX_VERSION_CODE >= KERNEL_VERSION(6,1,0)
2669                 system_set_master(dev, s->master_ifindex);
2670                 if (!(apply_mask & (DEV_OPT_MACADDR | DEV_OPT_DEFAULT_MACADDR)) || dev->external)
2671                         system_refresh_orig_macaddr(dev, &dev->orig_settings);
2672 #else
2673                 netifd_log_message(L_WARNING, "%s Your kernel is older than linux 6.1.0, changing DSA port conduit is not supported!", dev->ifname);
2674 #endif
2675         }
2676 
2677         memset(&ifr, 0, sizeof(ifr));
2678         strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
2679         if (apply_mask & DEV_OPT_MTU) {
2680                 ifr.ifr_mtu = s->mtu;
2681                 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
2682                         s->flags &= ~DEV_OPT_MTU;
2683         }
2684         if (apply_mask & DEV_OPT_MTU6) {
2685                 system_update_ipv6_mtu(dev, s->mtu6);
2686         }
2687         if (apply_mask & DEV_OPT_TXQUEUELEN) {
2688                 ifr.ifr_qlen = s->txqueuelen;
2689                 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
2690                         s->flags &= ~DEV_OPT_TXQUEUELEN;
2691         }
2692         if ((apply_mask & (DEV_OPT_MACADDR | DEV_OPT_DEFAULT_MACADDR)) && !dev->external) {
2693                 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
2694                 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
2695                 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
2696                         s->flags &= ~DEV_OPT_MACADDR;
2697         }
2698         if (apply_mask & DEV_OPT_IPV6)
2699                 system_set_disable_ipv6(dev, s->ipv6 ? "" : "1");
2700         if (s->flags & DEV_OPT_IP6SEGMENTROUTING & apply_mask) {
2701                 struct device dummy = {
2702                         .ifname = "all",
2703                 };
2704                 bool ip6segmentrouting = device_check_ip6segmentrouting();
2705 
2706                 system_set_ip6segmentrouting(dev, s->ip6segmentrouting ? "1" : "");
2707                 system_set_ip6segmentrouting(&dummy, ip6segmentrouting ? "1" : "");
2708         }
2709         if (apply_mask & DEV_OPT_PROMISC) {
2710                 if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
2711                                     !s->promisc ? IFF_PROMISC : 0) < 0)
2712                         s->flags &= ~DEV_OPT_PROMISC;
2713         }
2714         if (apply_mask & DEV_OPT_RPFILTER) {
2715                 snprintf(buf, sizeof(buf), "%u", s->rpfilter);
2716                 system_set_rpfilter(dev, buf);
2717         }
2718         if (apply_mask & DEV_OPT_ACCEPTLOCAL)
2719                 system_set_acceptlocal(dev, s->acceptlocal ? "1" : "");
2720         if (apply_mask & DEV_OPT_IGMPVERSION) {
2721                 snprintf(buf, sizeof(buf), "%u", s->igmpversion);
2722                 system_set_igmpversion(dev, buf);
2723         }
2724         if (apply_mask & DEV_OPT_MLDVERSION) {
2725                 snprintf(buf, sizeof(buf), "%u", s->mldversion);
2726                 system_set_mldversion(dev, buf);
2727         }
2728         if (apply_mask & DEV_OPT_NEIGHREACHABLETIME) {
2729                 snprintf(buf, sizeof(buf), "%u", s->neigh4reachabletime);
2730                 system_set_neigh4reachabletime(dev, buf);
2731                 snprintf(buf, sizeof(buf), "%u", s->neigh6reachabletime);
2732                 system_set_neigh6reachabletime(dev, buf);
2733         }
2734         if (apply_mask & DEV_OPT_NEIGHLOCKTIME) {
2735                 snprintf(buf, sizeof(buf), "%d", s->neigh4locktime);
2736                 system_set_neigh4locktime(dev, buf);
2737         }
2738         if (apply_mask & DEV_OPT_NEIGHGCSTALETIME) {
2739                 snprintf(buf, sizeof(buf), "%u", s->neigh4gcstaletime);
2740                 system_set_neigh4gcstaletime(dev, buf);
2741                 snprintf(buf, sizeof(buf), "%u", s->neigh6gcstaletime);
2742                 system_set_neigh6gcstaletime(dev, buf);
2743         }
2744         if (apply_mask & DEV_OPT_DADTRANSMITS) {
2745                 snprintf(buf, sizeof(buf), "%u", s->dadtransmits);
2746                 system_set_dadtransmits(dev, buf);
2747         }
2748         if (apply_mask & DEV_OPT_MULTICAST) {
2749                 if (system_if_flags(dev->ifname, s->multicast ? IFF_MULTICAST : 0,
2750                                     !s->multicast ? IFF_MULTICAST : 0) < 0)
2751                         s->flags &= ~DEV_OPT_MULTICAST;
2752         }
2753         if (apply_mask & DEV_OPT_SENDREDIRECTS)
2754                 system_set_sendredirects(dev, s->sendredirects ? "1" : "");
2755         if (apply_mask & DEV_OPT_DROP_V4_UNICAST_IN_L2_MULTICAST)
2756                 system_set_drop_v4_unicast_in_l2_multicast(dev, s->drop_v4_unicast_in_l2_multicast ? "1" : "");
2757         if (apply_mask & DEV_OPT_DROP_V6_UNICAST_IN_L2_MULTICAST)
2758                 system_set_drop_v6_unicast_in_l2_multicast(dev, s->drop_v6_unicast_in_l2_multicast ? "1" : "");
2759         if (apply_mask & DEV_OPT_DROP_GRATUITOUS_ARP)
2760                 system_set_drop_gratuitous_arp(dev, s->drop_gratuitous_arp ? "1" : "");
2761         if (apply_mask & DEV_OPT_DROP_UNSOLICITED_NA)
2762                 system_set_drop_unsolicited_na(dev, s->drop_unsolicited_na ? "1" : "");
2763         if (apply_mask & DEV_OPT_ARP_ACCEPT)
2764                 system_set_arp_accept(dev, s->arp_accept ? "1" : "");
2765         system_set_ethtool_settings(dev, s);
2766 }
2767 
2768 void system_if_apply_settings_after_up(struct device *dev, struct device_settings *s)
2769 {
2770         system_set_ethtool_settings_after_up(dev, s);
2771 }
2772 
2773 int system_if_up(struct device *dev)
2774 {
2775         return system_if_flags(dev->ifname, IFF_UP, 0);
2776 }
2777 
2778 int system_if_down(struct device *dev)
2779 {
2780         return system_if_flags(dev->ifname, 0, IFF_UP);
2781 }
2782 
2783 struct if_check_data {
2784         struct device *dev;
2785         int pending;
2786         int ret;
2787 };
2788 
2789 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
2790 {
2791         struct nlmsghdr *nh = nlmsg_hdr(msg);
2792         struct ifinfomsg *ifi = NLMSG_DATA(nh);
2793         struct if_check_data *chk = (struct if_check_data *)arg;
2794 
2795         if (nh->nlmsg_type != RTM_NEWLINK)
2796                 return NL_SKIP;
2797 
2798         system_device_update_state(chk->dev, ifi->ifi_flags);
2799         return NL_OK;
2800 }
2801 
2802 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
2803 {
2804         struct if_check_data *chk = (struct if_check_data *)arg;
2805         chk->pending = 0;
2806         return NL_STOP;
2807 }
2808 
2809 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
2810 {
2811         struct if_check_data *chk = (struct if_check_data *)arg;
2812 
2813         if (chk->dev->type == &simple_device_type)
2814                 device_set_present(chk->dev, false);
2815         device_set_link(chk->dev, false);
2816         chk->pending = err->error;
2817 
2818         return NL_STOP;
2819 }
2820 
2821 struct bridge_vlan_check_data {
2822         struct device *check_dev;
2823         int ifindex;
2824         int ret;
2825         bool pending;
2826 };
2827 
2828 static void bridge_vlan_check_port(struct bridge_vlan_check_data *data,
2829                                    struct bridge_vlan_port *port,
2830                                    struct bridge_vlan_info *vinfo)
2831 {
2832         uint16_t flags = 0, diff, mask;
2833 
2834         if (port->flags & BRVLAN_F_PVID)
2835                 flags |= BRIDGE_VLAN_INFO_PVID;
2836         if (port->flags & BRVLAN_F_UNTAGGED)
2837                 flags |= BRIDGE_VLAN_INFO_UNTAGGED;
2838 
2839         diff = vinfo->flags ^ flags;
2840         mask = BRVLAN_F_UNTAGGED | (flags & BRIDGE_VLAN_INFO_PVID);
2841         if (diff & mask) {
2842                 data->ret = 1;
2843                 data->pending = false;
2844         }
2845 
2846         port->check = 1;
2847 }
2848 
2849 static void bridge_vlan_check_attr(struct bridge_vlan_check_data *data,
2850                                    struct rtattr *attr)
2851 {
2852         struct bridge_vlan_hotplug_port *port;
2853         struct bridge_vlan_info *vinfo;
2854         struct bridge_vlan *vlan;
2855         struct rtattr *cur;
2856         int rem = RTA_PAYLOAD(attr);
2857         int i;
2858 
2859         for (cur = RTA_DATA(attr); RTA_OK(cur, rem); cur = RTA_NEXT(cur, rem)) {
2860                 if (cur->rta_type != IFLA_BRIDGE_VLAN_INFO)
2861                         continue;
2862 
2863                 vinfo = RTA_DATA(cur);
2864                 vlan = vlist_find(&data->check_dev->vlans, &vinfo->vid, vlan, node);
2865                 if (!vlan) {
2866                         data->ret = 1;
2867                         data->pending = false;
2868                         return;
2869                 }
2870 
2871                 for (i = 0; i < vlan->n_ports; i++)
2872                         if (!vlan->ports[i].check)
2873                                 bridge_vlan_check_port(data, &vlan->ports[i], vinfo);
2874 
2875                 list_for_each_entry(port, &vlan->hotplug_ports, list)
2876                         if (!port->port.check)
2877                                 bridge_vlan_check_port(data, &port->port, vinfo);
2878         }
2879 }
2880 
2881 static int bridge_vlan_check_cb(struct nl_msg *msg, void *arg)
2882 {
2883         struct bridge_vlan_check_data *data = arg;
2884         struct nlmsghdr *nh = nlmsg_hdr(msg);
2885         struct ifinfomsg *ifi = NLMSG_DATA(nh);
2886         struct rtattr *attr;
2887         int rem;
2888 
2889         if (nh->nlmsg_type != RTM_NEWLINK)
2890                 return NL_SKIP;
2891 
2892         if (ifi->ifi_family != AF_BRIDGE)
2893                 return NL_SKIP;
2894 
2895         if (ifi->ifi_index != data->ifindex)
2896                 return NL_SKIP;
2897 
2898         attr = IFLA_RTA(ifi);
2899         rem = nh->nlmsg_len - NLMSG_LENGTH(sizeof(*ifi));
2900         while (RTA_OK(attr, rem)) {
2901                 if (attr->rta_type == IFLA_AF_SPEC)
2902                         bridge_vlan_check_attr(data, attr);
2903 
2904                 attr = RTA_NEXT(attr, rem);
2905         }
2906 
2907         return NL_SKIP;
2908 }
2909 
2910 static int bridge_vlan_ack_cb(struct nl_msg *msg, void *arg)
2911 {
2912         struct bridge_vlan_check_data *data = arg;
2913         data->pending = false;
2914         return NL_STOP;
2915 }
2916 
2917 static int bridge_vlan_error_cb(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
2918 {
2919         struct bridge_vlan_check_data *data = arg;
2920         data->pending = false;
2921         return NL_STOP;
2922 }
2923 
2924 int system_bridge_vlan_check(struct device *dev, char *ifname)
2925 {
2926         struct bridge_vlan_check_data data = {
2927                 .check_dev = dev,
2928                 .ifindex = if_nametoindex(ifname),
2929                 .ret = -1,
2930                 .pending = true,
2931         };
2932         static struct ifinfomsg ifi = {
2933                 .ifi_family = AF_BRIDGE
2934         };
2935         static struct rtattr ext_req = {
2936                 .rta_type = IFLA_EXT_MASK,
2937                 .rta_len = RTA_LENGTH(sizeof(uint32_t)),
2938         };
2939         uint32_t filter = RTEXT_FILTER_BRVLAN;
2940         struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
2941         struct bridge_vlan *vlan;
2942         struct nl_msg *msg;
2943         int i;
2944 
2945         if (!data.ifindex)
2946                 return 0;
2947 
2948         msg = nlmsg_alloc_simple(RTM_GETLINK, NLM_F_DUMP);
2949 
2950         if (nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
2951                 nlmsg_append(msg, &ext_req, sizeof(ext_req), NLMSG_ALIGNTO) ||
2952                 nlmsg_append(msg, &filter, sizeof(filter), 0))
2953                 goto free;
2954 
2955         vlist_for_each_element(&dev->vlans, vlan, node) {
2956                 struct bridge_vlan_hotplug_port *port;
2957 
2958                 for (i = 0; i < vlan->n_ports; i++) {
2959                         if (!strcmp(vlan->ports[i].ifname, ifname))
2960                                 vlan->ports[i].check = 0;
2961                         else
2962                                 vlan->ports[i].check = -1;
2963                 }
2964 
2965                 list_for_each_entry(port, &vlan->hotplug_ports, list) {
2966                         if (!strcmp(port->port.ifname, ifname))
2967                                 port->port.check = 0;
2968                         else
2969                                 port->port.check = -1;
2970                 }
2971         }
2972 
2973         nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, bridge_vlan_check_cb, &data);
2974         nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, bridge_vlan_ack_cb, &data);
2975         nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, bridge_vlan_ack_cb, &data);
2976         nl_cb_err(cb, NL_CB_CUSTOM, bridge_vlan_error_cb, &data);
2977 
2978         if (nl_send_auto_complete(sock_rtnl, msg) < 0)
2979                 goto free;
2980 
2981         data.ret = 0;
2982         while (data.pending)
2983                 nl_recvmsgs(sock_rtnl, cb);
2984 
2985         vlist_for_each_element(&dev->vlans, vlan, node) {
2986                 struct bridge_vlan_hotplug_port *port;
2987 
2988                 for (i = 0; i < vlan->n_ports; i++) {
2989                         if (!vlan->ports[i].check) {
2990                                 data.ret = 1;
2991                                 break;
2992                         }
2993                 }
2994 
2995                 list_for_each_entry(port, &vlan->hotplug_ports, list) {
2996                         if (!port->port.check) {
2997                                 data.ret = 1;
2998                                 break;
2999                         }
3000                 }
3001         }
3002 
3003 free:
3004         nlmsg_free(msg);
3005         nl_cb_put(cb);
3006         return data.ret;
3007 }
3008 
3009 int system_if_check(struct device *dev)
3010 {
3011         struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
3012         struct nl_msg *msg;
3013         struct ifinfomsg ifi = {
3014                 .ifi_family = AF_UNSPEC,
3015                 .ifi_index = 0,
3016         };
3017         struct if_check_data chk = {
3018                 .dev = dev,
3019                 .pending = 1,
3020         };
3021         int ret = 1;
3022 
3023         if (!cb)
3024                 return ret;
3025 
3026         msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
3027         if (!msg)
3028                 goto out;
3029 
3030         if (nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
3031             nla_put_string(msg, IFLA_IFNAME, dev->ifname))
3032                 goto free;
3033 
3034         nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
3035         nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
3036         nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
3037 
3038         ret = nl_send_auto_complete(sock_rtnl, msg);
3039         if (ret < 0)
3040                 goto free;
3041 
3042         while (chk.pending > 0)
3043                 nl_recvmsgs(sock_rtnl, cb);
3044 
3045         ret = chk.pending;
3046 
3047 free:
3048         nlmsg_free(msg);
3049 out:
3050         nl_cb_put(cb);
3051         return ret;
3052 }
3053 
3054 struct device *
3055 system_if_get_parent(struct device *dev)
3056 {
3057         char buf[64], *devname;
3058         int ifindex, iflink;
3059 
3060         if (system_get_dev_sysfs("iflink", dev->ifname, buf, sizeof(buf)) < 0)
3061                 return NULL;
3062 
3063         iflink = strtoul(buf, NULL, 0);
3064         ifindex = system_if_resolve(dev);
3065         if (!iflink || iflink == ifindex)
3066                 return NULL;
3067 
3068         devname = if_indextoname(iflink, buf);
3069         if (!devname)
3070                 return NULL;
3071 
3072         return device_get(devname, true);
3073 }
3074 
3075 static bool
3076 read_string_file(int dir_fd, const char *file, char *buf, int len)
3077 {
3078         bool ret = false;
3079         char *c;
3080         int fd;
3081 
3082         fd = openat(dir_fd, file, O_RDONLY);
3083         if (fd < 0)
3084                 return false;
3085 
3086 retry:
3087         len = read(fd, buf, len - 1);
3088         if (len < 0) {
3089                 if (errno == EINTR)
3090                         goto retry;
3091         } else if (len > 0) {
3092                         buf[len] = 0;
3093 
3094                         c = strchr(buf, '\n');
3095                         if (c)
3096                                 *c = 0;
3097 
3098                         ret = true;
3099         }
3100 
3101         close(fd);
3102 
3103         return ret;
3104 }
3105 
3106 static bool
3107 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
3108 {
3109         char buf[64];
3110         bool ret = false;
3111 
3112         ret = read_string_file(dir_fd, file, buf, sizeof(buf));
3113         if (ret)
3114                 *val = strtoull(buf, NULL, 0);
3115 
3116         return ret;
3117 }
3118 
3119 bool
3120 system_if_force_external(const char *ifname)
3121 {
3122         struct stat s;
3123 
3124         return stat(dev_sysfs_path(ifname, "phy80211"), &s) == 0;
3125 }
3126 
3127 static const char *
3128 system_netdevtype_name(unsigned short dev_type)
3129 {
3130         size_t i;
3131 
3132         for (i = 0; i < ARRAY_SIZE(netdev_types); i++) {
3133                 if (netdev_types[i].id == dev_type)
3134                         return netdev_types[i].name;
3135         }
3136 
3137         /* the last key is used by default */
3138         i = ARRAY_SIZE(netdev_types) - 1;
3139 
3140         return netdev_types[i].name;
3141 }
3142 
3143 static void
3144 system_add_devtype(struct blob_buf *b, const char *ifname)
3145 {
3146         char buf[100];
3147         bool found = false;
3148 
3149         if (!system_get_dev_sysfs("uevent", ifname, buf, sizeof(buf))) {
3150                 const char *info = "DEVTYPE=";
3151                 char *context = NULL;
3152                 const char *line = strtok_r(buf, "\r\n", &context);
3153 
3154                 while (line != NULL) {
3155                         char *index = strstr(line, info);
3156 
3157                         if (index != NULL) {
3158                                 blobmsg_add_string(b, "devtype", index + strlen(info));
3159                                 found = true;
3160                                 break;
3161                         }
3162 
3163                         line = strtok_r(NULL, "\r\n", &context);
3164                 }
3165         }
3166 
3167         if (!found) {
3168                 unsigned short number = 0;
3169                 const char *name = NULL;
3170 
3171                 if (!system_get_dev_sysfs("type", ifname, buf, sizeof(buf))) {
3172                         number = strtoul(buf, NULL, 0);
3173                         name = system_netdevtype_name(number);
3174                         blobmsg_add_string(b, "devtype", name);
3175                 }
3176         }
3177 }
3178 
3179 #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
3180 
3181 static int32_t
3182 ethtool_feature_count(const char *ifname)
3183 {
3184         struct {
3185                 struct ethtool_sset_info hdr;
3186                 uint32_t buf;
3187         } req = {
3188                 .hdr = {
3189                         .cmd = ETHTOOL_GSSET_INFO,
3190                         .sset_mask = 1 << ETH_SS_FEATURES
3191                 }
3192         };
3193 
3194         struct ifreq ifr = {
3195                 .ifr_data = (void *)&req
3196         };
3197 
3198         strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1);
3199 
3200         if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) != 0)
3201                 return -1;
3202 
3203         if (!req.hdr.sset_mask)
3204                 return 0;
3205 
3206         return req.buf;
3207 }
3208 
3209 static int32_t
3210 ethtool_feature_index(const char *ifname, const char *keyname)
3211 {
3212         struct ethtool_gstrings *feature_names;
3213         struct ifreq ifr = { 0 };
3214         int32_t n_features;
3215         uint32_t i;
3216 
3217         n_features = ethtool_feature_count(ifname);
3218 
3219         if (n_features <= 0)
3220                 return -1;
3221 
3222         feature_names = calloc(1, sizeof(*feature_names) + n_features * ETH_GSTRING_LEN);
3223 
3224         if (!feature_names)
3225                 return -1;
3226 
3227         feature_names->cmd = ETHTOOL_GSTRINGS;
3228         feature_names->string_set = ETH_SS_FEATURES;
3229         feature_names->len = n_features;
3230 
3231         strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1);
3232         ifr.ifr_data = (void *)feature_names;
3233 
3234         if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) != 0) {
3235                 free(feature_names);
3236 
3237                 return -1;
3238         }
3239 
3240         for (i = 0; i < feature_names->len; i++)
3241                 if (!strcmp((char *)&feature_names->data[i * ETH_GSTRING_LEN], keyname))
3242                         break;
3243 
3244         if (i >= feature_names->len)
3245                 i = -1;
3246 
3247         free(feature_names);
3248 
3249         return i;
3250 }
3251 
3252 static bool
3253 ethtool_feature_value(const char *ifname, const char *keyname)
3254 {
3255         struct ethtool_get_features_block *feature_block;
3256         struct ethtool_gfeatures *feature_values;
3257         struct ifreq ifr = { 0 };
3258         int32_t feature_idx;
3259         bool active;
3260 
3261         feature_idx = ethtool_feature_index(ifname, keyname);
3262 
3263         if (feature_idx < 0)
3264                 return false;
3265 
3266         feature_values = calloc(1,
3267                 sizeof(*feature_values) +
3268                 sizeof(feature_values->features[0]) * DIV_ROUND_UP(feature_idx, 32));
3269 
3270         if (!feature_values)
3271                 return false;
3272 
3273         feature_values->cmd = ETHTOOL_GFEATURES;
3274         feature_values->size = DIV_ROUND_UP(feature_idx, 32);
3275 
3276         strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1);
3277         ifr.ifr_data = (void *)feature_values;
3278 
3279         if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) != 0) {
3280                 free(feature_values);
3281 
3282                 return false;
3283         }
3284 
3285         feature_block = &feature_values->features[feature_idx / 32];
3286         active = feature_block->active & (1U << feature_idx % 32);
3287 
3288         free(feature_values);
3289 
3290         return active;
3291 }
3292 
3293 static void
3294 system_add_link_mode_name(struct blob_buf *b, int i, bool half)
3295 {
3296         char *buf;
3297 
3298         /* allocate string buffer large enough for the mode name and a suffix
3299          * "-F" or "-H" indicating full duplex or half duplex.
3300          */
3301         buf = blobmsg_alloc_string_buffer(b, NULL, strlen(ethtool_modes[i].name) + 3);
3302         if (!buf)
3303                 return;
3304 
3305         strcpy(buf, ethtool_modes[i].name);
3306         if (half)
3307                 strcat(buf, "-H");
3308         else
3309                 strcat(buf, "-F");
3310 
3311         blobmsg_add_string_buffer(b);
3312 }
3313 
3314 static void
3315 system_add_link_modes(__s8 nwords, struct blob_buf *b, __u32 *mask)
3316 {
3317         size_t i;
3318 
3319         for (i = 0; i < ARRAY_SIZE(ethtool_modes); i++) {
3320                 if (ethtool_link_mode_test_bit(nwords, ethtool_modes[i].bit_half, mask))
3321                         system_add_link_mode_name(b, i, true);
3322 
3323                 if (ethtool_link_mode_test_bit(nwords, ethtool_modes[i].bit_full, mask))
3324                         system_add_link_mode_name(b, i, false);
3325         }
3326 }
3327 
3328 static void
3329 system_add_pause_modes(__s8 nwords, struct blob_buf *b, __u32 *mask)
3330 {
3331         if (ethtool_link_mode_test_bit(nwords, ETHTOOL_LINK_MODE_Pause_BIT, mask))
3332                 blobmsg_add_string(b, NULL, "pause");
3333 
3334         if (ethtool_link_mode_test_bit(nwords, ETHTOOL_LINK_MODE_Asym_Pause_BIT, mask))
3335                 blobmsg_add_string(b, NULL, "asym_pause");
3336 }
3337 
3338 
3339 static void
3340 system_add_ethtool_pause_an(struct blob_buf *b, __s8 nwords,
3341                             __u32 *advertising, __u32 *lp_advertising)
3342 {
3343         bool an_rx = false, an_tx = false;
3344         void *d;
3345 
3346         d = blobmsg_open_array(b, "negotiated");
3347 
3348         /* Work out negotiated pause frame usage per
3349          * IEEE 802.3-2005 table 28B-3.
3350          */
3351         if (ethtool_link_mode_test_bit(nwords,
3352                                        ETHTOOL_LINK_MODE_Pause_BIT,
3353                                        advertising) &&
3354             ethtool_link_mode_test_bit(nwords,
3355                                        ETHTOOL_LINK_MODE_Pause_BIT,
3356                                        lp_advertising)) {
3357                 an_tx = true;
3358                 an_rx = true;
3359         } else if (ethtool_link_mode_test_bit(nwords,
3360                                               ETHTOOL_LINK_MODE_Asym_Pause_BIT,
3361                                               advertising) &&
3362                    ethtool_link_mode_test_bit(nwords,
3363                                               ETHTOOL_LINK_MODE_Asym_Pause_BIT,
3364                                               lp_advertising)) {
3365                 if (ethtool_link_mode_test_bit(nwords,
3366                                                ETHTOOL_LINK_MODE_Pause_BIT,
3367                                                advertising))
3368                         an_rx = true;
3369                 else if (ethtool_link_mode_test_bit(nwords,
3370                                                     ETHTOOL_LINK_MODE_Pause_BIT,
3371                                                     lp_advertising))
3372                         an_tx = true;
3373         }
3374         if (an_tx)
3375                 blobmsg_add_string(b, NULL, "rx");
3376 
3377         if (an_rx)
3378                 blobmsg_add_string(b, NULL, "tx");
3379 
3380         blobmsg_close_array(b, d);
3381 }
3382 
3383 static void
3384 system_get_ethtool_pause(struct device *dev, bool *rx_pause, bool *tx_pause, bool *pause_autoneg)
3385 {
3386         struct ethtool_pauseparam pp;
3387         struct ifreq ifr = {
3388                 .ifr_data = (caddr_t)&pp,
3389         };
3390 
3391         strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
3392         memset(&pp, 0, sizeof(pp));
3393         pp.cmd = ETHTOOL_GPAUSEPARAM;
3394 
3395         /* may fail */
3396         if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == -1) {
3397                 *pause_autoneg = true;
3398                 return;
3399         }
3400 
3401         *rx_pause = pp.rx_pause;
3402         *tx_pause = pp.tx_pause;
3403         *pause_autoneg = pp.autoneg;
3404 }
3405 
3406 int
3407 system_if_dump_info(struct device *dev, struct blob_buf *b)
3408 {
3409         __u32 *supported, *advertising, *lp_advertising;
3410         bool rx_pause = false, tx_pause = false, pause_autoneg;
3411         struct {
3412                 struct ethtool_link_settings req;
3413                 __u32 link_mode_data[3 * 127];
3414         } ecmd;
3415         struct ifreq ifr = {
3416                 .ifr_data = (caddr_t)&ecmd,
3417         };
3418         __s8 nwords;
3419         void *c, *d;
3420         char *s;
3421 
3422         system_get_ethtool_pause(dev, &rx_pause, &tx_pause, &pause_autoneg);
3423 
3424         memset(&ecmd, 0, sizeof(ecmd));
3425         ecmd.req.cmd = ETHTOOL_GLINKSETTINGS;
3426         strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
3427 
3428         if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) < 0 ||
3429             ecmd.req.link_mode_masks_nwords >= 0 ||
3430             ecmd.req.cmd != ETHTOOL_GLINKSETTINGS)
3431                 return -EOPNOTSUPP;
3432 
3433         ecmd.req.link_mode_masks_nwords = -ecmd.req.link_mode_masks_nwords;
3434 
3435         if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) < 0 ||
3436             ecmd.req.link_mode_masks_nwords <= 0 ||
3437             ecmd.req.cmd != ETHTOOL_GLINKSETTINGS)
3438                 return -EIO;
3439 
3440         nwords = ecmd.req.link_mode_masks_nwords;
3441         supported = &ecmd.link_mode_data[0];
3442         advertising = &ecmd.link_mode_data[nwords];
3443         lp_advertising = &ecmd.link_mode_data[2 * nwords];
3444 
3445         c = blobmsg_open_array(b, "link-advertising");
3446         system_add_link_modes(nwords, b, advertising);
3447         blobmsg_close_array(b, c);
3448 
3449         c = blobmsg_open_array(b, "link-partner-advertising");
3450         system_add_link_modes(nwords, b, lp_advertising);
3451         blobmsg_close_array(b, c);
3452 
3453         c = blobmsg_open_array(b, "link-supported");
3454         system_add_link_modes(nwords, b, supported);
3455         blobmsg_close_array(b, c);
3456 
3457         if (ethtool_validate_speed(ecmd.req.speed) &&
3458             (ecmd.req.speed != (__u32)SPEED_UNKNOWN) &&
3459             (ecmd.req.speed != 0)) {
3460                 s = blobmsg_alloc_string_buffer(b, "speed", 10);
3461                 snprintf(s, 8, "%d%c", ecmd.req.speed,
3462                         ecmd.req.duplex == DUPLEX_HALF ? 'H' : 'F');
3463                 blobmsg_add_string_buffer(b);
3464         }
3465         blobmsg_add_u8(b, "autoneg", !!ecmd.req.autoneg);
3466 
3467         c = blobmsg_open_table(b, "flow-control");
3468         blobmsg_add_u8(b, "autoneg", pause_autoneg);
3469 
3470         d = blobmsg_open_array(b, "supported");
3471         system_add_pause_modes(nwords, b, supported);
3472         blobmsg_close_array(b, d);
3473 
3474         if (pause_autoneg) {
3475                 d = blobmsg_open_array(b, "link-advertising");
3476                 system_add_pause_modes(nwords, b, advertising);
3477                 blobmsg_close_array(b, d);
3478         }
3479 
3480         d = blobmsg_open_array(b, "link-partner-advertising");
3481         system_add_pause_modes(nwords, b, lp_advertising);
3482         blobmsg_close_array(b, d);
3483 
3484         if (pause_autoneg) {
3485                 system_add_ethtool_pause_an(b, nwords, advertising,
3486                                             lp_advertising);
3487         } else {
3488                 d = blobmsg_open_array(b, "selected");
3489                 if (rx_pause)
3490                         blobmsg_add_string(b, NULL, "rx");
3491 
3492                 if (tx_pause)
3493                         blobmsg_add_string(b, NULL, "tx");
3494 
3495                 blobmsg_close_array(b, d);
3496         }
3497 
3498         blobmsg_close_table(b, c);
3499 
3500         blobmsg_add_u8(b, "hw-tc-offload",
3501                 ethtool_feature_value(dev->ifname, "hw-tc-offload"));
3502 
3503         system_add_devtype(b, dev->ifname);
3504 
3505         /* Add PSE (PoE) status if available */
3506         {
3507                 struct pse_reply_data pse_data;
3508                 if (system_pse_get(dev, &pse_data) == 0) {
3509                         void *pse_tbl = blobmsg_open_table(b, "pse");
3510 
3511                         /* C33 (Clause 33 PoE) status */
3512                         if (pse_data.c33_admin_state) {
3513                                 const char *state = "unknown";
3514                                 switch (pse_data.c33_admin_state) {
3515                                 case ETHTOOL_C33_PSE_ADMIN_STATE_DISABLED:
3516                                         state = "disabled";
3517                                         break;
3518                                 case ETHTOOL_C33_PSE_ADMIN_STATE_ENABLED:
3519                                         state = "enabled";
3520                                         break;
3521                                 }
3522                                 blobmsg_add_string(b, "c33-admin-state", state);
3523                         }
3524 
3525                         if (pse_data.c33_pw_status) {
3526                                 const char *status = "unknown";
3527                                 switch (pse_data.c33_pw_status) {
3528                                 case ETHTOOL_C33_PSE_PW_D_STATUS_DISABLED:
3529                                         status = "disabled";
3530                                         break;
3531                                 case ETHTOOL_C33_PSE_PW_D_STATUS_SEARCHING:
3532                                         status = "searching";
3533                                         break;
3534                                 case ETHTOOL_C33_PSE_PW_D_STATUS_DELIVERING:
3535                                         status = "delivering";
3536                                         break;
3537                                 case ETHTOOL_C33_PSE_PW_D_STATUS_TEST:
3538                                         status = "test";
3539                                         break;
3540                                 case ETHTOOL_C33_PSE_PW_D_STATUS_FAULT:
3541                                         status = "fault";
3542                                         break;
3543                                 case ETHTOOL_C33_PSE_PW_D_STATUS_OTHERFAULT:
3544                                         status = "otherfault";
3545                                         break;
3546                                 }
3547                                 blobmsg_add_string(b, "c33-power-status", status);
3548                         }
3549 
3550                         if (pse_data.c33_pw_class)
3551                                 blobmsg_add_u32(b, "c33-power-class", pse_data.c33_pw_class);
3552 
3553                         if (pse_data.c33_actual_pw)
3554                                 blobmsg_add_u32(b, "c33-actual-power", pse_data.c33_actual_pw);
3555 
3556                         if (pse_data.c33_avail_pw_limit)
3557                                 blobmsg_add_u32(b, "c33-available-power-limit", pse_data.c33_avail_pw_limit);
3558 
3559                         /* PoDL (Power over Data Line) status */
3560                         if (pse_data.podl_admin_state) {
3561                                 const char *state = "unknown";
3562                                 switch (pse_data.podl_admin_state) {
3563                                 case ETHTOOL_PODL_PSE_ADMIN_STATE_DISABLED:
3564                                         state = "disabled";
3565                                         break;
3566                                 case ETHTOOL_PODL_PSE_ADMIN_STATE_ENABLED:
3567                                         state = "enabled";
3568                                         break;
3569                                 }
3570                                 blobmsg_add_string(b, "podl-admin-state", state);
3571                         }
3572 
3573                         if (pse_data.podl_pw_status) {
3574                                 const char *status = "unknown";
3575                                 switch (pse_data.podl_pw_status) {
3576                                 case ETHTOOL_PODL_PSE_PW_D_STATUS_DISABLED:
3577                                         status = "disabled";
3578                                         break;
3579                                 case ETHTOOL_PODL_PSE_PW_D_STATUS_SEARCHING:
3580                                         status = "searching";
3581                                         break;
3582                                 case ETHTOOL_PODL_PSE_PW_D_STATUS_DELIVERING:
3583                                         status = "delivering";
3584                                         break;
3585                                 case ETHTOOL_PODL_PSE_PW_D_STATUS_SLEEP:
3586                                         status = "sleep";
3587                                         break;
3588                                 case ETHTOOL_PODL_PSE_PW_D_STATUS_IDLE:
3589                                         status = "idle";
3590                                         break;
3591                                 case ETHTOOL_PODL_PSE_PW_D_STATUS_ERROR:
3592                                         status = "error";
3593                                         break;
3594                                 }
3595                                 blobmsg_add_string(b, "podl-power-status", status);
3596                         }
3597 
3598                         /* Priority settings */
3599                         if (pse_data.pse_prio_max)
3600                                 blobmsg_add_u32(b, "priority-max", pse_data.pse_prio_max);
3601 
3602                         if (pse_data.pse_prio)
3603                                 blobmsg_add_u32(b, "priority", pse_data.pse_prio);
3604 
3605                         blobmsg_close_table(b, pse_tbl);
3606                 }
3607         }
3608 
3609         return 0;
3610 }
3611 
3612 int
3613 system_if_dump_stats(struct device *dev, struct blob_buf *b)
3614 {
3615         const char *const counters[] = {
3616                 "collisions",     "rx_frame_errors",   "tx_compressed",
3617                 "multicast",      "rx_length_errors",  "tx_dropped",
3618                 "rx_bytes",       "rx_missed_errors",  "tx_errors",
3619                 "rx_compressed",  "rx_over_errors",    "tx_fifo_errors",
3620                 "rx_crc_errors",  "rx_packets",        "tx_heartbeat_errors",
3621                 "rx_dropped",     "tx_aborted_errors", "tx_packets",
3622                 "rx_errors",      "tx_bytes",          "tx_window_errors",
3623                 "rx_fifo_errors", "tx_carrier_errors",
3624         };
3625         int stats_dir;
3626         size_t i;
3627         uint64_t val = 0;
3628 
3629         stats_dir = open(dev_sysfs_path(dev->ifname, "statistics"), O_DIRECTORY);
3630         if (stats_dir < 0)
3631                 return -1;
3632 
3633         for (i = 0; i < ARRAY_SIZE(counters); i++)
3634                 if (read_uint64_file(stats_dir, counters[i], &val))
3635                         blobmsg_add_u64(b, counters[i], val);
3636 
3637         close(stats_dir);
3638         return 0;
3639 }
3640 
3641 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
3642 {
3643         bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
3644         int alen = v4 ? 4 : 16;
3645         unsigned int flags = 0;
3646         struct ifaddrmsg ifa = {
3647                 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
3648                 .ifa_prefixlen = addr->mask,
3649                 .ifa_index = dev->ifindex,
3650         };
3651 
3652         struct nl_msg *msg;
3653         if (cmd == RTM_NEWADDR)
3654                 flags |= NLM_F_CREATE | NLM_F_REPLACE;
3655 
3656         msg = nlmsg_alloc_simple(cmd, flags);
3657         if (!msg)
3658                 return -1;
3659 
3660         nlmsg_append(msg, &ifa, sizeof(ifa), 0);
3661         nla_put(msg, IFA_LOCAL, alen, &addr->addr);
3662         if (v4) {
3663                 if (addr->broadcast)
3664                         nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
3665                 if (addr->point_to_point)
3666                         nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
3667         } else {
3668                 time_t now = system_get_rtime();
3669                 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
3670 
3671                 if (addr->preferred_until) {
3672                         int64_t preferred = addr->preferred_until - now;
3673                         if (preferred < 0)
3674                                 preferred = 0;
3675                         else if (preferred > UINT32_MAX)
3676                                 preferred = UINT32_MAX;
3677 
3678                         cinfo.ifa_prefered = preferred;
3679                 }
3680 
3681                 if (addr->valid_until) {
3682                         int64_t valid = addr->valid_until - now;
3683                         if (valid <= 0) {
3684                                 nlmsg_free(msg);
3685                                 return -1;
3686                         }
3687                         else if (valid > UINT32_MAX)
3688                                 valid = UINT32_MAX;
3689 
3690                         cinfo.ifa_valid = valid;
3691                 }
3692 
3693                 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
3694 
3695                 if (cmd == RTM_NEWADDR && (addr->flags & DEVADDR_OFFLINK))
3696                         nla_put_u32(msg, IFA_FLAGS, IFA_F_NOPREFIXROUTE);
3697         }
3698 
3699         return system_rtnl_call(msg);
3700 }
3701 
3702 int system_add_address(struct device *dev, struct device_addr *addr)
3703 {
3704         return system_addr(dev, addr, RTM_NEWADDR);
3705 }
3706 
3707 int system_del_address(struct device *dev, struct device_addr *addr)
3708 {
3709         return system_addr(dev, addr, RTM_DELADDR);
3710 }
3711 
3712 static int system_neigh(struct device *dev, struct device_neighbor *neighbor, int cmd)
3713 {
3714         int alen = ((neighbor->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
3715         unsigned int flags = 0;
3716         struct ndmsg ndm = {
3717                 .ndm_family = (alen == 4) ? AF_INET : AF_INET6,
3718                 .ndm_ifindex = dev->ifindex,
3719                 .ndm_state = NUD_PERMANENT,
3720                 .ndm_flags = (neighbor->proxy ? NTF_PROXY : 0) | (neighbor->router ? NTF_ROUTER : 0),
3721         };
3722         struct nl_msg *msg;
3723 
3724         if (cmd == RTM_NEWNEIGH)
3725                 flags |= NLM_F_CREATE | NLM_F_REPLACE;
3726 
3727         msg = nlmsg_alloc_simple(cmd, flags);
3728 
3729         if (!msg)
3730                 return -1;
3731 
3732         nlmsg_append(msg, &ndm, sizeof(ndm), 0);
3733 
3734         nla_put(msg, NDA_DST, alen, &neighbor->addr);
3735         if (neighbor->flags & DEVNEIGH_MAC)
3736                 nla_put(msg, NDA_LLADDR, sizeof(neighbor->macaddr), &neighbor->macaddr);
3737 
3738 
3739         return system_rtnl_call(msg);
3740 }
3741 
3742 int system_add_neighbor(struct device *dev, struct device_neighbor *neighbor)
3743 {
3744         return system_neigh(dev, neighbor, RTM_NEWNEIGH);
3745 }
3746 
3747 int system_del_neighbor(struct device *dev, struct device_neighbor *neighbor)
3748 {
3749         return system_neigh(dev, neighbor, RTM_DELNEIGH);
3750 }
3751 
3752 static int system_rt(struct device *dev, struct device_route *route, int cmd)
3753 {
3754         int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
3755         bool have_gw;
3756         unsigned int flags = 0;
3757 
3758         if (alen == 4)
3759                 have_gw = !!route->nexthop.in.s_addr;
3760         else
3761                 have_gw = route->nexthop.in6.s6_addr32[0] ||
3762                         route->nexthop.in6.s6_addr32[1] ||
3763                         route->nexthop.in6.s6_addr32[2] ||
3764                         route->nexthop.in6.s6_addr32[3];
3765 
3766         unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
3767                         ? route->table : RT_TABLE_MAIN;
3768 
3769         struct rtmsg rtm = {
3770                 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
3771                 .rtm_dst_len = route->mask,
3772                 .rtm_src_len = route->sourcemask,
3773                 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
3774                 .rtm_protocol = (route->flags & DEVROUTE_PROTO) ? route->proto : RTPROT_STATIC,
3775                 .rtm_scope = RT_SCOPE_NOWHERE,
3776                 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
3777                 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
3778         };
3779         struct nl_msg *msg;
3780 
3781         if (cmd == RTM_NEWROUTE) {
3782                 flags |= NLM_F_CREATE | NLM_F_REPLACE;
3783 
3784                 if (!dev) { /* Add null-route */
3785                         rtm.rtm_scope = RT_SCOPE_UNIVERSE;
3786                         rtm.rtm_type = RTN_UNREACHABLE;
3787                 }
3788                 else
3789                         rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
3790         }
3791 
3792         if (route->flags & DEVROUTE_TYPE) {
3793                 rtm.rtm_type = route->type;
3794                 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
3795                         if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
3796                             rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
3797                                 rtm.rtm_table = RT_TABLE_LOCAL;
3798                 }
3799 
3800                 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT) {
3801                         rtm.rtm_scope = RT_SCOPE_HOST;
3802                 } else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
3803                                 rtm.rtm_type == RTN_ANYCAST) {
3804                         rtm.rtm_scope = RT_SCOPE_LINK;
3805                 } else if (rtm.rtm_type == RTN_BLACKHOLE || rtm.rtm_type == RTN_UNREACHABLE ||
3806                                 rtm.rtm_type == RTN_PROHIBIT || rtm.rtm_type == RTN_FAILED_POLICY ||
3807                                 rtm.rtm_type == RTN_THROW) {
3808                         rtm.rtm_scope = RT_SCOPE_UNIVERSE;
3809                         dev = NULL;
3810                 }
3811         }
3812 
3813         if (route->flags & DEVROUTE_NODEV)
3814                 dev = NULL;
3815 
3816         msg = nlmsg_alloc_simple(cmd, flags);
3817         if (!msg)
3818                 return -1;
3819 
3820         nlmsg_append(msg, &rtm, sizeof(rtm), 0);
3821 
3822         if (route->mask)
3823                 nla_put(msg, RTA_DST, alen, &route->addr);
3824 
3825         if (route->sourcemask) {
3826                 if (rtm.rtm_family == AF_INET)
3827                         nla_put(msg, RTA_PREFSRC, alen, &route->source);
3828                 else
3829                         nla_put(msg, RTA_SRC, alen, &route->source);
3830         }
3831 
3832         if (route->metric > 0)
3833                 nla_put_u32(msg, RTA_PRIORITY, route->metric);
3834 
3835         if (have_gw)
3836                 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
3837 
3838         if (dev)
3839                 nla_put_u32(msg, RTA_OIF, dev->ifindex);
3840 
3841         if (table >= 256)
3842                 nla_put_u32(msg, RTA_TABLE, table);
3843 
3844         if (route->flags & DEVROUTE_MTU) {
3845                 struct nlattr *metrics;
3846 
3847                 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
3848                         goto nla_put_failure;
3849 
3850                 nla_put_u32(msg, RTAX_MTU, route->mtu);
3851 
3852                 nla_nest_end(msg, metrics);
3853         }
3854 
3855         return system_rtnl_call(msg);
3856 
3857 nla_put_failure:
3858         nlmsg_free(msg);
3859         return -ENOMEM;
3860 }
3861 
3862 int system_add_route(struct device *dev, struct device_route *route)
3863 {
3864         return system_rt(dev, route, RTM_NEWROUTE);
3865 }
3866 
3867 int system_del_route(struct device *dev, struct device_route *route)
3868 {
3869         return system_rt(dev, route, RTM_DELROUTE);
3870 }
3871 
3872 int system_flush_routes(void)
3873 {
3874         const char *names[] = { "ipv4", "ipv6" };
3875         size_t i;
3876         int fd;
3877 
3878         for (i = 0; i < ARRAY_SIZE(names); i++) {
3879                 snprintf(dev_buf, sizeof(dev_buf), "%s/sys/net/%s/route/flush", proc_path, names[i]);
3880                 fd = open(dev_buf, O_WRONLY);
3881                 if (fd < 0)
3882                         continue;
3883 
3884                 if (write(fd, "-1", 2)) {}
3885                 close(fd);
3886         }
3887         return 0;
3888 }
3889 
3890 bool system_resolve_rt_type(const char *type, unsigned int *id)
3891 {
3892         return system_rtn_aton(type, id);
3893 }
3894 
3895 bool system_resolve_rt_proto(const char *type, unsigned int *id)
3896 {
3897         FILE *f;
3898         char *e, buf[128];
3899         unsigned int n, proto = 256;
3900         n = strtoul(type, &e, 0);
3901         if (!*e && e != type)
3902                 proto = n;
3903         else if (!strcmp(type, "unspec"))
3904                 proto = RTPROT_UNSPEC;
3905         else if (!strcmp(type, "kernel"))
3906                 proto = RTPROT_KERNEL;
3907         else if (!strcmp(type, "boot"))
3908                 proto = RTPROT_BOOT;
3909         else if (!strcmp(type, "static"))
3910                 proto = RTPROT_STATIC;
3911         else if ((f = fopen("/etc/iproute2/rt_protos", "r")) != NULL) {
3912                 while (fgets(buf, sizeof(buf) - 1, f) != NULL) {
3913                         if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
3914                                 continue;
3915 
3916                         n = strtoul(e, NULL, 10);
3917                         e = strtok(NULL, " \t\n");
3918 
3919                         if (e && !strcmp(e, type)) {
3920                                 proto = n;
3921                                 break;
3922                         }
3923                 }
3924                 fclose(f);
3925         }
3926 
3927         if (proto > 255)
3928                 return false;
3929 
3930         *id = proto;
3931         return true;
3932 }
3933 
3934 bool system_resolve_rt_table(const char *name, unsigned int *id)
3935 {
3936         FILE *f;
3937         char *e, buf[128];
3938         unsigned int n, table = RT_TABLE_UNSPEC;
3939 
3940         /* first try to parse table as number */
3941         if ((n = strtoul(name, &e, 0)) > 0 && !*e)
3942                 table = n;
3943 
3944         /* handle well known aliases */
3945         else if (!strcmp(name, "default"))
3946                 table = RT_TABLE_DEFAULT;
3947         else if (!strcmp(name, "main"))
3948                 table = RT_TABLE_MAIN;
3949         else if (!strcmp(name, "local"))
3950                 table = RT_TABLE_LOCAL;
3951 
3952         /* try to look up name in /etc/iproute2/rt_tables */
3953         else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
3954         {
3955                 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
3956                 {
3957                         if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
3958                                 continue;
3959 
3960                         n = strtoul(e, NULL, 10);
3961                         e = strtok(NULL, " \t\n");
3962 
3963                         if (e && !strcmp(e, name))
3964                         {
3965                                 table = n;
3966                                 break;
3967                         }
3968                 }
3969 
3970                 fclose(f);
3971         }
3972 
3973         if (table == RT_TABLE_UNSPEC)
3974                 return false;
3975 
3976         *id = table;
3977         return true;
3978 }
3979 
3980 bool system_is_default_rt_table(unsigned int id)
3981 {
3982         return (id == RT_TABLE_MAIN);
3983 }
3984 
3985 bool system_resolve_rpfilter(const char *filter, unsigned int *id)
3986 {
3987         char *e;
3988         unsigned int n;
3989 
3990         if (!strcmp(filter, "strict"))
3991                 n = 1;
3992         else if (!strcmp(filter, "loose"))
3993                 n = 2;
3994         else {
3995                 n = strtoul(filter, &e, 0);
3996                 if (*e || e == filter || n > 2)
3997                         return false;
3998         }
3999 
4000         *id = n;
4001         return true;
4002 }
4003 
4004 static int system_iprule(struct iprule *rule, int cmd)
4005 {
4006         int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
4007 
4008         struct nl_msg *msg;
4009         struct rtmsg rtm = {
4010                 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
4011                 .rtm_protocol = RTPROT_STATIC,
4012                 .rtm_scope = RT_SCOPE_UNIVERSE,
4013                 .rtm_table = RT_TABLE_UNSPEC,
4014                 .rtm_type = RTN_UNSPEC,
4015                 .rtm_flags = 0,
4016         };
4017 
4018         if (cmd == RTM_NEWRULE)
4019                 rtm.rtm_type = RTN_UNICAST;
4020 
4021         if (rule->invert)
4022                 rtm.rtm_flags |= FIB_RULE_INVERT;
4023 
4024         if (rule->flags & IPRULE_SRC)
4025                 rtm.rtm_src_len = rule->src_mask;
4026 
4027         if (rule->flags & IPRULE_DEST)
4028                 rtm.rtm_dst_len = rule->dest_mask;
4029 
4030         if (rule->flags & IPRULE_TOS)
4031                 rtm.rtm_tos = rule->tos;
4032 
4033         if (rule->flags & IPRULE_LOOKUP) {
4034                 if (rule->lookup < 256)
4035                         rtm.rtm_table = rule->lookup;
4036         }
4037 
4038         if (rule->flags & IPRULE_ACTION)
4039                 rtm.rtm_type = rule->action;
4040         else if (rule->flags & IPRULE_GOTO)
4041                 rtm.rtm_type = FR_ACT_GOTO;
4042         else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
4043                 rtm.rtm_type = FR_ACT_NOP;
4044 
4045         msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
4046 
4047         if (!msg)
4048                 return -1;
4049 
4050         nlmsg_append(msg, &rtm, sizeof(rtm), 0);
4051 
4052         if (rule->flags & IPRULE_IN)
4053                 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
4054 
4055         if (rule->flags & IPRULE_OUT)
4056                 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
4057 
4058         if (rule->flags & IPRULE_SRC)
4059                 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
4060 
4061         if (rule->flags & IPRULE_DEST)
4062                 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
4063 
4064         if (rule->flags & IPRULE_PRIORITY)
4065                 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
4066         else if (cmd == RTM_NEWRULE)
4067                 nla_put_u32(msg, FRA_PRIORITY, rule->order);
4068 
4069         if (rule->flags & IPRULE_FWMARK)
4070                 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
4071 
4072         if (rule->flags & IPRULE_FWMASK)
4073                 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
4074 
4075         if (rule->flags & IPRULE_LOOKUP) {
4076                 if (rule->lookup >= 256)
4077                         nla_put_u32(msg, FRA_TABLE, rule->lookup);
4078         }
4079 
4080         if (rule->flags & IPRULE_SUP_PREFIXLEN)
4081                 nla_put_u32(msg, FRA_SUPPRESS_PREFIXLEN, rule->sup_prefixlen);
4082 
4083         if (rule->flags & IPRULE_UIDRANGE) {
4084                 struct fib_rule_uid_range uidrange = {
4085                         .start = rule->uidrange_start,
4086                         .end = rule->uidrange_end
4087                 };
4088 
4089                 nla_put(msg, FRA_UID_RANGE, sizeof(uidrange), &uidrange);
4090         }
4091 
4092         if (rule->flags & IPRULE_GOTO)
4093                 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
4094 
4095         if (rule->flags & IPRULE_IPPROTO)
4096                 nla_put_u8(msg, FRA_IP_PROTO, rule->ipproto);
4097 
4098         if (rule->flags & IPRULE_SPORT) {
4099                 struct fib_rule_port_range sportrange = {
4100                         .start = rule->sport_start,
4101                         .end = rule->sport_end
4102                 };
4103 
4104                 nla_put(msg, FRA_SPORT_RANGE, sizeof(sportrange), &sportrange);
4105         }
4106 
4107         if (rule->flags & IPRULE_DPORT) {
4108                 struct fib_rule_port_range dportrange = {
4109                         .start = rule->dport_start,
4110                         .end = rule->dport_end
4111                 };
4112 
4113                 nla_put(msg, FRA_DPORT_RANGE, sizeof(dportrange), &dportrange);
4114         }
4115 
4116         return system_rtnl_call(msg);
4117 }
4118 
4119 int system_add_iprule(struct iprule *rule)
4120 {
4121         return system_iprule(rule, RTM_NEWRULE);
4122 }
4123 
4124 int system_del_iprule(struct iprule *rule)
4125 {
4126         return system_iprule(rule, RTM_DELRULE);
4127 }
4128 
4129 int system_flush_iprules(void)
4130 {
4131         int rv = 0;
4132         struct iprule rule;
4133 
4134         system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
4135         system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
4136 
4137         memset(&rule, 0, sizeof(rule));
4138 
4139 
4140         rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
4141 
4142         rule.priority = 0;
4143         rule.lookup = RT_TABLE_LOCAL;
4144         rv |= system_iprule(&rule, RTM_NEWRULE);
4145 
4146         rule.priority = 32766;
4147         rule.lookup = RT_TABLE_MAIN;
4148         rv |= system_iprule(&rule, RTM_NEWRULE);
4149 
4150         rule.priority = 32767;
4151         rule.lookup = RT_TABLE_DEFAULT;
4152         rv |= system_iprule(&rule, RTM_NEWRULE);
4153 
4154 
4155         rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
4156 
4157         rule.priority = 0;
4158         rule.lookup = RT_TABLE_LOCAL;
4159         rv |= system_iprule(&rule, RTM_NEWRULE);
4160 
4161         rule.priority = 32766;
4162         rule.lookup = RT_TABLE_MAIN;
4163         rv |= system_iprule(&rule, RTM_NEWRULE);
4164 
4165         return rv;
4166 }
4167 
4168 bool system_resolve_iprule_action(const char *action, unsigned int *id)
4169 {
4170         return system_rtn_aton(action, id);
4171 }
4172 
4173 bool system_resolve_iprule_ipproto(const char *name, unsigned int *id)
4174 {
4175         char *e;
4176         struct protoent *ent;
4177         unsigned int n, ipproto = 0;
4178 
4179         if ((n = strtoul(name, &e, 0)) > 0 && *e == '\0')
4180                 ipproto = n;
4181         else {
4182                 ent = getprotobyname(name);
4183 
4184                 if (ent)
4185                         ipproto = ent->p_proto;
4186                 else
4187                         return false;
4188         }
4189 
4190         *id = ipproto;
4191         return true;
4192 }
4193 
4194 time_t system_get_rtime(void)
4195 {
4196         struct timespec ts;
4197         struct timeval tv;
4198 
4199         if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
4200                 return ts.tv_sec;
4201 
4202         if (gettimeofday(&tv, NULL) == 0)
4203                 return tv.tv_sec;
4204 
4205         return 0;
4206 }
4207 
4208 #ifndef IP_DF
4209 #define IP_DF       0x4000
4210 #endif
4211 
4212 static int tunnel_ioctl(const char *name, int cmd, void *p)
4213 {
4214         struct ifreq ifr;
4215 
4216         memset(&ifr, 0, sizeof(ifr));
4217         strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name) - 1);
4218         ifr.ifr_ifru.ifru_data = p;
4219         return ioctl(sock_ioctl, cmd, &ifr);
4220 }
4221 
4222 #ifdef IFLA_IPTUN_MAX
4223 static int system_add_ip6_tunnel(const char *name, const unsigned int link,
4224                                  struct blob_attr **tb)
4225 {
4226         struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
4227                                 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
4228         struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
4229         struct blob_attr *cur;
4230         int ret = 0, ttl = 0;
4231 
4232         if (!nlm)
4233                 return -1;
4234 
4235         nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
4236         nla_put_string(nlm, IFLA_IFNAME, name);
4237 
4238         if (link)
4239                 nla_put_u32(nlm, IFLA_LINK, link);
4240 
4241         struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
4242         if (!linkinfo) {
4243                 ret = -ENOMEM;
4244                 goto failure;
4245         }
4246 
4247         nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
4248         struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
4249         if (!infodata) {
4250                 ret = -ENOMEM;
4251                 goto failure;
4252         }
4253 
4254         if (link)
4255                 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
4256 
4257         if ((cur = tb[TUNNEL_ATTR_TTL]))
4258                 ttl = blobmsg_get_u32(cur);
4259 
4260         nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
4261         nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
4262 
4263         struct in6_addr in6buf;
4264         if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
4265                 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
4266                         ret = -EINVAL;
4267                         goto failure;
4268                 }
4269                 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
4270         }
4271 
4272         if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
4273                 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
4274                         ret = -EINVAL;
4275                         goto failure;
4276                 }
4277                 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
4278         }
4279 
4280         if ((cur = tb[TUNNEL_ATTR_DATA])) {
4281                 struct blob_attr *tb_data[__IPIP6_DATA_ATTR_MAX];
4282                 uint32_t tun_flags = IP6_TNL_F_IGN_ENCAP_LIMIT;
4283 
4284                 blobmsg_parse_attr(ipip6_data_attr_list.params, __IPIP6_DATA_ATTR_MAX,
4285                                    tb_data, cur);
4286 
4287                 if ((cur = tb_data[IPIP6_DATA_ENCAPLIMIT])) {
4288                         char *str = blobmsg_get_string(cur);
4289 
4290                         if (strcmp(str, "ignore")) {
4291                                 char *e;
4292                                 unsigned encap_limit = strtoul(str, &e, 0);
4293 
4294                                 if (e == str || *e || encap_limit > 255) {
4295                                         ret = -EINVAL;
4296                                         goto failure;
4297                                 }
4298 
4299                                 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, encap_limit);
4300                                 tun_flags &= ~IP6_TNL_F_IGN_ENCAP_LIMIT;
4301                         }
4302                 }
4303 
4304 #ifdef IFLA_IPTUN_FMR_MAX
4305                 if ((cur = tb_data[IPIP6_DATA_FMRS])) {
4306                         struct blob_attr *rcur;
4307                         unsigned rrem, fmrcnt = 0;
4308                         struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
4309 
4310                         if (!fmrs) {
4311                                 ret = -ENOMEM;
4312                                 goto failure;
4313                         }
4314 
4315                         blobmsg_for_each_attr(rcur, cur, rrem) {
4316                                 struct blob_attr *tb_fmr[__FMR_DATA_ATTR_MAX], *tb_cur;
4317                                 struct in6_addr ip6prefix;
4318                                 struct in_addr ip4prefix;
4319                                 unsigned ip4len, ip6len, ealen, offset;
4320 
4321                                 blobmsg_parse_attr(fmr_data_attr_list.params, __FMR_DATA_ATTR_MAX,
4322                                                    tb_fmr, rcur);
4323 
4324                                 if (!(tb_cur = tb_fmr[FMR_DATA_PREFIX6]) ||
4325                                                 !parse_ip_and_netmask(AF_INET6,
4326                                                         blobmsg_data(tb_cur), &ip6prefix,
4327                                                         &ip6len)) {
4328                                         ret = -EINVAL;
4329                                         goto failure;
4330                                 }
4331 
4332                                 if (!(tb_cur = tb_fmr[FMR_DATA_PREFIX4]) ||
4333                                                 !parse_ip_and_netmask(AF_INET,
4334                                                         blobmsg_data(tb_cur), &ip4prefix,
4335                                                         &ip4len)) {
4336                                         ret = -EINVAL;
4337                                         goto failure;
4338                                 }
4339 
4340                                 if (!(tb_cur = tb_fmr[FMR_DATA_EALEN])) {
4341                                         ret = -EINVAL;
4342                                         goto failure;
4343                                 }
4344                                 ealen = blobmsg_get_u32(tb_cur);
4345 
4346                                 if (!(tb_cur = tb_fmr[FMR_DATA_OFFSET])) {
4347                                         ret = -EINVAL;
4348                                         goto failure;
4349                                 }
4350                                 offset = blobmsg_get_u32(tb_cur);
4351 
4352                                 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
4353                                 if (!rule) {
4354                                         ret = -ENOMEM;
4355                                         goto failure;
4356                                 }
4357 
4358                                 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
4359                                 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
4360                                 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
4361                                 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
4362                                 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
4363                                 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
4364 
4365                                 nla_nest_end(nlm, rule);
4366                         }
4367 
4368                         nla_nest_end(nlm, fmrs);
4369                 }
4370 #endif
4371                 if (tun_flags)
4372                         nla_put_u32(nlm, IFLA_IPTUN_FLAGS, tun_flags);
4373         }
4374 
4375         nla_nest_end(nlm, infodata);
4376         nla_nest_end(nlm, linkinfo);
4377 
4378         return system_rtnl_call(nlm);
4379 
4380 failure:
4381         nlmsg_free(nlm);
4382         return ret;
4383 }
4384 #endif
4385 
4386 #ifdef IFLA_IPTUN_MAX
4387 #define IP6_FLOWINFO_TCLASS     htonl(0x0FF00000)
4388 static int system_add_gre_tunnel(const char *name, const char *kind,
4389                                  const unsigned int link, struct blob_attr **tb, bool v6)
4390 {
4391         struct nl_msg *nlm;
4392         struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
4393         struct blob_attr *cur;
4394         uint32_t ikey = 0, okey = 0, flowinfo = 0, flags6 = IP6_TNL_F_IGN_ENCAP_LIMIT;
4395         uint16_t iflags = 0, oflags = 0;
4396         uint8_t tos = 0;
4397         int ret = 0, ttl = 0;
4398         unsigned encap_limit = 0;
4399 
4400         nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
4401         if (!nlm)
4402                 return -1;
4403 
4404         nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
4405         nla_put_string(nlm, IFLA_IFNAME, name);
4406 
4407         struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
4408         if (!linkinfo) {
4409                 ret = -ENOMEM;
4410                 goto failure;
4411         }
4412 
4413         nla_put_string(nlm, IFLA_INFO_KIND, kind);
4414         struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
4415         if (!infodata) {
4416                 ret = -ENOMEM;
4417                 goto failure;
4418         }
4419 
4420         if (link)
4421                 nla_put_u32(nlm, IFLA_GRE_LINK, link);
4422 
4423         if ((cur = tb[TUNNEL_ATTR_TTL]))
4424                 ttl = blobmsg_get_u32(cur);
4425 
4426         if ((cur = tb[TUNNEL_ATTR_TOS])) {
4427                 char *str = blobmsg_get_string(cur);
4428                 if (strcmp(str, "inherit")) {
4429                         unsigned uval;
4430 
4431                         if (!system_tos_aton(str, &uval)) {
4432                                 ret = -EINVAL;
4433                                 goto failure;
4434                         }
4435 
4436                         if (v6)
4437                                 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
4438                         else
4439                                 tos = uval;
4440                 } else {
4441                         if (v6)
4442                                 flags6 |= IP6_TNL_F_USE_ORIG_TCLASS;
4443                         else
4444                                 tos = 1;
4445                 }
4446         }
4447 
4448         if ((cur = tb[TUNNEL_ATTR_DATA])) {
4449                 struct blob_attr *tb_data[__GRE_DATA_ATTR_MAX];
4450 
4451                 blobmsg_parse_attr(gre_data_attr_list.params, __GRE_DATA_ATTR_MAX,
4452                                    tb_data, cur);
4453 
4454                 if ((cur = tb_data[GRE_DATA_IKEY])) {
4455                         if ((ikey = blobmsg_get_u32(cur)))
4456                                 iflags |= GRE_KEY;
4457                 }
4458 
4459                 if ((cur = tb_data[GRE_DATA_OKEY])) {
4460                         if ((okey = blobmsg_get_u32(cur)))
4461                                 oflags |= GRE_KEY;
4462                 }
4463 
4464                 if ((cur = tb_data[GRE_DATA_ICSUM])) {
4465                         if (blobmsg_get_bool(cur))
4466                                 iflags |= GRE_CSUM;
4467                 }
4468 
4469                 if ((cur = tb_data[GRE_DATA_OCSUM])) {
4470                         if (blobmsg_get_bool(cur))
4471                                 oflags |= GRE_CSUM;
4472                 }
4473 
4474                 if ((cur = tb_data[GRE_DATA_ISEQNO])) {
4475                         if (blobmsg_get_bool(cur))
4476                                 iflags |= GRE_SEQ;
4477                 }
4478 
4479                 if ((cur = tb_data[GRE_DATA_OSEQNO])) {
4480                         if (blobmsg_get_bool(cur))
4481                                 oflags |= GRE_SEQ;
4482                 }
4483 
4484                 if ((cur = tb_data[GRE_DATA_ENCAPLIMIT])) {
4485                         char *str = blobmsg_get_string(cur);
4486 
4487                         if (strcmp(str, "ignore")) {
4488                                 char *e;
4489 
4490                                 encap_limit = strtoul(str, &e, 0);
4491 
4492                                 if (e == str || *e || encap_limit > 255) {
4493                                         ret = -EINVAL;
4494                                         goto failure;
4495                                 }
4496 
4497                                 flags6 &= ~IP6_TNL_F_IGN_ENCAP_LIMIT;
4498                         }
4499                 }
4500         }
4501 
4502         if (v6) {
4503                 struct in6_addr in6buf;
4504                 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
4505                         if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
4506                                 ret = -EINVAL;
4507                                 goto failure;
4508                         }
4509                         nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
4510                 }
4511 
4512                 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
4513                         if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
4514                                 ret = -EINVAL;
4515                                 goto failure;
4516                         }
4517                         nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
4518                 }
4519 
4520                 if (!(flags6 & IP6_TNL_F_IGN_ENCAP_LIMIT))
4521                         nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, encap_limit);
4522 
4523                 if (flowinfo)
4524                         nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
4525 
4526                 if (flags6)
4527                         nla_put_u32(nlm, IFLA_GRE_FLAGS, flags6);
4528 
4529                 if (!ttl)
4530                         ttl = 64;
4531         } else {
4532                 struct in_addr inbuf;
4533                 bool set_df = true;
4534 
4535                 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
4536                         if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
4537                                 ret = -EINVAL;
4538                                 goto failure;
4539                         }
4540                         nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
4541                 }
4542 
4543                 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
4544                         if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
4545                                 ret = -EINVAL;
4546                                 goto failure;
4547                         }
4548                         nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
4549 
4550                         if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
4551                                 if (!okey) {
4552                                         okey = inbuf.s_addr;
4553                                         oflags |= GRE_KEY;
4554                                 }
4555 
4556                                 if (!ikey) {
4557                                         ikey = inbuf.s_addr;
4558                                         iflags |= GRE_KEY;
4559                                 }
4560                         }
4561                 }
4562 
4563                 if ((cur = tb[TUNNEL_ATTR_DF]))
4564                         set_df = blobmsg_get_bool(cur);
4565 
4566                 if (!set_df) {
4567                         /* ttl != 0 and nopmtudisc are incompatible */
4568                         if (ttl) {
4569                                 ret = -EINVAL;
4570                                 goto failure;
4571                         }
4572                 } else if (!ttl)
4573                         ttl = 64;
4574 
4575                 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
4576 
4577                 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
4578         }
4579 
4580         if (ttl)
4581                 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
4582 
4583         if (oflags)
4584                 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
4585 
4586         if (iflags)
4587                 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
4588 
4589         if (okey)
4590                 nla_put_u32(nlm, IFLA_GRE_OKEY, htonl(okey));
4591 
4592         if (ikey)
4593                 nla_put_u32(nlm, IFLA_GRE_IKEY, htonl(ikey));
4594 
4595         nla_nest_end(nlm, infodata);
4596         nla_nest_end(nlm, linkinfo);
4597 
4598         return system_rtnl_call(nlm);
4599 
4600 failure:
4601         nlmsg_free(nlm);
4602         return ret;
4603 }
4604 #endif
4605 
4606 #ifdef IFLA_VTI_MAX
4607 static int system_add_vti_tunnel(const char *name, const char *kind,
4608                                  const unsigned int link, struct blob_attr **tb, bool v6)
4609 {
4610         struct nl_msg *nlm;
4611         struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
4612         struct blob_attr *cur;
4613         int ret = 0;
4614 
4615         nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
4616         if (!nlm)
4617                 return -1;
4618 
4619         nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
4620         nla_put_string(nlm, IFLA_IFNAME, name);
4621 
4622         struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
4623         if (!linkinfo) {
4624                 ret = -ENOMEM;
4625                 goto failure;
4626         }
4627 
4628         nla_put_string(nlm, IFLA_INFO_KIND, kind);
4629         struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
4630         if (!infodata) {
4631                 ret = -ENOMEM;
4632                 goto failure;
4633         }
4634 
4635         if (link)
4636                 nla_put_u32(nlm, IFLA_VTI_LINK, link);
4637 
4638         if (v6) {
4639                 struct in6_addr in6buf;
4640                 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
4641                         if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
4642                                 ret = -EINVAL;
4643                                 goto failure;
4644                         }
4645                         nla_put(nlm, IFLA_VTI_LOCAL, sizeof(in6buf), &in6buf);
4646                 }
4647 
4648                 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
4649                         if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
4650                                 ret = -EINVAL;
4651                                 goto failure;
4652                         }
4653                         nla_put(nlm, IFLA_VTI_REMOTE, sizeof(in6buf), &in6buf);
4654                 }
4655 
4656         } else {
4657                 struct in_addr inbuf;
4658 
4659                 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
4660                         if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
4661                                 ret = -EINVAL;
4662                                 goto failure;
4663                         }
4664                         nla_put(nlm, IFLA_VTI_LOCAL, sizeof(inbuf), &inbuf);
4665                 }
4666 
4667                 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
4668                         if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
4669                                 ret = -EINVAL;
4670                                 goto failure;
4671                         }
4672                         nla_put(nlm, IFLA_VTI_REMOTE, sizeof(inbuf), &inbuf);
4673                 }
4674 
4675         }
4676 
4677         if ((cur = tb[TUNNEL_ATTR_DATA])) {
4678                 struct blob_attr *tb_data[__VTI_DATA_ATTR_MAX];
4679                 uint32_t ikey = 0, okey = 0;
4680 
4681                 blobmsg_parse_attr(vti_data_attr_list.params, __VTI_DATA_ATTR_MAX,
4682                                    tb_data, cur);
4683 
4684                 if ((cur = tb_data[VTI_DATA_IKEY])) {
4685                         if ((ikey = blobmsg_get_u32(cur)))
4686                                 nla_put_u32(nlm, IFLA_VTI_IKEY, htonl(ikey));
4687                 }
4688 
4689                 if ((cur = tb_data[VTI_DATA_OKEY])) {
4690                         if ((okey = blobmsg_get_u32(cur)))
4691                                 nla_put_u32(nlm, IFLA_VTI_OKEY, htonl(okey));
4692                 }
4693         }
4694 
4695         nla_nest_end(nlm, infodata);
4696         nla_nest_end(nlm, linkinfo);
4697 
4698         return system_rtnl_call(nlm);
4699 
4700 failure:
4701         nlmsg_free(nlm);
4702         return ret;
4703 }
4704 #endif
4705 
4706 #ifdef IFLA_XFRM_MAX
4707 static int system_add_xfrm_tunnel(const char *name, const char *kind,
4708                                  const unsigned int link, struct blob_attr **tb)
4709 {
4710         struct nl_msg *nlm;
4711         struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
4712         struct blob_attr *cur;
4713         int ret = 0;
4714 
4715         nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
4716         if (!nlm)
4717                 return -1;
4718 
4719         nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
4720         nla_put_string(nlm, IFLA_IFNAME, name);
4721 
4722         struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
4723         if (!linkinfo) {
4724                 ret = -ENOMEM;
4725                 goto failure;
4726         }
4727 
4728         nla_put_string(nlm, IFLA_INFO_KIND, kind);
4729         struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
4730         if (!infodata) {
4731                 ret = -ENOMEM;
4732                 goto failure;
4733         }
4734 
4735         if (link)
4736                 nla_put_u32(nlm, IFLA_XFRM_LINK, link);
4737 
4738         if ((cur = tb[TUNNEL_ATTR_DATA])) {
4739                 struct blob_attr *tb_data[__XFRM_DATA_ATTR_MAX];
4740                 uint32_t if_id = 0;
4741 
4742                 blobmsg_parse_attr(xfrm_data_attr_list.params, __XFRM_DATA_ATTR_MAX,
4743                                    tb_data, cur);
4744 
4745                 if ((cur = tb_data[XFRM_DATA_IF_ID])) {
4746                         if ((if_id = blobmsg_get_u32(cur)))
4747                                 nla_put_u32(nlm, IFLA_XFRM_IF_ID, if_id);
4748                 }
4749 
4750         }
4751 
4752         nla_nest_end(nlm, infodata);
4753         nla_nest_end(nlm, linkinfo);
4754 
4755         return system_rtnl_call(nlm);
4756 
4757 failure:
4758         nlmsg_free(nlm);
4759         return ret;
4760 }
4761 #endif
4762 
4763 #ifdef IFLA_VXLAN_MAX
4764 static void system_vxlan_map_bool_attr(struct nl_msg *msg, struct blob_attr **tb_data, int attrtype, int vxlandatatype, bool invert) {
4765         struct blob_attr *cur;
4766         if ((cur = tb_data[vxlandatatype])) {
4767                 bool val = blobmsg_get_bool(cur);
4768                 if (invert)
4769                         val = !val;
4770 
4771                 if ((attrtype == IFLA_VXLAN_GBP) && val)
4772                         nla_put_flag(msg, attrtype);
4773                 else 
4774                         nla_put_u8(msg, attrtype, val);
4775 
4776         }
4777 }
4778 
4779 static int system_add_vxlan(const char *name, const unsigned int link, struct blob_attr **tb, bool v6)
4780 {
4781         struct blob_attr *tb_data[__VXLAN_DATA_ATTR_MAX];
4782         struct nl_msg *msg;
4783         struct nlattr *linkinfo, *data;
4784         struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
4785         struct blob_attr *cur;
4786         int ret = 0;
4787 
4788         if ((cur = tb[TUNNEL_ATTR_DATA]))
4789                 blobmsg_parse_attr(vxlan_data_attr_list.params, __VXLAN_DATA_ATTR_MAX,
4790                                    tb_data, cur);
4791         else
4792                 return -EINVAL;
4793 
4794         msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
4795 
4796         if (!msg)
4797                 return -1;
4798 
4799         nlmsg_append(msg, &iim, sizeof(iim), 0);
4800 
4801         nla_put_string(msg, IFLA_IFNAME, name);
4802 
4803         if ((cur = tb_data[VXLAN_DATA_ATTR_MACADDR])) {
4804                 struct ether_addr *ea = ether_aton(blobmsg_get_string(cur));
4805                 if (!ea) {
4806                         ret = -EINVAL;
4807                         goto failure;
4808                 }
4809 
4810                 nla_put(msg, IFLA_ADDRESS, ETH_ALEN, ea);
4811         }
4812 
4813         if ((cur = tb[TUNNEL_ATTR_MTU])) {
4814                 uint32_t mtu = blobmsg_get_u32(cur);
4815                 nla_put_u32(msg, IFLA_MTU, mtu);
4816         }
4817 
4818         if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO))) {
4819                 ret = -ENOMEM;
4820                 goto failure;
4821         }
4822 
4823         nla_put_string(msg, IFLA_INFO_KIND, "vxlan");
4824 
4825         if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) {
4826                 ret = -ENOMEM;
4827                 goto failure;
4828         }
4829 
4830         if (link)
4831                 nla_put_u32(msg, IFLA_VXLAN_LINK, link);
4832 
4833         if ((cur = tb_data[VXLAN_DATA_ATTR_ID])) {
4834                 uint32_t id = blobmsg_get_u32(cur);
4835                 if (id >= (1u << 24) - 1) {
4836                         ret = -EINVAL;
4837                         goto failure;
4838                 }
4839 
4840                 nla_put_u32(msg, IFLA_VXLAN_ID, id);
4841         }
4842 
4843         if (v6) {
4844                 struct in6_addr in6buf;
4845                 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
4846                         if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
4847                                 ret = -EINVAL;
4848                                 goto failure;
4849                         }
4850                         nla_put(msg, IFLA_VXLAN_LOCAL6, sizeof(in6buf), &in6buf);
4851                 }
4852 
4853                 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
4854                         if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
4855                                 ret = -EINVAL;
4856                                 goto failure;
4857                         }
4858                         nla_put(msg, IFLA_VXLAN_GROUP6, sizeof(in6buf), &in6buf);
4859                 }
4860         } else {
4861                 struct in_addr inbuf;
4862 
4863                 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
4864                         if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
4865                                 ret = -EINVAL;
4866                                 goto failure;
4867                         }
4868                         nla_put(msg, IFLA_VXLAN_LOCAL, sizeof(inbuf), &inbuf);
4869                 }
4870 
4871                 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
4872                         if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
4873                                 ret = -EINVAL;
4874                                 goto failure;
4875                         }
4876                         nla_put(msg, IFLA_VXLAN_GROUP, sizeof(inbuf), &inbuf);
4877                 }
4878         }
4879 
4880         uint32_t port = 4789;
4881         if ((cur = tb_data[VXLAN_DATA_ATTR_PORT])) {
4882                 port = blobmsg_get_u32(cur);
4883                 if (port < 1 || port > 65535) {
4884                         ret = -EINVAL;
4885                         goto failure;
4886                 }
4887         }
4888         nla_put_u16(msg, IFLA_VXLAN_PORT, htons(port));
4889 
4890         if ((cur = tb_data[VXLAN_DATA_ATTR_SRCPORTMIN])) {
4891                 struct ifla_vxlan_port_range srcports = {0,0};
4892 
4893                 uint32_t low = blobmsg_get_u32(cur);
4894                 if (low < 1 || low > 65535 - 1) {
4895                         ret = -EINVAL;
4896                         goto failure;
4897                 }
4898 
4899                 srcports.low = htons((uint16_t) low);
4900                 srcports.high = htons((uint16_t) (low+1));
4901 
4902                 if ((cur = tb_data[VXLAN_DATA_ATTR_SRCPORTMAX])) {
4903                         uint32_t high = blobmsg_get_u32(cur);
4904                         if (high < 1 || high > 65535) {
4905                                 ret = -EINVAL;
4906                                 goto failure;
4907                         }
4908 
4909                         if (high > low)
4910                                 srcports.high = htons((uint16_t) high);
4911                 }
4912 
4913                 nla_put(msg, IFLA_VXLAN_PORT_RANGE, sizeof(srcports), &srcports);
4914         }
4915 
4916         system_vxlan_map_bool_attr(msg, tb_data, IFLA_VXLAN_UDP_CSUM, VXLAN_DATA_ATTR_TXCSUM, false);
4917         system_vxlan_map_bool_attr(msg, tb_data, IFLA_VXLAN_UDP_ZERO_CSUM6_RX, VXLAN_DATA_ATTR_RXCSUM, true);
4918         system_vxlan_map_bool_attr(msg, tb_data, IFLA_VXLAN_UDP_ZERO_CSUM6_TX, VXLAN_DATA_ATTR_TXCSUM, true);
4919         system_vxlan_map_bool_attr(msg, tb_data, IFLA_VXLAN_LEARNING, VXLAN_DATA_ATTR_LEARNING, false);
4920         system_vxlan_map_bool_attr(msg, tb_data, IFLA_VXLAN_RSC , VXLAN_DATA_ATTR_RSC, false);
4921         system_vxlan_map_bool_attr(msg, tb_data, IFLA_VXLAN_PROXY , VXLAN_DATA_ATTR_PROXY, false);
4922         system_vxlan_map_bool_attr(msg, tb_data, IFLA_VXLAN_L2MISS , VXLAN_DATA_ATTR_L2MISS, false);
4923         system_vxlan_map_bool_attr(msg, tb_data, IFLA_VXLAN_L3MISS , VXLAN_DATA_ATTR_L3MISS, false);
4924         system_vxlan_map_bool_attr(msg, tb_data, IFLA_VXLAN_GBP , VXLAN_DATA_ATTR_GBP, false);
4925 
4926         if ((cur = tb_data[VXLAN_DATA_ATTR_AGEING])) {
4927                 uint32_t ageing = blobmsg_get_u32(cur);
4928                 nla_put_u32(msg, IFLA_VXLAN_AGEING, ageing);
4929         }
4930 
4931         if ((cur = tb_data[VXLAN_DATA_ATTR_LIMIT])) {
4932                 uint32_t maxaddress = blobmsg_get_u32(cur);
4933                 nla_put_u32(msg, IFLA_VXLAN_LIMIT, maxaddress);
4934         }
4935 
4936         if ((cur = tb[TUNNEL_ATTR_TOS])) {
4937                 char *str = blobmsg_get_string(cur);
4938                 unsigned tos = 1;
4939 
4940                 if (strcmp(str, "inherit")) {
4941                         if (!system_tos_aton(str, &tos)) {
4942                                 ret = -EINVAL;
4943                                 goto failure;
4944                         }
4945                 }
4946 
4947                 nla_put_u8(msg, IFLA_VXLAN_TOS, tos);
4948         }
4949 
4950         if ((cur = tb[TUNNEL_ATTR_TTL])) {
4951                 uint32_t ttl = blobmsg_get_u32(cur);
4952                 if (ttl < 1 || ttl > 255) {
4953                         ret = -EINVAL;
4954                         goto failure;
4955                 }
4956 
4957                 nla_put_u8(msg, IFLA_VXLAN_TTL, ttl);
4958         }
4959 
4960         nla_nest_end(msg, data);
4961         nla_nest_end(msg, linkinfo);
4962 
4963         ret = system_rtnl_call(msg);
4964         if (ret)
4965                 D(SYSTEM, "Error adding vxlan '%s': %d", name, ret);
4966 
4967         return ret;
4968 
4969 failure:
4970         nlmsg_free(msg);
4971         return ret;
4972 }
4973 #endif
4974 
4975 static int system_add_sit_tunnel(const char *name, const unsigned int link, struct blob_attr **tb)
4976 {
4977         struct blob_attr *cur;
4978         int ret = 0;
4979 
4980         if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
4981                 return -1;
4982 
4983 #ifdef SIOCADD6RD
4984         if ((cur = tb[TUNNEL_ATTR_DATA])) {
4985                 struct blob_attr *tb_data[__SIXRD_DATA_ATTR_MAX];
4986                 unsigned int mask;
4987                 struct ip_tunnel_6rd p6;
4988 
4989                 blobmsg_parse_attr(sixrd_data_attr_list.params, __SIXRD_DATA_ATTR_MAX,
4990                                    tb_data, cur);
4991 
4992                 memset(&p6, 0, sizeof(p6));
4993 
4994                 if ((cur = tb_data[SIXRD_DATA_PREFIX])) {
4995                         if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
4996                                                 &p6.prefix, &mask) || mask > 128) {
4997                                 ret = -EINVAL;
4998                                 goto failure;
4999                         }
5000 
5001                         p6.prefixlen = mask;
5002                 }
5003 
5004                 if ((cur = tb_data[SIXRD_DATA_RELAY_PREFIX])) {
5005                         if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
5006                                                 &p6.relay_prefix, &mask) || mask > 32) {
5007                                 ret = -EINVAL;
5008                                 goto failure;
5009                         }
5010 
5011                         p6.relay_prefixlen = mask;
5012                 }
5013 
5014                 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
5015                         ret = -1;
5016                         goto failure;
5017                 }
5018         }
5019 #endif
5020 
5021         return ret;
5022 
5023 failure:
5024         system_link_del(name);
5025         return ret;
5026 }
5027 
5028 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
5029 {
5030         struct blob_attr *cur;
5031         bool set_df = true;
5032         struct ip_tunnel_parm p  = {
5033                 .link = link,
5034                 .iph = {
5035                         .version = 4,
5036                         .ihl = 5,
5037                         .protocol = proto,
5038                 }
5039         };
5040 
5041         if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
5042                         inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
5043                 return -EINVAL;
5044 
5045         if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
5046                         inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
5047                 return -EINVAL;
5048 
5049         if ((cur = tb[TUNNEL_ATTR_DF]))
5050                 set_df = blobmsg_get_bool(cur);
5051 
5052         if ((cur = tb[TUNNEL_ATTR_TTL]))
5053                 p.iph.ttl = blobmsg_get_u32(cur);
5054 
5055         if ((cur = tb[TUNNEL_ATTR_TOS])) {
5056                 char *str = blobmsg_get_string(cur);
5057                 if (strcmp(str, "inherit")) {
5058                         unsigned uval;
5059 
5060                         if (!system_tos_aton(str, &uval))
5061                                 return -EINVAL;
5062 
5063                         p.iph.tos = uval;
5064                 } else
5065                         p.iph.tos = 1;
5066         }
5067 
5068         p.iph.frag_off = set_df ? htons(IP_DF) : 0;
5069         /* ttl !=0 and nopmtudisc are incompatible */
5070         if (p.iph.ttl && p.iph.frag_off == 0)
5071                 return -EINVAL;
5072 
5073         strncpy(p.name, name, sizeof(p.name) - 1);
5074 
5075         switch (p.iph.protocol) {
5076         case IPPROTO_IPIP:
5077                 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
5078         case IPPROTO_IPV6:
5079                 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
5080         default:
5081                 break;
5082         }
5083         return -1;
5084 }
5085 
5086 int system_del_ip_tunnel(const struct device *dev)
5087 {
5088         return system_link_del(dev->ifname);
5089 }
5090 
5091 int system_update_ipv6_mtu(struct device *dev, int mtu)
5092 {
5093         int ret = -1;
5094         char buf[64];
5095         int fd;
5096 
5097         fd = open(dev_sysctl_path("ipv6/conf", dev->ifname, "mtu"), O_RDWR);
5098         if (fd < 0)
5099                 return ret;
5100 
5101         if (!mtu) {
5102                 ssize_t len = read(fd, buf, sizeof(buf) - 1);
5103                 if (len < 0)
5104                         goto out;
5105 
5106                 buf[len] = 0;
5107                 ret = atoi(buf);
5108         } else {
5109                 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) > 0)
5110                         ret = mtu;
5111         }
5112 
5113 out:
5114         close(fd);
5115         return ret;
5116 }
5117 
5118 int system_add_ip_tunnel(const struct device *dev, struct blob_attr *attr)
5119 {
5120         struct blob_attr *tb[__TUNNEL_ATTR_MAX];
5121         struct blob_attr *cur;
5122         const char *str;
5123 
5124         blobmsg_parse_attr(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb, attr);
5125 
5126         system_link_del(dev->ifname);
5127 
5128         if (!(cur = tb[TUNNEL_ATTR_TYPE]))
5129                 return -EINVAL;
5130         str = blobmsg_data(cur);
5131 
5132         unsigned int ttl = 0;
5133         if ((cur = tb[TUNNEL_ATTR_TTL])) {
5134                 ttl = blobmsg_get_u32(cur);
5135                 if (ttl > 255)
5136                         return -EINVAL;
5137         }
5138 
5139         unsigned int link = 0;
5140         if ((cur = tb[TUNNEL_ATTR_LINK])) {
5141                 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
5142                 if (!iface)
5143                         return -EINVAL;
5144 
5145                 if (iface->l3_dev.dev)
5146                         link = iface->l3_dev.dev->ifindex;
5147         }
5148 
5149         if (!strcmp(str, "sit"))
5150                 return system_add_sit_tunnel(dev->ifname, link, tb);
5151 #ifdef IFLA_IPTUN_MAX
5152         else if (!strcmp(str, "ipip6")) {
5153                 return system_add_ip6_tunnel(dev->ifname, link, tb);
5154         } else if (!strcmp(str, "greip")) {
5155                 return system_add_gre_tunnel(dev->ifname, "gre", link, tb, false);
5156         } else if (!strcmp(str, "gretapip"))  {
5157                 return system_add_gre_tunnel(dev->ifname, "gretap", link, tb, false);
5158         } else if (!strcmp(str, "greip6")) {
5159                 return system_add_gre_tunnel(dev->ifname, "ip6gre", link, tb, true);
5160         } else if (!strcmp(str, "gretapip6")) {
5161                 return system_add_gre_tunnel(dev->ifname, "ip6gretap", link, tb, true);
5162 #ifdef IFLA_VTI_MAX
5163         } else if (!strcmp(str, "vtiip")) {
5164                 return system_add_vti_tunnel(dev->ifname, "vti", link, tb, false);
5165         } else if (!strcmp(str, "vtiip6")) {
5166                 return system_add_vti_tunnel(dev->ifname, "vti6", link, tb, true);
5167 #endif
5168 #ifdef IFLA_XFRM_MAX
5169         } else if (!strcmp(str, "xfrm")) {
5170                 return system_add_xfrm_tunnel(dev->ifname, "xfrm", link, tb);
5171 #endif
5172 #ifdef IFLA_VXLAN_MAX
5173         } else if(!strcmp(str, "vxlan")) {
5174                 return system_add_vxlan(dev->ifname, link, tb, false);
5175         } else if(!strcmp(str, "vxlan6")) {
5176                 return system_add_vxlan(dev->ifname, link, tb, true);
5177 #endif
5178 #endif
5179         } else if (!strcmp(str, "ipip")) {
5180                 return system_add_proto_tunnel(dev->ifname, IPPROTO_IPIP, link, tb);
5181         }
5182         else
5183                 return -EINVAL;
5184 
5185         return 0;
5186 }
5187 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt