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, unsigned int apply_mask)
808 memset(&ifr, 0, sizeof(ifr));
809 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
810 if (s->flags & DEV_OPT_MTU & apply_mask) {
811 ifr.ifr_mtu = s->mtu;
812 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
813 s->flags &= ~DEV_OPT_MTU;
815 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
816 ifr.ifr_qlen = s->txqueuelen;
817 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
818 s->flags &= ~DEV_OPT_TXQUEUELEN;
820 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
821 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
822 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
823 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
824 s->flags &= ~DEV_OPT_MACADDR;
828 int system_if_up(struct device *dev)
830 system_if_get_settings(dev, &dev->orig_settings);
831 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
832 device_set_ifindex(dev, system_if_resolve(dev));
833 return system_if_flags(dev->ifname, IFF_UP, 0);
836 int system_if_down(struct device *dev)
838 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
839 dev->orig_settings.flags &= dev->settings.flags;
840 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
844 struct if_check_data {
850 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
852 struct nlmsghdr *nh = nlmsg_hdr(msg);
853 struct ifinfomsg *ifi = NLMSG_DATA(nh);
854 struct if_check_data *chk = (struct if_check_data *)arg;
856 if (nh->nlmsg_type != RTM_NEWLINK)
859 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
860 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
865 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
867 struct if_check_data *chk = (struct if_check_data *)arg;
872 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
874 struct if_check_data *chk = (struct if_check_data *)arg;
876 device_set_present(chk->dev, false);
877 device_set_link(chk->dev, false);
878 chk->pending = err->error;
883 int system_if_check(struct device *dev)
885 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
887 struct ifinfomsg ifi = {
888 .ifi_family = AF_UNSPEC,
891 struct if_check_data chk = {
897 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
898 if (!msg || nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
899 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
902 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
903 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
904 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
906 nl_send_auto_complete(sock_rtnl, msg);
907 while (chk.pending > 0)
908 nl_recvmsgs(sock_rtnl, cb);
919 system_if_get_parent(struct device *dev)
921 char buf[64], *devname;
922 int ifindex, iflink, len;
925 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
930 len = fread(buf, 1, sizeof(buf) - 1, f);
937 iflink = strtoul(buf, NULL, 0);
938 ifindex = system_if_resolve(dev);
939 if (!iflink || iflink == ifindex)
942 devname = if_indextoname(iflink, buf);
946 return device_get(devname, true);
950 read_string_file(int dir_fd, const char *file, char *buf, int len)
956 fd = openat(dir_fd, file, O_RDONLY);
961 len = read(fd, buf, len - 1);
965 } else if (len > 0) {
968 c = strchr(buf, '\n');
981 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
986 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
988 *val = strtoull(buf, NULL, 0);
993 /* Assume advertised flags == supported flags */
994 static const struct {
997 } ethtool_link_modes[] = {
998 { ADVERTISED_10baseT_Half, "10H" },
999 { ADVERTISED_10baseT_Full, "10F" },
1000 { ADVERTISED_100baseT_Half, "100H" },
1001 { ADVERTISED_100baseT_Full, "100F" },
1002 { ADVERTISED_1000baseT_Half, "1000H" },
1003 { ADVERTISED_1000baseT_Full, "1000F" },
1006 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1009 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1010 if (mask & ethtool_link_modes[i].mask)
1011 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1016 system_if_force_external(const char *ifname)
1021 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1022 return stat(buf, &s) == 0;
1026 system_if_dump_info(struct device *dev, struct blob_buf *b)
1028 struct ethtool_cmd ecmd;
1034 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
1035 dir_fd = open(buf, O_DIRECTORY);
1037 memset(&ecmd, 0, sizeof(ecmd));
1038 memset(&ifr, 0, sizeof(ifr));
1039 strcpy(ifr.ifr_name, dev->ifname);
1040 ifr.ifr_data = (caddr_t) &ecmd;
1041 ecmd.cmd = ETHTOOL_GSET;
1043 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1044 c = blobmsg_open_array(b, "link-advertising");
1045 system_add_link_modes(b, ecmd.advertising);
1046 blobmsg_close_array(b, c);
1048 c = blobmsg_open_array(b, "link-supported");
1049 system_add_link_modes(b, ecmd.supported);
1050 blobmsg_close_array(b, c);
1052 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1053 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1054 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1055 blobmsg_add_string_buffer(b);
1063 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1065 const char *const counters[] = {
1066 "collisions", "rx_frame_errors", "tx_compressed",
1067 "multicast", "rx_length_errors", "tx_dropped",
1068 "rx_bytes", "rx_missed_errors", "tx_errors",
1069 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1070 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1071 "rx_dropped", "tx_aborted_errors", "tx_packets",
1072 "rx_errors", "tx_bytes", "tx_window_errors",
1073 "rx_fifo_errors", "tx_carrier_errors",
1080 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1081 stats_dir = open(buf, O_DIRECTORY);
1085 for (i = 0; i < ARRAY_SIZE(counters); i++)
1086 if (read_uint64_file(stats_dir, counters[i], &val))
1087 blobmsg_add_u64(b, counters[i], val);
1093 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1095 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1096 int alen = v4 ? 4 : 16;
1097 unsigned int flags = 0;
1098 struct ifaddrmsg ifa = {
1099 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1100 .ifa_prefixlen = addr->mask,
1101 .ifa_index = dev->ifindex,
1105 if (cmd == RTM_NEWADDR)
1106 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1108 msg = nlmsg_alloc_simple(cmd, flags);
1112 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1113 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1115 if (addr->broadcast)
1116 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1117 if (addr->point_to_point)
1118 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1120 time_t now = system_get_rtime();
1121 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1123 if (addr->preferred_until) {
1124 int64_t preferred = addr->preferred_until - now;
1127 else if (preferred > UINT32_MAX)
1128 preferred = UINT32_MAX;
1130 cinfo.ifa_prefered = preferred;
1133 if (addr->valid_until) {
1134 int64_t valid = addr->valid_until - now;
1137 else if (valid > UINT32_MAX)
1140 cinfo.ifa_valid = valid;
1143 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1146 return system_rtnl_call(msg);
1149 int system_add_address(struct device *dev, struct device_addr *addr)
1151 return system_addr(dev, addr, RTM_NEWADDR);
1154 int system_del_address(struct device *dev, struct device_addr *addr)
1156 return system_addr(dev, addr, RTM_DELADDR);
1159 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1161 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1163 unsigned int flags = 0;
1166 have_gw = !!route->nexthop.in.s_addr;
1168 have_gw = route->nexthop.in6.s6_addr32[0] ||
1169 route->nexthop.in6.s6_addr32[1] ||
1170 route->nexthop.in6.s6_addr32[2] ||
1171 route->nexthop.in6.s6_addr32[3];
1173 unsigned char scope = (cmd == RTM_DELROUTE) ? RT_SCOPE_NOWHERE :
1174 (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1176 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1177 ? route->table : RT_TABLE_MAIN;
1179 struct rtmsg rtm = {
1180 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1181 .rtm_dst_len = route->mask,
1182 .rtm_src_len = route->sourcemask,
1183 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1184 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
1186 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1190 if (cmd == RTM_NEWROUTE) {
1191 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1193 if (!dev) { // Add null-route
1194 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1195 rtm.rtm_type = RTN_UNREACHABLE;
1199 msg = nlmsg_alloc_simple(cmd, flags);
1203 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1206 nla_put(msg, RTA_DST, alen, &route->addr);
1208 if (route->sourcemask)
1209 nla_put(msg, RTA_SRC, alen, &route->source);
1211 if (route->metric > 0)
1212 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1215 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1218 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1221 nla_put_u32(msg, RTA_TABLE, table);
1223 return system_rtnl_call(msg);
1226 int system_add_route(struct device *dev, struct device_route *route)
1228 return system_rt(dev, route, RTM_NEWROUTE);
1231 int system_del_route(struct device *dev, struct device_route *route)
1233 return system_rt(dev, route, RTM_DELROUTE);
1236 int system_flush_routes(void)
1238 const char *names[] = {
1239 "/proc/sys/net/ipv4/route/flush",
1240 "/proc/sys/net/ipv6/route/flush"
1244 for (i = 0; i < ARRAY_SIZE(names); i++) {
1245 fd = open(names[i], O_WRONLY);
1249 if (write(fd, "-1", 2)) {}
1255 bool system_resolve_rt_table(const char *name, unsigned int *id)
1259 unsigned int n, table = RT_TABLE_UNSPEC;
1261 /* first try to parse table as number */
1262 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1265 /* handle well known aliases */
1266 else if (!strcmp(name, "default"))
1267 table = RT_TABLE_DEFAULT;
1268 else if (!strcmp(name, "main"))
1269 table = RT_TABLE_MAIN;
1270 else if (!strcmp(name, "local"))
1271 table = RT_TABLE_LOCAL;
1273 /* try to look up name in /etc/iproute2/rt_tables */
1274 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1276 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1278 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1281 n = strtoul(e, NULL, 10);
1282 e = strtok(NULL, " \t\n");
1284 if (e && !strcmp(e, name))
1294 if (table == RT_TABLE_UNSPEC)
1297 /* do not consider main table special */
1298 if (table == RT_TABLE_MAIN)
1299 table = RT_TABLE_UNSPEC;
1305 static int system_iprule(struct iprule *rule, int cmd)
1307 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1310 struct rtmsg rtm = {
1311 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1312 .rtm_protocol = RTPROT_STATIC,
1313 .rtm_scope = RT_SCOPE_UNIVERSE,
1314 .rtm_table = RT_TABLE_UNSPEC,
1315 .rtm_type = RTN_UNSPEC,
1319 if (cmd == RTM_NEWRULE) {
1320 rtm.rtm_type = RTN_UNICAST;
1321 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1325 rtm.rtm_flags |= FIB_RULE_INVERT;
1327 if (rule->flags & IPRULE_SRC)
1328 rtm.rtm_src_len = rule->src_mask;
1330 if (rule->flags & IPRULE_DEST)
1331 rtm.rtm_dst_len = rule->dest_mask;
1333 if (rule->flags & IPRULE_TOS)
1334 rtm.rtm_tos = rule->tos;
1336 if (rule->flags & IPRULE_LOOKUP) {
1337 if (rule->lookup < 256)
1338 rtm.rtm_table = rule->lookup;
1341 if (rule->flags & IPRULE_ACTION)
1342 rtm.rtm_type = rule->action;
1343 else if (rule->flags & IPRULE_GOTO)
1344 rtm.rtm_type = FR_ACT_GOTO;
1345 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1346 rtm.rtm_type = FR_ACT_NOP;
1348 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1353 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1355 if (rule->flags & IPRULE_IN)
1356 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1358 if (rule->flags & IPRULE_OUT)
1359 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1361 if (rule->flags & IPRULE_SRC)
1362 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1364 if (rule->flags & IPRULE_DEST)
1365 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1367 if (rule->flags & IPRULE_PRIORITY)
1368 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1369 else if (cmd == RTM_NEWRULE)
1370 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1372 if (rule->flags & IPRULE_FWMARK)
1373 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1375 if (rule->flags & IPRULE_FWMASK)
1376 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1378 if (rule->flags & IPRULE_LOOKUP) {
1379 if (rule->lookup >= 256)
1380 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1383 if (rule->flags & IPRULE_GOTO)
1384 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1386 return system_rtnl_call(msg);
1389 int system_add_iprule(struct iprule *rule)
1391 return system_iprule(rule, RTM_NEWRULE);
1394 int system_del_iprule(struct iprule *rule)
1396 return system_iprule(rule, RTM_DELRULE);
1399 int system_flush_iprules(void)
1404 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1405 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1407 memset(&rule, 0, sizeof(rule));
1410 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1413 rule.lookup = RT_TABLE_LOCAL;
1414 rv |= system_iprule(&rule, RTM_NEWRULE);
1416 rule.priority = 32766;
1417 rule.lookup = RT_TABLE_MAIN;
1418 rv |= system_iprule(&rule, RTM_NEWRULE);
1420 rule.priority = 32767;
1421 rule.lookup = RT_TABLE_DEFAULT;
1422 rv |= system_iprule(&rule, RTM_NEWRULE);
1425 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1428 rule.lookup = RT_TABLE_LOCAL;
1429 rv |= system_iprule(&rule, RTM_NEWRULE);
1431 rule.priority = 32766;
1432 rule.lookup = RT_TABLE_MAIN;
1433 rv |= system_iprule(&rule, RTM_NEWRULE);
1438 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1443 if (!strcmp(action, "local"))
1445 else if (!strcmp(action, "nat"))
1447 else if (!strcmp(action, "broadcast"))
1449 else if (!strcmp(action, "anycast"))
1451 else if (!strcmp(action, "multicast"))
1453 else if (!strcmp(action, "prohibit"))
1455 else if (!strcmp(action, "unreachable"))
1456 n = RTN_UNREACHABLE;
1457 else if (!strcmp(action, "blackhole"))
1459 else if (!strcmp(action, "xresolve"))
1461 else if (!strcmp(action, "unicast"))
1463 else if (!strcmp(action, "throw"))
1465 else if (!strcmp(action, "failed_policy"))
1466 n = RTN_FAILED_POLICY;
1468 n = strtoul(action, &e, 0);
1469 if (!e || *e || e == action || n > 255)
1477 time_t system_get_rtime(void)
1482 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1485 if (gettimeofday(&tv, NULL) == 0)
1492 #define IP_DF 0x4000
1495 static int tunnel_ioctl(const char *name, int cmd, void *p)
1499 memset(&ifr, 0, sizeof(ifr));
1500 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1501 ifr.ifr_ifru.ifru_data = p;
1502 return ioctl(sock_ioctl, cmd, &ifr);
1505 int system_del_ip_tunnel(const char *name)
1507 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
1510 int system_update_ipv6_mtu(struct device *dev, int mtu)
1514 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
1517 int fd = open(buf, O_RDWR);
1518 ssize_t len = read(fd, buf, sizeof(buf) - 1);
1525 if (!mtu || ret <= mtu)
1528 lseek(fd, 0, SEEK_SET);
1529 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) <= 0)
1537 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
1539 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
1540 struct blob_attr *cur;
1544 system_del_ip_tunnel(name);
1546 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
1547 blob_data(attr), blob_len(attr));
1549 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
1551 str = blobmsg_data(cur);
1553 if ((cur = tb[TUNNEL_ATTR_DF]))
1554 set_df = blobmsg_get_bool(cur);
1556 unsigned int ttl = 0;
1557 if ((cur = tb[TUNNEL_ATTR_TTL])) {
1558 ttl = blobmsg_get_u32(cur);
1559 if (ttl > 255 || (!set_df && ttl))
1563 unsigned int link = 0;
1564 if ((cur = tb[TUNNEL_ATTR_LINK])) {
1565 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
1569 if (iface->l3_dev.dev)
1570 link = iface->l3_dev.dev->ifindex;
1573 if (!strcmp(str, "sit")) {
1574 struct ip_tunnel_parm p = {
1579 .frag_off = set_df ? htons(IP_DF) : 0,
1580 .protocol = IPPROTO_IPV6,
1585 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
1586 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
1589 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
1590 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
1593 strncpy(p.name, name, sizeof(p.name));
1594 if (tunnel_ioctl("sit0", SIOCADDTUNNEL, &p) < 0)
1598 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
1600 struct ip_tunnel_6rd p6;
1602 memset(&p6, 0, sizeof(p6));
1604 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
1605 &p6.prefix, &mask) || mask > 128)
1607 p6.prefixlen = mask;
1609 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
1610 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
1611 &p6.relay_prefix, &mask) || mask > 32)
1613 p6.relay_prefixlen = mask;
1616 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
1617 system_del_ip_tunnel(name);
1622 } else if (!strcmp(str, "ipip6")) {
1623 struct ip6_tnl_parm p = {
1625 .proto = IPPROTO_IPIP,
1626 .hop_limit = (ttl) ? ttl : 64,
1630 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
1631 inet_pton(AF_INET6, blobmsg_data(cur), &p.laddr) < 1)
1634 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
1635 inet_pton(AF_INET6, blobmsg_data(cur), &p.raddr) < 1)
1638 strncpy(p.name, name, sizeof(p.name));
1639 if (tunnel_ioctl("ip6tnl0", SIOCADDTUNNEL, &p) < 0)