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 IFA_F_NOPREFIXROUTE
48 #define IFA_F_NOPREFIXROUTE 0x200
52 #define IFA_FLAGS (IFA_MULTICAST + 1)
62 #include <netlink/msg.h>
63 #include <netlink/attr.h>
64 #include <netlink/socket.h>
65 #include <libubox/uloop.h>
72 struct uloop_fd uloop;
77 static int sock_ioctl = -1;
78 static struct nl_sock *sock_rtnl = NULL;
80 static int cb_rtnl_event(struct nl_msg *msg, void *arg);
81 static void handle_hotplug_event(struct uloop_fd *u, unsigned int events);
83 static char dev_buf[256];
86 handler_nl_event(struct uloop_fd *u, unsigned int events)
88 struct event_socket *ev = container_of(u, struct event_socket, uloop);
90 socklen_t errlen = sizeof(err);
93 nl_recvmsgs_default(ev->sock);
97 if (getsockopt(u->fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen))
102 // Increase rx buffer size on netlink socket
104 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
107 // Request full dump since some info got dropped
108 struct rtgenmsg msg = { .rtgen_family = AF_UNSPEC };
109 nl_send_simple(ev->sock, RTM_GETLINK, NLM_F_DUMP, &msg, sizeof(msg));
119 uloop_fd_delete(&ev->uloop);
123 static struct nl_sock *
124 create_socket(int protocol, int groups)
126 struct nl_sock *sock;
128 sock = nl_socket_alloc();
133 nl_join_groups(sock, groups);
135 if (nl_connect(sock, protocol))
142 create_raw_event_socket(struct event_socket *ev, int protocol, int groups,
143 uloop_fd_handler cb, int flags)
145 ev->sock = create_socket(protocol, groups);
149 ev->uloop.fd = nl_socket_get_fd(ev->sock);
151 if (uloop_fd_add(&ev->uloop, ULOOP_READ|flags))
158 create_event_socket(struct event_socket *ev, int protocol,
159 int (*cb)(struct nl_msg *msg, void *arg))
161 if (!create_raw_event_socket(ev, protocol, 0, handler_nl_event, ULOOP_ERROR_CB))
164 // Install the valid custom callback handler
165 nl_socket_modify_cb(ev->sock, NL_CB_VALID, NL_CB_CUSTOM, cb, NULL);
167 // Disable sequence number checking on event sockets
168 nl_socket_disable_seq_check(ev->sock);
170 // Increase rx buffer size to 65K on event sockets
172 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
179 system_rtn_aton(const char *src, unsigned int *dst)
184 if (!strcmp(src, "local"))
186 else if (!strcmp(src, "nat"))
188 else if (!strcmp(src, "broadcast"))
190 else if (!strcmp(src, "anycast"))
192 else if (!strcmp(src, "multicast"))
194 else if (!strcmp(src, "prohibit"))
196 else if (!strcmp(src, "unreachable"))
198 else if (!strcmp(src, "blackhole"))
200 else if (!strcmp(src, "xresolve"))
202 else if (!strcmp(src, "unicast"))
204 else if (!strcmp(src, "throw"))
206 else if (!strcmp(src, "failed_policy"))
207 n = RTN_FAILED_POLICY;
209 n = strtoul(src, &e, 0);
210 if (!e || *e || e == src || n > 255)
219 system_tos_aton(const char *src, unsigned *dst)
223 *dst = strtoul(src, &e, 16);
224 if (e == src || *e || *dst > 255)
230 int system_init(void)
232 static struct event_socket rtnl_event;
233 static struct event_socket hotplug_event;
235 sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0);
236 system_fd_set_cloexec(sock_ioctl);
238 // Prepare socket for routing / address control
239 sock_rtnl = create_socket(NETLINK_ROUTE, 0);
243 if (!create_event_socket(&rtnl_event, NETLINK_ROUTE, cb_rtnl_event))
246 if (!create_raw_event_socket(&hotplug_event, NETLINK_KOBJECT_UEVENT, 1,
247 handle_hotplug_event, 0))
250 // Receive network link events form kernel
251 nl_socket_add_membership(rtnl_event.sock, RTNLGRP_LINK);
256 static void system_set_sysctl(const char *path, const char *val)
260 fd = open(path, O_WRONLY);
264 if (write(fd, val, strlen(val))) {}
268 static void system_set_dev_sysctl(const char *path, const char *device, const char *val)
270 snprintf(dev_buf, sizeof(dev_buf), path, device);
271 system_set_sysctl(dev_buf, val);
274 static void system_set_disable_ipv6(struct device *dev, const char *val)
276 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val);
279 static void system_set_rpfilter(struct device *dev, const char *val)
281 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter", dev->ifname, val);
284 static void system_set_acceptlocal(struct device *dev, const char *val)
286 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local", dev->ifname, val);
289 static void system_set_igmpversion(struct device *dev, const char *val)
291 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version", dev->ifname, val);
294 static void system_set_mldversion(struct device *dev, const char *val)
296 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version", dev->ifname, val);
299 static void system_set_neigh4reachabletime(struct device *dev, const char *val)
301 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms", dev->ifname, val);
304 static void system_set_neigh6reachabletime(struct device *dev, const char *val)
306 system_set_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms", dev->ifname, val);
309 static void system_set_dadtransmits(struct device *dev, const char *val)
311 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits", dev->ifname, val);
314 static void system_bridge_set_multicast_to_unicast(struct device *dev, const char *val)
316 system_set_dev_sysctl("/sys/class/net/%s/brport/multicast_to_unicast", dev->ifname, val);
319 static void system_bridge_set_hairpin_mode(struct device *dev, const char *val)
321 system_set_dev_sysctl("/sys/class/net/%s/brport/hairpin_mode", dev->ifname, val);
324 static void system_bridge_set_multicast_router(struct device *dev, const char *val, bool bridge)
326 system_set_dev_sysctl(bridge ? "/sys/class/net/%s/bridge/multicast_router" :
327 "/sys/class/net/%s/brport/multicast_router",
331 static void system_bridge_set_robustness(struct device *dev, const char *val)
333 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_startup_query_count",
335 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_last_member_count",
339 static void system_bridge_set_query_interval(struct device *dev, const char *val)
341 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_query_interval",
345 static void system_bridge_set_query_response_interval(struct device *dev, const char *val)
347 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_query_response_interval",
351 static void system_bridge_set_last_member_interval(struct device *dev, const char *val)
353 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_last_member_interval",
357 static void system_bridge_set_membership_interval(struct device *dev, const char *val)
359 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_membership_interval",
363 static void system_bridge_set_other_querier_timeout(struct device *dev, const char *val)
365 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier_interval",
369 static void system_bridge_set_startup_query_interval(struct device *dev, const char *val)
371 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_startup_query_interval",
375 static void system_bridge_set_learning(struct device *dev, const char *val)
377 system_set_dev_sysctl("/sys/class/net/%s/brport/learning", dev->ifname, val);
380 static void system_bridge_set_unicast_flood(struct device *dev, const char *val)
382 system_set_dev_sysctl("/sys/class/net/%s/brport/unicast_flood", dev->ifname, val);
385 static int system_get_sysctl(const char *path, char *buf, const size_t buf_sz)
387 int fd = -1, ret = -1;
389 fd = open(path, O_RDONLY);
393 ssize_t len = read(fd, buf, buf_sz - 1);
407 system_get_dev_sysctl(const char *path, const char *device, char *buf, const size_t buf_sz)
409 snprintf(dev_buf, sizeof(dev_buf), path, device);
410 return system_get_sysctl(dev_buf, buf, buf_sz);
413 static int system_get_disable_ipv6(struct device *dev, char *buf, const size_t buf_sz)
415 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6",
416 dev->ifname, buf, buf_sz);
419 static int system_get_rpfilter(struct device *dev, char *buf, const size_t buf_sz)
421 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter",
422 dev->ifname, buf, buf_sz);
425 static int system_get_acceptlocal(struct device *dev, char *buf, const size_t buf_sz)
427 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local",
428 dev->ifname, buf, buf_sz);
431 static int system_get_igmpversion(struct device *dev, char *buf, const size_t buf_sz)
433 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version",
434 dev->ifname, buf, buf_sz);
437 static int system_get_mldversion(struct device *dev, char *buf, const size_t buf_sz)
439 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version",
440 dev->ifname, buf, buf_sz);
443 static int system_get_neigh4reachabletime(struct device *dev, char *buf, const size_t buf_sz)
445 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms",
446 dev->ifname, buf, buf_sz);
449 static int system_get_neigh6reachabletime(struct device *dev, char *buf, const size_t buf_sz)
451 return system_get_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms",
452 dev->ifname, buf, buf_sz);
455 static int system_get_dadtransmits(struct device *dev, char *buf, const size_t buf_sz)
457 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits",
458 dev->ifname, buf, buf_sz);
461 // Evaluate netlink messages
462 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
464 struct nlmsghdr *nh = nlmsg_hdr(msg);
465 struct nlattr *nla[__IFLA_MAX];
469 if (nh->nlmsg_type != RTM_NEWLINK)
472 nlmsg_parse(nh, sizeof(struct ifinfomsg), nla, __IFLA_MAX - 1, NULL);
473 if (!nla[IFLA_IFNAME])
476 struct device *dev = device_get(nla_data(nla[IFLA_IFNAME]), false);
480 if (!system_get_dev_sysctl("/sys/class/net/%s/carrier", dev->ifname, buf, sizeof(buf)))
481 link_state = strtoul(buf, NULL, 0);
483 device_set_link(dev, link_state ? true : false);
490 handle_hotplug_msg(char *data, int size)
492 const char *subsystem = NULL, *interface = NULL;
493 char *cur, *end, *sep;
498 if (!strncmp(data, "add@", 4))
500 else if (!strncmp(data, "remove@", 7))
505 skip = strlen(data) + 1;
508 for (cur = data + skip; cur < end; cur += skip) {
509 skip = strlen(cur) + 1;
511 sep = strchr(cur, '=');
516 if (!strcmp(cur, "INTERFACE"))
518 else if (!strcmp(cur, "SUBSYSTEM")) {
520 if (strcmp(subsystem, "net") != 0)
523 if (subsystem && interface)
529 dev = device_get(interface, false);
533 if (dev->type != &simple_device_type)
536 if (add && system_if_force_external(dev->ifname))
539 device_set_present(dev, add);
543 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
545 struct event_socket *ev = container_of(u, struct event_socket, uloop);
546 struct sockaddr_nl nla;
547 unsigned char *buf = NULL;
550 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
552 handle_hotplug_msg((char *) buf, size);
558 static int system_rtnl_call(struct nl_msg *msg)
562 ret = nl_send_auto_complete(sock_rtnl, msg);
568 return nl_wait_for_ack(sock_rtnl);
571 int system_bridge_delbr(struct device *bridge)
573 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
576 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
580 memset(&ifr, 0, sizeof(ifr));
582 ifr.ifr_ifindex = dev->ifindex;
585 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
586 return ioctl(sock_ioctl, cmd, &ifr);
589 static bool system_is_bridge(const char *name, char *buf, int buflen)
593 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
594 if (stat(buf, &st) < 0)
600 static char *system_get_bridge(const char *name, char *buf, int buflen)
606 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
607 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
611 len = readlink(gl.gl_pathv[0], buf, buflen);
619 path = strrchr(buf, '/');
627 system_bridge_set_wireless(struct device *bridge, struct device *dev)
629 bool mcast_to_ucast = dev->wireless_ap;
632 if (bridge->settings.flags & DEV_OPT_MULTICAST_TO_UNICAST &&
633 !bridge->settings.multicast_to_unicast)
634 mcast_to_ucast = false;
636 if (!mcast_to_ucast || dev->wireless_isolate)
639 system_bridge_set_multicast_to_unicast(dev, mcast_to_ucast ? "1" : "0");
640 system_bridge_set_hairpin_mode(dev, hairpin ? "1" : "0");
643 int system_bridge_addif(struct device *bridge, struct device *dev)
649 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
650 if (!oldbr || strcmp(oldbr, bridge->ifname) != 0)
651 ret = system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
654 system_bridge_set_wireless(bridge, dev);
656 if (dev->settings.flags & DEV_OPT_MULTICAST_ROUTER) {
657 snprintf(buf, sizeof(buf), "%i", dev->settings.multicast_router);
658 system_bridge_set_multicast_router(dev, buf, false);
661 if (dev->settings.flags & DEV_OPT_LEARNING &&
662 !dev->settings.learning)
663 system_bridge_set_learning(dev, "0");
665 if (dev->settings.flags & DEV_OPT_UNICAST_FLOOD &&
666 !dev->settings.unicast_flood)
667 system_bridge_set_unicast_flood(dev, "0");
672 int system_bridge_delif(struct device *bridge, struct device *dev)
674 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
677 int system_if_resolve(struct device *dev)
680 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
681 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
682 return ifr.ifr_ifindex;
687 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
691 memset(&ifr, 0, sizeof(ifr));
692 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
693 ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
694 ifr.ifr_flags |= add;
695 ifr.ifr_flags &= ~rem;
696 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
708 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
710 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
712 return ifa->ifa_index == ifindex;
715 static bool check_route(struct nlmsghdr *hdr, int ifindex)
717 struct rtmsg *r = NLMSG_DATA(hdr);
718 struct nlattr *tb[__RTA_MAX];
720 if (r->rtm_protocol == RTPROT_KERNEL &&
721 r->rtm_family == AF_INET6)
724 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
728 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
731 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
736 static int cb_clear_event(struct nl_msg *msg, void *arg)
738 struct clear_data *clr = arg;
739 struct nlmsghdr *hdr = nlmsg_hdr(msg);
740 bool (*cb)(struct nlmsghdr *, int ifindex);
746 if (hdr->nlmsg_type != RTM_NEWADDR)
753 if (hdr->nlmsg_type != RTM_NEWROUTE)
760 if (hdr->nlmsg_type != RTM_NEWRULE)
769 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
772 if (type == RTM_DELRULE)
773 D(SYSTEM, "Remove a rule\n");
775 D(SYSTEM, "Remove %s from device %s\n",
776 type == RTM_DELADDR ? "an address" : "a route",
778 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
779 hdr = nlmsg_hdr(clr->msg);
780 hdr->nlmsg_type = type;
781 hdr->nlmsg_flags = NLM_F_REQUEST;
783 nl_socket_disable_auto_ack(sock_rtnl);
784 nl_send_auto_complete(sock_rtnl, clr->msg);
785 nl_socket_enable_auto_ack(sock_rtnl);
791 cb_finish_event(struct nl_msg *msg, void *arg)
799 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
802 *pending = err->error;
807 system_if_clear_entries(struct device *dev, int type, int af)
809 struct clear_data clr;
810 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
813 .rtm_flags = RTM_F_CLONED,
815 int flags = NLM_F_DUMP;
824 clr.size = sizeof(struct rtgenmsg);
827 clr.size = sizeof(struct rtmsg);
836 clr.msg = nlmsg_alloc_simple(type, flags);
840 nlmsg_append(clr.msg, &rtm, clr.size, 0);
841 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
842 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
843 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
845 nl_send_auto_complete(sock_rtnl, clr.msg);
847 nl_recvmsgs(sock_rtnl, cb);
855 * Clear bridge (membership) state and bring down device
857 void system_if_clear_state(struct device *dev)
859 static char buf[256];
862 device_set_ifindex(dev, system_if_resolve(dev));
863 if (dev->external || !dev->ifindex)
866 system_if_flags(dev->ifname, 0, IFF_UP);
868 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
869 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
870 system_bridge_delbr(dev);
874 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
876 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
877 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
880 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
881 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
882 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
883 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
884 system_set_disable_ipv6(dev, "0");
887 static inline unsigned long
888 sec_to_jiffies(int val)
890 return (unsigned long) val * 100;
893 static void system_bridge_conf_multicast_deps(struct device *bridge,
894 struct bridge_config *cfg,
900 if (cfg->flags & BRIDGE_OPT_ROBUSTNESS ||
901 cfg->flags & BRIDGE_OPT_QUERY_INTERVAL ||
902 cfg->flags & BRIDGE_OPT_QUERY_RESPONSE_INTERVAL) {
903 val = cfg->robustness * cfg->query_interval +
904 cfg->query_response_interval;
906 snprintf(buf, buf_len, "%i", val);
907 system_bridge_set_membership_interval(bridge, buf);
909 val = cfg->robustness * cfg->query_interval +
910 cfg->query_response_interval / 2;
912 snprintf(buf, buf_len, "%i", val);
913 system_bridge_set_other_querier_timeout(bridge, buf);
916 if (cfg->flags & BRIDGE_OPT_QUERY_INTERVAL) {
917 val = cfg->query_interval / 4;
919 snprintf(buf, buf_len, "%i", val);
920 system_bridge_set_startup_query_interval(bridge, buf);
924 static void system_bridge_conf_multicast(struct device *bridge,
925 struct bridge_config *cfg,
929 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
930 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
932 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier",
933 bridge->ifname, cfg->multicast_querier ? "1" : "0");
935 snprintf(buf, buf_len, "%i", cfg->hash_max);
936 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/hash_max",
937 bridge->ifname, buf);
939 if (bridge->settings.flags & DEV_OPT_MULTICAST_ROUTER) {
940 snprintf(buf, buf_len, "%i", bridge->settings.multicast_router);
941 system_bridge_set_multicast_router(bridge, buf, true);
944 if (cfg->flags & BRIDGE_OPT_ROBUSTNESS) {
945 snprintf(buf, buf_len, "%i", cfg->robustness);
946 system_bridge_set_robustness(bridge, buf);
949 if (cfg->flags & BRIDGE_OPT_QUERY_INTERVAL) {
950 snprintf(buf, buf_len, "%i", cfg->query_interval);
951 system_bridge_set_query_interval(bridge, buf);
954 if (cfg->flags & BRIDGE_OPT_QUERY_RESPONSE_INTERVAL) {
955 snprintf(buf, buf_len, "%i", cfg->query_response_interval);
956 system_bridge_set_query_response_interval(bridge, buf);
959 if (cfg->flags & BRIDGE_OPT_LAST_MEMBER_INTERVAL) {
960 snprintf(buf, buf_len, "%i", cfg->last_member_interval);
961 system_bridge_set_last_member_interval(bridge, buf);
964 system_bridge_conf_multicast_deps(bridge, cfg, buf, buf_len);
967 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
970 unsigned long args[4] = {};
972 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
975 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
976 args[1] = !!cfg->stp;
977 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
979 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
980 args[1] = sec_to_jiffies(cfg->forward_delay);
981 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
983 system_bridge_conf_multicast(bridge, cfg, buf, sizeof(buf));
985 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
986 args[1] = cfg->priority;
987 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
989 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
990 args[0] = BRCTL_SET_AGEING_TIME;
991 args[1] = sec_to_jiffies(cfg->ageing_time);
992 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
995 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
996 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
997 args[1] = sec_to_jiffies(cfg->hello_time);
998 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1001 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
1002 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
1003 args[1] = sec_to_jiffies(cfg->max_age);
1004 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1010 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
1013 struct nlattr *linkinfo, *data;
1014 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
1016 static const struct {
1018 enum macvlan_mode val;
1020 { "private", MACVLAN_MODE_PRIVATE },
1021 { "vepa", MACVLAN_MODE_VEPA },
1022 { "bridge", MACVLAN_MODE_BRIDGE },
1023 { "passthru", MACVLAN_MODE_PASSTHRU },
1026 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1031 nlmsg_append(msg, &iim, sizeof(iim), 0);
1033 if (cfg->flags & MACVLAN_OPT_MACADDR)
1034 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
1035 nla_put_string(msg, IFLA_IFNAME, macvlan->ifname);
1036 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
1038 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1039 goto nla_put_failure;
1041 nla_put_string(msg, IFLA_INFO_KIND, "macvlan");
1043 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1044 goto nla_put_failure;
1047 for (i = 0; i < ARRAY_SIZE(modes); i++) {
1048 if (strcmp(cfg->mode, modes[i].name) != 0)
1051 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
1056 nla_nest_end(msg, data);
1057 nla_nest_end(msg, linkinfo);
1059 rv = system_rtnl_call(msg);
1061 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
1070 static int system_link_del(const char *ifname)
1073 struct ifinfomsg iim = {
1074 .ifi_family = AF_UNSPEC,
1078 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
1083 nlmsg_append(msg, &iim, sizeof(iim), 0);
1084 nla_put_string(msg, IFLA_IFNAME, ifname);
1085 return system_rtnl_call(msg);
1088 int system_macvlan_del(struct device *macvlan)
1090 return system_link_del(macvlan->ifname);
1093 static int system_vlan(struct device *dev, int id)
1095 struct vlan_ioctl_args ifr = {
1096 .cmd = SET_VLAN_NAME_TYPE_CMD,
1097 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
1100 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
1103 ifr.cmd = DEL_VLAN_CMD;
1106 ifr.cmd = ADD_VLAN_CMD;
1109 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
1110 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
1113 int system_vlan_add(struct device *dev, int id)
1115 return system_vlan(dev, id);
1118 int system_vlan_del(struct device *dev)
1120 return system_vlan(dev, -1);
1123 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
1126 struct nlattr *linkinfo, *data;
1127 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
1130 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1135 nlmsg_append(msg, &iim, sizeof(iim), 0);
1136 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
1137 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
1139 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1140 goto nla_put_failure;
1142 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
1144 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1145 goto nla_put_failure;
1147 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
1149 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
1150 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
1152 if(cfg->proto == VLAN_PROTO_8021AD)
1153 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);
1156 nla_nest_end(msg, data);
1157 nla_nest_end(msg, linkinfo);
1159 rv = system_rtnl_call(msg);
1161 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
1170 int system_vlandev_del(struct device *vlandev)
1172 return system_link_del(vlandev->ifname);
1176 system_if_get_settings(struct device *dev, struct device_settings *s)
1181 memset(&ifr, 0, sizeof(ifr));
1182 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1184 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
1185 s->mtu = ifr.ifr_mtu;
1186 s->flags |= DEV_OPT_MTU;
1189 s->mtu6 = system_update_ipv6_mtu(dev, 0);
1191 s->flags |= DEV_OPT_MTU6;
1193 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
1194 s->txqueuelen = ifr.ifr_qlen;
1195 s->flags |= DEV_OPT_TXQUEUELEN;
1198 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
1199 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
1200 s->flags |= DEV_OPT_MACADDR;
1203 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
1204 s->ipv6 = !strtoul(buf, NULL, 0);
1205 s->flags |= DEV_OPT_IPV6;
1208 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
1209 s->promisc = ifr.ifr_flags & IFF_PROMISC;
1210 s->flags |= DEV_OPT_PROMISC;
1212 s->multicast = ifr.ifr_flags & IFF_MULTICAST;
1213 s->flags |= DEV_OPT_MULTICAST;
1216 if (!system_get_rpfilter(dev, buf, sizeof(buf))) {
1217 s->rpfilter = strtoul(buf, NULL, 0);
1218 s->flags |= DEV_OPT_RPFILTER;
1221 if (!system_get_acceptlocal(dev, buf, sizeof(buf))) {
1222 s->acceptlocal = strtoul(buf, NULL, 0);
1223 s->flags |= DEV_OPT_ACCEPTLOCAL;
1226 if (!system_get_igmpversion(dev, buf, sizeof(buf))) {
1227 s->igmpversion = strtoul(buf, NULL, 0);
1228 s->flags |= DEV_OPT_IGMPVERSION;
1231 if (!system_get_mldversion(dev, buf, sizeof(buf))) {
1232 s->mldversion = strtoul(buf, NULL, 0);
1233 s->flags |= DEV_OPT_MLDVERSION;
1236 if (!system_get_neigh4reachabletime(dev, buf, sizeof(buf))) {
1237 s->neigh4reachabletime = strtoul(buf, NULL, 0);
1238 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1241 if (!system_get_neigh6reachabletime(dev, buf, sizeof(buf))) {
1242 s->neigh6reachabletime = strtoul(buf, NULL, 0);
1243 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1246 if (!system_get_dadtransmits(dev, buf, sizeof(buf))) {
1247 s->dadtransmits = strtoul(buf, NULL, 0);
1248 s->flags |= DEV_OPT_DADTRANSMITS;
1253 system_if_set_rps_xps_val(const char *path, int val)
1259 if (glob(path, 0, NULL, &gl))
1262 snprintf(val_buf, sizeof(val_buf), "%x", val);
1263 for (i = 0; i < gl.gl_pathc; i++)
1264 system_set_sysctl(gl.gl_pathv[i], val_buf);
1270 system_if_apply_rps_xps(struct device *dev, struct device_settings *s)
1272 long n_cpus = sysconf(_SC_NPROCESSORS_ONLN);
1278 val = (1 << n_cpus) - 1;
1279 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/rps_cpus", dev->ifname);
1280 system_if_set_rps_xps_val(dev_buf, s->rps ? val : 0);
1282 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/xps_cpus", dev->ifname);
1283 system_if_set_rps_xps_val(dev_buf, s->xps ? val : 0);
1287 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
1292 memset(&ifr, 0, sizeof(ifr));
1293 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1294 if (s->flags & DEV_OPT_MTU & apply_mask) {
1295 ifr.ifr_mtu = s->mtu;
1296 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
1297 s->flags &= ~DEV_OPT_MTU;
1299 if (s->flags & DEV_OPT_MTU6 & apply_mask) {
1300 system_update_ipv6_mtu(dev, s->mtu6);
1302 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
1303 ifr.ifr_qlen = s->txqueuelen;
1304 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
1305 s->flags &= ~DEV_OPT_TXQUEUELEN;
1307 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
1308 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
1309 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
1310 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
1311 s->flags &= ~DEV_OPT_MACADDR;
1313 if (s->flags & DEV_OPT_IPV6 & apply_mask)
1314 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
1315 if (s->flags & DEV_OPT_PROMISC & apply_mask) {
1316 if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
1317 !s->promisc ? IFF_PROMISC : 0) < 0)
1318 s->flags &= ~DEV_OPT_PROMISC;
1320 if (s->flags & DEV_OPT_RPFILTER & apply_mask) {
1321 snprintf(buf, sizeof(buf), "%d", s->rpfilter);
1322 system_set_rpfilter(dev, buf);
1324 if (s->flags & DEV_OPT_ACCEPTLOCAL & apply_mask)
1325 system_set_acceptlocal(dev, s->acceptlocal ? "1" : "0");
1326 if (s->flags & DEV_OPT_IGMPVERSION & apply_mask) {
1327 snprintf(buf, sizeof(buf), "%d", s->igmpversion);
1328 system_set_igmpversion(dev, buf);
1330 if (s->flags & DEV_OPT_MLDVERSION & apply_mask) {
1331 snprintf(buf, sizeof(buf), "%d", s->mldversion);
1332 system_set_mldversion(dev, buf);
1334 if (s->flags & DEV_OPT_NEIGHREACHABLETIME & apply_mask) {
1335 snprintf(buf, sizeof(buf), "%d", s->neigh4reachabletime);
1336 system_set_neigh4reachabletime(dev, buf);
1337 snprintf(buf, sizeof(buf), "%d", s->neigh6reachabletime);
1338 system_set_neigh6reachabletime(dev, buf);
1340 if (s->flags & DEV_OPT_DADTRANSMITS & apply_mask) {
1341 snprintf(buf, sizeof(buf), "%d", s->dadtransmits);
1342 system_set_dadtransmits(dev, buf);
1344 if (s->flags & DEV_OPT_MULTICAST & apply_mask) {
1345 if (system_if_flags(dev->ifname, s->multicast ? IFF_MULTICAST : 0,
1346 !s->multicast ? IFF_MULTICAST : 0) < 0)
1347 s->flags &= ~DEV_OPT_MULTICAST;
1350 system_if_apply_rps_xps(dev, s);
1353 int system_if_up(struct device *dev)
1355 system_if_get_settings(dev, &dev->orig_settings);
1356 /* Only keep orig settings based on what needs to be set */
1357 dev->orig_settings.valid_flags = dev->orig_settings.flags;
1358 dev->orig_settings.flags &= dev->settings.flags;
1359 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
1360 return system_if_flags(dev->ifname, IFF_UP, 0);
1363 int system_if_down(struct device *dev)
1365 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
1366 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
1370 struct if_check_data {
1376 #ifndef IFF_LOWER_UP
1377 #define IFF_LOWER_UP 0x10000
1380 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1382 struct nlmsghdr *nh = nlmsg_hdr(msg);
1383 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1384 struct if_check_data *chk = (struct if_check_data *)arg;
1386 if (nh->nlmsg_type != RTM_NEWLINK)
1389 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1390 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1395 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1397 struct if_check_data *chk = (struct if_check_data *)arg;
1402 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1404 struct if_check_data *chk = (struct if_check_data *)arg;
1406 device_set_present(chk->dev, false);
1407 device_set_link(chk->dev, false);
1408 chk->pending = err->error;
1413 int system_if_check(struct device *dev)
1415 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1417 struct ifinfomsg ifi = {
1418 .ifi_family = AF_UNSPEC,
1421 struct if_check_data chk = {
1427 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1431 if (nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1432 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1435 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1436 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1437 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1439 nl_send_auto_complete(sock_rtnl, msg);
1440 while (chk.pending > 0)
1441 nl_recvmsgs(sock_rtnl, cb);
1453 system_if_get_parent(struct device *dev)
1455 char buf[64], *devname;
1456 int ifindex, iflink, len;
1459 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1460 f = fopen(buf, "r");
1464 len = fread(buf, 1, sizeof(buf) - 1, f);
1471 iflink = strtoul(buf, NULL, 0);
1472 ifindex = system_if_resolve(dev);
1473 if (!iflink || iflink == ifindex)
1476 devname = if_indextoname(iflink, buf);
1480 return device_get(devname, true);
1484 read_string_file(int dir_fd, const char *file, char *buf, int len)
1490 fd = openat(dir_fd, file, O_RDONLY);
1495 len = read(fd, buf, len - 1);
1499 } else if (len > 0) {
1502 c = strchr(buf, '\n');
1515 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1520 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1522 *val = strtoull(buf, NULL, 0);
1527 /* Assume advertised flags == supported flags */
1528 static const struct {
1531 } ethtool_link_modes[] = {
1532 { ADVERTISED_10baseT_Half, "10H" },
1533 { ADVERTISED_10baseT_Full, "10F" },
1534 { ADVERTISED_100baseT_Half, "100H" },
1535 { ADVERTISED_100baseT_Full, "100F" },
1536 { ADVERTISED_1000baseT_Half, "1000H" },
1537 { ADVERTISED_1000baseT_Full, "1000F" },
1540 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1543 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1544 if (mask & ethtool_link_modes[i].mask)
1545 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1550 system_if_force_external(const char *ifname)
1555 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1556 return stat(buf, &s) == 0;
1560 system_if_dump_info(struct device *dev, struct blob_buf *b)
1562 struct ethtool_cmd ecmd;
1568 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
1569 dir_fd = open(buf, O_DIRECTORY);
1571 memset(&ecmd, 0, sizeof(ecmd));
1572 memset(&ifr, 0, sizeof(ifr));
1573 strcpy(ifr.ifr_name, dev->ifname);
1574 ifr.ifr_data = (caddr_t) &ecmd;
1575 ecmd.cmd = ETHTOOL_GSET;
1577 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1578 c = blobmsg_open_array(b, "link-advertising");
1579 system_add_link_modes(b, ecmd.advertising);
1580 blobmsg_close_array(b, c);
1582 c = blobmsg_open_array(b, "link-supported");
1583 system_add_link_modes(b, ecmd.supported);
1584 blobmsg_close_array(b, c);
1586 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1587 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1588 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1589 blobmsg_add_string_buffer(b);
1597 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1599 const char *const counters[] = {
1600 "collisions", "rx_frame_errors", "tx_compressed",
1601 "multicast", "rx_length_errors", "tx_dropped",
1602 "rx_bytes", "rx_missed_errors", "tx_errors",
1603 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1604 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1605 "rx_dropped", "tx_aborted_errors", "tx_packets",
1606 "rx_errors", "tx_bytes", "tx_window_errors",
1607 "rx_fifo_errors", "tx_carrier_errors",
1614 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1615 stats_dir = open(buf, O_DIRECTORY);
1619 for (i = 0; i < ARRAY_SIZE(counters); i++)
1620 if (read_uint64_file(stats_dir, counters[i], &val))
1621 blobmsg_add_u64(b, counters[i], val);
1627 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1629 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1630 int alen = v4 ? 4 : 16;
1631 unsigned int flags = 0;
1632 struct ifaddrmsg ifa = {
1633 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1634 .ifa_prefixlen = addr->mask,
1635 .ifa_index = dev->ifindex,
1639 if (cmd == RTM_NEWADDR)
1640 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1642 msg = nlmsg_alloc_simple(cmd, flags);
1646 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1647 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1649 if (addr->broadcast)
1650 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1651 if (addr->point_to_point)
1652 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1654 time_t now = system_get_rtime();
1655 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1657 if (addr->preferred_until) {
1658 int64_t preferred = addr->preferred_until - now;
1661 else if (preferred > UINT32_MAX)
1662 preferred = UINT32_MAX;
1664 cinfo.ifa_prefered = preferred;
1667 if (addr->valid_until) {
1668 int64_t valid = addr->valid_until - now;
1673 else if (valid > UINT32_MAX)
1676 cinfo.ifa_valid = valid;
1679 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1681 if (cmd == RTM_NEWADDR && (addr->flags & DEVADDR_OFFLINK))
1682 nla_put_u32(msg, IFA_FLAGS, IFA_F_NOPREFIXROUTE);
1685 return system_rtnl_call(msg);
1688 int system_add_address(struct device *dev, struct device_addr *addr)
1690 return system_addr(dev, addr, RTM_NEWADDR);
1693 int system_del_address(struct device *dev, struct device_addr *addr)
1695 return system_addr(dev, addr, RTM_DELADDR);
1698 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1700 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1702 unsigned int flags = 0;
1705 have_gw = !!route->nexthop.in.s_addr;
1707 have_gw = route->nexthop.in6.s6_addr32[0] ||
1708 route->nexthop.in6.s6_addr32[1] ||
1709 route->nexthop.in6.s6_addr32[2] ||
1710 route->nexthop.in6.s6_addr32[3];
1712 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1713 ? route->table : RT_TABLE_MAIN;
1715 struct rtmsg rtm = {
1716 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1717 .rtm_dst_len = route->mask,
1718 .rtm_src_len = route->sourcemask,
1719 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1720 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
1721 .rtm_scope = RT_SCOPE_NOWHERE,
1722 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1723 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1727 if (cmd == RTM_NEWROUTE) {
1728 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1730 if (!dev) { // Add null-route
1731 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1732 rtm.rtm_type = RTN_UNREACHABLE;
1735 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1738 if (route->flags & DEVROUTE_TYPE) {
1739 rtm.rtm_type = route->type;
1740 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
1741 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
1742 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
1743 rtm.rtm_table = RT_TABLE_LOCAL;
1746 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT) {
1747 rtm.rtm_scope = RT_SCOPE_HOST;
1748 } else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
1749 rtm.rtm_type == RTN_ANYCAST) {
1750 rtm.rtm_scope = RT_SCOPE_LINK;
1751 } else if (rtm.rtm_type == RTN_BLACKHOLE || rtm.rtm_type == RTN_UNREACHABLE ||
1752 rtm.rtm_type == RTN_PROHIBIT || rtm.rtm_type == RTN_FAILED_POLICY) {
1753 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1758 msg = nlmsg_alloc_simple(cmd, flags);
1762 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1765 nla_put(msg, RTA_DST, alen, &route->addr);
1767 if (route->sourcemask) {
1768 if (rtm.rtm_family == AF_INET)
1769 nla_put(msg, RTA_PREFSRC, alen, &route->source);
1771 nla_put(msg, RTA_SRC, alen, &route->source);
1774 if (route->metric > 0)
1775 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1778 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1781 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1784 nla_put_u32(msg, RTA_TABLE, table);
1786 if (route->flags & DEVROUTE_MTU) {
1787 struct nlattr *metrics;
1789 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1790 goto nla_put_failure;
1792 nla_put_u32(msg, RTAX_MTU, route->mtu);
1794 nla_nest_end(msg, metrics);
1797 return system_rtnl_call(msg);
1804 int system_add_route(struct device *dev, struct device_route *route)
1806 return system_rt(dev, route, RTM_NEWROUTE);
1809 int system_del_route(struct device *dev, struct device_route *route)
1811 return system_rt(dev, route, RTM_DELROUTE);
1814 int system_flush_routes(void)
1816 const char *names[] = {
1817 "/proc/sys/net/ipv4/route/flush",
1818 "/proc/sys/net/ipv6/route/flush"
1822 for (i = 0; i < ARRAY_SIZE(names); i++) {
1823 fd = open(names[i], O_WRONLY);
1827 if (write(fd, "-1", 2)) {}
1833 bool system_resolve_rt_type(const char *type, unsigned int *id)
1835 return system_rtn_aton(type, id);
1838 bool system_resolve_rt_table(const char *name, unsigned int *id)
1842 unsigned int n, table = RT_TABLE_UNSPEC;
1844 /* first try to parse table as number */
1845 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1848 /* handle well known aliases */
1849 else if (!strcmp(name, "default"))
1850 table = RT_TABLE_DEFAULT;
1851 else if (!strcmp(name, "main"))
1852 table = RT_TABLE_MAIN;
1853 else if (!strcmp(name, "local"))
1854 table = RT_TABLE_LOCAL;
1856 /* try to look up name in /etc/iproute2/rt_tables */
1857 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1859 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1861 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1864 n = strtoul(e, NULL, 10);
1865 e = strtok(NULL, " \t\n");
1867 if (e && !strcmp(e, name))
1877 if (table == RT_TABLE_UNSPEC)
1884 bool system_is_default_rt_table(unsigned int id)
1886 return (id == RT_TABLE_MAIN);
1889 bool system_resolve_rpfilter(const char *filter, unsigned int *id)
1894 if (!strcmp(filter, "strict"))
1896 else if (!strcmp(filter, "loose"))
1899 n = strtoul(filter, &e, 0);
1900 if (*e || e == filter || n > 2)
1908 static int system_iprule(struct iprule *rule, int cmd)
1910 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1913 struct rtmsg rtm = {
1914 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1915 .rtm_protocol = RTPROT_STATIC,
1916 .rtm_scope = RT_SCOPE_UNIVERSE,
1917 .rtm_table = RT_TABLE_UNSPEC,
1918 .rtm_type = RTN_UNSPEC,
1922 if (cmd == RTM_NEWRULE)
1923 rtm.rtm_type = RTN_UNICAST;
1926 rtm.rtm_flags |= FIB_RULE_INVERT;
1928 if (rule->flags & IPRULE_SRC)
1929 rtm.rtm_src_len = rule->src_mask;
1931 if (rule->flags & IPRULE_DEST)
1932 rtm.rtm_dst_len = rule->dest_mask;
1934 if (rule->flags & IPRULE_TOS)
1935 rtm.rtm_tos = rule->tos;
1937 if (rule->flags & IPRULE_LOOKUP) {
1938 if (rule->lookup < 256)
1939 rtm.rtm_table = rule->lookup;
1942 if (rule->flags & IPRULE_ACTION)
1943 rtm.rtm_type = rule->action;
1944 else if (rule->flags & IPRULE_GOTO)
1945 rtm.rtm_type = FR_ACT_GOTO;
1946 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1947 rtm.rtm_type = FR_ACT_NOP;
1949 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1954 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1956 if (rule->flags & IPRULE_IN)
1957 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1959 if (rule->flags & IPRULE_OUT)
1960 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1962 if (rule->flags & IPRULE_SRC)
1963 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1965 if (rule->flags & IPRULE_DEST)
1966 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1968 if (rule->flags & IPRULE_PRIORITY)
1969 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1970 else if (cmd == RTM_NEWRULE)
1971 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1973 if (rule->flags & IPRULE_FWMARK)
1974 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1976 if (rule->flags & IPRULE_FWMASK)
1977 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1979 if (rule->flags & IPRULE_LOOKUP) {
1980 if (rule->lookup >= 256)
1981 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1984 if (rule->flags & IPRULE_GOTO)
1985 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1987 return system_rtnl_call(msg);
1990 int system_add_iprule(struct iprule *rule)
1992 return system_iprule(rule, RTM_NEWRULE);
1995 int system_del_iprule(struct iprule *rule)
1997 return system_iprule(rule, RTM_DELRULE);
2000 int system_flush_iprules(void)
2005 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
2006 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
2008 memset(&rule, 0, sizeof(rule));
2011 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2014 rule.lookup = RT_TABLE_LOCAL;
2015 rv |= system_iprule(&rule, RTM_NEWRULE);
2017 rule.priority = 32766;
2018 rule.lookup = RT_TABLE_MAIN;
2019 rv |= system_iprule(&rule, RTM_NEWRULE);
2021 rule.priority = 32767;
2022 rule.lookup = RT_TABLE_DEFAULT;
2023 rv |= system_iprule(&rule, RTM_NEWRULE);
2026 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2029 rule.lookup = RT_TABLE_LOCAL;
2030 rv |= system_iprule(&rule, RTM_NEWRULE);
2032 rule.priority = 32766;
2033 rule.lookup = RT_TABLE_MAIN;
2034 rv |= system_iprule(&rule, RTM_NEWRULE);
2039 bool system_resolve_iprule_action(const char *action, unsigned int *id)
2041 return system_rtn_aton(action, id);
2044 time_t system_get_rtime(void)
2049 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
2052 if (gettimeofday(&tv, NULL) == 0)
2059 #define IP_DF 0x4000
2062 static int tunnel_ioctl(const char *name, int cmd, void *p)
2066 memset(&ifr, 0, sizeof(ifr));
2067 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
2068 ifr.ifr_ifru.ifru_data = p;
2069 return ioctl(sock_ioctl, cmd, &ifr);
2072 #ifdef IFLA_IPTUN_MAX
2073 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
2074 static int system_add_gre_tunnel(const char *name, const char *kind,
2075 const unsigned int link, struct blob_attr **tb, bool v6)
2078 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2079 struct blob_attr *cur;
2080 uint32_t ikey = 0, okey = 0, flags = 0, flowinfo = 0;
2081 uint16_t iflags = 0, oflags = 0;
2083 int ret = 0, ttl = 64;
2085 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2089 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2090 nla_put_string(nlm, IFLA_IFNAME, name);
2092 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2098 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2099 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2106 nla_put_u32(nlm, IFLA_GRE_LINK, link);
2108 if ((cur = tb[TUNNEL_ATTR_TTL]))
2109 ttl = blobmsg_get_u32(cur);
2111 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
2113 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2114 char *str = blobmsg_get_string(cur);
2115 if (strcmp(str, "inherit")) {
2118 if (!system_tos_aton(str, &uval)) {
2124 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
2129 flags |= IP6_TNL_F_USE_ORIG_TCLASS;
2135 if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) {
2136 uint8_t icsum, ocsum, iseqno, oseqno;
2137 if (sscanf(blobmsg_get_string(cur), "%u,%u,%hhu,%hhu,%hhu,%hhu",
2138 &ikey, &okey, &icsum, &ocsum, &iseqno, &oseqno) < 6) {
2163 struct in6_addr in6buf;
2164 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2165 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2169 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
2172 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2173 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2177 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
2179 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, 4);
2182 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
2185 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags);
2187 struct in_addr inbuf;
2190 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2191 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2195 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
2198 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2199 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2203 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
2205 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
2207 okey = inbuf.s_addr;
2212 ikey = inbuf.s_addr;
2218 if ((cur = tb[TUNNEL_ATTR_DF]))
2219 set_df = blobmsg_get_bool(cur);
2221 /* ttl !=0 and nopmtudisc are incompatible */
2222 if (ttl && !set_df) {
2227 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
2229 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
2233 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
2236 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
2239 nla_put_u32(nlm, IFLA_GRE_OKEY, okey);
2242 nla_put_u32(nlm, IFLA_GRE_IKEY, ikey);
2244 nla_nest_end(nlm, infodata);
2245 nla_nest_end(nlm, linkinfo);
2247 return system_rtnl_call(nlm);
2256 static int system_add_vti_tunnel(const char *name, const char *kind,
2257 const unsigned int link, struct blob_attr **tb, bool v6)
2260 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2261 struct blob_attr *cur;
2262 uint32_t ikey = 0, okey = 0;
2265 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2269 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2270 nla_put_string(nlm, IFLA_IFNAME, name);
2272 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2278 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2279 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2286 nla_put_u32(nlm, IFLA_VTI_LINK, link);
2288 if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) {
2289 if (sscanf(blobmsg_get_string(cur), "%u,%u",
2290 &ikey, &okey) < 2) {
2297 struct in6_addr in6buf;
2298 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2299 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2303 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(in6buf), &in6buf);
2306 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2307 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2311 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(in6buf), &in6buf);
2315 struct in_addr inbuf;
2317 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2318 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2322 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(inbuf), &inbuf);
2325 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2326 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2330 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(inbuf), &inbuf);
2336 nla_put_u32(nlm, IFLA_VTI_OKEY, htonl(okey));
2339 nla_put_u32(nlm, IFLA_VTI_IKEY, htonl(ikey));
2341 nla_nest_end(nlm, infodata);
2342 nla_nest_end(nlm, linkinfo);
2344 return system_rtnl_call(nlm);
2352 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
2354 struct blob_attr *cur;
2356 struct ip_tunnel_parm p = {
2365 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
2366 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
2369 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
2370 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
2373 if ((cur = tb[TUNNEL_ATTR_DF]))
2374 set_df = blobmsg_get_bool(cur);
2376 if ((cur = tb[TUNNEL_ATTR_TTL]))
2377 p.iph.ttl = blobmsg_get_u32(cur);
2379 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2380 char *str = blobmsg_get_string(cur);
2381 if (strcmp(str, "inherit")) {
2384 if (!system_tos_aton(str, &uval))
2392 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
2393 /* ttl !=0 and nopmtudisc are incompatible */
2394 if (p.iph.ttl && p.iph.frag_off == 0)
2397 strncpy(p.name, name, sizeof(p.name));
2399 switch (p.iph.protocol) {
2401 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
2403 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
2410 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
2412 struct blob_attr *cur;
2415 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2417 str = blobmsg_data(cur);
2419 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
2420 !strcmp(str, "greip6") || !strcmp(str, "gretapip6") ||
2421 !strcmp(str, "vtiip") || !strcmp(str, "vtiip6"))
2422 return system_link_del(name);
2424 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
2427 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
2429 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2431 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2432 blob_data(attr), blob_len(attr));
2434 return __system_del_ip_tunnel(name, tb);
2437 int system_update_ipv6_mtu(struct device *dev, int mtu)
2441 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
2444 int fd = open(buf, O_RDWR);
2447 ssize_t len = read(fd, buf, sizeof(buf) - 1);
2454 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) > 0)
2463 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
2465 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2466 struct blob_attr *cur;
2469 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2470 blob_data(attr), blob_len(attr));
2472 __system_del_ip_tunnel(name, tb);
2474 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2476 str = blobmsg_data(cur);
2478 unsigned int ttl = 0;
2479 if ((cur = tb[TUNNEL_ATTR_TTL])) {
2480 ttl = blobmsg_get_u32(cur);
2485 unsigned int link = 0;
2486 if ((cur = tb[TUNNEL_ATTR_LINK])) {
2487 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
2491 if (iface->l3_dev.dev)
2492 link = iface->l3_dev.dev->ifindex;
2495 if (!strcmp(str, "sit")) {
2496 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
2500 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
2502 struct ip_tunnel_6rd p6;
2504 memset(&p6, 0, sizeof(p6));
2506 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
2507 &p6.prefix, &mask) || mask > 128)
2509 p6.prefixlen = mask;
2511 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
2512 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
2513 &p6.relay_prefix, &mask) || mask > 32)
2515 p6.relay_prefixlen = mask;
2518 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
2519 __system_del_ip_tunnel(name, tb);
2524 #ifdef IFLA_IPTUN_MAX
2525 } else if (!strcmp(str, "ipip6")) {
2526 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2527 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2528 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2534 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2535 nla_put_string(nlm, IFLA_IFNAME, name);
2538 nla_put_u32(nlm, IFLA_LINK, link);
2540 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2545 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2546 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2553 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2555 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2556 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2557 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
2559 struct in6_addr in6buf;
2560 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2561 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2565 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2568 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2569 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2573 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2576 #ifdef IFLA_IPTUN_FMR_MAX
2577 if ((cur = tb[TUNNEL_ATTR_FMRS])) {
2578 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2580 struct blob_attr *fmr;
2581 unsigned rem, fmrcnt = 0;
2582 blobmsg_for_each_attr(fmr, cur, rem) {
2583 if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
2586 unsigned ip4len, ip6len, ealen, offset = 6;
2590 if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
2591 ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) {
2596 struct in6_addr ip6prefix;
2597 struct in_addr ip4prefix;
2598 if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
2599 inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) {
2604 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2606 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2607 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2608 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2609 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2610 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2611 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2613 nla_nest_end(nlm, rule);
2616 nla_nest_end(nlm, fmrs);
2620 nla_nest_end(nlm, infodata);
2621 nla_nest_end(nlm, linkinfo);
2623 return system_rtnl_call(nlm);
2627 } else if (!strcmp(str, "greip")) {
2628 return system_add_gre_tunnel(name, "gre", link, tb, false);
2629 } else if (!strcmp(str, "gretapip")) {
2630 return system_add_gre_tunnel(name, "gretap", link, tb, false);
2631 } else if (!strcmp(str, "greip6")) {
2632 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
2633 } else if (!strcmp(str, "gretapip6")) {
2634 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
2636 } else if (!strcmp(str, "vtiip")) {
2637 return system_add_vti_tunnel(name, "vti", link, tb, false);
2638 } else if (!strcmp(str, "vtiip6")) {
2639 return system_add_vti_tunnel(name, "vti6", link, tb, true);
2642 } else if (!strcmp(str, "ipip")) {
2643 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);