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

This page was automatically generated by LXR 0.3.1.  •  OpenWrt