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>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2
9 * as published by the Free Software Foundation
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
18 #include <sys/socket.h>
19 #include <sys/ioctl.h>
21 #include <sys/syscall.h>
24 #include <net/if_arp.h>
26 #include <arpa/inet.h>
27 #include <netinet/in.h>
29 #include <linux/rtnetlink.h>
30 #include <linux/sockios.h>
32 #include <linux/if_link.h>
33 #include <linux/if_vlan.h>
34 #include <linux/if_bridge.h>
35 #include <linux/if_tunnel.h>
36 #include <linux/ip6_tunnel.h>
37 #include <linux/ethtool.h>
38 #include <linux/fib_rules.h>
40 #ifndef RTN_FAILED_POLICY
41 #define RTN_FAILED_POLICY 12
49 #include <netlink/msg.h>
50 #include <netlink/attr.h>
51 #include <netlink/socket.h>
52 #include <libubox/uloop.h>
59 struct uloop_fd uloop;
64 static int sock_ioctl = -1;
65 static struct nl_sock *sock_rtnl = NULL;
67 static int cb_rtnl_event(struct nl_msg *msg, void *arg);
68 static void handle_hotplug_event(struct uloop_fd *u, unsigned int events);
70 static char dev_buf[256];
73 handler_nl_event(struct uloop_fd *u, unsigned int events)
75 struct event_socket *ev = container_of(u, struct event_socket, uloop);
77 socklen_t errlen = sizeof(err);
80 nl_recvmsgs_default(ev->sock);
84 if (getsockopt(u->fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen))
89 // Increase rx buffer size on netlink socket
91 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
94 // Request full dump since some info got dropped
95 struct rtgenmsg msg = { .rtgen_family = AF_UNSPEC };
96 nl_send_simple(ev->sock, RTM_GETLINK, NLM_F_DUMP, &msg, sizeof(msg));
106 uloop_fd_delete(&ev->uloop);
110 static struct nl_sock *
111 create_socket(int protocol, int groups)
113 struct nl_sock *sock;
115 sock = nl_socket_alloc();
120 nl_join_groups(sock, groups);
122 if (nl_connect(sock, protocol))
129 create_raw_event_socket(struct event_socket *ev, int protocol, int groups,
130 uloop_fd_handler cb, int flags)
132 ev->sock = create_socket(protocol, groups);
136 ev->uloop.fd = nl_socket_get_fd(ev->sock);
138 if (uloop_fd_add(&ev->uloop, ULOOP_READ|flags))
145 create_event_socket(struct event_socket *ev, int protocol,
146 int (*cb)(struct nl_msg *msg, void *arg))
148 if (!create_raw_event_socket(ev, protocol, 0, handler_nl_event, ULOOP_ERROR_CB))
151 // Install the valid custom callback handler
152 nl_socket_modify_cb(ev->sock, NL_CB_VALID, NL_CB_CUSTOM, cb, NULL);
154 // Disable sequence number checking on event sockets
155 nl_socket_disable_seq_check(ev->sock);
157 // Increase rx buffer size to 65K on event sockets
159 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
165 int system_init(void)
167 static struct event_socket rtnl_event;
168 static struct event_socket hotplug_event;
170 sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0);
171 system_fd_set_cloexec(sock_ioctl);
173 // Prepare socket for routing / address control
174 sock_rtnl = create_socket(NETLINK_ROUTE, 0);
178 if (!create_event_socket(&rtnl_event, NETLINK_ROUTE, cb_rtnl_event))
181 if (!create_raw_event_socket(&hotplug_event, NETLINK_KOBJECT_UEVENT, 1,
182 handle_hotplug_event, 0))
185 // Receive network link events form kernel
186 nl_socket_add_membership(rtnl_event.sock, RTNLGRP_LINK);
191 static void system_set_sysctl(const char *path, const char *val)
195 fd = open(path, O_WRONLY);
199 if (write(fd, val, strlen(val))) {}
203 static void system_set_dev_sysctl(const char *path, const char *device, const char *val)
205 snprintf(dev_buf, sizeof(dev_buf), path, device);
206 system_set_sysctl(dev_buf, val);
209 static void system_set_disable_ipv6(struct device *dev, const char *val)
211 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val);
215 #define IFF_LOWER_UP 0x10000
218 // Evaluate netlink messages
219 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
221 struct nlmsghdr *nh = nlmsg_hdr(msg);
222 struct ifinfomsg *ifi = NLMSG_DATA(nh);
223 struct nlattr *nla[__IFLA_MAX];
225 if (nh->nlmsg_type != RTM_NEWLINK)
228 nlmsg_parse(nh, sizeof(*ifi), nla, __IFLA_MAX - 1, NULL);
229 if (!nla[IFLA_IFNAME])
232 struct device *dev = device_get(nla_data(nla[IFLA_IFNAME]), false);
236 device_set_ifindex(dev, ifi->ifi_index);
237 device_set_link(dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
244 handle_hotplug_msg(char *data, int size)
246 const char *subsystem = NULL, *interface = NULL;
247 char *cur, *end, *sep;
252 if (!strncmp(data, "add@", 4))
254 else if (!strncmp(data, "remove@", 7))
259 skip = strlen(data) + 1;
262 for (cur = data + skip; cur < end; cur += skip) {
263 skip = strlen(cur) + 1;
265 sep = strchr(cur, '=');
270 if (!strcmp(cur, "INTERFACE"))
272 else if (!strcmp(cur, "SUBSYSTEM")) {
274 if (strcmp(subsystem, "net") != 0)
277 if (subsystem && interface)
283 dev = device_get(interface, false);
287 if (dev->type != &simple_device_type)
290 if (add && system_if_force_external(dev->ifname))
293 device_set_present(dev, add);
297 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
299 struct event_socket *ev = container_of(u, struct event_socket, uloop);
300 struct sockaddr_nl nla;
301 unsigned char *buf = NULL;
304 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
306 handle_hotplug_msg((char *) buf, size);
312 static int system_rtnl_call(struct nl_msg *msg)
316 ret = nl_send_auto_complete(sock_rtnl, msg);
322 return nl_wait_for_ack(sock_rtnl);
325 int system_bridge_delbr(struct device *bridge)
327 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
330 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
334 memset(&ifr, 0, sizeof(ifr));
336 ifr.ifr_ifindex = dev->ifindex;
339 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
340 return ioctl(sock_ioctl, cmd, &ifr);
343 static bool system_is_bridge(const char *name, char *buf, int buflen)
347 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
348 if (stat(buf, &st) < 0)
354 static char *system_get_bridge(const char *name, char *buf, int buflen)
360 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
361 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
364 if (gl.gl_pathc == 0)
367 len = readlink(gl.gl_pathv[0], buf, buflen);
372 path = strrchr(buf, '/');
379 int system_bridge_addif(struct device *bridge, struct device *dev)
383 system_set_disable_ipv6(dev, "1");
384 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
385 if (oldbr && !strcmp(oldbr, bridge->ifname))
388 return system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
391 int system_bridge_delif(struct device *bridge, struct device *dev)
393 system_set_disable_ipv6(dev, "0");
394 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
397 static int system_if_resolve(struct device *dev)
400 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
401 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
402 return ifr.ifr_ifindex;
407 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
411 memset(&ifr, 0, sizeof(ifr));
412 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
413 ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
414 ifr.ifr_flags |= add;
415 ifr.ifr_flags &= ~rem;
416 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
428 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
430 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
432 return ifa->ifa_index == ifindex;
435 static bool check_route(struct nlmsghdr *hdr, int ifindex)
437 struct rtmsg *r = NLMSG_DATA(hdr);
438 struct nlattr *tb[__RTA_MAX];
440 if (r->rtm_protocol == RTPROT_KERNEL &&
441 r->rtm_family == AF_INET6)
444 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
448 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
451 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
456 static int cb_clear_event(struct nl_msg *msg, void *arg)
458 struct clear_data *clr = arg;
459 struct nlmsghdr *hdr = nlmsg_hdr(msg);
460 bool (*cb)(struct nlmsghdr *, int ifindex);
466 if (hdr->nlmsg_type != RTM_NEWADDR)
473 if (hdr->nlmsg_type != RTM_NEWROUTE)
480 if (hdr->nlmsg_type != RTM_NEWRULE)
489 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
492 if (type == RTM_DELRULE)
493 D(SYSTEM, "Remove a rule\n");
495 D(SYSTEM, "Remove %s from device %s\n",
496 type == RTM_DELADDR ? "an address" : "a route",
498 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
499 hdr = nlmsg_hdr(clr->msg);
500 hdr->nlmsg_type = type;
501 hdr->nlmsg_flags = NLM_F_REQUEST;
503 nl_socket_disable_auto_ack(sock_rtnl);
504 nl_send_auto_complete(sock_rtnl, clr->msg);
505 nl_socket_enable_auto_ack(sock_rtnl);
511 cb_finish_event(struct nl_msg *msg, void *arg)
519 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
522 *pending = err->error;
527 system_if_clear_entries(struct device *dev, int type, int af)
529 struct clear_data clr;
530 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
533 .rtm_flags = RTM_F_CLONED,
535 int flags = NLM_F_DUMP;
544 clr.size = sizeof(struct rtgenmsg);
547 clr.size = sizeof(struct rtmsg);
556 clr.msg = nlmsg_alloc_simple(type, flags);
560 nlmsg_append(clr.msg, &rtm, clr.size, 0);
561 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
562 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
563 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
565 nl_send_auto_complete(sock_rtnl, clr.msg);
567 nl_recvmsgs(sock_rtnl, cb);
575 * Clear bridge (membership) state and bring down device
577 void system_if_clear_state(struct device *dev)
579 static char buf[256];
585 device_set_ifindex(dev, system_if_resolve(dev));
589 system_if_flags(dev->ifname, 0, IFF_UP);
591 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
592 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
593 system_bridge_delbr(dev);
597 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
599 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
600 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
603 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
604 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
605 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
606 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
607 system_set_disable_ipv6(dev, "0");
610 static inline unsigned long
611 sec_to_jiffies(int val)
613 return (unsigned long) val * 100;
616 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
618 unsigned long args[4] = {};
620 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
623 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
624 args[1] = !!cfg->stp;
625 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
627 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
628 args[1] = sec_to_jiffies(cfg->forward_delay);
629 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
631 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
632 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
634 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
635 args[1] = cfg->priority;
636 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
638 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
639 args[0] = BRCTL_SET_AGEING_TIME;
640 args[1] = sec_to_jiffies(cfg->ageing_time);
641 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
644 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
645 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
646 args[1] = sec_to_jiffies(cfg->hello_time);
647 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
650 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
651 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
652 args[1] = sec_to_jiffies(cfg->max_age);
653 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
659 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
662 struct nlattr *linkinfo, *data;
663 struct ifinfomsg iim = { .ifi_family = AF_INET };
664 int ifindex = system_if_resolve(dev);
666 static const struct {
668 enum macvlan_mode val;
670 { "private", MACVLAN_MODE_PRIVATE },
671 { "vepa", MACVLAN_MODE_VEPA },
672 { "bridge", MACVLAN_MODE_BRIDGE },
673 { "passthru", MACVLAN_MODE_PASSTHRU },
679 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
684 nlmsg_append(msg, &iim, sizeof(iim), 0);
686 if (cfg->flags & MACVLAN_OPT_MACADDR)
687 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
688 nla_put(msg, IFLA_IFNAME, IFNAMSIZ, macvlan->ifname);
689 nla_put_u32(msg, IFLA_LINK, ifindex);
691 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
692 goto nla_put_failure;
694 nla_put(msg, IFLA_INFO_KIND, strlen("macvlan"), "macvlan");
696 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
697 goto nla_put_failure;
700 for (i = 0; i < ARRAY_SIZE(modes); i++) {
701 if (strcmp(cfg->mode, modes[i].name) != 0)
704 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
709 nla_nest_end(msg, data);
710 nla_nest_end(msg, linkinfo);
712 rv = system_rtnl_call(msg);
714 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
723 int system_macvlan_del(struct device *macvlan)
726 struct ifinfomsg iim;
728 iim.ifi_family = AF_INET;
731 msg = nlmsg_alloc_simple(RTM_DELLINK, 0);
736 nlmsg_append(msg, &iim, sizeof(iim), 0);
738 nla_put(msg, IFLA_INFO_KIND, strlen("macvlan"), "macvlan");
739 nla_put(msg, IFLA_IFNAME, sizeof(macvlan->ifname), macvlan->ifname);
741 system_rtnl_call(msg);
746 static int system_vlan(struct device *dev, int id)
748 struct vlan_ioctl_args ifr = {
749 .cmd = SET_VLAN_NAME_TYPE_CMD,
750 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
753 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
756 ifr.cmd = DEL_VLAN_CMD;
759 ifr.cmd = ADD_VLAN_CMD;
762 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
763 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
766 int system_vlan_add(struct device *dev, int id)
768 return system_vlan(dev, id);
771 int system_vlan_del(struct device *dev)
773 return system_vlan(dev, -1);
777 system_if_get_settings(struct device *dev, struct device_settings *s)
781 memset(&ifr, 0, sizeof(ifr));
782 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
784 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
785 s->mtu = ifr.ifr_mtu;
786 s->flags |= DEV_OPT_MTU;
789 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
790 s->txqueuelen = ifr.ifr_qlen;
791 s->flags |= DEV_OPT_TXQUEUELEN;
794 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
795 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
796 s->flags |= DEV_OPT_MACADDR;
801 system_if_apply_settings(struct device *dev, struct device_settings *s)
805 memset(&ifr, 0, sizeof(ifr));
806 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
807 if (s->flags & DEV_OPT_MTU) {
808 ifr.ifr_mtu = s->mtu;
809 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
810 s->flags &= ~DEV_OPT_MTU;
812 if (s->flags & DEV_OPT_TXQUEUELEN) {
813 ifr.ifr_qlen = s->txqueuelen;
814 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
815 s->flags &= ~DEV_OPT_TXQUEUELEN;
817 if ((s->flags & DEV_OPT_MACADDR) && !dev->external) {
818 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
819 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
820 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
821 s->flags &= ~DEV_OPT_MACADDR;
825 int system_if_up(struct device *dev)
827 system_if_get_settings(dev, &dev->orig_settings);
828 system_if_apply_settings(dev, &dev->settings);
829 device_set_ifindex(dev, system_if_resolve(dev));
830 return system_if_flags(dev->ifname, IFF_UP, 0);
833 int system_if_down(struct device *dev)
835 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
836 dev->orig_settings.flags &= dev->settings.flags;
837 system_if_apply_settings(dev, &dev->orig_settings);
841 struct if_check_data {
847 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
849 struct nlmsghdr *nh = nlmsg_hdr(msg);
850 struct ifinfomsg *ifi = NLMSG_DATA(nh);
851 struct if_check_data *chk = (struct if_check_data *)arg;
853 if (nh->nlmsg_type != RTM_NEWLINK)
856 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
857 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
862 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
864 struct if_check_data *chk = (struct if_check_data *)arg;
869 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
871 struct if_check_data *chk = (struct if_check_data *)arg;
873 device_set_present(chk->dev, false);
874 device_set_link(chk->dev, false);
875 chk->pending = err->error;
880 int system_if_check(struct device *dev)
882 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
884 struct ifinfomsg ifi = {
885 .ifi_family = AF_UNSPEC,
888 struct if_check_data chk = {
894 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
895 if (!msg || nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
896 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
899 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
900 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
901 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
903 nl_send_auto_complete(sock_rtnl, msg);
904 while (chk.pending > 0)
905 nl_recvmsgs(sock_rtnl, cb);
916 system_if_get_parent(struct device *dev)
918 char buf[64], *devname;
919 int ifindex, iflink, len;
922 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
927 len = fread(buf, 1, sizeof(buf) - 1, f);
934 iflink = strtoul(buf, NULL, 0);
935 ifindex = system_if_resolve(dev);
936 if (!iflink || iflink == ifindex)
939 devname = if_indextoname(iflink, buf);
943 return device_get(devname, true);
947 read_string_file(int dir_fd, const char *file, char *buf, int len)
953 fd = openat(dir_fd, file, O_RDONLY);
958 len = read(fd, buf, len - 1);
962 } else if (len > 0) {
965 c = strchr(buf, '\n');
978 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
983 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
985 *val = strtoull(buf, NULL, 0);
990 /* Assume advertised flags == supported flags */
991 static const struct {
994 } ethtool_link_modes[] = {
995 { ADVERTISED_10baseT_Half, "10H" },
996 { ADVERTISED_10baseT_Full, "10F" },
997 { ADVERTISED_100baseT_Half, "100H" },
998 { ADVERTISED_100baseT_Full, "100F" },
999 { ADVERTISED_1000baseT_Half, "1000H" },
1000 { ADVERTISED_1000baseT_Full, "1000F" },
1003 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1006 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1007 if (mask & ethtool_link_modes[i].mask)
1008 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1013 system_if_force_external(const char *ifname)
1018 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1019 return stat(buf, &s) == 0;
1023 system_if_dump_info(struct device *dev, struct blob_buf *b)
1025 struct ethtool_cmd ecmd;
1031 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
1032 dir_fd = open(buf, O_DIRECTORY);
1034 memset(&ecmd, 0, sizeof(ecmd));
1035 memset(&ifr, 0, sizeof(ifr));
1036 strcpy(ifr.ifr_name, dev->ifname);
1037 ifr.ifr_data = (caddr_t) &ecmd;
1038 ecmd.cmd = ETHTOOL_GSET;
1040 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1041 c = blobmsg_open_array(b, "link-advertising");
1042 system_add_link_modes(b, ecmd.advertising);
1043 blobmsg_close_array(b, c);
1045 c = blobmsg_open_array(b, "link-supported");
1046 system_add_link_modes(b, ecmd.supported);
1047 blobmsg_close_array(b, c);
1049 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1050 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1051 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1052 blobmsg_add_string_buffer(b);
1060 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1062 const char *const counters[] = {
1063 "collisions", "rx_frame_errors", "tx_compressed",
1064 "multicast", "rx_length_errors", "tx_dropped",
1065 "rx_bytes", "rx_missed_errors", "tx_errors",
1066 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1067 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1068 "rx_dropped", "tx_aborted_errors", "tx_packets",
1069 "rx_errors", "tx_bytes", "tx_window_errors",
1070 "rx_fifo_errors", "tx_carrier_errors",
1077 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1078 stats_dir = open(buf, O_DIRECTORY);
1082 for (i = 0; i < ARRAY_SIZE(counters); i++)
1083 if (read_uint64_file(stats_dir, counters[i], &val))
1084 blobmsg_add_u64(b, counters[i], val);
1090 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1092 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1093 int alen = v4 ? 4 : 16;
1094 unsigned int flags = 0;
1095 struct ifaddrmsg ifa = {
1096 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1097 .ifa_prefixlen = addr->mask,
1098 .ifa_index = dev->ifindex,
1102 if (cmd == RTM_NEWADDR)
1103 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1105 msg = nlmsg_alloc_simple(cmd, flags);
1109 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1110 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1112 if (addr->broadcast)
1113 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1114 if (addr->point_to_point)
1115 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1117 time_t now = system_get_rtime();
1118 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1120 if (addr->preferred_until) {
1121 int64_t preferred = addr->preferred_until - now;
1124 else if (preferred > UINT32_MAX)
1125 preferred = UINT32_MAX;
1127 cinfo.ifa_prefered = preferred;
1130 if (addr->valid_until) {
1131 int64_t valid = addr->valid_until - now;
1134 else if (valid > UINT32_MAX)
1137 cinfo.ifa_valid = valid;
1140 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1143 return system_rtnl_call(msg);
1146 int system_add_address(struct device *dev, struct device_addr *addr)
1148 return system_addr(dev, addr, RTM_NEWADDR);
1151 int system_del_address(struct device *dev, struct device_addr *addr)
1153 return system_addr(dev, addr, RTM_DELADDR);
1156 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1158 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1160 unsigned int flags = 0;
1163 have_gw = !!route->nexthop.in.s_addr;
1165 have_gw = route->nexthop.in6.s6_addr32[0] ||
1166 route->nexthop.in6.s6_addr32[1] ||
1167 route->nexthop.in6.s6_addr32[2] ||
1168 route->nexthop.in6.s6_addr32[3];
1170 unsigned char scope = (cmd == RTM_DELROUTE) ? RT_SCOPE_NOWHERE :
1171 (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1173 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1174 ? route->table : RT_TABLE_MAIN;
1176 struct rtmsg rtm = {
1177 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1178 .rtm_dst_len = route->mask,
1179 .rtm_src_len = route->sourcemask,
1180 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1181 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
1183 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1187 if (cmd == RTM_NEWROUTE) {
1188 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1190 if (!dev) { // Add null-route
1191 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1192 rtm.rtm_type = RTN_UNREACHABLE;
1196 msg = nlmsg_alloc_simple(cmd, flags);
1200 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1203 nla_put(msg, RTA_DST, alen, &route->addr);
1205 if (route->sourcemask)
1206 nla_put(msg, RTA_SRC, alen, &route->source);
1208 if (route->metric > 0)
1209 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1212 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1215 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1218 nla_put_u32(msg, RTA_TABLE, table);
1220 return system_rtnl_call(msg);
1223 int system_add_route(struct device *dev, struct device_route *route)
1225 return system_rt(dev, route, RTM_NEWROUTE);
1228 int system_del_route(struct device *dev, struct device_route *route)
1230 return system_rt(dev, route, RTM_DELROUTE);
1233 int system_flush_routes(void)
1235 const char *names[] = {
1236 "/proc/sys/net/ipv4/route/flush",
1237 "/proc/sys/net/ipv6/route/flush"
1241 for (i = 0; i < ARRAY_SIZE(names); i++) {
1242 fd = open(names[i], O_WRONLY);
1246 if (write(fd, "-1", 2)) {}
1252 bool system_resolve_rt_table(const char *name, unsigned int *id)
1256 unsigned int n, table = RT_TABLE_UNSPEC;
1258 /* first try to parse table as number */
1259 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1262 /* handle well known aliases */
1263 else if (!strcmp(name, "default"))
1264 table = RT_TABLE_DEFAULT;
1265 else if (!strcmp(name, "main"))
1266 table = RT_TABLE_MAIN;
1267 else if (!strcmp(name, "local"))
1268 table = RT_TABLE_LOCAL;
1270 /* try to look up name in /etc/iproute2/rt_tables */
1271 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1273 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1275 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1278 n = strtoul(e, NULL, 10);
1279 e = strtok(NULL, " \t\n");
1281 if (e && !strcmp(e, name))
1291 if (table == RT_TABLE_UNSPEC)
1294 /* do not consider main table special */
1295 if (table == RT_TABLE_MAIN)
1296 table = RT_TABLE_UNSPEC;
1302 static int system_iprule(struct iprule *rule, int cmd)
1304 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1307 struct rtmsg rtm = {
1308 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1309 .rtm_protocol = RTPROT_STATIC,
1310 .rtm_scope = RT_SCOPE_UNIVERSE,
1311 .rtm_table = RT_TABLE_UNSPEC,
1312 .rtm_type = RTN_UNSPEC,
1316 if (cmd == RTM_NEWRULE) {
1317 rtm.rtm_type = RTN_UNICAST;
1318 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1322 rtm.rtm_flags |= FIB_RULE_INVERT;
1324 if (rule->flags & IPRULE_SRC)
1325 rtm.rtm_src_len = rule->src_mask;
1327 if (rule->flags & IPRULE_DEST)
1328 rtm.rtm_dst_len = rule->dest_mask;
1330 if (rule->flags & IPRULE_TOS)
1331 rtm.rtm_tos = rule->tos;
1333 if (rule->flags & IPRULE_LOOKUP) {
1334 if (rule->lookup < 256)
1335 rtm.rtm_table = rule->lookup;
1338 if (rule->flags & IPRULE_ACTION)
1339 rtm.rtm_type = rule->action;
1340 else if (rule->flags & IPRULE_GOTO)
1341 rtm.rtm_type = FR_ACT_GOTO;
1342 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1343 rtm.rtm_type = FR_ACT_NOP;
1345 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1350 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1352 if (rule->flags & IPRULE_IN)
1353 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1355 if (rule->flags & IPRULE_OUT)
1356 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1358 if (rule->flags & IPRULE_SRC)
1359 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1361 if (rule->flags & IPRULE_DEST)
1362 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1364 if (rule->flags & IPRULE_PRIORITY)
1365 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1366 else if (cmd == RTM_NEWRULE)
1367 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1369 if (rule->flags & IPRULE_FWMARK)
1370 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1372 if (rule->flags & IPRULE_FWMASK)
1373 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1375 if (rule->flags & IPRULE_LOOKUP) {
1376 if (rule->lookup >= 256)
1377 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1380 if (rule->flags & IPRULE_GOTO)
1381 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1383 return system_rtnl_call(msg);
1386 int system_add_iprule(struct iprule *rule)
1388 return system_iprule(rule, RTM_NEWRULE);
1391 int system_del_iprule(struct iprule *rule)
1393 return system_iprule(rule, RTM_DELRULE);
1396 int system_flush_iprules(void)
1401 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1402 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1404 memset(&rule, 0, sizeof(rule));
1407 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1410 rule.lookup = RT_TABLE_LOCAL;
1411 rv |= system_iprule(&rule, RTM_NEWRULE);
1413 rule.priority = 32766;
1414 rule.lookup = RT_TABLE_MAIN;
1415 rv |= system_iprule(&rule, RTM_NEWRULE);
1417 rule.priority = 32767;
1418 rule.lookup = RT_TABLE_DEFAULT;
1419 rv |= system_iprule(&rule, RTM_NEWRULE);
1422 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1425 rule.lookup = RT_TABLE_LOCAL;
1426 rv |= system_iprule(&rule, RTM_NEWRULE);
1428 rule.priority = 32766;
1429 rule.lookup = RT_TABLE_MAIN;
1430 rv |= system_iprule(&rule, RTM_NEWRULE);
1435 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1440 if (!strcmp(action, "local"))
1442 else if (!strcmp(action, "nat"))
1444 else if (!strcmp(action, "broadcast"))
1446 else if (!strcmp(action, "anycast"))
1448 else if (!strcmp(action, "multicast"))
1450 else if (!strcmp(action, "prohibit"))
1452 else if (!strcmp(action, "unreachable"))
1453 n = RTN_UNREACHABLE;
1454 else if (!strcmp(action, "blackhole"))
1456 else if (!strcmp(action, "xresolve"))
1458 else if (!strcmp(action, "unicast"))
1460 else if (!strcmp(action, "throw"))
1462 else if (!strcmp(action, "failed_policy"))
1463 n = RTN_FAILED_POLICY;
1465 n = strtoul(action, &e, 0);
1466 if (!e || *e || e == action || n > 255)
1474 time_t system_get_rtime(void)
1479 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1482 if (gettimeofday(&tv, NULL) == 0)
1489 #define IP_DF 0x4000
1492 static int tunnel_ioctl(const char *name, int cmd, void *p)
1496 memset(&ifr, 0, sizeof(ifr));
1497 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1498 ifr.ifr_ifru.ifru_data = p;
1499 return ioctl(sock_ioctl, cmd, &ifr);
1502 int system_del_ip_tunnel(const char *name)
1504 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
1507 int system_update_ipv6_mtu(struct device *dev, int mtu)
1511 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
1514 int fd = open(buf, O_RDWR);
1515 ssize_t len = read(fd, buf, sizeof(buf) - 1);
1522 if (!mtu || ret <= mtu)
1525 lseek(fd, 0, SEEK_SET);
1526 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) <= 0)
1534 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
1536 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
1537 struct blob_attr *cur;
1541 system_del_ip_tunnel(name);
1543 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
1544 blob_data(attr), blob_len(attr));
1546 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
1548 str = blobmsg_data(cur);
1550 if ((cur = tb[TUNNEL_ATTR_DF]))
1551 set_df = blobmsg_get_bool(cur);
1553 unsigned int ttl = 0;
1554 if ((cur = tb[TUNNEL_ATTR_TTL])) {
1555 ttl = blobmsg_get_u32(cur);
1556 if (ttl > 255 || (!set_df && ttl))
1560 unsigned int link = 0;
1561 if ((cur = tb[TUNNEL_ATTR_LINK])) {
1562 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
1566 if (iface->l3_dev.dev)
1567 link = iface->l3_dev.dev->ifindex;
1570 if (!strcmp(str, "sit")) {
1571 struct ip_tunnel_parm p = {
1576 .frag_off = set_df ? htons(IP_DF) : 0,
1577 .protocol = IPPROTO_IPV6,
1582 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
1583 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
1586 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
1587 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
1590 strncpy(p.name, name, sizeof(p.name));
1591 if (tunnel_ioctl("sit0", SIOCADDTUNNEL, &p) < 0)
1595 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
1597 struct ip_tunnel_6rd p6;
1599 memset(&p6, 0, sizeof(p6));
1601 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
1602 &p6.prefix, &mask) || mask > 128)
1604 p6.prefixlen = mask;
1606 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
1607 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
1608 &p6.relay_prefix, &mask) || mask > 32)
1610 p6.relay_prefixlen = mask;
1613 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
1614 system_del_ip_tunnel(name);
1619 } else if (!strcmp(str, "ipip6")) {
1620 struct ip6_tnl_parm p = {
1622 .proto = IPPROTO_IPIP,
1623 .hop_limit = (ttl) ? ttl : 64,
1627 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
1628 inet_pton(AF_INET6, blobmsg_data(cur), &p.laddr) < 1)
1631 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
1632 inet_pton(AF_INET6, blobmsg_data(cur), &p.raddr) < 1)
1635 strncpy(p.name, name, sizeof(p.name));
1636 if (tunnel_ioctl("ip6tnl0", SIOCADDTUNNEL, &p) < 0)