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
50 #ifndef IFA_F_NOPREFIXROUTE
51 #define IFA_F_NOPREFIXROUTE 0x200
60 #include <netlink/msg.h>
61 #include <netlink/attr.h>
62 #include <netlink/socket.h>
63 #include <libubox/uloop.h>
70 struct uloop_fd uloop;
75 static int sock_ioctl = -1;
76 static struct nl_sock *sock_rtnl = NULL;
78 static int cb_rtnl_event(struct nl_msg *msg, void *arg);
79 static void handle_hotplug_event(struct uloop_fd *u, unsigned int events);
81 static char dev_buf[256];
84 handler_nl_event(struct uloop_fd *u, unsigned int events)
86 struct event_socket *ev = container_of(u, struct event_socket, uloop);
88 socklen_t errlen = sizeof(err);
91 nl_recvmsgs_default(ev->sock);
95 if (getsockopt(u->fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen))
100 // Increase rx buffer size on netlink socket
102 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
105 // Request full dump since some info got dropped
106 struct rtgenmsg msg = { .rtgen_family = AF_UNSPEC };
107 nl_send_simple(ev->sock, RTM_GETLINK, NLM_F_DUMP, &msg, sizeof(msg));
117 uloop_fd_delete(&ev->uloop);
121 static struct nl_sock *
122 create_socket(int protocol, int groups)
124 struct nl_sock *sock;
126 sock = nl_socket_alloc();
131 nl_join_groups(sock, groups);
133 if (nl_connect(sock, protocol))
140 create_raw_event_socket(struct event_socket *ev, int protocol, int groups,
141 uloop_fd_handler cb, int flags)
143 ev->sock = create_socket(protocol, groups);
147 ev->uloop.fd = nl_socket_get_fd(ev->sock);
149 if (uloop_fd_add(&ev->uloop, ULOOP_READ|flags))
156 create_event_socket(struct event_socket *ev, int protocol,
157 int (*cb)(struct nl_msg *msg, void *arg))
159 if (!create_raw_event_socket(ev, protocol, 0, handler_nl_event, ULOOP_ERROR_CB))
162 // Install the valid custom callback handler
163 nl_socket_modify_cb(ev->sock, NL_CB_VALID, NL_CB_CUSTOM, cb, NULL);
165 // Disable sequence number checking on event sockets
166 nl_socket_disable_seq_check(ev->sock);
168 // Increase rx buffer size to 65K on event sockets
170 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
177 system_rtn_aton(const char *src, unsigned int *dst)
182 if (!strcmp(src, "local"))
184 else if (!strcmp(src, "nat"))
186 else if (!strcmp(src, "broadcast"))
188 else if (!strcmp(src, "anycast"))
190 else if (!strcmp(src, "multicast"))
192 else if (!strcmp(src, "prohibit"))
194 else if (!strcmp(src, "unreachable"))
196 else if (!strcmp(src, "blackhole"))
198 else if (!strcmp(src, "xresolve"))
200 else if (!strcmp(src, "unicast"))
202 else if (!strcmp(src, "throw"))
204 else if (!strcmp(src, "failed_policy"))
205 n = RTN_FAILED_POLICY;
207 n = strtoul(src, &e, 0);
208 if (!e || *e || e == src || n > 255)
217 system_tos_aton(const char *src, unsigned *dst)
221 *dst = strtoul(src, &e, 16);
222 if (e == src || *e || *dst > 255)
228 int system_init(void)
230 static struct event_socket rtnl_event;
231 static struct event_socket hotplug_event;
233 sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0);
234 system_fd_set_cloexec(sock_ioctl);
236 // Prepare socket for routing / address control
237 sock_rtnl = create_socket(NETLINK_ROUTE, 0);
241 if (!create_event_socket(&rtnl_event, NETLINK_ROUTE, cb_rtnl_event))
244 if (!create_raw_event_socket(&hotplug_event, NETLINK_KOBJECT_UEVENT, 1,
245 handle_hotplug_event, 0))
248 // Receive network link events form kernel
249 nl_socket_add_membership(rtnl_event.sock, RTNLGRP_LINK);
254 static void system_set_sysctl(const char *path, const char *val)
258 fd = open(path, O_WRONLY);
262 if (write(fd, val, strlen(val))) {}
266 static void system_set_dev_sysctl(const char *path, const char *device, const char *val)
268 snprintf(dev_buf, sizeof(dev_buf), path, device);
269 system_set_sysctl(dev_buf, val);
272 static void system_set_disable_ipv6(struct device *dev, const char *val)
274 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val);
277 static void system_set_rpfilter(struct device *dev, const char *val)
279 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter", dev->ifname, val);
282 static void system_set_acceptlocal(struct device *dev, const char *val)
284 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local", dev->ifname, val);
287 static void system_set_igmpversion(struct device *dev, const char *val)
289 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version", dev->ifname, val);
292 static void system_set_mldversion(struct device *dev, const char *val)
294 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version", dev->ifname, val);
297 static void system_set_neigh4reachabletime(struct device *dev, const char *val)
299 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms", dev->ifname, val);
302 static void system_set_neigh6reachabletime(struct device *dev, const char *val)
304 system_set_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms", dev->ifname, val);
307 static int system_get_sysctl(const char *path, char *buf, const size_t buf_sz)
309 int fd = -1, ret = -1;
311 fd = open(path, O_RDONLY);
315 ssize_t len = read(fd, buf, buf_sz - 1);
329 system_get_dev_sysctl(const char *path, const char *device, char *buf, const size_t buf_sz)
331 snprintf(dev_buf, sizeof(dev_buf), path, device);
332 return system_get_sysctl(dev_buf, buf, buf_sz);
335 static int system_get_disable_ipv6(struct device *dev, char *buf, const size_t buf_sz)
337 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6",
338 dev->ifname, buf, buf_sz);
341 static int system_get_rpfilter(struct device *dev, char *buf, const size_t buf_sz)
343 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter",
344 dev->ifname, buf, buf_sz);
347 static int system_get_acceptlocal(struct device *dev, char *buf, const size_t buf_sz)
349 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local",
350 dev->ifname, buf, buf_sz);
353 static int system_get_igmpversion(struct device *dev, char *buf, const size_t buf_sz)
355 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version",
356 dev->ifname, buf, buf_sz);
359 static int system_get_mldversion(struct device *dev, char *buf, const size_t buf_sz)
361 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version",
362 dev->ifname, buf, buf_sz);
365 static int system_get_neigh4reachabletime(struct device *dev, char *buf, const size_t buf_sz)
367 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms",
368 dev->ifname, buf, buf_sz);
371 static int system_get_neigh6reachabletime(struct device *dev, char *buf, const size_t buf_sz)
373 return system_get_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms",
374 dev->ifname, buf, buf_sz);
377 // Evaluate netlink messages
378 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
380 struct nlmsghdr *nh = nlmsg_hdr(msg);
381 struct nlattr *nla[__IFLA_MAX];
385 if (nh->nlmsg_type != RTM_NEWLINK)
388 nlmsg_parse(nh, sizeof(struct ifinfomsg), nla, __IFLA_MAX - 1, NULL);
389 if (!nla[IFLA_IFNAME])
392 struct device *dev = device_get(nla_data(nla[IFLA_IFNAME]), false);
393 if (!dev || dev->type->keep_link_status)
396 if (!system_get_dev_sysctl("/sys/class/net/%s/carrier", dev->ifname, buf, sizeof(buf)))
397 link_state = strtoul(buf, NULL, 0);
399 device_set_link(dev, link_state ? true : false);
406 handle_hotplug_msg(char *data, int size)
408 const char *subsystem = NULL, *interface = NULL;
409 char *cur, *end, *sep;
414 if (!strncmp(data, "add@", 4))
416 else if (!strncmp(data, "remove@", 7))
421 skip = strlen(data) + 1;
424 for (cur = data + skip; cur < end; cur += skip) {
425 skip = strlen(cur) + 1;
427 sep = strchr(cur, '=');
432 if (!strcmp(cur, "INTERFACE"))
434 else if (!strcmp(cur, "SUBSYSTEM")) {
436 if (strcmp(subsystem, "net") != 0)
439 if (subsystem && interface)
445 dev = device_get(interface, false);
449 if (dev->type != &simple_device_type)
452 if (add && system_if_force_external(dev->ifname))
455 device_set_present(dev, add);
459 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
461 struct event_socket *ev = container_of(u, struct event_socket, uloop);
462 struct sockaddr_nl nla;
463 unsigned char *buf = NULL;
466 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
468 handle_hotplug_msg((char *) buf, size);
474 static int system_rtnl_call(struct nl_msg *msg)
478 ret = nl_send_auto_complete(sock_rtnl, msg);
484 return nl_wait_for_ack(sock_rtnl);
487 int system_bridge_delbr(struct device *bridge)
489 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
492 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
496 memset(&ifr, 0, sizeof(ifr));
498 ifr.ifr_ifindex = dev->ifindex;
501 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
502 return ioctl(sock_ioctl, cmd, &ifr);
505 static bool system_is_bridge(const char *name, char *buf, int buflen)
509 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
510 if (stat(buf, &st) < 0)
516 static char *system_get_bridge(const char *name, char *buf, int buflen)
522 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
523 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
527 len = readlink(gl.gl_pathv[0], buf, buflen);
535 path = strrchr(buf, '/');
542 static void system_bridge_set_wireless(const char *bridge, const char *dev)
544 snprintf(dev_buf, sizeof(dev_buf),
545 "/sys/devices/virtual/net/%s/brif/%s/multicast_to_unicast",
547 system_set_sysctl(dev_buf, "1");
550 int system_bridge_addif(struct device *bridge, struct device *dev)
555 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
556 if (!oldbr || strcmp(oldbr, bridge->ifname) != 0)
557 ret = system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
560 system_bridge_set_wireless(bridge->ifname, dev->ifname);
565 int system_bridge_delif(struct device *bridge, struct device *dev)
567 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
570 int system_if_resolve(struct device *dev)
573 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
574 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
575 return ifr.ifr_ifindex;
580 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
584 memset(&ifr, 0, sizeof(ifr));
585 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
586 ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
587 ifr.ifr_flags |= add;
588 ifr.ifr_flags &= ~rem;
589 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
601 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
603 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
605 return ifa->ifa_index == ifindex;
608 static bool check_route(struct nlmsghdr *hdr, int ifindex)
610 struct rtmsg *r = NLMSG_DATA(hdr);
611 struct nlattr *tb[__RTA_MAX];
613 if (r->rtm_protocol == RTPROT_KERNEL &&
614 r->rtm_family == AF_INET6)
617 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
621 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
624 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
629 static int cb_clear_event(struct nl_msg *msg, void *arg)
631 struct clear_data *clr = arg;
632 struct nlmsghdr *hdr = nlmsg_hdr(msg);
633 bool (*cb)(struct nlmsghdr *, int ifindex);
639 if (hdr->nlmsg_type != RTM_NEWADDR)
646 if (hdr->nlmsg_type != RTM_NEWROUTE)
653 if (hdr->nlmsg_type != RTM_NEWRULE)
662 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
665 if (type == RTM_DELRULE)
666 D(SYSTEM, "Remove a rule\n");
668 D(SYSTEM, "Remove %s from device %s\n",
669 type == RTM_DELADDR ? "an address" : "a route",
671 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
672 hdr = nlmsg_hdr(clr->msg);
673 hdr->nlmsg_type = type;
674 hdr->nlmsg_flags = NLM_F_REQUEST;
676 nl_socket_disable_auto_ack(sock_rtnl);
677 nl_send_auto_complete(sock_rtnl, clr->msg);
678 nl_socket_enable_auto_ack(sock_rtnl);
684 cb_finish_event(struct nl_msg *msg, void *arg)
692 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
695 *pending = err->error;
700 system_if_clear_entries(struct device *dev, int type, int af)
702 struct clear_data clr;
703 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
706 .rtm_flags = RTM_F_CLONED,
708 int flags = NLM_F_DUMP;
717 clr.size = sizeof(struct rtgenmsg);
720 clr.size = sizeof(struct rtmsg);
729 clr.msg = nlmsg_alloc_simple(type, flags);
733 nlmsg_append(clr.msg, &rtm, clr.size, 0);
734 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
735 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
736 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
738 nl_send_auto_complete(sock_rtnl, clr.msg);
740 nl_recvmsgs(sock_rtnl, cb);
748 * Clear bridge (membership) state and bring down device
750 void system_if_clear_state(struct device *dev)
752 static char buf[256];
755 device_set_ifindex(dev, system_if_resolve(dev));
756 if (dev->external || !dev->ifindex)
759 system_if_flags(dev->ifname, 0, IFF_UP);
761 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
762 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
763 system_bridge_delbr(dev);
767 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
769 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
770 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
773 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
774 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
775 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
776 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
777 system_set_disable_ipv6(dev, "0");
780 static inline unsigned long
781 sec_to_jiffies(int val)
783 return (unsigned long) val * 100;
786 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
788 unsigned long args[4] = {};
790 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
793 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
794 args[1] = !!cfg->stp;
795 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
797 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
798 args[1] = sec_to_jiffies(cfg->forward_delay);
799 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
801 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
802 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
804 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier",
805 bridge->ifname, cfg->multicast_querier ? "1" : "0");
807 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
808 args[1] = cfg->priority;
809 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
811 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
812 args[0] = BRCTL_SET_AGEING_TIME;
813 args[1] = sec_to_jiffies(cfg->ageing_time);
814 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
817 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
818 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
819 args[1] = sec_to_jiffies(cfg->hello_time);
820 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
823 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
824 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
825 args[1] = sec_to_jiffies(cfg->max_age);
826 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
832 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
835 struct nlattr *linkinfo, *data;
836 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
838 static const struct {
840 enum macvlan_mode val;
842 { "private", MACVLAN_MODE_PRIVATE },
843 { "vepa", MACVLAN_MODE_VEPA },
844 { "bridge", MACVLAN_MODE_BRIDGE },
845 { "passthru", MACVLAN_MODE_PASSTHRU },
848 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
853 nlmsg_append(msg, &iim, sizeof(iim), 0);
855 if (cfg->flags & MACVLAN_OPT_MACADDR)
856 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
857 nla_put_string(msg, IFLA_IFNAME, macvlan->ifname);
858 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
860 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
861 goto nla_put_failure;
863 nla_put_string(msg, IFLA_INFO_KIND, "macvlan");
865 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
866 goto nla_put_failure;
869 for (i = 0; i < ARRAY_SIZE(modes); i++) {
870 if (strcmp(cfg->mode, modes[i].name) != 0)
873 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
878 nla_nest_end(msg, data);
879 nla_nest_end(msg, linkinfo);
881 rv = system_rtnl_call(msg);
883 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
892 static int system_link_del(const char *ifname)
895 struct ifinfomsg iim = {
896 .ifi_family = AF_UNSPEC,
900 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
905 nlmsg_append(msg, &iim, sizeof(iim), 0);
906 nla_put_string(msg, IFLA_IFNAME, ifname);
907 return system_rtnl_call(msg);
910 int system_macvlan_del(struct device *macvlan)
912 return system_link_del(macvlan->ifname);
915 static int system_vlan(struct device *dev, int id)
917 struct vlan_ioctl_args ifr = {
918 .cmd = SET_VLAN_NAME_TYPE_CMD,
919 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
922 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
925 ifr.cmd = DEL_VLAN_CMD;
928 ifr.cmd = ADD_VLAN_CMD;
931 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
932 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
935 int system_vlan_add(struct device *dev, int id)
937 return system_vlan(dev, id);
940 int system_vlan_del(struct device *dev)
942 return system_vlan(dev, -1);
945 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
948 struct nlattr *linkinfo, *data;
949 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
952 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
957 nlmsg_append(msg, &iim, sizeof(iim), 0);
958 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
959 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
961 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
962 goto nla_put_failure;
964 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
966 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
967 goto nla_put_failure;
969 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
971 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
972 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
974 if(cfg->proto == VLAN_PROTO_8021AD)
975 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);
978 nla_nest_end(msg, data);
979 nla_nest_end(msg, linkinfo);
981 rv = system_rtnl_call(msg);
983 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
992 int system_vlandev_del(struct device *vlandev)
994 return system_link_del(vlandev->ifname);
998 system_if_get_settings(struct device *dev, struct device_settings *s)
1003 memset(&ifr, 0, sizeof(ifr));
1004 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1006 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
1007 s->mtu = ifr.ifr_mtu;
1008 s->flags |= DEV_OPT_MTU;
1011 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
1012 s->txqueuelen = ifr.ifr_qlen;
1013 s->flags |= DEV_OPT_TXQUEUELEN;
1016 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
1017 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
1018 s->flags |= DEV_OPT_MACADDR;
1021 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
1022 s->ipv6 = !strtoul(buf, NULL, 0);
1023 s->flags |= DEV_OPT_IPV6;
1026 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
1027 s->promisc = ifr.ifr_flags & IFF_PROMISC;
1028 s->flags |= DEV_OPT_PROMISC;
1031 if (!system_get_rpfilter(dev, buf, sizeof(buf))) {
1032 s->rpfilter = strtoul(buf, NULL, 0);
1033 s->flags |= DEV_OPT_RPFILTER;
1036 if (!system_get_acceptlocal(dev, buf, sizeof(buf))) {
1037 s->acceptlocal = strtoul(buf, NULL, 0);
1038 s->flags |= DEV_OPT_ACCEPTLOCAL;
1041 if (!system_get_igmpversion(dev, buf, sizeof(buf))) {
1042 s->igmpversion = strtoul(buf, NULL, 0);
1043 s->flags |= DEV_OPT_IGMPVERSION;
1046 if (!system_get_mldversion(dev, buf, sizeof(buf))) {
1047 s->mldversion = strtoul(buf, NULL, 0);
1048 s->flags |= DEV_OPT_MLDVERSION;
1051 if (!system_get_neigh4reachabletime(dev, buf, sizeof(buf))) {
1052 s->neigh4reachabletime = strtoul(buf, NULL, 0);
1053 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1056 if (!system_get_neigh6reachabletime(dev, buf, sizeof(buf))) {
1057 s->neigh6reachabletime = strtoul(buf, NULL, 0);
1058 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1063 system_if_set_rps_xps_val(const char *path, int val)
1069 if (glob(path, 0, NULL, &gl))
1072 snprintf(val_buf, sizeof(val_buf), "%x", val);
1073 for (i = 0; i < gl.gl_pathc; i++)
1074 system_set_sysctl(gl.gl_pathv[i], val_buf);
1078 system_if_apply_rps_xps(struct device *dev, struct device_settings *s)
1080 long n_cpus = sysconf(_SC_NPROCESSORS_ONLN);
1086 val = (1 << n_cpus) - 1;
1087 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/rps_cpus", dev->ifname);
1088 system_if_set_rps_xps_val(dev_buf, s->rps ? val : 0);
1090 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/xps_cpus", dev->ifname);
1091 system_if_set_rps_xps_val(dev_buf, s->xps ? val : 0);
1095 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
1099 memset(&ifr, 0, sizeof(ifr));
1100 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1101 if (s->flags & DEV_OPT_MTU & apply_mask) {
1102 ifr.ifr_mtu = s->mtu;
1103 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
1104 s->flags &= ~DEV_OPT_MTU;
1106 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
1107 ifr.ifr_qlen = s->txqueuelen;
1108 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
1109 s->flags &= ~DEV_OPT_TXQUEUELEN;
1111 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
1112 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
1113 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
1114 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
1115 s->flags &= ~DEV_OPT_MACADDR;
1117 if (s->flags & DEV_OPT_IPV6 & apply_mask)
1118 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
1119 if (s->flags & DEV_OPT_PROMISC & apply_mask) {
1120 if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
1121 !s->promisc ? IFF_PROMISC : 0) < 0)
1122 s->flags &= ~DEV_OPT_PROMISC;
1124 if (s->flags & DEV_OPT_RPFILTER & apply_mask) {
1127 snprintf(buf, sizeof(buf), "%d", s->rpfilter);
1128 system_set_rpfilter(dev, buf);
1130 if (s->flags & DEV_OPT_ACCEPTLOCAL & apply_mask)
1131 system_set_acceptlocal(dev, s->acceptlocal ? "1" : "0");
1132 if (s->flags & DEV_OPT_IGMPVERSION & apply_mask) {
1135 snprintf(buf, sizeof(buf), "%d", s->igmpversion);
1136 system_set_igmpversion(dev, buf);
1138 if (s->flags & DEV_OPT_MLDVERSION & apply_mask) {
1141 snprintf(buf, sizeof(buf), "%d", s->mldversion);
1142 system_set_mldversion(dev, buf);
1144 if (s->flags & DEV_OPT_NEIGHREACHABLETIME & apply_mask) {
1147 snprintf(buf, sizeof(buf), "%d", s->neigh4reachabletime);
1148 system_set_neigh4reachabletime(dev, buf);
1149 snprintf(buf, sizeof(buf), "%d", s->neigh6reachabletime);
1150 system_set_neigh6reachabletime(dev, buf);
1153 system_if_apply_rps_xps(dev, s);
1156 int system_if_up(struct device *dev)
1158 system_if_get_settings(dev, &dev->orig_settings);
1159 /* Only keep orig settings based on what needs to be set */
1160 dev->orig_settings.flags &= dev->settings.flags;
1161 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
1162 return system_if_flags(dev->ifname, IFF_UP, 0);
1165 int system_if_down(struct device *dev)
1167 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
1168 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
1172 struct if_check_data {
1178 #ifndef IFF_LOWER_UP
1179 #define IFF_LOWER_UP 0x10000
1182 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1184 struct nlmsghdr *nh = nlmsg_hdr(msg);
1185 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1186 struct if_check_data *chk = (struct if_check_data *)arg;
1188 if (nh->nlmsg_type != RTM_NEWLINK)
1191 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1192 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1197 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1199 struct if_check_data *chk = (struct if_check_data *)arg;
1204 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1206 struct if_check_data *chk = (struct if_check_data *)arg;
1208 device_set_present(chk->dev, false);
1209 device_set_link(chk->dev, false);
1210 chk->pending = err->error;
1215 int system_if_check(struct device *dev)
1217 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1219 struct ifinfomsg ifi = {
1220 .ifi_family = AF_UNSPEC,
1223 struct if_check_data chk = {
1229 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1230 if (!msg || nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1231 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1234 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1235 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1236 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1238 nl_send_auto_complete(sock_rtnl, msg);
1239 while (chk.pending > 0)
1240 nl_recvmsgs(sock_rtnl, cb);
1251 system_if_get_parent(struct device *dev)
1253 char buf[64], *devname;
1254 int ifindex, iflink, len;
1257 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1258 f = fopen(buf, "r");
1262 len = fread(buf, 1, sizeof(buf) - 1, f);
1269 iflink = strtoul(buf, NULL, 0);
1270 ifindex = system_if_resolve(dev);
1271 if (!iflink || iflink == ifindex)
1274 devname = if_indextoname(iflink, buf);
1278 return device_get(devname, true);
1282 read_string_file(int dir_fd, const char *file, char *buf, int len)
1288 fd = openat(dir_fd, file, O_RDONLY);
1293 len = read(fd, buf, len - 1);
1297 } else if (len > 0) {
1300 c = strchr(buf, '\n');
1313 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1318 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1320 *val = strtoull(buf, NULL, 0);
1325 /* Assume advertised flags == supported flags */
1326 static const struct {
1329 } ethtool_link_modes[] = {
1330 { ADVERTISED_10baseT_Half, "10H" },
1331 { ADVERTISED_10baseT_Full, "10F" },
1332 { ADVERTISED_100baseT_Half, "100H" },
1333 { ADVERTISED_100baseT_Full, "100F" },
1334 { ADVERTISED_1000baseT_Half, "1000H" },
1335 { ADVERTISED_1000baseT_Full, "1000F" },
1338 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1341 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1342 if (mask & ethtool_link_modes[i].mask)
1343 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1348 system_if_force_external(const char *ifname)
1353 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1354 return stat(buf, &s) == 0;
1358 system_if_dump_info(struct device *dev, struct blob_buf *b)
1360 struct ethtool_cmd ecmd;
1366 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
1367 dir_fd = open(buf, O_DIRECTORY);
1369 memset(&ecmd, 0, sizeof(ecmd));
1370 memset(&ifr, 0, sizeof(ifr));
1371 strcpy(ifr.ifr_name, dev->ifname);
1372 ifr.ifr_data = (caddr_t) &ecmd;
1373 ecmd.cmd = ETHTOOL_GSET;
1375 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1376 c = blobmsg_open_array(b, "link-advertising");
1377 system_add_link_modes(b, ecmd.advertising);
1378 blobmsg_close_array(b, c);
1380 c = blobmsg_open_array(b, "link-supported");
1381 system_add_link_modes(b, ecmd.supported);
1382 blobmsg_close_array(b, c);
1384 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1385 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1386 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1387 blobmsg_add_string_buffer(b);
1395 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1397 const char *const counters[] = {
1398 "collisions", "rx_frame_errors", "tx_compressed",
1399 "multicast", "rx_length_errors", "tx_dropped",
1400 "rx_bytes", "rx_missed_errors", "tx_errors",
1401 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1402 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1403 "rx_dropped", "tx_aborted_errors", "tx_packets",
1404 "rx_errors", "tx_bytes", "tx_window_errors",
1405 "rx_fifo_errors", "tx_carrier_errors",
1412 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1413 stats_dir = open(buf, O_DIRECTORY);
1417 for (i = 0; i < ARRAY_SIZE(counters); i++)
1418 if (read_uint64_file(stats_dir, counters[i], &val))
1419 blobmsg_add_u64(b, counters[i], val);
1425 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1427 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1428 int alen = v4 ? 4 : 16;
1429 unsigned int flags = 0;
1430 struct ifaddrmsg ifa = {
1431 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1432 .ifa_prefixlen = addr->mask,
1433 .ifa_index = dev->ifindex,
1434 .ifa_flags = (addr->flags & DEVADDR_OFFLINK) ? IFA_F_NOPREFIXROUTE : 0,
1438 if (cmd == RTM_NEWADDR)
1439 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1441 msg = nlmsg_alloc_simple(cmd, flags);
1445 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1446 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1448 if (addr->broadcast)
1449 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1450 if (addr->point_to_point)
1451 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1453 time_t now = system_get_rtime();
1454 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1456 if (addr->preferred_until) {
1457 int64_t preferred = addr->preferred_until - now;
1460 else if (preferred > UINT32_MAX)
1461 preferred = UINT32_MAX;
1463 cinfo.ifa_prefered = preferred;
1466 if (addr->valid_until) {
1467 int64_t valid = addr->valid_until - now;
1470 else if (valid > UINT32_MAX)
1473 cinfo.ifa_valid = valid;
1476 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1479 return system_rtnl_call(msg);
1482 int system_add_address(struct device *dev, struct device_addr *addr)
1484 return system_addr(dev, addr, RTM_NEWADDR);
1487 int system_del_address(struct device *dev, struct device_addr *addr)
1489 return system_addr(dev, addr, RTM_DELADDR);
1492 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1494 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1496 unsigned int flags = 0;
1499 have_gw = !!route->nexthop.in.s_addr;
1501 have_gw = route->nexthop.in6.s6_addr32[0] ||
1502 route->nexthop.in6.s6_addr32[1] ||
1503 route->nexthop.in6.s6_addr32[2] ||
1504 route->nexthop.in6.s6_addr32[3];
1506 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1507 ? route->table : RT_TABLE_MAIN;
1509 struct rtmsg rtm = {
1510 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1511 .rtm_dst_len = route->mask,
1512 .rtm_src_len = route->sourcemask,
1513 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1514 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
1515 .rtm_scope = RT_SCOPE_NOWHERE,
1516 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1517 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1521 if (cmd == RTM_NEWROUTE) {
1522 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1524 if (!dev) { // Add null-route
1525 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1526 rtm.rtm_type = RTN_UNREACHABLE;
1529 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1532 if (route->flags & DEVROUTE_TYPE) {
1533 rtm.rtm_type = route->type;
1534 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
1535 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
1536 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
1537 rtm.rtm_table = RT_TABLE_LOCAL;
1540 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT) {
1541 rtm.rtm_scope = RT_SCOPE_HOST;
1542 } else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
1543 rtm.rtm_type == RTN_ANYCAST) {
1544 rtm.rtm_scope = RT_SCOPE_LINK;
1545 } else if (rtm.rtm_type == RTN_BLACKHOLE || rtm.rtm_type == RTN_UNREACHABLE ||
1546 rtm.rtm_type == RTN_PROHIBIT || rtm.rtm_type == RTN_FAILED_POLICY) {
1547 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1552 msg = nlmsg_alloc_simple(cmd, flags);
1556 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1559 nla_put(msg, RTA_DST, alen, &route->addr);
1561 if (route->sourcemask) {
1562 if (rtm.rtm_family == AF_INET)
1563 nla_put(msg, RTA_PREFSRC, alen, &route->source);
1565 nla_put(msg, RTA_SRC, alen, &route->source);
1568 if (route->metric > 0)
1569 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1572 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1575 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1578 nla_put_u32(msg, RTA_TABLE, table);
1580 if (route->flags & DEVROUTE_MTU) {
1581 struct nlattr *metrics;
1583 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1584 goto nla_put_failure;
1586 nla_put_u32(msg, RTAX_MTU, route->mtu);
1588 nla_nest_end(msg, metrics);
1591 return system_rtnl_call(msg);
1598 int system_add_route(struct device *dev, struct device_route *route)
1600 return system_rt(dev, route, RTM_NEWROUTE);
1603 int system_del_route(struct device *dev, struct device_route *route)
1605 return system_rt(dev, route, RTM_DELROUTE);
1608 int system_flush_routes(void)
1610 const char *names[] = {
1611 "/proc/sys/net/ipv4/route/flush",
1612 "/proc/sys/net/ipv6/route/flush"
1616 for (i = 0; i < ARRAY_SIZE(names); i++) {
1617 fd = open(names[i], O_WRONLY);
1621 if (write(fd, "-1", 2)) {}
1627 bool system_resolve_rt_type(const char *type, unsigned int *id)
1629 return system_rtn_aton(type, id);
1632 bool system_resolve_rt_table(const char *name, unsigned int *id)
1636 unsigned int n, table = RT_TABLE_UNSPEC;
1638 /* first try to parse table as number */
1639 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1642 /* handle well known aliases */
1643 else if (!strcmp(name, "default"))
1644 table = RT_TABLE_DEFAULT;
1645 else if (!strcmp(name, "main"))
1646 table = RT_TABLE_MAIN;
1647 else if (!strcmp(name, "local"))
1648 table = RT_TABLE_LOCAL;
1649 else if (!strcmp(name, "prelocal"))
1650 table = RT_TABLE_PRELOCAL;
1652 /* try to look up name in /etc/iproute2/rt_tables */
1653 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1655 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1657 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1660 n = strtoul(e, NULL, 10);
1661 e = strtok(NULL, " \t\n");
1663 if (e && !strcmp(e, name))
1673 if (table == RT_TABLE_UNSPEC)
1680 bool system_is_default_rt_table(unsigned int id)
1682 return (id == RT_TABLE_MAIN);
1685 bool system_resolve_rpfilter(const char *filter, unsigned int *id)
1690 if (!strcmp(filter, "strict"))
1692 else if (!strcmp(filter, "loose"))
1695 n = strtoul(filter, &e, 0);
1696 if (*e || e == filter || n > 2)
1704 static int system_iprule(struct iprule *rule, int cmd)
1706 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1709 struct rtmsg rtm = {
1710 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1711 .rtm_protocol = RTPROT_STATIC,
1712 .rtm_scope = RT_SCOPE_UNIVERSE,
1713 .rtm_table = RT_TABLE_UNSPEC,
1714 .rtm_type = RTN_UNSPEC,
1718 if (cmd == RTM_NEWRULE) {
1719 rtm.rtm_type = RTN_UNICAST;
1720 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1724 rtm.rtm_flags |= FIB_RULE_INVERT;
1726 if (rule->flags & IPRULE_SRC)
1727 rtm.rtm_src_len = rule->src_mask;
1729 if (rule->flags & IPRULE_DEST)
1730 rtm.rtm_dst_len = rule->dest_mask;
1732 if (rule->flags & IPRULE_TOS)
1733 rtm.rtm_tos = rule->tos;
1735 if (rule->flags & IPRULE_LOOKUP) {
1736 if (rule->lookup < 256)
1737 rtm.rtm_table = rule->lookup;
1740 if (rule->flags & IPRULE_ACTION)
1741 rtm.rtm_type = rule->action;
1742 else if (rule->flags & IPRULE_GOTO)
1743 rtm.rtm_type = FR_ACT_GOTO;
1744 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1745 rtm.rtm_type = FR_ACT_NOP;
1747 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1752 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1754 if (rule->flags & IPRULE_IN)
1755 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1757 if (rule->flags & IPRULE_OUT)
1758 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1760 if (rule->flags & IPRULE_SRC)
1761 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1763 if (rule->flags & IPRULE_DEST)
1764 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1766 if (rule->flags & IPRULE_PRIORITY)
1767 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1768 else if (cmd == RTM_NEWRULE)
1769 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1771 if (rule->flags & IPRULE_FWMARK)
1772 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1774 if (rule->flags & IPRULE_FWMASK)
1775 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1777 if (rule->flags & IPRULE_LOOKUP) {
1778 if (rule->lookup >= 256)
1779 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1782 if (rule->flags & IPRULE_GOTO)
1783 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1785 return system_rtnl_call(msg);
1788 int system_add_iprule(struct iprule *rule)
1790 return system_iprule(rule, RTM_NEWRULE);
1793 int system_del_iprule(struct iprule *rule)
1795 return system_iprule(rule, RTM_DELRULE);
1798 int system_flush_iprules(void)
1803 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1804 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1806 memset(&rule, 0, sizeof(rule));
1809 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1812 rule.lookup = RT_TABLE_PRELOCAL;
1813 rv |= system_iprule(&rule, RTM_NEWRULE);
1816 rule.lookup = RT_TABLE_LOCAL;
1817 rv |= system_iprule(&rule, RTM_NEWRULE);
1819 rule.priority = 32766;
1820 rule.lookup = RT_TABLE_MAIN;
1821 rv |= system_iprule(&rule, RTM_NEWRULE);
1823 rule.priority = 32767;
1824 rule.lookup = RT_TABLE_DEFAULT;
1825 rv |= system_iprule(&rule, RTM_NEWRULE);
1828 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1831 rule.lookup = RT_TABLE_PRELOCAL;
1832 rv |= system_iprule(&rule, RTM_NEWRULE);
1835 rule.lookup = RT_TABLE_LOCAL;
1836 rv |= system_iprule(&rule, RTM_NEWRULE);
1838 rule.priority = 32766;
1839 rule.lookup = RT_TABLE_MAIN;
1840 rv |= system_iprule(&rule, RTM_NEWRULE);
1845 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1847 return system_rtn_aton(action, id);
1850 time_t system_get_rtime(void)
1855 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1858 if (gettimeofday(&tv, NULL) == 0)
1865 #define IP_DF 0x4000
1868 static int tunnel_ioctl(const char *name, int cmd, void *p)
1872 memset(&ifr, 0, sizeof(ifr));
1873 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1874 ifr.ifr_ifru.ifru_data = p;
1875 return ioctl(sock_ioctl, cmd, &ifr);
1878 #ifdef IFLA_IPTUN_MAX
1879 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
1880 static int system_add_gre_tunnel(const char *name, const char *kind,
1881 const unsigned int link, struct blob_attr **tb, bool v6)
1884 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
1885 struct blob_attr *cur;
1886 uint32_t ikey = 0, okey = 0, flags = 0, flowinfo = 0;
1887 uint16_t iflags = 0, oflags = 0;
1889 int ret = 0, ttl = 64;
1891 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
1895 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
1896 nla_put_string(nlm, IFLA_IFNAME, name);
1898 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
1904 nla_put_string(nlm, IFLA_INFO_KIND, kind);
1905 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
1912 nla_put_u32(nlm, IFLA_GRE_LINK, link);
1914 if ((cur = tb[TUNNEL_ATTR_TTL]))
1915 ttl = blobmsg_get_u32(cur);
1917 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
1919 if ((cur = tb[TUNNEL_ATTR_TOS])) {
1920 char *str = blobmsg_get_string(cur);
1921 if (strcmp(str, "inherit")) {
1924 if (!system_tos_aton(str, &uval)) {
1930 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
1935 flags |= IP6_TNL_F_USE_ORIG_TCLASS;
1941 if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) {
1942 uint8_t icsum, ocsum, iseqno, oseqno;
1943 if (sscanf(blobmsg_get_string(cur), "%u,%u,%hhu,%hhu,%hhu,%hhu",
1944 &ikey, &okey, &icsum, &ocsum, &iseqno, &oseqno) < 6) {
1969 struct in6_addr in6buf;
1970 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1971 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1975 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
1978 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
1979 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1983 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
1985 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, 4);
1988 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
1991 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags);
1993 struct in_addr inbuf;
1996 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1997 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2001 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
2004 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2005 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2009 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
2011 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
2013 okey = inbuf.s_addr;
2018 ikey = inbuf.s_addr;
2024 if ((cur = tb[TUNNEL_ATTR_DF]))
2025 set_df = blobmsg_get_bool(cur);
2027 /* ttl !=0 and nopmtudisc are incompatible */
2028 if (ttl && !set_df) {
2033 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
2035 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
2039 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
2042 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
2045 nla_put_u32(nlm, IFLA_GRE_OKEY, okey);
2048 nla_put_u32(nlm, IFLA_GRE_IKEY, ikey);
2050 nla_nest_end(nlm, infodata);
2051 nla_nest_end(nlm, linkinfo);
2053 return system_rtnl_call(nlm);
2061 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
2063 struct blob_attr *cur;
2065 struct ip_tunnel_parm p = {
2074 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
2075 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
2078 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
2079 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
2082 if ((cur = tb[TUNNEL_ATTR_DF]))
2083 set_df = blobmsg_get_bool(cur);
2085 if ((cur = tb[TUNNEL_ATTR_TTL]))
2086 p.iph.ttl = blobmsg_get_u32(cur);
2088 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2089 char *str = blobmsg_get_string(cur);
2090 if (strcmp(str, "inherit")) {
2093 if (!system_tos_aton(str, &uval))
2101 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
2102 /* ttl !=0 and nopmtudisc are incompatible */
2103 if (p.iph.ttl && p.iph.frag_off == 0)
2106 strncpy(p.name, name, sizeof(p.name));
2108 switch (p.iph.protocol) {
2110 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
2112 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
2119 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
2121 struct blob_attr *cur;
2124 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2126 str = blobmsg_data(cur);
2128 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
2129 !strcmp(str, "greip6") || !strcmp(str, "gretapip6"))
2130 return system_link_del(name);
2132 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
2135 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
2137 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2139 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2140 blob_data(attr), blob_len(attr));
2142 return __system_del_ip_tunnel(name, tb);
2145 int system_update_ipv6_mtu(struct device *dev, int mtu)
2149 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
2152 int fd = open(buf, O_RDWR);
2153 ssize_t len = read(fd, buf, sizeof(buf) - 1);
2160 if (!mtu || ret <= mtu)
2163 lseek(fd, 0, SEEK_SET);
2164 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) <= 0)
2172 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
2174 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2175 struct blob_attr *cur;
2178 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2179 blob_data(attr), blob_len(attr));
2181 __system_del_ip_tunnel(name, tb);
2183 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2185 str = blobmsg_data(cur);
2187 unsigned int ttl = 0;
2188 if ((cur = tb[TUNNEL_ATTR_TTL])) {
2189 ttl = blobmsg_get_u32(cur);
2194 unsigned int link = 0;
2195 if ((cur = tb[TUNNEL_ATTR_LINK])) {
2196 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
2200 if (iface->l3_dev.dev)
2201 link = iface->l3_dev.dev->ifindex;
2204 if (!strcmp(str, "sit")) {
2205 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
2209 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
2211 struct ip_tunnel_6rd p6;
2213 memset(&p6, 0, sizeof(p6));
2215 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
2216 &p6.prefix, &mask) || mask > 128)
2218 p6.prefixlen = mask;
2220 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
2221 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
2222 &p6.relay_prefix, &mask) || mask > 32)
2224 p6.relay_prefixlen = mask;
2227 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
2228 __system_del_ip_tunnel(name, tb);
2233 #ifdef IFLA_IPTUN_MAX
2234 } else if (!strcmp(str, "ipip6")) {
2235 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2236 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2237 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2243 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2244 nla_put_string(nlm, IFLA_IFNAME, name);
2247 nla_put_u32(nlm, IFLA_LINK, link);
2249 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2254 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2255 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2262 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2264 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2265 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2266 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
2268 struct in6_addr in6buf;
2269 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2270 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2274 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2277 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2278 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2282 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2285 #ifdef IFLA_IPTUN_FMR_MAX
2286 if ((cur = tb[TUNNEL_ATTR_FMRS])) {
2287 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2289 struct blob_attr *fmr;
2290 unsigned rem, fmrcnt = 0;
2291 blobmsg_for_each_attr(fmr, cur, rem) {
2292 if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
2295 unsigned ip4len, ip6len, ealen, offset = 6;
2299 if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
2300 ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) {
2305 struct in6_addr ip6prefix;
2306 struct in_addr ip4prefix;
2307 if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
2308 inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) {
2313 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2315 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2316 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2317 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2318 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2319 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2320 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2322 nla_nest_end(nlm, rule);
2325 nla_nest_end(nlm, fmrs);
2329 nla_nest_end(nlm, infodata);
2330 nla_nest_end(nlm, linkinfo);
2332 return system_rtnl_call(nlm);
2336 } else if (!strcmp(str, "greip")) {
2337 return system_add_gre_tunnel(name, "gre", link, tb, false);
2338 } else if (!strcmp(str, "gretapip")) {
2339 return system_add_gre_tunnel(name, "gretap", link, tb, false);
2340 } else if (!strcmp(str, "greip6")) {
2341 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
2342 } else if (!strcmp(str, "gretapip6")) {
2343 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
2345 } else if (!strcmp(str, "ipip")) {
2346 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);