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_addr.h>
34 #include <linux/if_link.h>
35 #include <linux/if_vlan.h>
36 #include <linux/if_bridge.h>
37 #include <linux/if_tunnel.h>
38 #include <linux/ip6_tunnel.h>
39 #include <linux/ethtool.h>
40 #include <linux/fib_rules.h>
41 #include <linux/version.h>
43 #ifndef RTN_FAILED_POLICY
44 #define RTN_FAILED_POLICY 12
47 #ifndef RT_TABLE_PRELOCAL
48 #define RT_TABLE_PRELOCAL 128
51 #ifndef IFA_F_NOPREFIXROUTE
52 #define IFA_F_NOPREFIXROUTE 0x200
56 #define IFA_FLAGS (IFA_MULTICAST + 1)
66 #include <netlink/msg.h>
67 #include <netlink/attr.h>
68 #include <netlink/socket.h>
69 #include <libubox/uloop.h>
76 struct uloop_fd uloop;
81 static int sock_ioctl = -1;
82 static struct nl_sock *sock_rtnl = NULL;
84 static int cb_rtnl_event(struct nl_msg *msg, void *arg);
85 static void handle_hotplug_event(struct uloop_fd *u, unsigned int events);
87 static char dev_buf[256];
90 handler_nl_event(struct uloop_fd *u, unsigned int events)
92 struct event_socket *ev = container_of(u, struct event_socket, uloop);
94 socklen_t errlen = sizeof(err);
97 nl_recvmsgs_default(ev->sock);
101 if (getsockopt(u->fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen))
106 // Increase rx buffer size on netlink socket
108 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
111 // Request full dump since some info got dropped
112 struct rtgenmsg msg = { .rtgen_family = AF_UNSPEC };
113 nl_send_simple(ev->sock, RTM_GETLINK, NLM_F_DUMP, &msg, sizeof(msg));
123 uloop_fd_delete(&ev->uloop);
127 static struct nl_sock *
128 create_socket(int protocol, int groups)
130 struct nl_sock *sock;
132 sock = nl_socket_alloc();
137 nl_join_groups(sock, groups);
139 if (nl_connect(sock, protocol))
146 create_raw_event_socket(struct event_socket *ev, int protocol, int groups,
147 uloop_fd_handler cb, int flags)
149 ev->sock = create_socket(protocol, groups);
153 ev->uloop.fd = nl_socket_get_fd(ev->sock);
155 if (uloop_fd_add(&ev->uloop, ULOOP_READ|flags))
162 create_event_socket(struct event_socket *ev, int protocol,
163 int (*cb)(struct nl_msg *msg, void *arg))
165 if (!create_raw_event_socket(ev, protocol, 0, handler_nl_event, ULOOP_ERROR_CB))
168 // Install the valid custom callback handler
169 nl_socket_modify_cb(ev->sock, NL_CB_VALID, NL_CB_CUSTOM, cb, NULL);
171 // Disable sequence number checking on event sockets
172 nl_socket_disable_seq_check(ev->sock);
174 // Increase rx buffer size to 65K on event sockets
176 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
183 system_rtn_aton(const char *src, unsigned int *dst)
188 if (!strcmp(src, "local"))
190 else if (!strcmp(src, "nat"))
192 else if (!strcmp(src, "broadcast"))
194 else if (!strcmp(src, "anycast"))
196 else if (!strcmp(src, "multicast"))
198 else if (!strcmp(src, "prohibit"))
200 else if (!strcmp(src, "unreachable"))
202 else if (!strcmp(src, "blackhole"))
204 else if (!strcmp(src, "xresolve"))
206 else if (!strcmp(src, "unicast"))
208 else if (!strcmp(src, "throw"))
210 else if (!strcmp(src, "failed_policy"))
211 n = RTN_FAILED_POLICY;
213 n = strtoul(src, &e, 0);
214 if (!e || *e || e == src || n > 255)
223 system_tos_aton(const char *src, unsigned *dst)
227 *dst = strtoul(src, &e, 16);
228 if (e == src || *e || *dst > 255)
234 int system_init(void)
236 static struct event_socket rtnl_event;
237 static struct event_socket hotplug_event;
239 sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0);
240 system_fd_set_cloexec(sock_ioctl);
242 // Prepare socket for routing / address control
243 sock_rtnl = create_socket(NETLINK_ROUTE, 0);
247 if (!create_event_socket(&rtnl_event, NETLINK_ROUTE, cb_rtnl_event))
250 if (!create_raw_event_socket(&hotplug_event, NETLINK_KOBJECT_UEVENT, 1,
251 handle_hotplug_event, 0))
254 // Receive network link events form kernel
255 nl_socket_add_membership(rtnl_event.sock, RTNLGRP_LINK);
260 static void system_set_sysctl(const char *path, const char *val)
264 fd = open(path, O_WRONLY);
268 if (write(fd, val, strlen(val))) {}
272 static void system_set_dev_sysctl(const char *path, const char *device, const char *val)
274 snprintf(dev_buf, sizeof(dev_buf), path, device);
275 system_set_sysctl(dev_buf, val);
278 static void system_set_disable_ipv6(struct device *dev, const char *val)
280 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val);
283 static void system_set_rpfilter(struct device *dev, const char *val)
285 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter", dev->ifname, val);
288 static void system_set_acceptlocal(struct device *dev, const char *val)
290 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local", dev->ifname, val);
293 static void system_set_igmpversion(struct device *dev, const char *val)
295 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version", dev->ifname, val);
298 static void system_set_mldversion(struct device *dev, const char *val)
300 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version", dev->ifname, val);
303 static void system_set_neigh4reachabletime(struct device *dev, const char *val)
305 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms", dev->ifname, val);
308 static void system_set_neigh6reachabletime(struct device *dev, const char *val)
310 system_set_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms", dev->ifname, val);
313 static void system_set_dadtransmits(struct device *dev, const char *val)
315 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits", dev->ifname, val);
318 static void system_bridge_set_multicast_to_unicast(struct device *dev, const char *val)
320 system_set_dev_sysctl("/sys/class/net/%s/brport/multicast_to_unicast", dev->ifname, val);
323 static void system_bridge_set_hairpin_mode(struct device *dev, const char *val)
325 system_set_dev_sysctl("/sys/class/net/%s/brport/hairpin_mode", dev->ifname, val);
328 static void system_bridge_set_multicast_router(struct device *dev, const char *val, bool bridge)
330 system_set_dev_sysctl(bridge ? "/sys/class/net/%s/bridge/multicast_router" :
331 "/sys/class/net/%s/brport/multicast_router",
335 static int system_get_sysctl(const char *path, char *buf, const size_t buf_sz)
337 int fd = -1, ret = -1;
339 fd = open(path, O_RDONLY);
343 ssize_t len = read(fd, buf, buf_sz - 1);
357 system_get_dev_sysctl(const char *path, const char *device, char *buf, const size_t buf_sz)
359 snprintf(dev_buf, sizeof(dev_buf), path, device);
360 return system_get_sysctl(dev_buf, buf, buf_sz);
363 static int system_get_disable_ipv6(struct device *dev, char *buf, const size_t buf_sz)
365 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6",
366 dev->ifname, buf, buf_sz);
369 static int system_get_rpfilter(struct device *dev, char *buf, const size_t buf_sz)
371 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter",
372 dev->ifname, buf, buf_sz);
375 static int system_get_acceptlocal(struct device *dev, char *buf, const size_t buf_sz)
377 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local",
378 dev->ifname, buf, buf_sz);
381 static int system_get_igmpversion(struct device *dev, char *buf, const size_t buf_sz)
383 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version",
384 dev->ifname, buf, buf_sz);
387 static int system_get_mldversion(struct device *dev, char *buf, const size_t buf_sz)
389 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version",
390 dev->ifname, buf, buf_sz);
393 static int system_get_neigh4reachabletime(struct device *dev, char *buf, const size_t buf_sz)
395 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms",
396 dev->ifname, buf, buf_sz);
399 static int system_get_neigh6reachabletime(struct device *dev, char *buf, const size_t buf_sz)
401 return system_get_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms",
402 dev->ifname, buf, buf_sz);
405 static int system_get_dadtransmits(struct device *dev, char *buf, const size_t buf_sz)
407 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits",
408 dev->ifname, buf, buf_sz);
411 // Evaluate netlink messages
412 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
414 struct nlmsghdr *nh = nlmsg_hdr(msg);
415 struct nlattr *nla[__IFLA_MAX];
419 if (nh->nlmsg_type != RTM_NEWLINK)
422 nlmsg_parse(nh, sizeof(struct ifinfomsg), nla, __IFLA_MAX - 1, NULL);
423 if (!nla[IFLA_IFNAME])
426 struct device *dev = device_get(nla_data(nla[IFLA_IFNAME]), false);
427 if (!dev || dev->type->keep_link_status)
430 if (!system_get_dev_sysctl("/sys/class/net/%s/carrier", dev->ifname, buf, sizeof(buf)))
431 link_state = strtoul(buf, NULL, 0);
433 device_set_link(dev, link_state ? true : false);
440 handle_hotplug_msg(char *data, int size)
442 const char *subsystem = NULL, *interface = NULL;
443 char *cur, *end, *sep;
448 if (!strncmp(data, "add@", 4))
450 else if (!strncmp(data, "remove@", 7))
455 skip = strlen(data) + 1;
458 for (cur = data + skip; cur < end; cur += skip) {
459 skip = strlen(cur) + 1;
461 sep = strchr(cur, '=');
466 if (!strcmp(cur, "INTERFACE"))
468 else if (!strcmp(cur, "SUBSYSTEM")) {
470 if (strcmp(subsystem, "net") != 0)
473 if (subsystem && interface)
479 dev = device_get(interface, false);
483 if (dev->type != &simple_device_type)
486 if (add && system_if_force_external(dev->ifname))
489 device_set_present(dev, add);
493 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
495 struct event_socket *ev = container_of(u, struct event_socket, uloop);
496 struct sockaddr_nl nla;
497 unsigned char *buf = NULL;
500 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
502 handle_hotplug_msg((char *) buf, size);
508 static int system_rtnl_call(struct nl_msg *msg)
512 ret = nl_send_auto_complete(sock_rtnl, msg);
518 return nl_wait_for_ack(sock_rtnl);
521 int system_bridge_delbr(struct device *bridge)
523 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
526 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
530 memset(&ifr, 0, sizeof(ifr));
532 ifr.ifr_ifindex = dev->ifindex;
535 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
536 return ioctl(sock_ioctl, cmd, &ifr);
539 static bool system_is_bridge(const char *name, char *buf, int buflen)
543 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
544 if (stat(buf, &st) < 0)
550 static char *system_get_bridge(const char *name, char *buf, int buflen)
556 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
557 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
561 len = readlink(gl.gl_pathv[0], buf, buflen);
569 path = strrchr(buf, '/');
577 system_bridge_set_wireless(struct device *bridge, struct device *dev)
579 bool mcast_to_ucast = dev->wireless_ap;
582 if (bridge->settings.flags & DEV_OPT_MULTICAST_TO_UNICAST &&
583 !bridge->settings.multicast_to_unicast)
584 mcast_to_ucast = false;
586 if (!mcast_to_ucast || dev->wireless_isolate)
589 system_bridge_set_multicast_to_unicast(dev, mcast_to_ucast ? "1" : "0");
590 system_bridge_set_hairpin_mode(dev, hairpin ? "1" : "0");
593 int system_bridge_addif(struct device *bridge, struct device *dev)
599 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
600 if (!oldbr || strcmp(oldbr, bridge->ifname) != 0)
601 ret = system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
604 system_bridge_set_wireless(bridge, dev);
606 if (dev->settings.flags & DEV_OPT_MULTICAST_ROUTER) {
607 snprintf(buf, sizeof(buf), "%i", dev->settings.multicast_router);
608 system_bridge_set_multicast_router(dev, buf, false);
614 int system_bridge_delif(struct device *bridge, struct device *dev)
616 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
619 int system_if_resolve(struct device *dev)
622 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
623 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
624 return ifr.ifr_ifindex;
629 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
633 memset(&ifr, 0, sizeof(ifr));
634 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
635 ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
636 ifr.ifr_flags |= add;
637 ifr.ifr_flags &= ~rem;
638 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
650 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
652 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
654 return ifa->ifa_index == ifindex;
657 static bool check_route(struct nlmsghdr *hdr, int ifindex)
659 struct rtmsg *r = NLMSG_DATA(hdr);
660 struct nlattr *tb[__RTA_MAX];
662 if (r->rtm_protocol == RTPROT_KERNEL &&
663 r->rtm_family == AF_INET6)
666 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
670 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
673 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
678 static int cb_clear_event(struct nl_msg *msg, void *arg)
680 struct clear_data *clr = arg;
681 struct nlmsghdr *hdr = nlmsg_hdr(msg);
682 bool (*cb)(struct nlmsghdr *, int ifindex);
688 if (hdr->nlmsg_type != RTM_NEWADDR)
695 if (hdr->nlmsg_type != RTM_NEWROUTE)
702 if (hdr->nlmsg_type != RTM_NEWRULE)
711 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
714 if (type == RTM_DELRULE)
715 D(SYSTEM, "Remove a rule\n");
717 D(SYSTEM, "Remove %s from device %s\n",
718 type == RTM_DELADDR ? "an address" : "a route",
720 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
721 hdr = nlmsg_hdr(clr->msg);
722 hdr->nlmsg_type = type;
723 hdr->nlmsg_flags = NLM_F_REQUEST;
725 nl_socket_disable_auto_ack(sock_rtnl);
726 nl_send_auto_complete(sock_rtnl, clr->msg);
727 nl_socket_enable_auto_ack(sock_rtnl);
733 cb_finish_event(struct nl_msg *msg, void *arg)
741 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
744 *pending = err->error;
749 system_if_clear_entries(struct device *dev, int type, int af)
751 struct clear_data clr;
752 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
755 .rtm_flags = RTM_F_CLONED,
757 int flags = NLM_F_DUMP;
766 clr.size = sizeof(struct rtgenmsg);
769 clr.size = sizeof(struct rtmsg);
778 clr.msg = nlmsg_alloc_simple(type, flags);
782 nlmsg_append(clr.msg, &rtm, clr.size, 0);
783 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
784 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
785 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
787 nl_send_auto_complete(sock_rtnl, clr.msg);
789 nl_recvmsgs(sock_rtnl, cb);
797 * Clear bridge (membership) state and bring down device
799 void system_if_clear_state(struct device *dev)
801 static char buf[256];
804 device_set_ifindex(dev, system_if_resolve(dev));
805 if (dev->external || !dev->ifindex)
808 system_if_flags(dev->ifname, 0, IFF_UP);
810 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
811 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
812 system_bridge_delbr(dev);
816 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
818 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
819 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
822 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
823 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
824 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
825 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
826 system_set_disable_ipv6(dev, "0");
829 static inline unsigned long
830 sec_to_jiffies(int val)
832 return (unsigned long) val * 100;
835 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
838 unsigned long args[4] = {};
840 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
843 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
844 args[1] = !!cfg->stp;
845 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
847 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
848 args[1] = sec_to_jiffies(cfg->forward_delay);
849 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
851 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
852 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
854 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier",
855 bridge->ifname, cfg->multicast_querier ? "1" : "0");
857 snprintf(buf, sizeof(buf), "%i", cfg->hash_max);
858 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/hash_max",
859 bridge->ifname, buf);
861 if (bridge->settings.flags & DEV_OPT_MULTICAST_ROUTER) {
862 snprintf(buf, sizeof(buf), "%i", bridge->settings.multicast_router);
863 system_bridge_set_multicast_router(bridge, buf, true);
866 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
867 args[1] = cfg->priority;
868 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
870 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
871 args[0] = BRCTL_SET_AGEING_TIME;
872 args[1] = sec_to_jiffies(cfg->ageing_time);
873 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
876 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
877 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
878 args[1] = sec_to_jiffies(cfg->hello_time);
879 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
882 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
883 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
884 args[1] = sec_to_jiffies(cfg->max_age);
885 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
891 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
894 struct nlattr *linkinfo, *data;
895 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
897 static const struct {
899 enum macvlan_mode val;
901 { "private", MACVLAN_MODE_PRIVATE },
902 { "vepa", MACVLAN_MODE_VEPA },
903 { "bridge", MACVLAN_MODE_BRIDGE },
904 { "passthru", MACVLAN_MODE_PASSTHRU },
907 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
912 nlmsg_append(msg, &iim, sizeof(iim), 0);
914 if (cfg->flags & MACVLAN_OPT_MACADDR)
915 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
916 nla_put_string(msg, IFLA_IFNAME, macvlan->ifname);
917 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
919 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
920 goto nla_put_failure;
922 nla_put_string(msg, IFLA_INFO_KIND, "macvlan");
924 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
925 goto nla_put_failure;
928 for (i = 0; i < ARRAY_SIZE(modes); i++) {
929 if (strcmp(cfg->mode, modes[i].name) != 0)
932 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
937 nla_nest_end(msg, data);
938 nla_nest_end(msg, linkinfo);
940 rv = system_rtnl_call(msg);
942 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
951 static int system_link_del(const char *ifname)
954 struct ifinfomsg iim = {
955 .ifi_family = AF_UNSPEC,
959 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
964 nlmsg_append(msg, &iim, sizeof(iim), 0);
965 nla_put_string(msg, IFLA_IFNAME, ifname);
966 return system_rtnl_call(msg);
969 int system_macvlan_del(struct device *macvlan)
971 return system_link_del(macvlan->ifname);
974 static int system_vlan(struct device *dev, int id)
976 struct vlan_ioctl_args ifr = {
977 .cmd = SET_VLAN_NAME_TYPE_CMD,
978 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
981 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
984 ifr.cmd = DEL_VLAN_CMD;
987 ifr.cmd = ADD_VLAN_CMD;
990 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
991 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
994 int system_vlan_add(struct device *dev, int id)
996 return system_vlan(dev, id);
999 int system_vlan_del(struct device *dev)
1001 return system_vlan(dev, -1);
1004 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
1007 struct nlattr *linkinfo, *data;
1008 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
1011 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1016 nlmsg_append(msg, &iim, sizeof(iim), 0);
1017 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
1018 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
1020 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1021 goto nla_put_failure;
1023 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
1025 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1026 goto nla_put_failure;
1028 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
1030 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
1031 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
1033 if(cfg->proto == VLAN_PROTO_8021AD)
1034 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);
1037 nla_nest_end(msg, data);
1038 nla_nest_end(msg, linkinfo);
1040 rv = system_rtnl_call(msg);
1042 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
1051 int system_vlandev_del(struct device *vlandev)
1053 return system_link_del(vlandev->ifname);
1057 system_if_get_settings(struct device *dev, struct device_settings *s)
1062 memset(&ifr, 0, sizeof(ifr));
1063 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1065 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
1066 s->mtu = ifr.ifr_mtu;
1067 s->flags |= DEV_OPT_MTU;
1070 s->mtu6 = system_update_ipv6_mtu(dev, 0);
1072 s->flags |= DEV_OPT_MTU6;
1074 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
1075 s->txqueuelen = ifr.ifr_qlen;
1076 s->flags |= DEV_OPT_TXQUEUELEN;
1079 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
1080 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
1081 s->flags |= DEV_OPT_MACADDR;
1084 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
1085 s->ipv6 = !strtoul(buf, NULL, 0);
1086 s->flags |= DEV_OPT_IPV6;
1089 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
1090 s->promisc = ifr.ifr_flags & IFF_PROMISC;
1091 s->flags |= DEV_OPT_PROMISC;
1094 if (!system_get_rpfilter(dev, buf, sizeof(buf))) {
1095 s->rpfilter = strtoul(buf, NULL, 0);
1096 s->flags |= DEV_OPT_RPFILTER;
1099 if (!system_get_acceptlocal(dev, buf, sizeof(buf))) {
1100 s->acceptlocal = strtoul(buf, NULL, 0);
1101 s->flags |= DEV_OPT_ACCEPTLOCAL;
1104 if (!system_get_igmpversion(dev, buf, sizeof(buf))) {
1105 s->igmpversion = strtoul(buf, NULL, 0);
1106 s->flags |= DEV_OPT_IGMPVERSION;
1109 if (!system_get_mldversion(dev, buf, sizeof(buf))) {
1110 s->mldversion = strtoul(buf, NULL, 0);
1111 s->flags |= DEV_OPT_MLDVERSION;
1114 if (!system_get_neigh4reachabletime(dev, buf, sizeof(buf))) {
1115 s->neigh4reachabletime = strtoul(buf, NULL, 0);
1116 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1119 if (!system_get_neigh6reachabletime(dev, buf, sizeof(buf))) {
1120 s->neigh6reachabletime = strtoul(buf, NULL, 0);
1121 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1124 if (!system_get_dadtransmits(dev, buf, sizeof(buf))) {
1125 s->dadtransmits = strtoul(buf, NULL, 0);
1126 s->flags |= DEV_OPT_DADTRANSMITS;
1131 system_if_set_rps_xps_val(const char *path, int val)
1137 if (glob(path, 0, NULL, &gl))
1140 snprintf(val_buf, sizeof(val_buf), "%x", val);
1141 for (i = 0; i < gl.gl_pathc; i++)
1142 system_set_sysctl(gl.gl_pathv[i], val_buf);
1146 system_if_apply_rps_xps(struct device *dev, struct device_settings *s)
1148 long n_cpus = sysconf(_SC_NPROCESSORS_ONLN);
1154 val = (1 << n_cpus) - 1;
1155 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/rps_cpus", dev->ifname);
1156 system_if_set_rps_xps_val(dev_buf, s->rps ? val : 0);
1158 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/xps_cpus", dev->ifname);
1159 system_if_set_rps_xps_val(dev_buf, s->xps ? val : 0);
1163 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
1168 memset(&ifr, 0, sizeof(ifr));
1169 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1170 if (s->flags & DEV_OPT_MTU & apply_mask) {
1171 ifr.ifr_mtu = s->mtu;
1172 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
1173 s->flags &= ~DEV_OPT_MTU;
1175 if (s->flags & DEV_OPT_MTU6 & apply_mask) {
1176 system_update_ipv6_mtu(dev, s->mtu6);
1178 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
1179 ifr.ifr_qlen = s->txqueuelen;
1180 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
1181 s->flags &= ~DEV_OPT_TXQUEUELEN;
1183 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
1184 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
1185 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
1186 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
1187 s->flags &= ~DEV_OPT_MACADDR;
1189 if (s->flags & DEV_OPT_IPV6 & apply_mask)
1190 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
1191 if (s->flags & DEV_OPT_PROMISC & apply_mask) {
1192 if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
1193 !s->promisc ? IFF_PROMISC : 0) < 0)
1194 s->flags &= ~DEV_OPT_PROMISC;
1196 if (s->flags & DEV_OPT_RPFILTER & apply_mask) {
1197 snprintf(buf, sizeof(buf), "%d", s->rpfilter);
1198 system_set_rpfilter(dev, buf);
1200 if (s->flags & DEV_OPT_ACCEPTLOCAL & apply_mask)
1201 system_set_acceptlocal(dev, s->acceptlocal ? "1" : "0");
1202 if (s->flags & DEV_OPT_IGMPVERSION & apply_mask) {
1203 snprintf(buf, sizeof(buf), "%d", s->igmpversion);
1204 system_set_igmpversion(dev, buf);
1206 if (s->flags & DEV_OPT_MLDVERSION & apply_mask) {
1207 snprintf(buf, sizeof(buf), "%d", s->mldversion);
1208 system_set_mldversion(dev, buf);
1210 if (s->flags & DEV_OPT_NEIGHREACHABLETIME & apply_mask) {
1211 snprintf(buf, sizeof(buf), "%d", s->neigh4reachabletime);
1212 system_set_neigh4reachabletime(dev, buf);
1213 snprintf(buf, sizeof(buf), "%d", s->neigh6reachabletime);
1214 system_set_neigh6reachabletime(dev, buf);
1216 if (s->flags & DEV_OPT_DADTRANSMITS & apply_mask) {
1217 snprintf(buf, sizeof(buf), "%d", s->dadtransmits);
1218 system_set_dadtransmits(dev, buf);
1221 system_if_apply_rps_xps(dev, s);
1224 int system_if_up(struct device *dev)
1226 system_if_get_settings(dev, &dev->orig_settings);
1227 /* Only keep orig settings based on what needs to be set */
1228 dev->orig_settings.flags &= dev->settings.flags;
1229 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
1230 return system_if_flags(dev->ifname, IFF_UP, 0);
1233 int system_if_down(struct device *dev)
1235 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
1236 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
1240 struct if_check_data {
1246 #ifndef IFF_LOWER_UP
1247 #define IFF_LOWER_UP 0x10000
1250 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1252 struct nlmsghdr *nh = nlmsg_hdr(msg);
1253 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1254 struct if_check_data *chk = (struct if_check_data *)arg;
1256 if (nh->nlmsg_type != RTM_NEWLINK)
1259 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1260 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1265 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1267 struct if_check_data *chk = (struct if_check_data *)arg;
1272 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1274 struct if_check_data *chk = (struct if_check_data *)arg;
1276 device_set_present(chk->dev, false);
1277 device_set_link(chk->dev, false);
1278 chk->pending = err->error;
1283 int system_if_check(struct device *dev)
1285 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1287 struct ifinfomsg ifi = {
1288 .ifi_family = AF_UNSPEC,
1291 struct if_check_data chk = {
1297 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1298 if (!msg || nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1299 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1302 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1303 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1304 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1306 nl_send_auto_complete(sock_rtnl, msg);
1307 while (chk.pending > 0)
1308 nl_recvmsgs(sock_rtnl, cb);
1319 system_if_get_parent(struct device *dev)
1321 char buf[64], *devname;
1322 int ifindex, iflink, len;
1325 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1326 f = fopen(buf, "r");
1330 len = fread(buf, 1, sizeof(buf) - 1, f);
1337 iflink = strtoul(buf, NULL, 0);
1338 ifindex = system_if_resolve(dev);
1339 if (!iflink || iflink == ifindex)
1342 devname = if_indextoname(iflink, buf);
1346 return device_get(devname, true);
1350 read_string_file(int dir_fd, const char *file, char *buf, int len)
1356 fd = openat(dir_fd, file, O_RDONLY);
1361 len = read(fd, buf, len - 1);
1365 } else if (len > 0) {
1368 c = strchr(buf, '\n');
1381 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1386 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1388 *val = strtoull(buf, NULL, 0);
1393 /* Assume advertised flags == supported flags */
1394 static const struct {
1397 } ethtool_link_modes[] = {
1398 { ADVERTISED_10baseT_Half, "10H" },
1399 { ADVERTISED_10baseT_Full, "10F" },
1400 { ADVERTISED_100baseT_Half, "100H" },
1401 { ADVERTISED_100baseT_Full, "100F" },
1402 { ADVERTISED_1000baseT_Half, "1000H" },
1403 { ADVERTISED_1000baseT_Full, "1000F" },
1406 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1409 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1410 if (mask & ethtool_link_modes[i].mask)
1411 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1416 system_if_force_external(const char *ifname)
1421 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1422 return stat(buf, &s) == 0;
1426 system_if_dump_info(struct device *dev, struct blob_buf *b)
1428 struct ethtool_cmd ecmd;
1434 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
1435 dir_fd = open(buf, O_DIRECTORY);
1437 memset(&ecmd, 0, sizeof(ecmd));
1438 memset(&ifr, 0, sizeof(ifr));
1439 strcpy(ifr.ifr_name, dev->ifname);
1440 ifr.ifr_data = (caddr_t) &ecmd;
1441 ecmd.cmd = ETHTOOL_GSET;
1443 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1444 c = blobmsg_open_array(b, "link-advertising");
1445 system_add_link_modes(b, ecmd.advertising);
1446 blobmsg_close_array(b, c);
1448 c = blobmsg_open_array(b, "link-supported");
1449 system_add_link_modes(b, ecmd.supported);
1450 blobmsg_close_array(b, c);
1452 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1453 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1454 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1455 blobmsg_add_string_buffer(b);
1463 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1465 const char *const counters[] = {
1466 "collisions", "rx_frame_errors", "tx_compressed",
1467 "multicast", "rx_length_errors", "tx_dropped",
1468 "rx_bytes", "rx_missed_errors", "tx_errors",
1469 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1470 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1471 "rx_dropped", "tx_aborted_errors", "tx_packets",
1472 "rx_errors", "tx_bytes", "tx_window_errors",
1473 "rx_fifo_errors", "tx_carrier_errors",
1480 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1481 stats_dir = open(buf, O_DIRECTORY);
1485 for (i = 0; i < ARRAY_SIZE(counters); i++)
1486 if (read_uint64_file(stats_dir, counters[i], &val))
1487 blobmsg_add_u64(b, counters[i], val);
1493 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1495 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1496 int alen = v4 ? 4 : 16;
1497 unsigned int flags = 0;
1498 struct ifaddrmsg ifa = {
1499 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1500 .ifa_prefixlen = addr->mask,
1501 .ifa_index = dev->ifindex,
1505 if (cmd == RTM_NEWADDR)
1506 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1508 msg = nlmsg_alloc_simple(cmd, flags);
1512 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1513 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1515 if (addr->broadcast)
1516 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1517 if (addr->point_to_point)
1518 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1520 time_t now = system_get_rtime();
1521 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1523 if (addr->preferred_until) {
1524 int64_t preferred = addr->preferred_until - now;
1527 else if (preferred > UINT32_MAX)
1528 preferred = UINT32_MAX;
1530 cinfo.ifa_prefered = preferred;
1533 if (addr->valid_until) {
1534 int64_t valid = addr->valid_until - now;
1539 else if (valid > UINT32_MAX)
1542 cinfo.ifa_valid = valid;
1545 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1547 if (cmd == RTM_NEWADDR && (addr->flags & DEVADDR_OFFLINK))
1548 nla_put_u32(msg, IFA_FLAGS, IFA_F_NOPREFIXROUTE);
1551 return system_rtnl_call(msg);
1554 int system_add_address(struct device *dev, struct device_addr *addr)
1556 return system_addr(dev, addr, RTM_NEWADDR);
1559 int system_del_address(struct device *dev, struct device_addr *addr)
1561 return system_addr(dev, addr, RTM_DELADDR);
1564 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1566 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1568 unsigned int flags = 0;
1571 have_gw = !!route->nexthop.in.s_addr;
1573 have_gw = route->nexthop.in6.s6_addr32[0] ||
1574 route->nexthop.in6.s6_addr32[1] ||
1575 route->nexthop.in6.s6_addr32[2] ||
1576 route->nexthop.in6.s6_addr32[3];
1578 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1579 ? route->table : RT_TABLE_MAIN;
1581 struct rtmsg rtm = {
1582 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1583 .rtm_dst_len = route->mask,
1584 .rtm_src_len = route->sourcemask,
1585 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1586 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
1587 .rtm_scope = RT_SCOPE_NOWHERE,
1588 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1589 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1593 if (cmd == RTM_NEWROUTE) {
1594 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1596 if (!dev) { // Add null-route
1597 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1598 rtm.rtm_type = RTN_UNREACHABLE;
1601 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1604 if (route->flags & DEVROUTE_TYPE) {
1605 rtm.rtm_type = route->type;
1606 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
1607 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
1608 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
1609 rtm.rtm_table = RT_TABLE_LOCAL;
1612 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT) {
1613 rtm.rtm_scope = RT_SCOPE_HOST;
1614 } else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
1615 rtm.rtm_type == RTN_ANYCAST) {
1616 rtm.rtm_scope = RT_SCOPE_LINK;
1617 } else if (rtm.rtm_type == RTN_BLACKHOLE || rtm.rtm_type == RTN_UNREACHABLE ||
1618 rtm.rtm_type == RTN_PROHIBIT || rtm.rtm_type == RTN_FAILED_POLICY) {
1619 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1624 msg = nlmsg_alloc_simple(cmd, flags);
1628 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1631 nla_put(msg, RTA_DST, alen, &route->addr);
1633 if (route->sourcemask) {
1634 if (rtm.rtm_family == AF_INET)
1635 nla_put(msg, RTA_PREFSRC, alen, &route->source);
1637 nla_put(msg, RTA_SRC, alen, &route->source);
1640 if (route->metric > 0)
1641 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1644 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1647 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1650 nla_put_u32(msg, RTA_TABLE, table);
1652 if (route->flags & DEVROUTE_MTU) {
1653 struct nlattr *metrics;
1655 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1656 goto nla_put_failure;
1658 nla_put_u32(msg, RTAX_MTU, route->mtu);
1660 nla_nest_end(msg, metrics);
1663 return system_rtnl_call(msg);
1670 int system_add_route(struct device *dev, struct device_route *route)
1672 return system_rt(dev, route, RTM_NEWROUTE);
1675 int system_del_route(struct device *dev, struct device_route *route)
1677 return system_rt(dev, route, RTM_DELROUTE);
1680 int system_flush_routes(void)
1682 const char *names[] = {
1683 "/proc/sys/net/ipv4/route/flush",
1684 "/proc/sys/net/ipv6/route/flush"
1688 for (i = 0; i < ARRAY_SIZE(names); i++) {
1689 fd = open(names[i], O_WRONLY);
1693 if (write(fd, "-1", 2)) {}
1699 bool system_resolve_rt_type(const char *type, unsigned int *id)
1701 return system_rtn_aton(type, id);
1704 bool system_resolve_rt_table(const char *name, unsigned int *id)
1708 unsigned int n, table = RT_TABLE_UNSPEC;
1710 /* first try to parse table as number */
1711 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1714 /* handle well known aliases */
1715 else if (!strcmp(name, "default"))
1716 table = RT_TABLE_DEFAULT;
1717 else if (!strcmp(name, "main"))
1718 table = RT_TABLE_MAIN;
1719 else if (!strcmp(name, "local"))
1720 table = RT_TABLE_LOCAL;
1721 else if (!strcmp(name, "prelocal"))
1722 table = RT_TABLE_PRELOCAL;
1724 /* try to look up name in /etc/iproute2/rt_tables */
1725 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1727 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1729 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1732 n = strtoul(e, NULL, 10);
1733 e = strtok(NULL, " \t\n");
1735 if (e && !strcmp(e, name))
1745 if (table == RT_TABLE_UNSPEC)
1752 bool system_is_default_rt_table(unsigned int id)
1754 return (id == RT_TABLE_MAIN);
1757 bool system_resolve_rpfilter(const char *filter, unsigned int *id)
1762 if (!strcmp(filter, "strict"))
1764 else if (!strcmp(filter, "loose"))
1767 n = strtoul(filter, &e, 0);
1768 if (*e || e == filter || n > 2)
1776 static int system_iprule(struct iprule *rule, int cmd)
1778 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1781 struct rtmsg rtm = {
1782 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1783 .rtm_protocol = RTPROT_STATIC,
1784 .rtm_scope = RT_SCOPE_UNIVERSE,
1785 .rtm_table = RT_TABLE_UNSPEC,
1786 .rtm_type = RTN_UNSPEC,
1790 if (cmd == RTM_NEWRULE) {
1791 rtm.rtm_type = RTN_UNICAST;
1792 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1796 rtm.rtm_flags |= FIB_RULE_INVERT;
1798 if (rule->flags & IPRULE_SRC)
1799 rtm.rtm_src_len = rule->src_mask;
1801 if (rule->flags & IPRULE_DEST)
1802 rtm.rtm_dst_len = rule->dest_mask;
1804 if (rule->flags & IPRULE_TOS)
1805 rtm.rtm_tos = rule->tos;
1807 if (rule->flags & IPRULE_LOOKUP) {
1808 if (rule->lookup < 256)
1809 rtm.rtm_table = rule->lookup;
1812 if (rule->flags & IPRULE_ACTION)
1813 rtm.rtm_type = rule->action;
1814 else if (rule->flags & IPRULE_GOTO)
1815 rtm.rtm_type = FR_ACT_GOTO;
1816 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1817 rtm.rtm_type = FR_ACT_NOP;
1819 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1824 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1826 if (rule->flags & IPRULE_IN)
1827 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1829 if (rule->flags & IPRULE_OUT)
1830 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1832 if (rule->flags & IPRULE_SRC)
1833 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1835 if (rule->flags & IPRULE_DEST)
1836 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1838 if (rule->flags & IPRULE_PRIORITY)
1839 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1840 else if (cmd == RTM_NEWRULE)
1841 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1843 if (rule->flags & IPRULE_FWMARK)
1844 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1846 if (rule->flags & IPRULE_FWMASK)
1847 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1849 if (rule->flags & IPRULE_LOOKUP) {
1850 if (rule->lookup >= 256)
1851 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1854 if (rule->flags & IPRULE_GOTO)
1855 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1857 return system_rtnl_call(msg);
1860 int system_add_iprule(struct iprule *rule)
1862 return system_iprule(rule, RTM_NEWRULE);
1865 int system_del_iprule(struct iprule *rule)
1867 return system_iprule(rule, RTM_DELRULE);
1870 int system_flush_iprules(void)
1875 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1876 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1878 memset(&rule, 0, sizeof(rule));
1881 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1884 rule.lookup = RT_TABLE_PRELOCAL;
1885 rv |= system_iprule(&rule, RTM_NEWRULE);
1888 rule.lookup = RT_TABLE_LOCAL;
1889 rv |= system_iprule(&rule, RTM_NEWRULE);
1891 rule.priority = 32766;
1892 rule.lookup = RT_TABLE_MAIN;
1893 rv |= system_iprule(&rule, RTM_NEWRULE);
1895 rule.priority = 32767;
1896 rule.lookup = RT_TABLE_DEFAULT;
1897 rv |= system_iprule(&rule, RTM_NEWRULE);
1900 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1903 rule.lookup = RT_TABLE_PRELOCAL;
1904 rv |= system_iprule(&rule, RTM_NEWRULE);
1907 rule.lookup = RT_TABLE_LOCAL;
1908 rv |= system_iprule(&rule, RTM_NEWRULE);
1910 rule.priority = 32766;
1911 rule.lookup = RT_TABLE_MAIN;
1912 rv |= system_iprule(&rule, RTM_NEWRULE);
1917 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1919 return system_rtn_aton(action, id);
1922 time_t system_get_rtime(void)
1927 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1930 if (gettimeofday(&tv, NULL) == 0)
1937 #define IP_DF 0x4000
1940 static int tunnel_ioctl(const char *name, int cmd, void *p)
1944 memset(&ifr, 0, sizeof(ifr));
1945 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1946 ifr.ifr_ifru.ifru_data = p;
1947 return ioctl(sock_ioctl, cmd, &ifr);
1950 #ifdef IFLA_IPTUN_MAX
1951 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
1952 static int system_add_gre_tunnel(const char *name, const char *kind,
1953 const unsigned int link, struct blob_attr **tb, bool v6)
1956 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
1957 struct blob_attr *cur;
1958 uint32_t ikey = 0, okey = 0, flags = 0, flowinfo = 0;
1959 uint16_t iflags = 0, oflags = 0;
1961 int ret = 0, ttl = 64;
1963 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
1967 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
1968 nla_put_string(nlm, IFLA_IFNAME, name);
1970 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
1976 nla_put_string(nlm, IFLA_INFO_KIND, kind);
1977 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
1984 nla_put_u32(nlm, IFLA_GRE_LINK, link);
1986 if ((cur = tb[TUNNEL_ATTR_TTL]))
1987 ttl = blobmsg_get_u32(cur);
1989 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
1991 if ((cur = tb[TUNNEL_ATTR_TOS])) {
1992 char *str = blobmsg_get_string(cur);
1993 if (strcmp(str, "inherit")) {
1996 if (!system_tos_aton(str, &uval)) {
2002 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
2007 flags |= IP6_TNL_F_USE_ORIG_TCLASS;
2013 if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) {
2014 uint8_t icsum, ocsum, iseqno, oseqno;
2015 if (sscanf(blobmsg_get_string(cur), "%u,%u,%hhu,%hhu,%hhu,%hhu",
2016 &ikey, &okey, &icsum, &ocsum, &iseqno, &oseqno) < 6) {
2041 struct in6_addr in6buf;
2042 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2043 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2047 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
2050 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2051 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2055 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
2057 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, 4);
2060 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
2063 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags);
2065 struct in_addr inbuf;
2068 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2069 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2073 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
2076 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2077 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2081 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
2083 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
2085 okey = inbuf.s_addr;
2090 ikey = inbuf.s_addr;
2096 if ((cur = tb[TUNNEL_ATTR_DF]))
2097 set_df = blobmsg_get_bool(cur);
2099 /* ttl !=0 and nopmtudisc are incompatible */
2100 if (ttl && !set_df) {
2105 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
2107 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
2111 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
2114 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
2117 nla_put_u32(nlm, IFLA_GRE_OKEY, okey);
2120 nla_put_u32(nlm, IFLA_GRE_IKEY, ikey);
2122 nla_nest_end(nlm, infodata);
2123 nla_nest_end(nlm, linkinfo);
2125 return system_rtnl_call(nlm);
2133 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
2135 struct blob_attr *cur;
2137 struct ip_tunnel_parm p = {
2146 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
2147 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
2150 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
2151 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
2154 if ((cur = tb[TUNNEL_ATTR_DF]))
2155 set_df = blobmsg_get_bool(cur);
2157 if ((cur = tb[TUNNEL_ATTR_TTL]))
2158 p.iph.ttl = blobmsg_get_u32(cur);
2160 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2161 char *str = blobmsg_get_string(cur);
2162 if (strcmp(str, "inherit")) {
2165 if (!system_tos_aton(str, &uval))
2173 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
2174 /* ttl !=0 and nopmtudisc are incompatible */
2175 if (p.iph.ttl && p.iph.frag_off == 0)
2178 strncpy(p.name, name, sizeof(p.name));
2180 switch (p.iph.protocol) {
2182 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
2184 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
2191 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
2193 struct blob_attr *cur;
2196 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2198 str = blobmsg_data(cur);
2200 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
2201 !strcmp(str, "greip6") || !strcmp(str, "gretapip6"))
2202 return system_link_del(name);
2204 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
2207 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
2209 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2211 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2212 blob_data(attr), blob_len(attr));
2214 return __system_del_ip_tunnel(name, tb);
2217 int system_update_ipv6_mtu(struct device *dev, int mtu)
2221 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
2224 int fd = open(buf, O_RDWR);
2227 ssize_t len = read(fd, buf, sizeof(buf) - 1);
2234 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) > 0)
2243 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
2245 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2246 struct blob_attr *cur;
2249 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2250 blob_data(attr), blob_len(attr));
2252 __system_del_ip_tunnel(name, tb);
2254 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2256 str = blobmsg_data(cur);
2258 unsigned int ttl = 0;
2259 if ((cur = tb[TUNNEL_ATTR_TTL])) {
2260 ttl = blobmsg_get_u32(cur);
2265 unsigned int link = 0;
2266 if ((cur = tb[TUNNEL_ATTR_LINK])) {
2267 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
2271 if (iface->l3_dev.dev)
2272 link = iface->l3_dev.dev->ifindex;
2275 if (!strcmp(str, "sit")) {
2276 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
2280 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
2282 struct ip_tunnel_6rd p6;
2284 memset(&p6, 0, sizeof(p6));
2286 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
2287 &p6.prefix, &mask) || mask > 128)
2289 p6.prefixlen = mask;
2291 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
2292 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
2293 &p6.relay_prefix, &mask) || mask > 32)
2295 p6.relay_prefixlen = mask;
2298 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
2299 __system_del_ip_tunnel(name, tb);
2304 #ifdef IFLA_IPTUN_MAX
2305 } else if (!strcmp(str, "ipip6")) {
2306 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2307 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2308 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2314 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2315 nla_put_string(nlm, IFLA_IFNAME, name);
2318 nla_put_u32(nlm, IFLA_LINK, link);
2320 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2325 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2326 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2333 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2335 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2336 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2337 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
2339 struct in6_addr in6buf;
2340 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2341 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2345 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2348 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2349 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2353 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2356 #ifdef IFLA_IPTUN_FMR_MAX
2357 if ((cur = tb[TUNNEL_ATTR_FMRS])) {
2358 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2360 struct blob_attr *fmr;
2361 unsigned rem, fmrcnt = 0;
2362 blobmsg_for_each_attr(fmr, cur, rem) {
2363 if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
2366 unsigned ip4len, ip6len, ealen, offset = 6;
2370 if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
2371 ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) {
2376 struct in6_addr ip6prefix;
2377 struct in_addr ip4prefix;
2378 if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
2379 inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) {
2384 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2386 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2387 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2388 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2389 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2390 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2391 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2393 nla_nest_end(nlm, rule);
2396 nla_nest_end(nlm, fmrs);
2400 nla_nest_end(nlm, infodata);
2401 nla_nest_end(nlm, linkinfo);
2403 return system_rtnl_call(nlm);
2407 } else if (!strcmp(str, "greip")) {
2408 return system_add_gre_tunnel(name, "gre", link, tb, false);
2409 } else if (!strcmp(str, "gretapip")) {
2410 return system_add_gre_tunnel(name, "gretap", link, tb, false);
2411 } else if (!strcmp(str, "greip6")) {
2412 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
2413 } else if (!strcmp(str, "gretapip6")) {
2414 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
2416 } else if (!strcmp(str, "ipip")) {
2417 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);