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);
76 nl_recvmsgs(ev->sock, ev->cb);
79 static struct nl_sock *
80 create_socket(int protocol, int groups)
84 sock = nl_socket_alloc();
89 nl_join_groups(sock, groups);
91 if (nl_connect(sock, protocol))
98 create_raw_event_socket(struct event_socket *ev, int protocol, int groups,
101 ev->sock = create_socket(protocol, groups);
105 ev->uloop.fd = nl_socket_get_fd(ev->sock);
107 uloop_fd_add(&ev->uloop, ULOOP_READ | ULOOP_EDGE_TRIGGER);
112 create_event_socket(struct event_socket *ev, int protocol,
113 int (*cb)(struct nl_msg *msg, void *arg))
115 // Prepare socket for link events
116 ev->cb = nl_cb_alloc(NL_CB_DEFAULT);
120 nl_cb_set(ev->cb, NL_CB_VALID, NL_CB_CUSTOM, cb, NULL);
122 return create_raw_event_socket(ev, protocol, 0, handler_nl_event);
125 int system_init(void)
127 static struct event_socket rtnl_event;
128 static struct event_socket hotplug_event;
130 sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0);
131 fcntl(sock_ioctl, F_SETFD, fcntl(sock_ioctl, F_GETFD) | FD_CLOEXEC);
133 // Prepare socket for routing / address control
134 sock_rtnl = create_socket(NETLINK_ROUTE, 0);
138 if (!create_event_socket(&rtnl_event, NETLINK_ROUTE, cb_rtnl_event))
141 if (!create_raw_event_socket(&hotplug_event, NETLINK_KOBJECT_UEVENT, 1,
142 handle_hotplug_event))
145 // Receive network link events form kernel
146 nl_socket_add_membership(rtnl_event.sock, RTNLGRP_LINK);
151 static void system_set_sysctl(const char *path, const char *val)
155 fd = open(path, O_WRONLY);
159 if (write(fd, val, strlen(val))) {}
163 static void system_set_dev_sysctl(const char *path, const char *device, const char *val)
165 snprintf(dev_buf, sizeof(dev_buf), path, device);
166 system_set_sysctl(dev_buf, val);
169 static void system_set_disable_ipv6(struct device *dev, const char *val)
171 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val);
174 // Evaluate netlink messages
175 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
177 struct nlmsghdr *nh = nlmsg_hdr(msg);
178 struct ifinfomsg *ifi = NLMSG_DATA(nh);
179 struct nlattr *nla[__IFLA_MAX];
181 if (nh->nlmsg_type != RTM_DELLINK && nh->nlmsg_type != RTM_NEWLINK)
184 nlmsg_parse(nh, sizeof(*ifi), nla, __IFLA_MAX - 1, NULL);
185 if (!nla[IFLA_IFNAME])
188 struct device *dev = device_get(RTA_DATA(nla[IFLA_IFNAME]), false);
192 dev->ifindex = ifi->ifi_index;
193 /* TODO: parse link status */
200 handle_hotplug_msg(char *data, int size)
202 const char *subsystem = NULL, *interface = NULL;
203 char *cur, *end, *sep;
208 if (!strncmp(data, "add@", 4))
210 else if (!strncmp(data, "remove@", 7))
215 skip = strlen(data) + 1;
218 for (cur = data + skip; cur < end; cur += skip) {
219 skip = strlen(cur) + 1;
221 sep = strchr(cur, '=');
226 if (!strcmp(cur, "INTERFACE"))
228 else if (!strcmp(cur, "SUBSYSTEM")) {
230 if (strcmp(subsystem, "net") != 0)
233 if (subsystem && interface)
239 dev = device_get(interface, false);
243 if (dev->type != &simple_device_type)
246 if (add && system_if_force_external(dev->ifname))
249 device_set_present(dev, add);
253 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
255 struct event_socket *ev = container_of(u, struct event_socket, uloop);
256 struct sockaddr_nl nla;
257 unsigned char *buf = NULL;
260 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
262 handle_hotplug_msg((char *) buf, size);
268 static int system_rtnl_call(struct nl_msg *msg)
272 ret = nl_send_auto_complete(sock_rtnl, msg);
278 return nl_wait_for_ack(sock_rtnl);
281 int system_bridge_delbr(struct device *bridge)
283 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
286 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
290 memset(&ifr, 0, sizeof(ifr));
292 ifr.ifr_ifindex = dev->ifindex;
295 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
296 return ioctl(sock_ioctl, cmd, &ifr);
299 static bool system_is_bridge(const char *name, char *buf, int buflen)
303 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
304 if (stat(buf, &st) < 0)
310 static char *system_get_bridge(const char *name, char *buf, int buflen)
316 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
317 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
320 if (gl.gl_pathc == 0)
323 len = readlink(gl.gl_pathv[0], buf, buflen);
328 path = strrchr(buf, '/');
335 int system_bridge_addif(struct device *bridge, struct device *dev)
339 system_set_disable_ipv6(dev, "1");
340 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
341 if (oldbr && !strcmp(oldbr, bridge->ifname))
344 return system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
347 int system_bridge_delif(struct device *bridge, struct device *dev)
349 system_set_disable_ipv6(dev, "0");
350 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
353 static int system_if_resolve(struct device *dev)
356 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
357 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
358 return ifr.ifr_ifindex;
363 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
367 memset(&ifr, 0, sizeof(ifr));
368 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
369 ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
370 ifr.ifr_flags |= add;
371 ifr.ifr_flags &= ~rem;
372 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
384 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
386 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
388 return ifa->ifa_index == ifindex;
391 static bool check_route(struct nlmsghdr *hdr, int ifindex)
393 struct rtmsg *r = NLMSG_DATA(hdr);
394 struct nlattr *tb[__RTA_MAX];
396 if (r->rtm_protocol == RTPROT_KERNEL &&
397 r->rtm_family == AF_INET6)
400 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
404 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
407 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
412 static int cb_clear_event(struct nl_msg *msg, void *arg)
414 struct clear_data *clr = arg;
415 struct nlmsghdr *hdr = nlmsg_hdr(msg);
416 bool (*cb)(struct nlmsghdr *, int ifindex);
422 if (hdr->nlmsg_type != RTM_NEWADDR)
429 if (hdr->nlmsg_type != RTM_NEWROUTE)
436 if (hdr->nlmsg_type != RTM_NEWRULE)
445 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
448 if (type == RTM_DELRULE)
449 D(SYSTEM, "Remove a rule\n");
451 D(SYSTEM, "Remove %s from device %s\n",
452 type == RTM_DELADDR ? "an address" : "a route",
454 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
455 hdr = nlmsg_hdr(clr->msg);
456 hdr->nlmsg_type = type;
457 hdr->nlmsg_flags = NLM_F_REQUEST;
459 nl_socket_disable_auto_ack(sock_rtnl);
460 nl_send_auto_complete(sock_rtnl, clr->msg);
461 nl_socket_enable_auto_ack(sock_rtnl);
467 cb_finish_event(struct nl_msg *msg, void *arg)
475 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
478 *pending = err->error;
483 system_if_clear_entries(struct device *dev, int type, int af)
485 struct clear_data clr;
486 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
489 .rtm_flags = RTM_F_CLONED,
491 int flags = NLM_F_DUMP;
500 clr.size = sizeof(struct rtgenmsg);
503 clr.size = sizeof(struct rtmsg);
512 clr.msg = nlmsg_alloc_simple(type, flags);
516 nlmsg_append(clr.msg, &rtm, clr.size, 0);
517 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
518 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
519 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
521 nl_send_auto_complete(sock_rtnl, clr.msg);
523 nl_recvmsgs(sock_rtnl, cb);
531 * Clear bridge (membership) state and bring down device
533 void system_if_clear_state(struct device *dev)
535 static char buf[256];
541 dev->ifindex = system_if_resolve(dev);
545 system_if_flags(dev->ifname, 0, IFF_UP);
547 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
548 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
549 system_bridge_delbr(dev);
553 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
555 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
556 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
559 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
560 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
561 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
562 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
563 system_set_disable_ipv6(dev, "0");
566 static inline unsigned long
567 sec_to_jiffies(int val)
569 return (unsigned long) val * 100;
572 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
574 unsigned long args[4] = {};
576 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
579 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
580 args[1] = !!cfg->stp;
581 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
583 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
584 args[1] = sec_to_jiffies(cfg->forward_delay);
585 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
587 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
588 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
590 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
591 args[1] = cfg->priority;
592 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
594 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
595 args[0] = BRCTL_SET_AGEING_TIME;
596 args[1] = sec_to_jiffies(cfg->ageing_time);
597 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
600 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
601 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
602 args[1] = sec_to_jiffies(cfg->hello_time);
603 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
606 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
607 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
608 args[1] = sec_to_jiffies(cfg->max_age);
609 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
615 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
618 struct nlattr *linkinfo, *data;
619 struct ifinfomsg iim = { .ifi_family = AF_INET };
620 int ifindex = system_if_resolve(dev);
622 static const struct {
624 enum macvlan_mode val;
626 { "private", MACVLAN_MODE_PRIVATE },
627 { "vepa", MACVLAN_MODE_VEPA },
628 { "bridge", MACVLAN_MODE_BRIDGE },
629 { "passthru", MACVLAN_MODE_PASSTHRU },
635 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
640 nlmsg_append(msg, &iim, sizeof(iim), 0);
642 if (cfg->flags & MACVLAN_OPT_MACADDR)
643 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
644 nla_put(msg, IFLA_IFNAME, IFNAMSIZ, macvlan->ifname);
645 nla_put_u32(msg, IFLA_LINK, ifindex);
647 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
648 goto nla_put_failure;
650 nla_put(msg, IFLA_INFO_KIND, strlen("macvlan"), "macvlan");
652 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
653 goto nla_put_failure;
656 for (i = 0; i < ARRAY_SIZE(modes); i++) {
657 if (strcmp(cfg->mode, modes[i].name) != 0)
660 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
665 nla_nest_end(msg, data);
666 nla_nest_end(msg, linkinfo);
668 rv = system_rtnl_call(msg);
670 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
679 int system_macvlan_del(struct device *macvlan)
682 struct ifinfomsg iim;
684 iim.ifi_family = AF_INET;
687 msg = nlmsg_alloc_simple(RTM_DELLINK, 0);
692 nlmsg_append(msg, &iim, sizeof(iim), 0);
694 nla_put(msg, IFLA_INFO_KIND, strlen("macvlan"), "macvlan");
695 nla_put(msg, IFLA_IFNAME, sizeof(macvlan->ifname), macvlan->ifname);
697 system_rtnl_call(msg);
702 static int system_vlan(struct device *dev, int id)
704 struct vlan_ioctl_args ifr = {
705 .cmd = SET_VLAN_NAME_TYPE_CMD,
706 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
709 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
712 ifr.cmd = DEL_VLAN_CMD;
715 ifr.cmd = ADD_VLAN_CMD;
718 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
719 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
722 int system_vlan_add(struct device *dev, int id)
724 return system_vlan(dev, id);
727 int system_vlan_del(struct device *dev)
729 return system_vlan(dev, -1);
733 system_if_get_settings(struct device *dev, struct device_settings *s)
737 memset(&ifr, 0, sizeof(ifr));
738 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
740 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
741 s->mtu = ifr.ifr_mtu;
742 s->flags |= DEV_OPT_MTU;
745 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
746 s->txqueuelen = ifr.ifr_qlen;
747 s->flags |= DEV_OPT_TXQUEUELEN;
750 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
751 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
752 s->flags |= DEV_OPT_MACADDR;
757 system_if_apply_settings(struct device *dev, struct device_settings *s)
761 memset(&ifr, 0, sizeof(ifr));
762 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
763 if (s->flags & DEV_OPT_MTU) {
764 ifr.ifr_mtu = s->mtu;
765 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
766 s->flags &= ~DEV_OPT_MTU;
768 if (s->flags & DEV_OPT_TXQUEUELEN) {
769 ifr.ifr_qlen = s->txqueuelen;
770 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
771 s->flags &= ~DEV_OPT_TXQUEUELEN;
773 if ((s->flags & DEV_OPT_MACADDR) && !dev->external) {
774 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
775 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
776 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
777 s->flags &= ~DEV_OPT_MACADDR;
781 int system_if_up(struct device *dev)
783 system_if_get_settings(dev, &dev->orig_settings);
784 system_if_apply_settings(dev, &dev->settings);
785 dev->ifindex = system_if_resolve(dev);
786 return system_if_flags(dev->ifname, IFF_UP, 0);
789 int system_if_down(struct device *dev)
791 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
792 dev->orig_settings.flags &= dev->settings.flags;
793 system_if_apply_settings(dev, &dev->orig_settings);
797 int system_if_check(struct device *dev)
799 device_set_present(dev, (system_if_resolve(dev) > 0));
804 system_if_get_parent(struct device *dev)
806 char buf[64], *devname;
807 int ifindex, iflink, len;
810 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
815 len = fread(buf, 1, sizeof(buf) - 1, f);
822 iflink = strtoul(buf, NULL, 0);
823 ifindex = system_if_resolve(dev);
824 if (!iflink || iflink == ifindex)
827 devname = if_indextoname(iflink, buf);
831 return device_get(devname, true);
835 read_string_file(int dir_fd, const char *file, char *buf, int len)
841 fd = openat(dir_fd, file, O_RDONLY);
846 len = read(fd, buf, len - 1);
850 } else if (len > 0) {
853 c = strchr(buf, '\n');
866 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
871 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
873 *val = strtoull(buf, NULL, 0);
878 /* Assume advertised flags == supported flags */
879 static const struct {
882 } ethtool_link_modes[] = {
883 { ADVERTISED_10baseT_Half, "10H" },
884 { ADVERTISED_10baseT_Full, "10F" },
885 { ADVERTISED_100baseT_Half, "100H" },
886 { ADVERTISED_100baseT_Full, "100F" },
887 { ADVERTISED_1000baseT_Half, "1000H" },
888 { ADVERTISED_1000baseT_Full, "1000F" },
891 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
894 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
895 if (mask & ethtool_link_modes[i].mask)
896 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
901 system_if_force_external(const char *ifname)
906 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
907 return stat(buf, &s) == 0;
911 system_if_dump_info(struct device *dev, struct blob_buf *b)
913 struct ethtool_cmd ecmd;
920 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
921 dir_fd = open(buf, O_DIRECTORY);
923 if (read_uint64_file(dir_fd, "carrier", &val))
924 blobmsg_add_u8(b, "link", !!val);
926 memset(&ecmd, 0, sizeof(ecmd));
927 memset(&ifr, 0, sizeof(ifr));
928 strcpy(ifr.ifr_name, dev->ifname);
929 ifr.ifr_data = (caddr_t) &ecmd;
930 ecmd.cmd = ETHTOOL_GSET;
932 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
933 c = blobmsg_open_array(b, "link-advertising");
934 system_add_link_modes(b, ecmd.advertising);
935 blobmsg_close_array(b, c);
937 c = blobmsg_open_array(b, "link-supported");
938 system_add_link_modes(b, ecmd.supported);
939 blobmsg_close_array(b, c);
941 s = blobmsg_alloc_string_buffer(b, "speed", 8);
942 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
943 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
944 blobmsg_add_string_buffer(b);
952 system_if_dump_stats(struct device *dev, struct blob_buf *b)
954 const char *const counters[] = {
955 "collisions", "rx_frame_errors", "tx_compressed",
956 "multicast", "rx_length_errors", "tx_dropped",
957 "rx_bytes", "rx_missed_errors", "tx_errors",
958 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
959 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
960 "rx_dropped", "tx_aborted_errors", "tx_packets",
961 "rx_errors", "tx_bytes", "tx_window_errors",
962 "rx_fifo_errors", "tx_carrier_errors",
969 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
970 stats_dir = open(buf, O_DIRECTORY);
974 for (i = 0; i < ARRAY_SIZE(counters); i++)
975 if (read_uint64_file(stats_dir, counters[i], &val))
976 blobmsg_add_u64(b, counters[i], val);
982 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
984 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
985 int alen = v4 ? 4 : 16;
986 unsigned int flags = 0;
987 struct ifaddrmsg ifa = {
988 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
989 .ifa_prefixlen = addr->mask,
990 .ifa_index = dev->ifindex,
994 if (cmd == RTM_NEWADDR)
995 flags |= NLM_F_CREATE | NLM_F_REPLACE;
997 msg = nlmsg_alloc_simple(cmd, flags);
1001 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1002 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1004 if (addr->broadcast)
1005 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1006 if (addr->point_to_point)
1007 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1009 time_t now = system_get_rtime();
1010 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1012 if (addr->preferred_until) {
1013 int64_t preferred = addr->preferred_until - now;
1016 else if (preferred > UINT32_MAX)
1017 preferred = UINT32_MAX;
1019 cinfo.ifa_prefered = preferred;
1022 if (addr->valid_until) {
1023 int64_t valid = addr->valid_until - now;
1026 else if (valid > UINT32_MAX)
1029 cinfo.ifa_valid = valid;
1032 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1035 return system_rtnl_call(msg);
1038 int system_add_address(struct device *dev, struct device_addr *addr)
1040 return system_addr(dev, addr, RTM_NEWADDR);
1043 int system_del_address(struct device *dev, struct device_addr *addr)
1045 return system_addr(dev, addr, RTM_DELADDR);
1048 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1050 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1052 unsigned int flags = 0;
1055 have_gw = !!route->nexthop.in.s_addr;
1057 have_gw = route->nexthop.in6.s6_addr32[0] ||
1058 route->nexthop.in6.s6_addr32[1] ||
1059 route->nexthop.in6.s6_addr32[2] ||
1060 route->nexthop.in6.s6_addr32[3];
1062 unsigned char scope = (cmd == RTM_DELROUTE) ? RT_SCOPE_NOWHERE :
1063 (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1065 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1066 ? route->table : RT_TABLE_MAIN;
1068 struct rtmsg rtm = {
1069 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1070 .rtm_dst_len = route->mask,
1071 .rtm_src_len = route->sourcemask,
1072 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1073 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
1075 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1079 if (cmd == RTM_NEWROUTE) {
1080 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1082 if (!dev) { // Add null-route
1083 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1084 rtm.rtm_type = RTN_UNREACHABLE;
1088 msg = nlmsg_alloc_simple(cmd, flags);
1092 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1095 nla_put(msg, RTA_DST, alen, &route->addr);
1097 if (route->sourcemask)
1098 nla_put(msg, RTA_SRC, alen, &route->source);
1100 if (route->metric > 0)
1101 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1104 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1107 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1110 nla_put_u32(msg, RTA_TABLE, table);
1112 return system_rtnl_call(msg);
1115 int system_add_route(struct device *dev, struct device_route *route)
1117 return system_rt(dev, route, RTM_NEWROUTE);
1120 int system_del_route(struct device *dev, struct device_route *route)
1122 return system_rt(dev, route, RTM_DELROUTE);
1125 int system_flush_routes(void)
1127 const char *names[] = {
1128 "/proc/sys/net/ipv4/route/flush",
1129 "/proc/sys/net/ipv6/route/flush"
1133 for (i = 0; i < ARRAY_SIZE(names); i++) {
1134 fd = open(names[i], O_WRONLY);
1138 if (write(fd, "-1", 2)) {}
1144 bool system_resolve_rt_table(const char *name, unsigned int *id)
1148 unsigned int n, table = RT_TABLE_UNSPEC;
1150 /* first try to parse table as number */
1151 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1154 /* handle well known aliases */
1155 else if (!strcmp(name, "default"))
1156 table = RT_TABLE_DEFAULT;
1157 else if (!strcmp(name, "main"))
1158 table = RT_TABLE_MAIN;
1159 else if (!strcmp(name, "local"))
1160 table = RT_TABLE_LOCAL;
1162 /* try to look up name in /etc/iproute2/rt_tables */
1163 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1165 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1167 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1170 n = strtoul(e, NULL, 10);
1171 e = strtok(NULL, " \t\n");
1173 if (e && !strcmp(e, name))
1183 if (table == RT_TABLE_UNSPEC)
1186 /* do not consider main table special */
1187 if (table == RT_TABLE_MAIN)
1188 table = RT_TABLE_UNSPEC;
1194 static int system_iprule(struct iprule *rule, int cmd)
1196 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1199 struct rtmsg rtm = {
1200 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1201 .rtm_protocol = RTPROT_STATIC,
1202 .rtm_scope = RT_SCOPE_UNIVERSE,
1203 .rtm_table = RT_TABLE_UNSPEC,
1204 .rtm_type = RTN_UNSPEC,
1208 if (cmd == RTM_NEWRULE) {
1209 rtm.rtm_type = RTN_UNICAST;
1210 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1214 rtm.rtm_flags |= FIB_RULE_INVERT;
1216 if (rule->flags & IPRULE_SRC)
1217 rtm.rtm_src_len = rule->src_mask;
1219 if (rule->flags & IPRULE_DEST)
1220 rtm.rtm_dst_len = rule->dest_mask;
1222 if (rule->flags & IPRULE_TOS)
1223 rtm.rtm_tos = rule->tos;
1225 if (rule->flags & IPRULE_LOOKUP) {
1226 if (rule->lookup < 256)
1227 rtm.rtm_table = rule->lookup;
1230 if (rule->flags & IPRULE_ACTION)
1231 rtm.rtm_type = rule->action;
1232 else if (rule->flags & IPRULE_GOTO)
1233 rtm.rtm_type = FR_ACT_GOTO;
1234 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1235 rtm.rtm_type = FR_ACT_NOP;
1237 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1242 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1244 if (rule->flags & IPRULE_IN)
1245 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1247 if (rule->flags & IPRULE_OUT)
1248 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1250 if (rule->flags & IPRULE_SRC)
1251 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1253 if (rule->flags & IPRULE_DEST)
1254 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1256 if (rule->flags & IPRULE_PRIORITY)
1257 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1258 else if (cmd == RTM_NEWRULE)
1259 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1261 if (rule->flags & IPRULE_FWMARK)
1262 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1264 if (rule->flags & IPRULE_FWMASK)
1265 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1267 if (rule->flags & IPRULE_LOOKUP) {
1268 if (rule->lookup >= 256)
1269 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1272 if (rule->flags & IPRULE_GOTO)
1273 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1275 return system_rtnl_call(msg);
1278 int system_add_iprule(struct iprule *rule)
1280 return system_iprule(rule, RTM_NEWRULE);
1283 int system_del_iprule(struct iprule *rule)
1285 return system_iprule(rule, RTM_DELRULE);
1288 int system_flush_iprules(void)
1293 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1294 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1296 memset(&rule, 0, sizeof(rule));
1299 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1302 rule.lookup = RT_TABLE_LOCAL;
1303 rv |= system_iprule(&rule, RTM_NEWRULE);
1305 rule.priority = 32766;
1306 rule.lookup = RT_TABLE_MAIN;
1307 rv |= system_iprule(&rule, RTM_NEWRULE);
1309 rule.priority = 32767;
1310 rule.lookup = RT_TABLE_DEFAULT;
1311 rv |= system_iprule(&rule, RTM_NEWRULE);
1314 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1317 rule.lookup = RT_TABLE_LOCAL;
1318 rv |= system_iprule(&rule, RTM_NEWRULE);
1320 rule.priority = 32766;
1321 rule.lookup = RT_TABLE_MAIN;
1322 rv |= system_iprule(&rule, RTM_NEWRULE);
1327 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1332 if (!strcmp(action, "local"))
1334 else if (!strcmp(action, "nat"))
1336 else if (!strcmp(action, "broadcast"))
1338 else if (!strcmp(action, "anycast"))
1340 else if (!strcmp(action, "multicast"))
1342 else if (!strcmp(action, "prohibit"))
1344 else if (!strcmp(action, "unreachable"))
1345 n = RTN_UNREACHABLE;
1346 else if (!strcmp(action, "blackhole"))
1348 else if (!strcmp(action, "xresolve"))
1350 else if (!strcmp(action, "unicast"))
1352 else if (!strcmp(action, "throw"))
1354 else if (!strcmp(action, "failed_policy"))
1355 n = RTN_FAILED_POLICY;
1357 n = strtoul(action, &e, 0);
1358 if (!e || *e || e == action || n > 255)
1366 time_t system_get_rtime(void)
1371 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1374 if (gettimeofday(&tv, NULL) == 0)
1381 #define IP_DF 0x4000
1384 static int tunnel_ioctl(const char *name, int cmd, void *p)
1388 memset(&ifr, 0, sizeof(ifr));
1389 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1390 ifr.ifr_ifru.ifru_data = p;
1391 return ioctl(sock_ioctl, cmd, &ifr);
1394 int system_del_ip_tunnel(const char *name)
1396 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
1399 int system_update_ipv6_mtu(struct device *dev, int mtu)
1403 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
1406 int fd = open(buf, O_RDWR);
1407 ssize_t len = read(fd, buf, sizeof(buf) - 1);
1414 if (!mtu || ret <= mtu)
1417 lseek(fd, 0, SEEK_SET);
1418 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) <= 0)
1426 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
1428 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
1429 struct blob_attr *cur;
1433 system_del_ip_tunnel(name);
1435 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
1436 blob_data(attr), blob_len(attr));
1438 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
1440 str = blobmsg_data(cur);
1442 if ((cur = tb[TUNNEL_ATTR_DF]))
1443 set_df = blobmsg_get_bool(cur);
1445 unsigned int ttl = 0;
1446 if ((cur = tb[TUNNEL_ATTR_TTL])) {
1447 ttl = blobmsg_get_u32(cur);
1448 if (ttl > 255 || (!set_df && ttl))
1452 unsigned int link = 0;
1453 if ((cur = tb[TUNNEL_ATTR_LINK])) {
1454 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
1458 if (iface->l3_dev.dev)
1459 link = iface->l3_dev.dev->ifindex;
1462 if (!strcmp(str, "sit")) {
1463 struct ip_tunnel_parm p = {
1468 .frag_off = set_df ? htons(IP_DF) : 0,
1469 .protocol = IPPROTO_IPV6,
1474 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
1475 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
1478 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
1479 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
1482 strncpy(p.name, name, sizeof(p.name));
1483 if (tunnel_ioctl("sit0", SIOCADDTUNNEL, &p) < 0)
1487 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
1489 struct ip_tunnel_6rd p6;
1491 memset(&p6, 0, sizeof(p6));
1493 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
1494 &p6.prefix, &mask) || mask > 128)
1496 p6.prefixlen = mask;
1498 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
1499 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
1500 &p6.relay_prefix, &mask) || mask > 32)
1502 p6.relay_prefixlen = mask;
1505 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
1506 system_del_ip_tunnel(name);
1511 } else if (!strcmp(str, "ipip6")) {
1512 struct ip6_tnl_parm p = {
1514 .proto = IPPROTO_IPIP,
1515 .hop_limit = (ttl) ? ttl : 64,
1519 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
1520 inet_pton(AF_INET6, blobmsg_data(cur), &p.laddr) < 1)
1523 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
1524 inet_pton(AF_INET6, blobmsg_data(cur), &p.raddr) < 1)
1527 strncpy(p.name, name, sizeof(p.name));
1528 if (tunnel_ioctl("ip6tnl0", SIOCADDTUNNEL, &p) < 0)