2 * netifd - network interface daemon
3 * Copyright (C) 2012 Felix Fietkau <nbd@openwrt.org>
4 * Copyright (C) 2013 Jo-Philipp Wich <jow@openwrt.org>
5 * Copyright (C) 2013 Steven Barth <steven@midlink.org>
6 * Copyright (C) 2014 Gioacchino Mazzurco <gio@eigenlab.org>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2
10 * as published by the Free Software Foundation
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
19 #include <sys/socket.h>
20 #include <sys/ioctl.h>
22 #include <sys/syscall.h>
25 #include <net/if_arp.h>
27 #include <arpa/inet.h>
28 #include <netinet/in.h>
30 #include <linux/rtnetlink.h>
31 #include <linux/sockios.h>
33 #include <linux/if_addr.h>
34 #include <linux/if_link.h>
35 #include <linux/if_vlan.h>
36 #include <linux/if_bridge.h>
37 #include <linux/if_tunnel.h>
38 #include <linux/ip6_tunnel.h>
39 #include <linux/ethtool.h>
40 #include <linux/fib_rules.h>
41 #include <linux/version.h>
43 #ifndef RTN_FAILED_POLICY
44 #define RTN_FAILED_POLICY 12
47 #ifndef RT_TABLE_PRELOCAL
48 #define RT_TABLE_PRELOCAL 128
51 #ifndef IFA_F_NOPREFIXROUTE
52 #define IFA_F_NOPREFIXROUTE 0x200
56 #define IFA_FLAGS (IFA_MULTICAST + 1)
66 #include <netlink/msg.h>
67 #include <netlink/attr.h>
68 #include <netlink/socket.h>
69 #include <libubox/uloop.h>
76 struct uloop_fd uloop;
81 static int sock_ioctl = -1;
82 static struct nl_sock *sock_rtnl = NULL;
84 static int cb_rtnl_event(struct nl_msg *msg, void *arg);
85 static void handle_hotplug_event(struct uloop_fd *u, unsigned int events);
87 static char dev_buf[256];
90 handler_nl_event(struct uloop_fd *u, unsigned int events)
92 struct event_socket *ev = container_of(u, struct event_socket, uloop);
94 socklen_t errlen = sizeof(err);
97 nl_recvmsgs_default(ev->sock);
101 if (getsockopt(u->fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen))
106 // Increase rx buffer size on netlink socket
108 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
111 // Request full dump since some info got dropped
112 struct rtgenmsg msg = { .rtgen_family = AF_UNSPEC };
113 nl_send_simple(ev->sock, RTM_GETLINK, NLM_F_DUMP, &msg, sizeof(msg));
123 uloop_fd_delete(&ev->uloop);
127 static struct nl_sock *
128 create_socket(int protocol, int groups)
130 struct nl_sock *sock;
132 sock = nl_socket_alloc();
137 nl_join_groups(sock, groups);
139 if (nl_connect(sock, protocol))
146 create_raw_event_socket(struct event_socket *ev, int protocol, int groups,
147 uloop_fd_handler cb, int flags)
149 ev->sock = create_socket(protocol, groups);
153 ev->uloop.fd = nl_socket_get_fd(ev->sock);
155 if (uloop_fd_add(&ev->uloop, ULOOP_READ|flags))
162 create_event_socket(struct event_socket *ev, int protocol,
163 int (*cb)(struct nl_msg *msg, void *arg))
165 if (!create_raw_event_socket(ev, protocol, 0, handler_nl_event, ULOOP_ERROR_CB))
168 // Install the valid custom callback handler
169 nl_socket_modify_cb(ev->sock, NL_CB_VALID, NL_CB_CUSTOM, cb, NULL);
171 // Disable sequence number checking on event sockets
172 nl_socket_disable_seq_check(ev->sock);
174 // Increase rx buffer size to 65K on event sockets
176 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
183 system_rtn_aton(const char *src, unsigned int *dst)
188 if (!strcmp(src, "local"))
190 else if (!strcmp(src, "nat"))
192 else if (!strcmp(src, "broadcast"))
194 else if (!strcmp(src, "anycast"))
196 else if (!strcmp(src, "multicast"))
198 else if (!strcmp(src, "prohibit"))
200 else if (!strcmp(src, "unreachable"))
202 else if (!strcmp(src, "blackhole"))
204 else if (!strcmp(src, "xresolve"))
206 else if (!strcmp(src, "unicast"))
208 else if (!strcmp(src, "throw"))
210 else if (!strcmp(src, "failed_policy"))
211 n = RTN_FAILED_POLICY;
213 n = strtoul(src, &e, 0);
214 if (!e || *e || e == src || n > 255)
223 system_tos_aton(const char *src, unsigned *dst)
227 *dst = strtoul(src, &e, 16);
228 if (e == src || *e || *dst > 255)
234 int system_init(void)
236 static struct event_socket rtnl_event;
237 static struct event_socket hotplug_event;
239 sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0);
240 system_fd_set_cloexec(sock_ioctl);
242 // Prepare socket for routing / address control
243 sock_rtnl = create_socket(NETLINK_ROUTE, 0);
247 if (!create_event_socket(&rtnl_event, NETLINK_ROUTE, cb_rtnl_event))
250 if (!create_raw_event_socket(&hotplug_event, NETLINK_KOBJECT_UEVENT, 1,
251 handle_hotplug_event, 0))
254 // Receive network link events form kernel
255 nl_socket_add_membership(rtnl_event.sock, RTNLGRP_LINK);
260 static void system_set_sysctl(const char *path, const char *val)
264 fd = open(path, O_WRONLY);
268 if (write(fd, val, strlen(val))) {}
272 static void system_set_dev_sysctl(const char *path, const char *device, const char *val)
274 snprintf(dev_buf, sizeof(dev_buf), path, device);
275 system_set_sysctl(dev_buf, val);
278 static void system_set_disable_ipv6(struct device *dev, const char *val)
280 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val);
283 static void system_set_rpfilter(struct device *dev, const char *val)
285 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter", dev->ifname, val);
288 static void system_set_acceptlocal(struct device *dev, const char *val)
290 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local", dev->ifname, val);
293 static void system_set_igmpversion(struct device *dev, const char *val)
295 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version", dev->ifname, val);
298 static void system_set_mldversion(struct device *dev, const char *val)
300 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version", dev->ifname, val);
303 static void system_set_neigh4reachabletime(struct device *dev, const char *val)
305 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms", dev->ifname, val);
308 static void system_set_neigh6reachabletime(struct device *dev, const char *val)
310 system_set_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms", dev->ifname, val);
313 static void system_set_dadtransmits(struct device *dev, const char *val)
315 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits", dev->ifname, val);
318 static int system_get_sysctl(const char *path, char *buf, const size_t buf_sz)
320 int fd = -1, ret = -1;
322 fd = open(path, O_RDONLY);
326 ssize_t len = read(fd, buf, buf_sz - 1);
340 system_get_dev_sysctl(const char *path, const char *device, char *buf, const size_t buf_sz)
342 snprintf(dev_buf, sizeof(dev_buf), path, device);
343 return system_get_sysctl(dev_buf, buf, buf_sz);
346 static int system_get_disable_ipv6(struct device *dev, char *buf, const size_t buf_sz)
348 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6",
349 dev->ifname, buf, buf_sz);
352 static int system_get_rpfilter(struct device *dev, char *buf, const size_t buf_sz)
354 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter",
355 dev->ifname, buf, buf_sz);
358 static int system_get_acceptlocal(struct device *dev, char *buf, const size_t buf_sz)
360 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local",
361 dev->ifname, buf, buf_sz);
364 static int system_get_igmpversion(struct device *dev, char *buf, const size_t buf_sz)
366 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version",
367 dev->ifname, buf, buf_sz);
370 static int system_get_mldversion(struct device *dev, char *buf, const size_t buf_sz)
372 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version",
373 dev->ifname, buf, buf_sz);
376 static int system_get_neigh4reachabletime(struct device *dev, char *buf, const size_t buf_sz)
378 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms",
379 dev->ifname, buf, buf_sz);
382 static int system_get_neigh6reachabletime(struct device *dev, char *buf, const size_t buf_sz)
384 return system_get_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms",
385 dev->ifname, buf, buf_sz);
388 static int system_get_dadtransmits(struct device *dev, char *buf, const size_t buf_sz)
390 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits",
391 dev->ifname, buf, buf_sz);
394 // Evaluate netlink messages
395 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
397 struct nlmsghdr *nh = nlmsg_hdr(msg);
398 struct nlattr *nla[__IFLA_MAX];
402 if (nh->nlmsg_type != RTM_NEWLINK)
405 nlmsg_parse(nh, sizeof(struct ifinfomsg), nla, __IFLA_MAX - 1, NULL);
406 if (!nla[IFLA_IFNAME])
409 struct device *dev = device_get(nla_data(nla[IFLA_IFNAME]), false);
410 if (!dev || dev->type->keep_link_status)
413 if (!system_get_dev_sysctl("/sys/class/net/%s/carrier", dev->ifname, buf, sizeof(buf)))
414 link_state = strtoul(buf, NULL, 0);
416 device_set_link(dev, link_state ? true : false);
423 handle_hotplug_msg(char *data, int size)
425 const char *subsystem = NULL, *interface = NULL;
426 char *cur, *end, *sep;
431 if (!strncmp(data, "add@", 4))
433 else if (!strncmp(data, "remove@", 7))
438 skip = strlen(data) + 1;
441 for (cur = data + skip; cur < end; cur += skip) {
442 skip = strlen(cur) + 1;
444 sep = strchr(cur, '=');
449 if (!strcmp(cur, "INTERFACE"))
451 else if (!strcmp(cur, "SUBSYSTEM")) {
453 if (strcmp(subsystem, "net") != 0)
456 if (subsystem && interface)
462 dev = device_get(interface, false);
466 if (dev->type != &simple_device_type)
469 if (add && system_if_force_external(dev->ifname))
472 device_set_present(dev, add);
476 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
478 struct event_socket *ev = container_of(u, struct event_socket, uloop);
479 struct sockaddr_nl nla;
480 unsigned char *buf = NULL;
483 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
485 handle_hotplug_msg((char *) buf, size);
491 static int system_rtnl_call(struct nl_msg *msg)
495 ret = nl_send_auto_complete(sock_rtnl, msg);
501 return nl_wait_for_ack(sock_rtnl);
504 int system_bridge_delbr(struct device *bridge)
506 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
509 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
513 memset(&ifr, 0, sizeof(ifr));
515 ifr.ifr_ifindex = dev->ifindex;
518 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
519 return ioctl(sock_ioctl, cmd, &ifr);
522 static bool system_is_bridge(const char *name, char *buf, int buflen)
526 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
527 if (stat(buf, &st) < 0)
533 static char *system_get_bridge(const char *name, char *buf, int buflen)
539 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
540 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
544 len = readlink(gl.gl_pathv[0], buf, buflen);
552 path = strrchr(buf, '/');
559 static void system_bridge_set_wireless(const char *bridge, const char *dev)
561 snprintf(dev_buf, sizeof(dev_buf),
562 "/sys/devices/virtual/net/%s/brif/%s/multicast_to_unicast",
564 system_set_sysctl(dev_buf, "1");
567 int system_bridge_addif(struct device *bridge, struct device *dev)
572 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
573 if (!oldbr || strcmp(oldbr, bridge->ifname) != 0)
574 ret = system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
577 system_bridge_set_wireless(bridge->ifname, dev->ifname);
582 int system_bridge_delif(struct device *bridge, struct device *dev)
584 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
587 int system_if_resolve(struct device *dev)
590 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
591 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
592 return ifr.ifr_ifindex;
597 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
601 memset(&ifr, 0, sizeof(ifr));
602 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
603 ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
604 ifr.ifr_flags |= add;
605 ifr.ifr_flags &= ~rem;
606 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
618 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
620 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
622 return ifa->ifa_index == ifindex;
625 static bool check_route(struct nlmsghdr *hdr, int ifindex)
627 struct rtmsg *r = NLMSG_DATA(hdr);
628 struct nlattr *tb[__RTA_MAX];
630 if (r->rtm_protocol == RTPROT_KERNEL &&
631 r->rtm_family == AF_INET6)
634 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
638 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
641 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
646 static int cb_clear_event(struct nl_msg *msg, void *arg)
648 struct clear_data *clr = arg;
649 struct nlmsghdr *hdr = nlmsg_hdr(msg);
650 bool (*cb)(struct nlmsghdr *, int ifindex);
656 if (hdr->nlmsg_type != RTM_NEWADDR)
663 if (hdr->nlmsg_type != RTM_NEWROUTE)
670 if (hdr->nlmsg_type != RTM_NEWRULE)
679 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
682 if (type == RTM_DELRULE)
683 D(SYSTEM, "Remove a rule\n");
685 D(SYSTEM, "Remove %s from device %s\n",
686 type == RTM_DELADDR ? "an address" : "a route",
688 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
689 hdr = nlmsg_hdr(clr->msg);
690 hdr->nlmsg_type = type;
691 hdr->nlmsg_flags = NLM_F_REQUEST;
693 nl_socket_disable_auto_ack(sock_rtnl);
694 nl_send_auto_complete(sock_rtnl, clr->msg);
695 nl_socket_enable_auto_ack(sock_rtnl);
701 cb_finish_event(struct nl_msg *msg, void *arg)
709 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
712 *pending = err->error;
717 system_if_clear_entries(struct device *dev, int type, int af)
719 struct clear_data clr;
720 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
723 .rtm_flags = RTM_F_CLONED,
725 int flags = NLM_F_DUMP;
734 clr.size = sizeof(struct rtgenmsg);
737 clr.size = sizeof(struct rtmsg);
746 clr.msg = nlmsg_alloc_simple(type, flags);
750 nlmsg_append(clr.msg, &rtm, clr.size, 0);
751 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
752 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
753 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
755 nl_send_auto_complete(sock_rtnl, clr.msg);
757 nl_recvmsgs(sock_rtnl, cb);
765 * Clear bridge (membership) state and bring down device
767 void system_if_clear_state(struct device *dev)
769 static char buf[256];
772 device_set_ifindex(dev, system_if_resolve(dev));
773 if (dev->external || !dev->ifindex)
776 system_if_flags(dev->ifname, 0, IFF_UP);
778 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
779 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
780 system_bridge_delbr(dev);
784 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
786 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
787 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
790 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
791 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
792 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
793 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
794 system_set_disable_ipv6(dev, "0");
797 static inline unsigned long
798 sec_to_jiffies(int val)
800 return (unsigned long) val * 100;
803 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
806 unsigned long args[4] = {};
808 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
811 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
812 args[1] = !!cfg->stp;
813 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
815 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
816 args[1] = sec_to_jiffies(cfg->forward_delay);
817 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
819 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
820 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
822 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier",
823 bridge->ifname, cfg->multicast_querier ? "1" : "0");
825 snprintf(buf, sizeof(buf), "%i", cfg->hash_max);
826 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/hash_max",
827 bridge->ifname, buf);
829 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
830 args[1] = cfg->priority;
831 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
833 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
834 args[0] = BRCTL_SET_AGEING_TIME;
835 args[1] = sec_to_jiffies(cfg->ageing_time);
836 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
839 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
840 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
841 args[1] = sec_to_jiffies(cfg->hello_time);
842 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
845 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
846 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
847 args[1] = sec_to_jiffies(cfg->max_age);
848 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
854 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
857 struct nlattr *linkinfo, *data;
858 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
860 static const struct {
862 enum macvlan_mode val;
864 { "private", MACVLAN_MODE_PRIVATE },
865 { "vepa", MACVLAN_MODE_VEPA },
866 { "bridge", MACVLAN_MODE_BRIDGE },
867 { "passthru", MACVLAN_MODE_PASSTHRU },
870 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
875 nlmsg_append(msg, &iim, sizeof(iim), 0);
877 if (cfg->flags & MACVLAN_OPT_MACADDR)
878 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
879 nla_put_string(msg, IFLA_IFNAME, macvlan->ifname);
880 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
882 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
883 goto nla_put_failure;
885 nla_put_string(msg, IFLA_INFO_KIND, "macvlan");
887 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
888 goto nla_put_failure;
891 for (i = 0; i < ARRAY_SIZE(modes); i++) {
892 if (strcmp(cfg->mode, modes[i].name) != 0)
895 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
900 nla_nest_end(msg, data);
901 nla_nest_end(msg, linkinfo);
903 rv = system_rtnl_call(msg);
905 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
914 static int system_link_del(const char *ifname)
917 struct ifinfomsg iim = {
918 .ifi_family = AF_UNSPEC,
922 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
927 nlmsg_append(msg, &iim, sizeof(iim), 0);
928 nla_put_string(msg, IFLA_IFNAME, ifname);
929 return system_rtnl_call(msg);
932 int system_macvlan_del(struct device *macvlan)
934 return system_link_del(macvlan->ifname);
937 static int system_vlan(struct device *dev, int id)
939 struct vlan_ioctl_args ifr = {
940 .cmd = SET_VLAN_NAME_TYPE_CMD,
941 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
944 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
947 ifr.cmd = DEL_VLAN_CMD;
950 ifr.cmd = ADD_VLAN_CMD;
953 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
954 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
957 int system_vlan_add(struct device *dev, int id)
959 return system_vlan(dev, id);
962 int system_vlan_del(struct device *dev)
964 return system_vlan(dev, -1);
967 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
970 struct nlattr *linkinfo, *data;
971 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
974 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
979 nlmsg_append(msg, &iim, sizeof(iim), 0);
980 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
981 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
983 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
984 goto nla_put_failure;
986 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
988 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
989 goto nla_put_failure;
991 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
993 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
994 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
996 if(cfg->proto == VLAN_PROTO_8021AD)
997 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);
1000 nla_nest_end(msg, data);
1001 nla_nest_end(msg, linkinfo);
1003 rv = system_rtnl_call(msg);
1005 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
1014 int system_vlandev_del(struct device *vlandev)
1016 return system_link_del(vlandev->ifname);
1020 system_if_get_settings(struct device *dev, struct device_settings *s)
1025 memset(&ifr, 0, sizeof(ifr));
1026 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1028 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
1029 s->mtu = ifr.ifr_mtu;
1030 s->flags |= DEV_OPT_MTU;
1033 s->mtu6 = system_update_ipv6_mtu(dev, 0);
1035 s->flags |= DEV_OPT_MTU6;
1037 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
1038 s->txqueuelen = ifr.ifr_qlen;
1039 s->flags |= DEV_OPT_TXQUEUELEN;
1042 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
1043 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
1044 s->flags |= DEV_OPT_MACADDR;
1047 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
1048 s->ipv6 = !strtoul(buf, NULL, 0);
1049 s->flags |= DEV_OPT_IPV6;
1052 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
1053 s->promisc = ifr.ifr_flags & IFF_PROMISC;
1054 s->flags |= DEV_OPT_PROMISC;
1057 if (!system_get_rpfilter(dev, buf, sizeof(buf))) {
1058 s->rpfilter = strtoul(buf, NULL, 0);
1059 s->flags |= DEV_OPT_RPFILTER;
1062 if (!system_get_acceptlocal(dev, buf, sizeof(buf))) {
1063 s->acceptlocal = strtoul(buf, NULL, 0);
1064 s->flags |= DEV_OPT_ACCEPTLOCAL;
1067 if (!system_get_igmpversion(dev, buf, sizeof(buf))) {
1068 s->igmpversion = strtoul(buf, NULL, 0);
1069 s->flags |= DEV_OPT_IGMPVERSION;
1072 if (!system_get_mldversion(dev, buf, sizeof(buf))) {
1073 s->mldversion = strtoul(buf, NULL, 0);
1074 s->flags |= DEV_OPT_MLDVERSION;
1077 if (!system_get_neigh4reachabletime(dev, buf, sizeof(buf))) {
1078 s->neigh4reachabletime = strtoul(buf, NULL, 0);
1079 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1082 if (!system_get_neigh6reachabletime(dev, buf, sizeof(buf))) {
1083 s->neigh6reachabletime = strtoul(buf, NULL, 0);
1084 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1087 if (!system_get_dadtransmits(dev, buf, sizeof(buf))) {
1088 s->dadtransmits = strtoul(buf, NULL, 0);
1089 s->flags |= DEV_OPT_DADTRANSMITS;
1094 system_if_set_rps_xps_val(const char *path, int val)
1100 if (glob(path, 0, NULL, &gl))
1103 snprintf(val_buf, sizeof(val_buf), "%x", val);
1104 for (i = 0; i < gl.gl_pathc; i++)
1105 system_set_sysctl(gl.gl_pathv[i], val_buf);
1109 system_if_apply_rps_xps(struct device *dev, struct device_settings *s)
1111 long n_cpus = sysconf(_SC_NPROCESSORS_ONLN);
1117 val = (1 << n_cpus) - 1;
1118 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/rps_cpus", dev->ifname);
1119 system_if_set_rps_xps_val(dev_buf, s->rps ? val : 0);
1121 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/xps_cpus", dev->ifname);
1122 system_if_set_rps_xps_val(dev_buf, s->xps ? val : 0);
1126 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
1131 memset(&ifr, 0, sizeof(ifr));
1132 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1133 if (s->flags & DEV_OPT_MTU & apply_mask) {
1134 ifr.ifr_mtu = s->mtu;
1135 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
1136 s->flags &= ~DEV_OPT_MTU;
1138 if (s->flags & DEV_OPT_MTU6 & apply_mask) {
1139 system_update_ipv6_mtu(dev, s->mtu6);
1141 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
1142 ifr.ifr_qlen = s->txqueuelen;
1143 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
1144 s->flags &= ~DEV_OPT_TXQUEUELEN;
1146 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
1147 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
1148 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
1149 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
1150 s->flags &= ~DEV_OPT_MACADDR;
1152 if (s->flags & DEV_OPT_IPV6 & apply_mask)
1153 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
1154 if (s->flags & DEV_OPT_PROMISC & apply_mask) {
1155 if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
1156 !s->promisc ? IFF_PROMISC : 0) < 0)
1157 s->flags &= ~DEV_OPT_PROMISC;
1159 if (s->flags & DEV_OPT_RPFILTER & apply_mask) {
1160 snprintf(buf, sizeof(buf), "%d", s->rpfilter);
1161 system_set_rpfilter(dev, buf);
1163 if (s->flags & DEV_OPT_ACCEPTLOCAL & apply_mask)
1164 system_set_acceptlocal(dev, s->acceptlocal ? "1" : "0");
1165 if (s->flags & DEV_OPT_IGMPVERSION & apply_mask) {
1166 snprintf(buf, sizeof(buf), "%d", s->igmpversion);
1167 system_set_igmpversion(dev, buf);
1169 if (s->flags & DEV_OPT_MLDVERSION & apply_mask) {
1170 snprintf(buf, sizeof(buf), "%d", s->mldversion);
1171 system_set_mldversion(dev, buf);
1173 if (s->flags & DEV_OPT_NEIGHREACHABLETIME & apply_mask) {
1174 snprintf(buf, sizeof(buf), "%d", s->neigh4reachabletime);
1175 system_set_neigh4reachabletime(dev, buf);
1176 snprintf(buf, sizeof(buf), "%d", s->neigh6reachabletime);
1177 system_set_neigh6reachabletime(dev, buf);
1179 if (s->flags & DEV_OPT_DADTRANSMITS & apply_mask) {
1180 snprintf(buf, sizeof(buf), "%d", s->dadtransmits);
1181 system_set_dadtransmits(dev, buf);
1184 system_if_apply_rps_xps(dev, s);
1187 int system_if_up(struct device *dev)
1189 system_if_get_settings(dev, &dev->orig_settings);
1190 /* Only keep orig settings based on what needs to be set */
1191 dev->orig_settings.flags &= dev->settings.flags;
1192 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
1193 return system_if_flags(dev->ifname, IFF_UP, 0);
1196 int system_if_down(struct device *dev)
1198 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
1199 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
1203 struct if_check_data {
1209 #ifndef IFF_LOWER_UP
1210 #define IFF_LOWER_UP 0x10000
1213 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1215 struct nlmsghdr *nh = nlmsg_hdr(msg);
1216 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1217 struct if_check_data *chk = (struct if_check_data *)arg;
1219 if (nh->nlmsg_type != RTM_NEWLINK)
1222 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1223 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1228 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1230 struct if_check_data *chk = (struct if_check_data *)arg;
1235 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1237 struct if_check_data *chk = (struct if_check_data *)arg;
1239 device_set_present(chk->dev, false);
1240 device_set_link(chk->dev, false);
1241 chk->pending = err->error;
1246 int system_if_check(struct device *dev)
1248 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1250 struct ifinfomsg ifi = {
1251 .ifi_family = AF_UNSPEC,
1254 struct if_check_data chk = {
1260 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1261 if (!msg || nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1262 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1265 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1266 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1267 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1269 nl_send_auto_complete(sock_rtnl, msg);
1270 while (chk.pending > 0)
1271 nl_recvmsgs(sock_rtnl, cb);
1282 system_if_get_parent(struct device *dev)
1284 char buf[64], *devname;
1285 int ifindex, iflink, len;
1288 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1289 f = fopen(buf, "r");
1293 len = fread(buf, 1, sizeof(buf) - 1, f);
1300 iflink = strtoul(buf, NULL, 0);
1301 ifindex = system_if_resolve(dev);
1302 if (!iflink || iflink == ifindex)
1305 devname = if_indextoname(iflink, buf);
1309 return device_get(devname, true);
1313 read_string_file(int dir_fd, const char *file, char *buf, int len)
1319 fd = openat(dir_fd, file, O_RDONLY);
1324 len = read(fd, buf, len - 1);
1328 } else if (len > 0) {
1331 c = strchr(buf, '\n');
1344 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1349 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1351 *val = strtoull(buf, NULL, 0);
1356 /* Assume advertised flags == supported flags */
1357 static const struct {
1360 } ethtool_link_modes[] = {
1361 { ADVERTISED_10baseT_Half, "10H" },
1362 { ADVERTISED_10baseT_Full, "10F" },
1363 { ADVERTISED_100baseT_Half, "100H" },
1364 { ADVERTISED_100baseT_Full, "100F" },
1365 { ADVERTISED_1000baseT_Half, "1000H" },
1366 { ADVERTISED_1000baseT_Full, "1000F" },
1369 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1372 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1373 if (mask & ethtool_link_modes[i].mask)
1374 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1379 system_if_force_external(const char *ifname)
1384 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1385 return stat(buf, &s) == 0;
1389 system_if_dump_info(struct device *dev, struct blob_buf *b)
1391 struct ethtool_cmd ecmd;
1397 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
1398 dir_fd = open(buf, O_DIRECTORY);
1400 memset(&ecmd, 0, sizeof(ecmd));
1401 memset(&ifr, 0, sizeof(ifr));
1402 strcpy(ifr.ifr_name, dev->ifname);
1403 ifr.ifr_data = (caddr_t) &ecmd;
1404 ecmd.cmd = ETHTOOL_GSET;
1406 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1407 c = blobmsg_open_array(b, "link-advertising");
1408 system_add_link_modes(b, ecmd.advertising);
1409 blobmsg_close_array(b, c);
1411 c = blobmsg_open_array(b, "link-supported");
1412 system_add_link_modes(b, ecmd.supported);
1413 blobmsg_close_array(b, c);
1415 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1416 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1417 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1418 blobmsg_add_string_buffer(b);
1426 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1428 const char *const counters[] = {
1429 "collisions", "rx_frame_errors", "tx_compressed",
1430 "multicast", "rx_length_errors", "tx_dropped",
1431 "rx_bytes", "rx_missed_errors", "tx_errors",
1432 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1433 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1434 "rx_dropped", "tx_aborted_errors", "tx_packets",
1435 "rx_errors", "tx_bytes", "tx_window_errors",
1436 "rx_fifo_errors", "tx_carrier_errors",
1443 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1444 stats_dir = open(buf, O_DIRECTORY);
1448 for (i = 0; i < ARRAY_SIZE(counters); i++)
1449 if (read_uint64_file(stats_dir, counters[i], &val))
1450 blobmsg_add_u64(b, counters[i], val);
1456 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1458 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1459 int alen = v4 ? 4 : 16;
1460 unsigned int flags = 0;
1461 struct ifaddrmsg ifa = {
1462 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1463 .ifa_prefixlen = addr->mask,
1464 .ifa_index = dev->ifindex,
1468 if (cmd == RTM_NEWADDR)
1469 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1471 msg = nlmsg_alloc_simple(cmd, flags);
1475 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1476 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1478 if (addr->broadcast)
1479 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1480 if (addr->point_to_point)
1481 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1483 time_t now = system_get_rtime();
1484 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1486 if (addr->preferred_until) {
1487 int64_t preferred = addr->preferred_until - now;
1490 else if (preferred > UINT32_MAX)
1491 preferred = UINT32_MAX;
1493 cinfo.ifa_prefered = preferred;
1496 if (addr->valid_until) {
1497 int64_t valid = addr->valid_until - now;
1500 else if (valid > UINT32_MAX)
1503 cinfo.ifa_valid = valid;
1506 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1508 if (cmd == RTM_NEWADDR && (addr->flags & DEVADDR_OFFLINK))
1509 nla_put_u32(msg, IFA_FLAGS, IFA_F_NOPREFIXROUTE);
1512 return system_rtnl_call(msg);
1515 int system_add_address(struct device *dev, struct device_addr *addr)
1517 return system_addr(dev, addr, RTM_NEWADDR);
1520 int system_del_address(struct device *dev, struct device_addr *addr)
1522 return system_addr(dev, addr, RTM_DELADDR);
1525 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1527 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1529 unsigned int flags = 0;
1532 have_gw = !!route->nexthop.in.s_addr;
1534 have_gw = route->nexthop.in6.s6_addr32[0] ||
1535 route->nexthop.in6.s6_addr32[1] ||
1536 route->nexthop.in6.s6_addr32[2] ||
1537 route->nexthop.in6.s6_addr32[3];
1539 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1540 ? route->table : RT_TABLE_MAIN;
1542 struct rtmsg rtm = {
1543 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1544 .rtm_dst_len = route->mask,
1545 .rtm_src_len = route->sourcemask,
1546 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1547 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
1548 .rtm_scope = RT_SCOPE_NOWHERE,
1549 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1550 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1554 if (cmd == RTM_NEWROUTE) {
1555 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1557 if (!dev) { // Add null-route
1558 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1559 rtm.rtm_type = RTN_UNREACHABLE;
1562 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1565 if (route->flags & DEVROUTE_TYPE) {
1566 rtm.rtm_type = route->type;
1567 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
1568 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
1569 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
1570 rtm.rtm_table = RT_TABLE_LOCAL;
1573 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT) {
1574 rtm.rtm_scope = RT_SCOPE_HOST;
1575 } else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
1576 rtm.rtm_type == RTN_ANYCAST) {
1577 rtm.rtm_scope = RT_SCOPE_LINK;
1578 } else if (rtm.rtm_type == RTN_BLACKHOLE || rtm.rtm_type == RTN_UNREACHABLE ||
1579 rtm.rtm_type == RTN_PROHIBIT || rtm.rtm_type == RTN_FAILED_POLICY) {
1580 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1585 msg = nlmsg_alloc_simple(cmd, flags);
1589 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1592 nla_put(msg, RTA_DST, alen, &route->addr);
1594 if (route->sourcemask) {
1595 if (rtm.rtm_family == AF_INET)
1596 nla_put(msg, RTA_PREFSRC, alen, &route->source);
1598 nla_put(msg, RTA_SRC, alen, &route->source);
1601 if (route->metric > 0)
1602 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1605 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1608 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1611 nla_put_u32(msg, RTA_TABLE, table);
1613 if (route->flags & DEVROUTE_MTU) {
1614 struct nlattr *metrics;
1616 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1617 goto nla_put_failure;
1619 nla_put_u32(msg, RTAX_MTU, route->mtu);
1621 nla_nest_end(msg, metrics);
1624 return system_rtnl_call(msg);
1631 int system_add_route(struct device *dev, struct device_route *route)
1633 return system_rt(dev, route, RTM_NEWROUTE);
1636 int system_del_route(struct device *dev, struct device_route *route)
1638 return system_rt(dev, route, RTM_DELROUTE);
1641 int system_flush_routes(void)
1643 const char *names[] = {
1644 "/proc/sys/net/ipv4/route/flush",
1645 "/proc/sys/net/ipv6/route/flush"
1649 for (i = 0; i < ARRAY_SIZE(names); i++) {
1650 fd = open(names[i], O_WRONLY);
1654 if (write(fd, "-1", 2)) {}
1660 bool system_resolve_rt_type(const char *type, unsigned int *id)
1662 return system_rtn_aton(type, id);
1665 bool system_resolve_rt_table(const char *name, unsigned int *id)
1669 unsigned int n, table = RT_TABLE_UNSPEC;
1671 /* first try to parse table as number */
1672 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1675 /* handle well known aliases */
1676 else if (!strcmp(name, "default"))
1677 table = RT_TABLE_DEFAULT;
1678 else if (!strcmp(name, "main"))
1679 table = RT_TABLE_MAIN;
1680 else if (!strcmp(name, "local"))
1681 table = RT_TABLE_LOCAL;
1682 else if (!strcmp(name, "prelocal"))
1683 table = RT_TABLE_PRELOCAL;
1685 /* try to look up name in /etc/iproute2/rt_tables */
1686 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1688 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1690 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1693 n = strtoul(e, NULL, 10);
1694 e = strtok(NULL, " \t\n");
1696 if (e && !strcmp(e, name))
1706 if (table == RT_TABLE_UNSPEC)
1713 bool system_is_default_rt_table(unsigned int id)
1715 return (id == RT_TABLE_MAIN);
1718 bool system_resolve_rpfilter(const char *filter, unsigned int *id)
1723 if (!strcmp(filter, "strict"))
1725 else if (!strcmp(filter, "loose"))
1728 n = strtoul(filter, &e, 0);
1729 if (*e || e == filter || n > 2)
1737 static int system_iprule(struct iprule *rule, int cmd)
1739 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1742 struct rtmsg rtm = {
1743 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1744 .rtm_protocol = RTPROT_STATIC,
1745 .rtm_scope = RT_SCOPE_UNIVERSE,
1746 .rtm_table = RT_TABLE_UNSPEC,
1747 .rtm_type = RTN_UNSPEC,
1751 if (cmd == RTM_NEWRULE) {
1752 rtm.rtm_type = RTN_UNICAST;
1753 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1757 rtm.rtm_flags |= FIB_RULE_INVERT;
1759 if (rule->flags & IPRULE_SRC)
1760 rtm.rtm_src_len = rule->src_mask;
1762 if (rule->flags & IPRULE_DEST)
1763 rtm.rtm_dst_len = rule->dest_mask;
1765 if (rule->flags & IPRULE_TOS)
1766 rtm.rtm_tos = rule->tos;
1768 if (rule->flags & IPRULE_LOOKUP) {
1769 if (rule->lookup < 256)
1770 rtm.rtm_table = rule->lookup;
1773 if (rule->flags & IPRULE_ACTION)
1774 rtm.rtm_type = rule->action;
1775 else if (rule->flags & IPRULE_GOTO)
1776 rtm.rtm_type = FR_ACT_GOTO;
1777 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1778 rtm.rtm_type = FR_ACT_NOP;
1780 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1785 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1787 if (rule->flags & IPRULE_IN)
1788 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1790 if (rule->flags & IPRULE_OUT)
1791 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1793 if (rule->flags & IPRULE_SRC)
1794 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1796 if (rule->flags & IPRULE_DEST)
1797 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1799 if (rule->flags & IPRULE_PRIORITY)
1800 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1801 else if (cmd == RTM_NEWRULE)
1802 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1804 if (rule->flags & IPRULE_FWMARK)
1805 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1807 if (rule->flags & IPRULE_FWMASK)
1808 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1810 if (rule->flags & IPRULE_LOOKUP) {
1811 if (rule->lookup >= 256)
1812 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1815 if (rule->flags & IPRULE_GOTO)
1816 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1818 return system_rtnl_call(msg);
1821 int system_add_iprule(struct iprule *rule)
1823 return system_iprule(rule, RTM_NEWRULE);
1826 int system_del_iprule(struct iprule *rule)
1828 return system_iprule(rule, RTM_DELRULE);
1831 int system_flush_iprules(void)
1836 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1837 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1839 memset(&rule, 0, sizeof(rule));
1842 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1845 rule.lookup = RT_TABLE_PRELOCAL;
1846 rv |= system_iprule(&rule, RTM_NEWRULE);
1849 rule.lookup = RT_TABLE_LOCAL;
1850 rv |= system_iprule(&rule, RTM_NEWRULE);
1852 rule.priority = 32766;
1853 rule.lookup = RT_TABLE_MAIN;
1854 rv |= system_iprule(&rule, RTM_NEWRULE);
1856 rule.priority = 32767;
1857 rule.lookup = RT_TABLE_DEFAULT;
1858 rv |= system_iprule(&rule, RTM_NEWRULE);
1861 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1864 rule.lookup = RT_TABLE_PRELOCAL;
1865 rv |= system_iprule(&rule, RTM_NEWRULE);
1868 rule.lookup = RT_TABLE_LOCAL;
1869 rv |= system_iprule(&rule, RTM_NEWRULE);
1871 rule.priority = 32766;
1872 rule.lookup = RT_TABLE_MAIN;
1873 rv |= system_iprule(&rule, RTM_NEWRULE);
1878 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1880 return system_rtn_aton(action, id);
1883 time_t system_get_rtime(void)
1888 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1891 if (gettimeofday(&tv, NULL) == 0)
1898 #define IP_DF 0x4000
1901 static int tunnel_ioctl(const char *name, int cmd, void *p)
1905 memset(&ifr, 0, sizeof(ifr));
1906 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1907 ifr.ifr_ifru.ifru_data = p;
1908 return ioctl(sock_ioctl, cmd, &ifr);
1911 #ifdef IFLA_IPTUN_MAX
1912 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
1913 static int system_add_gre_tunnel(const char *name, const char *kind,
1914 const unsigned int link, struct blob_attr **tb, bool v6)
1917 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
1918 struct blob_attr *cur;
1919 uint32_t ikey = 0, okey = 0, flags = 0, flowinfo = 0;
1920 uint16_t iflags = 0, oflags = 0;
1922 int ret = 0, ttl = 64;
1924 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
1928 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
1929 nla_put_string(nlm, IFLA_IFNAME, name);
1931 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
1937 nla_put_string(nlm, IFLA_INFO_KIND, kind);
1938 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
1945 nla_put_u32(nlm, IFLA_GRE_LINK, link);
1947 if ((cur = tb[TUNNEL_ATTR_TTL]))
1948 ttl = blobmsg_get_u32(cur);
1950 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
1952 if ((cur = tb[TUNNEL_ATTR_TOS])) {
1953 char *str = blobmsg_get_string(cur);
1954 if (strcmp(str, "inherit")) {
1957 if (!system_tos_aton(str, &uval)) {
1963 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
1968 flags |= IP6_TNL_F_USE_ORIG_TCLASS;
1974 if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) {
1975 uint8_t icsum, ocsum, iseqno, oseqno;
1976 if (sscanf(blobmsg_get_string(cur), "%u,%u,%hhu,%hhu,%hhu,%hhu",
1977 &ikey, &okey, &icsum, &ocsum, &iseqno, &oseqno) < 6) {
2002 struct in6_addr in6buf;
2003 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2004 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2008 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
2011 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2012 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2016 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
2018 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, 4);
2021 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
2024 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags);
2026 struct in_addr inbuf;
2029 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2030 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2034 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
2037 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2038 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2042 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
2044 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
2046 okey = inbuf.s_addr;
2051 ikey = inbuf.s_addr;
2057 if ((cur = tb[TUNNEL_ATTR_DF]))
2058 set_df = blobmsg_get_bool(cur);
2060 /* ttl !=0 and nopmtudisc are incompatible */
2061 if (ttl && !set_df) {
2066 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
2068 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
2072 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
2075 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
2078 nla_put_u32(nlm, IFLA_GRE_OKEY, okey);
2081 nla_put_u32(nlm, IFLA_GRE_IKEY, ikey);
2083 nla_nest_end(nlm, infodata);
2084 nla_nest_end(nlm, linkinfo);
2086 return system_rtnl_call(nlm);
2094 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
2096 struct blob_attr *cur;
2098 struct ip_tunnel_parm p = {
2107 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
2108 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
2111 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
2112 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
2115 if ((cur = tb[TUNNEL_ATTR_DF]))
2116 set_df = blobmsg_get_bool(cur);
2118 if ((cur = tb[TUNNEL_ATTR_TTL]))
2119 p.iph.ttl = blobmsg_get_u32(cur);
2121 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2122 char *str = blobmsg_get_string(cur);
2123 if (strcmp(str, "inherit")) {
2126 if (!system_tos_aton(str, &uval))
2134 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
2135 /* ttl !=0 and nopmtudisc are incompatible */
2136 if (p.iph.ttl && p.iph.frag_off == 0)
2139 strncpy(p.name, name, sizeof(p.name));
2141 switch (p.iph.protocol) {
2143 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
2145 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
2152 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
2154 struct blob_attr *cur;
2157 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2159 str = blobmsg_data(cur);
2161 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
2162 !strcmp(str, "greip6") || !strcmp(str, "gretapip6"))
2163 return system_link_del(name);
2165 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
2168 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
2170 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2172 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2173 blob_data(attr), blob_len(attr));
2175 return __system_del_ip_tunnel(name, tb);
2178 int system_update_ipv6_mtu(struct device *dev, int mtu)
2182 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
2185 int fd = open(buf, O_RDWR);
2188 ssize_t len = read(fd, buf, sizeof(buf) - 1);
2195 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) > 0)
2204 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
2206 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2207 struct blob_attr *cur;
2210 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2211 blob_data(attr), blob_len(attr));
2213 __system_del_ip_tunnel(name, tb);
2215 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2217 str = blobmsg_data(cur);
2219 unsigned int ttl = 0;
2220 if ((cur = tb[TUNNEL_ATTR_TTL])) {
2221 ttl = blobmsg_get_u32(cur);
2226 unsigned int link = 0;
2227 if ((cur = tb[TUNNEL_ATTR_LINK])) {
2228 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
2232 if (iface->l3_dev.dev)
2233 link = iface->l3_dev.dev->ifindex;
2236 if (!strcmp(str, "sit")) {
2237 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
2241 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
2243 struct ip_tunnel_6rd p6;
2245 memset(&p6, 0, sizeof(p6));
2247 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
2248 &p6.prefix, &mask) || mask > 128)
2250 p6.prefixlen = mask;
2252 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
2253 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
2254 &p6.relay_prefix, &mask) || mask > 32)
2256 p6.relay_prefixlen = mask;
2259 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
2260 __system_del_ip_tunnel(name, tb);
2265 #ifdef IFLA_IPTUN_MAX
2266 } else if (!strcmp(str, "ipip6")) {
2267 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2268 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2269 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2275 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2276 nla_put_string(nlm, IFLA_IFNAME, name);
2279 nla_put_u32(nlm, IFLA_LINK, link);
2281 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2286 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2287 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2294 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2296 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2297 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2298 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
2300 struct in6_addr in6buf;
2301 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2302 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2306 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2309 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2310 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2314 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2317 #ifdef IFLA_IPTUN_FMR_MAX
2318 if ((cur = tb[TUNNEL_ATTR_FMRS])) {
2319 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2321 struct blob_attr *fmr;
2322 unsigned rem, fmrcnt = 0;
2323 blobmsg_for_each_attr(fmr, cur, rem) {
2324 if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
2327 unsigned ip4len, ip6len, ealen, offset = 6;
2331 if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
2332 ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) {
2337 struct in6_addr ip6prefix;
2338 struct in_addr ip4prefix;
2339 if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
2340 inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) {
2345 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2347 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2348 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2349 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2350 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2351 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2352 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2354 nla_nest_end(nlm, rule);
2357 nla_nest_end(nlm, fmrs);
2361 nla_nest_end(nlm, infodata);
2362 nla_nest_end(nlm, linkinfo);
2364 return system_rtnl_call(nlm);
2368 } else if (!strcmp(str, "greip")) {
2369 return system_add_gre_tunnel(name, "gre", link, tb, false);
2370 } else if (!strcmp(str, "gretapip")) {
2371 return system_add_gre_tunnel(name, "gretap", link, tb, false);
2372 } else if (!strcmp(str, "greip6")) {
2373 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
2374 } else if (!strcmp(str, "gretapip6")) {
2375 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
2377 } else if (!strcmp(str, "ipip")) {
2378 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);