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_neigh4gcstaletime(struct device *dev, const char *val)
311 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/gc_stale_time", dev->ifname, val);
314 static void system_set_neigh6gcstaletime(struct device *dev, const char *val)
316 system_set_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/gc_stale_time", dev->ifname, val);
319 static void system_set_dadtransmits(struct device *dev, const char *val)
321 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits", dev->ifname, val);
324 static void system_bridge_set_multicast_to_unicast(struct device *dev, const char *val)
326 system_set_dev_sysctl("/sys/class/net/%s/brport/multicast_to_unicast", dev->ifname, val);
329 static void system_bridge_set_multicast_fast_leave(struct device *dev, const char *val)
331 system_set_dev_sysctl("/sys/class/net/%s/brport/multicast_fast_leave", dev->ifname, val);
334 static void system_bridge_set_hairpin_mode(struct device *dev, const char *val)
336 system_set_dev_sysctl("/sys/class/net/%s/brport/hairpin_mode", dev->ifname, val);
339 static void system_bridge_set_multicast_router(struct device *dev, const char *val, bool bridge)
341 system_set_dev_sysctl(bridge ? "/sys/class/net/%s/bridge/multicast_router" :
342 "/sys/class/net/%s/brport/multicast_router",
346 static void system_bridge_set_robustness(struct device *dev, const char *val)
348 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_startup_query_count",
350 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_last_member_count",
354 static void system_bridge_set_query_interval(struct device *dev, const char *val)
356 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_query_interval",
360 static void system_bridge_set_query_response_interval(struct device *dev, const char *val)
362 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_query_response_interval",
366 static void system_bridge_set_last_member_interval(struct device *dev, const char *val)
368 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_last_member_interval",
372 static void system_bridge_set_membership_interval(struct device *dev, const char *val)
374 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_membership_interval",
378 static void system_bridge_set_other_querier_timeout(struct device *dev, const char *val)
380 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier_interval",
384 static void system_bridge_set_startup_query_interval(struct device *dev, const char *val)
386 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_startup_query_interval",
390 static void system_bridge_set_learning(struct device *dev, const char *val)
392 system_set_dev_sysctl("/sys/class/net/%s/brport/learning", dev->ifname, val);
395 static void system_bridge_set_unicast_flood(struct device *dev, const char *val)
397 system_set_dev_sysctl("/sys/class/net/%s/brport/unicast_flood", dev->ifname, val);
400 static int system_get_sysctl(const char *path, char *buf, const size_t buf_sz)
402 int fd = -1, ret = -1;
404 fd = open(path, O_RDONLY);
408 ssize_t len = read(fd, buf, buf_sz - 1);
422 system_get_dev_sysctl(const char *path, const char *device, char *buf, const size_t buf_sz)
424 snprintf(dev_buf, sizeof(dev_buf), path, device);
425 return system_get_sysctl(dev_buf, buf, buf_sz);
428 static int system_get_disable_ipv6(struct device *dev, char *buf, const size_t buf_sz)
430 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6",
431 dev->ifname, buf, buf_sz);
434 static int system_get_rpfilter(struct device *dev, char *buf, const size_t buf_sz)
436 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter",
437 dev->ifname, buf, buf_sz);
440 static int system_get_acceptlocal(struct device *dev, char *buf, const size_t buf_sz)
442 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local",
443 dev->ifname, buf, buf_sz);
446 static int system_get_igmpversion(struct device *dev, char *buf, const size_t buf_sz)
448 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version",
449 dev->ifname, buf, buf_sz);
452 static int system_get_mldversion(struct device *dev, char *buf, const size_t buf_sz)
454 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version",
455 dev->ifname, buf, buf_sz);
458 static int system_get_neigh4reachabletime(struct device *dev, char *buf, const size_t buf_sz)
460 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms",
461 dev->ifname, buf, buf_sz);
464 static int system_get_neigh6reachabletime(struct device *dev, char *buf, const size_t buf_sz)
466 return system_get_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms",
467 dev->ifname, buf, buf_sz);
470 static int system_get_neigh4gcstaletime(struct device *dev, char *buf, const size_t buf_sz)
472 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/gc_stale_time",
473 dev->ifname, buf, buf_sz);
476 static int system_get_neigh6gcstaletime(struct device *dev, char *buf, const size_t buf_sz)
478 return system_get_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/gc_stale_time",
479 dev->ifname, buf, buf_sz);
482 static int system_get_dadtransmits(struct device *dev, char *buf, const size_t buf_sz)
484 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits",
485 dev->ifname, buf, buf_sz);
488 // Evaluate netlink messages
489 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
491 struct nlmsghdr *nh = nlmsg_hdr(msg);
492 struct nlattr *nla[__IFLA_MAX];
496 if (nh->nlmsg_type != RTM_NEWLINK)
499 nlmsg_parse(nh, sizeof(struct ifinfomsg), nla, __IFLA_MAX - 1, NULL);
500 if (!nla[IFLA_IFNAME])
503 struct device *dev = device_find(nla_data(nla[IFLA_IFNAME]));
507 if (!system_get_dev_sysctl("/sys/class/net/%s/carrier", dev->ifname, buf, sizeof(buf)))
508 link_state = strtoul(buf, NULL, 0);
510 device_set_link(dev, link_state ? true : false);
517 handle_hotplug_msg(char *data, int size)
519 const char *subsystem = NULL, *interface = NULL;
520 char *cur, *end, *sep;
525 if (!strncmp(data, "add@", 4))
527 else if (!strncmp(data, "remove@", 7))
532 skip = strlen(data) + 1;
535 for (cur = data + skip; cur < end; cur += skip) {
536 skip = strlen(cur) + 1;
538 sep = strchr(cur, '=');
543 if (!strcmp(cur, "INTERFACE"))
545 else if (!strcmp(cur, "SUBSYSTEM")) {
547 if (strcmp(subsystem, "net") != 0)
550 if (subsystem && interface)
556 dev = device_find(interface);
560 if (dev->type != &simple_device_type)
563 if (add && system_if_force_external(dev->ifname))
566 device_set_present(dev, add);
570 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
572 struct event_socket *ev = container_of(u, struct event_socket, uloop);
573 struct sockaddr_nl nla;
574 unsigned char *buf = NULL;
577 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
579 handle_hotplug_msg((char *) buf, size);
585 static int system_rtnl_call(struct nl_msg *msg)
589 ret = nl_send_auto_complete(sock_rtnl, msg);
595 return nl_wait_for_ack(sock_rtnl);
598 int system_bridge_delbr(struct device *bridge)
600 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
603 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
607 memset(&ifr, 0, sizeof(ifr));
609 ifr.ifr_ifindex = dev->ifindex;
612 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
613 return ioctl(sock_ioctl, cmd, &ifr);
616 static bool system_is_bridge(const char *name, char *buf, int buflen)
620 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
621 if (stat(buf, &st) < 0)
627 static char *system_get_bridge(const char *name, char *buf, int buflen)
633 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
634 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
638 len = readlink(gl.gl_pathv[0], buf, buflen);
646 path = strrchr(buf, '/');
654 system_bridge_set_wireless(struct device *bridge, struct device *dev)
656 bool mcast_to_ucast = dev->wireless_ap;
659 if (bridge->settings.flags & DEV_OPT_MULTICAST_TO_UNICAST &&
660 !bridge->settings.multicast_to_unicast)
661 mcast_to_ucast = false;
663 if (!mcast_to_ucast || dev->wireless_isolate)
666 system_bridge_set_multicast_to_unicast(dev, mcast_to_ucast ? "1" : "0");
667 system_bridge_set_hairpin_mode(dev, hairpin ? "1" : "0");
670 int system_bridge_addif(struct device *bridge, struct device *dev)
676 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
677 if (!oldbr || strcmp(oldbr, bridge->ifname) != 0)
678 ret = system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
681 system_bridge_set_wireless(bridge, dev);
683 if (dev->settings.flags & DEV_OPT_MULTICAST_ROUTER) {
684 snprintf(buf, sizeof(buf), "%i", dev->settings.multicast_router);
685 system_bridge_set_multicast_router(dev, buf, false);
688 if (dev->settings.flags & DEV_OPT_MULTICAST_FAST_LEAVE &&
689 dev->settings.multicast_fast_leave)
690 system_bridge_set_multicast_fast_leave(dev, "1");
692 if (dev->settings.flags & DEV_OPT_LEARNING &&
693 !dev->settings.learning)
694 system_bridge_set_learning(dev, "0");
696 if (dev->settings.flags & DEV_OPT_UNICAST_FLOOD &&
697 !dev->settings.unicast_flood)
698 system_bridge_set_unicast_flood(dev, "0");
703 int system_bridge_delif(struct device *bridge, struct device *dev)
705 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
708 int system_if_resolve(struct device *dev)
711 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
712 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
713 return ifr.ifr_ifindex;
718 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
722 memset(&ifr, 0, sizeof(ifr));
723 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
724 ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
725 ifr.ifr_flags |= add;
726 ifr.ifr_flags &= ~rem;
727 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
739 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
741 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
743 return ifa->ifa_index == ifindex;
746 static bool check_route(struct nlmsghdr *hdr, int ifindex)
748 struct rtmsg *r = NLMSG_DATA(hdr);
749 struct nlattr *tb[__RTA_MAX];
751 if (r->rtm_protocol == RTPROT_KERNEL &&
752 r->rtm_family == AF_INET6)
755 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
759 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
762 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
767 static int cb_clear_event(struct nl_msg *msg, void *arg)
769 struct clear_data *clr = arg;
770 struct nlmsghdr *hdr = nlmsg_hdr(msg);
771 bool (*cb)(struct nlmsghdr *, int ifindex);
777 if (hdr->nlmsg_type != RTM_NEWADDR)
784 if (hdr->nlmsg_type != RTM_NEWROUTE)
791 if (hdr->nlmsg_type != RTM_NEWRULE)
800 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
803 if (type == RTM_DELRULE)
804 D(SYSTEM, "Remove a rule\n");
806 D(SYSTEM, "Remove %s from device %s\n",
807 type == RTM_DELADDR ? "an address" : "a route",
809 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
810 hdr = nlmsg_hdr(clr->msg);
811 hdr->nlmsg_type = type;
812 hdr->nlmsg_flags = NLM_F_REQUEST;
814 nl_socket_disable_auto_ack(sock_rtnl);
815 nl_send_auto_complete(sock_rtnl, clr->msg);
816 nl_socket_enable_auto_ack(sock_rtnl);
822 cb_finish_event(struct nl_msg *msg, void *arg)
830 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
833 *pending = err->error;
838 system_if_clear_entries(struct device *dev, int type, int af)
840 struct clear_data clr;
841 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
844 .rtm_flags = RTM_F_CLONED,
846 int flags = NLM_F_DUMP;
855 clr.size = sizeof(struct rtgenmsg);
858 clr.size = sizeof(struct rtmsg);
867 clr.msg = nlmsg_alloc_simple(type, flags);
871 nlmsg_append(clr.msg, &rtm, clr.size, 0);
872 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
873 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
874 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
876 nl_send_auto_complete(sock_rtnl, clr.msg);
878 nl_recvmsgs(sock_rtnl, cb);
886 * Clear bridge (membership) state and bring down device
888 void system_if_clear_state(struct device *dev)
890 static char buf[256];
893 device_set_ifindex(dev, system_if_resolve(dev));
894 if (dev->external || !dev->ifindex)
897 system_if_flags(dev->ifname, 0, IFF_UP);
899 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
900 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
901 system_bridge_delbr(dev);
905 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
907 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
908 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
911 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
912 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
913 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
914 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
915 system_set_disable_ipv6(dev, "0");
918 static inline unsigned long
919 sec_to_jiffies(int val)
921 return (unsigned long) val * 100;
924 static void system_bridge_conf_multicast_deps(struct device *bridge,
925 struct bridge_config *cfg,
931 if (cfg->flags & BRIDGE_OPT_ROBUSTNESS ||
932 cfg->flags & BRIDGE_OPT_QUERY_INTERVAL ||
933 cfg->flags & BRIDGE_OPT_QUERY_RESPONSE_INTERVAL) {
934 val = cfg->robustness * cfg->query_interval +
935 cfg->query_response_interval;
937 snprintf(buf, buf_len, "%i", val);
938 system_bridge_set_membership_interval(bridge, buf);
940 val = cfg->robustness * cfg->query_interval +
941 cfg->query_response_interval / 2;
943 snprintf(buf, buf_len, "%i", val);
944 system_bridge_set_other_querier_timeout(bridge, buf);
947 if (cfg->flags & BRIDGE_OPT_QUERY_INTERVAL) {
948 val = cfg->query_interval / 4;
950 snprintf(buf, buf_len, "%i", val);
951 system_bridge_set_startup_query_interval(bridge, buf);
955 static void system_bridge_conf_multicast(struct device *bridge,
956 struct bridge_config *cfg,
960 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
961 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
963 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier",
964 bridge->ifname, cfg->multicast_querier ? "1" : "0");
966 snprintf(buf, buf_len, "%i", cfg->hash_max);
967 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/hash_max",
968 bridge->ifname, buf);
970 if (bridge->settings.flags & DEV_OPT_MULTICAST_ROUTER) {
971 snprintf(buf, buf_len, "%i", bridge->settings.multicast_router);
972 system_bridge_set_multicast_router(bridge, buf, true);
975 if (cfg->flags & BRIDGE_OPT_ROBUSTNESS) {
976 snprintf(buf, buf_len, "%i", cfg->robustness);
977 system_bridge_set_robustness(bridge, buf);
980 if (cfg->flags & BRIDGE_OPT_QUERY_INTERVAL) {
981 snprintf(buf, buf_len, "%i", cfg->query_interval);
982 system_bridge_set_query_interval(bridge, buf);
985 if (cfg->flags & BRIDGE_OPT_QUERY_RESPONSE_INTERVAL) {
986 snprintf(buf, buf_len, "%i", cfg->query_response_interval);
987 system_bridge_set_query_response_interval(bridge, buf);
990 if (cfg->flags & BRIDGE_OPT_LAST_MEMBER_INTERVAL) {
991 snprintf(buf, buf_len, "%i", cfg->last_member_interval);
992 system_bridge_set_last_member_interval(bridge, buf);
995 system_bridge_conf_multicast_deps(bridge, cfg, buf, buf_len);
998 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
1001 unsigned long args[4] = {};
1003 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
1006 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
1007 args[1] = !!cfg->stp;
1008 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1010 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
1011 args[1] = sec_to_jiffies(cfg->forward_delay);
1012 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1014 system_bridge_conf_multicast(bridge, cfg, buf, sizeof(buf));
1016 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
1017 args[1] = cfg->priority;
1018 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1020 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
1021 args[0] = BRCTL_SET_AGEING_TIME;
1022 args[1] = sec_to_jiffies(cfg->ageing_time);
1023 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1026 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
1027 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
1028 args[1] = sec_to_jiffies(cfg->hello_time);
1029 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1032 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
1033 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
1034 args[1] = sec_to_jiffies(cfg->max_age);
1035 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1041 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
1044 struct nlattr *linkinfo, *data;
1045 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
1047 static const struct {
1049 enum macvlan_mode val;
1051 { "private", MACVLAN_MODE_PRIVATE },
1052 { "vepa", MACVLAN_MODE_VEPA },
1053 { "bridge", MACVLAN_MODE_BRIDGE },
1054 { "passthru", MACVLAN_MODE_PASSTHRU },
1057 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1062 nlmsg_append(msg, &iim, sizeof(iim), 0);
1064 if (cfg->flags & MACVLAN_OPT_MACADDR)
1065 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
1066 nla_put_string(msg, IFLA_IFNAME, macvlan->ifname);
1067 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
1069 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1070 goto nla_put_failure;
1072 nla_put_string(msg, IFLA_INFO_KIND, "macvlan");
1074 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1075 goto nla_put_failure;
1078 for (i = 0; i < ARRAY_SIZE(modes); i++) {
1079 if (strcmp(cfg->mode, modes[i].name) != 0)
1082 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
1087 nla_nest_end(msg, data);
1088 nla_nest_end(msg, linkinfo);
1090 rv = system_rtnl_call(msg);
1092 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
1101 static int system_link_del(const char *ifname)
1104 struct ifinfomsg iim = {
1105 .ifi_family = AF_UNSPEC,
1109 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
1114 nlmsg_append(msg, &iim, sizeof(iim), 0);
1115 nla_put_string(msg, IFLA_IFNAME, ifname);
1116 return system_rtnl_call(msg);
1119 int system_macvlan_del(struct device *macvlan)
1121 return system_link_del(macvlan->ifname);
1124 static int system_vlan(struct device *dev, int id)
1126 struct vlan_ioctl_args ifr = {
1127 .cmd = SET_VLAN_NAME_TYPE_CMD,
1128 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
1131 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
1134 ifr.cmd = DEL_VLAN_CMD;
1137 ifr.cmd = ADD_VLAN_CMD;
1140 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
1141 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
1144 int system_vlan_add(struct device *dev, int id)
1146 return system_vlan(dev, id);
1149 int system_vlan_del(struct device *dev)
1151 return system_vlan(dev, -1);
1154 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
1157 struct nlattr *linkinfo, *data;
1158 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
1161 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1166 nlmsg_append(msg, &iim, sizeof(iim), 0);
1167 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
1168 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
1170 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1171 goto nla_put_failure;
1173 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
1175 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1176 goto nla_put_failure;
1178 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
1180 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
1181 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
1183 if(cfg->proto == VLAN_PROTO_8021AD)
1184 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);
1187 nla_nest_end(msg, data);
1188 nla_nest_end(msg, linkinfo);
1190 rv = system_rtnl_call(msg);
1192 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
1201 int system_vlandev_del(struct device *vlandev)
1203 return system_link_del(vlandev->ifname);
1207 system_if_get_settings(struct device *dev, struct device_settings *s)
1212 memset(&ifr, 0, sizeof(ifr));
1213 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1215 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
1216 s->mtu = ifr.ifr_mtu;
1217 s->flags |= DEV_OPT_MTU;
1220 s->mtu6 = system_update_ipv6_mtu(dev, 0);
1222 s->flags |= DEV_OPT_MTU6;
1224 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
1225 s->txqueuelen = ifr.ifr_qlen;
1226 s->flags |= DEV_OPT_TXQUEUELEN;
1229 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
1230 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
1231 s->flags |= DEV_OPT_MACADDR;
1234 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
1235 s->ipv6 = !strtoul(buf, NULL, 0);
1236 s->flags |= DEV_OPT_IPV6;
1239 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
1240 s->promisc = ifr.ifr_flags & IFF_PROMISC;
1241 s->flags |= DEV_OPT_PROMISC;
1243 s->multicast = ifr.ifr_flags & IFF_MULTICAST;
1244 s->flags |= DEV_OPT_MULTICAST;
1247 if (!system_get_rpfilter(dev, buf, sizeof(buf))) {
1248 s->rpfilter = strtoul(buf, NULL, 0);
1249 s->flags |= DEV_OPT_RPFILTER;
1252 if (!system_get_acceptlocal(dev, buf, sizeof(buf))) {
1253 s->acceptlocal = strtoul(buf, NULL, 0);
1254 s->flags |= DEV_OPT_ACCEPTLOCAL;
1257 if (!system_get_igmpversion(dev, buf, sizeof(buf))) {
1258 s->igmpversion = strtoul(buf, NULL, 0);
1259 s->flags |= DEV_OPT_IGMPVERSION;
1262 if (!system_get_mldversion(dev, buf, sizeof(buf))) {
1263 s->mldversion = strtoul(buf, NULL, 0);
1264 s->flags |= DEV_OPT_MLDVERSION;
1267 if (!system_get_neigh4reachabletime(dev, buf, sizeof(buf))) {
1268 s->neigh4reachabletime = strtoul(buf, NULL, 0);
1269 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1272 if (!system_get_neigh6reachabletime(dev, buf, sizeof(buf))) {
1273 s->neigh6reachabletime = strtoul(buf, NULL, 0);
1274 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1277 if (!system_get_neigh4gcstaletime(dev, buf, sizeof(buf))) {
1278 s->neigh4gcstaletime = strtoul(buf, NULL, 0);
1279 s->flags |= DEV_OPT_NEIGHGCSTALETIME;
1282 if (!system_get_neigh6gcstaletime(dev, buf, sizeof(buf))) {
1283 s->neigh6gcstaletime = strtoul(buf, NULL, 0);
1284 s->flags |= DEV_OPT_NEIGHGCSTALETIME;
1287 if (!system_get_dadtransmits(dev, buf, sizeof(buf))) {
1288 s->dadtransmits = strtoul(buf, NULL, 0);
1289 s->flags |= DEV_OPT_DADTRANSMITS;
1294 system_if_set_rps_xps_val(const char *path, int val)
1300 if (glob(path, 0, NULL, &gl))
1303 snprintf(val_buf, sizeof(val_buf), "%x", val);
1304 for (i = 0; i < gl.gl_pathc; i++)
1305 system_set_sysctl(gl.gl_pathv[i], val_buf);
1311 system_if_apply_rps_xps(struct device *dev, struct device_settings *s)
1313 long n_cpus = sysconf(_SC_NPROCESSORS_ONLN);
1319 val = (1 << n_cpus) - 1;
1320 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/rps_cpus", dev->ifname);
1321 system_if_set_rps_xps_val(dev_buf, s->rps ? val : 0);
1323 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/xps_cpus", dev->ifname);
1324 system_if_set_rps_xps_val(dev_buf, s->xps ? val : 0);
1328 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
1333 memset(&ifr, 0, sizeof(ifr));
1334 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1335 if (s->flags & DEV_OPT_MTU & apply_mask) {
1336 ifr.ifr_mtu = s->mtu;
1337 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
1338 s->flags &= ~DEV_OPT_MTU;
1340 if (s->flags & DEV_OPT_MTU6 & apply_mask) {
1341 system_update_ipv6_mtu(dev, s->mtu6);
1343 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
1344 ifr.ifr_qlen = s->txqueuelen;
1345 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
1346 s->flags &= ~DEV_OPT_TXQUEUELEN;
1348 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
1349 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
1350 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
1351 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
1352 s->flags &= ~DEV_OPT_MACADDR;
1354 if (s->flags & DEV_OPT_IPV6 & apply_mask)
1355 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
1356 if (s->flags & DEV_OPT_PROMISC & apply_mask) {
1357 if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
1358 !s->promisc ? IFF_PROMISC : 0) < 0)
1359 s->flags &= ~DEV_OPT_PROMISC;
1361 if (s->flags & DEV_OPT_RPFILTER & apply_mask) {
1362 snprintf(buf, sizeof(buf), "%d", s->rpfilter);
1363 system_set_rpfilter(dev, buf);
1365 if (s->flags & DEV_OPT_ACCEPTLOCAL & apply_mask)
1366 system_set_acceptlocal(dev, s->acceptlocal ? "1" : "0");
1367 if (s->flags & DEV_OPT_IGMPVERSION & apply_mask) {
1368 snprintf(buf, sizeof(buf), "%d", s->igmpversion);
1369 system_set_igmpversion(dev, buf);
1371 if (s->flags & DEV_OPT_MLDVERSION & apply_mask) {
1372 snprintf(buf, sizeof(buf), "%d", s->mldversion);
1373 system_set_mldversion(dev, buf);
1375 if (s->flags & DEV_OPT_NEIGHREACHABLETIME & apply_mask) {
1376 snprintf(buf, sizeof(buf), "%d", s->neigh4reachabletime);
1377 system_set_neigh4reachabletime(dev, buf);
1378 snprintf(buf, sizeof(buf), "%d", s->neigh6reachabletime);
1379 system_set_neigh6reachabletime(dev, buf);
1381 if (s->flags & DEV_OPT_NEIGHGCSTALETIME & apply_mask) {
1382 snprintf(buf, sizeof(buf), "%d", s->neigh4gcstaletime);
1383 system_set_neigh4gcstaletime(dev, buf);
1384 snprintf(buf, sizeof(buf), "%d", s->neigh6gcstaletime);
1385 system_set_neigh6gcstaletime(dev, buf);
1387 if (s->flags & DEV_OPT_DADTRANSMITS & apply_mask) {
1388 snprintf(buf, sizeof(buf), "%d", s->dadtransmits);
1389 system_set_dadtransmits(dev, buf);
1391 if (s->flags & DEV_OPT_MULTICAST & apply_mask) {
1392 if (system_if_flags(dev->ifname, s->multicast ? IFF_MULTICAST : 0,
1393 !s->multicast ? IFF_MULTICAST : 0) < 0)
1394 s->flags &= ~DEV_OPT_MULTICAST;
1397 system_if_apply_rps_xps(dev, s);
1400 int system_if_up(struct device *dev)
1402 system_if_get_settings(dev, &dev->orig_settings);
1403 /* Only keep orig settings based on what needs to be set */
1404 dev->orig_settings.valid_flags = dev->orig_settings.flags;
1405 dev->orig_settings.flags &= dev->settings.flags;
1406 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
1407 return system_if_flags(dev->ifname, IFF_UP, 0);
1410 int system_if_down(struct device *dev)
1412 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
1413 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
1417 struct if_check_data {
1423 #ifndef IFF_LOWER_UP
1424 #define IFF_LOWER_UP 0x10000
1427 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1429 struct nlmsghdr *nh = nlmsg_hdr(msg);
1430 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1431 struct if_check_data *chk = (struct if_check_data *)arg;
1433 if (nh->nlmsg_type != RTM_NEWLINK)
1436 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1437 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1442 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1444 struct if_check_data *chk = (struct if_check_data *)arg;
1449 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1451 struct if_check_data *chk = (struct if_check_data *)arg;
1453 device_set_present(chk->dev, false);
1454 device_set_link(chk->dev, false);
1455 chk->pending = err->error;
1460 int system_if_check(struct device *dev)
1462 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1464 struct ifinfomsg ifi = {
1465 .ifi_family = AF_UNSPEC,
1468 struct if_check_data chk = {
1474 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1478 if (nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1479 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1482 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1483 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1484 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1486 nl_send_auto_complete(sock_rtnl, msg);
1487 while (chk.pending > 0)
1488 nl_recvmsgs(sock_rtnl, cb);
1500 system_if_get_parent(struct device *dev)
1502 char buf[64], *devname;
1503 int ifindex, iflink, len;
1506 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1507 f = fopen(buf, "r");
1511 len = fread(buf, 1, sizeof(buf) - 1, f);
1518 iflink = strtoul(buf, NULL, 0);
1519 ifindex = system_if_resolve(dev);
1520 if (!iflink || iflink == ifindex)
1523 devname = if_indextoname(iflink, buf);
1527 return device_get(devname, true);
1531 read_string_file(int dir_fd, const char *file, char *buf, int len)
1537 fd = openat(dir_fd, file, O_RDONLY);
1542 len = read(fd, buf, len - 1);
1546 } else if (len > 0) {
1549 c = strchr(buf, '\n');
1562 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1567 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1569 *val = strtoull(buf, NULL, 0);
1574 /* Assume advertised flags == supported flags */
1575 static const struct {
1578 } ethtool_link_modes[] = {
1579 { ADVERTISED_10baseT_Half, "10H" },
1580 { ADVERTISED_10baseT_Full, "10F" },
1581 { ADVERTISED_100baseT_Half, "100H" },
1582 { ADVERTISED_100baseT_Full, "100F" },
1583 { ADVERTISED_1000baseT_Half, "1000H" },
1584 { ADVERTISED_1000baseT_Full, "1000F" },
1587 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1590 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1591 if (mask & ethtool_link_modes[i].mask)
1592 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1597 system_if_force_external(const char *ifname)
1602 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1603 return stat(buf, &s) == 0;
1607 system_if_dump_info(struct device *dev, struct blob_buf *b)
1609 struct ethtool_cmd ecmd;
1615 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
1616 dir_fd = open(buf, O_DIRECTORY);
1618 memset(&ecmd, 0, sizeof(ecmd));
1619 memset(&ifr, 0, sizeof(ifr));
1620 strcpy(ifr.ifr_name, dev->ifname);
1621 ifr.ifr_data = (caddr_t) &ecmd;
1622 ecmd.cmd = ETHTOOL_GSET;
1624 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1625 c = blobmsg_open_array(b, "link-advertising");
1626 system_add_link_modes(b, ecmd.advertising);
1627 blobmsg_close_array(b, c);
1629 c = blobmsg_open_array(b, "link-supported");
1630 system_add_link_modes(b, ecmd.supported);
1631 blobmsg_close_array(b, c);
1633 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1634 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1635 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1636 blobmsg_add_string_buffer(b);
1644 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1646 const char *const counters[] = {
1647 "collisions", "rx_frame_errors", "tx_compressed",
1648 "multicast", "rx_length_errors", "tx_dropped",
1649 "rx_bytes", "rx_missed_errors", "tx_errors",
1650 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1651 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1652 "rx_dropped", "tx_aborted_errors", "tx_packets",
1653 "rx_errors", "tx_bytes", "tx_window_errors",
1654 "rx_fifo_errors", "tx_carrier_errors",
1661 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1662 stats_dir = open(buf, O_DIRECTORY);
1666 for (i = 0; i < ARRAY_SIZE(counters); i++)
1667 if (read_uint64_file(stats_dir, counters[i], &val))
1668 blobmsg_add_u64(b, counters[i], val);
1674 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1676 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1677 int alen = v4 ? 4 : 16;
1678 unsigned int flags = 0;
1679 struct ifaddrmsg ifa = {
1680 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1681 .ifa_prefixlen = addr->mask,
1682 .ifa_index = dev->ifindex,
1686 if (cmd == RTM_NEWADDR)
1687 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1689 msg = nlmsg_alloc_simple(cmd, flags);
1693 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1694 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1696 if (addr->broadcast)
1697 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1698 if (addr->point_to_point)
1699 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1701 time_t now = system_get_rtime();
1702 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1704 if (addr->preferred_until) {
1705 int64_t preferred = addr->preferred_until - now;
1708 else if (preferred > UINT32_MAX)
1709 preferred = UINT32_MAX;
1711 cinfo.ifa_prefered = preferred;
1714 if (addr->valid_until) {
1715 int64_t valid = addr->valid_until - now;
1720 else if (valid > UINT32_MAX)
1723 cinfo.ifa_valid = valid;
1726 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1728 if (cmd == RTM_NEWADDR && (addr->flags & DEVADDR_OFFLINK))
1729 nla_put_u32(msg, IFA_FLAGS, IFA_F_NOPREFIXROUTE);
1732 return system_rtnl_call(msg);
1735 int system_add_address(struct device *dev, struct device_addr *addr)
1737 return system_addr(dev, addr, RTM_NEWADDR);
1740 int system_del_address(struct device *dev, struct device_addr *addr)
1742 return system_addr(dev, addr, RTM_DELADDR);
1745 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1747 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1749 unsigned int flags = 0;
1752 have_gw = !!route->nexthop.in.s_addr;
1754 have_gw = route->nexthop.in6.s6_addr32[0] ||
1755 route->nexthop.in6.s6_addr32[1] ||
1756 route->nexthop.in6.s6_addr32[2] ||
1757 route->nexthop.in6.s6_addr32[3];
1759 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1760 ? route->table : RT_TABLE_MAIN;
1762 struct rtmsg rtm = {
1763 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1764 .rtm_dst_len = route->mask,
1765 .rtm_src_len = route->sourcemask,
1766 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1767 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
1768 .rtm_scope = RT_SCOPE_NOWHERE,
1769 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1770 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1774 if (cmd == RTM_NEWROUTE) {
1775 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1777 if (!dev) { // Add null-route
1778 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1779 rtm.rtm_type = RTN_UNREACHABLE;
1782 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1785 if (route->flags & DEVROUTE_TYPE) {
1786 rtm.rtm_type = route->type;
1787 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
1788 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
1789 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
1790 rtm.rtm_table = RT_TABLE_LOCAL;
1793 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT) {
1794 rtm.rtm_scope = RT_SCOPE_HOST;
1795 } else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
1796 rtm.rtm_type == RTN_ANYCAST) {
1797 rtm.rtm_scope = RT_SCOPE_LINK;
1798 } else if (rtm.rtm_type == RTN_BLACKHOLE || rtm.rtm_type == RTN_UNREACHABLE ||
1799 rtm.rtm_type == RTN_PROHIBIT || rtm.rtm_type == RTN_FAILED_POLICY) {
1800 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1805 msg = nlmsg_alloc_simple(cmd, flags);
1809 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1812 nla_put(msg, RTA_DST, alen, &route->addr);
1814 if (route->sourcemask) {
1815 if (rtm.rtm_family == AF_INET)
1816 nla_put(msg, RTA_PREFSRC, alen, &route->source);
1818 nla_put(msg, RTA_SRC, alen, &route->source);
1821 if (route->metric > 0)
1822 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1825 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1828 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1831 nla_put_u32(msg, RTA_TABLE, table);
1833 if (route->flags & DEVROUTE_MTU) {
1834 struct nlattr *metrics;
1836 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1837 goto nla_put_failure;
1839 nla_put_u32(msg, RTAX_MTU, route->mtu);
1841 nla_nest_end(msg, metrics);
1844 return system_rtnl_call(msg);
1851 int system_add_route(struct device *dev, struct device_route *route)
1853 return system_rt(dev, route, RTM_NEWROUTE);
1856 int system_del_route(struct device *dev, struct device_route *route)
1858 return system_rt(dev, route, RTM_DELROUTE);
1861 int system_flush_routes(void)
1863 const char *names[] = {
1864 "/proc/sys/net/ipv4/route/flush",
1865 "/proc/sys/net/ipv6/route/flush"
1869 for (i = 0; i < ARRAY_SIZE(names); i++) {
1870 fd = open(names[i], O_WRONLY);
1874 if (write(fd, "-1", 2)) {}
1880 bool system_resolve_rt_type(const char *type, unsigned int *id)
1882 return system_rtn_aton(type, id);
1885 bool system_resolve_rt_table(const char *name, unsigned int *id)
1889 unsigned int n, table = RT_TABLE_UNSPEC;
1891 /* first try to parse table as number */
1892 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1895 /* handle well known aliases */
1896 else if (!strcmp(name, "default"))
1897 table = RT_TABLE_DEFAULT;
1898 else if (!strcmp(name, "main"))
1899 table = RT_TABLE_MAIN;
1900 else if (!strcmp(name, "local"))
1901 table = RT_TABLE_LOCAL;
1903 /* try to look up name in /etc/iproute2/rt_tables */
1904 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1906 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1908 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1911 n = strtoul(e, NULL, 10);
1912 e = strtok(NULL, " \t\n");
1914 if (e && !strcmp(e, name))
1924 if (table == RT_TABLE_UNSPEC)
1931 bool system_is_default_rt_table(unsigned int id)
1933 return (id == RT_TABLE_MAIN);
1936 bool system_resolve_rpfilter(const char *filter, unsigned int *id)
1941 if (!strcmp(filter, "strict"))
1943 else if (!strcmp(filter, "loose"))
1946 n = strtoul(filter, &e, 0);
1947 if (*e || e == filter || n > 2)
1955 static int system_iprule(struct iprule *rule, int cmd)
1957 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1960 struct rtmsg rtm = {
1961 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1962 .rtm_protocol = RTPROT_STATIC,
1963 .rtm_scope = RT_SCOPE_UNIVERSE,
1964 .rtm_table = RT_TABLE_UNSPEC,
1965 .rtm_type = RTN_UNSPEC,
1969 if (cmd == RTM_NEWRULE)
1970 rtm.rtm_type = RTN_UNICAST;
1973 rtm.rtm_flags |= FIB_RULE_INVERT;
1975 if (rule->flags & IPRULE_SRC)
1976 rtm.rtm_src_len = rule->src_mask;
1978 if (rule->flags & IPRULE_DEST)
1979 rtm.rtm_dst_len = rule->dest_mask;
1981 if (rule->flags & IPRULE_TOS)
1982 rtm.rtm_tos = rule->tos;
1984 if (rule->flags & IPRULE_LOOKUP) {
1985 if (rule->lookup < 256)
1986 rtm.rtm_table = rule->lookup;
1989 if (rule->flags & IPRULE_ACTION)
1990 rtm.rtm_type = rule->action;
1991 else if (rule->flags & IPRULE_GOTO)
1992 rtm.rtm_type = FR_ACT_GOTO;
1993 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1994 rtm.rtm_type = FR_ACT_NOP;
1996 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
2001 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
2003 if (rule->flags & IPRULE_IN)
2004 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
2006 if (rule->flags & IPRULE_OUT)
2007 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
2009 if (rule->flags & IPRULE_SRC)
2010 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
2012 if (rule->flags & IPRULE_DEST)
2013 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
2015 if (rule->flags & IPRULE_PRIORITY)
2016 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
2017 else if (cmd == RTM_NEWRULE)
2018 nla_put_u32(msg, FRA_PRIORITY, rule->order);
2020 if (rule->flags & IPRULE_FWMARK)
2021 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
2023 if (rule->flags & IPRULE_FWMASK)
2024 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
2026 if (rule->flags & IPRULE_LOOKUP) {
2027 if (rule->lookup >= 256)
2028 nla_put_u32(msg, FRA_TABLE, rule->lookup);
2031 if (rule->flags & IPRULE_GOTO)
2032 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
2034 return system_rtnl_call(msg);
2037 int system_add_iprule(struct iprule *rule)
2039 return system_iprule(rule, RTM_NEWRULE);
2042 int system_del_iprule(struct iprule *rule)
2044 return system_iprule(rule, RTM_DELRULE);
2047 int system_flush_iprules(void)
2052 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
2053 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
2055 memset(&rule, 0, sizeof(rule));
2058 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2061 rule.lookup = RT_TABLE_LOCAL;
2062 rv |= system_iprule(&rule, RTM_NEWRULE);
2064 rule.priority = 32766;
2065 rule.lookup = RT_TABLE_MAIN;
2066 rv |= system_iprule(&rule, RTM_NEWRULE);
2068 rule.priority = 32767;
2069 rule.lookup = RT_TABLE_DEFAULT;
2070 rv |= system_iprule(&rule, RTM_NEWRULE);
2073 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2076 rule.lookup = RT_TABLE_LOCAL;
2077 rv |= system_iprule(&rule, RTM_NEWRULE);
2079 rule.priority = 32766;
2080 rule.lookup = RT_TABLE_MAIN;
2081 rv |= system_iprule(&rule, RTM_NEWRULE);
2086 bool system_resolve_iprule_action(const char *action, unsigned int *id)
2088 return system_rtn_aton(action, id);
2091 time_t system_get_rtime(void)
2096 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
2099 if (gettimeofday(&tv, NULL) == 0)
2106 #define IP_DF 0x4000
2109 static int tunnel_ioctl(const char *name, int cmd, void *p)
2113 memset(&ifr, 0, sizeof(ifr));
2114 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
2115 ifr.ifr_ifru.ifru_data = p;
2116 return ioctl(sock_ioctl, cmd, &ifr);
2119 #ifdef IFLA_IPTUN_MAX
2120 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
2121 static int system_add_gre_tunnel(const char *name, const char *kind,
2122 const unsigned int link, struct blob_attr **tb, bool v6)
2125 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2126 struct blob_attr *cur;
2127 uint32_t ikey = 0, okey = 0, flags = 0, flowinfo = 0;
2128 uint16_t iflags = 0, oflags = 0;
2130 int ret = 0, ttl = 0;
2132 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2136 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2137 nla_put_string(nlm, IFLA_IFNAME, name);
2139 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2145 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2146 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2153 nla_put_u32(nlm, IFLA_GRE_LINK, link);
2155 if ((cur = tb[TUNNEL_ATTR_TTL]))
2156 ttl = blobmsg_get_u32(cur);
2158 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2159 char *str = blobmsg_get_string(cur);
2160 if (strcmp(str, "inherit")) {
2163 if (!system_tos_aton(str, &uval)) {
2169 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
2174 flags |= IP6_TNL_F_USE_ORIG_TCLASS;
2180 if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) {
2181 uint8_t icsum, ocsum, iseqno, oseqno;
2182 if (sscanf(blobmsg_get_string(cur), "%u,%u,%hhu,%hhu,%hhu,%hhu",
2183 &ikey, &okey, &icsum, &ocsum, &iseqno, &oseqno) < 6) {
2208 struct in6_addr in6buf;
2209 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2210 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2214 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
2217 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2218 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2222 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
2224 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, 4);
2227 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
2230 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags);
2235 struct in_addr inbuf;
2238 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2239 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2243 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
2246 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2247 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2251 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
2253 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
2255 okey = inbuf.s_addr;
2260 ikey = inbuf.s_addr;
2266 if ((cur = tb[TUNNEL_ATTR_DF]))
2267 set_df = blobmsg_get_bool(cur);
2270 /* ttl != 0 and nopmtudisc are incompatible */
2278 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
2280 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
2284 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
2287 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
2290 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
2293 nla_put_u32(nlm, IFLA_GRE_OKEY, okey);
2296 nla_put_u32(nlm, IFLA_GRE_IKEY, ikey);
2298 nla_nest_end(nlm, infodata);
2299 nla_nest_end(nlm, linkinfo);
2301 return system_rtnl_call(nlm);
2310 static int system_add_vti_tunnel(const char *name, const char *kind,
2311 const unsigned int link, struct blob_attr **tb, bool v6)
2314 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2315 struct blob_attr *cur;
2316 uint32_t ikey = 0, okey = 0;
2319 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2323 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2324 nla_put_string(nlm, IFLA_IFNAME, name);
2326 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2332 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2333 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2340 nla_put_u32(nlm, IFLA_VTI_LINK, link);
2342 if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) {
2343 if (sscanf(blobmsg_get_string(cur), "%u,%u",
2344 &ikey, &okey) < 2) {
2351 struct in6_addr in6buf;
2352 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2353 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2357 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(in6buf), &in6buf);
2360 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2361 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2365 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(in6buf), &in6buf);
2369 struct in_addr inbuf;
2371 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2372 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2376 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(inbuf), &inbuf);
2379 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2380 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2384 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(inbuf), &inbuf);
2390 nla_put_u32(nlm, IFLA_VTI_OKEY, htonl(okey));
2393 nla_put_u32(nlm, IFLA_VTI_IKEY, htonl(ikey));
2395 nla_nest_end(nlm, infodata);
2396 nla_nest_end(nlm, linkinfo);
2398 return system_rtnl_call(nlm);
2406 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
2408 struct blob_attr *cur;
2410 struct ip_tunnel_parm p = {
2419 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
2420 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
2423 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
2424 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
2427 if ((cur = tb[TUNNEL_ATTR_DF]))
2428 set_df = blobmsg_get_bool(cur);
2430 if ((cur = tb[TUNNEL_ATTR_TTL]))
2431 p.iph.ttl = blobmsg_get_u32(cur);
2433 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2434 char *str = blobmsg_get_string(cur);
2435 if (strcmp(str, "inherit")) {
2438 if (!system_tos_aton(str, &uval))
2446 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
2447 /* ttl !=0 and nopmtudisc are incompatible */
2448 if (p.iph.ttl && p.iph.frag_off == 0)
2451 strncpy(p.name, name, sizeof(p.name));
2453 switch (p.iph.protocol) {
2455 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
2457 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
2464 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
2466 struct blob_attr *cur;
2469 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2471 str = blobmsg_data(cur);
2473 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
2474 !strcmp(str, "greip6") || !strcmp(str, "gretapip6") ||
2475 !strcmp(str, "vtiip") || !strcmp(str, "vtiip6"))
2476 return system_link_del(name);
2478 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
2481 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
2483 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2485 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2486 blob_data(attr), blob_len(attr));
2488 return __system_del_ip_tunnel(name, tb);
2491 int system_update_ipv6_mtu(struct device *dev, int mtu)
2497 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
2500 fd = open(buf, O_RDWR);
2505 ssize_t len = read(fd, buf, sizeof(buf) - 1);
2512 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) > 0)
2521 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
2523 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2524 struct blob_attr *cur;
2527 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2528 blob_data(attr), blob_len(attr));
2530 __system_del_ip_tunnel(name, tb);
2532 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2534 str = blobmsg_data(cur);
2536 unsigned int ttl = 0;
2537 if ((cur = tb[TUNNEL_ATTR_TTL])) {
2538 ttl = blobmsg_get_u32(cur);
2543 unsigned int link = 0;
2544 if ((cur = tb[TUNNEL_ATTR_LINK])) {
2545 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
2549 if (iface->l3_dev.dev)
2550 link = iface->l3_dev.dev->ifindex;
2553 if (!strcmp(str, "sit")) {
2554 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
2558 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
2560 struct ip_tunnel_6rd p6;
2562 memset(&p6, 0, sizeof(p6));
2564 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
2565 &p6.prefix, &mask) || mask > 128)
2567 p6.prefixlen = mask;
2569 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
2570 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
2571 &p6.relay_prefix, &mask) || mask > 32)
2573 p6.relay_prefixlen = mask;
2576 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
2577 __system_del_ip_tunnel(name, tb);
2582 #ifdef IFLA_IPTUN_MAX
2583 } else if (!strcmp(str, "ipip6")) {
2584 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2585 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2586 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2592 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2593 nla_put_string(nlm, IFLA_IFNAME, name);
2596 nla_put_u32(nlm, IFLA_LINK, link);
2598 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2603 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2604 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2611 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2613 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2614 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2615 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
2617 struct in6_addr in6buf;
2618 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2619 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2623 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2626 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2627 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2631 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2634 #ifdef IFLA_IPTUN_FMR_MAX
2635 if ((cur = tb[TUNNEL_ATTR_FMRS])) {
2636 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2638 struct blob_attr *fmr;
2639 unsigned rem, fmrcnt = 0;
2640 blobmsg_for_each_attr(fmr, cur, rem) {
2641 if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
2644 unsigned ip4len, ip6len, ealen, offset = 6;
2648 if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
2649 ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) {
2654 struct in6_addr ip6prefix;
2655 struct in_addr ip4prefix;
2656 if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
2657 inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) {
2662 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2664 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2665 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2666 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2667 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2668 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2669 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2671 nla_nest_end(nlm, rule);
2674 nla_nest_end(nlm, fmrs);
2678 nla_nest_end(nlm, infodata);
2679 nla_nest_end(nlm, linkinfo);
2681 return system_rtnl_call(nlm);
2685 } else if (!strcmp(str, "greip")) {
2686 return system_add_gre_tunnel(name, "gre", link, tb, false);
2687 } else if (!strcmp(str, "gretapip")) {
2688 return system_add_gre_tunnel(name, "gretap", link, tb, false);
2689 } else if (!strcmp(str, "greip6")) {
2690 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
2691 } else if (!strcmp(str, "gretapip6")) {
2692 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
2694 } else if (!strcmp(str, "vtiip")) {
2695 return system_add_vti_tunnel(name, "vti", link, tb, false);
2696 } else if (!strcmp(str, "vtiip6")) {
2697 return system_add_vti_tunnel(name, "vti6", link, tb, true);
2700 } else if (!strcmp(str, "ipip")) {
2701 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);