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,
1430 .ifa_flags = (addr->flags & DEVADDR_OFFLINK) ? IFA_F_NOPREFIXROUTE : 0,
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);