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>
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
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.
21 #include <sys/socket.h>
22 #include <sys/ioctl.h>
24 #include <sys/syscall.h>
27 #include <net/if_arp.h>
29 #include <arpa/inet.h>
30 #include <netinet/ether.h>
31 #include <netinet/in.h>
33 #include <linux/rtnetlink.h>
34 #include <linux/sockios.h>
36 #include <linux/if_addr.h>
37 #include <linux/if_link.h>
38 #include <linux/if_vlan.h>
39 #include <linux/if_bridge.h>
40 #include <linux/if_tunnel.h>
41 #include <linux/ip6_tunnel.h>
42 #include <linux/ethtool.h>
43 #include <linux/fib_rules.h>
44 #include <linux/veth.h>
45 #include <linux/version.h>
47 #ifndef RTN_FAILED_POLICY
48 #define RTN_FAILED_POLICY 12
51 #ifndef IFA_F_NOPREFIXROUTE
52 #define IFA_F_NOPREFIXROUTE 0x200
56 #define IFA_FLAGS (IFA_MULTICAST + 1)
65 #include <netlink/msg.h>
66 #include <netlink/attr.h>
67 #include <netlink/socket.h>
68 #include <libubox/uloop.h>
75 struct uloop_fd uloop;
80 static int sock_ioctl = -1;
81 static struct nl_sock *sock_rtnl = NULL;
83 static int cb_rtnl_event(struct nl_msg *msg, void *arg);
84 static void handle_hotplug_event(struct uloop_fd *u, unsigned int events);
85 static int system_add_proto_tunnel(const char *name, const uint8_t proto,
86 const unsigned int link, struct blob_attr **tb);
87 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb);
89 static char dev_buf[256];
92 handler_nl_event(struct uloop_fd *u, unsigned int events)
94 struct event_socket *ev = container_of(u, struct event_socket, uloop);
96 socklen_t errlen = sizeof(err);
99 nl_recvmsgs_default(ev->sock);
103 if (getsockopt(u->fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen))
108 /* Increase rx buffer size on netlink socket */
110 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
113 /* Request full dump since some info got dropped */
114 struct rtgenmsg msg = { .rtgen_family = AF_UNSPEC };
115 nl_send_simple(ev->sock, RTM_GETLINK, NLM_F_DUMP, &msg, sizeof(msg));
125 uloop_fd_delete(&ev->uloop);
129 static struct nl_sock *
130 create_socket(int protocol, int groups)
132 struct nl_sock *sock;
134 sock = nl_socket_alloc();
139 nl_join_groups(sock, groups);
141 if (nl_connect(sock, protocol))
148 create_raw_event_socket(struct event_socket *ev, int protocol, int groups,
149 uloop_fd_handler cb, int flags)
151 ev->sock = create_socket(protocol, groups);
155 ev->uloop.fd = nl_socket_get_fd(ev->sock);
157 if (uloop_fd_add(&ev->uloop, ULOOP_READ|flags))
164 create_event_socket(struct event_socket *ev, int protocol,
165 int (*cb)(struct nl_msg *msg, void *arg))
167 if (!create_raw_event_socket(ev, protocol, 0, handler_nl_event, ULOOP_ERROR_CB))
170 /* Install the valid custom callback handler */
171 nl_socket_modify_cb(ev->sock, NL_CB_VALID, NL_CB_CUSTOM, cb, NULL);
173 /* Disable sequence number checking on event sockets */
174 nl_socket_disable_seq_check(ev->sock);
176 /* Increase rx buffer size to 65K on event sockets */
178 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
185 create_hotplug_event_socket(struct event_socket *ev, int protocol,
186 void (*cb)(struct uloop_fd *u, unsigned int events))
188 if (!create_raw_event_socket(ev, protocol, 1, cb, ULOOP_ERROR_CB))
191 /* Increase rx buffer size to 65K on event sockets */
193 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
200 system_rtn_aton(const char *src, unsigned int *dst)
205 if (!strcmp(src, "local"))
207 else if (!strcmp(src, "nat"))
209 else if (!strcmp(src, "broadcast"))
211 else if (!strcmp(src, "anycast"))
213 else if (!strcmp(src, "multicast"))
215 else if (!strcmp(src, "prohibit"))
217 else if (!strcmp(src, "unreachable"))
219 else if (!strcmp(src, "blackhole"))
221 else if (!strcmp(src, "xresolve"))
223 else if (!strcmp(src, "unicast"))
225 else if (!strcmp(src, "throw"))
227 else if (!strcmp(src, "failed_policy"))
228 n = RTN_FAILED_POLICY;
230 n = strtoul(src, &e, 0);
231 if (!e || *e || e == src || n > 255)
240 system_tos_aton(const char *src, unsigned *dst)
244 *dst = strtoul(src, &e, 16);
245 if (e == src || *e || *dst > 255)
251 int system_init(void)
253 static struct event_socket rtnl_event;
254 static struct event_socket hotplug_event;
256 sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0);
257 system_fd_set_cloexec(sock_ioctl);
259 /* Prepare socket for routing / address control */
260 sock_rtnl = create_socket(NETLINK_ROUTE, 0);
264 if (!create_event_socket(&rtnl_event, NETLINK_ROUTE, cb_rtnl_event))
267 if (!create_hotplug_event_socket(&hotplug_event, NETLINK_KOBJECT_UEVENT,
268 handle_hotplug_event))
271 /* Receive network link events form kernel */
272 nl_socket_add_membership(rtnl_event.sock, RTNLGRP_LINK);
277 static void system_set_sysctl(const char *path, const char *val)
281 fd = open(path, O_WRONLY);
285 if (write(fd, val, strlen(val))) {}
289 static void system_set_dev_sysctl(const char *path, const char *device, const char *val)
291 snprintf(dev_buf, sizeof(dev_buf), path, device);
292 system_set_sysctl(dev_buf, val);
295 static void system_set_disable_ipv6(struct device *dev, const char *val)
297 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val);
300 static void system_set_rpfilter(struct device *dev, const char *val)
302 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter", dev->ifname, val);
305 static void system_set_acceptlocal(struct device *dev, const char *val)
307 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local", dev->ifname, val);
310 static void system_set_igmpversion(struct device *dev, const char *val)
312 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version", dev->ifname, val);
315 static void system_set_mldversion(struct device *dev, const char *val)
317 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version", dev->ifname, val);
320 static void system_set_neigh4reachabletime(struct device *dev, const char *val)
322 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms", dev->ifname, val);
325 static void system_set_neigh6reachabletime(struct device *dev, const char *val)
327 system_set_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms", dev->ifname, val);
330 static void system_set_neigh4gcstaletime(struct device *dev, const char *val)
332 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/gc_stale_time", dev->ifname, val);
335 static void system_set_neigh6gcstaletime(struct device *dev, const char *val)
337 system_set_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/gc_stale_time", dev->ifname, val);
340 static void system_set_neigh4locktime(struct device *dev, const char *val)
342 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/locktime", dev->ifname, val);
345 static void system_set_dadtransmits(struct device *dev, const char *val)
347 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits", dev->ifname, val);
350 static void system_bridge_set_multicast_to_unicast(struct device *dev, const char *val)
352 system_set_dev_sysctl("/sys/class/net/%s/brport/multicast_to_unicast", dev->ifname, val);
355 static void system_bridge_set_multicast_fast_leave(struct device *dev, const char *val)
357 system_set_dev_sysctl("/sys/class/net/%s/brport/multicast_fast_leave", dev->ifname, val);
360 static void system_bridge_set_hairpin_mode(struct device *dev, const char *val)
362 system_set_dev_sysctl("/sys/class/net/%s/brport/hairpin_mode", dev->ifname, val);
365 static void system_bridge_set_isolated(struct device *dev, const char *val)
367 system_set_dev_sysctl("/sys/class/net/%s/brport/isolated", dev->ifname, val);
370 static void system_bridge_set_multicast_router(struct device *dev, const char *val, bool bridge)
372 system_set_dev_sysctl(bridge ? "/sys/class/net/%s/bridge/multicast_router" :
373 "/sys/class/net/%s/brport/multicast_router",
377 static void system_bridge_set_robustness(struct device *dev, const char *val)
379 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_startup_query_count",
381 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_last_member_count",
385 static void system_bridge_set_query_interval(struct device *dev, const char *val)
387 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_query_interval",
391 static void system_bridge_set_query_response_interval(struct device *dev, const char *val)
393 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_query_response_interval",
397 static void system_bridge_set_last_member_interval(struct device *dev, const char *val)
399 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_last_member_interval",
403 static void system_bridge_set_membership_interval(struct device *dev, const char *val)
405 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_membership_interval",
409 static void system_bridge_set_other_querier_timeout(struct device *dev, const char *val)
411 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier_interval",
415 static void system_bridge_set_startup_query_interval(struct device *dev, const char *val)
417 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_startup_query_interval",
421 static void system_bridge_set_stp_state(struct device *dev, const char *val)
423 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/stp_state", dev->ifname, val);
426 static void system_bridge_set_forward_delay(struct device *dev, const char *val)
428 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/forward_delay", dev->ifname, val);
431 static void system_bridge_set_priority(struct device *dev, const char *val)
433 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/priority", dev->ifname, val);
436 static void system_bridge_set_ageing_time(struct device *dev, const char *val)
438 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/ageing_time", dev->ifname, val);
441 static void system_bridge_set_hello_time(struct device *dev, const char *val)
443 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/hello_time", dev->ifname, val);
446 static void system_bridge_set_max_age(struct device *dev, const char *val)
448 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/max_age", dev->ifname, val);
451 static void system_bridge_set_learning(struct device *dev, const char *val)
453 system_set_dev_sysctl("/sys/class/net/%s/brport/learning", dev->ifname, val);
456 static void system_bridge_set_unicast_flood(struct device *dev, const char *val)
458 system_set_dev_sysctl("/sys/class/net/%s/brport/unicast_flood", dev->ifname, val);
461 static void system_set_sendredirects(struct device *dev, const char *val)
463 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/send_redirects", dev->ifname, val);
466 static int system_get_sysctl(const char *path, char *buf, const size_t buf_sz)
468 int fd = -1, ret = -1;
470 fd = open(path, O_RDONLY);
474 ssize_t len = read(fd, buf, buf_sz - 1);
488 system_get_dev_sysctl(const char *path, const char *device, char *buf, const size_t buf_sz)
490 snprintf(dev_buf, sizeof(dev_buf), path, device);
491 return system_get_sysctl(dev_buf, buf, buf_sz);
494 static int system_get_disable_ipv6(struct device *dev, char *buf, const size_t buf_sz)
496 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6",
497 dev->ifname, buf, buf_sz);
500 static int system_get_rpfilter(struct device *dev, char *buf, const size_t buf_sz)
502 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter",
503 dev->ifname, buf, buf_sz);
506 static int system_get_acceptlocal(struct device *dev, char *buf, const size_t buf_sz)
508 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local",
509 dev->ifname, buf, buf_sz);
512 static int system_get_igmpversion(struct device *dev, char *buf, const size_t buf_sz)
514 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version",
515 dev->ifname, buf, buf_sz);
518 static int system_get_mldversion(struct device *dev, char *buf, const size_t buf_sz)
520 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version",
521 dev->ifname, buf, buf_sz);
524 static int system_get_neigh4reachabletime(struct device *dev, char *buf, const size_t buf_sz)
526 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms",
527 dev->ifname, buf, buf_sz);
530 static int system_get_neigh6reachabletime(struct device *dev, char *buf, const size_t buf_sz)
532 return system_get_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms",
533 dev->ifname, buf, buf_sz);
536 static int system_get_neigh4gcstaletime(struct device *dev, char *buf, const size_t buf_sz)
538 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/gc_stale_time",
539 dev->ifname, buf, buf_sz);
542 static int system_get_neigh6gcstaletime(struct device *dev, char *buf, const size_t buf_sz)
544 return system_get_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/gc_stale_time",
545 dev->ifname, buf, buf_sz);
548 static int system_get_neigh4locktime(struct device *dev, char *buf, const size_t buf_sz)
550 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/locktime",
551 dev->ifname, buf, buf_sz);
554 static int system_get_dadtransmits(struct device *dev, char *buf, const size_t buf_sz)
556 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits",
557 dev->ifname, buf, buf_sz);
560 static int system_get_sendredirects(struct device *dev, char *buf, const size_t buf_sz)
562 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/send_redirects",
563 dev->ifname, buf, buf_sz);
566 /* Evaluate netlink messages */
567 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
569 struct nlmsghdr *nh = nlmsg_hdr(msg);
570 struct nlattr *nla[__IFLA_MAX];
574 if (nh->nlmsg_type != RTM_NEWLINK)
577 nlmsg_parse(nh, sizeof(struct ifinfomsg), nla, __IFLA_MAX - 1, NULL);
578 if (!nla[IFLA_IFNAME])
581 struct device *dev = device_find(nla_data(nla[IFLA_IFNAME]));
585 if (!system_get_dev_sysctl("/sys/class/net/%s/carrier", dev->ifname, buf, sizeof(buf)))
586 link_state = strtoul(buf, NULL, 0);
588 device_set_link(dev, link_state ? true : false);
595 handle_hotplug_msg(char *data, int size)
597 const char *subsystem = NULL, *interface = NULL, *interface_old = NULL;
598 char *cur, *end, *sep;
601 bool add, move = false;
603 if (!strncmp(data, "add@", 4))
605 else if (!strncmp(data, "remove@", 7))
607 else if (!strncmp(data, "move@", 5)) {
614 skip = strlen(data) + 1;
617 for (cur = data + skip; cur < end; cur += skip) {
618 skip = strlen(cur) + 1;
620 sep = strchr(cur, '=');
625 if (!strcmp(cur, "INTERFACE"))
627 else if (!strcmp(cur, "SUBSYSTEM")) {
629 if (strcmp(subsystem, "net") != 0)
631 } else if (!strcmp(cur, "DEVPATH_OLD")) {
632 interface_old = strrchr(sep + 1, '/');
638 if (subsystem && interface) {
639 if (move && interface_old)
648 dev = device_find(interface_old);
652 if (dev->type != &simple_device_type)
655 device_set_present(dev, false);
658 dev = device_find(interface);
662 if (dev->type != &simple_device_type)
665 if (add && system_if_force_external(dev->ifname))
668 device_set_present(dev, add);
672 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
674 struct event_socket *ev = container_of(u, struct event_socket, uloop);
675 struct sockaddr_nl nla;
676 unsigned char *buf = NULL;
679 socklen_t errlen = sizeof(err);
682 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
684 handle_hotplug_msg((char *) buf, size);
691 if (getsockopt(u->fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen))
696 /* Increase rx buffer size on netlink socket */
698 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
709 uloop_fd_delete(&ev->uloop);
713 static int system_rtnl_call(struct nl_msg *msg)
717 ret = nl_send_auto_complete(sock_rtnl, msg);
723 return nl_wait_for_ack(sock_rtnl);
726 int system_bridge_delbr(struct device *bridge)
728 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
731 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
735 memset(&ifr, 0, sizeof(ifr));
737 ifr.ifr_ifindex = dev->ifindex;
740 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name) - 1);
741 return ioctl(sock_ioctl, cmd, &ifr);
744 static bool system_is_bridge(const char *name, char *buf, int buflen)
748 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
749 if (stat(buf, &st) < 0)
755 static char *system_get_bridge(const char *name, char *buf, int buflen)
761 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
762 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
766 len = readlink(gl.gl_pathv[0], buf, buflen);
774 path = strrchr(buf, '/');
782 system_bridge_set_wireless(struct device *bridge, struct device *dev)
784 bool mcast_to_ucast = dev->wireless_ap;
787 if (bridge->settings.flags & DEV_OPT_MULTICAST_TO_UNICAST &&
788 !bridge->settings.multicast_to_unicast)
789 mcast_to_ucast = false;
791 if (!mcast_to_ucast || dev->wireless_isolate)
794 system_bridge_set_multicast_to_unicast(dev, mcast_to_ucast ? "1" : "0");
795 system_bridge_set_hairpin_mode(dev, hairpin ? "1" : "0");
798 int system_bridge_addif(struct device *bridge, struct device *dev)
804 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
805 if (!oldbr || strcmp(oldbr, bridge->ifname) != 0)
806 ret = system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
809 system_bridge_set_wireless(bridge, dev);
811 if (dev->settings.flags & DEV_OPT_MULTICAST_ROUTER) {
812 snprintf(buf, sizeof(buf), "%u", dev->settings.multicast_router);
813 system_bridge_set_multicast_router(dev, buf, false);
816 if (dev->settings.flags & DEV_OPT_MULTICAST_FAST_LEAVE &&
817 dev->settings.multicast_fast_leave)
818 system_bridge_set_multicast_fast_leave(dev, "1");
820 if (dev->settings.flags & DEV_OPT_LEARNING &&
821 !dev->settings.learning)
822 system_bridge_set_learning(dev, "0");
824 if (dev->settings.flags & DEV_OPT_UNICAST_FLOOD &&
825 !dev->settings.unicast_flood)
826 system_bridge_set_unicast_flood(dev, "0");
828 if (dev->settings.flags & DEV_OPT_ISOLATE &&
829 dev->settings.isolate)
830 system_bridge_set_isolated(dev, "1");
835 int system_bridge_delif(struct device *bridge, struct device *dev)
837 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
840 int system_if_resolve(struct device *dev)
843 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
844 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
845 return ifr.ifr_ifindex;
850 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
854 memset(&ifr, 0, sizeof(ifr));
855 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1);
856 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) < 0)
859 ifr.ifr_flags |= add;
860 ifr.ifr_flags &= ~rem;
861 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
873 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
875 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
877 return ifa->ifa_index == ifindex;
880 static bool check_route(struct nlmsghdr *hdr, int ifindex)
882 struct rtmsg *r = NLMSG_DATA(hdr);
883 struct nlattr *tb[__RTA_MAX];
885 if (r->rtm_protocol == RTPROT_KERNEL &&
886 r->rtm_family == AF_INET6)
889 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
893 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
896 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
901 static int cb_clear_event(struct nl_msg *msg, void *arg)
903 struct clear_data *clr = arg;
904 struct nlmsghdr *hdr = nlmsg_hdr(msg);
905 bool (*cb)(struct nlmsghdr *, int ifindex);
911 if (hdr->nlmsg_type != RTM_NEWADDR)
918 if (hdr->nlmsg_type != RTM_NEWROUTE)
925 if (hdr->nlmsg_type != RTM_NEWRULE)
934 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
937 if (type == RTM_DELRULE)
938 D(SYSTEM, "Remove a rule\n");
940 D(SYSTEM, "Remove %s from device %s\n",
941 type == RTM_DELADDR ? "an address" : "a route",
943 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
944 hdr = nlmsg_hdr(clr->msg);
945 hdr->nlmsg_type = type;
946 hdr->nlmsg_flags = NLM_F_REQUEST;
948 nl_socket_disable_auto_ack(sock_rtnl);
949 nl_send_auto_complete(sock_rtnl, clr->msg);
950 nl_socket_enable_auto_ack(sock_rtnl);
956 cb_finish_event(struct nl_msg *msg, void *arg)
964 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
967 *pending = err->error;
972 system_if_clear_entries(struct device *dev, int type, int af)
974 struct clear_data clr;
975 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
978 .rtm_flags = RTM_F_CLONED,
980 int flags = NLM_F_DUMP;
989 clr.size = sizeof(struct rtgenmsg);
992 clr.size = sizeof(struct rtmsg);
1001 clr.msg = nlmsg_alloc_simple(type, flags);
1005 nlmsg_append(clr.msg, &rtm, clr.size, 0);
1006 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
1007 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
1008 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
1010 nl_send_auto_complete(sock_rtnl, clr.msg);
1012 nl_recvmsgs(sock_rtnl, cb);
1014 nlmsg_free(clr.msg);
1020 * Clear bridge (membership) state and bring down device
1022 void system_if_clear_state(struct device *dev)
1024 static char buf[256];
1027 device_set_ifindex(dev, system_if_resolve(dev));
1028 if (dev->external || !dev->ifindex)
1031 system_if_flags(dev->ifname, 0, IFF_UP);
1033 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
1034 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
1035 system_bridge_delbr(dev);
1039 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
1041 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
1042 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
1045 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
1046 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
1047 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
1048 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
1049 system_set_disable_ipv6(dev, "0");
1052 static inline unsigned long
1053 sec_to_jiffies(int val)
1055 return (unsigned long) val * 100;
1058 static void system_bridge_conf_multicast_deps(struct device *bridge,
1059 struct bridge_config *cfg,
1065 if (cfg->flags & BRIDGE_OPT_ROBUSTNESS ||
1066 cfg->flags & BRIDGE_OPT_QUERY_INTERVAL ||
1067 cfg->flags & BRIDGE_OPT_QUERY_RESPONSE_INTERVAL) {
1068 val = cfg->robustness * cfg->query_interval +
1069 cfg->query_response_interval;
1071 snprintf(buf, buf_len, "%i", val);
1072 system_bridge_set_membership_interval(bridge, buf);
1074 val = cfg->robustness * cfg->query_interval +
1075 cfg->query_response_interval / 2;
1077 snprintf(buf, buf_len, "%i", val);
1078 system_bridge_set_other_querier_timeout(bridge, buf);
1081 if (cfg->flags & BRIDGE_OPT_QUERY_INTERVAL) {
1082 val = cfg->query_interval / 4;
1084 snprintf(buf, buf_len, "%i", val);
1085 system_bridge_set_startup_query_interval(bridge, buf);
1089 static void system_bridge_conf_multicast(struct device *bridge,
1090 struct bridge_config *cfg,
1094 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
1095 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
1097 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier",
1098 bridge->ifname, cfg->multicast_querier ? "1" : "0");
1100 snprintf(buf, buf_len, "%i", cfg->hash_max);
1101 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/hash_max",
1102 bridge->ifname, buf);
1104 if (bridge->settings.flags & DEV_OPT_MULTICAST_ROUTER) {
1105 snprintf(buf, buf_len, "%u", bridge->settings.multicast_router);
1106 system_bridge_set_multicast_router(bridge, buf, true);
1109 if (cfg->flags & BRIDGE_OPT_ROBUSTNESS) {
1110 snprintf(buf, buf_len, "%i", cfg->robustness);
1111 system_bridge_set_robustness(bridge, buf);
1114 if (cfg->flags & BRIDGE_OPT_QUERY_INTERVAL) {
1115 snprintf(buf, buf_len, "%i", cfg->query_interval);
1116 system_bridge_set_query_interval(bridge, buf);
1119 if (cfg->flags & BRIDGE_OPT_QUERY_RESPONSE_INTERVAL) {
1120 snprintf(buf, buf_len, "%i", cfg->query_response_interval);
1121 system_bridge_set_query_response_interval(bridge, buf);
1124 if (cfg->flags & BRIDGE_OPT_LAST_MEMBER_INTERVAL) {
1125 snprintf(buf, buf_len, "%i", cfg->last_member_interval);
1126 system_bridge_set_last_member_interval(bridge, buf);
1129 system_bridge_conf_multicast_deps(bridge, cfg, buf, buf_len);
1132 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
1136 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
1139 system_bridge_set_stp_state(bridge, cfg->stp ? "1" : "0");
1141 snprintf(buf, sizeof(buf), "%lu", sec_to_jiffies(cfg->forward_delay));
1142 system_bridge_set_forward_delay(bridge, buf);
1144 system_bridge_conf_multicast(bridge, cfg, buf, sizeof(buf));
1146 snprintf(buf, sizeof(buf), "%d", cfg->priority);
1147 system_bridge_set_priority(bridge, buf);
1149 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
1150 snprintf(buf, sizeof(buf), "%lu", sec_to_jiffies(cfg->ageing_time));
1151 system_bridge_set_ageing_time(bridge, buf);
1154 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
1155 snprintf(buf, sizeof(buf), "%lu", sec_to_jiffies(cfg->hello_time));
1156 system_bridge_set_hello_time(bridge, buf);
1159 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
1160 snprintf(buf, sizeof(buf), "%lu", sec_to_jiffies(cfg->max_age));
1161 system_bridge_set_max_age(bridge, buf);
1167 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
1170 struct nlattr *linkinfo, *data;
1171 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
1173 static const struct {
1175 enum macvlan_mode val;
1177 { "private", MACVLAN_MODE_PRIVATE },
1178 { "vepa", MACVLAN_MODE_VEPA },
1179 { "bridge", MACVLAN_MODE_BRIDGE },
1180 { "passthru", MACVLAN_MODE_PASSTHRU },
1183 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1188 nlmsg_append(msg, &iim, sizeof(iim), 0);
1190 if (cfg->flags & MACVLAN_OPT_MACADDR)
1191 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
1192 nla_put_string(msg, IFLA_IFNAME, macvlan->ifname);
1193 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
1195 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1196 goto nla_put_failure;
1198 nla_put_string(msg, IFLA_INFO_KIND, "macvlan");
1200 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1201 goto nla_put_failure;
1204 for (i = 0; i < ARRAY_SIZE(modes); i++) {
1205 if (strcmp(cfg->mode, modes[i].name) != 0)
1208 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
1213 nla_nest_end(msg, data);
1214 nla_nest_end(msg, linkinfo);
1216 rv = system_rtnl_call(msg);
1218 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
1227 static int system_link_del(const char *ifname)
1230 struct ifinfomsg iim = {
1231 .ifi_family = AF_UNSPEC,
1235 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
1240 nlmsg_append(msg, &iim, sizeof(iim), 0);
1241 nla_put_string(msg, IFLA_IFNAME, ifname);
1242 return system_rtnl_call(msg);
1245 int system_macvlan_del(struct device *macvlan)
1247 return system_link_del(macvlan->ifname);
1250 int system_veth_add(struct device *veth, struct veth_config *cfg)
1253 struct ifinfomsg empty_iim = {};
1254 struct nlattr *linkinfo, *data, *veth_info;
1257 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1262 nlmsg_append(msg, &empty_iim, sizeof(empty_iim), 0);
1264 if (cfg->flags & VETH_OPT_MACADDR)
1265 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
1266 nla_put_string(msg, IFLA_IFNAME, veth->ifname);
1268 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1269 goto nla_put_failure;
1271 nla_put_string(msg, IFLA_INFO_KIND, "veth");
1273 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1274 goto nla_put_failure;
1276 if (!(veth_info = nla_nest_start(msg, VETH_INFO_PEER)))
1277 goto nla_put_failure;
1279 nlmsg_append(msg, &empty_iim, sizeof(empty_iim), 0);
1281 if (cfg->flags & VETH_OPT_PEER_NAME)
1282 nla_put_string(msg, IFLA_IFNAME, cfg->peer_name);
1283 if (cfg->flags & VETH_OPT_PEER_MACADDR)
1284 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->peer_macaddr), cfg->peer_macaddr);
1286 nla_nest_end(msg, veth_info);
1287 nla_nest_end(msg, data);
1288 nla_nest_end(msg, linkinfo);
1290 rv = system_rtnl_call(msg);
1292 if (cfg->flags & VETH_OPT_PEER_NAME)
1293 D(SYSTEM, "Error adding veth '%s' with peer '%s': %d\n", veth->ifname, cfg->peer_name, rv);
1295 D(SYSTEM, "Error adding veth '%s': %d\n", veth->ifname, rv);
1305 int system_veth_del(struct device *veth)
1307 return system_link_del(veth->ifname);
1310 static int system_vlan(struct device *dev, int id)
1312 struct vlan_ioctl_args ifr = {
1313 .cmd = SET_VLAN_NAME_TYPE_CMD,
1314 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
1317 if (ioctl(sock_ioctl, SIOCSIFVLAN, &ifr) < 0)
1321 ifr.cmd = DEL_VLAN_CMD;
1324 ifr.cmd = ADD_VLAN_CMD;
1327 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
1328 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
1331 int system_vlan_add(struct device *dev, int id)
1333 return system_vlan(dev, id);
1336 int system_vlan_del(struct device *dev)
1338 return system_vlan(dev, -1);
1341 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
1344 struct nlattr *linkinfo, *data;
1345 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
1348 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1353 nlmsg_append(msg, &iim, sizeof(iim), 0);
1354 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
1355 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
1357 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1358 goto nla_put_failure;
1360 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
1362 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1363 goto nla_put_failure;
1365 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
1367 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
1368 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
1370 if(cfg->proto == VLAN_PROTO_8021AD)
1371 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);
1374 nla_nest_end(msg, data);
1375 nla_nest_end(msg, linkinfo);
1377 rv = system_rtnl_call(msg);
1379 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
1388 int system_vlandev_del(struct device *vlandev)
1390 return system_link_del(vlandev->ifname);
1394 system_if_get_settings(struct device *dev, struct device_settings *s)
1399 memset(&ifr, 0, sizeof(ifr));
1400 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
1402 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
1403 s->mtu = ifr.ifr_mtu;
1404 s->flags |= DEV_OPT_MTU;
1407 s->mtu6 = system_update_ipv6_mtu(dev, 0);
1409 s->flags |= DEV_OPT_MTU6;
1411 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
1412 s->txqueuelen = ifr.ifr_qlen;
1413 s->flags |= DEV_OPT_TXQUEUELEN;
1416 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
1417 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
1418 s->flags |= DEV_OPT_MACADDR;
1421 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
1422 s->ipv6 = !strtoul(buf, NULL, 0);
1423 s->flags |= DEV_OPT_IPV6;
1426 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
1427 s->promisc = ifr.ifr_flags & IFF_PROMISC;
1428 s->flags |= DEV_OPT_PROMISC;
1430 s->multicast = ifr.ifr_flags & IFF_MULTICAST;
1431 s->flags |= DEV_OPT_MULTICAST;
1434 if (!system_get_rpfilter(dev, buf, sizeof(buf))) {
1435 s->rpfilter = strtoul(buf, NULL, 0);
1436 s->flags |= DEV_OPT_RPFILTER;
1439 if (!system_get_acceptlocal(dev, buf, sizeof(buf))) {
1440 s->acceptlocal = strtoul(buf, NULL, 0);
1441 s->flags |= DEV_OPT_ACCEPTLOCAL;
1444 if (!system_get_igmpversion(dev, buf, sizeof(buf))) {
1445 s->igmpversion = strtoul(buf, NULL, 0);
1446 s->flags |= DEV_OPT_IGMPVERSION;
1449 if (!system_get_mldversion(dev, buf, sizeof(buf))) {
1450 s->mldversion = strtoul(buf, NULL, 0);
1451 s->flags |= DEV_OPT_MLDVERSION;
1454 if (!system_get_neigh4reachabletime(dev, buf, sizeof(buf))) {
1455 s->neigh4reachabletime = strtoul(buf, NULL, 0);
1456 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1459 if (!system_get_neigh6reachabletime(dev, buf, sizeof(buf))) {
1460 s->neigh6reachabletime = strtoul(buf, NULL, 0);
1461 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1464 if (!system_get_neigh4locktime(dev, buf, sizeof(buf))) {
1465 s->neigh4locktime = strtol(buf, NULL, 0);
1466 s->flags |= DEV_OPT_NEIGHLOCKTIME;
1469 if (!system_get_neigh4gcstaletime(dev, buf, sizeof(buf))) {
1470 s->neigh4gcstaletime = strtoul(buf, NULL, 0);
1471 s->flags |= DEV_OPT_NEIGHGCSTALETIME;
1474 if (!system_get_neigh6gcstaletime(dev, buf, sizeof(buf))) {
1475 s->neigh6gcstaletime = strtoul(buf, NULL, 0);
1476 s->flags |= DEV_OPT_NEIGHGCSTALETIME;
1479 if (!system_get_dadtransmits(dev, buf, sizeof(buf))) {
1480 s->dadtransmits = strtoul(buf, NULL, 0);
1481 s->flags |= DEV_OPT_DADTRANSMITS;
1484 if (!system_get_sendredirects(dev, buf, sizeof(buf))) {
1485 s->sendredirects = strtoul(buf, NULL, 0);
1486 s->flags |= DEV_OPT_SENDREDIRECTS;
1491 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
1496 memset(&ifr, 0, sizeof(ifr));
1497 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
1498 if (s->flags & DEV_OPT_MTU & apply_mask) {
1499 ifr.ifr_mtu = s->mtu;
1500 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
1501 s->flags &= ~DEV_OPT_MTU;
1503 if (s->flags & DEV_OPT_MTU6 & apply_mask) {
1504 system_update_ipv6_mtu(dev, s->mtu6);
1506 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
1507 ifr.ifr_qlen = s->txqueuelen;
1508 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
1509 s->flags &= ~DEV_OPT_TXQUEUELEN;
1511 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
1512 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
1513 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
1514 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
1515 s->flags &= ~DEV_OPT_MACADDR;
1517 if (s->flags & DEV_OPT_IPV6 & apply_mask)
1518 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
1519 if (s->flags & DEV_OPT_PROMISC & apply_mask) {
1520 if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
1521 !s->promisc ? IFF_PROMISC : 0) < 0)
1522 s->flags &= ~DEV_OPT_PROMISC;
1524 if (s->flags & DEV_OPT_RPFILTER & apply_mask) {
1525 snprintf(buf, sizeof(buf), "%u", s->rpfilter);
1526 system_set_rpfilter(dev, buf);
1528 if (s->flags & DEV_OPT_ACCEPTLOCAL & apply_mask)
1529 system_set_acceptlocal(dev, s->acceptlocal ? "1" : "0");
1530 if (s->flags & DEV_OPT_IGMPVERSION & apply_mask) {
1531 snprintf(buf, sizeof(buf), "%u", s->igmpversion);
1532 system_set_igmpversion(dev, buf);
1534 if (s->flags & DEV_OPT_MLDVERSION & apply_mask) {
1535 snprintf(buf, sizeof(buf), "%u", s->mldversion);
1536 system_set_mldversion(dev, buf);
1538 if (s->flags & DEV_OPT_NEIGHREACHABLETIME & apply_mask) {
1539 snprintf(buf, sizeof(buf), "%u", s->neigh4reachabletime);
1540 system_set_neigh4reachabletime(dev, buf);
1541 snprintf(buf, sizeof(buf), "%u", s->neigh6reachabletime);
1542 system_set_neigh6reachabletime(dev, buf);
1544 if (s->flags & DEV_OPT_NEIGHLOCKTIME & apply_mask) {
1545 snprintf(buf, sizeof(buf), "%d", s->neigh4locktime);
1546 system_set_neigh4locktime(dev, buf);
1548 if (s->flags & DEV_OPT_NEIGHGCSTALETIME & apply_mask) {
1549 snprintf(buf, sizeof(buf), "%u", s->neigh4gcstaletime);
1550 system_set_neigh4gcstaletime(dev, buf);
1551 snprintf(buf, sizeof(buf), "%u", s->neigh6gcstaletime);
1552 system_set_neigh6gcstaletime(dev, buf);
1554 if (s->flags & DEV_OPT_DADTRANSMITS & apply_mask) {
1555 snprintf(buf, sizeof(buf), "%u", s->dadtransmits);
1556 system_set_dadtransmits(dev, buf);
1558 if (s->flags & DEV_OPT_MULTICAST & apply_mask) {
1559 if (system_if_flags(dev->ifname, s->multicast ? IFF_MULTICAST : 0,
1560 !s->multicast ? IFF_MULTICAST : 0) < 0)
1561 s->flags &= ~DEV_OPT_MULTICAST;
1563 if (s->flags & DEV_OPT_SENDREDIRECTS & apply_mask)
1564 system_set_sendredirects(dev, s->sendredirects ? "1" : "0");
1567 int system_if_up(struct device *dev)
1569 system_if_get_settings(dev, &dev->orig_settings);
1570 /* Only keep orig settings based on what needs to be set */
1571 dev->orig_settings.valid_flags = dev->orig_settings.flags;
1572 dev->orig_settings.flags &= dev->settings.flags;
1573 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
1574 return system_if_flags(dev->ifname, IFF_UP, 0);
1577 int system_if_down(struct device *dev)
1579 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
1580 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
1584 struct if_check_data {
1590 #ifndef IFF_LOWER_UP
1591 #define IFF_LOWER_UP 0x10000
1594 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1596 struct nlmsghdr *nh = nlmsg_hdr(msg);
1597 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1598 struct if_check_data *chk = (struct if_check_data *)arg;
1600 if (nh->nlmsg_type != RTM_NEWLINK)
1603 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1604 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1609 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1611 struct if_check_data *chk = (struct if_check_data *)arg;
1616 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1618 struct if_check_data *chk = (struct if_check_data *)arg;
1620 device_set_present(chk->dev, false);
1621 device_set_link(chk->dev, false);
1622 chk->pending = err->error;
1627 int system_if_check(struct device *dev)
1629 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1631 struct ifinfomsg ifi = {
1632 .ifi_family = AF_UNSPEC,
1635 struct if_check_data chk = {
1644 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1648 if (nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1649 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1652 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1653 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1654 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1656 nl_send_auto_complete(sock_rtnl, msg);
1657 while (chk.pending > 0)
1658 nl_recvmsgs(sock_rtnl, cb);
1670 system_if_get_parent(struct device *dev)
1672 char buf[64], *devname;
1673 int ifindex, iflink, len;
1676 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1677 f = fopen(buf, "r");
1681 len = fread(buf, 1, sizeof(buf) - 1, f);
1688 iflink = strtoul(buf, NULL, 0);
1689 ifindex = system_if_resolve(dev);
1690 if (!iflink || iflink == ifindex)
1693 devname = if_indextoname(iflink, buf);
1697 return device_get(devname, true);
1701 read_string_file(int dir_fd, const char *file, char *buf, int len)
1707 fd = openat(dir_fd, file, O_RDONLY);
1712 len = read(fd, buf, len - 1);
1716 } else if (len > 0) {
1719 c = strchr(buf, '\n');
1732 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1737 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1739 *val = strtoull(buf, NULL, 0);
1744 /* Assume advertised flags == supported flags */
1745 static const struct {
1748 } ethtool_link_modes[] = {
1749 { ADVERTISED_10baseT_Half, "10baseT-H" },
1750 { ADVERTISED_10baseT_Full, "10baseT-F" },
1751 { ADVERTISED_100baseT_Half, "100baseT-H" },
1752 { ADVERTISED_100baseT_Full, "100baseT-F" },
1753 { ADVERTISED_1000baseT_Half, "1000baseT-H" },
1754 { ADVERTISED_1000baseT_Full, "1000baseT-F" },
1755 { ADVERTISED_1000baseKX_Full, "1000baseKX-F" },
1756 { ADVERTISED_2500baseX_Full, "2500baseX-F" },
1757 { ADVERTISED_10000baseT_Full, "10000baseT-F" },
1758 { ADVERTISED_10000baseKX4_Full, "10000baseKX4-F" },
1759 { ADVERTISED_10000baseKR_Full, "10000baseKR-F" },
1760 { ADVERTISED_20000baseMLD2_Full, "20000baseMLD2-F" },
1761 { ADVERTISED_20000baseKR2_Full, "20000baseKR2-F" },
1762 { ADVERTISED_40000baseKR4_Full, "40000baseKR4-F" },
1763 { ADVERTISED_40000baseCR4_Full, "40000baseCR4-F" },
1764 { ADVERTISED_40000baseSR4_Full, "40000baseSR4-F" },
1765 { ADVERTISED_40000baseLR4_Full, "40000baseLR4-F" },
1766 #ifdef ADVERTISED_56000baseKR4_Full
1767 { ADVERTISED_56000baseKR4_Full, "56000baseKR4-F" },
1768 { ADVERTISED_56000baseCR4_Full, "56000baseCR4-F" },
1769 { ADVERTISED_56000baseSR4_Full, "56000baseSR4-F" },
1770 { ADVERTISED_56000baseLR4_Full, "56000baseLR4-F" },
1774 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1777 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1778 if (mask & ethtool_link_modes[i].mask)
1779 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1784 system_if_force_external(const char *ifname)
1789 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1790 return stat(buf, &s) == 0;
1794 system_if_dump_info(struct device *dev, struct blob_buf *b)
1796 struct ethtool_cmd ecmd;
1801 memset(&ecmd, 0, sizeof(ecmd));
1802 memset(&ifr, 0, sizeof(ifr));
1803 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
1804 ifr.ifr_data = (caddr_t) &ecmd;
1805 ecmd.cmd = ETHTOOL_GSET;
1807 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1808 c = blobmsg_open_array(b, "link-advertising");
1809 system_add_link_modes(b, ecmd.advertising);
1810 blobmsg_close_array(b, c);
1812 c = blobmsg_open_array(b, "link-partner-advertising");
1813 system_add_link_modes(b, ecmd.lp_advertising);
1814 blobmsg_close_array(b, c);
1816 c = blobmsg_open_array(b, "link-supported");
1817 system_add_link_modes(b, ecmd.supported);
1818 blobmsg_close_array(b, c);
1820 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1821 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1822 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1823 blobmsg_add_string_buffer(b);
1825 blobmsg_add_u8(b, "autoneg", !!ecmd.autoneg);
1832 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1834 const char *const counters[] = {
1835 "collisions", "rx_frame_errors", "tx_compressed",
1836 "multicast", "rx_length_errors", "tx_dropped",
1837 "rx_bytes", "rx_missed_errors", "tx_errors",
1838 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1839 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1840 "rx_dropped", "tx_aborted_errors", "tx_packets",
1841 "rx_errors", "tx_bytes", "tx_window_errors",
1842 "rx_fifo_errors", "tx_carrier_errors",
1849 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1850 stats_dir = open(buf, O_DIRECTORY);
1854 for (i = 0; i < ARRAY_SIZE(counters); i++)
1855 if (read_uint64_file(stats_dir, counters[i], &val))
1856 blobmsg_add_u64(b, counters[i], val);
1862 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1864 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1865 int alen = v4 ? 4 : 16;
1866 unsigned int flags = 0;
1867 struct ifaddrmsg ifa = {
1868 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1869 .ifa_prefixlen = addr->mask,
1870 .ifa_index = dev->ifindex,
1874 if (cmd == RTM_NEWADDR)
1875 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1877 msg = nlmsg_alloc_simple(cmd, flags);
1881 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1882 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1884 if (addr->broadcast)
1885 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1886 if (addr->point_to_point)
1887 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1889 time_t now = system_get_rtime();
1890 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1892 if (addr->preferred_until) {
1893 int64_t preferred = addr->preferred_until - now;
1896 else if (preferred > UINT32_MAX)
1897 preferred = UINT32_MAX;
1899 cinfo.ifa_prefered = preferred;
1902 if (addr->valid_until) {
1903 int64_t valid = addr->valid_until - now;
1908 else if (valid > UINT32_MAX)
1911 cinfo.ifa_valid = valid;
1914 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1916 if (cmd == RTM_NEWADDR && (addr->flags & DEVADDR_OFFLINK))
1917 nla_put_u32(msg, IFA_FLAGS, IFA_F_NOPREFIXROUTE);
1920 return system_rtnl_call(msg);
1923 int system_add_address(struct device *dev, struct device_addr *addr)
1925 return system_addr(dev, addr, RTM_NEWADDR);
1928 int system_del_address(struct device *dev, struct device_addr *addr)
1930 return system_addr(dev, addr, RTM_DELADDR);
1933 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1935 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1937 unsigned int flags = 0;
1940 have_gw = !!route->nexthop.in.s_addr;
1942 have_gw = route->nexthop.in6.s6_addr32[0] ||
1943 route->nexthop.in6.s6_addr32[1] ||
1944 route->nexthop.in6.s6_addr32[2] ||
1945 route->nexthop.in6.s6_addr32[3];
1947 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1948 ? route->table : RT_TABLE_MAIN;
1950 struct rtmsg rtm = {
1951 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1952 .rtm_dst_len = route->mask,
1953 .rtm_src_len = route->sourcemask,
1954 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1955 .rtm_protocol = (route->flags & DEVROUTE_PROTO) ? route->proto : RTPROT_STATIC,
1956 .rtm_scope = RT_SCOPE_NOWHERE,
1957 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1958 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1962 if (cmd == RTM_NEWROUTE) {
1963 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1965 if (!dev) { /* Add null-route */
1966 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1967 rtm.rtm_type = RTN_UNREACHABLE;
1970 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1973 if (route->flags & DEVROUTE_TYPE) {
1974 rtm.rtm_type = route->type;
1975 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
1976 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
1977 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
1978 rtm.rtm_table = RT_TABLE_LOCAL;
1981 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT) {
1982 rtm.rtm_scope = RT_SCOPE_HOST;
1983 } else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
1984 rtm.rtm_type == RTN_ANYCAST) {
1985 rtm.rtm_scope = RT_SCOPE_LINK;
1986 } else if (rtm.rtm_type == RTN_BLACKHOLE || rtm.rtm_type == RTN_UNREACHABLE ||
1987 rtm.rtm_type == RTN_PROHIBIT || rtm.rtm_type == RTN_FAILED_POLICY ||
1988 rtm.rtm_type == RTN_THROW) {
1989 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1994 msg = nlmsg_alloc_simple(cmd, flags);
1998 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
2001 nla_put(msg, RTA_DST, alen, &route->addr);
2003 if (route->sourcemask) {
2004 if (rtm.rtm_family == AF_INET)
2005 nla_put(msg, RTA_PREFSRC, alen, &route->source);
2007 nla_put(msg, RTA_SRC, alen, &route->source);
2010 if (route->metric > 0)
2011 nla_put_u32(msg, RTA_PRIORITY, route->metric);
2014 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
2017 nla_put_u32(msg, RTA_OIF, dev->ifindex);
2020 nla_put_u32(msg, RTA_TABLE, table);
2022 if (route->flags & DEVROUTE_MTU) {
2023 struct nlattr *metrics;
2025 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
2026 goto nla_put_failure;
2028 nla_put_u32(msg, RTAX_MTU, route->mtu);
2030 nla_nest_end(msg, metrics);
2033 return system_rtnl_call(msg);
2040 int system_add_route(struct device *dev, struct device_route *route)
2042 return system_rt(dev, route, RTM_NEWROUTE);
2045 int system_del_route(struct device *dev, struct device_route *route)
2047 return system_rt(dev, route, RTM_DELROUTE);
2050 int system_flush_routes(void)
2052 const char *names[] = {
2053 "/proc/sys/net/ipv4/route/flush",
2054 "/proc/sys/net/ipv6/route/flush"
2058 for (i = 0; i < ARRAY_SIZE(names); i++) {
2059 fd = open(names[i], O_WRONLY);
2063 if (write(fd, "-1", 2)) {}
2069 bool system_resolve_rt_type(const char *type, unsigned int *id)
2071 return system_rtn_aton(type, id);
2074 bool system_resolve_rt_proto(const char *type, unsigned int *id)
2078 unsigned int n, proto = 256;
2079 n = strtoul(type, &e, 0);
2080 if (!*e && e != type)
2082 else if (!strcmp(type, "unspec"))
2083 proto = RTPROT_UNSPEC;
2084 else if (!strcmp(type, "kernel"))
2085 proto = RTPROT_KERNEL;
2086 else if (!strcmp(type, "boot"))
2087 proto = RTPROT_BOOT;
2088 else if (!strcmp(type, "static"))
2089 proto = RTPROT_STATIC;
2090 else if ((f = fopen("/etc/iproute2/rt_protos", "r")) != NULL) {
2091 while (fgets(buf, sizeof(buf) - 1, f) != NULL) {
2092 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
2095 n = strtoul(e, NULL, 10);
2096 e = strtok(NULL, " \t\n");
2098 if (e && !strcmp(e, type)) {
2113 bool system_resolve_rt_table(const char *name, unsigned int *id)
2117 unsigned int n, table = RT_TABLE_UNSPEC;
2119 /* first try to parse table as number */
2120 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
2123 /* handle well known aliases */
2124 else if (!strcmp(name, "default"))
2125 table = RT_TABLE_DEFAULT;
2126 else if (!strcmp(name, "main"))
2127 table = RT_TABLE_MAIN;
2128 else if (!strcmp(name, "local"))
2129 table = RT_TABLE_LOCAL;
2131 /* try to look up name in /etc/iproute2/rt_tables */
2132 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
2134 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
2136 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
2139 n = strtoul(e, NULL, 10);
2140 e = strtok(NULL, " \t\n");
2142 if (e && !strcmp(e, name))
2152 if (table == RT_TABLE_UNSPEC)
2159 bool system_is_default_rt_table(unsigned int id)
2161 return (id == RT_TABLE_MAIN);
2164 bool system_resolve_rpfilter(const char *filter, unsigned int *id)
2169 if (!strcmp(filter, "strict"))
2171 else if (!strcmp(filter, "loose"))
2174 n = strtoul(filter, &e, 0);
2175 if (*e || e == filter || n > 2)
2183 static int system_iprule(struct iprule *rule, int cmd)
2185 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
2188 struct rtmsg rtm = {
2189 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
2190 .rtm_protocol = RTPROT_STATIC,
2191 .rtm_scope = RT_SCOPE_UNIVERSE,
2192 .rtm_table = RT_TABLE_UNSPEC,
2193 .rtm_type = RTN_UNSPEC,
2197 if (cmd == RTM_NEWRULE)
2198 rtm.rtm_type = RTN_UNICAST;
2201 rtm.rtm_flags |= FIB_RULE_INVERT;
2203 if (rule->flags & IPRULE_SRC)
2204 rtm.rtm_src_len = rule->src_mask;
2206 if (rule->flags & IPRULE_DEST)
2207 rtm.rtm_dst_len = rule->dest_mask;
2209 if (rule->flags & IPRULE_TOS)
2210 rtm.rtm_tos = rule->tos;
2212 if (rule->flags & IPRULE_LOOKUP) {
2213 if (rule->lookup < 256)
2214 rtm.rtm_table = rule->lookup;
2217 if (rule->flags & IPRULE_ACTION)
2218 rtm.rtm_type = rule->action;
2219 else if (rule->flags & IPRULE_GOTO)
2220 rtm.rtm_type = FR_ACT_GOTO;
2221 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
2222 rtm.rtm_type = FR_ACT_NOP;
2224 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
2229 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
2231 if (rule->flags & IPRULE_IN)
2232 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
2234 if (rule->flags & IPRULE_OUT)
2235 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
2237 if (rule->flags & IPRULE_SRC)
2238 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
2240 if (rule->flags & IPRULE_DEST)
2241 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
2243 if (rule->flags & IPRULE_PRIORITY)
2244 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
2245 else if (cmd == RTM_NEWRULE)
2246 nla_put_u32(msg, FRA_PRIORITY, rule->order);
2248 if (rule->flags & IPRULE_FWMARK)
2249 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
2251 if (rule->flags & IPRULE_FWMASK)
2252 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
2254 if (rule->flags & IPRULE_LOOKUP) {
2255 if (rule->lookup >= 256)
2256 nla_put_u32(msg, FRA_TABLE, rule->lookup);
2259 if (rule->flags & IPRULE_SUP_PREFIXLEN)
2260 nla_put_u32(msg, FRA_SUPPRESS_PREFIXLEN, rule->sup_prefixlen);
2262 if (rule->flags & IPRULE_GOTO)
2263 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
2265 return system_rtnl_call(msg);
2268 int system_add_iprule(struct iprule *rule)
2270 return system_iprule(rule, RTM_NEWRULE);
2273 int system_del_iprule(struct iprule *rule)
2275 return system_iprule(rule, RTM_DELRULE);
2278 int system_flush_iprules(void)
2283 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
2284 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
2286 memset(&rule, 0, sizeof(rule));
2289 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2292 rule.lookup = RT_TABLE_LOCAL;
2293 rv |= system_iprule(&rule, RTM_NEWRULE);
2295 rule.priority = 32766;
2296 rule.lookup = RT_TABLE_MAIN;
2297 rv |= system_iprule(&rule, RTM_NEWRULE);
2299 rule.priority = 32767;
2300 rule.lookup = RT_TABLE_DEFAULT;
2301 rv |= system_iprule(&rule, RTM_NEWRULE);
2304 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2307 rule.lookup = RT_TABLE_LOCAL;
2308 rv |= system_iprule(&rule, RTM_NEWRULE);
2310 rule.priority = 32766;
2311 rule.lookup = RT_TABLE_MAIN;
2312 rv |= system_iprule(&rule, RTM_NEWRULE);
2317 bool system_resolve_iprule_action(const char *action, unsigned int *id)
2319 return system_rtn_aton(action, id);
2322 time_t system_get_rtime(void)
2327 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
2330 if (gettimeofday(&tv, NULL) == 0)
2337 #define IP_DF 0x4000
2340 static int tunnel_ioctl(const char *name, int cmd, void *p)
2344 memset(&ifr, 0, sizeof(ifr));
2345 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name) - 1);
2346 ifr.ifr_ifru.ifru_data = p;
2347 return ioctl(sock_ioctl, cmd, &ifr);
2350 #ifdef IFLA_IPTUN_MAX
2351 static int system_add_ip6_tunnel(const char *name, const unsigned int link,
2352 struct blob_attr **tb)
2354 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2355 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2356 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2357 struct blob_attr *cur;
2358 int ret = 0, ttl = 0;
2363 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2364 nla_put_string(nlm, IFLA_IFNAME, name);
2367 nla_put_u32(nlm, IFLA_LINK, link);
2369 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2375 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2376 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2383 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2385 if ((cur = tb[TUNNEL_ATTR_TTL]))
2386 ttl = blobmsg_get_u32(cur);
2388 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2389 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2391 struct in6_addr in6buf;
2392 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2393 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2397 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2400 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2401 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2405 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2408 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2409 struct blob_attr *tb_data[__IPIP6_DATA_ATTR_MAX];
2410 uint32_t tun_flags = IP6_TNL_F_IGN_ENCAP_LIMIT;
2412 blobmsg_parse(ipip6_data_attr_list.params, __IPIP6_DATA_ATTR_MAX, tb_data,
2413 blobmsg_data(cur), blobmsg_len(cur));
2415 if ((cur = tb_data[IPIP6_DATA_ENCAPLIMIT])) {
2416 char *str = blobmsg_get_string(cur);
2418 if (strcmp(str, "ignore")) {
2420 unsigned encap_limit = strtoul(str, &e, 0);
2422 if (e == str || *e || encap_limit > 255) {
2427 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, encap_limit);
2428 tun_flags &= ~IP6_TNL_F_IGN_ENCAP_LIMIT;
2432 #ifdef IFLA_IPTUN_FMR_MAX
2433 if ((cur = tb_data[IPIP6_DATA_FMRS])) {
2434 struct blob_attr *rcur;
2435 unsigned rrem, fmrcnt = 0;
2436 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2443 blobmsg_for_each_attr(rcur, cur, rrem) {
2444 struct blob_attr *tb_fmr[__FMR_DATA_ATTR_MAX], *tb_cur;
2445 struct in6_addr ip6prefix;
2446 struct in_addr ip4prefix;
2447 unsigned ip4len, ip6len, ealen, offset;
2449 blobmsg_parse(fmr_data_attr_list.params, __FMR_DATA_ATTR_MAX, tb_fmr,
2450 blobmsg_data(rcur), blobmsg_len(rcur));
2452 if (!(tb_cur = tb_fmr[FMR_DATA_PREFIX6]) ||
2453 !parse_ip_and_netmask(AF_INET6,
2454 blobmsg_data(tb_cur), &ip6prefix,
2460 if (!(tb_cur = tb_fmr[FMR_DATA_PREFIX4]) ||
2461 !parse_ip_and_netmask(AF_INET,
2462 blobmsg_data(tb_cur), &ip4prefix,
2468 if (!(tb_cur = tb_fmr[FMR_DATA_EALEN])) {
2472 ealen = blobmsg_get_u32(tb_cur);
2474 if (!(tb_cur = tb_fmr[FMR_DATA_OFFSET])) {
2478 offset = blobmsg_get_u32(tb_cur);
2480 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2486 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2487 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2488 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2489 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2490 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2491 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2493 nla_nest_end(nlm, rule);
2496 nla_nest_end(nlm, fmrs);
2500 nla_put_u32(nlm, IFLA_IPTUN_FLAGS, tun_flags);
2503 nla_nest_end(nlm, infodata);
2504 nla_nest_end(nlm, linkinfo);
2506 return system_rtnl_call(nlm);
2514 #ifdef IFLA_IPTUN_MAX
2515 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
2516 static int system_add_gre_tunnel(const char *name, const char *kind,
2517 const unsigned int link, struct blob_attr **tb, bool v6)
2520 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2521 struct blob_attr *cur;
2522 uint32_t ikey = 0, okey = 0, flowinfo = 0, flags6 = IP6_TNL_F_IGN_ENCAP_LIMIT;
2523 uint16_t iflags = 0, oflags = 0;
2525 int ret = 0, ttl = 0;
2526 unsigned encap_limit = 0;
2528 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2532 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2533 nla_put_string(nlm, IFLA_IFNAME, name);
2535 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2541 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2542 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2549 nla_put_u32(nlm, IFLA_GRE_LINK, link);
2551 if ((cur = tb[TUNNEL_ATTR_TTL]))
2552 ttl = blobmsg_get_u32(cur);
2554 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2555 char *str = blobmsg_get_string(cur);
2556 if (strcmp(str, "inherit")) {
2559 if (!system_tos_aton(str, &uval)) {
2565 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
2570 flags6 |= IP6_TNL_F_USE_ORIG_TCLASS;
2576 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2577 struct blob_attr *tb_data[__GRE_DATA_ATTR_MAX];
2579 blobmsg_parse(gre_data_attr_list.params, __GRE_DATA_ATTR_MAX, tb_data,
2580 blobmsg_data(cur), blobmsg_len(cur));
2582 if ((cur = tb_data[GRE_DATA_IKEY])) {
2583 if ((ikey = blobmsg_get_u32(cur)))
2587 if ((cur = tb_data[GRE_DATA_OKEY])) {
2588 if ((okey = blobmsg_get_u32(cur)))
2592 if ((cur = tb_data[GRE_DATA_ICSUM])) {
2593 if (blobmsg_get_bool(cur))
2597 if ((cur = tb_data[GRE_DATA_OCSUM])) {
2598 if (blobmsg_get_bool(cur))
2602 if ((cur = tb_data[GRE_DATA_ISEQNO])) {
2603 if (blobmsg_get_bool(cur))
2607 if ((cur = tb_data[GRE_DATA_OSEQNO])) {
2608 if (blobmsg_get_bool(cur))
2612 if ((cur = tb_data[GRE_DATA_ENCAPLIMIT])) {
2613 char *str = blobmsg_get_string(cur);
2615 if (strcmp(str, "ignore")) {
2618 encap_limit = strtoul(str, &e, 0);
2620 if (e == str || *e || encap_limit > 255) {
2625 flags6 &= ~IP6_TNL_F_IGN_ENCAP_LIMIT;
2631 struct in6_addr in6buf;
2632 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2633 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2637 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
2640 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2641 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2645 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
2648 if (!(flags6 & IP6_TNL_F_IGN_ENCAP_LIMIT))
2649 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, encap_limit);
2652 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
2655 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags6);
2660 struct in_addr inbuf;
2663 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2664 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2668 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
2671 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2672 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2676 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
2678 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
2680 okey = inbuf.s_addr;
2685 ikey = inbuf.s_addr;
2691 if ((cur = tb[TUNNEL_ATTR_DF]))
2692 set_df = blobmsg_get_bool(cur);
2695 /* ttl != 0 and nopmtudisc are incompatible */
2703 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
2705 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
2709 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
2712 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
2715 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
2718 nla_put_u32(nlm, IFLA_GRE_OKEY, htonl(okey));
2721 nla_put_u32(nlm, IFLA_GRE_IKEY, htonl(ikey));
2723 nla_nest_end(nlm, infodata);
2724 nla_nest_end(nlm, linkinfo);
2726 return system_rtnl_call(nlm);
2735 static int system_add_vti_tunnel(const char *name, const char *kind,
2736 const unsigned int link, struct blob_attr **tb, bool v6)
2739 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2740 struct blob_attr *cur;
2743 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2747 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2748 nla_put_string(nlm, IFLA_IFNAME, name);
2750 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2756 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2757 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2764 nla_put_u32(nlm, IFLA_VTI_LINK, link);
2767 struct in6_addr in6buf;
2768 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2769 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2773 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(in6buf), &in6buf);
2776 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2777 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2781 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(in6buf), &in6buf);
2785 struct in_addr inbuf;
2787 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2788 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2792 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(inbuf), &inbuf);
2795 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2796 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2800 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(inbuf), &inbuf);
2805 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2806 struct blob_attr *tb_data[__VTI_DATA_ATTR_MAX];
2807 uint32_t ikey = 0, okey = 0;
2809 blobmsg_parse(vti_data_attr_list.params, __VTI_DATA_ATTR_MAX, tb_data,
2810 blobmsg_data(cur), blobmsg_len(cur));
2812 if ((cur = tb_data[VTI_DATA_IKEY])) {
2813 if ((ikey = blobmsg_get_u32(cur)))
2814 nla_put_u32(nlm, IFLA_VTI_IKEY, htonl(ikey));
2817 if ((cur = tb_data[VTI_DATA_OKEY])) {
2818 if ((okey = blobmsg_get_u32(cur)))
2819 nla_put_u32(nlm, IFLA_VTI_OKEY, htonl(okey));
2823 nla_nest_end(nlm, infodata);
2824 nla_nest_end(nlm, linkinfo);
2826 return system_rtnl_call(nlm);
2834 #ifdef IFLA_VXLAN_MAX
2835 static int system_add_vxlan(const char *name, const unsigned int link, struct blob_attr **tb, bool v6)
2837 struct blob_attr *tb_data[__VXLAN_DATA_ATTR_MAX];
2839 struct nlattr *linkinfo, *data;
2840 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
2841 struct blob_attr *cur;
2844 if ((cur = tb[TUNNEL_ATTR_DATA]))
2845 blobmsg_parse(vxlan_data_attr_list.params, __VXLAN_DATA_ATTR_MAX, tb_data,
2846 blobmsg_data(cur), blobmsg_len(cur));
2850 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
2855 nlmsg_append(msg, &iim, sizeof(iim), 0);
2857 nla_put_string(msg, IFLA_IFNAME, name);
2859 if ((cur = tb_data[VXLAN_DATA_ATTR_MACADDR])) {
2860 struct ether_addr *ea = ether_aton(blobmsg_get_string(cur));
2866 nla_put(msg, IFLA_ADDRESS, ETH_ALEN, ea);
2869 if ((cur = tb[TUNNEL_ATTR_MTU])) {
2870 uint32_t mtu = blobmsg_get_u32(cur);
2871 nla_put_u32(msg, IFLA_MTU, mtu);
2874 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO))) {
2879 nla_put_string(msg, IFLA_INFO_KIND, "vxlan");
2881 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) {
2887 nla_put_u32(msg, IFLA_VXLAN_LINK, link);
2889 if ((cur = tb_data[VXLAN_DATA_ATTR_ID])) {
2890 uint32_t id = blobmsg_get_u32(cur);
2891 if (id >= (1u << 24) - 1) {
2896 nla_put_u32(msg, IFLA_VXLAN_ID, id);
2900 struct in6_addr in6buf;
2901 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2902 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2906 nla_put(msg, IFLA_VXLAN_LOCAL6, sizeof(in6buf), &in6buf);
2909 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2910 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2914 nla_put(msg, IFLA_VXLAN_GROUP6, sizeof(in6buf), &in6buf);
2917 struct in_addr inbuf;
2919 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2920 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2924 nla_put(msg, IFLA_VXLAN_LOCAL, sizeof(inbuf), &inbuf);
2927 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2928 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2932 nla_put(msg, IFLA_VXLAN_GROUP, sizeof(inbuf), &inbuf);
2936 uint32_t port = 4789;
2937 if ((cur = tb_data[VXLAN_DATA_ATTR_PORT])) {
2938 port = blobmsg_get_u32(cur);
2939 if (port < 1 || port > 65535) {
2944 nla_put_u16(msg, IFLA_VXLAN_PORT, htons(port));
2946 if ((cur = tb_data[VXLAN_DATA_ATTR_RXCSUM])) {
2947 bool rxcsum = blobmsg_get_bool(cur);
2948 nla_put_u8(msg, IFLA_VXLAN_UDP_ZERO_CSUM6_RX, !rxcsum);
2951 if ((cur = tb_data[VXLAN_DATA_ATTR_TXCSUM])) {
2952 bool txcsum = blobmsg_get_bool(cur);
2953 nla_put_u8(msg, IFLA_VXLAN_UDP_CSUM, txcsum);
2954 nla_put_u8(msg, IFLA_VXLAN_UDP_ZERO_CSUM6_TX, !txcsum);
2957 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2958 char *str = blobmsg_get_string(cur);
2961 if (strcmp(str, "inherit")) {
2962 if (!system_tos_aton(str, &tos)) {
2968 nla_put_u8(msg, IFLA_VXLAN_TOS, tos);
2971 if ((cur = tb[TUNNEL_ATTR_TTL])) {
2972 uint32_t ttl = blobmsg_get_u32(cur);
2973 if (ttl < 1 || ttl > 255) {
2978 nla_put_u8(msg, IFLA_VXLAN_TTL, ttl);
2981 nla_nest_end(msg, data);
2982 nla_nest_end(msg, linkinfo);
2984 ret = system_rtnl_call(msg);
2986 D(SYSTEM, "Error adding vxlan '%s': %d\n", name, ret);
2996 static int system_add_sit_tunnel(const char *name, const unsigned int link, struct blob_attr **tb)
2998 struct blob_attr *cur;
3001 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
3005 if ((cur = tb[TUNNEL_ATTR_DATA])) {
3006 struct blob_attr *tb_data[__SIXRD_DATA_ATTR_MAX];
3008 struct ip_tunnel_6rd p6;
3010 blobmsg_parse(sixrd_data_attr_list.params, __SIXRD_DATA_ATTR_MAX, tb_data,
3011 blobmsg_data(cur), blobmsg_len(cur));
3013 memset(&p6, 0, sizeof(p6));
3015 if ((cur = tb_data[SIXRD_DATA_PREFIX])) {
3016 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
3017 &p6.prefix, &mask) || mask > 128) {
3022 p6.prefixlen = mask;
3025 if ((cur = tb_data[SIXRD_DATA_RELAY_PREFIX])) {
3026 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
3027 &p6.relay_prefix, &mask) || mask > 32) {
3032 p6.relay_prefixlen = mask;
3035 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
3045 __system_del_ip_tunnel(name, tb);
3049 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
3051 struct blob_attr *cur;
3053 struct ip_tunnel_parm p = {
3062 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
3063 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
3066 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
3067 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
3070 if ((cur = tb[TUNNEL_ATTR_DF]))
3071 set_df = blobmsg_get_bool(cur);
3073 if ((cur = tb[TUNNEL_ATTR_TTL]))
3074 p.iph.ttl = blobmsg_get_u32(cur);
3076 if ((cur = tb[TUNNEL_ATTR_TOS])) {
3077 char *str = blobmsg_get_string(cur);
3078 if (strcmp(str, "inherit")) {
3081 if (!system_tos_aton(str, &uval))
3089 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
3090 /* ttl !=0 and nopmtudisc are incompatible */
3091 if (p.iph.ttl && p.iph.frag_off == 0)
3094 strncpy(p.name, name, sizeof(p.name) - 1);
3096 switch (p.iph.protocol) {
3098 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
3100 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
3107 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
3109 struct blob_attr *cur;
3112 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
3114 str = blobmsg_data(cur);
3116 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
3117 !strcmp(str, "greip6") || !strcmp(str, "gretapip6") ||
3118 !strcmp(str, "vtiip") || !strcmp(str, "vtiip6") ||
3119 !strcmp(str, "vxlan") || !strcmp(str, "vxlan6"))
3120 return system_link_del(name);
3122 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
3125 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
3127 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
3129 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
3130 blob_data(attr), blob_len(attr));
3132 return __system_del_ip_tunnel(name, tb);
3135 int system_update_ipv6_mtu(struct device *dev, int mtu)
3141 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
3144 fd = open(buf, O_RDWR);
3149 ssize_t len = read(fd, buf, sizeof(buf) - 1);
3156 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) > 0)
3165 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
3167 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
3168 struct blob_attr *cur;
3171 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
3172 blob_data(attr), blob_len(attr));
3174 __system_del_ip_tunnel(name, tb);
3176 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
3178 str = blobmsg_data(cur);
3180 unsigned int ttl = 0;
3181 if ((cur = tb[TUNNEL_ATTR_TTL])) {
3182 ttl = blobmsg_get_u32(cur);
3187 unsigned int link = 0;
3188 if ((cur = tb[TUNNEL_ATTR_LINK])) {
3189 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
3193 if (iface->l3_dev.dev)
3194 link = iface->l3_dev.dev->ifindex;
3197 if (!strcmp(str, "sit"))
3198 return system_add_sit_tunnel(name, link, tb);
3199 #ifdef IFLA_IPTUN_MAX
3200 else if (!strcmp(str, "ipip6")) {
3201 return system_add_ip6_tunnel(name, link, tb);
3202 } else if (!strcmp(str, "greip")) {
3203 return system_add_gre_tunnel(name, "gre", link, tb, false);
3204 } else if (!strcmp(str, "gretapip")) {
3205 return system_add_gre_tunnel(name, "gretap", link, tb, false);
3206 } else if (!strcmp(str, "greip6")) {
3207 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
3208 } else if (!strcmp(str, "gretapip6")) {
3209 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
3211 } else if (!strcmp(str, "vtiip")) {
3212 return system_add_vti_tunnel(name, "vti", link, tb, false);
3213 } else if (!strcmp(str, "vtiip6")) {
3214 return system_add_vti_tunnel(name, "vti6", link, tb, true);
3216 #ifdef IFLA_VXLAN_MAX
3217 } else if(!strcmp(str, "vxlan")) {
3218 return system_add_vxlan(name, link, tb, false);
3219 } else if(!strcmp(str, "vxlan6")) {
3220 return system_add_vxlan(name, link, tb, true);
3223 } else if (!strcmp(str, "ipip")) {
3224 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);