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_link.h>
34 #include <linux/if_vlan.h>
35 #include <linux/if_bridge.h>
36 #include <linux/if_tunnel.h>
37 #include <linux/ip6_tunnel.h>
38 #include <linux/ethtool.h>
39 #include <linux/fib_rules.h>
40 #include <linux/version.h>
42 #ifndef RTN_FAILED_POLICY
43 #define RTN_FAILED_POLICY 12
46 #ifndef RT_TABLE_PRELOCAL
47 #define RT_TABLE_PRELOCAL 128
56 #include <netlink/msg.h>
57 #include <netlink/attr.h>
58 #include <netlink/socket.h>
59 #include <libubox/uloop.h>
66 struct uloop_fd uloop;
71 static int sock_ioctl = -1;
72 static struct nl_sock *sock_rtnl = NULL;
74 static int cb_rtnl_event(struct nl_msg *msg, void *arg);
75 static void handle_hotplug_event(struct uloop_fd *u, unsigned int events);
77 static char dev_buf[256];
80 handler_nl_event(struct uloop_fd *u, unsigned int events)
82 struct event_socket *ev = container_of(u, struct event_socket, uloop);
84 socklen_t errlen = sizeof(err);
87 nl_recvmsgs_default(ev->sock);
91 if (getsockopt(u->fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen))
96 // Increase rx buffer size on netlink socket
98 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
101 // Request full dump since some info got dropped
102 struct rtgenmsg msg = { .rtgen_family = AF_UNSPEC };
103 nl_send_simple(ev->sock, RTM_GETLINK, NLM_F_DUMP, &msg, sizeof(msg));
113 uloop_fd_delete(&ev->uloop);
117 static struct nl_sock *
118 create_socket(int protocol, int groups)
120 struct nl_sock *sock;
122 sock = nl_socket_alloc();
127 nl_join_groups(sock, groups);
129 if (nl_connect(sock, protocol))
136 create_raw_event_socket(struct event_socket *ev, int protocol, int groups,
137 uloop_fd_handler cb, int flags)
139 ev->sock = create_socket(protocol, groups);
143 ev->uloop.fd = nl_socket_get_fd(ev->sock);
145 if (uloop_fd_add(&ev->uloop, ULOOP_READ|flags))
152 create_event_socket(struct event_socket *ev, int protocol,
153 int (*cb)(struct nl_msg *msg, void *arg))
155 if (!create_raw_event_socket(ev, protocol, 0, handler_nl_event, ULOOP_ERROR_CB))
158 // Install the valid custom callback handler
159 nl_socket_modify_cb(ev->sock, NL_CB_VALID, NL_CB_CUSTOM, cb, NULL);
161 // Disable sequence number checking on event sockets
162 nl_socket_disable_seq_check(ev->sock);
164 // Increase rx buffer size to 65K on event sockets
166 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
173 system_rtn_aton(const char *src, unsigned int *dst)
178 if (!strcmp(src, "local"))
180 else if (!strcmp(src, "nat"))
182 else if (!strcmp(src, "broadcast"))
184 else if (!strcmp(src, "anycast"))
186 else if (!strcmp(src, "multicast"))
188 else if (!strcmp(src, "prohibit"))
190 else if (!strcmp(src, "unreachable"))
192 else if (!strcmp(src, "blackhole"))
194 else if (!strcmp(src, "xresolve"))
196 else if (!strcmp(src, "unicast"))
198 else if (!strcmp(src, "throw"))
200 else if (!strcmp(src, "failed_policy"))
201 n = RTN_FAILED_POLICY;
203 n = strtoul(src, &e, 0);
204 if (!e || *e || e == src || n > 255)
213 system_tos_aton(const char *src, unsigned *dst)
217 *dst = strtoul(src, &e, 16);
218 if (e == src || *e || *dst > 255)
224 int system_init(void)
226 static struct event_socket rtnl_event;
227 static struct event_socket hotplug_event;
229 sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0);
230 system_fd_set_cloexec(sock_ioctl);
232 // Prepare socket for routing / address control
233 sock_rtnl = create_socket(NETLINK_ROUTE, 0);
237 if (!create_event_socket(&rtnl_event, NETLINK_ROUTE, cb_rtnl_event))
240 if (!create_raw_event_socket(&hotplug_event, NETLINK_KOBJECT_UEVENT, 1,
241 handle_hotplug_event, 0))
244 // Receive network link events form kernel
245 nl_socket_add_membership(rtnl_event.sock, RTNLGRP_LINK);
250 static void system_set_sysctl(const char *path, const char *val)
254 fd = open(path, O_WRONLY);
258 if (write(fd, val, strlen(val))) {}
262 static void system_set_dev_sysctl(const char *path, const char *device, const char *val)
264 snprintf(dev_buf, sizeof(dev_buf), path, device);
265 system_set_sysctl(dev_buf, val);
268 static void system_set_disable_ipv6(struct device *dev, const char *val)
270 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val);
273 static void system_set_rpfilter(struct device *dev, const char *val)
275 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter", dev->ifname, val);
278 static void system_set_acceptlocal(struct device *dev, const char *val)
280 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local", dev->ifname, val);
283 static void system_set_igmpversion(struct device *dev, const char *val)
285 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version", dev->ifname, val);
288 static void system_set_mldversion(struct device *dev, const char *val)
290 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version", dev->ifname, val);
293 static void system_set_neigh4reachabletime(struct device *dev, const char *val)
295 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms", dev->ifname, val);
298 static void system_set_neigh6reachabletime(struct device *dev, const char *val)
300 system_set_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms", dev->ifname, val);
303 static int system_get_sysctl(const char *path, char *buf, const size_t buf_sz)
305 int fd = -1, ret = -1;
307 fd = open(path, O_RDONLY);
311 ssize_t len = read(fd, buf, buf_sz - 1);
325 system_get_dev_sysctl(const char *path, const char *device, char *buf, const size_t buf_sz)
327 snprintf(dev_buf, sizeof(dev_buf), path, device);
328 return system_get_sysctl(dev_buf, buf, buf_sz);
331 static int system_get_disable_ipv6(struct device *dev, char *buf, const size_t buf_sz)
333 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6",
334 dev->ifname, buf, buf_sz);
337 static int system_get_rpfilter(struct device *dev, char *buf, const size_t buf_sz)
339 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter",
340 dev->ifname, buf, buf_sz);
343 static int system_get_acceptlocal(struct device *dev, char *buf, const size_t buf_sz)
345 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local",
346 dev->ifname, buf, buf_sz);
349 static int system_get_igmpversion(struct device *dev, char *buf, const size_t buf_sz)
351 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version",
352 dev->ifname, buf, buf_sz);
355 static int system_get_mldversion(struct device *dev, char *buf, const size_t buf_sz)
357 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version",
358 dev->ifname, buf, buf_sz);
361 static int system_get_neigh4reachabletime(struct device *dev, char *buf, const size_t buf_sz)
363 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms",
364 dev->ifname, buf, buf_sz);
367 static int system_get_neigh6reachabletime(struct device *dev, char *buf, const size_t buf_sz)
369 return system_get_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms",
370 dev->ifname, buf, buf_sz);
373 // Evaluate netlink messages
374 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
376 struct nlmsghdr *nh = nlmsg_hdr(msg);
377 struct ifinfomsg *ifi = NLMSG_DATA(nh);
378 struct nlattr *nla[__IFLA_MAX];
382 if (nh->nlmsg_type != RTM_NEWLINK)
385 nlmsg_parse(nh, sizeof(*ifi), 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);
1475 return system_rtnl_call(msg);
1478 int system_add_address(struct device *dev, struct device_addr *addr)
1480 return system_addr(dev, addr, RTM_NEWADDR);
1483 int system_del_address(struct device *dev, struct device_addr *addr)
1485 return system_addr(dev, addr, RTM_DELADDR);
1488 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1490 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1492 unsigned int flags = 0;
1495 have_gw = !!route->nexthop.in.s_addr;
1497 have_gw = route->nexthop.in6.s6_addr32[0] ||
1498 route->nexthop.in6.s6_addr32[1] ||
1499 route->nexthop.in6.s6_addr32[2] ||
1500 route->nexthop.in6.s6_addr32[3];
1502 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1503 ? route->table : RT_TABLE_MAIN;
1505 struct rtmsg rtm = {
1506 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1507 .rtm_dst_len = route->mask,
1508 .rtm_src_len = route->sourcemask,
1509 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1510 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
1511 .rtm_scope = RT_SCOPE_NOWHERE,
1512 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1513 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1517 if (cmd == RTM_NEWROUTE) {
1518 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1520 if (!dev) { // Add null-route
1521 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1522 rtm.rtm_type = RTN_UNREACHABLE;
1525 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1528 if (route->flags & DEVROUTE_TYPE) {
1529 rtm.rtm_type = route->type;
1530 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
1531 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
1532 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
1533 rtm.rtm_table = RT_TABLE_LOCAL;
1536 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT) {
1537 rtm.rtm_scope = RT_SCOPE_HOST;
1538 } else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
1539 rtm.rtm_type == RTN_ANYCAST) {
1540 rtm.rtm_scope = RT_SCOPE_LINK;
1541 } else if (rtm.rtm_type == RTN_BLACKHOLE || rtm.rtm_type == RTN_UNREACHABLE ||
1542 rtm.rtm_type == RTN_PROHIBIT || rtm.rtm_type == RTN_FAILED_POLICY) {
1543 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1548 msg = nlmsg_alloc_simple(cmd, flags);
1552 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1555 nla_put(msg, RTA_DST, alen, &route->addr);
1557 if (route->sourcemask) {
1558 if (rtm.rtm_family == AF_INET)
1559 nla_put(msg, RTA_PREFSRC, alen, &route->source);
1561 nla_put(msg, RTA_SRC, alen, &route->source);
1564 if (route->metric > 0)
1565 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1568 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1571 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1574 nla_put_u32(msg, RTA_TABLE, table);
1576 if (route->flags & DEVROUTE_MTU) {
1577 struct nlattr *metrics;
1579 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1580 goto nla_put_failure;
1582 nla_put_u32(msg, RTAX_MTU, route->mtu);
1584 nla_nest_end(msg, metrics);
1587 return system_rtnl_call(msg);
1594 int system_add_route(struct device *dev, struct device_route *route)
1596 return system_rt(dev, route, RTM_NEWROUTE);
1599 int system_del_route(struct device *dev, struct device_route *route)
1601 return system_rt(dev, route, RTM_DELROUTE);
1604 int system_flush_routes(void)
1606 const char *names[] = {
1607 "/proc/sys/net/ipv4/route/flush",
1608 "/proc/sys/net/ipv6/route/flush"
1612 for (i = 0; i < ARRAY_SIZE(names); i++) {
1613 fd = open(names[i], O_WRONLY);
1617 if (write(fd, "-1", 2)) {}
1623 bool system_resolve_rt_type(const char *type, unsigned int *id)
1625 return system_rtn_aton(type, id);
1628 bool system_resolve_rt_table(const char *name, unsigned int *id)
1632 unsigned int n, table = RT_TABLE_UNSPEC;
1634 /* first try to parse table as number */
1635 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1638 /* handle well known aliases */
1639 else if (!strcmp(name, "default"))
1640 table = RT_TABLE_DEFAULT;
1641 else if (!strcmp(name, "main"))
1642 table = RT_TABLE_MAIN;
1643 else if (!strcmp(name, "local"))
1644 table = RT_TABLE_LOCAL;
1645 else if (!strcmp(name, "prelocal"))
1646 table = RT_TABLE_PRELOCAL;
1648 /* try to look up name in /etc/iproute2/rt_tables */
1649 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1651 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1653 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1656 n = strtoul(e, NULL, 10);
1657 e = strtok(NULL, " \t\n");
1659 if (e && !strcmp(e, name))
1669 if (table == RT_TABLE_UNSPEC)
1676 bool system_is_default_rt_table(unsigned int id)
1678 return (id == RT_TABLE_MAIN);
1681 bool system_resolve_rpfilter(const char *filter, unsigned int *id)
1686 if (!strcmp(filter, "strict"))
1688 else if (!strcmp(filter, "loose"))
1691 n = strtoul(filter, &e, 0);
1692 if (*e || e == filter || n > 2)
1700 static int system_iprule(struct iprule *rule, int cmd)
1702 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1705 struct rtmsg rtm = {
1706 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1707 .rtm_protocol = RTPROT_STATIC,
1708 .rtm_scope = RT_SCOPE_UNIVERSE,
1709 .rtm_table = RT_TABLE_UNSPEC,
1710 .rtm_type = RTN_UNSPEC,
1714 if (cmd == RTM_NEWRULE) {
1715 rtm.rtm_type = RTN_UNICAST;
1716 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1720 rtm.rtm_flags |= FIB_RULE_INVERT;
1722 if (rule->flags & IPRULE_SRC)
1723 rtm.rtm_src_len = rule->src_mask;
1725 if (rule->flags & IPRULE_DEST)
1726 rtm.rtm_dst_len = rule->dest_mask;
1728 if (rule->flags & IPRULE_TOS)
1729 rtm.rtm_tos = rule->tos;
1731 if (rule->flags & IPRULE_LOOKUP) {
1732 if (rule->lookup < 256)
1733 rtm.rtm_table = rule->lookup;
1736 if (rule->flags & IPRULE_ACTION)
1737 rtm.rtm_type = rule->action;
1738 else if (rule->flags & IPRULE_GOTO)
1739 rtm.rtm_type = FR_ACT_GOTO;
1740 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1741 rtm.rtm_type = FR_ACT_NOP;
1743 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1748 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1750 if (rule->flags & IPRULE_IN)
1751 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1753 if (rule->flags & IPRULE_OUT)
1754 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1756 if (rule->flags & IPRULE_SRC)
1757 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1759 if (rule->flags & IPRULE_DEST)
1760 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1762 if (rule->flags & IPRULE_PRIORITY)
1763 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1764 else if (cmd == RTM_NEWRULE)
1765 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1767 if (rule->flags & IPRULE_FWMARK)
1768 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1770 if (rule->flags & IPRULE_FWMASK)
1771 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1773 if (rule->flags & IPRULE_LOOKUP) {
1774 if (rule->lookup >= 256)
1775 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1778 if (rule->flags & IPRULE_GOTO)
1779 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1781 return system_rtnl_call(msg);
1784 int system_add_iprule(struct iprule *rule)
1786 return system_iprule(rule, RTM_NEWRULE);
1789 int system_del_iprule(struct iprule *rule)
1791 return system_iprule(rule, RTM_DELRULE);
1794 int system_flush_iprules(void)
1799 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1800 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1802 memset(&rule, 0, sizeof(rule));
1805 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1808 rule.lookup = RT_TABLE_PRELOCAL;
1809 rv |= system_iprule(&rule, RTM_NEWRULE);
1812 rule.lookup = RT_TABLE_LOCAL;
1813 rv |= system_iprule(&rule, RTM_NEWRULE);
1815 rule.priority = 32766;
1816 rule.lookup = RT_TABLE_MAIN;
1817 rv |= system_iprule(&rule, RTM_NEWRULE);
1819 rule.priority = 32767;
1820 rule.lookup = RT_TABLE_DEFAULT;
1821 rv |= system_iprule(&rule, RTM_NEWRULE);
1824 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1827 rule.lookup = RT_TABLE_PRELOCAL;
1828 rv |= system_iprule(&rule, RTM_NEWRULE);
1831 rule.lookup = RT_TABLE_LOCAL;
1832 rv |= system_iprule(&rule, RTM_NEWRULE);
1834 rule.priority = 32766;
1835 rule.lookup = RT_TABLE_MAIN;
1836 rv |= system_iprule(&rule, RTM_NEWRULE);
1841 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1843 return system_rtn_aton(action, id);
1846 time_t system_get_rtime(void)
1851 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1854 if (gettimeofday(&tv, NULL) == 0)
1861 #define IP_DF 0x4000
1864 static int tunnel_ioctl(const char *name, int cmd, void *p)
1868 memset(&ifr, 0, sizeof(ifr));
1869 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1870 ifr.ifr_ifru.ifru_data = p;
1871 return ioctl(sock_ioctl, cmd, &ifr);
1874 #ifdef IFLA_IPTUN_MAX
1875 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
1876 static int system_add_gre_tunnel(const char *name, const char *kind,
1877 const unsigned int link, struct blob_attr **tb, bool v6)
1880 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
1881 struct blob_attr *cur;
1882 uint32_t ikey = 0, okey = 0, flags = 0, flowinfo = 0;
1883 uint16_t iflags = 0, oflags = 0;
1885 int ret = 0, ttl = 64;
1887 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
1891 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
1892 nla_put_string(nlm, IFLA_IFNAME, name);
1894 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
1900 nla_put_string(nlm, IFLA_INFO_KIND, kind);
1901 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
1908 nla_put_u32(nlm, IFLA_GRE_LINK, link);
1910 if ((cur = tb[TUNNEL_ATTR_TTL]))
1911 ttl = blobmsg_get_u32(cur);
1913 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
1915 if ((cur = tb[TUNNEL_ATTR_TOS])) {
1916 char *str = blobmsg_get_string(cur);
1917 if (strcmp(str, "inherit")) {
1920 if (!system_tos_aton(str, &uval)) {
1926 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
1931 flags |= IP6_TNL_F_USE_ORIG_TCLASS;
1937 if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) {
1938 uint8_t icsum, ocsum, iseqno, oseqno;
1939 if (sscanf(blobmsg_get_string(cur), "%u,%u,%hhu,%hhu,%hhu,%hhu",
1940 &ikey, &okey, &icsum, &ocsum, &iseqno, &oseqno) < 6) {
1965 struct in6_addr in6buf;
1966 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1967 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1971 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
1974 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
1975 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1979 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
1981 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, 4);
1984 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
1987 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags);
1989 struct in_addr inbuf;
1992 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1993 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
1997 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
2000 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2001 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2005 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
2007 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
2009 okey = inbuf.s_addr;
2014 ikey = inbuf.s_addr;
2020 if ((cur = tb[TUNNEL_ATTR_DF]))
2021 set_df = blobmsg_get_bool(cur);
2023 /* ttl !=0 and nopmtudisc are incompatible */
2024 if (ttl && !set_df) {
2029 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
2031 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
2035 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
2038 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
2041 nla_put_u32(nlm, IFLA_GRE_OKEY, okey);
2044 nla_put_u32(nlm, IFLA_GRE_IKEY, ikey);
2046 nla_nest_end(nlm, infodata);
2047 nla_nest_end(nlm, linkinfo);
2049 return system_rtnl_call(nlm);
2057 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
2059 struct blob_attr *cur;
2061 struct ip_tunnel_parm p = {
2070 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
2071 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
2074 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
2075 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
2078 if ((cur = tb[TUNNEL_ATTR_DF]))
2079 set_df = blobmsg_get_bool(cur);
2081 if ((cur = tb[TUNNEL_ATTR_TTL]))
2082 p.iph.ttl = blobmsg_get_u32(cur);
2084 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2085 char *str = blobmsg_get_string(cur);
2086 if (strcmp(str, "inherit")) {
2089 if (!system_tos_aton(str, &uval))
2097 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
2098 /* ttl !=0 and nopmtudisc are incompatible */
2099 if (p.iph.ttl && p.iph.frag_off == 0)
2102 strncpy(p.name, name, sizeof(p.name));
2104 switch (p.iph.protocol) {
2106 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
2108 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
2115 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
2117 struct blob_attr *cur;
2120 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2122 str = blobmsg_data(cur);
2124 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
2125 !strcmp(str, "greip6") || !strcmp(str, "gretapip6"))
2126 return system_link_del(name);
2128 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
2131 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
2133 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2135 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2136 blob_data(attr), blob_len(attr));
2138 return __system_del_ip_tunnel(name, tb);
2141 int system_update_ipv6_mtu(struct device *dev, int mtu)
2145 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
2148 int fd = open(buf, O_RDWR);
2149 ssize_t len = read(fd, buf, sizeof(buf) - 1);
2156 if (!mtu || ret <= mtu)
2159 lseek(fd, 0, SEEK_SET);
2160 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) <= 0)
2168 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
2170 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2171 struct blob_attr *cur;
2174 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2175 blob_data(attr), blob_len(attr));
2177 __system_del_ip_tunnel(name, tb);
2179 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2181 str = blobmsg_data(cur);
2183 unsigned int ttl = 0;
2184 if ((cur = tb[TUNNEL_ATTR_TTL])) {
2185 ttl = blobmsg_get_u32(cur);
2190 unsigned int link = 0;
2191 if ((cur = tb[TUNNEL_ATTR_LINK])) {
2192 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
2196 if (iface->l3_dev.dev)
2197 link = iface->l3_dev.dev->ifindex;
2200 if (!strcmp(str, "sit")) {
2201 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
2205 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
2207 struct ip_tunnel_6rd p6;
2209 memset(&p6, 0, sizeof(p6));
2211 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
2212 &p6.prefix, &mask) || mask > 128)
2214 p6.prefixlen = mask;
2216 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
2217 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
2218 &p6.relay_prefix, &mask) || mask > 32)
2220 p6.relay_prefixlen = mask;
2223 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
2224 __system_del_ip_tunnel(name, tb);
2229 #ifdef IFLA_IPTUN_MAX
2230 } else if (!strcmp(str, "ipip6")) {
2231 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2232 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2233 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2239 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2240 nla_put_string(nlm, IFLA_IFNAME, name);
2243 nla_put_u32(nlm, IFLA_LINK, link);
2245 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2250 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2251 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2258 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2260 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2261 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2262 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
2264 struct in6_addr in6buf;
2265 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2266 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2270 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2273 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2274 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2278 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2281 #ifdef IFLA_IPTUN_FMR_MAX
2282 if ((cur = tb[TUNNEL_ATTR_FMRS])) {
2283 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2285 struct blob_attr *fmr;
2286 unsigned rem, fmrcnt = 0;
2287 blobmsg_for_each_attr(fmr, cur, rem) {
2288 if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
2291 unsigned ip4len, ip6len, ealen, offset = 6;
2295 if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
2296 ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) {
2301 struct in6_addr ip6prefix;
2302 struct in_addr ip4prefix;
2303 if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
2304 inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) {
2309 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2311 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2312 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2313 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2314 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2315 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2316 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2318 nla_nest_end(nlm, rule);
2321 nla_nest_end(nlm, fmrs);
2325 nla_nest_end(nlm, infodata);
2326 nla_nest_end(nlm, linkinfo);
2328 return system_rtnl_call(nlm);
2332 } else if (!strcmp(str, "greip")) {
2333 return system_add_gre_tunnel(name, "gre", link, tb, false);
2334 } else if (!strcmp(str, "gretapip")) {
2335 return system_add_gre_tunnel(name, "gretap", link, tb, false);
2336 } else if (!strcmp(str, "greip6")) {
2337 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
2338 } else if (!strcmp(str, "gretapip6")) {
2339 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
2341 } else if (!strcmp(str, "ipip")) {
2342 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);