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)
61 #include <netlink/msg.h>
62 #include <netlink/attr.h>
63 #include <netlink/socket.h>
64 #include <libubox/uloop.h>
71 struct uloop_fd uloop;
76 static int sock_ioctl = -1;
77 static struct nl_sock *sock_rtnl = NULL;
79 static int cb_rtnl_event(struct nl_msg *msg, void *arg);
80 static void handle_hotplug_event(struct uloop_fd *u, unsigned int events);
82 static char dev_buf[256];
85 handler_nl_event(struct uloop_fd *u, unsigned int events)
87 struct event_socket *ev = container_of(u, struct event_socket, uloop);
89 socklen_t errlen = sizeof(err);
92 nl_recvmsgs_default(ev->sock);
96 if (getsockopt(u->fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen))
101 // Increase rx buffer size on netlink socket
103 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
106 // Request full dump since some info got dropped
107 struct rtgenmsg msg = { .rtgen_family = AF_UNSPEC };
108 nl_send_simple(ev->sock, RTM_GETLINK, NLM_F_DUMP, &msg, sizeof(msg));
118 uloop_fd_delete(&ev->uloop);
122 static struct nl_sock *
123 create_socket(int protocol, int groups)
125 struct nl_sock *sock;
127 sock = nl_socket_alloc();
132 nl_join_groups(sock, groups);
134 if (nl_connect(sock, protocol))
141 create_raw_event_socket(struct event_socket *ev, int protocol, int groups,
142 uloop_fd_handler cb, int flags)
144 ev->sock = create_socket(protocol, groups);
148 ev->uloop.fd = nl_socket_get_fd(ev->sock);
150 if (uloop_fd_add(&ev->uloop, ULOOP_READ|flags))
157 create_event_socket(struct event_socket *ev, int protocol,
158 int (*cb)(struct nl_msg *msg, void *arg))
160 if (!create_raw_event_socket(ev, protocol, 0, handler_nl_event, ULOOP_ERROR_CB))
163 // Install the valid custom callback handler
164 nl_socket_modify_cb(ev->sock, NL_CB_VALID, NL_CB_CUSTOM, cb, NULL);
166 // Disable sequence number checking on event sockets
167 nl_socket_disable_seq_check(ev->sock);
169 // Increase rx buffer size to 65K on event sockets
171 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
178 system_rtn_aton(const char *src, unsigned int *dst)
183 if (!strcmp(src, "local"))
185 else if (!strcmp(src, "nat"))
187 else if (!strcmp(src, "broadcast"))
189 else if (!strcmp(src, "anycast"))
191 else if (!strcmp(src, "multicast"))
193 else if (!strcmp(src, "prohibit"))
195 else if (!strcmp(src, "unreachable"))
197 else if (!strcmp(src, "blackhole"))
199 else if (!strcmp(src, "xresolve"))
201 else if (!strcmp(src, "unicast"))
203 else if (!strcmp(src, "throw"))
205 else if (!strcmp(src, "failed_policy"))
206 n = RTN_FAILED_POLICY;
208 n = strtoul(src, &e, 0);
209 if (!e || *e || e == src || n > 255)
218 system_tos_aton(const char *src, unsigned *dst)
222 *dst = strtoul(src, &e, 16);
223 if (e == src || *e || *dst > 255)
229 int system_init(void)
231 static struct event_socket rtnl_event;
232 static struct event_socket hotplug_event;
234 sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0);
235 system_fd_set_cloexec(sock_ioctl);
237 // Prepare socket for routing / address control
238 sock_rtnl = create_socket(NETLINK_ROUTE, 0);
242 if (!create_event_socket(&rtnl_event, NETLINK_ROUTE, cb_rtnl_event))
245 if (!create_raw_event_socket(&hotplug_event, NETLINK_KOBJECT_UEVENT, 1,
246 handle_hotplug_event, 0))
249 // Receive network link events form kernel
250 nl_socket_add_membership(rtnl_event.sock, RTNLGRP_LINK);
255 static void system_set_sysctl(const char *path, const char *val)
259 fd = open(path, O_WRONLY);
263 if (write(fd, val, strlen(val))) {}
267 static void system_set_dev_sysctl(const char *path, const char *device, const char *val)
269 snprintf(dev_buf, sizeof(dev_buf), path, device);
270 system_set_sysctl(dev_buf, val);
273 static void system_set_disable_ipv6(struct device *dev, const char *val)
275 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val);
278 static void system_set_rpfilter(struct device *dev, const char *val)
280 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter", dev->ifname, val);
283 static void system_set_acceptlocal(struct device *dev, const char *val)
285 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local", dev->ifname, val);
288 static void system_set_igmpversion(struct device *dev, const char *val)
290 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version", dev->ifname, val);
293 static void system_set_mldversion(struct device *dev, const char *val)
295 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version", dev->ifname, val);
298 static void system_set_neigh4reachabletime(struct device *dev, const char *val)
300 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms", dev->ifname, val);
303 static void system_set_neigh6reachabletime(struct device *dev, const char *val)
305 system_set_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms", dev->ifname, val);
308 static void system_set_neigh4gcstaletime(struct device *dev, const char *val)
310 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/gc_stale_time", dev->ifname, val);
313 static void system_set_neigh6gcstaletime(struct device *dev, const char *val)
315 system_set_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/gc_stale_time", dev->ifname, val);
318 static void system_set_dadtransmits(struct device *dev, const char *val)
320 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits", dev->ifname, val);
323 static void system_bridge_set_multicast_to_unicast(struct device *dev, const char *val)
325 system_set_dev_sysctl("/sys/class/net/%s/brport/multicast_to_unicast", dev->ifname, val);
328 static void system_bridge_set_multicast_fast_leave(struct device *dev, const char *val)
330 system_set_dev_sysctl("/sys/class/net/%s/brport/multicast_fast_leave", dev->ifname, val);
333 static void system_bridge_set_hairpin_mode(struct device *dev, const char *val)
335 system_set_dev_sysctl("/sys/class/net/%s/brport/hairpin_mode", dev->ifname, val);
338 static void system_bridge_set_multicast_router(struct device *dev, const char *val, bool bridge)
340 system_set_dev_sysctl(bridge ? "/sys/class/net/%s/bridge/multicast_router" :
341 "/sys/class/net/%s/brport/multicast_router",
345 static void system_bridge_set_robustness(struct device *dev, const char *val)
347 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_startup_query_count",
349 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_last_member_count",
353 static void system_bridge_set_query_interval(struct device *dev, const char *val)
355 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_query_interval",
359 static void system_bridge_set_query_response_interval(struct device *dev, const char *val)
361 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_query_response_interval",
365 static void system_bridge_set_last_member_interval(struct device *dev, const char *val)
367 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_last_member_interval",
371 static void system_bridge_set_membership_interval(struct device *dev, const char *val)
373 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_membership_interval",
377 static void system_bridge_set_other_querier_timeout(struct device *dev, const char *val)
379 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier_interval",
383 static void system_bridge_set_startup_query_interval(struct device *dev, const char *val)
385 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_startup_query_interval",
389 static void system_bridge_set_learning(struct device *dev, const char *val)
391 system_set_dev_sysctl("/sys/class/net/%s/brport/learning", dev->ifname, val);
394 static void system_bridge_set_unicast_flood(struct device *dev, const char *val)
396 system_set_dev_sysctl("/sys/class/net/%s/brport/unicast_flood", dev->ifname, val);
399 static void system_set_sendredirects(struct device *dev, const char *val)
401 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/send_redirects", dev->ifname, val);
404 static int system_get_sysctl(const char *path, char *buf, const size_t buf_sz)
406 int fd = -1, ret = -1;
408 fd = open(path, O_RDONLY);
412 ssize_t len = read(fd, buf, buf_sz - 1);
426 system_get_dev_sysctl(const char *path, const char *device, char *buf, const size_t buf_sz)
428 snprintf(dev_buf, sizeof(dev_buf), path, device);
429 return system_get_sysctl(dev_buf, buf, buf_sz);
432 static int system_get_disable_ipv6(struct device *dev, char *buf, const size_t buf_sz)
434 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6",
435 dev->ifname, buf, buf_sz);
438 static int system_get_rpfilter(struct device *dev, char *buf, const size_t buf_sz)
440 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter",
441 dev->ifname, buf, buf_sz);
444 static int system_get_acceptlocal(struct device *dev, char *buf, const size_t buf_sz)
446 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local",
447 dev->ifname, buf, buf_sz);
450 static int system_get_igmpversion(struct device *dev, char *buf, const size_t buf_sz)
452 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version",
453 dev->ifname, buf, buf_sz);
456 static int system_get_mldversion(struct device *dev, char *buf, const size_t buf_sz)
458 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version",
459 dev->ifname, buf, buf_sz);
462 static int system_get_neigh4reachabletime(struct device *dev, char *buf, const size_t buf_sz)
464 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms",
465 dev->ifname, buf, buf_sz);
468 static int system_get_neigh6reachabletime(struct device *dev, char *buf, const size_t buf_sz)
470 return system_get_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms",
471 dev->ifname, buf, buf_sz);
474 static int system_get_neigh4gcstaletime(struct device *dev, char *buf, const size_t buf_sz)
476 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/gc_stale_time",
477 dev->ifname, buf, buf_sz);
480 static int system_get_neigh6gcstaletime(struct device *dev, char *buf, const size_t buf_sz)
482 return system_get_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/gc_stale_time",
483 dev->ifname, buf, buf_sz);
486 static int system_get_dadtransmits(struct device *dev, char *buf, const size_t buf_sz)
488 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits",
489 dev->ifname, buf, buf_sz);
492 static int system_get_sendredirects(struct device *dev, char *buf, const size_t buf_sz)
494 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/send_redirects",
495 dev->ifname, buf, buf_sz);
498 // Evaluate netlink messages
499 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
501 struct nlmsghdr *nh = nlmsg_hdr(msg);
502 struct nlattr *nla[__IFLA_MAX];
506 if (nh->nlmsg_type != RTM_NEWLINK)
509 nlmsg_parse(nh, sizeof(struct ifinfomsg), nla, __IFLA_MAX - 1, NULL);
510 if (!nla[IFLA_IFNAME])
513 struct device *dev = device_find(nla_data(nla[IFLA_IFNAME]));
517 if (!system_get_dev_sysctl("/sys/class/net/%s/carrier", dev->ifname, buf, sizeof(buf)))
518 link_state = strtoul(buf, NULL, 0);
520 device_set_link(dev, link_state ? true : false);
527 handle_hotplug_msg(char *data, int size)
529 const char *subsystem = NULL, *interface = NULL;
530 char *cur, *end, *sep;
535 if (!strncmp(data, "add@", 4))
537 else if (!strncmp(data, "remove@", 7))
542 skip = strlen(data) + 1;
545 for (cur = data + skip; cur < end; cur += skip) {
546 skip = strlen(cur) + 1;
548 sep = strchr(cur, '=');
553 if (!strcmp(cur, "INTERFACE"))
555 else if (!strcmp(cur, "SUBSYSTEM")) {
557 if (strcmp(subsystem, "net") != 0)
560 if (subsystem && interface)
566 dev = device_find(interface);
570 if (dev->type != &simple_device_type)
573 if (add && system_if_force_external(dev->ifname))
576 device_set_present(dev, add);
580 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
582 struct event_socket *ev = container_of(u, struct event_socket, uloop);
583 struct sockaddr_nl nla;
584 unsigned char *buf = NULL;
587 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
589 handle_hotplug_msg((char *) buf, size);
595 static int system_rtnl_call(struct nl_msg *msg)
599 ret = nl_send_auto_complete(sock_rtnl, msg);
605 return nl_wait_for_ack(sock_rtnl);
608 int system_bridge_delbr(struct device *bridge)
610 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
613 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
617 memset(&ifr, 0, sizeof(ifr));
619 ifr.ifr_ifindex = dev->ifindex;
622 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
623 return ioctl(sock_ioctl, cmd, &ifr);
626 static bool system_is_bridge(const char *name, char *buf, int buflen)
630 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
631 if (stat(buf, &st) < 0)
637 static char *system_get_bridge(const char *name, char *buf, int buflen)
643 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
644 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
648 len = readlink(gl.gl_pathv[0], buf, buflen);
656 path = strrchr(buf, '/');
664 system_bridge_set_wireless(struct device *bridge, struct device *dev)
666 bool mcast_to_ucast = dev->wireless_ap;
669 if (bridge->settings.flags & DEV_OPT_MULTICAST_TO_UNICAST &&
670 !bridge->settings.multicast_to_unicast)
671 mcast_to_ucast = false;
673 if (!mcast_to_ucast || dev->wireless_isolate)
676 system_bridge_set_multicast_to_unicast(dev, mcast_to_ucast ? "1" : "0");
677 system_bridge_set_hairpin_mode(dev, hairpin ? "1" : "0");
680 int system_bridge_addif(struct device *bridge, struct device *dev)
686 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
687 if (!oldbr || strcmp(oldbr, bridge->ifname) != 0)
688 ret = system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
691 system_bridge_set_wireless(bridge, dev);
693 if (dev->settings.flags & DEV_OPT_MULTICAST_ROUTER) {
694 snprintf(buf, sizeof(buf), "%i", dev->settings.multicast_router);
695 system_bridge_set_multicast_router(dev, buf, false);
698 if (dev->settings.flags & DEV_OPT_MULTICAST_FAST_LEAVE &&
699 dev->settings.multicast_fast_leave)
700 system_bridge_set_multicast_fast_leave(dev, "1");
702 if (dev->settings.flags & DEV_OPT_LEARNING &&
703 !dev->settings.learning)
704 system_bridge_set_learning(dev, "0");
706 if (dev->settings.flags & DEV_OPT_UNICAST_FLOOD &&
707 !dev->settings.unicast_flood)
708 system_bridge_set_unicast_flood(dev, "0");
713 int system_bridge_delif(struct device *bridge, struct device *dev)
715 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
718 int system_if_resolve(struct device *dev)
721 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
722 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
723 return ifr.ifr_ifindex;
728 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
732 memset(&ifr, 0, sizeof(ifr));
733 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
734 ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
735 ifr.ifr_flags |= add;
736 ifr.ifr_flags &= ~rem;
737 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
749 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
751 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
753 return ifa->ifa_index == ifindex;
756 static bool check_route(struct nlmsghdr *hdr, int ifindex)
758 struct rtmsg *r = NLMSG_DATA(hdr);
759 struct nlattr *tb[__RTA_MAX];
761 if (r->rtm_protocol == RTPROT_KERNEL &&
762 r->rtm_family == AF_INET6)
765 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
769 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
772 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
777 static int cb_clear_event(struct nl_msg *msg, void *arg)
779 struct clear_data *clr = arg;
780 struct nlmsghdr *hdr = nlmsg_hdr(msg);
781 bool (*cb)(struct nlmsghdr *, int ifindex);
787 if (hdr->nlmsg_type != RTM_NEWADDR)
794 if (hdr->nlmsg_type != RTM_NEWROUTE)
801 if (hdr->nlmsg_type != RTM_NEWRULE)
810 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
813 if (type == RTM_DELRULE)
814 D(SYSTEM, "Remove a rule\n");
816 D(SYSTEM, "Remove %s from device %s\n",
817 type == RTM_DELADDR ? "an address" : "a route",
819 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
820 hdr = nlmsg_hdr(clr->msg);
821 hdr->nlmsg_type = type;
822 hdr->nlmsg_flags = NLM_F_REQUEST;
824 nl_socket_disable_auto_ack(sock_rtnl);
825 nl_send_auto_complete(sock_rtnl, clr->msg);
826 nl_socket_enable_auto_ack(sock_rtnl);
832 cb_finish_event(struct nl_msg *msg, void *arg)
840 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
843 *pending = err->error;
848 system_if_clear_entries(struct device *dev, int type, int af)
850 struct clear_data clr;
851 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
854 .rtm_flags = RTM_F_CLONED,
856 int flags = NLM_F_DUMP;
865 clr.size = sizeof(struct rtgenmsg);
868 clr.size = sizeof(struct rtmsg);
877 clr.msg = nlmsg_alloc_simple(type, flags);
881 nlmsg_append(clr.msg, &rtm, clr.size, 0);
882 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
883 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
884 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
886 nl_send_auto_complete(sock_rtnl, clr.msg);
888 nl_recvmsgs(sock_rtnl, cb);
896 * Clear bridge (membership) state and bring down device
898 void system_if_clear_state(struct device *dev)
900 static char buf[256];
903 device_set_ifindex(dev, system_if_resolve(dev));
904 if (dev->external || !dev->ifindex)
907 system_if_flags(dev->ifname, 0, IFF_UP);
909 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
910 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
911 system_bridge_delbr(dev);
915 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
917 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
918 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
921 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
922 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
923 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
924 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
925 system_set_disable_ipv6(dev, "0");
928 static inline unsigned long
929 sec_to_jiffies(int val)
931 return (unsigned long) val * 100;
934 static void system_bridge_conf_multicast_deps(struct device *bridge,
935 struct bridge_config *cfg,
941 if (cfg->flags & BRIDGE_OPT_ROBUSTNESS ||
942 cfg->flags & BRIDGE_OPT_QUERY_INTERVAL ||
943 cfg->flags & BRIDGE_OPT_QUERY_RESPONSE_INTERVAL) {
944 val = cfg->robustness * cfg->query_interval +
945 cfg->query_response_interval;
947 snprintf(buf, buf_len, "%i", val);
948 system_bridge_set_membership_interval(bridge, buf);
950 val = cfg->robustness * cfg->query_interval +
951 cfg->query_response_interval / 2;
953 snprintf(buf, buf_len, "%i", val);
954 system_bridge_set_other_querier_timeout(bridge, buf);
957 if (cfg->flags & BRIDGE_OPT_QUERY_INTERVAL) {
958 val = cfg->query_interval / 4;
960 snprintf(buf, buf_len, "%i", val);
961 system_bridge_set_startup_query_interval(bridge, buf);
965 static void system_bridge_conf_multicast(struct device *bridge,
966 struct bridge_config *cfg,
970 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
971 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
973 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier",
974 bridge->ifname, cfg->multicast_querier ? "1" : "0");
976 snprintf(buf, buf_len, "%i", cfg->hash_max);
977 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/hash_max",
978 bridge->ifname, buf);
980 if (bridge->settings.flags & DEV_OPT_MULTICAST_ROUTER) {
981 snprintf(buf, buf_len, "%i", bridge->settings.multicast_router);
982 system_bridge_set_multicast_router(bridge, buf, true);
985 if (cfg->flags & BRIDGE_OPT_ROBUSTNESS) {
986 snprintf(buf, buf_len, "%i", cfg->robustness);
987 system_bridge_set_robustness(bridge, buf);
990 if (cfg->flags & BRIDGE_OPT_QUERY_INTERVAL) {
991 snprintf(buf, buf_len, "%i", cfg->query_interval);
992 system_bridge_set_query_interval(bridge, buf);
995 if (cfg->flags & BRIDGE_OPT_QUERY_RESPONSE_INTERVAL) {
996 snprintf(buf, buf_len, "%i", cfg->query_response_interval);
997 system_bridge_set_query_response_interval(bridge, buf);
1000 if (cfg->flags & BRIDGE_OPT_LAST_MEMBER_INTERVAL) {
1001 snprintf(buf, buf_len, "%i", cfg->last_member_interval);
1002 system_bridge_set_last_member_interval(bridge, buf);
1005 system_bridge_conf_multicast_deps(bridge, cfg, buf, buf_len);
1008 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
1011 unsigned long args[4] = {};
1013 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
1016 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
1017 args[1] = !!cfg->stp;
1018 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1020 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
1021 args[1] = sec_to_jiffies(cfg->forward_delay);
1022 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1024 system_bridge_conf_multicast(bridge, cfg, buf, sizeof(buf));
1026 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
1027 args[1] = cfg->priority;
1028 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1030 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
1031 args[0] = BRCTL_SET_AGEING_TIME;
1032 args[1] = sec_to_jiffies(cfg->ageing_time);
1033 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1036 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
1037 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
1038 args[1] = sec_to_jiffies(cfg->hello_time);
1039 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1042 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
1043 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
1044 args[1] = sec_to_jiffies(cfg->max_age);
1045 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1051 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
1054 struct nlattr *linkinfo, *data;
1055 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
1057 static const struct {
1059 enum macvlan_mode val;
1061 { "private", MACVLAN_MODE_PRIVATE },
1062 { "vepa", MACVLAN_MODE_VEPA },
1063 { "bridge", MACVLAN_MODE_BRIDGE },
1064 { "passthru", MACVLAN_MODE_PASSTHRU },
1067 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1072 nlmsg_append(msg, &iim, sizeof(iim), 0);
1074 if (cfg->flags & MACVLAN_OPT_MACADDR)
1075 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
1076 nla_put_string(msg, IFLA_IFNAME, macvlan->ifname);
1077 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
1079 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1080 goto nla_put_failure;
1082 nla_put_string(msg, IFLA_INFO_KIND, "macvlan");
1084 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1085 goto nla_put_failure;
1088 for (i = 0; i < ARRAY_SIZE(modes); i++) {
1089 if (strcmp(cfg->mode, modes[i].name) != 0)
1092 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
1097 nla_nest_end(msg, data);
1098 nla_nest_end(msg, linkinfo);
1100 rv = system_rtnl_call(msg);
1102 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
1111 static int system_link_del(const char *ifname)
1114 struct ifinfomsg iim = {
1115 .ifi_family = AF_UNSPEC,
1119 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
1124 nlmsg_append(msg, &iim, sizeof(iim), 0);
1125 nla_put_string(msg, IFLA_IFNAME, ifname);
1126 return system_rtnl_call(msg);
1129 int system_macvlan_del(struct device *macvlan)
1131 return system_link_del(macvlan->ifname);
1134 static int system_vlan(struct device *dev, int id)
1136 struct vlan_ioctl_args ifr = {
1137 .cmd = SET_VLAN_NAME_TYPE_CMD,
1138 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
1141 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
1144 ifr.cmd = DEL_VLAN_CMD;
1147 ifr.cmd = ADD_VLAN_CMD;
1150 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
1151 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
1154 int system_vlan_add(struct device *dev, int id)
1156 return system_vlan(dev, id);
1159 int system_vlan_del(struct device *dev)
1161 return system_vlan(dev, -1);
1164 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
1167 struct nlattr *linkinfo, *data;
1168 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
1171 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1176 nlmsg_append(msg, &iim, sizeof(iim), 0);
1177 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
1178 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
1180 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1181 goto nla_put_failure;
1183 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
1185 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1186 goto nla_put_failure;
1188 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
1190 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
1191 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
1193 if(cfg->proto == VLAN_PROTO_8021AD)
1194 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);
1197 nla_nest_end(msg, data);
1198 nla_nest_end(msg, linkinfo);
1200 rv = system_rtnl_call(msg);
1202 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
1211 int system_vlandev_del(struct device *vlandev)
1213 return system_link_del(vlandev->ifname);
1217 system_if_get_settings(struct device *dev, struct device_settings *s)
1222 memset(&ifr, 0, sizeof(ifr));
1223 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1225 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
1226 s->mtu = ifr.ifr_mtu;
1227 s->flags |= DEV_OPT_MTU;
1230 s->mtu6 = system_update_ipv6_mtu(dev, 0);
1232 s->flags |= DEV_OPT_MTU6;
1234 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
1235 s->txqueuelen = ifr.ifr_qlen;
1236 s->flags |= DEV_OPT_TXQUEUELEN;
1239 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
1240 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
1241 s->flags |= DEV_OPT_MACADDR;
1244 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
1245 s->ipv6 = !strtoul(buf, NULL, 0);
1246 s->flags |= DEV_OPT_IPV6;
1249 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
1250 s->promisc = ifr.ifr_flags & IFF_PROMISC;
1251 s->flags |= DEV_OPT_PROMISC;
1253 s->multicast = ifr.ifr_flags & IFF_MULTICAST;
1254 s->flags |= DEV_OPT_MULTICAST;
1257 if (!system_get_rpfilter(dev, buf, sizeof(buf))) {
1258 s->rpfilter = strtoul(buf, NULL, 0);
1259 s->flags |= DEV_OPT_RPFILTER;
1262 if (!system_get_acceptlocal(dev, buf, sizeof(buf))) {
1263 s->acceptlocal = strtoul(buf, NULL, 0);
1264 s->flags |= DEV_OPT_ACCEPTLOCAL;
1267 if (!system_get_igmpversion(dev, buf, sizeof(buf))) {
1268 s->igmpversion = strtoul(buf, NULL, 0);
1269 s->flags |= DEV_OPT_IGMPVERSION;
1272 if (!system_get_mldversion(dev, buf, sizeof(buf))) {
1273 s->mldversion = strtoul(buf, NULL, 0);
1274 s->flags |= DEV_OPT_MLDVERSION;
1277 if (!system_get_neigh4reachabletime(dev, buf, sizeof(buf))) {
1278 s->neigh4reachabletime = strtoul(buf, NULL, 0);
1279 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1282 if (!system_get_neigh6reachabletime(dev, buf, sizeof(buf))) {
1283 s->neigh6reachabletime = strtoul(buf, NULL, 0);
1284 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1287 if (!system_get_neigh4gcstaletime(dev, buf, sizeof(buf))) {
1288 s->neigh4gcstaletime = strtoul(buf, NULL, 0);
1289 s->flags |= DEV_OPT_NEIGHGCSTALETIME;
1292 if (!system_get_neigh6gcstaletime(dev, buf, sizeof(buf))) {
1293 s->neigh6gcstaletime = strtoul(buf, NULL, 0);
1294 s->flags |= DEV_OPT_NEIGHGCSTALETIME;
1297 if (!system_get_dadtransmits(dev, buf, sizeof(buf))) {
1298 s->dadtransmits = strtoul(buf, NULL, 0);
1299 s->flags |= DEV_OPT_DADTRANSMITS;
1302 if (!system_get_sendredirects(dev, buf, sizeof(buf))) {
1303 s->sendredirects = strtoul(buf, NULL, 0);
1304 s->flags |= DEV_OPT_SENDREDIRECTS;
1309 system_if_set_rps_xps_val(const char *path, int val)
1315 if (glob(path, 0, NULL, &gl))
1318 snprintf(val_buf, sizeof(val_buf), "%x", val);
1319 for (i = 0; i < gl.gl_pathc; i++)
1320 system_set_sysctl(gl.gl_pathv[i], val_buf);
1326 system_if_apply_rps_xps(struct device *dev, struct device_settings *s)
1328 long n_cpus = sysconf(_SC_NPROCESSORS_ONLN);
1334 val = (1 << n_cpus) - 1;
1335 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/rps_cpus", dev->ifname);
1336 system_if_set_rps_xps_val(dev_buf, s->rps ? val : 0);
1338 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/xps_cpus", dev->ifname);
1339 system_if_set_rps_xps_val(dev_buf, s->xps ? val : 0);
1343 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
1348 memset(&ifr, 0, sizeof(ifr));
1349 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1350 if (s->flags & DEV_OPT_MTU & apply_mask) {
1351 ifr.ifr_mtu = s->mtu;
1352 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
1353 s->flags &= ~DEV_OPT_MTU;
1355 if (s->flags & DEV_OPT_MTU6 & apply_mask) {
1356 system_update_ipv6_mtu(dev, s->mtu6);
1358 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
1359 ifr.ifr_qlen = s->txqueuelen;
1360 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
1361 s->flags &= ~DEV_OPT_TXQUEUELEN;
1363 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
1364 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
1365 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
1366 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
1367 s->flags &= ~DEV_OPT_MACADDR;
1369 if (s->flags & DEV_OPT_IPV6 & apply_mask)
1370 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
1371 if (s->flags & DEV_OPT_PROMISC & apply_mask) {
1372 if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
1373 !s->promisc ? IFF_PROMISC : 0) < 0)
1374 s->flags &= ~DEV_OPT_PROMISC;
1376 if (s->flags & DEV_OPT_RPFILTER & apply_mask) {
1377 snprintf(buf, sizeof(buf), "%d", s->rpfilter);
1378 system_set_rpfilter(dev, buf);
1380 if (s->flags & DEV_OPT_ACCEPTLOCAL & apply_mask)
1381 system_set_acceptlocal(dev, s->acceptlocal ? "1" : "0");
1382 if (s->flags & DEV_OPT_IGMPVERSION & apply_mask) {
1383 snprintf(buf, sizeof(buf), "%d", s->igmpversion);
1384 system_set_igmpversion(dev, buf);
1386 if (s->flags & DEV_OPT_MLDVERSION & apply_mask) {
1387 snprintf(buf, sizeof(buf), "%d", s->mldversion);
1388 system_set_mldversion(dev, buf);
1390 if (s->flags & DEV_OPT_NEIGHREACHABLETIME & apply_mask) {
1391 snprintf(buf, sizeof(buf), "%d", s->neigh4reachabletime);
1392 system_set_neigh4reachabletime(dev, buf);
1393 snprintf(buf, sizeof(buf), "%d", s->neigh6reachabletime);
1394 system_set_neigh6reachabletime(dev, buf);
1396 if (s->flags & DEV_OPT_NEIGHGCSTALETIME & apply_mask) {
1397 snprintf(buf, sizeof(buf), "%d", s->neigh4gcstaletime);
1398 system_set_neigh4gcstaletime(dev, buf);
1399 snprintf(buf, sizeof(buf), "%d", s->neigh6gcstaletime);
1400 system_set_neigh6gcstaletime(dev, buf);
1402 if (s->flags & DEV_OPT_DADTRANSMITS & apply_mask) {
1403 snprintf(buf, sizeof(buf), "%d", s->dadtransmits);
1404 system_set_dadtransmits(dev, buf);
1406 if (s->flags & DEV_OPT_MULTICAST & apply_mask) {
1407 if (system_if_flags(dev->ifname, s->multicast ? IFF_MULTICAST : 0,
1408 !s->multicast ? IFF_MULTICAST : 0) < 0)
1409 s->flags &= ~DEV_OPT_MULTICAST;
1411 if (s->flags & DEV_OPT_SENDREDIRECTS & apply_mask)
1412 system_set_sendredirects(dev, s->sendredirects ? "1" : "0");
1414 system_if_apply_rps_xps(dev, s);
1417 int system_if_up(struct device *dev)
1419 system_if_get_settings(dev, &dev->orig_settings);
1420 /* Only keep orig settings based on what needs to be set */
1421 dev->orig_settings.valid_flags = dev->orig_settings.flags;
1422 dev->orig_settings.flags &= dev->settings.flags;
1423 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
1424 return system_if_flags(dev->ifname, IFF_UP, 0);
1427 int system_if_down(struct device *dev)
1429 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
1430 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
1434 struct if_check_data {
1440 #ifndef IFF_LOWER_UP
1441 #define IFF_LOWER_UP 0x10000
1444 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1446 struct nlmsghdr *nh = nlmsg_hdr(msg);
1447 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1448 struct if_check_data *chk = (struct if_check_data *)arg;
1450 if (nh->nlmsg_type != RTM_NEWLINK)
1453 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1454 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1459 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1461 struct if_check_data *chk = (struct if_check_data *)arg;
1466 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1468 struct if_check_data *chk = (struct if_check_data *)arg;
1470 device_set_present(chk->dev, false);
1471 device_set_link(chk->dev, false);
1472 chk->pending = err->error;
1477 int system_if_check(struct device *dev)
1479 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1481 struct ifinfomsg ifi = {
1482 .ifi_family = AF_UNSPEC,
1485 struct if_check_data chk = {
1491 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1495 if (nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1496 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1499 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1500 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1501 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1503 nl_send_auto_complete(sock_rtnl, msg);
1504 while (chk.pending > 0)
1505 nl_recvmsgs(sock_rtnl, cb);
1517 system_if_get_parent(struct device *dev)
1519 char buf[64], *devname;
1520 int ifindex, iflink, len;
1523 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1524 f = fopen(buf, "r");
1528 len = fread(buf, 1, sizeof(buf) - 1, f);
1535 iflink = strtoul(buf, NULL, 0);
1536 ifindex = system_if_resolve(dev);
1537 if (!iflink || iflink == ifindex)
1540 devname = if_indextoname(iflink, buf);
1544 return device_get(devname, true);
1548 read_string_file(int dir_fd, const char *file, char *buf, int len)
1554 fd = openat(dir_fd, file, O_RDONLY);
1559 len = read(fd, buf, len - 1);
1563 } else if (len > 0) {
1566 c = strchr(buf, '\n');
1579 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1584 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1586 *val = strtoull(buf, NULL, 0);
1591 /* Assume advertised flags == supported flags */
1592 static const struct {
1595 } ethtool_link_modes[] = {
1596 { ADVERTISED_10baseT_Half, "10H" },
1597 { ADVERTISED_10baseT_Full, "10F" },
1598 { ADVERTISED_100baseT_Half, "100H" },
1599 { ADVERTISED_100baseT_Full, "100F" },
1600 { ADVERTISED_1000baseT_Half, "1000H" },
1601 { ADVERTISED_1000baseT_Full, "1000F" },
1604 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1607 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1608 if (mask & ethtool_link_modes[i].mask)
1609 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1614 system_if_force_external(const char *ifname)
1619 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1620 return stat(buf, &s) == 0;
1624 system_if_dump_info(struct device *dev, struct blob_buf *b)
1626 struct ethtool_cmd ecmd;
1632 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
1633 dir_fd = open(buf, O_DIRECTORY);
1635 memset(&ecmd, 0, sizeof(ecmd));
1636 memset(&ifr, 0, sizeof(ifr));
1637 strcpy(ifr.ifr_name, dev->ifname);
1638 ifr.ifr_data = (caddr_t) &ecmd;
1639 ecmd.cmd = ETHTOOL_GSET;
1641 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1642 c = blobmsg_open_array(b, "link-advertising");
1643 system_add_link_modes(b, ecmd.advertising);
1644 blobmsg_close_array(b, c);
1646 c = blobmsg_open_array(b, "link-supported");
1647 system_add_link_modes(b, ecmd.supported);
1648 blobmsg_close_array(b, c);
1650 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1651 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1652 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1653 blobmsg_add_string_buffer(b);
1661 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1663 const char *const counters[] = {
1664 "collisions", "rx_frame_errors", "tx_compressed",
1665 "multicast", "rx_length_errors", "tx_dropped",
1666 "rx_bytes", "rx_missed_errors", "tx_errors",
1667 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1668 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1669 "rx_dropped", "tx_aborted_errors", "tx_packets",
1670 "rx_errors", "tx_bytes", "tx_window_errors",
1671 "rx_fifo_errors", "tx_carrier_errors",
1678 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1679 stats_dir = open(buf, O_DIRECTORY);
1683 for (i = 0; i < ARRAY_SIZE(counters); i++)
1684 if (read_uint64_file(stats_dir, counters[i], &val))
1685 blobmsg_add_u64(b, counters[i], val);
1691 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1693 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1694 int alen = v4 ? 4 : 16;
1695 unsigned int flags = 0;
1696 struct ifaddrmsg ifa = {
1697 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1698 .ifa_prefixlen = addr->mask,
1699 .ifa_index = dev->ifindex,
1703 if (cmd == RTM_NEWADDR)
1704 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1706 msg = nlmsg_alloc_simple(cmd, flags);
1710 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1711 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1713 if (addr->broadcast)
1714 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1715 if (addr->point_to_point)
1716 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1718 time_t now = system_get_rtime();
1719 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1721 if (addr->preferred_until) {
1722 int64_t preferred = addr->preferred_until - now;
1725 else if (preferred > UINT32_MAX)
1726 preferred = UINT32_MAX;
1728 cinfo.ifa_prefered = preferred;
1731 if (addr->valid_until) {
1732 int64_t valid = addr->valid_until - now;
1737 else if (valid > UINT32_MAX)
1740 cinfo.ifa_valid = valid;
1743 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1745 if (cmd == RTM_NEWADDR && (addr->flags & DEVADDR_OFFLINK))
1746 nla_put_u32(msg, IFA_FLAGS, IFA_F_NOPREFIXROUTE);
1749 return system_rtnl_call(msg);
1752 int system_add_address(struct device *dev, struct device_addr *addr)
1754 return system_addr(dev, addr, RTM_NEWADDR);
1757 int system_del_address(struct device *dev, struct device_addr *addr)
1759 return system_addr(dev, addr, RTM_DELADDR);
1762 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1764 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1766 unsigned int flags = 0;
1769 have_gw = !!route->nexthop.in.s_addr;
1771 have_gw = route->nexthop.in6.s6_addr32[0] ||
1772 route->nexthop.in6.s6_addr32[1] ||
1773 route->nexthop.in6.s6_addr32[2] ||
1774 route->nexthop.in6.s6_addr32[3];
1776 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1777 ? route->table : RT_TABLE_MAIN;
1779 struct rtmsg rtm = {
1780 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1781 .rtm_dst_len = route->mask,
1782 .rtm_src_len = route->sourcemask,
1783 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1784 .rtm_protocol = (route->flags & DEVROUTE_PROTO) ? route->proto : RTPROT_STATIC,
1785 .rtm_scope = RT_SCOPE_NOWHERE,
1786 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1787 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1791 if (cmd == RTM_NEWROUTE) {
1792 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1794 if (!dev) { // Add null-route
1795 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1796 rtm.rtm_type = RTN_UNREACHABLE;
1799 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1802 if (route->flags & DEVROUTE_TYPE) {
1803 rtm.rtm_type = route->type;
1804 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
1805 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
1806 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
1807 rtm.rtm_table = RT_TABLE_LOCAL;
1810 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT) {
1811 rtm.rtm_scope = RT_SCOPE_HOST;
1812 } else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
1813 rtm.rtm_type == RTN_ANYCAST) {
1814 rtm.rtm_scope = RT_SCOPE_LINK;
1815 } else if (rtm.rtm_type == RTN_BLACKHOLE || rtm.rtm_type == RTN_UNREACHABLE ||
1816 rtm.rtm_type == RTN_PROHIBIT || rtm.rtm_type == RTN_FAILED_POLICY) {
1817 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1822 msg = nlmsg_alloc_simple(cmd, flags);
1826 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1829 nla_put(msg, RTA_DST, alen, &route->addr);
1831 if (route->sourcemask) {
1832 if (rtm.rtm_family == AF_INET)
1833 nla_put(msg, RTA_PREFSRC, alen, &route->source);
1835 nla_put(msg, RTA_SRC, alen, &route->source);
1838 if (route->metric > 0)
1839 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1842 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1845 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1848 nla_put_u32(msg, RTA_TABLE, table);
1850 if (route->flags & DEVROUTE_MTU) {
1851 struct nlattr *metrics;
1853 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1854 goto nla_put_failure;
1856 nla_put_u32(msg, RTAX_MTU, route->mtu);
1858 nla_nest_end(msg, metrics);
1861 return system_rtnl_call(msg);
1868 int system_add_route(struct device *dev, struct device_route *route)
1870 return system_rt(dev, route, RTM_NEWROUTE);
1873 int system_del_route(struct device *dev, struct device_route *route)
1875 return system_rt(dev, route, RTM_DELROUTE);
1878 int system_flush_routes(void)
1880 const char *names[] = {
1881 "/proc/sys/net/ipv4/route/flush",
1882 "/proc/sys/net/ipv6/route/flush"
1886 for (i = 0; i < ARRAY_SIZE(names); i++) {
1887 fd = open(names[i], O_WRONLY);
1891 if (write(fd, "-1", 2)) {}
1897 bool system_resolve_rt_type(const char *type, unsigned int *id)
1899 return system_rtn_aton(type, id);
1902 bool system_resolve_rt_proto(const char *type, unsigned int *id)
1906 unsigned int n, proto = 256;
1908 if ((n = strtoul(type, &e, 0)) >= 0 && !*e && e != type)
1910 else if (!strcmp(type, "unspec"))
1911 proto = RTPROT_UNSPEC;
1912 else if (!strcmp(type, "kernel"))
1913 proto = RTPROT_KERNEL;
1914 else if (!strcmp(type, "boot"))
1915 proto = RTPROT_BOOT;
1916 else if (!strcmp(type, "static"))
1917 proto = RTPROT_STATIC;
1918 else if ((f = fopen("/etc/iproute2/rt_protos", "r")) != NULL) {
1919 while (fgets(buf, sizeof(buf) - 1, f) != NULL) {
1920 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1923 n = strtoul(e, NULL, 10);
1924 e = strtok(NULL, " \t\n");
1926 if (e && !strcmp(e, type)) {
1941 bool system_resolve_rt_table(const char *name, unsigned int *id)
1945 unsigned int n, table = RT_TABLE_UNSPEC;
1947 /* first try to parse table as number */
1948 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1951 /* handle well known aliases */
1952 else if (!strcmp(name, "default"))
1953 table = RT_TABLE_DEFAULT;
1954 else if (!strcmp(name, "main"))
1955 table = RT_TABLE_MAIN;
1956 else if (!strcmp(name, "local"))
1957 table = RT_TABLE_LOCAL;
1959 /* try to look up name in /etc/iproute2/rt_tables */
1960 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1962 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1964 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1967 n = strtoul(e, NULL, 10);
1968 e = strtok(NULL, " \t\n");
1970 if (e && !strcmp(e, name))
1980 if (table == RT_TABLE_UNSPEC)
1987 bool system_is_default_rt_table(unsigned int id)
1989 return (id == RT_TABLE_MAIN);
1992 bool system_resolve_rpfilter(const char *filter, unsigned int *id)
1997 if (!strcmp(filter, "strict"))
1999 else if (!strcmp(filter, "loose"))
2002 n = strtoul(filter, &e, 0);
2003 if (*e || e == filter || n > 2)
2011 static int system_iprule(struct iprule *rule, int cmd)
2013 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
2016 struct rtmsg rtm = {
2017 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
2018 .rtm_protocol = RTPROT_STATIC,
2019 .rtm_scope = RT_SCOPE_UNIVERSE,
2020 .rtm_table = RT_TABLE_UNSPEC,
2021 .rtm_type = RTN_UNSPEC,
2025 if (cmd == RTM_NEWRULE)
2026 rtm.rtm_type = RTN_UNICAST;
2029 rtm.rtm_flags |= FIB_RULE_INVERT;
2031 if (rule->flags & IPRULE_SRC)
2032 rtm.rtm_src_len = rule->src_mask;
2034 if (rule->flags & IPRULE_DEST)
2035 rtm.rtm_dst_len = rule->dest_mask;
2037 if (rule->flags & IPRULE_TOS)
2038 rtm.rtm_tos = rule->tos;
2040 if (rule->flags & IPRULE_LOOKUP) {
2041 if (rule->lookup < 256)
2042 rtm.rtm_table = rule->lookup;
2045 if (rule->flags & IPRULE_ACTION)
2046 rtm.rtm_type = rule->action;
2047 else if (rule->flags & IPRULE_GOTO)
2048 rtm.rtm_type = FR_ACT_GOTO;
2049 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
2050 rtm.rtm_type = FR_ACT_NOP;
2052 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
2057 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
2059 if (rule->flags & IPRULE_IN)
2060 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
2062 if (rule->flags & IPRULE_OUT)
2063 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
2065 if (rule->flags & IPRULE_SRC)
2066 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
2068 if (rule->flags & IPRULE_DEST)
2069 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
2071 if (rule->flags & IPRULE_PRIORITY)
2072 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
2073 else if (cmd == RTM_NEWRULE)
2074 nla_put_u32(msg, FRA_PRIORITY, rule->order);
2076 if (rule->flags & IPRULE_FWMARK)
2077 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
2079 if (rule->flags & IPRULE_FWMASK)
2080 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
2082 if (rule->flags & IPRULE_LOOKUP) {
2083 if (rule->lookup >= 256)
2084 nla_put_u32(msg, FRA_TABLE, rule->lookup);
2087 if (rule->flags & IPRULE_GOTO)
2088 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
2090 return system_rtnl_call(msg);
2093 int system_add_iprule(struct iprule *rule)
2095 return system_iprule(rule, RTM_NEWRULE);
2098 int system_del_iprule(struct iprule *rule)
2100 return system_iprule(rule, RTM_DELRULE);
2103 int system_flush_iprules(void)
2108 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
2109 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
2111 memset(&rule, 0, sizeof(rule));
2114 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2117 rule.lookup = RT_TABLE_LOCAL;
2118 rv |= system_iprule(&rule, RTM_NEWRULE);
2120 rule.priority = 32766;
2121 rule.lookup = RT_TABLE_MAIN;
2122 rv |= system_iprule(&rule, RTM_NEWRULE);
2124 rule.priority = 32767;
2125 rule.lookup = RT_TABLE_DEFAULT;
2126 rv |= system_iprule(&rule, RTM_NEWRULE);
2129 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2132 rule.lookup = RT_TABLE_LOCAL;
2133 rv |= system_iprule(&rule, RTM_NEWRULE);
2135 rule.priority = 32766;
2136 rule.lookup = RT_TABLE_MAIN;
2137 rv |= system_iprule(&rule, RTM_NEWRULE);
2142 bool system_resolve_iprule_action(const char *action, unsigned int *id)
2144 return system_rtn_aton(action, id);
2147 time_t system_get_rtime(void)
2152 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
2155 if (gettimeofday(&tv, NULL) == 0)
2162 #define IP_DF 0x4000
2165 static int tunnel_ioctl(const char *name, int cmd, void *p)
2169 memset(&ifr, 0, sizeof(ifr));
2170 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
2171 ifr.ifr_ifru.ifru_data = p;
2172 return ioctl(sock_ioctl, cmd, &ifr);
2175 #ifdef IFLA_IPTUN_MAX
2176 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
2177 static int system_add_gre_tunnel(const char *name, const char *kind,
2178 const unsigned int link, struct blob_attr **tb, bool v6)
2181 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2182 struct blob_attr *cur;
2183 uint32_t ikey = 0, okey = 0, flags = 0, flowinfo = 0;
2184 uint16_t iflags = 0, oflags = 0;
2186 int ret = 0, ttl = 0;
2188 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2192 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2193 nla_put_string(nlm, IFLA_IFNAME, name);
2195 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2201 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2202 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2209 nla_put_u32(nlm, IFLA_GRE_LINK, link);
2211 if ((cur = tb[TUNNEL_ATTR_TTL]))
2212 ttl = blobmsg_get_u32(cur);
2214 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2215 char *str = blobmsg_get_string(cur);
2216 if (strcmp(str, "inherit")) {
2219 if (!system_tos_aton(str, &uval)) {
2225 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
2230 flags |= IP6_TNL_F_USE_ORIG_TCLASS;
2236 if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) {
2237 uint8_t icsum, ocsum, iseqno, oseqno;
2238 if (sscanf(blobmsg_get_string(cur), "%u,%u,%hhu,%hhu,%hhu,%hhu",
2239 &ikey, &okey, &icsum, &ocsum, &iseqno, &oseqno) < 6) {
2264 struct in6_addr in6buf;
2265 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2266 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2270 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
2273 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2274 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2278 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
2280 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, 4);
2283 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
2286 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags);
2291 struct in_addr inbuf;
2294 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2295 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2299 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
2302 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2303 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2307 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
2309 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
2311 okey = inbuf.s_addr;
2316 ikey = inbuf.s_addr;
2322 if ((cur = tb[TUNNEL_ATTR_DF]))
2323 set_df = blobmsg_get_bool(cur);
2326 /* ttl != 0 and nopmtudisc are incompatible */
2334 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
2336 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
2340 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
2343 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
2346 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
2349 nla_put_u32(nlm, IFLA_GRE_OKEY, okey);
2352 nla_put_u32(nlm, IFLA_GRE_IKEY, ikey);
2354 nla_nest_end(nlm, infodata);
2355 nla_nest_end(nlm, linkinfo);
2357 return system_rtnl_call(nlm);
2366 static int system_add_vti_tunnel(const char *name, const char *kind,
2367 const unsigned int link, struct blob_attr **tb, bool v6)
2370 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2371 struct blob_attr *cur;
2372 uint32_t ikey = 0, okey = 0;
2375 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2379 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2380 nla_put_string(nlm, IFLA_IFNAME, name);
2382 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2388 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2389 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2396 nla_put_u32(nlm, IFLA_VTI_LINK, link);
2398 if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) {
2399 if (sscanf(blobmsg_get_string(cur), "%u,%u",
2400 &ikey, &okey) < 2) {
2407 struct in6_addr in6buf;
2408 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2409 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2413 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(in6buf), &in6buf);
2416 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2417 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2421 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(in6buf), &in6buf);
2425 struct in_addr inbuf;
2427 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2428 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2432 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(inbuf), &inbuf);
2435 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2436 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2440 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(inbuf), &inbuf);
2446 nla_put_u32(nlm, IFLA_VTI_OKEY, htonl(okey));
2449 nla_put_u32(nlm, IFLA_VTI_IKEY, htonl(ikey));
2451 nla_nest_end(nlm, infodata);
2452 nla_nest_end(nlm, linkinfo);
2454 return system_rtnl_call(nlm);
2462 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
2464 struct blob_attr *cur;
2466 struct ip_tunnel_parm p = {
2475 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
2476 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
2479 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
2480 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
2483 if ((cur = tb[TUNNEL_ATTR_DF]))
2484 set_df = blobmsg_get_bool(cur);
2486 if ((cur = tb[TUNNEL_ATTR_TTL]))
2487 p.iph.ttl = blobmsg_get_u32(cur);
2489 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2490 char *str = blobmsg_get_string(cur);
2491 if (strcmp(str, "inherit")) {
2494 if (!system_tos_aton(str, &uval))
2502 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
2503 /* ttl !=0 and nopmtudisc are incompatible */
2504 if (p.iph.ttl && p.iph.frag_off == 0)
2507 strncpy(p.name, name, sizeof(p.name));
2509 switch (p.iph.protocol) {
2511 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
2513 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
2520 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
2522 struct blob_attr *cur;
2525 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2527 str = blobmsg_data(cur);
2529 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
2530 !strcmp(str, "greip6") || !strcmp(str, "gretapip6") ||
2531 !strcmp(str, "vtiip") || !strcmp(str, "vtiip6"))
2532 return system_link_del(name);
2534 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
2537 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
2539 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2541 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2542 blob_data(attr), blob_len(attr));
2544 return __system_del_ip_tunnel(name, tb);
2547 int system_update_ipv6_mtu(struct device *dev, int mtu)
2553 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
2556 fd = open(buf, O_RDWR);
2561 ssize_t len = read(fd, buf, sizeof(buf) - 1);
2568 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) > 0)
2577 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
2579 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2580 struct blob_attr *cur;
2583 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2584 blob_data(attr), blob_len(attr));
2586 __system_del_ip_tunnel(name, tb);
2588 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2590 str = blobmsg_data(cur);
2592 unsigned int ttl = 0;
2593 if ((cur = tb[TUNNEL_ATTR_TTL])) {
2594 ttl = blobmsg_get_u32(cur);
2599 unsigned int link = 0;
2600 if ((cur = tb[TUNNEL_ATTR_LINK])) {
2601 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
2605 if (iface->l3_dev.dev)
2606 link = iface->l3_dev.dev->ifindex;
2609 if (!strcmp(str, "sit")) {
2610 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
2614 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
2616 struct ip_tunnel_6rd p6;
2618 memset(&p6, 0, sizeof(p6));
2620 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
2621 &p6.prefix, &mask) || mask > 128)
2623 p6.prefixlen = mask;
2625 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
2626 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
2627 &p6.relay_prefix, &mask) || mask > 32)
2629 p6.relay_prefixlen = mask;
2632 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
2633 __system_del_ip_tunnel(name, tb);
2638 #ifdef IFLA_IPTUN_MAX
2639 } else if (!strcmp(str, "ipip6")) {
2640 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2641 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2642 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2648 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2649 nla_put_string(nlm, IFLA_IFNAME, name);
2652 nla_put_u32(nlm, IFLA_LINK, link);
2654 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2659 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2660 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2667 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2669 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2670 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2671 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
2673 struct in6_addr in6buf;
2674 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2675 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2679 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2682 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2683 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2687 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2690 #ifdef IFLA_IPTUN_FMR_MAX
2691 if ((cur = tb[TUNNEL_ATTR_FMRS])) {
2692 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2694 struct blob_attr *fmr;
2695 unsigned rem, fmrcnt = 0;
2696 blobmsg_for_each_attr(fmr, cur, rem) {
2697 if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
2700 unsigned ip4len, ip6len, ealen, offset = 6;
2704 if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
2705 ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) {
2710 struct in6_addr ip6prefix;
2711 struct in_addr ip4prefix;
2712 if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
2713 inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) {
2718 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2720 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2721 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2722 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2723 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2724 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2725 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2727 nla_nest_end(nlm, rule);
2730 nla_nest_end(nlm, fmrs);
2734 nla_nest_end(nlm, infodata);
2735 nla_nest_end(nlm, linkinfo);
2737 return system_rtnl_call(nlm);
2741 } else if (!strcmp(str, "greip")) {
2742 return system_add_gre_tunnel(name, "gre", link, tb, false);
2743 } else if (!strcmp(str, "gretapip")) {
2744 return system_add_gre_tunnel(name, "gretap", link, tb, false);
2745 } else if (!strcmp(str, "greip6")) {
2746 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
2747 } else if (!strcmp(str, "gretapip6")) {
2748 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
2750 } else if (!strcmp(str, "vtiip")) {
2751 return system_add_vti_tunnel(name, "vti", link, tb, false);
2752 } else if (!strcmp(str, "vtiip6")) {
2753 return system_add_vti_tunnel(name, "vti6", link, tb, true);
2756 } else if (!strcmp(str, "ipip")) {
2757 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);