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
52 #include <netlink/msg.h>
53 #include <netlink/attr.h>
54 #include <netlink/socket.h>
55 #include <libubox/uloop.h>
62 struct uloop_fd uloop;
67 static int sock_ioctl = -1;
68 static struct nl_sock *sock_rtnl = NULL;
70 static int cb_rtnl_event(struct nl_msg *msg, void *arg);
71 static void handle_hotplug_event(struct uloop_fd *u, unsigned int events);
73 static char dev_buf[256];
76 handler_nl_event(struct uloop_fd *u, unsigned int events)
78 struct event_socket *ev = container_of(u, struct event_socket, uloop);
80 socklen_t errlen = sizeof(err);
83 nl_recvmsgs_default(ev->sock);
87 if (getsockopt(u->fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen))
92 // Increase rx buffer size on netlink socket
94 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
97 // Request full dump since some info got dropped
98 struct rtgenmsg msg = { .rtgen_family = AF_UNSPEC };
99 nl_send_simple(ev->sock, RTM_GETLINK, NLM_F_DUMP, &msg, sizeof(msg));
109 uloop_fd_delete(&ev->uloop);
113 static struct nl_sock *
114 create_socket(int protocol, int groups)
116 struct nl_sock *sock;
118 sock = nl_socket_alloc();
123 nl_join_groups(sock, groups);
125 if (nl_connect(sock, protocol))
132 create_raw_event_socket(struct event_socket *ev, int protocol, int groups,
133 uloop_fd_handler cb, int flags)
135 ev->sock = create_socket(protocol, groups);
139 ev->uloop.fd = nl_socket_get_fd(ev->sock);
141 if (uloop_fd_add(&ev->uloop, ULOOP_READ|flags))
148 create_event_socket(struct event_socket *ev, int protocol,
149 int (*cb)(struct nl_msg *msg, void *arg))
151 if (!create_raw_event_socket(ev, protocol, 0, handler_nl_event, ULOOP_ERROR_CB))
154 // Install the valid custom callback handler
155 nl_socket_modify_cb(ev->sock, NL_CB_VALID, NL_CB_CUSTOM, cb, NULL);
157 // Disable sequence number checking on event sockets
158 nl_socket_disable_seq_check(ev->sock);
160 // Increase rx buffer size to 65K on event sockets
162 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
169 system_rtn_aton(const char *src, unsigned int *dst)
174 if (!strcmp(src, "local"))
176 else if (!strcmp(src, "nat"))
178 else if (!strcmp(src, "broadcast"))
180 else if (!strcmp(src, "anycast"))
182 else if (!strcmp(src, "multicast"))
184 else if (!strcmp(src, "prohibit"))
186 else if (!strcmp(src, "unreachable"))
188 else if (!strcmp(src, "blackhole"))
190 else if (!strcmp(src, "xresolve"))
192 else if (!strcmp(src, "unicast"))
194 else if (!strcmp(src, "throw"))
196 else if (!strcmp(src, "failed_policy"))
197 n = RTN_FAILED_POLICY;
199 n = strtoul(src, &e, 0);
200 if (!e || *e || e == src || n > 255)
209 system_tos_aton(const char *src, unsigned *dst)
213 *dst = strtoul(src, &e, 16);
214 if (e == src || *e || *dst > 255)
220 int system_init(void)
222 static struct event_socket rtnl_event;
223 static struct event_socket hotplug_event;
225 sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0);
226 system_fd_set_cloexec(sock_ioctl);
228 // Prepare socket for routing / address control
229 sock_rtnl = create_socket(NETLINK_ROUTE, 0);
233 if (!create_event_socket(&rtnl_event, NETLINK_ROUTE, cb_rtnl_event))
236 if (!create_raw_event_socket(&hotplug_event, NETLINK_KOBJECT_UEVENT, 1,
237 handle_hotplug_event, 0))
240 // Receive network link events form kernel
241 nl_socket_add_membership(rtnl_event.sock, RTNLGRP_LINK);
246 static void system_set_sysctl(const char *path, const char *val)
250 fd = open(path, O_WRONLY);
254 if (write(fd, val, strlen(val))) {}
258 static void system_set_dev_sysctl(const char *path, const char *device, const char *val)
260 snprintf(dev_buf, sizeof(dev_buf), path, device);
261 system_set_sysctl(dev_buf, val);
264 static void system_set_disable_ipv6(struct device *dev, const char *val)
266 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val);
269 static void system_set_rpfilter(struct device *dev, const char *val)
271 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter", dev->ifname, val);
274 static void system_set_acceptlocal(struct device *dev, const char *val)
276 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local", dev->ifname, val);
279 static void system_set_igmpversion(struct device *dev, const char *val)
281 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version", dev->ifname, val);
284 static void system_set_mldversion(struct device *dev, const char *val)
286 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version", dev->ifname, val);
289 static void system_set_neigh4reachabletime(struct device *dev, const char *val)
291 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms", dev->ifname, val);
294 static void system_set_neigh6reachabletime(struct device *dev, const char *val)
296 system_set_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms", dev->ifname, val);
299 static int system_get_sysctl(const char *path, char *buf, const size_t buf_sz)
301 int fd = -1, ret = -1;
303 fd = open(path, O_RDONLY);
307 ssize_t len = read(fd, buf, buf_sz - 1);
321 system_get_dev_sysctl(const char *path, const char *device, char *buf, const size_t buf_sz)
323 snprintf(dev_buf, sizeof(dev_buf), path, device);
324 return system_get_sysctl(dev_buf, buf, buf_sz);
327 static int system_get_disable_ipv6(struct device *dev, char *buf, const size_t buf_sz)
329 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6",
330 dev->ifname, buf, buf_sz);
333 static int system_get_rpfilter(struct device *dev, char *buf, const size_t buf_sz)
335 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter",
336 dev->ifname, buf, buf_sz);
339 static int system_get_acceptlocal(struct device *dev, char *buf, const size_t buf_sz)
341 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local",
342 dev->ifname, buf, buf_sz);
345 static int system_get_igmpversion(struct device *dev, char *buf, const size_t buf_sz)
347 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version",
348 dev->ifname, buf, buf_sz);
351 static int system_get_mldversion(struct device *dev, char *buf, const size_t buf_sz)
353 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version",
354 dev->ifname, buf, buf_sz);
357 static int system_get_neigh4reachabletime(struct device *dev, char *buf, const size_t buf_sz)
359 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms",
360 dev->ifname, buf, buf_sz);
363 static int system_get_neigh6reachabletime(struct device *dev, char *buf, const size_t buf_sz)
365 return system_get_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms",
366 dev->ifname, buf, buf_sz);
369 // Evaluate netlink messages
370 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
372 struct nlmsghdr *nh = nlmsg_hdr(msg);
373 struct ifinfomsg *ifi = NLMSG_DATA(nh);
374 struct nlattr *nla[__IFLA_MAX];
378 if (nh->nlmsg_type != RTM_NEWLINK)
381 nlmsg_parse(nh, sizeof(*ifi), nla, __IFLA_MAX - 1, NULL);
382 if (!nla[IFLA_IFNAME])
385 struct device *dev = device_get(nla_data(nla[IFLA_IFNAME]), false);
386 if (!dev || dev->type->keep_link_status)
389 if (!system_get_dev_sysctl("/sys/class/net/%s/carrier", dev->ifname, buf, sizeof(buf)))
390 link_state = strtoul(buf, NULL, 0);
392 device_set_link(dev, link_state ? true : false);
399 handle_hotplug_msg(char *data, int size)
401 const char *subsystem = NULL, *interface = NULL;
402 char *cur, *end, *sep;
407 if (!strncmp(data, "add@", 4))
409 else if (!strncmp(data, "remove@", 7))
414 skip = strlen(data) + 1;
417 for (cur = data + skip; cur < end; cur += skip) {
418 skip = strlen(cur) + 1;
420 sep = strchr(cur, '=');
425 if (!strcmp(cur, "INTERFACE"))
427 else if (!strcmp(cur, "SUBSYSTEM")) {
429 if (strcmp(subsystem, "net") != 0)
432 if (subsystem && interface)
438 dev = device_get(interface, false);
442 if (dev->type != &simple_device_type)
445 if (add && system_if_force_external(dev->ifname))
448 device_set_present(dev, add);
452 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
454 struct event_socket *ev = container_of(u, struct event_socket, uloop);
455 struct sockaddr_nl nla;
456 unsigned char *buf = NULL;
459 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
461 handle_hotplug_msg((char *) buf, size);
467 static int system_rtnl_call(struct nl_msg *msg)
471 ret = nl_send_auto_complete(sock_rtnl, msg);
477 return nl_wait_for_ack(sock_rtnl);
480 int system_bridge_delbr(struct device *bridge)
482 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
485 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
489 memset(&ifr, 0, sizeof(ifr));
491 ifr.ifr_ifindex = dev->ifindex;
494 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
495 return ioctl(sock_ioctl, cmd, &ifr);
498 static bool system_is_bridge(const char *name, char *buf, int buflen)
502 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
503 if (stat(buf, &st) < 0)
509 static char *system_get_bridge(const char *name, char *buf, int buflen)
515 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
516 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
520 len = readlink(gl.gl_pathv[0], buf, buflen);
528 path = strrchr(buf, '/');
535 static void system_bridge_set_wireless(const char *bridge, const char *dev)
537 snprintf(dev_buf, sizeof(dev_buf),
538 "/sys/devices/virtual/net/%s/brif/%s/multicast_to_unicast",
540 system_set_sysctl(dev_buf, "1");
543 int system_bridge_addif(struct device *bridge, struct device *dev)
548 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
549 if (!oldbr || strcmp(oldbr, bridge->ifname) != 0)
550 ret = system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
553 system_bridge_set_wireless(bridge->ifname, dev->ifname);
558 int system_bridge_delif(struct device *bridge, struct device *dev)
560 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
563 int system_if_resolve(struct device *dev)
566 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
567 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
568 return ifr.ifr_ifindex;
573 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
577 memset(&ifr, 0, sizeof(ifr));
578 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
579 ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
580 ifr.ifr_flags |= add;
581 ifr.ifr_flags &= ~rem;
582 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
594 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
596 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
598 return ifa->ifa_index == ifindex;
601 static bool check_route(struct nlmsghdr *hdr, int ifindex)
603 struct rtmsg *r = NLMSG_DATA(hdr);
604 struct nlattr *tb[__RTA_MAX];
606 if (r->rtm_protocol == RTPROT_KERNEL &&
607 r->rtm_family == AF_INET6)
610 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
614 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
617 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
622 static int cb_clear_event(struct nl_msg *msg, void *arg)
624 struct clear_data *clr = arg;
625 struct nlmsghdr *hdr = nlmsg_hdr(msg);
626 bool (*cb)(struct nlmsghdr *, int ifindex);
632 if (hdr->nlmsg_type != RTM_NEWADDR)
639 if (hdr->nlmsg_type != RTM_NEWROUTE)
646 if (hdr->nlmsg_type != RTM_NEWRULE)
655 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
658 if (type == RTM_DELRULE)
659 D(SYSTEM, "Remove a rule\n");
661 D(SYSTEM, "Remove %s from device %s\n",
662 type == RTM_DELADDR ? "an address" : "a route",
664 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
665 hdr = nlmsg_hdr(clr->msg);
666 hdr->nlmsg_type = type;
667 hdr->nlmsg_flags = NLM_F_REQUEST;
669 nl_socket_disable_auto_ack(sock_rtnl);
670 nl_send_auto_complete(sock_rtnl, clr->msg);
671 nl_socket_enable_auto_ack(sock_rtnl);
677 cb_finish_event(struct nl_msg *msg, void *arg)
685 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
688 *pending = err->error;
693 system_if_clear_entries(struct device *dev, int type, int af)
695 struct clear_data clr;
696 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
699 .rtm_flags = RTM_F_CLONED,
701 int flags = NLM_F_DUMP;
710 clr.size = sizeof(struct rtgenmsg);
713 clr.size = sizeof(struct rtmsg);
722 clr.msg = nlmsg_alloc_simple(type, flags);
726 nlmsg_append(clr.msg, &rtm, clr.size, 0);
727 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
728 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
729 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
731 nl_send_auto_complete(sock_rtnl, clr.msg);
733 nl_recvmsgs(sock_rtnl, cb);
741 * Clear bridge (membership) state and bring down device
743 void system_if_clear_state(struct device *dev)
745 static char buf[256];
748 device_set_ifindex(dev, system_if_resolve(dev));
749 if (dev->external || !dev->ifindex)
752 system_if_flags(dev->ifname, 0, IFF_UP);
754 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
755 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
756 system_bridge_delbr(dev);
760 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
762 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
763 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
766 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
767 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
768 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
769 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
770 system_set_disable_ipv6(dev, "0");
773 static inline unsigned long
774 sec_to_jiffies(int val)
776 return (unsigned long) val * 100;
779 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
781 unsigned long args[4] = {};
783 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
786 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
787 args[1] = !!cfg->stp;
788 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
790 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
791 args[1] = sec_to_jiffies(cfg->forward_delay);
792 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
794 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
795 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
797 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier",
798 bridge->ifname, cfg->multicast_querier ? "1" : "0");
800 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
801 args[1] = cfg->priority;
802 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
804 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
805 args[0] = BRCTL_SET_AGEING_TIME;
806 args[1] = sec_to_jiffies(cfg->ageing_time);
807 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
810 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
811 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
812 args[1] = sec_to_jiffies(cfg->hello_time);
813 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
816 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
817 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
818 args[1] = sec_to_jiffies(cfg->max_age);
819 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
825 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
828 struct nlattr *linkinfo, *data;
829 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
831 static const struct {
833 enum macvlan_mode val;
835 { "private", MACVLAN_MODE_PRIVATE },
836 { "vepa", MACVLAN_MODE_VEPA },
837 { "bridge", MACVLAN_MODE_BRIDGE },
838 { "passthru", MACVLAN_MODE_PASSTHRU },
841 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
846 nlmsg_append(msg, &iim, sizeof(iim), 0);
848 if (cfg->flags & MACVLAN_OPT_MACADDR)
849 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
850 nla_put_string(msg, IFLA_IFNAME, macvlan->ifname);
851 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
853 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
854 goto nla_put_failure;
856 nla_put_string(msg, IFLA_INFO_KIND, "macvlan");
858 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
859 goto nla_put_failure;
862 for (i = 0; i < ARRAY_SIZE(modes); i++) {
863 if (strcmp(cfg->mode, modes[i].name) != 0)
866 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
871 nla_nest_end(msg, data);
872 nla_nest_end(msg, linkinfo);
874 rv = system_rtnl_call(msg);
876 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
885 static int system_link_del(const char *ifname)
888 struct ifinfomsg iim = {
889 .ifi_family = AF_UNSPEC,
893 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
898 nlmsg_append(msg, &iim, sizeof(iim), 0);
899 nla_put_string(msg, IFLA_IFNAME, ifname);
900 return system_rtnl_call(msg);
903 int system_macvlan_del(struct device *macvlan)
905 return system_link_del(macvlan->ifname);
908 static int system_vlan(struct device *dev, int id)
910 struct vlan_ioctl_args ifr = {
911 .cmd = SET_VLAN_NAME_TYPE_CMD,
912 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
915 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
918 ifr.cmd = DEL_VLAN_CMD;
921 ifr.cmd = ADD_VLAN_CMD;
924 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
925 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
928 int system_vlan_add(struct device *dev, int id)
930 return system_vlan(dev, id);
933 int system_vlan_del(struct device *dev)
935 return system_vlan(dev, -1);
938 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
941 struct nlattr *linkinfo, *data;
942 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
945 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
950 nlmsg_append(msg, &iim, sizeof(iim), 0);
951 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
952 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
954 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
955 goto nla_put_failure;
957 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
959 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
960 goto nla_put_failure;
962 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
964 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
965 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
967 if(cfg->proto == VLAN_PROTO_8021AD)
968 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);
971 nla_nest_end(msg, data);
972 nla_nest_end(msg, linkinfo);
974 rv = system_rtnl_call(msg);
976 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
985 int system_vlandev_del(struct device *vlandev)
987 return system_link_del(vlandev->ifname);
991 system_if_get_settings(struct device *dev, struct device_settings *s)
996 memset(&ifr, 0, sizeof(ifr));
997 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
999 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
1000 s->mtu = ifr.ifr_mtu;
1001 s->flags |= DEV_OPT_MTU;
1004 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
1005 s->txqueuelen = ifr.ifr_qlen;
1006 s->flags |= DEV_OPT_TXQUEUELEN;
1009 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
1010 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
1011 s->flags |= DEV_OPT_MACADDR;
1014 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
1015 s->ipv6 = !strtoul(buf, NULL, 0);
1016 s->flags |= DEV_OPT_IPV6;
1019 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
1020 s->promisc = ifr.ifr_flags & IFF_PROMISC;
1021 s->flags |= DEV_OPT_PROMISC;
1024 if (!system_get_rpfilter(dev, buf, sizeof(buf))) {
1025 s->rpfilter = strtoul(buf, NULL, 0);
1026 s->flags |= DEV_OPT_RPFILTER;
1029 if (!system_get_acceptlocal(dev, buf, sizeof(buf))) {
1030 s->acceptlocal = strtoul(buf, NULL, 0);
1031 s->flags |= DEV_OPT_ACCEPTLOCAL;
1034 if (!system_get_igmpversion(dev, buf, sizeof(buf))) {
1035 s->igmpversion = strtoul(buf, NULL, 0);
1036 s->flags |= DEV_OPT_IGMPVERSION;
1039 if (!system_get_mldversion(dev, buf, sizeof(buf))) {
1040 s->mldversion = strtoul(buf, NULL, 0);
1041 s->flags |= DEV_OPT_MLDVERSION;
1044 if (!system_get_neigh4reachabletime(dev, buf, sizeof(buf))) {
1045 s->neigh4reachabletime = strtoul(buf, NULL, 0);
1046 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1049 if (!system_get_neigh6reachabletime(dev, buf, sizeof(buf))) {
1050 s->neigh6reachabletime = strtoul(buf, NULL, 0);
1051 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1056 system_if_set_rps_xps_val(const char *path, int val)
1062 if (glob(path, 0, NULL, &gl))
1065 snprintf(val_buf, sizeof(val_buf), "%x", val);
1066 for (i = 0; i < gl.gl_pathc; i++)
1067 system_set_sysctl(gl.gl_pathv[i], val_buf);
1071 system_if_apply_rps_xps(struct device *dev, struct device_settings *s)
1073 long n_cpus = sysconf(_SC_NPROCESSORS_ONLN);
1079 val = (1 << n_cpus) - 1;
1080 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/rps_cpus", dev->ifname);
1081 system_if_set_rps_xps_val(dev_buf, s->rps ? val : 0);
1083 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/xps_cpus", dev->ifname);
1084 system_if_set_rps_xps_val(dev_buf, s->xps ? val : 0);
1088 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
1092 memset(&ifr, 0, sizeof(ifr));
1093 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1094 if (s->flags & DEV_OPT_MTU & apply_mask) {
1095 ifr.ifr_mtu = s->mtu;
1096 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
1097 s->flags &= ~DEV_OPT_MTU;
1099 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
1100 ifr.ifr_qlen = s->txqueuelen;
1101 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
1102 s->flags &= ~DEV_OPT_TXQUEUELEN;
1104 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
1105 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
1106 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
1107 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
1108 s->flags &= ~DEV_OPT_MACADDR;
1110 if (s->flags & DEV_OPT_IPV6 & apply_mask)
1111 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
1112 if (s->flags & DEV_OPT_PROMISC & apply_mask) {
1113 if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
1114 !s->promisc ? IFF_PROMISC : 0) < 0)
1115 s->flags &= ~DEV_OPT_PROMISC;
1117 if (s->flags & DEV_OPT_RPFILTER & apply_mask) {
1120 snprintf(buf, sizeof(buf), "%d", s->rpfilter);
1121 system_set_rpfilter(dev, buf);
1123 if (s->flags & DEV_OPT_ACCEPTLOCAL & apply_mask)
1124 system_set_acceptlocal(dev, s->acceptlocal ? "1" : "0");
1125 if (s->flags & DEV_OPT_IGMPVERSION & apply_mask) {
1128 snprintf(buf, sizeof(buf), "%d", s->igmpversion);
1129 system_set_igmpversion(dev, buf);
1131 if (s->flags & DEV_OPT_MLDVERSION & apply_mask) {
1134 snprintf(buf, sizeof(buf), "%d", s->mldversion);
1135 system_set_mldversion(dev, buf);
1137 if (s->flags & DEV_OPT_NEIGHREACHABLETIME & apply_mask) {
1140 snprintf(buf, sizeof(buf), "%d", s->neigh4reachabletime);
1141 system_set_neigh4reachabletime(dev, buf);
1142 snprintf(buf, sizeof(buf), "%d", s->neigh6reachabletime);
1143 system_set_neigh6reachabletime(dev, buf);
1146 system_if_apply_rps_xps(dev, s);
1149 int system_if_up(struct device *dev)
1151 system_if_get_settings(dev, &dev->orig_settings);
1152 /* Only keep orig settings based on what needs to be set */
1153 dev->orig_settings.flags &= dev->settings.flags;
1154 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
1155 return system_if_flags(dev->ifname, IFF_UP, 0);
1158 int system_if_down(struct device *dev)
1160 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
1161 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
1165 struct if_check_data {
1171 #ifndef IFF_LOWER_UP
1172 #define IFF_LOWER_UP 0x10000
1175 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1177 struct nlmsghdr *nh = nlmsg_hdr(msg);
1178 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1179 struct if_check_data *chk = (struct if_check_data *)arg;
1181 if (nh->nlmsg_type != RTM_NEWLINK)
1184 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1185 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1190 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1192 struct if_check_data *chk = (struct if_check_data *)arg;
1197 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1199 struct if_check_data *chk = (struct if_check_data *)arg;
1201 device_set_present(chk->dev, false);
1202 device_set_link(chk->dev, false);
1203 chk->pending = err->error;
1208 int system_if_check(struct device *dev)
1210 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1212 struct ifinfomsg ifi = {
1213 .ifi_family = AF_UNSPEC,
1216 struct if_check_data chk = {
1222 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1223 if (!msg || nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1224 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1227 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1228 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1229 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1231 nl_send_auto_complete(sock_rtnl, msg);
1232 while (chk.pending > 0)
1233 nl_recvmsgs(sock_rtnl, cb);
1244 system_if_get_parent(struct device *dev)
1246 char buf[64], *devname;
1247 int ifindex, iflink, len;
1250 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1251 f = fopen(buf, "r");
1255 len = fread(buf, 1, sizeof(buf) - 1, f);
1262 iflink = strtoul(buf, NULL, 0);
1263 ifindex = system_if_resolve(dev);
1264 if (!iflink || iflink == ifindex)
1267 devname = if_indextoname(iflink, buf);
1271 return device_get(devname, true);
1275 read_string_file(int dir_fd, const char *file, char *buf, int len)
1281 fd = openat(dir_fd, file, O_RDONLY);
1286 len = read(fd, buf, len - 1);
1290 } else if (len > 0) {
1293 c = strchr(buf, '\n');
1306 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1311 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1313 *val = strtoull(buf, NULL, 0);
1318 /* Assume advertised flags == supported flags */
1319 static const struct {
1322 } ethtool_link_modes[] = {
1323 { ADVERTISED_10baseT_Half, "10H" },
1324 { ADVERTISED_10baseT_Full, "10F" },
1325 { ADVERTISED_100baseT_Half, "100H" },
1326 { ADVERTISED_100baseT_Full, "100F" },
1327 { ADVERTISED_1000baseT_Half, "1000H" },
1328 { ADVERTISED_1000baseT_Full, "1000F" },
1331 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1334 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1335 if (mask & ethtool_link_modes[i].mask)
1336 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1341 system_if_force_external(const char *ifname)
1346 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1347 return stat(buf, &s) == 0;
1351 system_if_dump_info(struct device *dev, struct blob_buf *b)
1353 struct ethtool_cmd ecmd;
1359 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
1360 dir_fd = open(buf, O_DIRECTORY);
1362 memset(&ecmd, 0, sizeof(ecmd));
1363 memset(&ifr, 0, sizeof(ifr));
1364 strcpy(ifr.ifr_name, dev->ifname);
1365 ifr.ifr_data = (caddr_t) &ecmd;
1366 ecmd.cmd = ETHTOOL_GSET;
1368 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1369 c = blobmsg_open_array(b, "link-advertising");
1370 system_add_link_modes(b, ecmd.advertising);
1371 blobmsg_close_array(b, c);
1373 c = blobmsg_open_array(b, "link-supported");
1374 system_add_link_modes(b, ecmd.supported);
1375 blobmsg_close_array(b, c);
1377 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1378 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1379 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1380 blobmsg_add_string_buffer(b);
1388 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1390 const char *const counters[] = {
1391 "collisions", "rx_frame_errors", "tx_compressed",
1392 "multicast", "rx_length_errors", "tx_dropped",
1393 "rx_bytes", "rx_missed_errors", "tx_errors",
1394 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1395 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1396 "rx_dropped", "tx_aborted_errors", "tx_packets",
1397 "rx_errors", "tx_bytes", "tx_window_errors",
1398 "rx_fifo_errors", "tx_carrier_errors",
1405 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1406 stats_dir = open(buf, O_DIRECTORY);
1410 for (i = 0; i < ARRAY_SIZE(counters); i++)
1411 if (read_uint64_file(stats_dir, counters[i], &val))
1412 blobmsg_add_u64(b, counters[i], val);
1418 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1420 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1421 int alen = v4 ? 4 : 16;
1422 unsigned int flags = 0;
1423 struct ifaddrmsg ifa = {
1424 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1425 .ifa_prefixlen = addr->mask,
1426 .ifa_index = dev->ifindex,
1430 if (cmd == RTM_NEWADDR)
1431 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1433 msg = nlmsg_alloc_simple(cmd, flags);
1437 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1438 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1440 if (addr->broadcast)
1441 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1442 if (addr->point_to_point)
1443 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1445 time_t now = system_get_rtime();
1446 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1448 if (addr->preferred_until) {
1449 int64_t preferred = addr->preferred_until - now;
1452 else if (preferred > UINT32_MAX)
1453 preferred = UINT32_MAX;
1455 cinfo.ifa_prefered = preferred;
1458 if (addr->valid_until) {
1459 int64_t valid = addr->valid_until - now;
1462 else if (valid > UINT32_MAX)
1465 cinfo.ifa_valid = valid;
1468 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1471 return system_rtnl_call(msg);
1474 int system_add_address(struct device *dev, struct device_addr *addr)
1476 return system_addr(dev, addr, RTM_NEWADDR);
1479 int system_del_address(struct device *dev, struct device_addr *addr)
1481 return system_addr(dev, addr, RTM_DELADDR);
1484 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1486 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1488 unsigned int flags = 0;
1491 have_gw = !!route->nexthop.in.s_addr;
1493 have_gw = route->nexthop.in6.s6_addr32[0] ||
1494 route->nexthop.in6.s6_addr32[1] ||
1495 route->nexthop.in6.s6_addr32[2] ||
1496 route->nexthop.in6.s6_addr32[3];
1498 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1499 ? route->table : RT_TABLE_MAIN;
1501 struct rtmsg rtm = {
1502 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1503 .rtm_dst_len = route->mask,
1504 .rtm_src_len = route->sourcemask,
1505 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1506 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
1507 .rtm_scope = RT_SCOPE_NOWHERE,
1508 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1509 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1513 if (cmd == RTM_NEWROUTE) {
1514 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1516 if (!dev) { // Add null-route
1517 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1518 rtm.rtm_type = RTN_UNREACHABLE;
1521 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1524 if (route->flags & DEVROUTE_TYPE) {
1525 rtm.rtm_type = route->type;
1526 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
1527 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
1528 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
1529 rtm.rtm_table = RT_TABLE_LOCAL;
1532 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT) {
1533 rtm.rtm_scope = RT_SCOPE_HOST;
1534 } else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
1535 rtm.rtm_type == RTN_ANYCAST) {
1536 rtm.rtm_scope = RT_SCOPE_LINK;
1537 } else if (rtm.rtm_type == RTN_BLACKHOLE || rtm.rtm_type == RTN_UNREACHABLE ||
1538 rtm.rtm_type == RTN_PROHIBIT || rtm.rtm_type == RTN_FAILED_POLICY) {
1539 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1544 msg = nlmsg_alloc_simple(cmd, flags);
1548 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1551 nla_put(msg, RTA_DST, alen, &route->addr);
1553 if (route->sourcemask) {
1554 if (rtm.rtm_family == AF_INET)
1555 nla_put(msg, RTA_PREFSRC, alen, &route->source);
1557 nla_put(msg, RTA_SRC, alen, &route->source);
1560 if (route->metric > 0)
1561 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1564 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1567 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1570 nla_put_u32(msg, RTA_TABLE, table);
1572 if (route->flags & DEVROUTE_MTU) {
1573 struct nlattr *metrics;
1575 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1576 goto nla_put_failure;
1578 nla_put_u32(msg, RTAX_MTU, route->mtu);
1580 nla_nest_end(msg, metrics);
1583 return system_rtnl_call(msg);
1590 int system_add_route(struct device *dev, struct device_route *route)
1592 return system_rt(dev, route, RTM_NEWROUTE);
1595 int system_del_route(struct device *dev, struct device_route *route)
1597 return system_rt(dev, route, RTM_DELROUTE);
1600 int system_flush_routes(void)
1602 const char *names[] = {
1603 "/proc/sys/net/ipv4/route/flush",
1604 "/proc/sys/net/ipv6/route/flush"
1608 for (i = 0; i < ARRAY_SIZE(names); i++) {
1609 fd = open(names[i], O_WRONLY);
1613 if (write(fd, "-1", 2)) {}
1619 bool system_resolve_rt_type(const char *type, unsigned int *id)
1621 return system_rtn_aton(type, id);
1624 bool system_resolve_rt_table(const char *name, unsigned int *id)
1628 unsigned int n, table = RT_TABLE_UNSPEC;
1630 /* first try to parse table as number */
1631 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1634 /* handle well known aliases */
1635 else if (!strcmp(name, "default"))
1636 table = RT_TABLE_DEFAULT;
1637 else if (!strcmp(name, "main"))
1638 table = RT_TABLE_MAIN;
1639 else if (!strcmp(name, "local"))
1640 table = RT_TABLE_LOCAL;
1642 /* try to look up name in /etc/iproute2/rt_tables */
1643 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1645 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1647 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1650 n = strtoul(e, NULL, 10);
1651 e = strtok(NULL, " \t\n");
1653 if (e && !strcmp(e, name))
1663 if (table == RT_TABLE_UNSPEC)
1670 bool system_is_default_rt_table(unsigned int id)
1672 return (id == RT_TABLE_MAIN);
1675 bool system_resolve_rpfilter(const char *filter, unsigned int *id)
1680 if (!strcmp(filter, "strict"))
1682 else if (!strcmp(filter, "loose"))
1685 n = strtoul(filter, &e, 0);
1686 if (*e || e == filter || n > 2)
1694 static int system_iprule(struct iprule *rule, int cmd)
1696 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1699 struct rtmsg rtm = {
1700 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1701 .rtm_protocol = RTPROT_STATIC,
1702 .rtm_scope = RT_SCOPE_UNIVERSE,
1703 .rtm_table = RT_TABLE_UNSPEC,
1704 .rtm_type = RTN_UNSPEC,
1708 if (cmd == RTM_NEWRULE) {
1709 rtm.rtm_type = RTN_UNICAST;
1710 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1714 rtm.rtm_flags |= FIB_RULE_INVERT;
1716 if (rule->flags & IPRULE_SRC)
1717 rtm.rtm_src_len = rule->src_mask;
1719 if (rule->flags & IPRULE_DEST)
1720 rtm.rtm_dst_len = rule->dest_mask;
1722 if (rule->flags & IPRULE_TOS)
1723 rtm.rtm_tos = rule->tos;
1725 if (rule->flags & IPRULE_LOOKUP) {
1726 if (rule->lookup < 256)
1727 rtm.rtm_table = rule->lookup;
1730 if (rule->flags & IPRULE_ACTION)
1731 rtm.rtm_type = rule->action;
1732 else if (rule->flags & IPRULE_GOTO)
1733 rtm.rtm_type = FR_ACT_GOTO;
1734 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1735 rtm.rtm_type = FR_ACT_NOP;
1737 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1742 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1744 if (rule->flags & IPRULE_IN)
1745 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1747 if (rule->flags & IPRULE_OUT)
1748 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1750 if (rule->flags & IPRULE_SRC)
1751 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1753 if (rule->flags & IPRULE_DEST)
1754 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1756 if (rule->flags & IPRULE_PRIORITY)
1757 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1758 else if (cmd == RTM_NEWRULE)
1759 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1761 if (rule->flags & IPRULE_FWMARK)
1762 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1764 if (rule->flags & IPRULE_FWMASK)
1765 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1767 if (rule->flags & IPRULE_LOOKUP) {
1768 if (rule->lookup >= 256)
1769 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1772 if (rule->flags & IPRULE_GOTO)
1773 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1775 return system_rtnl_call(msg);
1778 int system_add_iprule(struct iprule *rule)
1780 return system_iprule(rule, RTM_NEWRULE);
1783 int system_del_iprule(struct iprule *rule)
1785 return system_iprule(rule, RTM_DELRULE);
1788 int system_flush_iprules(void)
1793 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1794 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1796 memset(&rule, 0, sizeof(rule));
1799 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1801 rule.priority = 128;
1802 rule.lookup = RT_TABLE_LOCAL;
1803 rv |= system_iprule(&rule, RTM_NEWRULE);
1805 rule.priority = 32766;
1806 rule.lookup = RT_TABLE_MAIN;
1807 rv |= system_iprule(&rule, RTM_NEWRULE);
1809 rule.priority = 32767;
1810 rule.lookup = RT_TABLE_DEFAULT;
1811 rv |= system_iprule(&rule, RTM_NEWRULE);
1814 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1816 rule.priority = 128;
1817 rule.lookup = RT_TABLE_LOCAL;
1818 rv |= system_iprule(&rule, RTM_NEWRULE);
1820 rule.priority = 32766;
1821 rule.lookup = RT_TABLE_MAIN;
1822 rv |= system_iprule(&rule, RTM_NEWRULE);
1827 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1829 return system_rtn_aton(action, id);
1832 time_t system_get_rtime(void)
1837 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1840 if (gettimeofday(&tv, NULL) == 0)
1847 #define IP_DF 0x4000
1850 static int tunnel_ioctl(const char *name, int cmd, void *p)
1854 memset(&ifr, 0, sizeof(ifr));
1855 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1856 ifr.ifr_ifru.ifru_data = p;
1857 return ioctl(sock_ioctl, cmd, &ifr);
1860 #ifdef IFLA_IPTUN_MAX
1861 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
1862 static int system_add_gre_tunnel(const char *name, const char *kind,
1863 const unsigned int link, struct blob_attr **tb, bool v6)
1866 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
1867 struct blob_attr *cur;
1868 uint32_t ikey = 0, okey = 0, flags = 0, flowinfo = 0;
1869 uint16_t iflags = 0, oflags = 0;
1871 int ret = 0, ttl = 64;
1873 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
1877 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
1878 nla_put_string(nlm, IFLA_IFNAME, name);
1880 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
1886 nla_put_string(nlm, IFLA_INFO_KIND, kind);
1887 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
1894 nla_put_u32(nlm, IFLA_GRE_LINK, link);
1896 if ((cur = tb[TUNNEL_ATTR_TTL]))
1897 ttl = blobmsg_get_u32(cur);
1899 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
1901 if ((cur = tb[TUNNEL_ATTR_TOS])) {
1902 char *str = blobmsg_get_string(cur);
1903 if (strcmp(str, "inherit")) {
1906 if (!system_tos_aton(str, &uval)) {
1912 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
1917 flags |= IP6_TNL_F_USE_ORIG_TCLASS;
1923 if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) {
1924 uint8_t icsum, ocsum, iseqno, oseqno;
1925 if (sscanf(blobmsg_get_string(cur), "%u,%u,%hhu,%hhu,%hhu,%hhu",
1926 &ikey, &okey, &icsum, &ocsum, &iseqno, &oseqno) < 6) {
1951 struct in6_addr in6buf;
1952 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1953 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1957 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
1960 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
1961 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1965 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
1967 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, 4);
1970 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
1973 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags);
1975 struct in_addr inbuf;
1978 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1979 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
1983 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
1986 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
1987 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
1991 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
1993 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
1995 okey = inbuf.s_addr;
2000 ikey = inbuf.s_addr;
2006 if ((cur = tb[TUNNEL_ATTR_DF]))
2007 set_df = blobmsg_get_bool(cur);
2009 /* ttl !=0 and nopmtudisc are incompatible */
2010 if (ttl && !set_df) {
2015 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
2017 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
2021 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
2024 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
2027 nla_put_u32(nlm, IFLA_GRE_OKEY, okey);
2030 nla_put_u32(nlm, IFLA_GRE_IKEY, ikey);
2032 nla_nest_end(nlm, infodata);
2033 nla_nest_end(nlm, linkinfo);
2035 return system_rtnl_call(nlm);
2043 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
2045 struct blob_attr *cur;
2047 struct ip_tunnel_parm p = {
2056 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
2057 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
2060 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
2061 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
2064 if ((cur = tb[TUNNEL_ATTR_DF]))
2065 set_df = blobmsg_get_bool(cur);
2067 if ((cur = tb[TUNNEL_ATTR_TTL]))
2068 p.iph.ttl = blobmsg_get_u32(cur);
2070 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2071 char *str = blobmsg_get_string(cur);
2072 if (strcmp(str, "inherit")) {
2075 if (!system_tos_aton(str, &uval))
2083 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
2084 /* ttl !=0 and nopmtudisc are incompatible */
2085 if (p.iph.ttl && p.iph.frag_off == 0)
2088 strncpy(p.name, name, sizeof(p.name));
2090 switch (p.iph.protocol) {
2092 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
2094 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
2101 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
2103 struct blob_attr *cur;
2106 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2108 str = blobmsg_data(cur);
2110 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
2111 !strcmp(str, "greip6") || !strcmp(str, "gretapip6"))
2112 return system_link_del(name);
2114 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
2117 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
2119 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2121 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2122 blob_data(attr), blob_len(attr));
2124 return __system_del_ip_tunnel(name, tb);
2127 int system_update_ipv6_mtu(struct device *dev, int mtu)
2131 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
2134 int fd = open(buf, O_RDWR);
2135 ssize_t len = read(fd, buf, sizeof(buf) - 1);
2142 if (!mtu || ret <= mtu)
2145 lseek(fd, 0, SEEK_SET);
2146 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) <= 0)
2154 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
2156 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2157 struct blob_attr *cur;
2160 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2161 blob_data(attr), blob_len(attr));
2163 __system_del_ip_tunnel(name, tb);
2165 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2167 str = blobmsg_data(cur);
2169 unsigned int ttl = 0;
2170 if ((cur = tb[TUNNEL_ATTR_TTL])) {
2171 ttl = blobmsg_get_u32(cur);
2176 unsigned int link = 0;
2177 if ((cur = tb[TUNNEL_ATTR_LINK])) {
2178 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
2182 if (iface->l3_dev.dev)
2183 link = iface->l3_dev.dev->ifindex;
2186 if (!strcmp(str, "sit")) {
2187 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
2191 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
2193 struct ip_tunnel_6rd p6;
2195 memset(&p6, 0, sizeof(p6));
2197 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
2198 &p6.prefix, &mask) || mask > 128)
2200 p6.prefixlen = mask;
2202 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
2203 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
2204 &p6.relay_prefix, &mask) || mask > 32)
2206 p6.relay_prefixlen = mask;
2209 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
2210 __system_del_ip_tunnel(name, tb);
2215 #ifdef IFLA_IPTUN_MAX
2216 } else if (!strcmp(str, "ipip6")) {
2217 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2218 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2219 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2225 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2226 nla_put_string(nlm, IFLA_IFNAME, name);
2229 nla_put_u32(nlm, IFLA_LINK, link);
2231 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2236 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2237 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2244 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2246 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2247 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2248 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
2250 struct in6_addr in6buf;
2251 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2252 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2256 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2259 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2260 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2264 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2267 #ifdef IFLA_IPTUN_FMR_MAX
2268 if ((cur = tb[TUNNEL_ATTR_FMRS])) {
2269 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2271 struct blob_attr *fmr;
2272 unsigned rem, fmrcnt = 0;
2273 blobmsg_for_each_attr(fmr, cur, rem) {
2274 if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
2277 unsigned ip4len, ip6len, ealen, offset = 6;
2281 if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
2282 ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) {
2287 struct in6_addr ip6prefix;
2288 struct in_addr ip4prefix;
2289 if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
2290 inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) {
2295 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2297 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2298 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2299 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2300 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2301 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2302 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2304 nla_nest_end(nlm, rule);
2307 nla_nest_end(nlm, fmrs);
2311 nla_nest_end(nlm, infodata);
2312 nla_nest_end(nlm, linkinfo);
2314 return system_rtnl_call(nlm);
2318 } else if (!strcmp(str, "greip")) {
2319 return system_add_gre_tunnel(name, "gre", link, tb, false);
2320 } else if (!strcmp(str, "gretapip")) {
2321 return system_add_gre_tunnel(name, "gretap", link, tb, false);
2322 } else if (!strcmp(str, "greip6")) {
2323 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
2324 } else if (!strcmp(str, "gretapip6")) {
2325 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
2327 } else if (!strcmp(str, "ipip")) {
2328 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);