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>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2
10 * as published by the Free Software Foundation
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
19 #include <sys/socket.h>
20 #include <sys/ioctl.h>
22 #include <sys/syscall.h>
25 #include <net/if_arp.h>
27 #include <arpa/inet.h>
28 #include <netinet/in.h>
30 #include <linux/rtnetlink.h>
31 #include <linux/sockios.h>
33 #include <linux/if_addr.h>
34 #include <linux/if_link.h>
35 #include <linux/if_vlan.h>
36 #include <linux/if_bridge.h>
37 #include <linux/if_tunnel.h>
38 #include <linux/ip6_tunnel.h>
39 #include <linux/ethtool.h>
40 #include <linux/fib_rules.h>
41 #include <linux/version.h>
43 #ifndef RTN_FAILED_POLICY
44 #define RTN_FAILED_POLICY 12
47 #ifndef RT_TABLE_PRELOCAL
48 #define RT_TABLE_PRELOCAL 128
51 #ifndef IFA_F_NOPREFIXROUTE
52 #define IFA_F_NOPREFIXROUTE 0x200
56 #define IFA_FLAGS (IFA_MULTICAST + 1)
66 #include <netlink/msg.h>
67 #include <netlink/attr.h>
68 #include <netlink/socket.h>
69 #include <libubox/uloop.h>
76 struct uloop_fd uloop;
81 static int sock_ioctl = -1;
82 static struct nl_sock *sock_rtnl = NULL;
84 static int cb_rtnl_event(struct nl_msg *msg, void *arg);
85 static void handle_hotplug_event(struct uloop_fd *u, unsigned int events);
87 static char dev_buf[256];
90 handler_nl_event(struct uloop_fd *u, unsigned int events)
92 struct event_socket *ev = container_of(u, struct event_socket, uloop);
94 socklen_t errlen = sizeof(err);
97 nl_recvmsgs_default(ev->sock);
101 if (getsockopt(u->fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen))
106 // Increase rx buffer size on netlink socket
108 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
111 // Request full dump since some info got dropped
112 struct rtgenmsg msg = { .rtgen_family = AF_UNSPEC };
113 nl_send_simple(ev->sock, RTM_GETLINK, NLM_F_DUMP, &msg, sizeof(msg));
123 uloop_fd_delete(&ev->uloop);
127 static struct nl_sock *
128 create_socket(int protocol, int groups)
130 struct nl_sock *sock;
132 sock = nl_socket_alloc();
137 nl_join_groups(sock, groups);
139 if (nl_connect(sock, protocol))
146 create_raw_event_socket(struct event_socket *ev, int protocol, int groups,
147 uloop_fd_handler cb, int flags)
149 ev->sock = create_socket(protocol, groups);
153 ev->uloop.fd = nl_socket_get_fd(ev->sock);
155 if (uloop_fd_add(&ev->uloop, ULOOP_READ|flags))
162 create_event_socket(struct event_socket *ev, int protocol,
163 int (*cb)(struct nl_msg *msg, void *arg))
165 if (!create_raw_event_socket(ev, protocol, 0, handler_nl_event, ULOOP_ERROR_CB))
168 // Install the valid custom callback handler
169 nl_socket_modify_cb(ev->sock, NL_CB_VALID, NL_CB_CUSTOM, cb, NULL);
171 // Disable sequence number checking on event sockets
172 nl_socket_disable_seq_check(ev->sock);
174 // Increase rx buffer size to 65K on event sockets
176 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
183 system_rtn_aton(const char *src, unsigned int *dst)
188 if (!strcmp(src, "local"))
190 else if (!strcmp(src, "nat"))
192 else if (!strcmp(src, "broadcast"))
194 else if (!strcmp(src, "anycast"))
196 else if (!strcmp(src, "multicast"))
198 else if (!strcmp(src, "prohibit"))
200 else if (!strcmp(src, "unreachable"))
202 else if (!strcmp(src, "blackhole"))
204 else if (!strcmp(src, "xresolve"))
206 else if (!strcmp(src, "unicast"))
208 else if (!strcmp(src, "throw"))
210 else if (!strcmp(src, "failed_policy"))
211 n = RTN_FAILED_POLICY;
213 n = strtoul(src, &e, 0);
214 if (!e || *e || e == src || n > 255)
223 system_tos_aton(const char *src, unsigned *dst)
227 *dst = strtoul(src, &e, 16);
228 if (e == src || *e || *dst > 255)
234 int system_init(void)
236 static struct event_socket rtnl_event;
237 static struct event_socket hotplug_event;
239 sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0);
240 system_fd_set_cloexec(sock_ioctl);
242 // Prepare socket for routing / address control
243 sock_rtnl = create_socket(NETLINK_ROUTE, 0);
247 if (!create_event_socket(&rtnl_event, NETLINK_ROUTE, cb_rtnl_event))
250 if (!create_raw_event_socket(&hotplug_event, NETLINK_KOBJECT_UEVENT, 1,
251 handle_hotplug_event, 0))
254 // Receive network link events form kernel
255 nl_socket_add_membership(rtnl_event.sock, RTNLGRP_LINK);
260 static void system_set_sysctl(const char *path, const char *val)
264 fd = open(path, O_WRONLY);
268 if (write(fd, val, strlen(val))) {}
272 static void system_set_dev_sysctl(const char *path, const char *device, const char *val)
274 snprintf(dev_buf, sizeof(dev_buf), path, device);
275 system_set_sysctl(dev_buf, val);
278 static void system_set_disable_ipv6(struct device *dev, const char *val)
280 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val);
283 static void system_set_rpfilter(struct device *dev, const char *val)
285 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter", dev->ifname, val);
288 static void system_set_acceptlocal(struct device *dev, const char *val)
290 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local", dev->ifname, val);
293 static void system_set_igmpversion(struct device *dev, const char *val)
295 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version", dev->ifname, val);
298 static void system_set_mldversion(struct device *dev, const char *val)
300 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version", dev->ifname, val);
303 static void system_set_neigh4reachabletime(struct device *dev, const char *val)
305 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms", dev->ifname, val);
308 static void system_set_neigh6reachabletime(struct device *dev, const char *val)
310 system_set_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms", dev->ifname, val);
313 static void system_set_dadtransmits(struct device *dev, const char *val)
315 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits", dev->ifname, val);
318 static void system_bridge_set_multicast_to_unicast(struct device *dev, const char *val)
320 system_set_dev_sysctl("/sys/class/net/%s/brport/multicast_to_unicast", dev->ifname, val);
323 static void system_bridge_set_hairpin_mode(struct device *dev, const char *val)
325 system_set_dev_sysctl("/sys/class/net/%s/brport/hairpin_mode", dev->ifname, val);
328 static void system_bridge_set_multicast_router(struct device *dev, const char *val, bool bridge)
330 system_set_dev_sysctl(bridge ? "/sys/class/net/%s/bridge/multicast_router" :
331 "/sys/class/net/%s/brport/multicast_router",
335 static int system_get_sysctl(const char *path, char *buf, const size_t buf_sz)
337 int fd = -1, ret = -1;
339 fd = open(path, O_RDONLY);
343 ssize_t len = read(fd, buf, buf_sz - 1);
357 system_get_dev_sysctl(const char *path, const char *device, char *buf, const size_t buf_sz)
359 snprintf(dev_buf, sizeof(dev_buf), path, device);
360 return system_get_sysctl(dev_buf, buf, buf_sz);
363 static int system_get_disable_ipv6(struct device *dev, char *buf, const size_t buf_sz)
365 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6",
366 dev->ifname, buf, buf_sz);
369 static int system_get_rpfilter(struct device *dev, char *buf, const size_t buf_sz)
371 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter",
372 dev->ifname, buf, buf_sz);
375 static int system_get_acceptlocal(struct device *dev, char *buf, const size_t buf_sz)
377 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local",
378 dev->ifname, buf, buf_sz);
381 static int system_get_igmpversion(struct device *dev, char *buf, const size_t buf_sz)
383 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version",
384 dev->ifname, buf, buf_sz);
387 static int system_get_mldversion(struct device *dev, char *buf, const size_t buf_sz)
389 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version",
390 dev->ifname, buf, buf_sz);
393 static int system_get_neigh4reachabletime(struct device *dev, char *buf, const size_t buf_sz)
395 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms",
396 dev->ifname, buf, buf_sz);
399 static int system_get_neigh6reachabletime(struct device *dev, char *buf, const size_t buf_sz)
401 return system_get_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms",
402 dev->ifname, buf, buf_sz);
405 static int system_get_dadtransmits(struct device *dev, char *buf, const size_t buf_sz)
407 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits",
408 dev->ifname, buf, buf_sz);
411 // Evaluate netlink messages
412 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
414 struct nlmsghdr *nh = nlmsg_hdr(msg);
415 struct nlattr *nla[__IFLA_MAX];
419 if (nh->nlmsg_type != RTM_NEWLINK)
422 nlmsg_parse(nh, sizeof(struct ifinfomsg), nla, __IFLA_MAX - 1, NULL);
423 if (!nla[IFLA_IFNAME])
426 struct device *dev = device_get(nla_data(nla[IFLA_IFNAME]), false);
430 if (!system_get_dev_sysctl("/sys/class/net/%s/carrier", dev->ifname, buf, sizeof(buf)))
431 link_state = strtoul(buf, NULL, 0);
433 device_set_link(dev, link_state ? true : false);
440 handle_hotplug_msg(char *data, int size)
442 const char *subsystem = NULL, *interface = NULL;
443 char *cur, *end, *sep;
448 if (!strncmp(data, "add@", 4))
450 else if (!strncmp(data, "remove@", 7))
455 skip = strlen(data) + 1;
458 for (cur = data + skip; cur < end; cur += skip) {
459 skip = strlen(cur) + 1;
461 sep = strchr(cur, '=');
466 if (!strcmp(cur, "INTERFACE"))
468 else if (!strcmp(cur, "SUBSYSTEM")) {
470 if (strcmp(subsystem, "net") != 0)
473 if (subsystem && interface)
479 dev = device_get(interface, false);
483 if (dev->type != &simple_device_type)
486 if (add && system_if_force_external(dev->ifname))
489 device_set_present(dev, add);
493 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
495 struct event_socket *ev = container_of(u, struct event_socket, uloop);
496 struct sockaddr_nl nla;
497 unsigned char *buf = NULL;
500 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
502 handle_hotplug_msg((char *) buf, size);
508 static int system_rtnl_call(struct nl_msg *msg)
512 ret = nl_send_auto_complete(sock_rtnl, msg);
518 return nl_wait_for_ack(sock_rtnl);
521 int system_bridge_delbr(struct device *bridge)
523 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
526 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
530 memset(&ifr, 0, sizeof(ifr));
532 ifr.ifr_ifindex = dev->ifindex;
535 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
536 return ioctl(sock_ioctl, cmd, &ifr);
539 static bool system_is_bridge(const char *name, char *buf, int buflen)
543 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
544 if (stat(buf, &st) < 0)
550 static char *system_get_bridge(const char *name, char *buf, int buflen)
556 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
557 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
561 len = readlink(gl.gl_pathv[0], buf, buflen);
569 path = strrchr(buf, '/');
577 system_bridge_set_wireless(struct device *bridge, struct device *dev)
579 bool mcast_to_ucast = dev->wireless_ap;
582 if (bridge->settings.flags & DEV_OPT_MULTICAST_TO_UNICAST &&
583 !bridge->settings.multicast_to_unicast)
584 mcast_to_ucast = false;
586 if (!mcast_to_ucast || dev->wireless_isolate)
589 system_bridge_set_multicast_to_unicast(dev, mcast_to_ucast ? "1" : "0");
590 system_bridge_set_hairpin_mode(dev, hairpin ? "1" : "0");
593 int system_bridge_addif(struct device *bridge, struct device *dev)
599 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
600 if (!oldbr || strcmp(oldbr, bridge->ifname) != 0)
601 ret = system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
604 system_bridge_set_wireless(bridge, dev);
606 if (dev->settings.flags & DEV_OPT_MULTICAST_ROUTER) {
607 snprintf(buf, sizeof(buf), "%i", dev->settings.multicast_router);
608 system_bridge_set_multicast_router(dev, buf, false);
614 int system_bridge_delif(struct device *bridge, struct device *dev)
616 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
619 int system_if_resolve(struct device *dev)
622 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
623 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
624 return ifr.ifr_ifindex;
629 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
633 memset(&ifr, 0, sizeof(ifr));
634 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
635 ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
636 ifr.ifr_flags |= add;
637 ifr.ifr_flags &= ~rem;
638 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
650 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
652 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
654 return ifa->ifa_index == ifindex;
657 static bool check_route(struct nlmsghdr *hdr, int ifindex)
659 struct rtmsg *r = NLMSG_DATA(hdr);
660 struct nlattr *tb[__RTA_MAX];
662 if (r->rtm_protocol == RTPROT_KERNEL &&
663 r->rtm_family == AF_INET6)
666 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
670 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
673 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
678 static int cb_clear_event(struct nl_msg *msg, void *arg)
680 struct clear_data *clr = arg;
681 struct nlmsghdr *hdr = nlmsg_hdr(msg);
682 bool (*cb)(struct nlmsghdr *, int ifindex);
688 if (hdr->nlmsg_type != RTM_NEWADDR)
695 if (hdr->nlmsg_type != RTM_NEWROUTE)
702 if (hdr->nlmsg_type != RTM_NEWRULE)
711 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
714 if (type == RTM_DELRULE)
715 D(SYSTEM, "Remove a rule\n");
717 D(SYSTEM, "Remove %s from device %s\n",
718 type == RTM_DELADDR ? "an address" : "a route",
720 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
721 hdr = nlmsg_hdr(clr->msg);
722 hdr->nlmsg_type = type;
723 hdr->nlmsg_flags = NLM_F_REQUEST;
725 nl_socket_disable_auto_ack(sock_rtnl);
726 nl_send_auto_complete(sock_rtnl, clr->msg);
727 nl_socket_enable_auto_ack(sock_rtnl);
733 cb_finish_event(struct nl_msg *msg, void *arg)
741 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
744 *pending = err->error;
749 system_if_clear_entries(struct device *dev, int type, int af)
751 struct clear_data clr;
752 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
755 .rtm_flags = RTM_F_CLONED,
757 int flags = NLM_F_DUMP;
766 clr.size = sizeof(struct rtgenmsg);
769 clr.size = sizeof(struct rtmsg);
778 clr.msg = nlmsg_alloc_simple(type, flags);
782 nlmsg_append(clr.msg, &rtm, clr.size, 0);
783 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
784 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
785 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
787 nl_send_auto_complete(sock_rtnl, clr.msg);
789 nl_recvmsgs(sock_rtnl, cb);
797 * Clear bridge (membership) state and bring down device
799 void system_if_clear_state(struct device *dev)
801 static char buf[256];
804 device_set_ifindex(dev, system_if_resolve(dev));
805 if (dev->external || !dev->ifindex)
808 system_if_flags(dev->ifname, 0, IFF_UP);
810 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
811 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
812 system_bridge_delbr(dev);
816 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
818 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
819 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
822 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
823 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
824 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
825 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
826 system_set_disable_ipv6(dev, "0");
829 static inline unsigned long
830 sec_to_jiffies(int val)
832 return (unsigned long) val * 100;
835 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
838 unsigned long args[4] = {};
840 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
843 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
844 args[1] = !!cfg->stp;
845 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
847 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
848 args[1] = sec_to_jiffies(cfg->forward_delay);
849 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
851 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
852 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
854 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier",
855 bridge->ifname, cfg->multicast_querier ? "1" : "0");
857 snprintf(buf, sizeof(buf), "%i", cfg->hash_max);
858 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/hash_max",
859 bridge->ifname, buf);
861 if (bridge->settings.flags & DEV_OPT_MULTICAST_ROUTER) {
862 snprintf(buf, sizeof(buf), "%i", bridge->settings.multicast_router);
863 system_bridge_set_multicast_router(bridge, buf, true);
866 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
867 args[1] = cfg->priority;
868 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
870 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
871 args[0] = BRCTL_SET_AGEING_TIME;
872 args[1] = sec_to_jiffies(cfg->ageing_time);
873 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
876 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
877 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
878 args[1] = sec_to_jiffies(cfg->hello_time);
879 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
882 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
883 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
884 args[1] = sec_to_jiffies(cfg->max_age);
885 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
891 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
894 struct nlattr *linkinfo, *data;
895 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
897 static const struct {
899 enum macvlan_mode val;
901 { "private", MACVLAN_MODE_PRIVATE },
902 { "vepa", MACVLAN_MODE_VEPA },
903 { "bridge", MACVLAN_MODE_BRIDGE },
904 { "passthru", MACVLAN_MODE_PASSTHRU },
907 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
912 nlmsg_append(msg, &iim, sizeof(iim), 0);
914 if (cfg->flags & MACVLAN_OPT_MACADDR)
915 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
916 nla_put_string(msg, IFLA_IFNAME, macvlan->ifname);
917 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
919 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
920 goto nla_put_failure;
922 nla_put_string(msg, IFLA_INFO_KIND, "macvlan");
924 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
925 goto nla_put_failure;
928 for (i = 0; i < ARRAY_SIZE(modes); i++) {
929 if (strcmp(cfg->mode, modes[i].name) != 0)
932 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
937 nla_nest_end(msg, data);
938 nla_nest_end(msg, linkinfo);
940 rv = system_rtnl_call(msg);
942 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
951 static int system_link_del(const char *ifname)
954 struct ifinfomsg iim = {
955 .ifi_family = AF_UNSPEC,
959 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
964 nlmsg_append(msg, &iim, sizeof(iim), 0);
965 nla_put_string(msg, IFLA_IFNAME, ifname);
966 return system_rtnl_call(msg);
969 int system_macvlan_del(struct device *macvlan)
971 return system_link_del(macvlan->ifname);
974 static int system_vlan(struct device *dev, int id)
976 struct vlan_ioctl_args ifr = {
977 .cmd = SET_VLAN_NAME_TYPE_CMD,
978 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
981 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
984 ifr.cmd = DEL_VLAN_CMD;
987 ifr.cmd = ADD_VLAN_CMD;
990 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
991 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
994 int system_vlan_add(struct device *dev, int id)
996 return system_vlan(dev, id);
999 int system_vlan_del(struct device *dev)
1001 return system_vlan(dev, -1);
1004 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
1007 struct nlattr *linkinfo, *data;
1008 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
1011 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1016 nlmsg_append(msg, &iim, sizeof(iim), 0);
1017 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
1018 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
1020 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1021 goto nla_put_failure;
1023 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
1025 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1026 goto nla_put_failure;
1028 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
1030 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
1031 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
1033 if(cfg->proto == VLAN_PROTO_8021AD)
1034 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);
1037 nla_nest_end(msg, data);
1038 nla_nest_end(msg, linkinfo);
1040 rv = system_rtnl_call(msg);
1042 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
1051 int system_vlandev_del(struct device *vlandev)
1053 return system_link_del(vlandev->ifname);
1057 system_if_get_settings(struct device *dev, struct device_settings *s)
1062 memset(&ifr, 0, sizeof(ifr));
1063 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1065 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
1066 s->mtu = ifr.ifr_mtu;
1067 s->flags |= DEV_OPT_MTU;
1070 s->mtu6 = system_update_ipv6_mtu(dev, 0);
1072 s->flags |= DEV_OPT_MTU6;
1074 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
1075 s->txqueuelen = ifr.ifr_qlen;
1076 s->flags |= DEV_OPT_TXQUEUELEN;
1079 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
1080 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
1081 s->flags |= DEV_OPT_MACADDR;
1084 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
1085 s->ipv6 = !strtoul(buf, NULL, 0);
1086 s->flags |= DEV_OPT_IPV6;
1089 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
1090 s->promisc = ifr.ifr_flags & IFF_PROMISC;
1091 s->flags |= DEV_OPT_PROMISC;
1093 s->multicast = ifr.ifr_flags & IFF_MULTICAST;
1094 s->flags |= DEV_OPT_MULTICAST;
1097 if (!system_get_rpfilter(dev, buf, sizeof(buf))) {
1098 s->rpfilter = strtoul(buf, NULL, 0);
1099 s->flags |= DEV_OPT_RPFILTER;
1102 if (!system_get_acceptlocal(dev, buf, sizeof(buf))) {
1103 s->acceptlocal = strtoul(buf, NULL, 0);
1104 s->flags |= DEV_OPT_ACCEPTLOCAL;
1107 if (!system_get_igmpversion(dev, buf, sizeof(buf))) {
1108 s->igmpversion = strtoul(buf, NULL, 0);
1109 s->flags |= DEV_OPT_IGMPVERSION;
1112 if (!system_get_mldversion(dev, buf, sizeof(buf))) {
1113 s->mldversion = strtoul(buf, NULL, 0);
1114 s->flags |= DEV_OPT_MLDVERSION;
1117 if (!system_get_neigh4reachabletime(dev, buf, sizeof(buf))) {
1118 s->neigh4reachabletime = strtoul(buf, NULL, 0);
1119 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1122 if (!system_get_neigh6reachabletime(dev, buf, sizeof(buf))) {
1123 s->neigh6reachabletime = strtoul(buf, NULL, 0);
1124 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1127 if (!system_get_dadtransmits(dev, buf, sizeof(buf))) {
1128 s->dadtransmits = strtoul(buf, NULL, 0);
1129 s->flags |= DEV_OPT_DADTRANSMITS;
1134 system_if_set_rps_xps_val(const char *path, int val)
1140 if (glob(path, 0, NULL, &gl))
1143 snprintf(val_buf, sizeof(val_buf), "%x", val);
1144 for (i = 0; i < gl.gl_pathc; i++)
1145 system_set_sysctl(gl.gl_pathv[i], val_buf);
1151 system_if_apply_rps_xps(struct device *dev, struct device_settings *s)
1153 long n_cpus = sysconf(_SC_NPROCESSORS_ONLN);
1159 val = (1 << n_cpus) - 1;
1160 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/rps_cpus", dev->ifname);
1161 system_if_set_rps_xps_val(dev_buf, s->rps ? val : 0);
1163 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/xps_cpus", dev->ifname);
1164 system_if_set_rps_xps_val(dev_buf, s->xps ? val : 0);
1168 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
1173 memset(&ifr, 0, sizeof(ifr));
1174 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1175 if (s->flags & DEV_OPT_MTU & apply_mask) {
1176 ifr.ifr_mtu = s->mtu;
1177 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
1178 s->flags &= ~DEV_OPT_MTU;
1180 if (s->flags & DEV_OPT_MTU6 & apply_mask) {
1181 system_update_ipv6_mtu(dev, s->mtu6);
1183 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
1184 ifr.ifr_qlen = s->txqueuelen;
1185 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
1186 s->flags &= ~DEV_OPT_TXQUEUELEN;
1188 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
1189 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
1190 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
1191 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
1192 s->flags &= ~DEV_OPT_MACADDR;
1194 if (s->flags & DEV_OPT_IPV6 & apply_mask)
1195 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
1196 if (s->flags & DEV_OPT_PROMISC & apply_mask) {
1197 if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
1198 !s->promisc ? IFF_PROMISC : 0) < 0)
1199 s->flags &= ~DEV_OPT_PROMISC;
1201 if (s->flags & DEV_OPT_RPFILTER & apply_mask) {
1202 snprintf(buf, sizeof(buf), "%d", s->rpfilter);
1203 system_set_rpfilter(dev, buf);
1205 if (s->flags & DEV_OPT_ACCEPTLOCAL & apply_mask)
1206 system_set_acceptlocal(dev, s->acceptlocal ? "1" : "0");
1207 if (s->flags & DEV_OPT_IGMPVERSION & apply_mask) {
1208 snprintf(buf, sizeof(buf), "%d", s->igmpversion);
1209 system_set_igmpversion(dev, buf);
1211 if (s->flags & DEV_OPT_MLDVERSION & apply_mask) {
1212 snprintf(buf, sizeof(buf), "%d", s->mldversion);
1213 system_set_mldversion(dev, buf);
1215 if (s->flags & DEV_OPT_NEIGHREACHABLETIME & apply_mask) {
1216 snprintf(buf, sizeof(buf), "%d", s->neigh4reachabletime);
1217 system_set_neigh4reachabletime(dev, buf);
1218 snprintf(buf, sizeof(buf), "%d", s->neigh6reachabletime);
1219 system_set_neigh6reachabletime(dev, buf);
1221 if (s->flags & DEV_OPT_DADTRANSMITS & apply_mask) {
1222 snprintf(buf, sizeof(buf), "%d", s->dadtransmits);
1223 system_set_dadtransmits(dev, buf);
1225 if (s->flags & DEV_OPT_MULTICAST & apply_mask) {
1226 if (system_if_flags(dev->ifname, s->multicast ? IFF_MULTICAST : 0,
1227 !s->multicast ? IFF_MULTICAST : 0) < 0)
1228 s->flags &= ~DEV_OPT_MULTICAST;
1231 system_if_apply_rps_xps(dev, s);
1234 int system_if_up(struct device *dev)
1236 system_if_get_settings(dev, &dev->orig_settings);
1237 /* Only keep orig settings based on what needs to be set */
1238 dev->orig_settings.valid_flags = dev->orig_settings.flags;
1239 dev->orig_settings.flags &= dev->settings.flags;
1240 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
1241 return system_if_flags(dev->ifname, IFF_UP, 0);
1244 int system_if_down(struct device *dev)
1246 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
1247 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
1251 struct if_check_data {
1257 #ifndef IFF_LOWER_UP
1258 #define IFF_LOWER_UP 0x10000
1261 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1263 struct nlmsghdr *nh = nlmsg_hdr(msg);
1264 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1265 struct if_check_data *chk = (struct if_check_data *)arg;
1267 if (nh->nlmsg_type != RTM_NEWLINK)
1270 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1271 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1276 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1278 struct if_check_data *chk = (struct if_check_data *)arg;
1283 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1285 struct if_check_data *chk = (struct if_check_data *)arg;
1287 device_set_present(chk->dev, false);
1288 device_set_link(chk->dev, false);
1289 chk->pending = err->error;
1294 int system_if_check(struct device *dev)
1296 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1298 struct ifinfomsg ifi = {
1299 .ifi_family = AF_UNSPEC,
1302 struct if_check_data chk = {
1308 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1312 if (nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1313 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1316 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1317 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1318 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1320 nl_send_auto_complete(sock_rtnl, msg);
1321 while (chk.pending > 0)
1322 nl_recvmsgs(sock_rtnl, cb);
1334 system_if_get_parent(struct device *dev)
1336 char buf[64], *devname;
1337 int ifindex, iflink, len;
1340 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1341 f = fopen(buf, "r");
1345 len = fread(buf, 1, sizeof(buf) - 1, f);
1352 iflink = strtoul(buf, NULL, 0);
1353 ifindex = system_if_resolve(dev);
1354 if (!iflink || iflink == ifindex)
1357 devname = if_indextoname(iflink, buf);
1361 return device_get(devname, true);
1365 read_string_file(int dir_fd, const char *file, char *buf, int len)
1371 fd = openat(dir_fd, file, O_RDONLY);
1376 len = read(fd, buf, len - 1);
1380 } else if (len > 0) {
1383 c = strchr(buf, '\n');
1396 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1401 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1403 *val = strtoull(buf, NULL, 0);
1408 /* Assume advertised flags == supported flags */
1409 static const struct {
1412 } ethtool_link_modes[] = {
1413 { ADVERTISED_10baseT_Half, "10H" },
1414 { ADVERTISED_10baseT_Full, "10F" },
1415 { ADVERTISED_100baseT_Half, "100H" },
1416 { ADVERTISED_100baseT_Full, "100F" },
1417 { ADVERTISED_1000baseT_Half, "1000H" },
1418 { ADVERTISED_1000baseT_Full, "1000F" },
1421 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1424 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1425 if (mask & ethtool_link_modes[i].mask)
1426 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1431 system_if_force_external(const char *ifname)
1436 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1437 return stat(buf, &s) == 0;
1441 system_if_dump_info(struct device *dev, struct blob_buf *b)
1443 struct ethtool_cmd ecmd;
1449 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
1450 dir_fd = open(buf, O_DIRECTORY);
1452 memset(&ecmd, 0, sizeof(ecmd));
1453 memset(&ifr, 0, sizeof(ifr));
1454 strcpy(ifr.ifr_name, dev->ifname);
1455 ifr.ifr_data = (caddr_t) &ecmd;
1456 ecmd.cmd = ETHTOOL_GSET;
1458 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1459 c = blobmsg_open_array(b, "link-advertising");
1460 system_add_link_modes(b, ecmd.advertising);
1461 blobmsg_close_array(b, c);
1463 c = blobmsg_open_array(b, "link-supported");
1464 system_add_link_modes(b, ecmd.supported);
1465 blobmsg_close_array(b, c);
1467 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1468 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1469 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1470 blobmsg_add_string_buffer(b);
1478 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1480 const char *const counters[] = {
1481 "collisions", "rx_frame_errors", "tx_compressed",
1482 "multicast", "rx_length_errors", "tx_dropped",
1483 "rx_bytes", "rx_missed_errors", "tx_errors",
1484 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1485 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1486 "rx_dropped", "tx_aborted_errors", "tx_packets",
1487 "rx_errors", "tx_bytes", "tx_window_errors",
1488 "rx_fifo_errors", "tx_carrier_errors",
1495 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1496 stats_dir = open(buf, O_DIRECTORY);
1500 for (i = 0; i < ARRAY_SIZE(counters); i++)
1501 if (read_uint64_file(stats_dir, counters[i], &val))
1502 blobmsg_add_u64(b, counters[i], val);
1508 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1510 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1511 int alen = v4 ? 4 : 16;
1512 unsigned int flags = 0;
1513 struct ifaddrmsg ifa = {
1514 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1515 .ifa_prefixlen = addr->mask,
1516 .ifa_index = dev->ifindex,
1520 if (cmd == RTM_NEWADDR)
1521 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1523 msg = nlmsg_alloc_simple(cmd, flags);
1527 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1528 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1530 if (addr->broadcast)
1531 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1532 if (addr->point_to_point)
1533 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1535 time_t now = system_get_rtime();
1536 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1538 if (addr->preferred_until) {
1539 int64_t preferred = addr->preferred_until - now;
1542 else if (preferred > UINT32_MAX)
1543 preferred = UINT32_MAX;
1545 cinfo.ifa_prefered = preferred;
1548 if (addr->valid_until) {
1549 int64_t valid = addr->valid_until - now;
1554 else if (valid > UINT32_MAX)
1557 cinfo.ifa_valid = valid;
1560 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1562 if (cmd == RTM_NEWADDR && (addr->flags & DEVADDR_OFFLINK))
1563 nla_put_u32(msg, IFA_FLAGS, IFA_F_NOPREFIXROUTE);
1566 return system_rtnl_call(msg);
1569 int system_add_address(struct device *dev, struct device_addr *addr)
1571 return system_addr(dev, addr, RTM_NEWADDR);
1574 int system_del_address(struct device *dev, struct device_addr *addr)
1576 return system_addr(dev, addr, RTM_DELADDR);
1579 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1581 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1583 unsigned int flags = 0;
1586 have_gw = !!route->nexthop.in.s_addr;
1588 have_gw = route->nexthop.in6.s6_addr32[0] ||
1589 route->nexthop.in6.s6_addr32[1] ||
1590 route->nexthop.in6.s6_addr32[2] ||
1591 route->nexthop.in6.s6_addr32[3];
1593 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1594 ? route->table : RT_TABLE_MAIN;
1596 struct rtmsg rtm = {
1597 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1598 .rtm_dst_len = route->mask,
1599 .rtm_src_len = route->sourcemask,
1600 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1601 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
1602 .rtm_scope = RT_SCOPE_NOWHERE,
1603 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1604 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1608 if (cmd == RTM_NEWROUTE) {
1609 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1611 if (!dev) { // Add null-route
1612 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1613 rtm.rtm_type = RTN_UNREACHABLE;
1616 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1619 if (route->flags & DEVROUTE_TYPE) {
1620 rtm.rtm_type = route->type;
1621 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
1622 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
1623 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
1624 rtm.rtm_table = RT_TABLE_LOCAL;
1627 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT) {
1628 rtm.rtm_scope = RT_SCOPE_HOST;
1629 } else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
1630 rtm.rtm_type == RTN_ANYCAST) {
1631 rtm.rtm_scope = RT_SCOPE_LINK;
1632 } else if (rtm.rtm_type == RTN_BLACKHOLE || rtm.rtm_type == RTN_UNREACHABLE ||
1633 rtm.rtm_type == RTN_PROHIBIT || rtm.rtm_type == RTN_FAILED_POLICY) {
1634 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1639 msg = nlmsg_alloc_simple(cmd, flags);
1643 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1646 nla_put(msg, RTA_DST, alen, &route->addr);
1648 if (route->sourcemask) {
1649 if (rtm.rtm_family == AF_INET)
1650 nla_put(msg, RTA_PREFSRC, alen, &route->source);
1652 nla_put(msg, RTA_SRC, alen, &route->source);
1655 if (route->metric > 0)
1656 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1659 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1662 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1665 nla_put_u32(msg, RTA_TABLE, table);
1667 if (route->flags & DEVROUTE_MTU) {
1668 struct nlattr *metrics;
1670 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1671 goto nla_put_failure;
1673 nla_put_u32(msg, RTAX_MTU, route->mtu);
1675 nla_nest_end(msg, metrics);
1678 return system_rtnl_call(msg);
1685 int system_add_route(struct device *dev, struct device_route *route)
1687 return system_rt(dev, route, RTM_NEWROUTE);
1690 int system_del_route(struct device *dev, struct device_route *route)
1692 return system_rt(dev, route, RTM_DELROUTE);
1695 int system_flush_routes(void)
1697 const char *names[] = {
1698 "/proc/sys/net/ipv4/route/flush",
1699 "/proc/sys/net/ipv6/route/flush"
1703 for (i = 0; i < ARRAY_SIZE(names); i++) {
1704 fd = open(names[i], O_WRONLY);
1708 if (write(fd, "-1", 2)) {}
1714 bool system_resolve_rt_type(const char *type, unsigned int *id)
1716 return system_rtn_aton(type, id);
1719 bool system_resolve_rt_table(const char *name, unsigned int *id)
1723 unsigned int n, table = RT_TABLE_UNSPEC;
1725 /* first try to parse table as number */
1726 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1729 /* handle well known aliases */
1730 else if (!strcmp(name, "default"))
1731 table = RT_TABLE_DEFAULT;
1732 else if (!strcmp(name, "main"))
1733 table = RT_TABLE_MAIN;
1734 else if (!strcmp(name, "local"))
1735 table = RT_TABLE_LOCAL;
1736 else if (!strcmp(name, "prelocal"))
1737 table = RT_TABLE_PRELOCAL;
1739 /* try to look up name in /etc/iproute2/rt_tables */
1740 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1742 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1744 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1747 n = strtoul(e, NULL, 10);
1748 e = strtok(NULL, " \t\n");
1750 if (e && !strcmp(e, name))
1760 if (table == RT_TABLE_UNSPEC)
1767 bool system_is_default_rt_table(unsigned int id)
1769 return (id == RT_TABLE_MAIN);
1772 bool system_resolve_rpfilter(const char *filter, unsigned int *id)
1777 if (!strcmp(filter, "strict"))
1779 else if (!strcmp(filter, "loose"))
1782 n = strtoul(filter, &e, 0);
1783 if (*e || e == filter || n > 2)
1791 static int system_iprule(struct iprule *rule, int cmd)
1793 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1796 struct rtmsg rtm = {
1797 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1798 .rtm_protocol = RTPROT_STATIC,
1799 .rtm_scope = RT_SCOPE_UNIVERSE,
1800 .rtm_table = RT_TABLE_UNSPEC,
1801 .rtm_type = RTN_UNSPEC,
1805 if (cmd == RTM_NEWRULE)
1806 rtm.rtm_type = RTN_UNICAST;
1809 rtm.rtm_flags |= FIB_RULE_INVERT;
1811 if (rule->flags & IPRULE_SRC)
1812 rtm.rtm_src_len = rule->src_mask;
1814 if (rule->flags & IPRULE_DEST)
1815 rtm.rtm_dst_len = rule->dest_mask;
1817 if (rule->flags & IPRULE_TOS)
1818 rtm.rtm_tos = rule->tos;
1820 if (rule->flags & IPRULE_LOOKUP) {
1821 if (rule->lookup < 256)
1822 rtm.rtm_table = rule->lookup;
1825 if (rule->flags & IPRULE_ACTION)
1826 rtm.rtm_type = rule->action;
1827 else if (rule->flags & IPRULE_GOTO)
1828 rtm.rtm_type = FR_ACT_GOTO;
1829 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1830 rtm.rtm_type = FR_ACT_NOP;
1832 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1837 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1839 if (rule->flags & IPRULE_IN)
1840 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1842 if (rule->flags & IPRULE_OUT)
1843 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1845 if (rule->flags & IPRULE_SRC)
1846 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1848 if (rule->flags & IPRULE_DEST)
1849 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1851 if (rule->flags & IPRULE_PRIORITY)
1852 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1853 else if (cmd == RTM_NEWRULE)
1854 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1856 if (rule->flags & IPRULE_FWMARK)
1857 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1859 if (rule->flags & IPRULE_FWMASK)
1860 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1862 if (rule->flags & IPRULE_LOOKUP) {
1863 if (rule->lookup >= 256)
1864 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1867 if (rule->flags & IPRULE_GOTO)
1868 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1870 return system_rtnl_call(msg);
1873 int system_add_iprule(struct iprule *rule)
1875 return system_iprule(rule, RTM_NEWRULE);
1878 int system_del_iprule(struct iprule *rule)
1880 return system_iprule(rule, RTM_DELRULE);
1883 int system_flush_iprules(void)
1888 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1889 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1891 memset(&rule, 0, sizeof(rule));
1894 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1897 rule.lookup = RT_TABLE_PRELOCAL;
1898 rv |= system_iprule(&rule, RTM_NEWRULE);
1901 rule.lookup = RT_TABLE_LOCAL;
1902 rv |= system_iprule(&rule, RTM_NEWRULE);
1904 rule.priority = 32766;
1905 rule.lookup = RT_TABLE_MAIN;
1906 rv |= system_iprule(&rule, RTM_NEWRULE);
1908 rule.priority = 32767;
1909 rule.lookup = RT_TABLE_DEFAULT;
1910 rv |= system_iprule(&rule, RTM_NEWRULE);
1913 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1916 rule.lookup = RT_TABLE_PRELOCAL;
1917 rv |= system_iprule(&rule, RTM_NEWRULE);
1920 rule.lookup = RT_TABLE_LOCAL;
1921 rv |= system_iprule(&rule, RTM_NEWRULE);
1923 rule.priority = 32766;
1924 rule.lookup = RT_TABLE_MAIN;
1925 rv |= system_iprule(&rule, RTM_NEWRULE);
1930 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1932 return system_rtn_aton(action, id);
1935 time_t system_get_rtime(void)
1940 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1943 if (gettimeofday(&tv, NULL) == 0)
1950 #define IP_DF 0x4000
1953 static int tunnel_ioctl(const char *name, int cmd, void *p)
1957 memset(&ifr, 0, sizeof(ifr));
1958 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1959 ifr.ifr_ifru.ifru_data = p;
1960 return ioctl(sock_ioctl, cmd, &ifr);
1963 #ifdef IFLA_IPTUN_MAX
1964 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
1965 static int system_add_gre_tunnel(const char *name, const char *kind,
1966 const unsigned int link, struct blob_attr **tb, bool v6)
1969 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
1970 struct blob_attr *cur;
1971 uint32_t ikey = 0, okey = 0, flags = 0, flowinfo = 0;
1972 uint16_t iflags = 0, oflags = 0;
1974 int ret = 0, ttl = 64;
1976 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
1980 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
1981 nla_put_string(nlm, IFLA_IFNAME, name);
1983 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
1989 nla_put_string(nlm, IFLA_INFO_KIND, kind);
1990 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
1997 nla_put_u32(nlm, IFLA_GRE_LINK, link);
1999 if ((cur = tb[TUNNEL_ATTR_TTL]))
2000 ttl = blobmsg_get_u32(cur);
2002 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
2004 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2005 char *str = blobmsg_get_string(cur);
2006 if (strcmp(str, "inherit")) {
2009 if (!system_tos_aton(str, &uval)) {
2015 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
2020 flags |= IP6_TNL_F_USE_ORIG_TCLASS;
2026 if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) {
2027 uint8_t icsum, ocsum, iseqno, oseqno;
2028 if (sscanf(blobmsg_get_string(cur), "%u,%u,%hhu,%hhu,%hhu,%hhu",
2029 &ikey, &okey, &icsum, &ocsum, &iseqno, &oseqno) < 6) {
2054 struct in6_addr in6buf;
2055 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2056 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2060 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
2063 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2064 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2068 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
2070 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, 4);
2073 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
2076 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags);
2078 struct in_addr inbuf;
2081 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2082 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2086 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
2089 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2090 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2094 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
2096 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
2098 okey = inbuf.s_addr;
2103 ikey = inbuf.s_addr;
2109 if ((cur = tb[TUNNEL_ATTR_DF]))
2110 set_df = blobmsg_get_bool(cur);
2112 /* ttl !=0 and nopmtudisc are incompatible */
2113 if (ttl && !set_df) {
2118 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
2120 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
2124 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
2127 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
2130 nla_put_u32(nlm, IFLA_GRE_OKEY, okey);
2133 nla_put_u32(nlm, IFLA_GRE_IKEY, ikey);
2135 nla_nest_end(nlm, infodata);
2136 nla_nest_end(nlm, linkinfo);
2138 return system_rtnl_call(nlm);
2147 static int system_add_vti_tunnel(const char *name, const char *kind,
2148 const unsigned int link, struct blob_attr **tb, bool v6)
2151 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2152 struct blob_attr *cur;
2153 uint32_t ikey = 0, okey = 0;
2156 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2160 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2161 nla_put_string(nlm, IFLA_IFNAME, name);
2163 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2169 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2170 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2177 nla_put_u32(nlm, IFLA_VTI_LINK, link);
2179 if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) {
2180 if (sscanf(blobmsg_get_string(cur), "%u,%u",
2181 &ikey, &okey) < 2) {
2188 struct in6_addr in6buf;
2189 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2190 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2194 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(in6buf), &in6buf);
2197 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2198 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2202 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(in6buf), &in6buf);
2206 struct in_addr inbuf;
2208 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2209 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2213 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(inbuf), &inbuf);
2216 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2217 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2221 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(inbuf), &inbuf);
2227 nla_put_u32(nlm, IFLA_VTI_OKEY, okey);
2230 nla_put_u32(nlm, IFLA_VTI_IKEY, ikey);
2232 nla_nest_end(nlm, infodata);
2233 nla_nest_end(nlm, linkinfo);
2235 return system_rtnl_call(nlm);
2243 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
2245 struct blob_attr *cur;
2247 struct ip_tunnel_parm p = {
2256 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
2257 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
2260 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
2261 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
2264 if ((cur = tb[TUNNEL_ATTR_DF]))
2265 set_df = blobmsg_get_bool(cur);
2267 if ((cur = tb[TUNNEL_ATTR_TTL]))
2268 p.iph.ttl = blobmsg_get_u32(cur);
2270 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2271 char *str = blobmsg_get_string(cur);
2272 if (strcmp(str, "inherit")) {
2275 if (!system_tos_aton(str, &uval))
2283 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
2284 /* ttl !=0 and nopmtudisc are incompatible */
2285 if (p.iph.ttl && p.iph.frag_off == 0)
2288 strncpy(p.name, name, sizeof(p.name));
2290 switch (p.iph.protocol) {
2292 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
2294 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
2301 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
2303 struct blob_attr *cur;
2306 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2308 str = blobmsg_data(cur);
2310 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
2311 !strcmp(str, "greip6") || !strcmp(str, "gretapip6") ||
2312 !strcmp(str, "vtiip") || !strcmp(str, "vtiip6"))
2313 return system_link_del(name);
2315 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
2318 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
2320 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2322 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2323 blob_data(attr), blob_len(attr));
2325 return __system_del_ip_tunnel(name, tb);
2328 int system_update_ipv6_mtu(struct device *dev, int mtu)
2332 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
2335 int fd = open(buf, O_RDWR);
2338 ssize_t len = read(fd, buf, sizeof(buf) - 1);
2345 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) > 0)
2354 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
2356 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2357 struct blob_attr *cur;
2360 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2361 blob_data(attr), blob_len(attr));
2363 __system_del_ip_tunnel(name, tb);
2365 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2367 str = blobmsg_data(cur);
2369 unsigned int ttl = 0;
2370 if ((cur = tb[TUNNEL_ATTR_TTL])) {
2371 ttl = blobmsg_get_u32(cur);
2376 unsigned int link = 0;
2377 if ((cur = tb[TUNNEL_ATTR_LINK])) {
2378 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
2382 if (iface->l3_dev.dev)
2383 link = iface->l3_dev.dev->ifindex;
2386 if (!strcmp(str, "sit")) {
2387 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
2391 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
2393 struct ip_tunnel_6rd p6;
2395 memset(&p6, 0, sizeof(p6));
2397 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
2398 &p6.prefix, &mask) || mask > 128)
2400 p6.prefixlen = mask;
2402 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
2403 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
2404 &p6.relay_prefix, &mask) || mask > 32)
2406 p6.relay_prefixlen = mask;
2409 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
2410 __system_del_ip_tunnel(name, tb);
2415 #ifdef IFLA_IPTUN_MAX
2416 } else if (!strcmp(str, "ipip6")) {
2417 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2418 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2419 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2425 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2426 nla_put_string(nlm, IFLA_IFNAME, name);
2429 nla_put_u32(nlm, IFLA_LINK, link);
2431 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2436 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2437 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2444 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2446 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2447 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2448 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
2450 struct in6_addr in6buf;
2451 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2452 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2456 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2459 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2460 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2464 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2467 #ifdef IFLA_IPTUN_FMR_MAX
2468 if ((cur = tb[TUNNEL_ATTR_FMRS])) {
2469 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2471 struct blob_attr *fmr;
2472 unsigned rem, fmrcnt = 0;
2473 blobmsg_for_each_attr(fmr, cur, rem) {
2474 if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
2477 unsigned ip4len, ip6len, ealen, offset = 6;
2481 if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
2482 ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) {
2487 struct in6_addr ip6prefix;
2488 struct in_addr ip4prefix;
2489 if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
2490 inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) {
2495 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2497 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2498 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2499 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2500 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2501 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2502 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2504 nla_nest_end(nlm, rule);
2507 nla_nest_end(nlm, fmrs);
2511 nla_nest_end(nlm, infodata);
2512 nla_nest_end(nlm, linkinfo);
2514 return system_rtnl_call(nlm);
2518 } else if (!strcmp(str, "greip")) {
2519 return system_add_gre_tunnel(name, "gre", link, tb, false);
2520 } else if (!strcmp(str, "gretapip")) {
2521 return system_add_gre_tunnel(name, "gretap", link, tb, false);
2522 } else if (!strcmp(str, "greip6")) {
2523 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
2524 } else if (!strcmp(str, "gretapip6")) {
2525 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
2527 } else if (!strcmp(str, "vtiip")) {
2528 return system_add_vti_tunnel(name, "vti", link, tb, false);
2529 } else if (!strcmp(str, "vtiip6")) {
2530 return system_add_vti_tunnel(name, "vti6", link, tb, true);
2533 } else if (!strcmp(str, "ipip")) {
2534 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);