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;
63 static int sock_ioctl = -1;
64 static struct nl_sock *sock_rtnl = NULL;
66 static int cb_rtnl_event(struct nl_msg *msg, void *arg);
67 static void handle_hotplug_event(struct uloop_fd *u, unsigned int events);
69 static char dev_buf[256];
72 handler_nl_event(struct uloop_fd *u, unsigned int events)
74 struct event_socket *ev = container_of(u, struct event_socket, uloop);
75 nl_recvmsgs_default(ev->sock);
78 static struct nl_sock *
79 create_socket(int protocol, int groups)
83 sock = nl_socket_alloc();
88 nl_join_groups(sock, groups);
90 if (nl_connect(sock, protocol))
97 create_raw_event_socket(struct event_socket *ev, int protocol, int groups,
100 ev->sock = create_socket(protocol, groups);
104 ev->uloop.fd = nl_socket_get_fd(ev->sock);
106 if (uloop_fd_add(&ev->uloop, ULOOP_READ))
113 create_event_socket(struct event_socket *ev, int protocol,
114 int (*cb)(struct nl_msg *msg, void *arg))
116 if (!create_raw_event_socket(ev, protocol, 0, handler_nl_event))
119 // Install the valid custom callback handler
120 nl_socket_modify_cb(ev->sock, NL_CB_VALID, NL_CB_CUSTOM, cb, NULL);
122 // Disable sequence number checking on event sockets
123 nl_socket_disable_seq_check(ev->sock);
125 // Increase rx buffer size to 65K on event sockets
126 if (nl_socket_set_buffer_size(ev->sock, 65535, 0))
132 int system_init(void)
134 static struct event_socket rtnl_event;
135 static struct event_socket hotplug_event;
137 sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0);
138 system_fd_set_cloexec(sock_ioctl);
140 // Prepare socket for routing / address control
141 sock_rtnl = create_socket(NETLINK_ROUTE, 0);
145 if (!create_event_socket(&rtnl_event, NETLINK_ROUTE, cb_rtnl_event))
148 if (!create_raw_event_socket(&hotplug_event, NETLINK_KOBJECT_UEVENT, 1,
149 handle_hotplug_event))
152 // Receive network link events form kernel
153 nl_socket_add_membership(rtnl_event.sock, RTNLGRP_LINK);
158 static void system_set_sysctl(const char *path, const char *val)
162 fd = open(path, O_WRONLY);
166 write(fd, val, strlen(val));
170 static void system_set_dev_sysctl(const char *path, const char *device, const char *val)
172 snprintf(dev_buf, sizeof(dev_buf), path, device);
173 system_set_sysctl(dev_buf, val);
176 static void system_set_disable_ipv6(struct device *dev, const char *val)
178 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val);
182 #define IFF_LOWER_UP 0x10000
185 // Evaluate netlink messages
186 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
188 struct nlmsghdr *nh = nlmsg_hdr(msg);
189 struct ifinfomsg *ifi = NLMSG_DATA(nh);
190 struct nlattr *nla[__IFLA_MAX];
192 if (nh->nlmsg_type != RTM_NEWLINK)
195 nlmsg_parse(nh, sizeof(*ifi), nla, __IFLA_MAX - 1, NULL);
196 if (!nla[IFLA_IFNAME])
199 struct device *dev = device_get(nla_data(nla[IFLA_IFNAME]), false);
203 device_set_ifindex(dev, ifi->ifi_index);
204 device_set_link(dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
211 handle_hotplug_msg(char *data, int size)
213 const char *subsystem = NULL, *interface = NULL;
214 char *cur, *end, *sep;
219 if (!strncmp(data, "add@", 4))
221 else if (!strncmp(data, "remove@", 7))
226 skip = strlen(data) + 1;
229 for (cur = data + skip; cur < end; cur += skip) {
230 skip = strlen(cur) + 1;
232 sep = strchr(cur, '=');
237 if (!strcmp(cur, "INTERFACE"))
239 else if (!strcmp(cur, "SUBSYSTEM")) {
241 if (strcmp(subsystem, "net") != 0)
244 if (subsystem && interface)
250 dev = device_get(interface, false);
254 if (dev->type != &simple_device_type)
257 if (add && system_if_force_external(dev->ifname))
260 device_set_present(dev, add);
264 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
266 struct event_socket *ev = container_of(u, struct event_socket, uloop);
267 struct sockaddr_nl nla;
268 unsigned char *buf = NULL;
271 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
273 handle_hotplug_msg((char *) buf, size);
279 static int system_rtnl_call(struct nl_msg *msg)
283 ret = nl_send_auto_complete(sock_rtnl, msg);
289 return nl_wait_for_ack(sock_rtnl);
292 int system_bridge_delbr(struct device *bridge)
294 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
297 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
301 memset(&ifr, 0, sizeof(ifr));
303 ifr.ifr_ifindex = dev->ifindex;
306 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
307 return ioctl(sock_ioctl, cmd, &ifr);
310 static bool system_is_bridge(const char *name, char *buf, int buflen)
314 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
315 if (stat(buf, &st) < 0)
321 static char *system_get_bridge(const char *name, char *buf, int buflen)
327 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
328 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
331 if (gl.gl_pathc == 0)
334 len = readlink(gl.gl_pathv[0], buf, buflen);
339 path = strrchr(buf, '/');
346 int system_bridge_addif(struct device *bridge, struct device *dev)
350 system_set_disable_ipv6(dev, "1");
351 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
352 if (oldbr && !strcmp(oldbr, bridge->ifname))
355 return system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
358 int system_bridge_delif(struct device *bridge, struct device *dev)
360 system_set_disable_ipv6(dev, "0");
361 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
364 static int system_if_resolve(struct device *dev)
367 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
368 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
369 return ifr.ifr_ifindex;
374 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
378 memset(&ifr, 0, sizeof(ifr));
379 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
380 ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
381 ifr.ifr_flags |= add;
382 ifr.ifr_flags &= ~rem;
383 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
395 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
397 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
399 return ifa->ifa_index == ifindex;
402 static bool check_route(struct nlmsghdr *hdr, int ifindex)
404 struct rtmsg *r = NLMSG_DATA(hdr);
405 struct nlattr *tb[__RTA_MAX];
407 if (r->rtm_protocol == RTPROT_KERNEL &&
408 r->rtm_family == AF_INET6)
411 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
415 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
418 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
423 static int cb_clear_event(struct nl_msg *msg, void *arg)
425 struct clear_data *clr = arg;
426 struct nlmsghdr *hdr = nlmsg_hdr(msg);
427 bool (*cb)(struct nlmsghdr *, int ifindex);
433 if (hdr->nlmsg_type != RTM_NEWADDR)
440 if (hdr->nlmsg_type != RTM_NEWROUTE)
447 if (hdr->nlmsg_type != RTM_NEWRULE)
456 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
459 if (type == RTM_DELRULE)
460 D(SYSTEM, "Remove a rule\n");
462 D(SYSTEM, "Remove %s from device %s\n",
463 type == RTM_DELADDR ? "an address" : "a route",
465 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
466 hdr = nlmsg_hdr(clr->msg);
467 hdr->nlmsg_type = type;
468 hdr->nlmsg_flags = NLM_F_REQUEST;
470 if (!nl_send_auto_complete(sock_rtnl, clr->msg))
471 nl_wait_for_ack(sock_rtnl);
477 cb_finish_event(struct nl_msg *msg, void *arg)
485 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
488 *pending = err->error;
493 system_if_clear_entries(struct device *dev, int type, int af)
495 struct clear_data clr;
496 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
499 .rtm_flags = RTM_F_CLONED,
501 int flags = NLM_F_DUMP;
510 clr.size = sizeof(struct rtgenmsg);
513 clr.size = sizeof(struct rtmsg);
522 clr.msg = nlmsg_alloc_simple(type, flags);
526 nlmsg_append(clr.msg, &rtm, clr.size, 0);
527 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
528 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
529 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
531 nl_send_auto_complete(sock_rtnl, clr.msg);
533 nl_recvmsgs(sock_rtnl, cb);
541 * Clear bridge (membership) state and bring down device
543 void system_if_clear_state(struct device *dev)
545 static char buf[256];
551 device_set_ifindex(dev, system_if_resolve(dev));
555 system_if_flags(dev->ifname, 0, IFF_UP);
557 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
558 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
559 system_bridge_delbr(dev);
563 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
565 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
566 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
569 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
570 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
571 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
572 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
573 system_set_disable_ipv6(dev, "0");
576 static inline unsigned long
577 sec_to_jiffies(int val)
579 return (unsigned long) val * 100;
582 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
584 unsigned long args[4] = {};
586 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
589 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
590 args[1] = !!cfg->stp;
591 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
593 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
594 args[1] = sec_to_jiffies(cfg->forward_delay);
595 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
597 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
598 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
600 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
601 args[1] = cfg->priority;
602 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
604 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
605 args[0] = BRCTL_SET_AGEING_TIME;
606 args[1] = sec_to_jiffies(cfg->ageing_time);
607 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
610 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
611 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
612 args[1] = sec_to_jiffies(cfg->hello_time);
613 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
616 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
617 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
618 args[1] = sec_to_jiffies(cfg->max_age);
619 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
625 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
628 struct nlattr *linkinfo, *data;
629 struct ifinfomsg iim = { .ifi_family = AF_INET };
630 int ifindex = system_if_resolve(dev);
632 static const struct {
634 enum macvlan_mode val;
636 { "private", MACVLAN_MODE_PRIVATE },
637 { "vepa", MACVLAN_MODE_VEPA },
638 { "bridge", MACVLAN_MODE_BRIDGE },
639 { "passthru", MACVLAN_MODE_PASSTHRU },
645 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
650 nlmsg_append(msg, &iim, sizeof(iim), 0);
652 if (cfg->flags & MACVLAN_OPT_MACADDR)
653 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
654 nla_put(msg, IFLA_IFNAME, IFNAMSIZ, macvlan->ifname);
655 nla_put_u32(msg, IFLA_LINK, ifindex);
657 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
658 goto nla_put_failure;
660 nla_put(msg, IFLA_INFO_KIND, strlen("macvlan"), "macvlan");
662 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
663 goto nla_put_failure;
666 for (i = 0; i < ARRAY_SIZE(modes); i++) {
667 if (strcmp(cfg->mode, modes[i].name) != 0)
670 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
675 nla_nest_end(msg, data);
676 nla_nest_end(msg, linkinfo);
678 rv = system_rtnl_call(msg);
680 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
689 int system_macvlan_del(struct device *macvlan)
692 struct ifinfomsg iim;
694 iim.ifi_family = AF_INET;
697 msg = nlmsg_alloc_simple(RTM_DELLINK, 0);
702 nlmsg_append(msg, &iim, sizeof(iim), 0);
704 nla_put(msg, IFLA_INFO_KIND, strlen("macvlan"), "macvlan");
705 nla_put(msg, IFLA_IFNAME, sizeof(macvlan->ifname), macvlan->ifname);
707 system_rtnl_call(msg);
712 static int system_vlan(struct device *dev, int id)
714 struct vlan_ioctl_args ifr = {
715 .cmd = SET_VLAN_NAME_TYPE_CMD,
716 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
719 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
722 ifr.cmd = DEL_VLAN_CMD;
725 ifr.cmd = ADD_VLAN_CMD;
728 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
729 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
732 int system_vlan_add(struct device *dev, int id)
734 return system_vlan(dev, id);
737 int system_vlan_del(struct device *dev)
739 return system_vlan(dev, -1);
743 system_if_get_settings(struct device *dev, struct device_settings *s)
747 memset(&ifr, 0, sizeof(ifr));
748 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
750 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
751 s->mtu = ifr.ifr_mtu;
752 s->flags |= DEV_OPT_MTU;
755 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
756 s->txqueuelen = ifr.ifr_qlen;
757 s->flags |= DEV_OPT_TXQUEUELEN;
760 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
761 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
762 s->flags |= DEV_OPT_MACADDR;
767 system_if_apply_settings(struct device *dev, struct device_settings *s)
771 memset(&ifr, 0, sizeof(ifr));
772 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
773 if (s->flags & DEV_OPT_MTU) {
774 ifr.ifr_mtu = s->mtu;
775 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
776 s->flags &= ~DEV_OPT_MTU;
778 if (s->flags & DEV_OPT_TXQUEUELEN) {
779 ifr.ifr_qlen = s->txqueuelen;
780 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
781 s->flags &= ~DEV_OPT_TXQUEUELEN;
783 if ((s->flags & DEV_OPT_MACADDR) && !dev->external) {
784 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
785 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
786 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
787 s->flags &= ~DEV_OPT_MACADDR;
791 int system_if_up(struct device *dev)
793 system_if_get_settings(dev, &dev->orig_settings);
794 system_if_apply_settings(dev, &dev->settings);
795 device_set_ifindex(dev, system_if_resolve(dev));
796 return system_if_flags(dev->ifname, IFF_UP, 0);
799 int system_if_down(struct device *dev)
801 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
802 dev->orig_settings.flags &= dev->settings.flags;
803 system_if_apply_settings(dev, &dev->orig_settings);
807 struct if_check_data {
813 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
815 struct nlmsghdr *nh = nlmsg_hdr(msg);
816 struct ifinfomsg *ifi = NLMSG_DATA(nh);
817 struct if_check_data *chk = (struct if_check_data *)arg;
819 if (nh->nlmsg_type != RTM_NEWLINK)
822 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
823 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
828 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
830 struct if_check_data *chk = (struct if_check_data *)arg;
835 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
837 struct if_check_data *chk = (struct if_check_data *)arg;
839 device_set_present(chk->dev, false);
840 device_set_link(chk->dev, false);
841 chk->pending = err->error;
846 int system_if_check(struct device *dev)
848 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
850 struct ifinfomsg ifi = {
851 .ifi_family = AF_UNSPEC,
854 struct if_check_data chk = {
860 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
861 if (!msg || nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
862 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
865 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
866 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
867 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
869 nl_send_auto_complete(sock_rtnl, msg);
870 while (chk.pending > 0)
871 nl_recvmsgs(sock_rtnl, cb);
882 system_if_get_parent(struct device *dev)
884 char buf[64], *devname;
885 int ifindex, iflink, len;
888 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
893 len = fread(buf, 1, sizeof(buf) - 1, f);
900 iflink = strtoul(buf, NULL, 0);
901 ifindex = system_if_resolve(dev);
902 if (!iflink || iflink == ifindex)
905 devname = if_indextoname(iflink, buf);
909 return device_get(devname, true);
913 read_string_file(int dir_fd, const char *file, char *buf, int len)
919 fd = openat(dir_fd, file, O_RDONLY);
924 len = read(fd, buf, len - 1);
928 } else if (len > 0) {
931 c = strchr(buf, '\n');
944 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
949 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
951 *val = strtoull(buf, NULL, 0);
956 /* Assume advertised flags == supported flags */
957 static const struct {
960 } ethtool_link_modes[] = {
961 { ADVERTISED_10baseT_Half, "10H" },
962 { ADVERTISED_10baseT_Full, "10F" },
963 { ADVERTISED_100baseT_Half, "100H" },
964 { ADVERTISED_100baseT_Full, "100F" },
965 { ADVERTISED_1000baseT_Half, "1000H" },
966 { ADVERTISED_1000baseT_Full, "1000F" },
969 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
972 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
973 if (mask & ethtool_link_modes[i].mask)
974 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
979 system_if_force_external(const char *ifname)
984 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
985 return stat(buf, &s) == 0;
989 system_if_dump_info(struct device *dev, struct blob_buf *b)
991 struct ethtool_cmd ecmd;
997 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
998 dir_fd = open(buf, O_DIRECTORY);
1000 memset(&ecmd, 0, sizeof(ecmd));
1001 memset(&ifr, 0, sizeof(ifr));
1002 strcpy(ifr.ifr_name, dev->ifname);
1003 ifr.ifr_data = (caddr_t) &ecmd;
1004 ecmd.cmd = ETHTOOL_GSET;
1006 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1007 c = blobmsg_open_array(b, "link-advertising");
1008 system_add_link_modes(b, ecmd.advertising);
1009 blobmsg_close_array(b, c);
1011 c = blobmsg_open_array(b, "link-supported");
1012 system_add_link_modes(b, ecmd.supported);
1013 blobmsg_close_array(b, c);
1015 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1016 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1017 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1018 blobmsg_add_string_buffer(b);
1026 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1028 const char *const counters[] = {
1029 "collisions", "rx_frame_errors", "tx_compressed",
1030 "multicast", "rx_length_errors", "tx_dropped",
1031 "rx_bytes", "rx_missed_errors", "tx_errors",
1032 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1033 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1034 "rx_dropped", "tx_aborted_errors", "tx_packets",
1035 "rx_errors", "tx_bytes", "tx_window_errors",
1036 "rx_fifo_errors", "tx_carrier_errors",
1043 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1044 stats_dir = open(buf, O_DIRECTORY);
1048 for (i = 0; i < ARRAY_SIZE(counters); i++)
1049 if (read_uint64_file(stats_dir, counters[i], &val))
1050 blobmsg_add_u64(b, counters[i], val);
1056 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1058 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1059 int alen = v4 ? 4 : 16;
1060 unsigned int flags = 0;
1061 struct ifaddrmsg ifa = {
1062 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1063 .ifa_prefixlen = addr->mask,
1064 .ifa_index = dev->ifindex,
1068 if (cmd == RTM_NEWADDR)
1069 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1071 msg = nlmsg_alloc_simple(cmd, flags);
1075 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1076 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1078 if (addr->broadcast)
1079 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1080 if (addr->point_to_point)
1081 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1083 time_t now = system_get_rtime();
1084 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1086 if (addr->preferred_until) {
1087 int64_t preferred = addr->preferred_until - now;
1090 else if (preferred > UINT32_MAX)
1091 preferred = UINT32_MAX;
1093 cinfo.ifa_prefered = preferred;
1096 if (addr->valid_until) {
1097 int64_t valid = addr->valid_until - now;
1100 else if (valid > UINT32_MAX)
1103 cinfo.ifa_valid = valid;
1106 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1109 return system_rtnl_call(msg);
1112 int system_add_address(struct device *dev, struct device_addr *addr)
1114 return system_addr(dev, addr, RTM_NEWADDR);
1117 int system_del_address(struct device *dev, struct device_addr *addr)
1119 return system_addr(dev, addr, RTM_DELADDR);
1122 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1124 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1126 unsigned int flags = 0;
1129 have_gw = !!route->nexthop.in.s_addr;
1131 have_gw = route->nexthop.in6.s6_addr32[0] ||
1132 route->nexthop.in6.s6_addr32[1] ||
1133 route->nexthop.in6.s6_addr32[2] ||
1134 route->nexthop.in6.s6_addr32[3];
1136 unsigned char scope = (cmd == RTM_DELROUTE) ? RT_SCOPE_NOWHERE :
1137 (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1139 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1140 ? route->table : RT_TABLE_MAIN;
1142 struct rtmsg rtm = {
1143 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1144 .rtm_dst_len = route->mask,
1145 .rtm_src_len = route->sourcemask,
1146 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1147 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
1149 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1153 if (cmd == RTM_NEWROUTE) {
1154 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1156 if (!dev) { // Add null-route
1157 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1158 rtm.rtm_type = RTN_UNREACHABLE;
1162 msg = nlmsg_alloc_simple(cmd, flags);
1166 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1169 nla_put(msg, RTA_DST, alen, &route->addr);
1171 if (route->sourcemask)
1172 nla_put(msg, RTA_SRC, alen, &route->source);
1174 if (route->metric > 0)
1175 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1178 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1181 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1184 nla_put_u32(msg, RTA_TABLE, table);
1186 return system_rtnl_call(msg);
1189 int system_add_route(struct device *dev, struct device_route *route)
1191 return system_rt(dev, route, RTM_NEWROUTE);
1194 int system_del_route(struct device *dev, struct device_route *route)
1196 return system_rt(dev, route, RTM_DELROUTE);
1199 int system_flush_routes(void)
1201 const char *names[] = {
1202 "/proc/sys/net/ipv4/route/flush",
1203 "/proc/sys/net/ipv6/route/flush"
1207 for (i = 0; i < ARRAY_SIZE(names); i++) {
1208 fd = open(names[i], O_WRONLY);
1218 bool system_resolve_rt_table(const char *name, unsigned int *id)
1222 unsigned int n, table = RT_TABLE_UNSPEC;
1224 /* first try to parse table as number */
1225 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1228 /* handle well known aliases */
1229 else if (!strcmp(name, "default"))
1230 table = RT_TABLE_DEFAULT;
1231 else if (!strcmp(name, "main"))
1232 table = RT_TABLE_MAIN;
1233 else if (!strcmp(name, "local"))
1234 table = RT_TABLE_LOCAL;
1236 /* try to look up name in /etc/iproute2/rt_tables */
1237 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1239 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1241 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1244 n = strtoul(e, NULL, 10);
1245 e = strtok(NULL, " \t\n");
1247 if (e && !strcmp(e, name))
1257 if (table == RT_TABLE_UNSPEC)
1260 /* do not consider main table special */
1261 if (table == RT_TABLE_MAIN)
1262 table = RT_TABLE_UNSPEC;
1268 static int system_iprule(struct iprule *rule, int cmd)
1270 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1273 struct rtmsg rtm = {
1274 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1275 .rtm_protocol = RTPROT_STATIC,
1276 .rtm_scope = RT_SCOPE_UNIVERSE,
1277 .rtm_table = RT_TABLE_UNSPEC,
1278 .rtm_type = RTN_UNSPEC,
1282 if (cmd == RTM_NEWRULE) {
1283 rtm.rtm_type = RTN_UNICAST;
1284 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1288 rtm.rtm_flags |= FIB_RULE_INVERT;
1290 if (rule->flags & IPRULE_SRC)
1291 rtm.rtm_src_len = rule->src_mask;
1293 if (rule->flags & IPRULE_DEST)
1294 rtm.rtm_dst_len = rule->dest_mask;
1296 if (rule->flags & IPRULE_TOS)
1297 rtm.rtm_tos = rule->tos;
1299 if (rule->flags & IPRULE_LOOKUP) {
1300 if (rule->lookup < 256)
1301 rtm.rtm_table = rule->lookup;
1304 if (rule->flags & IPRULE_ACTION)
1305 rtm.rtm_type = rule->action;
1306 else if (rule->flags & IPRULE_GOTO)
1307 rtm.rtm_type = FR_ACT_GOTO;
1308 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1309 rtm.rtm_type = FR_ACT_NOP;
1311 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1316 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1318 if (rule->flags & IPRULE_IN)
1319 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1321 if (rule->flags & IPRULE_OUT)
1322 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1324 if (rule->flags & IPRULE_SRC)
1325 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1327 if (rule->flags & IPRULE_DEST)
1328 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1330 if (rule->flags & IPRULE_PRIORITY)
1331 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1332 else if (cmd == RTM_NEWRULE)
1333 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1335 if (rule->flags & IPRULE_FWMARK)
1336 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1338 if (rule->flags & IPRULE_FWMASK)
1339 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1341 if (rule->flags & IPRULE_LOOKUP) {
1342 if (rule->lookup >= 256)
1343 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1346 if (rule->flags & IPRULE_GOTO)
1347 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1349 return system_rtnl_call(msg);
1352 int system_add_iprule(struct iprule *rule)
1354 return system_iprule(rule, RTM_NEWRULE);
1357 int system_del_iprule(struct iprule *rule)
1359 return system_iprule(rule, RTM_DELRULE);
1362 int system_flush_iprules(void)
1367 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1368 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1370 memset(&rule, 0, sizeof(rule));
1373 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1376 rule.lookup = RT_TABLE_LOCAL;
1377 rv |= system_iprule(&rule, RTM_NEWRULE);
1379 rule.priority = 32766;
1380 rule.lookup = RT_TABLE_MAIN;
1381 rv |= system_iprule(&rule, RTM_NEWRULE);
1383 rule.priority = 32767;
1384 rule.lookup = RT_TABLE_DEFAULT;
1385 rv |= system_iprule(&rule, RTM_NEWRULE);
1388 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1391 rule.lookup = RT_TABLE_LOCAL;
1392 rv |= system_iprule(&rule, RTM_NEWRULE);
1394 rule.priority = 32766;
1395 rule.lookup = RT_TABLE_MAIN;
1396 rv |= system_iprule(&rule, RTM_NEWRULE);
1401 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1406 if (!strcmp(action, "local"))
1408 else if (!strcmp(action, "nat"))
1410 else if (!strcmp(action, "broadcast"))
1412 else if (!strcmp(action, "anycast"))
1414 else if (!strcmp(action, "multicast"))
1416 else if (!strcmp(action, "prohibit"))
1418 else if (!strcmp(action, "unreachable"))
1419 n = RTN_UNREACHABLE;
1420 else if (!strcmp(action, "blackhole"))
1422 else if (!strcmp(action, "xresolve"))
1424 else if (!strcmp(action, "unicast"))
1426 else if (!strcmp(action, "throw"))
1428 else if (!strcmp(action, "failed_policy"))
1429 n = RTN_FAILED_POLICY;
1431 n = strtoul(action, &e, 0);
1432 if (!e || *e || e == action || n > 255)
1440 time_t system_get_rtime(void)
1445 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1448 if (gettimeofday(&tv, NULL) == 0)
1455 #define IP_DF 0x4000
1458 static int tunnel_ioctl(const char *name, int cmd, void *p)
1462 memset(&ifr, 0, sizeof(ifr));
1463 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1464 ifr.ifr_ifru.ifru_data = p;
1465 return ioctl(sock_ioctl, cmd, &ifr);
1468 int system_del_ip_tunnel(const char *name)
1470 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
1473 int system_update_ipv6_mtu(struct device *dev, int mtu)
1477 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
1480 int fd = open(buf, O_RDWR);
1481 ssize_t len = read(fd, buf, sizeof(buf) - 1);
1488 if (!mtu || ret <= mtu)
1491 lseek(fd, 0, SEEK_SET);
1492 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) <= 0)
1500 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
1502 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
1503 struct blob_attr *cur;
1507 system_del_ip_tunnel(name);
1509 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
1510 blob_data(attr), blob_len(attr));
1512 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
1514 str = blobmsg_data(cur);
1516 if ((cur = tb[TUNNEL_ATTR_DF]))
1517 set_df = blobmsg_get_bool(cur);
1519 unsigned int ttl = 0;
1520 if ((cur = tb[TUNNEL_ATTR_TTL])) {
1521 ttl = blobmsg_get_u32(cur);
1522 if (ttl > 255 || (!set_df && ttl))
1526 unsigned int link = 0;
1527 if ((cur = tb[TUNNEL_ATTR_LINK])) {
1528 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
1532 if (iface->l3_dev.dev)
1533 link = iface->l3_dev.dev->ifindex;
1536 if (!strcmp(str, "sit")) {
1537 struct ip_tunnel_parm p = {
1542 .frag_off = set_df ? htons(IP_DF) : 0,
1543 .protocol = IPPROTO_IPV6,
1548 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
1549 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
1552 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
1553 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
1556 strncpy(p.name, name, sizeof(p.name));
1557 if (tunnel_ioctl("sit0", SIOCADDTUNNEL, &p) < 0)
1561 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
1563 struct ip_tunnel_6rd p6;
1565 memset(&p6, 0, sizeof(p6));
1567 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
1568 &p6.prefix, &mask) || mask > 128)
1570 p6.prefixlen = mask;
1572 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
1573 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
1574 &p6.relay_prefix, &mask) || mask > 32)
1576 p6.relay_prefixlen = mask;
1579 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
1580 system_del_ip_tunnel(name);
1585 } else if (!strcmp(str, "ipip6")) {
1586 struct ip6_tnl_parm p = {
1588 .proto = IPPROTO_IPIP,
1589 .hop_limit = (ttl) ? ttl : 64,
1593 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
1594 inet_pton(AF_INET6, blobmsg_data(cur), &p.laddr) < 1)
1597 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
1598 inet_pton(AF_INET6, blobmsg_data(cur), &p.raddr) < 1)
1601 strncpy(p.name, name, sizeof(p.name));
1602 if (tunnel_ioctl("ip6tnl0", SIOCADDTUNNEL, &p) < 0)