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 int system_get_sysctl(const char *path, char *buf, const size_t buf_sz)
330 int fd = -1, ret = -1;
332 fd = open(path, O_RDONLY);
336 ssize_t len = read(fd, buf, buf_sz - 1);
350 system_get_dev_sysctl(const char *path, const char *device, char *buf, const size_t buf_sz)
352 snprintf(dev_buf, sizeof(dev_buf), path, device);
353 return system_get_sysctl(dev_buf, buf, buf_sz);
356 static int system_get_disable_ipv6(struct device *dev, char *buf, const size_t buf_sz)
358 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6",
359 dev->ifname, buf, buf_sz);
362 static int system_get_rpfilter(struct device *dev, char *buf, const size_t buf_sz)
364 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter",
365 dev->ifname, buf, buf_sz);
368 static int system_get_acceptlocal(struct device *dev, char *buf, const size_t buf_sz)
370 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local",
371 dev->ifname, buf, buf_sz);
374 static int system_get_igmpversion(struct device *dev, char *buf, const size_t buf_sz)
376 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version",
377 dev->ifname, buf, buf_sz);
380 static int system_get_mldversion(struct device *dev, char *buf, const size_t buf_sz)
382 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version",
383 dev->ifname, buf, buf_sz);
386 static int system_get_neigh4reachabletime(struct device *dev, char *buf, const size_t buf_sz)
388 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms",
389 dev->ifname, buf, buf_sz);
392 static int system_get_neigh6reachabletime(struct device *dev, char *buf, const size_t buf_sz)
394 return system_get_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms",
395 dev->ifname, buf, buf_sz);
398 static int system_get_dadtransmits(struct device *dev, char *buf, const size_t buf_sz)
400 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits",
401 dev->ifname, buf, buf_sz);
404 // Evaluate netlink messages
405 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
407 struct nlmsghdr *nh = nlmsg_hdr(msg);
408 struct nlattr *nla[__IFLA_MAX];
412 if (nh->nlmsg_type != RTM_NEWLINK)
415 nlmsg_parse(nh, sizeof(struct ifinfomsg), nla, __IFLA_MAX - 1, NULL);
416 if (!nla[IFLA_IFNAME])
419 struct device *dev = device_get(nla_data(nla[IFLA_IFNAME]), false);
420 if (!dev || dev->type->keep_link_status)
423 if (!system_get_dev_sysctl("/sys/class/net/%s/carrier", dev->ifname, buf, sizeof(buf)))
424 link_state = strtoul(buf, NULL, 0);
426 device_set_link(dev, link_state ? true : false);
433 handle_hotplug_msg(char *data, int size)
435 const char *subsystem = NULL, *interface = NULL;
436 char *cur, *end, *sep;
441 if (!strncmp(data, "add@", 4))
443 else if (!strncmp(data, "remove@", 7))
448 skip = strlen(data) + 1;
451 for (cur = data + skip; cur < end; cur += skip) {
452 skip = strlen(cur) + 1;
454 sep = strchr(cur, '=');
459 if (!strcmp(cur, "INTERFACE"))
461 else if (!strcmp(cur, "SUBSYSTEM")) {
463 if (strcmp(subsystem, "net") != 0)
466 if (subsystem && interface)
472 dev = device_get(interface, false);
476 if (dev->type != &simple_device_type)
479 if (add && system_if_force_external(dev->ifname))
482 device_set_present(dev, add);
486 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
488 struct event_socket *ev = container_of(u, struct event_socket, uloop);
489 struct sockaddr_nl nla;
490 unsigned char *buf = NULL;
493 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
495 handle_hotplug_msg((char *) buf, size);
501 static int system_rtnl_call(struct nl_msg *msg)
505 ret = nl_send_auto_complete(sock_rtnl, msg);
511 return nl_wait_for_ack(sock_rtnl);
514 int system_bridge_delbr(struct device *bridge)
516 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
519 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
523 memset(&ifr, 0, sizeof(ifr));
525 ifr.ifr_ifindex = dev->ifindex;
528 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
529 return ioctl(sock_ioctl, cmd, &ifr);
532 static bool system_is_bridge(const char *name, char *buf, int buflen)
536 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
537 if (stat(buf, &st) < 0)
543 static char *system_get_bridge(const char *name, char *buf, int buflen)
549 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
550 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
554 len = readlink(gl.gl_pathv[0], buf, buflen);
562 path = strrchr(buf, '/');
570 system_bridge_set_wireless(struct device *bridge, struct device *dev)
572 bool mcast_to_ucast = true;
575 if (bridge->settings.flags & DEV_OPT_MULTICAST_TO_UNICAST &&
576 !bridge->settings.multicast_to_unicast)
577 mcast_to_ucast = false;
579 if (!mcast_to_ucast || dev->wireless_isolate)
582 system_bridge_set_multicast_to_unicast(dev, mcast_to_ucast ? "1" : "0");
583 system_bridge_set_hairpin_mode(dev, hairpin ? "1" : "0");
586 int system_bridge_addif(struct device *bridge, struct device *dev)
591 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
592 if (!oldbr || strcmp(oldbr, bridge->ifname) != 0)
593 ret = system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
596 system_bridge_set_wireless(bridge, dev);
601 int system_bridge_delif(struct device *bridge, struct device *dev)
603 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
606 int system_if_resolve(struct device *dev)
609 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
610 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
611 return ifr.ifr_ifindex;
616 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
620 memset(&ifr, 0, sizeof(ifr));
621 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
622 ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
623 ifr.ifr_flags |= add;
624 ifr.ifr_flags &= ~rem;
625 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
637 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
639 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
641 return ifa->ifa_index == ifindex;
644 static bool check_route(struct nlmsghdr *hdr, int ifindex)
646 struct rtmsg *r = NLMSG_DATA(hdr);
647 struct nlattr *tb[__RTA_MAX];
649 if (r->rtm_protocol == RTPROT_KERNEL &&
650 r->rtm_family == AF_INET6)
653 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
657 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
660 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
665 static int cb_clear_event(struct nl_msg *msg, void *arg)
667 struct clear_data *clr = arg;
668 struct nlmsghdr *hdr = nlmsg_hdr(msg);
669 bool (*cb)(struct nlmsghdr *, int ifindex);
675 if (hdr->nlmsg_type != RTM_NEWADDR)
682 if (hdr->nlmsg_type != RTM_NEWROUTE)
689 if (hdr->nlmsg_type != RTM_NEWRULE)
698 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
701 if (type == RTM_DELRULE)
702 D(SYSTEM, "Remove a rule\n");
704 D(SYSTEM, "Remove %s from device %s\n",
705 type == RTM_DELADDR ? "an address" : "a route",
707 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
708 hdr = nlmsg_hdr(clr->msg);
709 hdr->nlmsg_type = type;
710 hdr->nlmsg_flags = NLM_F_REQUEST;
712 nl_socket_disable_auto_ack(sock_rtnl);
713 nl_send_auto_complete(sock_rtnl, clr->msg);
714 nl_socket_enable_auto_ack(sock_rtnl);
720 cb_finish_event(struct nl_msg *msg, void *arg)
728 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
731 *pending = err->error;
736 system_if_clear_entries(struct device *dev, int type, int af)
738 struct clear_data clr;
739 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
742 .rtm_flags = RTM_F_CLONED,
744 int flags = NLM_F_DUMP;
753 clr.size = sizeof(struct rtgenmsg);
756 clr.size = sizeof(struct rtmsg);
765 clr.msg = nlmsg_alloc_simple(type, flags);
769 nlmsg_append(clr.msg, &rtm, clr.size, 0);
770 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
771 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
772 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
774 nl_send_auto_complete(sock_rtnl, clr.msg);
776 nl_recvmsgs(sock_rtnl, cb);
784 * Clear bridge (membership) state and bring down device
786 void system_if_clear_state(struct device *dev)
788 static char buf[256];
791 device_set_ifindex(dev, system_if_resolve(dev));
792 if (dev->external || !dev->ifindex)
795 system_if_flags(dev->ifname, 0, IFF_UP);
797 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
798 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
799 system_bridge_delbr(dev);
803 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
805 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
806 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
809 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
810 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
811 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
812 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
813 system_set_disable_ipv6(dev, "0");
816 static inline unsigned long
817 sec_to_jiffies(int val)
819 return (unsigned long) val * 100;
822 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
825 unsigned long args[4] = {};
827 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
830 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
831 args[1] = !!cfg->stp;
832 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
834 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
835 args[1] = sec_to_jiffies(cfg->forward_delay);
836 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
838 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
839 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
841 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier",
842 bridge->ifname, cfg->multicast_querier ? "1" : "0");
844 snprintf(buf, sizeof(buf), "%i", cfg->hash_max);
845 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/hash_max",
846 bridge->ifname, buf);
848 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
849 args[1] = cfg->priority;
850 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
852 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
853 args[0] = BRCTL_SET_AGEING_TIME;
854 args[1] = sec_to_jiffies(cfg->ageing_time);
855 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
858 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
859 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
860 args[1] = sec_to_jiffies(cfg->hello_time);
861 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
864 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
865 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
866 args[1] = sec_to_jiffies(cfg->max_age);
867 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
873 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
876 struct nlattr *linkinfo, *data;
877 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
879 static const struct {
881 enum macvlan_mode val;
883 { "private", MACVLAN_MODE_PRIVATE },
884 { "vepa", MACVLAN_MODE_VEPA },
885 { "bridge", MACVLAN_MODE_BRIDGE },
886 { "passthru", MACVLAN_MODE_PASSTHRU },
889 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
894 nlmsg_append(msg, &iim, sizeof(iim), 0);
896 if (cfg->flags & MACVLAN_OPT_MACADDR)
897 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
898 nla_put_string(msg, IFLA_IFNAME, macvlan->ifname);
899 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
901 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
902 goto nla_put_failure;
904 nla_put_string(msg, IFLA_INFO_KIND, "macvlan");
906 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
907 goto nla_put_failure;
910 for (i = 0; i < ARRAY_SIZE(modes); i++) {
911 if (strcmp(cfg->mode, modes[i].name) != 0)
914 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
919 nla_nest_end(msg, data);
920 nla_nest_end(msg, linkinfo);
922 rv = system_rtnl_call(msg);
924 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
933 static int system_link_del(const char *ifname)
936 struct ifinfomsg iim = {
937 .ifi_family = AF_UNSPEC,
941 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
946 nlmsg_append(msg, &iim, sizeof(iim), 0);
947 nla_put_string(msg, IFLA_IFNAME, ifname);
948 return system_rtnl_call(msg);
951 int system_macvlan_del(struct device *macvlan)
953 return system_link_del(macvlan->ifname);
956 static int system_vlan(struct device *dev, int id)
958 struct vlan_ioctl_args ifr = {
959 .cmd = SET_VLAN_NAME_TYPE_CMD,
960 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
963 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
966 ifr.cmd = DEL_VLAN_CMD;
969 ifr.cmd = ADD_VLAN_CMD;
972 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
973 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
976 int system_vlan_add(struct device *dev, int id)
978 return system_vlan(dev, id);
981 int system_vlan_del(struct device *dev)
983 return system_vlan(dev, -1);
986 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
989 struct nlattr *linkinfo, *data;
990 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
993 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
998 nlmsg_append(msg, &iim, sizeof(iim), 0);
999 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
1000 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
1002 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1003 goto nla_put_failure;
1005 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
1007 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1008 goto nla_put_failure;
1010 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
1012 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
1013 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
1015 if(cfg->proto == VLAN_PROTO_8021AD)
1016 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);
1019 nla_nest_end(msg, data);
1020 nla_nest_end(msg, linkinfo);
1022 rv = system_rtnl_call(msg);
1024 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
1033 int system_vlandev_del(struct device *vlandev)
1035 return system_link_del(vlandev->ifname);
1039 system_if_get_settings(struct device *dev, struct device_settings *s)
1044 memset(&ifr, 0, sizeof(ifr));
1045 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1047 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
1048 s->mtu = ifr.ifr_mtu;
1049 s->flags |= DEV_OPT_MTU;
1052 s->mtu6 = system_update_ipv6_mtu(dev, 0);
1054 s->flags |= DEV_OPT_MTU6;
1056 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
1057 s->txqueuelen = ifr.ifr_qlen;
1058 s->flags |= DEV_OPT_TXQUEUELEN;
1061 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
1062 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
1063 s->flags |= DEV_OPT_MACADDR;
1066 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
1067 s->ipv6 = !strtoul(buf, NULL, 0);
1068 s->flags |= DEV_OPT_IPV6;
1071 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
1072 s->promisc = ifr.ifr_flags & IFF_PROMISC;
1073 s->flags |= DEV_OPT_PROMISC;
1076 if (!system_get_rpfilter(dev, buf, sizeof(buf))) {
1077 s->rpfilter = strtoul(buf, NULL, 0);
1078 s->flags |= DEV_OPT_RPFILTER;
1081 if (!system_get_acceptlocal(dev, buf, sizeof(buf))) {
1082 s->acceptlocal = strtoul(buf, NULL, 0);
1083 s->flags |= DEV_OPT_ACCEPTLOCAL;
1086 if (!system_get_igmpversion(dev, buf, sizeof(buf))) {
1087 s->igmpversion = strtoul(buf, NULL, 0);
1088 s->flags |= DEV_OPT_IGMPVERSION;
1091 if (!system_get_mldversion(dev, buf, sizeof(buf))) {
1092 s->mldversion = strtoul(buf, NULL, 0);
1093 s->flags |= DEV_OPT_MLDVERSION;
1096 if (!system_get_neigh4reachabletime(dev, buf, sizeof(buf))) {
1097 s->neigh4reachabletime = strtoul(buf, NULL, 0);
1098 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1101 if (!system_get_neigh6reachabletime(dev, buf, sizeof(buf))) {
1102 s->neigh6reachabletime = strtoul(buf, NULL, 0);
1103 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1106 if (!system_get_dadtransmits(dev, buf, sizeof(buf))) {
1107 s->dadtransmits = strtoul(buf, NULL, 0);
1108 s->flags |= DEV_OPT_DADTRANSMITS;
1113 system_if_set_rps_xps_val(const char *path, int val)
1119 if (glob(path, 0, NULL, &gl))
1122 snprintf(val_buf, sizeof(val_buf), "%x", val);
1123 for (i = 0; i < gl.gl_pathc; i++)
1124 system_set_sysctl(gl.gl_pathv[i], val_buf);
1128 system_if_apply_rps_xps(struct device *dev, struct device_settings *s)
1130 long n_cpus = sysconf(_SC_NPROCESSORS_ONLN);
1136 val = (1 << n_cpus) - 1;
1137 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/rps_cpus", dev->ifname);
1138 system_if_set_rps_xps_val(dev_buf, s->rps ? val : 0);
1140 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/xps_cpus", dev->ifname);
1141 system_if_set_rps_xps_val(dev_buf, s->xps ? val : 0);
1145 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
1150 memset(&ifr, 0, sizeof(ifr));
1151 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1152 if (s->flags & DEV_OPT_MTU & apply_mask) {
1153 ifr.ifr_mtu = s->mtu;
1154 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
1155 s->flags &= ~DEV_OPT_MTU;
1157 if (s->flags & DEV_OPT_MTU6 & apply_mask) {
1158 system_update_ipv6_mtu(dev, s->mtu6);
1160 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
1161 ifr.ifr_qlen = s->txqueuelen;
1162 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
1163 s->flags &= ~DEV_OPT_TXQUEUELEN;
1165 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
1166 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
1167 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
1168 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
1169 s->flags &= ~DEV_OPT_MACADDR;
1171 if (s->flags & DEV_OPT_IPV6 & apply_mask)
1172 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
1173 if (s->flags & DEV_OPT_PROMISC & apply_mask) {
1174 if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
1175 !s->promisc ? IFF_PROMISC : 0) < 0)
1176 s->flags &= ~DEV_OPT_PROMISC;
1178 if (s->flags & DEV_OPT_RPFILTER & apply_mask) {
1179 snprintf(buf, sizeof(buf), "%d", s->rpfilter);
1180 system_set_rpfilter(dev, buf);
1182 if (s->flags & DEV_OPT_ACCEPTLOCAL & apply_mask)
1183 system_set_acceptlocal(dev, s->acceptlocal ? "1" : "0");
1184 if (s->flags & DEV_OPT_IGMPVERSION & apply_mask) {
1185 snprintf(buf, sizeof(buf), "%d", s->igmpversion);
1186 system_set_igmpversion(dev, buf);
1188 if (s->flags & DEV_OPT_MLDVERSION & apply_mask) {
1189 snprintf(buf, sizeof(buf), "%d", s->mldversion);
1190 system_set_mldversion(dev, buf);
1192 if (s->flags & DEV_OPT_NEIGHREACHABLETIME & apply_mask) {
1193 snprintf(buf, sizeof(buf), "%d", s->neigh4reachabletime);
1194 system_set_neigh4reachabletime(dev, buf);
1195 snprintf(buf, sizeof(buf), "%d", s->neigh6reachabletime);
1196 system_set_neigh6reachabletime(dev, buf);
1198 if (s->flags & DEV_OPT_DADTRANSMITS & apply_mask) {
1199 snprintf(buf, sizeof(buf), "%d", s->dadtransmits);
1200 system_set_dadtransmits(dev, buf);
1203 system_if_apply_rps_xps(dev, s);
1206 int system_if_up(struct device *dev)
1208 system_if_get_settings(dev, &dev->orig_settings);
1209 /* Only keep orig settings based on what needs to be set */
1210 dev->orig_settings.flags &= dev->settings.flags;
1211 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
1212 return system_if_flags(dev->ifname, IFF_UP, 0);
1215 int system_if_down(struct device *dev)
1217 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
1218 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
1222 struct if_check_data {
1228 #ifndef IFF_LOWER_UP
1229 #define IFF_LOWER_UP 0x10000
1232 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1234 struct nlmsghdr *nh = nlmsg_hdr(msg);
1235 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1236 struct if_check_data *chk = (struct if_check_data *)arg;
1238 if (nh->nlmsg_type != RTM_NEWLINK)
1241 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1242 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1247 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1249 struct if_check_data *chk = (struct if_check_data *)arg;
1254 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1256 struct if_check_data *chk = (struct if_check_data *)arg;
1258 device_set_present(chk->dev, false);
1259 device_set_link(chk->dev, false);
1260 chk->pending = err->error;
1265 int system_if_check(struct device *dev)
1267 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1269 struct ifinfomsg ifi = {
1270 .ifi_family = AF_UNSPEC,
1273 struct if_check_data chk = {
1279 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1280 if (!msg || nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1281 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1284 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1285 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1286 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1288 nl_send_auto_complete(sock_rtnl, msg);
1289 while (chk.pending > 0)
1290 nl_recvmsgs(sock_rtnl, cb);
1301 system_if_get_parent(struct device *dev)
1303 char buf[64], *devname;
1304 int ifindex, iflink, len;
1307 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1308 f = fopen(buf, "r");
1312 len = fread(buf, 1, sizeof(buf) - 1, f);
1319 iflink = strtoul(buf, NULL, 0);
1320 ifindex = system_if_resolve(dev);
1321 if (!iflink || iflink == ifindex)
1324 devname = if_indextoname(iflink, buf);
1328 return device_get(devname, true);
1332 read_string_file(int dir_fd, const char *file, char *buf, int len)
1338 fd = openat(dir_fd, file, O_RDONLY);
1343 len = read(fd, buf, len - 1);
1347 } else if (len > 0) {
1350 c = strchr(buf, '\n');
1363 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1368 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1370 *val = strtoull(buf, NULL, 0);
1375 /* Assume advertised flags == supported flags */
1376 static const struct {
1379 } ethtool_link_modes[] = {
1380 { ADVERTISED_10baseT_Half, "10H" },
1381 { ADVERTISED_10baseT_Full, "10F" },
1382 { ADVERTISED_100baseT_Half, "100H" },
1383 { ADVERTISED_100baseT_Full, "100F" },
1384 { ADVERTISED_1000baseT_Half, "1000H" },
1385 { ADVERTISED_1000baseT_Full, "1000F" },
1388 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1391 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1392 if (mask & ethtool_link_modes[i].mask)
1393 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1398 system_if_force_external(const char *ifname)
1403 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1404 return stat(buf, &s) == 0;
1408 system_if_dump_info(struct device *dev, struct blob_buf *b)
1410 struct ethtool_cmd ecmd;
1416 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
1417 dir_fd = open(buf, O_DIRECTORY);
1419 memset(&ecmd, 0, sizeof(ecmd));
1420 memset(&ifr, 0, sizeof(ifr));
1421 strcpy(ifr.ifr_name, dev->ifname);
1422 ifr.ifr_data = (caddr_t) &ecmd;
1423 ecmd.cmd = ETHTOOL_GSET;
1425 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1426 c = blobmsg_open_array(b, "link-advertising");
1427 system_add_link_modes(b, ecmd.advertising);
1428 blobmsg_close_array(b, c);
1430 c = blobmsg_open_array(b, "link-supported");
1431 system_add_link_modes(b, ecmd.supported);
1432 blobmsg_close_array(b, c);
1434 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1435 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1436 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1437 blobmsg_add_string_buffer(b);
1445 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1447 const char *const counters[] = {
1448 "collisions", "rx_frame_errors", "tx_compressed",
1449 "multicast", "rx_length_errors", "tx_dropped",
1450 "rx_bytes", "rx_missed_errors", "tx_errors",
1451 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1452 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1453 "rx_dropped", "tx_aborted_errors", "tx_packets",
1454 "rx_errors", "tx_bytes", "tx_window_errors",
1455 "rx_fifo_errors", "tx_carrier_errors",
1462 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1463 stats_dir = open(buf, O_DIRECTORY);
1467 for (i = 0; i < ARRAY_SIZE(counters); i++)
1468 if (read_uint64_file(stats_dir, counters[i], &val))
1469 blobmsg_add_u64(b, counters[i], val);
1475 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1477 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1478 int alen = v4 ? 4 : 16;
1479 unsigned int flags = 0;
1480 struct ifaddrmsg ifa = {
1481 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1482 .ifa_prefixlen = addr->mask,
1483 .ifa_index = dev->ifindex,
1487 if (cmd == RTM_NEWADDR)
1488 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1490 msg = nlmsg_alloc_simple(cmd, flags);
1494 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1495 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1497 if (addr->broadcast)
1498 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1499 if (addr->point_to_point)
1500 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1502 time_t now = system_get_rtime();
1503 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1505 if (addr->preferred_until) {
1506 int64_t preferred = addr->preferred_until - now;
1509 else if (preferred > UINT32_MAX)
1510 preferred = UINT32_MAX;
1512 cinfo.ifa_prefered = preferred;
1515 if (addr->valid_until) {
1516 int64_t valid = addr->valid_until - now;
1519 else if (valid > UINT32_MAX)
1522 cinfo.ifa_valid = valid;
1525 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1527 if (cmd == RTM_NEWADDR && (addr->flags & DEVADDR_OFFLINK))
1528 nla_put_u32(msg, IFA_FLAGS, IFA_F_NOPREFIXROUTE);
1531 return system_rtnl_call(msg);
1534 int system_add_address(struct device *dev, struct device_addr *addr)
1536 return system_addr(dev, addr, RTM_NEWADDR);
1539 int system_del_address(struct device *dev, struct device_addr *addr)
1541 return system_addr(dev, addr, RTM_DELADDR);
1544 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1546 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1548 unsigned int flags = 0;
1551 have_gw = !!route->nexthop.in.s_addr;
1553 have_gw = route->nexthop.in6.s6_addr32[0] ||
1554 route->nexthop.in6.s6_addr32[1] ||
1555 route->nexthop.in6.s6_addr32[2] ||
1556 route->nexthop.in6.s6_addr32[3];
1558 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1559 ? route->table : RT_TABLE_MAIN;
1561 struct rtmsg rtm = {
1562 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1563 .rtm_dst_len = route->mask,
1564 .rtm_src_len = route->sourcemask,
1565 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1566 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
1567 .rtm_scope = RT_SCOPE_NOWHERE,
1568 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1569 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1573 if (cmd == RTM_NEWROUTE) {
1574 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1576 if (!dev) { // Add null-route
1577 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1578 rtm.rtm_type = RTN_UNREACHABLE;
1581 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1584 if (route->flags & DEVROUTE_TYPE) {
1585 rtm.rtm_type = route->type;
1586 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
1587 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
1588 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
1589 rtm.rtm_table = RT_TABLE_LOCAL;
1592 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT) {
1593 rtm.rtm_scope = RT_SCOPE_HOST;
1594 } else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
1595 rtm.rtm_type == RTN_ANYCAST) {
1596 rtm.rtm_scope = RT_SCOPE_LINK;
1597 } else if (rtm.rtm_type == RTN_BLACKHOLE || rtm.rtm_type == RTN_UNREACHABLE ||
1598 rtm.rtm_type == RTN_PROHIBIT || rtm.rtm_type == RTN_FAILED_POLICY) {
1599 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1604 msg = nlmsg_alloc_simple(cmd, flags);
1608 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1611 nla_put(msg, RTA_DST, alen, &route->addr);
1613 if (route->sourcemask) {
1614 if (rtm.rtm_family == AF_INET)
1615 nla_put(msg, RTA_PREFSRC, alen, &route->source);
1617 nla_put(msg, RTA_SRC, alen, &route->source);
1620 if (route->metric > 0)
1621 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1624 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1627 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1630 nla_put_u32(msg, RTA_TABLE, table);
1632 if (route->flags & DEVROUTE_MTU) {
1633 struct nlattr *metrics;
1635 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1636 goto nla_put_failure;
1638 nla_put_u32(msg, RTAX_MTU, route->mtu);
1640 nla_nest_end(msg, metrics);
1643 return system_rtnl_call(msg);
1650 int system_add_route(struct device *dev, struct device_route *route)
1652 return system_rt(dev, route, RTM_NEWROUTE);
1655 int system_del_route(struct device *dev, struct device_route *route)
1657 return system_rt(dev, route, RTM_DELROUTE);
1660 int system_flush_routes(void)
1662 const char *names[] = {
1663 "/proc/sys/net/ipv4/route/flush",
1664 "/proc/sys/net/ipv6/route/flush"
1668 for (i = 0; i < ARRAY_SIZE(names); i++) {
1669 fd = open(names[i], O_WRONLY);
1673 if (write(fd, "-1", 2)) {}
1679 bool system_resolve_rt_type(const char *type, unsigned int *id)
1681 return system_rtn_aton(type, id);
1684 bool system_resolve_rt_table(const char *name, unsigned int *id)
1688 unsigned int n, table = RT_TABLE_UNSPEC;
1690 /* first try to parse table as number */
1691 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1694 /* handle well known aliases */
1695 else if (!strcmp(name, "default"))
1696 table = RT_TABLE_DEFAULT;
1697 else if (!strcmp(name, "main"))
1698 table = RT_TABLE_MAIN;
1699 else if (!strcmp(name, "local"))
1700 table = RT_TABLE_LOCAL;
1701 else if (!strcmp(name, "prelocal"))
1702 table = RT_TABLE_PRELOCAL;
1704 /* try to look up name in /etc/iproute2/rt_tables */
1705 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1707 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1709 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1712 n = strtoul(e, NULL, 10);
1713 e = strtok(NULL, " \t\n");
1715 if (e && !strcmp(e, name))
1725 if (table == RT_TABLE_UNSPEC)
1732 bool system_is_default_rt_table(unsigned int id)
1734 return (id == RT_TABLE_MAIN);
1737 bool system_resolve_rpfilter(const char *filter, unsigned int *id)
1742 if (!strcmp(filter, "strict"))
1744 else if (!strcmp(filter, "loose"))
1747 n = strtoul(filter, &e, 0);
1748 if (*e || e == filter || n > 2)
1756 static int system_iprule(struct iprule *rule, int cmd)
1758 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1761 struct rtmsg rtm = {
1762 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1763 .rtm_protocol = RTPROT_STATIC,
1764 .rtm_scope = RT_SCOPE_UNIVERSE,
1765 .rtm_table = RT_TABLE_UNSPEC,
1766 .rtm_type = RTN_UNSPEC,
1770 if (cmd == RTM_NEWRULE) {
1771 rtm.rtm_type = RTN_UNICAST;
1772 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1776 rtm.rtm_flags |= FIB_RULE_INVERT;
1778 if (rule->flags & IPRULE_SRC)
1779 rtm.rtm_src_len = rule->src_mask;
1781 if (rule->flags & IPRULE_DEST)
1782 rtm.rtm_dst_len = rule->dest_mask;
1784 if (rule->flags & IPRULE_TOS)
1785 rtm.rtm_tos = rule->tos;
1787 if (rule->flags & IPRULE_LOOKUP) {
1788 if (rule->lookup < 256)
1789 rtm.rtm_table = rule->lookup;
1792 if (rule->flags & IPRULE_ACTION)
1793 rtm.rtm_type = rule->action;
1794 else if (rule->flags & IPRULE_GOTO)
1795 rtm.rtm_type = FR_ACT_GOTO;
1796 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1797 rtm.rtm_type = FR_ACT_NOP;
1799 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1804 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1806 if (rule->flags & IPRULE_IN)
1807 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1809 if (rule->flags & IPRULE_OUT)
1810 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1812 if (rule->flags & IPRULE_SRC)
1813 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1815 if (rule->flags & IPRULE_DEST)
1816 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1818 if (rule->flags & IPRULE_PRIORITY)
1819 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1820 else if (cmd == RTM_NEWRULE)
1821 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1823 if (rule->flags & IPRULE_FWMARK)
1824 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1826 if (rule->flags & IPRULE_FWMASK)
1827 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1829 if (rule->flags & IPRULE_LOOKUP) {
1830 if (rule->lookup >= 256)
1831 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1834 if (rule->flags & IPRULE_GOTO)
1835 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1837 return system_rtnl_call(msg);
1840 int system_add_iprule(struct iprule *rule)
1842 return system_iprule(rule, RTM_NEWRULE);
1845 int system_del_iprule(struct iprule *rule)
1847 return system_iprule(rule, RTM_DELRULE);
1850 int system_flush_iprules(void)
1855 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1856 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1858 memset(&rule, 0, sizeof(rule));
1861 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1864 rule.lookup = RT_TABLE_PRELOCAL;
1865 rv |= system_iprule(&rule, RTM_NEWRULE);
1868 rule.lookup = RT_TABLE_LOCAL;
1869 rv |= system_iprule(&rule, RTM_NEWRULE);
1871 rule.priority = 32766;
1872 rule.lookup = RT_TABLE_MAIN;
1873 rv |= system_iprule(&rule, RTM_NEWRULE);
1875 rule.priority = 32767;
1876 rule.lookup = RT_TABLE_DEFAULT;
1877 rv |= system_iprule(&rule, RTM_NEWRULE);
1880 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1883 rule.lookup = RT_TABLE_PRELOCAL;
1884 rv |= system_iprule(&rule, RTM_NEWRULE);
1887 rule.lookup = RT_TABLE_LOCAL;
1888 rv |= system_iprule(&rule, RTM_NEWRULE);
1890 rule.priority = 32766;
1891 rule.lookup = RT_TABLE_MAIN;
1892 rv |= system_iprule(&rule, RTM_NEWRULE);
1897 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1899 return system_rtn_aton(action, id);
1902 time_t system_get_rtime(void)
1907 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1910 if (gettimeofday(&tv, NULL) == 0)
1917 #define IP_DF 0x4000
1920 static int tunnel_ioctl(const char *name, int cmd, void *p)
1924 memset(&ifr, 0, sizeof(ifr));
1925 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1926 ifr.ifr_ifru.ifru_data = p;
1927 return ioctl(sock_ioctl, cmd, &ifr);
1930 #ifdef IFLA_IPTUN_MAX
1931 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
1932 static int system_add_gre_tunnel(const char *name, const char *kind,
1933 const unsigned int link, struct blob_attr **tb, bool v6)
1936 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
1937 struct blob_attr *cur;
1938 uint32_t ikey = 0, okey = 0, flags = 0, flowinfo = 0;
1939 uint16_t iflags = 0, oflags = 0;
1941 int ret = 0, ttl = 64;
1943 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
1947 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
1948 nla_put_string(nlm, IFLA_IFNAME, name);
1950 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
1956 nla_put_string(nlm, IFLA_INFO_KIND, kind);
1957 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
1964 nla_put_u32(nlm, IFLA_GRE_LINK, link);
1966 if ((cur = tb[TUNNEL_ATTR_TTL]))
1967 ttl = blobmsg_get_u32(cur);
1969 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
1971 if ((cur = tb[TUNNEL_ATTR_TOS])) {
1972 char *str = blobmsg_get_string(cur);
1973 if (strcmp(str, "inherit")) {
1976 if (!system_tos_aton(str, &uval)) {
1982 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
1987 flags |= IP6_TNL_F_USE_ORIG_TCLASS;
1993 if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) {
1994 uint8_t icsum, ocsum, iseqno, oseqno;
1995 if (sscanf(blobmsg_get_string(cur), "%u,%u,%hhu,%hhu,%hhu,%hhu",
1996 &ikey, &okey, &icsum, &ocsum, &iseqno, &oseqno) < 6) {
2021 struct in6_addr in6buf;
2022 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2023 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2027 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
2030 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2031 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2035 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
2037 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, 4);
2040 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
2043 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags);
2045 struct in_addr inbuf;
2048 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2049 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2053 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
2056 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2057 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2061 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
2063 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
2065 okey = inbuf.s_addr;
2070 ikey = inbuf.s_addr;
2076 if ((cur = tb[TUNNEL_ATTR_DF]))
2077 set_df = blobmsg_get_bool(cur);
2079 /* ttl !=0 and nopmtudisc are incompatible */
2080 if (ttl && !set_df) {
2085 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
2087 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
2091 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
2094 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
2097 nla_put_u32(nlm, IFLA_GRE_OKEY, okey);
2100 nla_put_u32(nlm, IFLA_GRE_IKEY, ikey);
2102 nla_nest_end(nlm, infodata);
2103 nla_nest_end(nlm, linkinfo);
2105 return system_rtnl_call(nlm);
2113 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
2115 struct blob_attr *cur;
2117 struct ip_tunnel_parm p = {
2126 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
2127 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
2130 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
2131 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
2134 if ((cur = tb[TUNNEL_ATTR_DF]))
2135 set_df = blobmsg_get_bool(cur);
2137 if ((cur = tb[TUNNEL_ATTR_TTL]))
2138 p.iph.ttl = blobmsg_get_u32(cur);
2140 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2141 char *str = blobmsg_get_string(cur);
2142 if (strcmp(str, "inherit")) {
2145 if (!system_tos_aton(str, &uval))
2153 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
2154 /* ttl !=0 and nopmtudisc are incompatible */
2155 if (p.iph.ttl && p.iph.frag_off == 0)
2158 strncpy(p.name, name, sizeof(p.name));
2160 switch (p.iph.protocol) {
2162 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
2164 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
2171 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
2173 struct blob_attr *cur;
2176 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2178 str = blobmsg_data(cur);
2180 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
2181 !strcmp(str, "greip6") || !strcmp(str, "gretapip6"))
2182 return system_link_del(name);
2184 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
2187 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
2189 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2191 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2192 blob_data(attr), blob_len(attr));
2194 return __system_del_ip_tunnel(name, tb);
2197 int system_update_ipv6_mtu(struct device *dev, int mtu)
2201 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
2204 int fd = open(buf, O_RDWR);
2207 ssize_t len = read(fd, buf, sizeof(buf) - 1);
2214 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) > 0)
2223 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
2225 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2226 struct blob_attr *cur;
2229 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2230 blob_data(attr), blob_len(attr));
2232 __system_del_ip_tunnel(name, tb);
2234 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2236 str = blobmsg_data(cur);
2238 unsigned int ttl = 0;
2239 if ((cur = tb[TUNNEL_ATTR_TTL])) {
2240 ttl = blobmsg_get_u32(cur);
2245 unsigned int link = 0;
2246 if ((cur = tb[TUNNEL_ATTR_LINK])) {
2247 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
2251 if (iface->l3_dev.dev)
2252 link = iface->l3_dev.dev->ifindex;
2255 if (!strcmp(str, "sit")) {
2256 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
2260 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
2262 struct ip_tunnel_6rd p6;
2264 memset(&p6, 0, sizeof(p6));
2266 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
2267 &p6.prefix, &mask) || mask > 128)
2269 p6.prefixlen = mask;
2271 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
2272 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
2273 &p6.relay_prefix, &mask) || mask > 32)
2275 p6.relay_prefixlen = mask;
2278 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
2279 __system_del_ip_tunnel(name, tb);
2284 #ifdef IFLA_IPTUN_MAX
2285 } else if (!strcmp(str, "ipip6")) {
2286 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2287 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2288 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2294 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2295 nla_put_string(nlm, IFLA_IFNAME, name);
2298 nla_put_u32(nlm, IFLA_LINK, link);
2300 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2305 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2306 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2313 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2315 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2316 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2317 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
2319 struct in6_addr in6buf;
2320 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2321 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2325 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2328 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2329 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2333 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2336 #ifdef IFLA_IPTUN_FMR_MAX
2337 if ((cur = tb[TUNNEL_ATTR_FMRS])) {
2338 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2340 struct blob_attr *fmr;
2341 unsigned rem, fmrcnt = 0;
2342 blobmsg_for_each_attr(fmr, cur, rem) {
2343 if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
2346 unsigned ip4len, ip6len, ealen, offset = 6;
2350 if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
2351 ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) {
2356 struct in6_addr ip6prefix;
2357 struct in_addr ip4prefix;
2358 if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
2359 inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) {
2364 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2366 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2367 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2368 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2369 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2370 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2371 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2373 nla_nest_end(nlm, rule);
2376 nla_nest_end(nlm, fmrs);
2380 nla_nest_end(nlm, infodata);
2381 nla_nest_end(nlm, linkinfo);
2383 return system_rtnl_call(nlm);
2387 } else if (!strcmp(str, "greip")) {
2388 return system_add_gre_tunnel(name, "gre", link, tb, false);
2389 } else if (!strcmp(str, "gretapip")) {
2390 return system_add_gre_tunnel(name, "gretap", link, tb, false);
2391 } else if (!strcmp(str, "greip6")) {
2392 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
2393 } else if (!strcmp(str, "gretapip6")) {
2394 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
2396 } else if (!strcmp(str, "ipip")) {
2397 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);