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

Sources/netifd/system-linux.c

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

This page was automatically generated by LXR 0.3.1.  •  OpenWrt