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 nlattr *nla[__IFLA_MAX];
381 if (nh->nlmsg_type != RTM_NEWLINK)
384 nlmsg_parse(nh, sizeof(struct ifinfomsg), nla, __IFLA_MAX - 1, NULL);
385 if (!nla[IFLA_IFNAME])
388 struct device *dev = device_get(nla_data(nla[IFLA_IFNAME]), false);
389 if (!dev || dev->type->keep_link_status)
392 if (!system_get_dev_sysctl("/sys/class/net/%s/carrier", dev->ifname, buf, sizeof(buf)))
393 link_state = strtoul(buf, NULL, 0);
395 device_set_link(dev, link_state ? true : false);
402 handle_hotplug_msg(char *data, int size)
404 const char *subsystem = NULL, *interface = NULL;
405 char *cur, *end, *sep;
410 if (!strncmp(data, "add@", 4))
412 else if (!strncmp(data, "remove@", 7))
417 skip = strlen(data) + 1;
420 for (cur = data + skip; cur < end; cur += skip) {
421 skip = strlen(cur) + 1;
423 sep = strchr(cur, '=');
428 if (!strcmp(cur, "INTERFACE"))
430 else if (!strcmp(cur, "SUBSYSTEM")) {
432 if (strcmp(subsystem, "net") != 0)
435 if (subsystem && interface)
441 dev = device_get(interface, false);
445 if (dev->type != &simple_device_type)
448 if (add && system_if_force_external(dev->ifname))
451 device_set_present(dev, add);
455 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
457 struct event_socket *ev = container_of(u, struct event_socket, uloop);
458 struct sockaddr_nl nla;
459 unsigned char *buf = NULL;
462 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
464 handle_hotplug_msg((char *) buf, size);
470 static int system_rtnl_call(struct nl_msg *msg)
474 ret = nl_send_auto_complete(sock_rtnl, msg);
480 return nl_wait_for_ack(sock_rtnl);
483 int system_bridge_delbr(struct device *bridge)
485 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
488 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
492 memset(&ifr, 0, sizeof(ifr));
494 ifr.ifr_ifindex = dev->ifindex;
497 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
498 return ioctl(sock_ioctl, cmd, &ifr);
501 static bool system_is_bridge(const char *name, char *buf, int buflen)
505 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
506 if (stat(buf, &st) < 0)
512 static char *system_get_bridge(const char *name, char *buf, int buflen)
518 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
519 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
523 len = readlink(gl.gl_pathv[0], buf, buflen);
531 path = strrchr(buf, '/');
538 static void system_bridge_set_wireless(const char *bridge, const char *dev)
540 snprintf(dev_buf, sizeof(dev_buf),
541 "/sys/devices/virtual/net/%s/brif/%s/multicast_to_unicast",
543 system_set_sysctl(dev_buf, "1");
546 int system_bridge_addif(struct device *bridge, struct device *dev)
551 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
552 if (!oldbr || strcmp(oldbr, bridge->ifname) != 0)
553 ret = system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
556 system_bridge_set_wireless(bridge->ifname, dev->ifname);
561 int system_bridge_delif(struct device *bridge, struct device *dev)
563 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
566 int system_if_resolve(struct device *dev)
569 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
570 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
571 return ifr.ifr_ifindex;
576 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
580 memset(&ifr, 0, sizeof(ifr));
581 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
582 ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
583 ifr.ifr_flags |= add;
584 ifr.ifr_flags &= ~rem;
585 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
597 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
599 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
601 return ifa->ifa_index == ifindex;
604 static bool check_route(struct nlmsghdr *hdr, int ifindex)
606 struct rtmsg *r = NLMSG_DATA(hdr);
607 struct nlattr *tb[__RTA_MAX];
609 if (r->rtm_protocol == RTPROT_KERNEL &&
610 r->rtm_family == AF_INET6)
613 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
617 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
620 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
625 static int cb_clear_event(struct nl_msg *msg, void *arg)
627 struct clear_data *clr = arg;
628 struct nlmsghdr *hdr = nlmsg_hdr(msg);
629 bool (*cb)(struct nlmsghdr *, int ifindex);
635 if (hdr->nlmsg_type != RTM_NEWADDR)
642 if (hdr->nlmsg_type != RTM_NEWROUTE)
649 if (hdr->nlmsg_type != RTM_NEWRULE)
658 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
661 if (type == RTM_DELRULE)
662 D(SYSTEM, "Remove a rule\n");
664 D(SYSTEM, "Remove %s from device %s\n",
665 type == RTM_DELADDR ? "an address" : "a route",
667 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
668 hdr = nlmsg_hdr(clr->msg);
669 hdr->nlmsg_type = type;
670 hdr->nlmsg_flags = NLM_F_REQUEST;
672 nl_socket_disable_auto_ack(sock_rtnl);
673 nl_send_auto_complete(sock_rtnl, clr->msg);
674 nl_socket_enable_auto_ack(sock_rtnl);
680 cb_finish_event(struct nl_msg *msg, void *arg)
688 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
691 *pending = err->error;
696 system_if_clear_entries(struct device *dev, int type, int af)
698 struct clear_data clr;
699 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
702 .rtm_flags = RTM_F_CLONED,
704 int flags = NLM_F_DUMP;
713 clr.size = sizeof(struct rtgenmsg);
716 clr.size = sizeof(struct rtmsg);
725 clr.msg = nlmsg_alloc_simple(type, flags);
729 nlmsg_append(clr.msg, &rtm, clr.size, 0);
730 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
731 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
732 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
734 nl_send_auto_complete(sock_rtnl, clr.msg);
736 nl_recvmsgs(sock_rtnl, cb);
744 * Clear bridge (membership) state and bring down device
746 void system_if_clear_state(struct device *dev)
748 static char buf[256];
751 device_set_ifindex(dev, system_if_resolve(dev));
752 if (dev->external || !dev->ifindex)
755 system_if_flags(dev->ifname, 0, IFF_UP);
757 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
758 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
759 system_bridge_delbr(dev);
763 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
765 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
766 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
769 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
770 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
771 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
772 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
773 system_set_disable_ipv6(dev, "0");
776 static inline unsigned long
777 sec_to_jiffies(int val)
779 return (unsigned long) val * 100;
782 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
784 unsigned long args[4] = {};
786 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
789 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
790 args[1] = !!cfg->stp;
791 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
793 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
794 args[1] = sec_to_jiffies(cfg->forward_delay);
795 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
797 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
798 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
800 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier",
801 bridge->ifname, cfg->multicast_querier ? "1" : "0");
803 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
804 args[1] = cfg->priority;
805 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
807 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
808 args[0] = BRCTL_SET_AGEING_TIME;
809 args[1] = sec_to_jiffies(cfg->ageing_time);
810 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
813 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
814 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
815 args[1] = sec_to_jiffies(cfg->hello_time);
816 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
819 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
820 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
821 args[1] = sec_to_jiffies(cfg->max_age);
822 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
828 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
831 struct nlattr *linkinfo, *data;
832 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
834 static const struct {
836 enum macvlan_mode val;
838 { "private", MACVLAN_MODE_PRIVATE },
839 { "vepa", MACVLAN_MODE_VEPA },
840 { "bridge", MACVLAN_MODE_BRIDGE },
841 { "passthru", MACVLAN_MODE_PASSTHRU },
844 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
849 nlmsg_append(msg, &iim, sizeof(iim), 0);
851 if (cfg->flags & MACVLAN_OPT_MACADDR)
852 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
853 nla_put_string(msg, IFLA_IFNAME, macvlan->ifname);
854 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
856 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
857 goto nla_put_failure;
859 nla_put_string(msg, IFLA_INFO_KIND, "macvlan");
861 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
862 goto nla_put_failure;
865 for (i = 0; i < ARRAY_SIZE(modes); i++) {
866 if (strcmp(cfg->mode, modes[i].name) != 0)
869 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
874 nla_nest_end(msg, data);
875 nla_nest_end(msg, linkinfo);
877 rv = system_rtnl_call(msg);
879 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
888 static int system_link_del(const char *ifname)
891 struct ifinfomsg iim = {
892 .ifi_family = AF_UNSPEC,
896 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
901 nlmsg_append(msg, &iim, sizeof(iim), 0);
902 nla_put_string(msg, IFLA_IFNAME, ifname);
903 return system_rtnl_call(msg);
906 int system_macvlan_del(struct device *macvlan)
908 return system_link_del(macvlan->ifname);
911 static int system_vlan(struct device *dev, int id)
913 struct vlan_ioctl_args ifr = {
914 .cmd = SET_VLAN_NAME_TYPE_CMD,
915 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
918 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
921 ifr.cmd = DEL_VLAN_CMD;
924 ifr.cmd = ADD_VLAN_CMD;
927 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
928 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
931 int system_vlan_add(struct device *dev, int id)
933 return system_vlan(dev, id);
936 int system_vlan_del(struct device *dev)
938 return system_vlan(dev, -1);
941 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
944 struct nlattr *linkinfo, *data;
945 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
948 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
953 nlmsg_append(msg, &iim, sizeof(iim), 0);
954 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
955 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
957 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
958 goto nla_put_failure;
960 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
962 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
963 goto nla_put_failure;
965 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
967 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
968 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
970 if(cfg->proto == VLAN_PROTO_8021AD)
971 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);
974 nla_nest_end(msg, data);
975 nla_nest_end(msg, linkinfo);
977 rv = system_rtnl_call(msg);
979 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
988 int system_vlandev_del(struct device *vlandev)
990 return system_link_del(vlandev->ifname);
994 system_if_get_settings(struct device *dev, struct device_settings *s)
999 memset(&ifr, 0, sizeof(ifr));
1000 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1002 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
1003 s->mtu = ifr.ifr_mtu;
1004 s->flags |= DEV_OPT_MTU;
1007 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
1008 s->txqueuelen = ifr.ifr_qlen;
1009 s->flags |= DEV_OPT_TXQUEUELEN;
1012 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
1013 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
1014 s->flags |= DEV_OPT_MACADDR;
1017 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
1018 s->ipv6 = !strtoul(buf, NULL, 0);
1019 s->flags |= DEV_OPT_IPV6;
1022 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
1023 s->promisc = ifr.ifr_flags & IFF_PROMISC;
1024 s->flags |= DEV_OPT_PROMISC;
1027 if (!system_get_rpfilter(dev, buf, sizeof(buf))) {
1028 s->rpfilter = strtoul(buf, NULL, 0);
1029 s->flags |= DEV_OPT_RPFILTER;
1032 if (!system_get_acceptlocal(dev, buf, sizeof(buf))) {
1033 s->acceptlocal = strtoul(buf, NULL, 0);
1034 s->flags |= DEV_OPT_ACCEPTLOCAL;
1037 if (!system_get_igmpversion(dev, buf, sizeof(buf))) {
1038 s->igmpversion = strtoul(buf, NULL, 0);
1039 s->flags |= DEV_OPT_IGMPVERSION;
1042 if (!system_get_mldversion(dev, buf, sizeof(buf))) {
1043 s->mldversion = strtoul(buf, NULL, 0);
1044 s->flags |= DEV_OPT_MLDVERSION;
1047 if (!system_get_neigh4reachabletime(dev, buf, sizeof(buf))) {
1048 s->neigh4reachabletime = strtoul(buf, NULL, 0);
1049 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1052 if (!system_get_neigh6reachabletime(dev, buf, sizeof(buf))) {
1053 s->neigh6reachabletime = strtoul(buf, NULL, 0);
1054 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1059 system_if_set_rps_xps_val(const char *path, int val)
1065 if (glob(path, 0, NULL, &gl))
1068 snprintf(val_buf, sizeof(val_buf), "%x", val);
1069 for (i = 0; i < gl.gl_pathc; i++)
1070 system_set_sysctl(gl.gl_pathv[i], val_buf);
1074 system_if_apply_rps_xps(struct device *dev, struct device_settings *s)
1076 long n_cpus = sysconf(_SC_NPROCESSORS_ONLN);
1082 val = (1 << n_cpus) - 1;
1083 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/rps_cpus", dev->ifname);
1084 system_if_set_rps_xps_val(dev_buf, s->rps ? val : 0);
1086 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/xps_cpus", dev->ifname);
1087 system_if_set_rps_xps_val(dev_buf, s->xps ? val : 0);
1091 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
1095 memset(&ifr, 0, sizeof(ifr));
1096 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1097 if (s->flags & DEV_OPT_MTU & apply_mask) {
1098 ifr.ifr_mtu = s->mtu;
1099 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
1100 s->flags &= ~DEV_OPT_MTU;
1102 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
1103 ifr.ifr_qlen = s->txqueuelen;
1104 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
1105 s->flags &= ~DEV_OPT_TXQUEUELEN;
1107 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
1108 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
1109 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
1110 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
1111 s->flags &= ~DEV_OPT_MACADDR;
1113 if (s->flags & DEV_OPT_IPV6 & apply_mask)
1114 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
1115 if (s->flags & DEV_OPT_PROMISC & apply_mask) {
1116 if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
1117 !s->promisc ? IFF_PROMISC : 0) < 0)
1118 s->flags &= ~DEV_OPT_PROMISC;
1120 if (s->flags & DEV_OPT_RPFILTER & apply_mask) {
1123 snprintf(buf, sizeof(buf), "%d", s->rpfilter);
1124 system_set_rpfilter(dev, buf);
1126 if (s->flags & DEV_OPT_ACCEPTLOCAL & apply_mask)
1127 system_set_acceptlocal(dev, s->acceptlocal ? "1" : "0");
1128 if (s->flags & DEV_OPT_IGMPVERSION & apply_mask) {
1131 snprintf(buf, sizeof(buf), "%d", s->igmpversion);
1132 system_set_igmpversion(dev, buf);
1134 if (s->flags & DEV_OPT_MLDVERSION & apply_mask) {
1137 snprintf(buf, sizeof(buf), "%d", s->mldversion);
1138 system_set_mldversion(dev, buf);
1140 if (s->flags & DEV_OPT_NEIGHREACHABLETIME & apply_mask) {
1143 snprintf(buf, sizeof(buf), "%d", s->neigh4reachabletime);
1144 system_set_neigh4reachabletime(dev, buf);
1145 snprintf(buf, sizeof(buf), "%d", s->neigh6reachabletime);
1146 system_set_neigh6reachabletime(dev, buf);
1149 system_if_apply_rps_xps(dev, s);
1152 int system_if_up(struct device *dev)
1154 system_if_get_settings(dev, &dev->orig_settings);
1155 /* Only keep orig settings based on what needs to be set */
1156 dev->orig_settings.flags &= dev->settings.flags;
1157 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
1158 return system_if_flags(dev->ifname, IFF_UP, 0);
1161 int system_if_down(struct device *dev)
1163 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
1164 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
1168 struct if_check_data {
1174 #ifndef IFF_LOWER_UP
1175 #define IFF_LOWER_UP 0x10000
1178 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1180 struct nlmsghdr *nh = nlmsg_hdr(msg);
1181 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1182 struct if_check_data *chk = (struct if_check_data *)arg;
1184 if (nh->nlmsg_type != RTM_NEWLINK)
1187 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1188 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1193 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1195 struct if_check_data *chk = (struct if_check_data *)arg;
1200 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1202 struct if_check_data *chk = (struct if_check_data *)arg;
1204 device_set_present(chk->dev, false);
1205 device_set_link(chk->dev, false);
1206 chk->pending = err->error;
1211 int system_if_check(struct device *dev)
1213 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1215 struct ifinfomsg ifi = {
1216 .ifi_family = AF_UNSPEC,
1219 struct if_check_data chk = {
1225 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1226 if (!msg || nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1227 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1230 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1231 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1232 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1234 nl_send_auto_complete(sock_rtnl, msg);
1235 while (chk.pending > 0)
1236 nl_recvmsgs(sock_rtnl, cb);
1247 system_if_get_parent(struct device *dev)
1249 char buf[64], *devname;
1250 int ifindex, iflink, len;
1253 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1254 f = fopen(buf, "r");
1258 len = fread(buf, 1, sizeof(buf) - 1, f);
1265 iflink = strtoul(buf, NULL, 0);
1266 ifindex = system_if_resolve(dev);
1267 if (!iflink || iflink == ifindex)
1270 devname = if_indextoname(iflink, buf);
1274 return device_get(devname, true);
1278 read_string_file(int dir_fd, const char *file, char *buf, int len)
1284 fd = openat(dir_fd, file, O_RDONLY);
1289 len = read(fd, buf, len - 1);
1293 } else if (len > 0) {
1296 c = strchr(buf, '\n');
1309 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1314 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1316 *val = strtoull(buf, NULL, 0);
1321 /* Assume advertised flags == supported flags */
1322 static const struct {
1325 } ethtool_link_modes[] = {
1326 { ADVERTISED_10baseT_Half, "10H" },
1327 { ADVERTISED_10baseT_Full, "10F" },
1328 { ADVERTISED_100baseT_Half, "100H" },
1329 { ADVERTISED_100baseT_Full, "100F" },
1330 { ADVERTISED_1000baseT_Half, "1000H" },
1331 { ADVERTISED_1000baseT_Full, "1000F" },
1334 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1337 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1338 if (mask & ethtool_link_modes[i].mask)
1339 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1344 system_if_force_external(const char *ifname)
1349 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1350 return stat(buf, &s) == 0;
1354 system_if_dump_info(struct device *dev, struct blob_buf *b)
1356 struct ethtool_cmd ecmd;
1362 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
1363 dir_fd = open(buf, O_DIRECTORY);
1365 memset(&ecmd, 0, sizeof(ecmd));
1366 memset(&ifr, 0, sizeof(ifr));
1367 strcpy(ifr.ifr_name, dev->ifname);
1368 ifr.ifr_data = (caddr_t) &ecmd;
1369 ecmd.cmd = ETHTOOL_GSET;
1371 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1372 c = blobmsg_open_array(b, "link-advertising");
1373 system_add_link_modes(b, ecmd.advertising);
1374 blobmsg_close_array(b, c);
1376 c = blobmsg_open_array(b, "link-supported");
1377 system_add_link_modes(b, ecmd.supported);
1378 blobmsg_close_array(b, c);
1380 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1381 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1382 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1383 blobmsg_add_string_buffer(b);
1391 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1393 const char *const counters[] = {
1394 "collisions", "rx_frame_errors", "tx_compressed",
1395 "multicast", "rx_length_errors", "tx_dropped",
1396 "rx_bytes", "rx_missed_errors", "tx_errors",
1397 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1398 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1399 "rx_dropped", "tx_aborted_errors", "tx_packets",
1400 "rx_errors", "tx_bytes", "tx_window_errors",
1401 "rx_fifo_errors", "tx_carrier_errors",
1408 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1409 stats_dir = open(buf, O_DIRECTORY);
1413 for (i = 0; i < ARRAY_SIZE(counters); i++)
1414 if (read_uint64_file(stats_dir, counters[i], &val))
1415 blobmsg_add_u64(b, counters[i], val);
1421 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1423 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1424 int alen = v4 ? 4 : 16;
1425 unsigned int flags = 0;
1426 struct ifaddrmsg ifa = {
1427 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1428 .ifa_prefixlen = addr->mask,
1429 .ifa_index = dev->ifindex,
1433 if (cmd == RTM_NEWADDR)
1434 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1436 msg = nlmsg_alloc_simple(cmd, flags);
1440 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1441 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1443 if (addr->broadcast)
1444 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1445 if (addr->point_to_point)
1446 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1448 time_t now = system_get_rtime();
1449 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1451 if (addr->preferred_until) {
1452 int64_t preferred = addr->preferred_until - now;
1455 else if (preferred > UINT32_MAX)
1456 preferred = UINT32_MAX;
1458 cinfo.ifa_prefered = preferred;
1461 if (addr->valid_until) {
1462 int64_t valid = addr->valid_until - now;
1465 else if (valid > UINT32_MAX)
1468 cinfo.ifa_valid = valid;
1471 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1474 return system_rtnl_call(msg);
1477 int system_add_address(struct device *dev, struct device_addr *addr)
1479 return system_addr(dev, addr, RTM_NEWADDR);
1482 int system_del_address(struct device *dev, struct device_addr *addr)
1484 return system_addr(dev, addr, RTM_DELADDR);
1487 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1489 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1491 unsigned int flags = 0;
1494 have_gw = !!route->nexthop.in.s_addr;
1496 have_gw = route->nexthop.in6.s6_addr32[0] ||
1497 route->nexthop.in6.s6_addr32[1] ||
1498 route->nexthop.in6.s6_addr32[2] ||
1499 route->nexthop.in6.s6_addr32[3];
1501 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1502 ? route->table : RT_TABLE_MAIN;
1504 struct rtmsg rtm = {
1505 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1506 .rtm_dst_len = route->mask,
1507 .rtm_src_len = route->sourcemask,
1508 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1509 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
1510 .rtm_scope = RT_SCOPE_NOWHERE,
1511 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1512 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1516 if (cmd == RTM_NEWROUTE) {
1517 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1519 if (!dev) { // Add null-route
1520 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1521 rtm.rtm_type = RTN_UNREACHABLE;
1524 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1527 if (route->flags & DEVROUTE_TYPE) {
1528 rtm.rtm_type = route->type;
1529 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
1530 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
1531 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
1532 rtm.rtm_table = RT_TABLE_LOCAL;
1535 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT) {
1536 rtm.rtm_scope = RT_SCOPE_HOST;
1537 } else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
1538 rtm.rtm_type == RTN_ANYCAST) {
1539 rtm.rtm_scope = RT_SCOPE_LINK;
1540 } else if (rtm.rtm_type == RTN_BLACKHOLE || rtm.rtm_type == RTN_UNREACHABLE ||
1541 rtm.rtm_type == RTN_PROHIBIT || rtm.rtm_type == RTN_FAILED_POLICY) {
1542 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1547 msg = nlmsg_alloc_simple(cmd, flags);
1551 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1554 nla_put(msg, RTA_DST, alen, &route->addr);
1556 if (route->sourcemask) {
1557 if (rtm.rtm_family == AF_INET)
1558 nla_put(msg, RTA_PREFSRC, alen, &route->source);
1560 nla_put(msg, RTA_SRC, alen, &route->source);
1563 if (route->metric > 0)
1564 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1567 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1570 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1573 nla_put_u32(msg, RTA_TABLE, table);
1575 if (route->flags & DEVROUTE_MTU) {
1576 struct nlattr *metrics;
1578 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1579 goto nla_put_failure;
1581 nla_put_u32(msg, RTAX_MTU, route->mtu);
1583 nla_nest_end(msg, metrics);
1586 return system_rtnl_call(msg);
1593 int system_add_route(struct device *dev, struct device_route *route)
1595 return system_rt(dev, route, RTM_NEWROUTE);
1598 int system_del_route(struct device *dev, struct device_route *route)
1600 return system_rt(dev, route, RTM_DELROUTE);
1603 int system_flush_routes(void)
1605 const char *names[] = {
1606 "/proc/sys/net/ipv4/route/flush",
1607 "/proc/sys/net/ipv6/route/flush"
1611 for (i = 0; i < ARRAY_SIZE(names); i++) {
1612 fd = open(names[i], O_WRONLY);
1616 if (write(fd, "-1", 2)) {}
1622 bool system_resolve_rt_type(const char *type, unsigned int *id)
1624 return system_rtn_aton(type, id);
1627 bool system_resolve_rt_table(const char *name, unsigned int *id)
1631 unsigned int n, table = RT_TABLE_UNSPEC;
1633 /* first try to parse table as number */
1634 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1637 /* handle well known aliases */
1638 else if (!strcmp(name, "default"))
1639 table = RT_TABLE_DEFAULT;
1640 else if (!strcmp(name, "main"))
1641 table = RT_TABLE_MAIN;
1642 else if (!strcmp(name, "local"))
1643 table = RT_TABLE_LOCAL;
1644 else if (!strcmp(name, "prelocal"))
1645 table = RT_TABLE_PRELOCAL;
1647 /* try to look up name in /etc/iproute2/rt_tables */
1648 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1650 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1652 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1655 n = strtoul(e, NULL, 10);
1656 e = strtok(NULL, " \t\n");
1658 if (e && !strcmp(e, name))
1668 if (table == RT_TABLE_UNSPEC)
1675 bool system_is_default_rt_table(unsigned int id)
1677 return (id == RT_TABLE_MAIN);
1680 bool system_resolve_rpfilter(const char *filter, unsigned int *id)
1685 if (!strcmp(filter, "strict"))
1687 else if (!strcmp(filter, "loose"))
1690 n = strtoul(filter, &e, 0);
1691 if (*e || e == filter || n > 2)
1699 static int system_iprule(struct iprule *rule, int cmd)
1701 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1704 struct rtmsg rtm = {
1705 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1706 .rtm_protocol = RTPROT_STATIC,
1707 .rtm_scope = RT_SCOPE_UNIVERSE,
1708 .rtm_table = RT_TABLE_UNSPEC,
1709 .rtm_type = RTN_UNSPEC,
1713 if (cmd == RTM_NEWRULE) {
1714 rtm.rtm_type = RTN_UNICAST;
1715 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1719 rtm.rtm_flags |= FIB_RULE_INVERT;
1721 if (rule->flags & IPRULE_SRC)
1722 rtm.rtm_src_len = rule->src_mask;
1724 if (rule->flags & IPRULE_DEST)
1725 rtm.rtm_dst_len = rule->dest_mask;
1727 if (rule->flags & IPRULE_TOS)
1728 rtm.rtm_tos = rule->tos;
1730 if (rule->flags & IPRULE_LOOKUP) {
1731 if (rule->lookup < 256)
1732 rtm.rtm_table = rule->lookup;
1735 if (rule->flags & IPRULE_ACTION)
1736 rtm.rtm_type = rule->action;
1737 else if (rule->flags & IPRULE_GOTO)
1738 rtm.rtm_type = FR_ACT_GOTO;
1739 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1740 rtm.rtm_type = FR_ACT_NOP;
1742 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1747 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1749 if (rule->flags & IPRULE_IN)
1750 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1752 if (rule->flags & IPRULE_OUT)
1753 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1755 if (rule->flags & IPRULE_SRC)
1756 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1758 if (rule->flags & IPRULE_DEST)
1759 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1761 if (rule->flags & IPRULE_PRIORITY)
1762 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1763 else if (cmd == RTM_NEWRULE)
1764 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1766 if (rule->flags & IPRULE_FWMARK)
1767 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1769 if (rule->flags & IPRULE_FWMASK)
1770 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1772 if (rule->flags & IPRULE_LOOKUP) {
1773 if (rule->lookup >= 256)
1774 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1777 if (rule->flags & IPRULE_GOTO)
1778 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1780 return system_rtnl_call(msg);
1783 int system_add_iprule(struct iprule *rule)
1785 return system_iprule(rule, RTM_NEWRULE);
1788 int system_del_iprule(struct iprule *rule)
1790 return system_iprule(rule, RTM_DELRULE);
1793 int system_flush_iprules(void)
1798 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1799 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1801 memset(&rule, 0, sizeof(rule));
1804 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1807 rule.lookup = RT_TABLE_PRELOCAL;
1808 rv |= system_iprule(&rule, RTM_NEWRULE);
1811 rule.lookup = RT_TABLE_LOCAL;
1812 rv |= system_iprule(&rule, RTM_NEWRULE);
1814 rule.priority = 32766;
1815 rule.lookup = RT_TABLE_MAIN;
1816 rv |= system_iprule(&rule, RTM_NEWRULE);
1818 rule.priority = 32767;
1819 rule.lookup = RT_TABLE_DEFAULT;
1820 rv |= system_iprule(&rule, RTM_NEWRULE);
1823 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1826 rule.lookup = RT_TABLE_PRELOCAL;
1827 rv |= system_iprule(&rule, RTM_NEWRULE);
1830 rule.lookup = RT_TABLE_LOCAL;
1831 rv |= system_iprule(&rule, RTM_NEWRULE);
1833 rule.priority = 32766;
1834 rule.lookup = RT_TABLE_MAIN;
1835 rv |= system_iprule(&rule, RTM_NEWRULE);
1840 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1842 return system_rtn_aton(action, id);
1845 time_t system_get_rtime(void)
1850 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1853 if (gettimeofday(&tv, NULL) == 0)
1860 #define IP_DF 0x4000
1863 static int tunnel_ioctl(const char *name, int cmd, void *p)
1867 memset(&ifr, 0, sizeof(ifr));
1868 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1869 ifr.ifr_ifru.ifru_data = p;
1870 return ioctl(sock_ioctl, cmd, &ifr);
1873 #ifdef IFLA_IPTUN_MAX
1874 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
1875 static int system_add_gre_tunnel(const char *name, const char *kind,
1876 const unsigned int link, struct blob_attr **tb, bool v6)
1879 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
1880 struct blob_attr *cur;
1881 uint32_t ikey = 0, okey = 0, flags = 0, flowinfo = 0;
1882 uint16_t iflags = 0, oflags = 0;
1884 int ret = 0, ttl = 64;
1886 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
1890 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
1891 nla_put_string(nlm, IFLA_IFNAME, name);
1893 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
1899 nla_put_string(nlm, IFLA_INFO_KIND, kind);
1900 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
1907 nla_put_u32(nlm, IFLA_GRE_LINK, link);
1909 if ((cur = tb[TUNNEL_ATTR_TTL]))
1910 ttl = blobmsg_get_u32(cur);
1912 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
1914 if ((cur = tb[TUNNEL_ATTR_TOS])) {
1915 char *str = blobmsg_get_string(cur);
1916 if (strcmp(str, "inherit")) {
1919 if (!system_tos_aton(str, &uval)) {
1925 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
1930 flags |= IP6_TNL_F_USE_ORIG_TCLASS;
1936 if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) {
1937 uint8_t icsum, ocsum, iseqno, oseqno;
1938 if (sscanf(blobmsg_get_string(cur), "%u,%u,%hhu,%hhu,%hhu,%hhu",
1939 &ikey, &okey, &icsum, &ocsum, &iseqno, &oseqno) < 6) {
1964 struct in6_addr in6buf;
1965 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1966 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1970 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
1973 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
1974 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1978 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
1980 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, 4);
1983 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
1986 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags);
1988 struct in_addr inbuf;
1991 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1992 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
1996 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
1999 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2000 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2004 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
2006 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
2008 okey = inbuf.s_addr;
2013 ikey = inbuf.s_addr;
2019 if ((cur = tb[TUNNEL_ATTR_DF]))
2020 set_df = blobmsg_get_bool(cur);
2022 /* ttl !=0 and nopmtudisc are incompatible */
2023 if (ttl && !set_df) {
2028 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
2030 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
2034 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
2037 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
2040 nla_put_u32(nlm, IFLA_GRE_OKEY, okey);
2043 nla_put_u32(nlm, IFLA_GRE_IKEY, ikey);
2045 nla_nest_end(nlm, infodata);
2046 nla_nest_end(nlm, linkinfo);
2048 return system_rtnl_call(nlm);
2056 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
2058 struct blob_attr *cur;
2060 struct ip_tunnel_parm p = {
2069 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
2070 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
2073 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
2074 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
2077 if ((cur = tb[TUNNEL_ATTR_DF]))
2078 set_df = blobmsg_get_bool(cur);
2080 if ((cur = tb[TUNNEL_ATTR_TTL]))
2081 p.iph.ttl = blobmsg_get_u32(cur);
2083 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2084 char *str = blobmsg_get_string(cur);
2085 if (strcmp(str, "inherit")) {
2088 if (!system_tos_aton(str, &uval))
2096 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
2097 /* ttl !=0 and nopmtudisc are incompatible */
2098 if (p.iph.ttl && p.iph.frag_off == 0)
2101 strncpy(p.name, name, sizeof(p.name));
2103 switch (p.iph.protocol) {
2105 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
2107 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
2114 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
2116 struct blob_attr *cur;
2119 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2121 str = blobmsg_data(cur);
2123 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
2124 !strcmp(str, "greip6") || !strcmp(str, "gretapip6"))
2125 return system_link_del(name);
2127 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
2130 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
2132 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2134 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2135 blob_data(attr), blob_len(attr));
2137 return __system_del_ip_tunnel(name, tb);
2140 int system_update_ipv6_mtu(struct device *dev, int mtu)
2144 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
2147 int fd = open(buf, O_RDWR);
2148 ssize_t len = read(fd, buf, sizeof(buf) - 1);
2155 if (!mtu || ret <= mtu)
2158 lseek(fd, 0, SEEK_SET);
2159 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) <= 0)
2167 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
2169 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2170 struct blob_attr *cur;
2173 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2174 blob_data(attr), blob_len(attr));
2176 __system_del_ip_tunnel(name, tb);
2178 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2180 str = blobmsg_data(cur);
2182 unsigned int ttl = 0;
2183 if ((cur = tb[TUNNEL_ATTR_TTL])) {
2184 ttl = blobmsg_get_u32(cur);
2189 unsigned int link = 0;
2190 if ((cur = tb[TUNNEL_ATTR_LINK])) {
2191 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
2195 if (iface->l3_dev.dev)
2196 link = iface->l3_dev.dev->ifindex;
2199 if (!strcmp(str, "sit")) {
2200 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
2204 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
2206 struct ip_tunnel_6rd p6;
2208 memset(&p6, 0, sizeof(p6));
2210 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
2211 &p6.prefix, &mask) || mask > 128)
2213 p6.prefixlen = mask;
2215 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
2216 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
2217 &p6.relay_prefix, &mask) || mask > 32)
2219 p6.relay_prefixlen = mask;
2222 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
2223 __system_del_ip_tunnel(name, tb);
2228 #ifdef IFLA_IPTUN_MAX
2229 } else if (!strcmp(str, "ipip6")) {
2230 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2231 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2232 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2238 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2239 nla_put_string(nlm, IFLA_IFNAME, name);
2242 nla_put_u32(nlm, IFLA_LINK, link);
2244 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2249 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2250 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2257 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2259 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2260 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2261 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
2263 struct in6_addr in6buf;
2264 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2265 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2269 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2272 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2273 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2277 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2280 #ifdef IFLA_IPTUN_FMR_MAX
2281 if ((cur = tb[TUNNEL_ATTR_FMRS])) {
2282 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2284 struct blob_attr *fmr;
2285 unsigned rem, fmrcnt = 0;
2286 blobmsg_for_each_attr(fmr, cur, rem) {
2287 if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
2290 unsigned ip4len, ip6len, ealen, offset = 6;
2294 if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
2295 ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) {
2300 struct in6_addr ip6prefix;
2301 struct in_addr ip4prefix;
2302 if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
2303 inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) {
2308 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2310 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2311 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2312 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2313 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2314 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2315 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2317 nla_nest_end(nlm, rule);
2320 nla_nest_end(nlm, fmrs);
2324 nla_nest_end(nlm, infodata);
2325 nla_nest_end(nlm, linkinfo);
2327 return system_rtnl_call(nlm);
2331 } else if (!strcmp(str, "greip")) {
2332 return system_add_gre_tunnel(name, "gre", link, tb, false);
2333 } else if (!strcmp(str, "gretapip")) {
2334 return system_add_gre_tunnel(name, "gretap", link, tb, false);
2335 } else if (!strcmp(str, "greip6")) {
2336 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
2337 } else if (!strcmp(str, "gretapip6")) {
2338 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
2340 } else if (!strcmp(str, "ipip")) {
2341 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);