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
57 #include <netlink/msg.h>
58 #include <netlink/attr.h>
59 #include <netlink/socket.h>
60 #include <libubox/uloop.h>
67 struct uloop_fd uloop;
72 static int sock_ioctl = -1;
73 static struct nl_sock *sock_rtnl = NULL;
75 static int cb_rtnl_event(struct nl_msg *msg, void *arg);
76 static void handle_hotplug_event(struct uloop_fd *u, unsigned int events);
78 static char dev_buf[256];
81 handler_nl_event(struct uloop_fd *u, unsigned int events)
83 struct event_socket *ev = container_of(u, struct event_socket, uloop);
85 socklen_t errlen = sizeof(err);
88 nl_recvmsgs_default(ev->sock);
92 if (getsockopt(u->fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen))
97 // Increase rx buffer size on netlink socket
99 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
102 // Request full dump since some info got dropped
103 struct rtgenmsg msg = { .rtgen_family = AF_UNSPEC };
104 nl_send_simple(ev->sock, RTM_GETLINK, NLM_F_DUMP, &msg, sizeof(msg));
114 uloop_fd_delete(&ev->uloop);
118 static struct nl_sock *
119 create_socket(int protocol, int groups)
121 struct nl_sock *sock;
123 sock = nl_socket_alloc();
128 nl_join_groups(sock, groups);
130 if (nl_connect(sock, protocol))
137 create_raw_event_socket(struct event_socket *ev, int protocol, int groups,
138 uloop_fd_handler cb, int flags)
140 ev->sock = create_socket(protocol, groups);
144 ev->uloop.fd = nl_socket_get_fd(ev->sock);
146 if (uloop_fd_add(&ev->uloop, ULOOP_READ|flags))
153 create_event_socket(struct event_socket *ev, int protocol,
154 int (*cb)(struct nl_msg *msg, void *arg))
156 if (!create_raw_event_socket(ev, protocol, 0, handler_nl_event, ULOOP_ERROR_CB))
159 // Install the valid custom callback handler
160 nl_socket_modify_cb(ev->sock, NL_CB_VALID, NL_CB_CUSTOM, cb, NULL);
162 // Disable sequence number checking on event sockets
163 nl_socket_disable_seq_check(ev->sock);
165 // Increase rx buffer size to 65K on event sockets
167 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
174 system_rtn_aton(const char *src, unsigned int *dst)
179 if (!strcmp(src, "local"))
181 else if (!strcmp(src, "nat"))
183 else if (!strcmp(src, "broadcast"))
185 else if (!strcmp(src, "anycast"))
187 else if (!strcmp(src, "multicast"))
189 else if (!strcmp(src, "prohibit"))
191 else if (!strcmp(src, "unreachable"))
193 else if (!strcmp(src, "blackhole"))
195 else if (!strcmp(src, "xresolve"))
197 else if (!strcmp(src, "unicast"))
199 else if (!strcmp(src, "throw"))
201 else if (!strcmp(src, "failed_policy"))
202 n = RTN_FAILED_POLICY;
204 n = strtoul(src, &e, 0);
205 if (!e || *e || e == src || n > 255)
214 system_tos_aton(const char *src, unsigned *dst)
218 *dst = strtoul(src, &e, 16);
219 if (e == src || *e || *dst > 255)
225 int system_init(void)
227 static struct event_socket rtnl_event;
228 static struct event_socket hotplug_event;
230 sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0);
231 system_fd_set_cloexec(sock_ioctl);
233 // Prepare socket for routing / address control
234 sock_rtnl = create_socket(NETLINK_ROUTE, 0);
238 if (!create_event_socket(&rtnl_event, NETLINK_ROUTE, cb_rtnl_event))
241 if (!create_raw_event_socket(&hotplug_event, NETLINK_KOBJECT_UEVENT, 1,
242 handle_hotplug_event, 0))
245 // Receive network link events form kernel
246 nl_socket_add_membership(rtnl_event.sock, RTNLGRP_LINK);
251 static void system_set_sysctl(const char *path, const char *val)
255 fd = open(path, O_WRONLY);
259 if (write(fd, val, strlen(val))) {}
263 static void system_set_dev_sysctl(const char *path, const char *device, const char *val)
265 snprintf(dev_buf, sizeof(dev_buf), path, device);
266 system_set_sysctl(dev_buf, val);
269 static void system_set_disable_ipv6(struct device *dev, const char *val)
271 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val);
274 static void system_set_rpfilter(struct device *dev, const char *val)
276 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter", dev->ifname, val);
279 static void system_set_acceptlocal(struct device *dev, const char *val)
281 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local", dev->ifname, val);
284 static void system_set_igmpversion(struct device *dev, const char *val)
286 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version", dev->ifname, val);
289 static void system_set_mldversion(struct device *dev, const char *val)
291 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version", dev->ifname, val);
294 static void system_set_neigh4reachabletime(struct device *dev, const char *val)
296 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms", dev->ifname, val);
299 static void system_set_neigh6reachabletime(struct device *dev, const char *val)
301 system_set_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms", dev->ifname, val);
304 static int system_get_sysctl(const char *path, char *buf, const size_t buf_sz)
306 int fd = -1, ret = -1;
308 fd = open(path, O_RDONLY);
312 ssize_t len = read(fd, buf, buf_sz - 1);
326 system_get_dev_sysctl(const char *path, const char *device, char *buf, const size_t buf_sz)
328 snprintf(dev_buf, sizeof(dev_buf), path, device);
329 return system_get_sysctl(dev_buf, buf, buf_sz);
332 static int system_get_disable_ipv6(struct device *dev, char *buf, const size_t buf_sz)
334 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6",
335 dev->ifname, buf, buf_sz);
338 static int system_get_rpfilter(struct device *dev, char *buf, const size_t buf_sz)
340 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter",
341 dev->ifname, buf, buf_sz);
344 static int system_get_acceptlocal(struct device *dev, char *buf, const size_t buf_sz)
346 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local",
347 dev->ifname, buf, buf_sz);
350 static int system_get_igmpversion(struct device *dev, char *buf, const size_t buf_sz)
352 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version",
353 dev->ifname, buf, buf_sz);
356 static int system_get_mldversion(struct device *dev, char *buf, const size_t buf_sz)
358 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version",
359 dev->ifname, buf, buf_sz);
362 static int system_get_neigh4reachabletime(struct device *dev, char *buf, const size_t buf_sz)
364 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms",
365 dev->ifname, buf, buf_sz);
368 static int system_get_neigh6reachabletime(struct device *dev, char *buf, const size_t buf_sz)
370 return system_get_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms",
371 dev->ifname, buf, buf_sz);
374 // Evaluate netlink messages
375 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
377 struct nlmsghdr *nh = nlmsg_hdr(msg);
378 struct nlattr *nla[__IFLA_MAX];
382 if (nh->nlmsg_type != RTM_NEWLINK)
385 nlmsg_parse(nh, sizeof(struct ifinfomsg), nla, __IFLA_MAX - 1, NULL);
386 if (!nla[IFLA_IFNAME])
389 struct device *dev = device_get(nla_data(nla[IFLA_IFNAME]), false);
390 if (!dev || dev->type->keep_link_status)
393 if (!system_get_dev_sysctl("/sys/class/net/%s/carrier", dev->ifname, buf, sizeof(buf)))
394 link_state = strtoul(buf, NULL, 0);
396 device_set_link(dev, link_state ? true : false);
403 handle_hotplug_msg(char *data, int size)
405 const char *subsystem = NULL, *interface = NULL;
406 char *cur, *end, *sep;
411 if (!strncmp(data, "add@", 4))
413 else if (!strncmp(data, "remove@", 7))
418 skip = strlen(data) + 1;
421 for (cur = data + skip; cur < end; cur += skip) {
422 skip = strlen(cur) + 1;
424 sep = strchr(cur, '=');
429 if (!strcmp(cur, "INTERFACE"))
431 else if (!strcmp(cur, "SUBSYSTEM")) {
433 if (strcmp(subsystem, "net") != 0)
436 if (subsystem && interface)
442 dev = device_get(interface, false);
446 if (dev->type != &simple_device_type)
449 if (add && system_if_force_external(dev->ifname))
452 device_set_present(dev, add);
456 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
458 struct event_socket *ev = container_of(u, struct event_socket, uloop);
459 struct sockaddr_nl nla;
460 unsigned char *buf = NULL;
463 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
465 handle_hotplug_msg((char *) buf, size);
471 static int system_rtnl_call(struct nl_msg *msg)
475 ret = nl_send_auto_complete(sock_rtnl, msg);
481 return nl_wait_for_ack(sock_rtnl);
484 int system_bridge_delbr(struct device *bridge)
486 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
489 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
493 memset(&ifr, 0, sizeof(ifr));
495 ifr.ifr_ifindex = dev->ifindex;
498 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
499 return ioctl(sock_ioctl, cmd, &ifr);
502 static bool system_is_bridge(const char *name, char *buf, int buflen)
506 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
507 if (stat(buf, &st) < 0)
513 static char *system_get_bridge(const char *name, char *buf, int buflen)
519 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
520 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
524 len = readlink(gl.gl_pathv[0], buf, buflen);
532 path = strrchr(buf, '/');
539 static void system_bridge_set_wireless(const char *bridge, const char *dev)
541 snprintf(dev_buf, sizeof(dev_buf),
542 "/sys/devices/virtual/net/%s/brif/%s/multicast_to_unicast",
544 system_set_sysctl(dev_buf, "1");
547 int system_bridge_addif(struct device *bridge, struct device *dev)
552 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
553 if (!oldbr || strcmp(oldbr, bridge->ifname) != 0)
554 ret = system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
557 system_bridge_set_wireless(bridge->ifname, dev->ifname);
562 int system_bridge_delif(struct device *bridge, struct device *dev)
564 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
567 int system_if_resolve(struct device *dev)
570 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
571 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
572 return ifr.ifr_ifindex;
577 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
581 memset(&ifr, 0, sizeof(ifr));
582 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
583 ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
584 ifr.ifr_flags |= add;
585 ifr.ifr_flags &= ~rem;
586 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
598 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
600 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
602 return ifa->ifa_index == ifindex;
605 static bool check_route(struct nlmsghdr *hdr, int ifindex)
607 struct rtmsg *r = NLMSG_DATA(hdr);
608 struct nlattr *tb[__RTA_MAX];
610 if (r->rtm_protocol == RTPROT_KERNEL &&
611 r->rtm_family == AF_INET6)
614 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
618 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
621 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
626 static int cb_clear_event(struct nl_msg *msg, void *arg)
628 struct clear_data *clr = arg;
629 struct nlmsghdr *hdr = nlmsg_hdr(msg);
630 bool (*cb)(struct nlmsghdr *, int ifindex);
636 if (hdr->nlmsg_type != RTM_NEWADDR)
643 if (hdr->nlmsg_type != RTM_NEWROUTE)
650 if (hdr->nlmsg_type != RTM_NEWRULE)
659 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
662 if (type == RTM_DELRULE)
663 D(SYSTEM, "Remove a rule\n");
665 D(SYSTEM, "Remove %s from device %s\n",
666 type == RTM_DELADDR ? "an address" : "a route",
668 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
669 hdr = nlmsg_hdr(clr->msg);
670 hdr->nlmsg_type = type;
671 hdr->nlmsg_flags = NLM_F_REQUEST;
673 nl_socket_disable_auto_ack(sock_rtnl);
674 nl_send_auto_complete(sock_rtnl, clr->msg);
675 nl_socket_enable_auto_ack(sock_rtnl);
681 cb_finish_event(struct nl_msg *msg, void *arg)
689 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
692 *pending = err->error;
697 system_if_clear_entries(struct device *dev, int type, int af)
699 struct clear_data clr;
700 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
703 .rtm_flags = RTM_F_CLONED,
705 int flags = NLM_F_DUMP;
714 clr.size = sizeof(struct rtgenmsg);
717 clr.size = sizeof(struct rtmsg);
726 clr.msg = nlmsg_alloc_simple(type, flags);
730 nlmsg_append(clr.msg, &rtm, clr.size, 0);
731 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
732 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
733 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
735 nl_send_auto_complete(sock_rtnl, clr.msg);
737 nl_recvmsgs(sock_rtnl, cb);
745 * Clear bridge (membership) state and bring down device
747 void system_if_clear_state(struct device *dev)
749 static char buf[256];
752 device_set_ifindex(dev, system_if_resolve(dev));
753 if (dev->external || !dev->ifindex)
756 system_if_flags(dev->ifname, 0, IFF_UP);
758 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
759 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
760 system_bridge_delbr(dev);
764 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
766 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
767 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
770 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
771 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
772 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
773 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
774 system_set_disable_ipv6(dev, "0");
777 static inline unsigned long
778 sec_to_jiffies(int val)
780 return (unsigned long) val * 100;
783 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
785 unsigned long args[4] = {};
787 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
790 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
791 args[1] = !!cfg->stp;
792 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
794 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
795 args[1] = sec_to_jiffies(cfg->forward_delay);
796 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
798 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
799 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
801 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier",
802 bridge->ifname, cfg->multicast_querier ? "1" : "0");
804 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
805 args[1] = cfg->priority;
806 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
808 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
809 args[0] = BRCTL_SET_AGEING_TIME;
810 args[1] = sec_to_jiffies(cfg->ageing_time);
811 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
814 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
815 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
816 args[1] = sec_to_jiffies(cfg->hello_time);
817 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
820 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
821 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
822 args[1] = sec_to_jiffies(cfg->max_age);
823 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
829 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
832 struct nlattr *linkinfo, *data;
833 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
835 static const struct {
837 enum macvlan_mode val;
839 { "private", MACVLAN_MODE_PRIVATE },
840 { "vepa", MACVLAN_MODE_VEPA },
841 { "bridge", MACVLAN_MODE_BRIDGE },
842 { "passthru", MACVLAN_MODE_PASSTHRU },
845 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
850 nlmsg_append(msg, &iim, sizeof(iim), 0);
852 if (cfg->flags & MACVLAN_OPT_MACADDR)
853 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
854 nla_put_string(msg, IFLA_IFNAME, macvlan->ifname);
855 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
857 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
858 goto nla_put_failure;
860 nla_put_string(msg, IFLA_INFO_KIND, "macvlan");
862 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
863 goto nla_put_failure;
866 for (i = 0; i < ARRAY_SIZE(modes); i++) {
867 if (strcmp(cfg->mode, modes[i].name) != 0)
870 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
875 nla_nest_end(msg, data);
876 nla_nest_end(msg, linkinfo);
878 rv = system_rtnl_call(msg);
880 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
889 static int system_link_del(const char *ifname)
892 struct ifinfomsg iim = {
893 .ifi_family = AF_UNSPEC,
897 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
902 nlmsg_append(msg, &iim, sizeof(iim), 0);
903 nla_put_string(msg, IFLA_IFNAME, ifname);
904 return system_rtnl_call(msg);
907 int system_macvlan_del(struct device *macvlan)
909 return system_link_del(macvlan->ifname);
912 static int system_vlan(struct device *dev, int id)
914 struct vlan_ioctl_args ifr = {
915 .cmd = SET_VLAN_NAME_TYPE_CMD,
916 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
919 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
922 ifr.cmd = DEL_VLAN_CMD;
925 ifr.cmd = ADD_VLAN_CMD;
928 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
929 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
932 int system_vlan_add(struct device *dev, int id)
934 return system_vlan(dev, id);
937 int system_vlan_del(struct device *dev)
939 return system_vlan(dev, -1);
942 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
945 struct nlattr *linkinfo, *data;
946 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
949 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
954 nlmsg_append(msg, &iim, sizeof(iim), 0);
955 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
956 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
958 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
959 goto nla_put_failure;
961 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
963 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
964 goto nla_put_failure;
966 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
968 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
969 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
971 if(cfg->proto == VLAN_PROTO_8021AD)
972 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);
975 nla_nest_end(msg, data);
976 nla_nest_end(msg, linkinfo);
978 rv = system_rtnl_call(msg);
980 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
989 int system_vlandev_del(struct device *vlandev)
991 return system_link_del(vlandev->ifname);
995 system_if_get_settings(struct device *dev, struct device_settings *s)
1000 memset(&ifr, 0, sizeof(ifr));
1001 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1003 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
1004 s->mtu = ifr.ifr_mtu;
1005 s->flags |= DEV_OPT_MTU;
1008 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
1009 s->txqueuelen = ifr.ifr_qlen;
1010 s->flags |= DEV_OPT_TXQUEUELEN;
1013 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
1014 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
1015 s->flags |= DEV_OPT_MACADDR;
1018 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
1019 s->ipv6 = !strtoul(buf, NULL, 0);
1020 s->flags |= DEV_OPT_IPV6;
1023 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
1024 s->promisc = ifr.ifr_flags & IFF_PROMISC;
1025 s->flags |= DEV_OPT_PROMISC;
1028 if (!system_get_rpfilter(dev, buf, sizeof(buf))) {
1029 s->rpfilter = strtoul(buf, NULL, 0);
1030 s->flags |= DEV_OPT_RPFILTER;
1033 if (!system_get_acceptlocal(dev, buf, sizeof(buf))) {
1034 s->acceptlocal = strtoul(buf, NULL, 0);
1035 s->flags |= DEV_OPT_ACCEPTLOCAL;
1038 if (!system_get_igmpversion(dev, buf, sizeof(buf))) {
1039 s->igmpversion = strtoul(buf, NULL, 0);
1040 s->flags |= DEV_OPT_IGMPVERSION;
1043 if (!system_get_mldversion(dev, buf, sizeof(buf))) {
1044 s->mldversion = strtoul(buf, NULL, 0);
1045 s->flags |= DEV_OPT_MLDVERSION;
1048 if (!system_get_neigh4reachabletime(dev, buf, sizeof(buf))) {
1049 s->neigh4reachabletime = strtoul(buf, NULL, 0);
1050 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1053 if (!system_get_neigh6reachabletime(dev, buf, sizeof(buf))) {
1054 s->neigh6reachabletime = strtoul(buf, NULL, 0);
1055 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1060 system_if_set_rps_xps_val(const char *path, int val)
1066 if (glob(path, 0, NULL, &gl))
1069 snprintf(val_buf, sizeof(val_buf), "%x", val);
1070 for (i = 0; i < gl.gl_pathc; i++)
1071 system_set_sysctl(gl.gl_pathv[i], val_buf);
1075 system_if_apply_rps_xps(struct device *dev, struct device_settings *s)
1077 long n_cpus = sysconf(_SC_NPROCESSORS_ONLN);
1083 val = (1 << n_cpus) - 1;
1084 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/rps_cpus", dev->ifname);
1085 system_if_set_rps_xps_val(dev_buf, s->rps ? val : 0);
1087 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/xps_cpus", dev->ifname);
1088 system_if_set_rps_xps_val(dev_buf, s->xps ? val : 0);
1092 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
1096 memset(&ifr, 0, sizeof(ifr));
1097 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1098 if (s->flags & DEV_OPT_MTU & apply_mask) {
1099 ifr.ifr_mtu = s->mtu;
1100 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
1101 s->flags &= ~DEV_OPT_MTU;
1103 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
1104 ifr.ifr_qlen = s->txqueuelen;
1105 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
1106 s->flags &= ~DEV_OPT_TXQUEUELEN;
1108 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
1109 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
1110 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
1111 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
1112 s->flags &= ~DEV_OPT_MACADDR;
1114 if (s->flags & DEV_OPT_IPV6 & apply_mask)
1115 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
1116 if (s->flags & DEV_OPT_PROMISC & apply_mask) {
1117 if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
1118 !s->promisc ? IFF_PROMISC : 0) < 0)
1119 s->flags &= ~DEV_OPT_PROMISC;
1121 if (s->flags & DEV_OPT_RPFILTER & apply_mask) {
1124 snprintf(buf, sizeof(buf), "%d", s->rpfilter);
1125 system_set_rpfilter(dev, buf);
1127 if (s->flags & DEV_OPT_ACCEPTLOCAL & apply_mask)
1128 system_set_acceptlocal(dev, s->acceptlocal ? "1" : "0");
1129 if (s->flags & DEV_OPT_IGMPVERSION & apply_mask) {
1132 snprintf(buf, sizeof(buf), "%d", s->igmpversion);
1133 system_set_igmpversion(dev, buf);
1135 if (s->flags & DEV_OPT_MLDVERSION & apply_mask) {
1138 snprintf(buf, sizeof(buf), "%d", s->mldversion);
1139 system_set_mldversion(dev, buf);
1141 if (s->flags & DEV_OPT_NEIGHREACHABLETIME & apply_mask) {
1144 snprintf(buf, sizeof(buf), "%d", s->neigh4reachabletime);
1145 system_set_neigh4reachabletime(dev, buf);
1146 snprintf(buf, sizeof(buf), "%d", s->neigh6reachabletime);
1147 system_set_neigh6reachabletime(dev, buf);
1150 system_if_apply_rps_xps(dev, s);
1153 int system_if_up(struct device *dev)
1155 system_if_get_settings(dev, &dev->orig_settings);
1156 /* Only keep orig settings based on what needs to be set */
1157 dev->orig_settings.flags &= dev->settings.flags;
1158 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
1159 return system_if_flags(dev->ifname, IFF_UP, 0);
1162 int system_if_down(struct device *dev)
1164 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
1165 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
1169 struct if_check_data {
1175 #ifndef IFF_LOWER_UP
1176 #define IFF_LOWER_UP 0x10000
1179 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1181 struct nlmsghdr *nh = nlmsg_hdr(msg);
1182 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1183 struct if_check_data *chk = (struct if_check_data *)arg;
1185 if (nh->nlmsg_type != RTM_NEWLINK)
1188 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1189 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1194 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1196 struct if_check_data *chk = (struct if_check_data *)arg;
1201 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1203 struct if_check_data *chk = (struct if_check_data *)arg;
1205 device_set_present(chk->dev, false);
1206 device_set_link(chk->dev, false);
1207 chk->pending = err->error;
1212 int system_if_check(struct device *dev)
1214 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1216 struct ifinfomsg ifi = {
1217 .ifi_family = AF_UNSPEC,
1220 struct if_check_data chk = {
1226 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1227 if (!msg || nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1228 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1231 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1232 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1233 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1235 nl_send_auto_complete(sock_rtnl, msg);
1236 while (chk.pending > 0)
1237 nl_recvmsgs(sock_rtnl, cb);
1248 system_if_get_parent(struct device *dev)
1250 char buf[64], *devname;
1251 int ifindex, iflink, len;
1254 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1255 f = fopen(buf, "r");
1259 len = fread(buf, 1, sizeof(buf) - 1, f);
1266 iflink = strtoul(buf, NULL, 0);
1267 ifindex = system_if_resolve(dev);
1268 if (!iflink || iflink == ifindex)
1271 devname = if_indextoname(iflink, buf);
1275 return device_get(devname, true);
1279 read_string_file(int dir_fd, const char *file, char *buf, int len)
1285 fd = openat(dir_fd, file, O_RDONLY);
1290 len = read(fd, buf, len - 1);
1294 } else if (len > 0) {
1297 c = strchr(buf, '\n');
1310 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1315 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1317 *val = strtoull(buf, NULL, 0);
1322 /* Assume advertised flags == supported flags */
1323 static const struct {
1326 } ethtool_link_modes[] = {
1327 { ADVERTISED_10baseT_Half, "10H" },
1328 { ADVERTISED_10baseT_Full, "10F" },
1329 { ADVERTISED_100baseT_Half, "100H" },
1330 { ADVERTISED_100baseT_Full, "100F" },
1331 { ADVERTISED_1000baseT_Half, "1000H" },
1332 { ADVERTISED_1000baseT_Full, "1000F" },
1335 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1338 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1339 if (mask & ethtool_link_modes[i].mask)
1340 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1345 system_if_force_external(const char *ifname)
1350 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1351 return stat(buf, &s) == 0;
1355 system_if_dump_info(struct device *dev, struct blob_buf *b)
1357 struct ethtool_cmd ecmd;
1363 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
1364 dir_fd = open(buf, O_DIRECTORY);
1366 memset(&ecmd, 0, sizeof(ecmd));
1367 memset(&ifr, 0, sizeof(ifr));
1368 strcpy(ifr.ifr_name, dev->ifname);
1369 ifr.ifr_data = (caddr_t) &ecmd;
1370 ecmd.cmd = ETHTOOL_GSET;
1372 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1373 c = blobmsg_open_array(b, "link-advertising");
1374 system_add_link_modes(b, ecmd.advertising);
1375 blobmsg_close_array(b, c);
1377 c = blobmsg_open_array(b, "link-supported");
1378 system_add_link_modes(b, ecmd.supported);
1379 blobmsg_close_array(b, c);
1381 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1382 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1383 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1384 blobmsg_add_string_buffer(b);
1392 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1394 const char *const counters[] = {
1395 "collisions", "rx_frame_errors", "tx_compressed",
1396 "multicast", "rx_length_errors", "tx_dropped",
1397 "rx_bytes", "rx_missed_errors", "tx_errors",
1398 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1399 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1400 "rx_dropped", "tx_aborted_errors", "tx_packets",
1401 "rx_errors", "tx_bytes", "tx_window_errors",
1402 "rx_fifo_errors", "tx_carrier_errors",
1409 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1410 stats_dir = open(buf, O_DIRECTORY);
1414 for (i = 0; i < ARRAY_SIZE(counters); i++)
1415 if (read_uint64_file(stats_dir, counters[i], &val))
1416 blobmsg_add_u64(b, counters[i], val);
1422 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1424 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1425 int alen = v4 ? 4 : 16;
1426 unsigned int flags = 0;
1427 struct ifaddrmsg ifa = {
1428 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1429 .ifa_prefixlen = addr->mask,
1430 .ifa_index = dev->ifindex,
1434 if (cmd == RTM_NEWADDR)
1435 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1437 msg = nlmsg_alloc_simple(cmd, flags);
1441 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1442 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1444 if (addr->broadcast)
1445 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1446 if (addr->point_to_point)
1447 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1449 time_t now = system_get_rtime();
1450 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1452 if (addr->preferred_until) {
1453 int64_t preferred = addr->preferred_until - now;
1456 else if (preferred > UINT32_MAX)
1457 preferred = UINT32_MAX;
1459 cinfo.ifa_prefered = preferred;
1462 if (addr->valid_until) {
1463 int64_t valid = addr->valid_until - now;
1466 else if (valid > UINT32_MAX)
1469 cinfo.ifa_valid = valid;
1472 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1474 if (cmd == RTM_NEWADDR && (addr->flags & DEVADDR_OFFLINK))
1475 nla_put_u32(msg, IFA_FLAGS, IFA_F_NOPREFIXROUTE);
1478 return system_rtnl_call(msg);
1481 int system_add_address(struct device *dev, struct device_addr *addr)
1483 return system_addr(dev, addr, RTM_NEWADDR);
1486 int system_del_address(struct device *dev, struct device_addr *addr)
1488 return system_addr(dev, addr, RTM_DELADDR);
1491 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1493 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1495 unsigned int flags = 0;
1498 have_gw = !!route->nexthop.in.s_addr;
1500 have_gw = route->nexthop.in6.s6_addr32[0] ||
1501 route->nexthop.in6.s6_addr32[1] ||
1502 route->nexthop.in6.s6_addr32[2] ||
1503 route->nexthop.in6.s6_addr32[3];
1505 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1506 ? route->table : RT_TABLE_MAIN;
1508 struct rtmsg rtm = {
1509 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1510 .rtm_dst_len = route->mask,
1511 .rtm_src_len = route->sourcemask,
1512 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1513 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
1514 .rtm_scope = RT_SCOPE_NOWHERE,
1515 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1516 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1520 if (cmd == RTM_NEWROUTE) {
1521 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1523 if (!dev) { // Add null-route
1524 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1525 rtm.rtm_type = RTN_UNREACHABLE;
1528 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1531 if (route->flags & DEVROUTE_TYPE) {
1532 rtm.rtm_type = route->type;
1533 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
1534 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
1535 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
1536 rtm.rtm_table = RT_TABLE_LOCAL;
1539 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT) {
1540 rtm.rtm_scope = RT_SCOPE_HOST;
1541 } else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
1542 rtm.rtm_type == RTN_ANYCAST) {
1543 rtm.rtm_scope = RT_SCOPE_LINK;
1544 } else if (rtm.rtm_type == RTN_BLACKHOLE || rtm.rtm_type == RTN_UNREACHABLE ||
1545 rtm.rtm_type == RTN_PROHIBIT || rtm.rtm_type == RTN_FAILED_POLICY) {
1546 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1551 msg = nlmsg_alloc_simple(cmd, flags);
1555 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1558 nla_put(msg, RTA_DST, alen, &route->addr);
1560 if (route->sourcemask) {
1561 if (rtm.rtm_family == AF_INET)
1562 nla_put(msg, RTA_PREFSRC, alen, &route->source);
1564 nla_put(msg, RTA_SRC, alen, &route->source);
1567 if (route->metric > 0)
1568 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1571 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1574 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1577 nla_put_u32(msg, RTA_TABLE, table);
1579 if (route->flags & DEVROUTE_MTU) {
1580 struct nlattr *metrics;
1582 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1583 goto nla_put_failure;
1585 nla_put_u32(msg, RTAX_MTU, route->mtu);
1587 nla_nest_end(msg, metrics);
1590 return system_rtnl_call(msg);
1597 int system_add_route(struct device *dev, struct device_route *route)
1599 return system_rt(dev, route, RTM_NEWROUTE);
1602 int system_del_route(struct device *dev, struct device_route *route)
1604 return system_rt(dev, route, RTM_DELROUTE);
1607 int system_flush_routes(void)
1609 const char *names[] = {
1610 "/proc/sys/net/ipv4/route/flush",
1611 "/proc/sys/net/ipv6/route/flush"
1615 for (i = 0; i < ARRAY_SIZE(names); i++) {
1616 fd = open(names[i], O_WRONLY);
1620 if (write(fd, "-1", 2)) {}
1626 bool system_resolve_rt_type(const char *type, unsigned int *id)
1628 return system_rtn_aton(type, id);
1631 bool system_resolve_rt_table(const char *name, unsigned int *id)
1635 unsigned int n, table = RT_TABLE_UNSPEC;
1637 /* first try to parse table as number */
1638 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1641 /* handle well known aliases */
1642 else if (!strcmp(name, "default"))
1643 table = RT_TABLE_DEFAULT;
1644 else if (!strcmp(name, "main"))
1645 table = RT_TABLE_MAIN;
1646 else if (!strcmp(name, "local"))
1647 table = RT_TABLE_LOCAL;
1648 else if (!strcmp(name, "prelocal"))
1649 table = RT_TABLE_PRELOCAL;
1651 /* try to look up name in /etc/iproute2/rt_tables */
1652 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1654 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1656 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1659 n = strtoul(e, NULL, 10);
1660 e = strtok(NULL, " \t\n");
1662 if (e && !strcmp(e, name))
1672 if (table == RT_TABLE_UNSPEC)
1679 bool system_is_default_rt_table(unsigned int id)
1681 return (id == RT_TABLE_MAIN);
1684 bool system_resolve_rpfilter(const char *filter, unsigned int *id)
1689 if (!strcmp(filter, "strict"))
1691 else if (!strcmp(filter, "loose"))
1694 n = strtoul(filter, &e, 0);
1695 if (*e || e == filter || n > 2)
1703 static int system_iprule(struct iprule *rule, int cmd)
1705 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1708 struct rtmsg rtm = {
1709 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1710 .rtm_protocol = RTPROT_STATIC,
1711 .rtm_scope = RT_SCOPE_UNIVERSE,
1712 .rtm_table = RT_TABLE_UNSPEC,
1713 .rtm_type = RTN_UNSPEC,
1717 if (cmd == RTM_NEWRULE) {
1718 rtm.rtm_type = RTN_UNICAST;
1719 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1723 rtm.rtm_flags |= FIB_RULE_INVERT;
1725 if (rule->flags & IPRULE_SRC)
1726 rtm.rtm_src_len = rule->src_mask;
1728 if (rule->flags & IPRULE_DEST)
1729 rtm.rtm_dst_len = rule->dest_mask;
1731 if (rule->flags & IPRULE_TOS)
1732 rtm.rtm_tos = rule->tos;
1734 if (rule->flags & IPRULE_LOOKUP) {
1735 if (rule->lookup < 256)
1736 rtm.rtm_table = rule->lookup;
1739 if (rule->flags & IPRULE_ACTION)
1740 rtm.rtm_type = rule->action;
1741 else if (rule->flags & IPRULE_GOTO)
1742 rtm.rtm_type = FR_ACT_GOTO;
1743 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1744 rtm.rtm_type = FR_ACT_NOP;
1746 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1751 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1753 if (rule->flags & IPRULE_IN)
1754 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1756 if (rule->flags & IPRULE_OUT)
1757 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1759 if (rule->flags & IPRULE_SRC)
1760 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1762 if (rule->flags & IPRULE_DEST)
1763 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1765 if (rule->flags & IPRULE_PRIORITY)
1766 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1767 else if (cmd == RTM_NEWRULE)
1768 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1770 if (rule->flags & IPRULE_FWMARK)
1771 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1773 if (rule->flags & IPRULE_FWMASK)
1774 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1776 if (rule->flags & IPRULE_LOOKUP) {
1777 if (rule->lookup >= 256)
1778 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1781 if (rule->flags & IPRULE_GOTO)
1782 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1784 return system_rtnl_call(msg);
1787 int system_add_iprule(struct iprule *rule)
1789 return system_iprule(rule, RTM_NEWRULE);
1792 int system_del_iprule(struct iprule *rule)
1794 return system_iprule(rule, RTM_DELRULE);
1797 int system_flush_iprules(void)
1802 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1803 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1805 memset(&rule, 0, sizeof(rule));
1808 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1811 rule.lookup = RT_TABLE_PRELOCAL;
1812 rv |= system_iprule(&rule, RTM_NEWRULE);
1815 rule.lookup = RT_TABLE_LOCAL;
1816 rv |= system_iprule(&rule, RTM_NEWRULE);
1818 rule.priority = 32766;
1819 rule.lookup = RT_TABLE_MAIN;
1820 rv |= system_iprule(&rule, RTM_NEWRULE);
1822 rule.priority = 32767;
1823 rule.lookup = RT_TABLE_DEFAULT;
1824 rv |= system_iprule(&rule, RTM_NEWRULE);
1827 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1830 rule.lookup = RT_TABLE_PRELOCAL;
1831 rv |= system_iprule(&rule, RTM_NEWRULE);
1834 rule.lookup = RT_TABLE_LOCAL;
1835 rv |= system_iprule(&rule, RTM_NEWRULE);
1837 rule.priority = 32766;
1838 rule.lookup = RT_TABLE_MAIN;
1839 rv |= system_iprule(&rule, RTM_NEWRULE);
1844 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1846 return system_rtn_aton(action, id);
1849 time_t system_get_rtime(void)
1854 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1857 if (gettimeofday(&tv, NULL) == 0)
1864 #define IP_DF 0x4000
1867 static int tunnel_ioctl(const char *name, int cmd, void *p)
1871 memset(&ifr, 0, sizeof(ifr));
1872 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1873 ifr.ifr_ifru.ifru_data = p;
1874 return ioctl(sock_ioctl, cmd, &ifr);
1877 #ifdef IFLA_IPTUN_MAX
1878 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
1879 static int system_add_gre_tunnel(const char *name, const char *kind,
1880 const unsigned int link, struct blob_attr **tb, bool v6)
1883 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
1884 struct blob_attr *cur;
1885 uint32_t ikey = 0, okey = 0, flags = 0, flowinfo = 0;
1886 uint16_t iflags = 0, oflags = 0;
1888 int ret = 0, ttl = 64;
1890 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
1894 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
1895 nla_put_string(nlm, IFLA_IFNAME, name);
1897 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
1903 nla_put_string(nlm, IFLA_INFO_KIND, kind);
1904 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
1911 nla_put_u32(nlm, IFLA_GRE_LINK, link);
1913 if ((cur = tb[TUNNEL_ATTR_TTL]))
1914 ttl = blobmsg_get_u32(cur);
1916 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
1918 if ((cur = tb[TUNNEL_ATTR_TOS])) {
1919 char *str = blobmsg_get_string(cur);
1920 if (strcmp(str, "inherit")) {
1923 if (!system_tos_aton(str, &uval)) {
1929 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
1934 flags |= IP6_TNL_F_USE_ORIG_TCLASS;
1940 if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) {
1941 uint8_t icsum, ocsum, iseqno, oseqno;
1942 if (sscanf(blobmsg_get_string(cur), "%u,%u,%hhu,%hhu,%hhu,%hhu",
1943 &ikey, &okey, &icsum, &ocsum, &iseqno, &oseqno) < 6) {
1968 struct in6_addr in6buf;
1969 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1970 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1974 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
1977 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
1978 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1982 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
1984 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, 4);
1987 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
1990 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags);
1992 struct in_addr inbuf;
1995 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1996 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2000 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
2003 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2004 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2008 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
2010 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
2012 okey = inbuf.s_addr;
2017 ikey = inbuf.s_addr;
2023 if ((cur = tb[TUNNEL_ATTR_DF]))
2024 set_df = blobmsg_get_bool(cur);
2026 /* ttl !=0 and nopmtudisc are incompatible */
2027 if (ttl && !set_df) {
2032 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
2034 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
2038 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
2041 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
2044 nla_put_u32(nlm, IFLA_GRE_OKEY, okey);
2047 nla_put_u32(nlm, IFLA_GRE_IKEY, ikey);
2049 nla_nest_end(nlm, infodata);
2050 nla_nest_end(nlm, linkinfo);
2052 return system_rtnl_call(nlm);
2060 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
2062 struct blob_attr *cur;
2064 struct ip_tunnel_parm p = {
2073 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
2074 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
2077 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
2078 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
2081 if ((cur = tb[TUNNEL_ATTR_DF]))
2082 set_df = blobmsg_get_bool(cur);
2084 if ((cur = tb[TUNNEL_ATTR_TTL]))
2085 p.iph.ttl = blobmsg_get_u32(cur);
2087 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2088 char *str = blobmsg_get_string(cur);
2089 if (strcmp(str, "inherit")) {
2092 if (!system_tos_aton(str, &uval))
2100 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
2101 /* ttl !=0 and nopmtudisc are incompatible */
2102 if (p.iph.ttl && p.iph.frag_off == 0)
2105 strncpy(p.name, name, sizeof(p.name));
2107 switch (p.iph.protocol) {
2109 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
2111 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
2118 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
2120 struct blob_attr *cur;
2123 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2125 str = blobmsg_data(cur);
2127 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
2128 !strcmp(str, "greip6") || !strcmp(str, "gretapip6"))
2129 return system_link_del(name);
2131 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
2134 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
2136 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2138 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2139 blob_data(attr), blob_len(attr));
2141 return __system_del_ip_tunnel(name, tb);
2144 int system_update_ipv6_mtu(struct device *dev, int mtu)
2148 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
2151 int fd = open(buf, O_RDWR);
2152 ssize_t len = read(fd, buf, sizeof(buf) - 1);
2159 if (!mtu || ret <= mtu)
2162 lseek(fd, 0, SEEK_SET);
2163 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) <= 0)
2171 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
2173 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2174 struct blob_attr *cur;
2177 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2178 blob_data(attr), blob_len(attr));
2180 __system_del_ip_tunnel(name, tb);
2182 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2184 str = blobmsg_data(cur);
2186 unsigned int ttl = 0;
2187 if ((cur = tb[TUNNEL_ATTR_TTL])) {
2188 ttl = blobmsg_get_u32(cur);
2193 unsigned int link = 0;
2194 if ((cur = tb[TUNNEL_ATTR_LINK])) {
2195 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
2199 if (iface->l3_dev.dev)
2200 link = iface->l3_dev.dev->ifindex;
2203 if (!strcmp(str, "sit")) {
2204 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
2208 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
2210 struct ip_tunnel_6rd p6;
2212 memset(&p6, 0, sizeof(p6));
2214 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
2215 &p6.prefix, &mask) || mask > 128)
2217 p6.prefixlen = mask;
2219 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
2220 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
2221 &p6.relay_prefix, &mask) || mask > 32)
2223 p6.relay_prefixlen = mask;
2226 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
2227 __system_del_ip_tunnel(name, tb);
2232 #ifdef IFLA_IPTUN_MAX
2233 } else if (!strcmp(str, "ipip6")) {
2234 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2235 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2236 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2242 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2243 nla_put_string(nlm, IFLA_IFNAME, name);
2246 nla_put_u32(nlm, IFLA_LINK, link);
2248 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2253 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2254 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2261 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2263 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2264 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2265 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
2267 struct in6_addr in6buf;
2268 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2269 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2273 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2276 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2277 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2281 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2284 #ifdef IFLA_IPTUN_FMR_MAX
2285 if ((cur = tb[TUNNEL_ATTR_FMRS])) {
2286 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2288 struct blob_attr *fmr;
2289 unsigned rem, fmrcnt = 0;
2290 blobmsg_for_each_attr(fmr, cur, rem) {
2291 if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
2294 unsigned ip4len, ip6len, ealen, offset = 6;
2298 if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
2299 ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) {
2304 struct in6_addr ip6prefix;
2305 struct in_addr ip4prefix;
2306 if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
2307 inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) {
2312 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2314 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2315 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2316 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2317 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2318 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2319 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2321 nla_nest_end(nlm, rule);
2324 nla_nest_end(nlm, fmrs);
2328 nla_nest_end(nlm, infodata);
2329 nla_nest_end(nlm, linkinfo);
2331 return system_rtnl_call(nlm);
2335 } else if (!strcmp(str, "greip")) {
2336 return system_add_gre_tunnel(name, "gre", link, tb, false);
2337 } else if (!strcmp(str, "gretapip")) {
2338 return system_add_gre_tunnel(name, "gretap", link, tb, false);
2339 } else if (!strcmp(str, "greip6")) {
2340 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
2341 } else if (!strcmp(str, "gretapip6")) {
2342 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
2344 } else if (!strcmp(str, "ipip")) {
2345 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);