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
50 #include <netlink/msg.h>
51 #include <netlink/attr.h>
52 #include <netlink/socket.h>
53 #include <libubox/uloop.h>
60 struct uloop_fd uloop;
65 static int sock_ioctl = -1;
66 static struct nl_sock *sock_rtnl = NULL;
68 static int cb_rtnl_event(struct nl_msg *msg, void *arg);
69 static void handle_hotplug_event(struct uloop_fd *u, unsigned int events);
71 static char dev_buf[256];
74 handler_nl_event(struct uloop_fd *u, unsigned int events)
76 struct event_socket *ev = container_of(u, struct event_socket, uloop);
77 nl_recvmsgs(ev->sock, ev->cb);
80 static struct nl_sock *
81 create_socket(int protocol, int groups)
85 sock = nl_socket_alloc();
90 nl_join_groups(sock, groups);
92 if (nl_connect(sock, protocol))
99 create_raw_event_socket(struct event_socket *ev, int protocol, int groups,
102 ev->sock = create_socket(protocol, groups);
106 ev->uloop.fd = nl_socket_get_fd(ev->sock);
108 uloop_fd_add(&ev->uloop, ULOOP_READ | ULOOP_EDGE_TRIGGER);
113 create_event_socket(struct event_socket *ev, int protocol,
114 int (*cb)(struct nl_msg *msg, void *arg))
116 // Prepare socket for link events
117 ev->cb = nl_cb_alloc(NL_CB_DEFAULT);
121 nl_cb_set(ev->cb, NL_CB_VALID, NL_CB_CUSTOM, cb, NULL);
123 return create_raw_event_socket(ev, protocol, 0, handler_nl_event);
126 int system_init(void)
128 static struct event_socket rtnl_event;
129 static struct event_socket hotplug_event;
131 sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0);
132 fcntl(sock_ioctl, F_SETFD, fcntl(sock_ioctl, F_GETFD) | FD_CLOEXEC);
134 // Prepare socket for routing / address control
135 sock_rtnl = create_socket(NETLINK_ROUTE, 0);
139 if (!create_event_socket(&rtnl_event, NETLINK_ROUTE, cb_rtnl_event))
142 if (!create_raw_event_socket(&hotplug_event, NETLINK_KOBJECT_UEVENT, 1,
143 handle_hotplug_event))
146 // Receive network link events form kernel
147 nl_socket_add_membership(rtnl_event.sock, RTNLGRP_LINK);
152 static void system_set_sysctl(const char *path, const char *val)
156 fd = open(path, O_WRONLY);
160 write(fd, val, strlen(val));
164 static void system_set_dev_sysctl(const char *path, const char *device, const char *val)
166 snprintf(dev_buf, sizeof(dev_buf), path, device);
167 system_set_sysctl(dev_buf, val);
170 static void system_set_disable_ipv6(struct device *dev, const char *val)
172 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val);
175 // Evaluate netlink messages
176 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
178 struct nlmsghdr *nh = nlmsg_hdr(msg);
179 struct ifinfomsg *ifi = NLMSG_DATA(nh);
180 struct nlattr *nla[__IFLA_MAX];
182 if (nh->nlmsg_type != RTM_DELLINK && nh->nlmsg_type != RTM_NEWLINK)
185 nlmsg_parse(nh, sizeof(*ifi), nla, __IFLA_MAX - 1, NULL);
186 if (!nla[IFLA_IFNAME])
189 struct device *dev = device_get(RTA_DATA(nla[IFLA_IFNAME]), false);
193 dev->ifindex = ifi->ifi_index;
194 /* TODO: parse link status */
201 handle_hotplug_msg(char *data, int size)
203 const char *subsystem = NULL, *interface = NULL;
204 char *cur, *end, *sep;
209 if (!strncmp(data, "add@", 4))
211 else if (!strncmp(data, "remove@", 7))
216 skip = strlen(data) + 1;
219 for (cur = data + skip; cur < end; cur += skip) {
220 skip = strlen(cur) + 1;
222 sep = strchr(cur, '=');
227 if (!strcmp(cur, "INTERFACE"))
229 else if (!strcmp(cur, "SUBSYSTEM")) {
231 if (strcmp(subsystem, "net") != 0)
234 if (subsystem && interface)
240 dev = device_get(interface, false);
244 if (dev->type != &simple_device_type)
247 if (add && system_if_force_external(dev->ifname))
250 device_set_present(dev, add);
254 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
256 struct event_socket *ev = container_of(u, struct event_socket, uloop);
257 struct sockaddr_nl nla;
258 unsigned char *buf = NULL;
261 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
263 handle_hotplug_msg((char *) buf, size);
269 static int system_rtnl_call(struct nl_msg *msg)
273 ret = nl_send_auto_complete(sock_rtnl, msg);
279 return nl_wait_for_ack(sock_rtnl);
282 int system_bridge_delbr(struct device *bridge)
284 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
287 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
291 memset(&ifr, 0, sizeof(ifr));
293 ifr.ifr_ifindex = dev->ifindex;
296 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
297 return ioctl(sock_ioctl, cmd, &ifr);
300 static bool system_is_bridge(const char *name, char *buf, int buflen)
304 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
305 if (stat(buf, &st) < 0)
311 static char *system_get_bridge(const char *name, char *buf, int buflen)
317 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
318 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
321 if (gl.gl_pathc == 0)
324 len = readlink(gl.gl_pathv[0], buf, buflen);
329 path = strrchr(buf, '/');
336 int system_bridge_addif(struct device *bridge, struct device *dev)
340 system_set_disable_ipv6(dev, "1");
341 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
342 if (oldbr && !strcmp(oldbr, bridge->ifname))
345 return system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
348 int system_bridge_delif(struct device *bridge, struct device *dev)
350 system_set_disable_ipv6(dev, "0");
351 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
354 static int system_if_resolve(struct device *dev)
357 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
358 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
359 return ifr.ifr_ifindex;
364 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
368 memset(&ifr, 0, sizeof(ifr));
369 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
370 ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
371 ifr.ifr_flags |= add;
372 ifr.ifr_flags &= ~rem;
373 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
385 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
387 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
389 return ifa->ifa_index == ifindex;
392 static bool check_route(struct nlmsghdr *hdr, int ifindex)
394 struct rtmsg *r = NLMSG_DATA(hdr);
395 struct nlattr *tb[__RTA_MAX];
397 if (r->rtm_protocol == RTPROT_KERNEL &&
398 r->rtm_family == AF_INET6)
401 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
405 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
408 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
413 static int cb_clear_event(struct nl_msg *msg, void *arg)
415 struct clear_data *clr = arg;
416 struct nlmsghdr *hdr = nlmsg_hdr(msg);
417 bool (*cb)(struct nlmsghdr *, int ifindex);
423 if (hdr->nlmsg_type != RTM_NEWADDR)
430 if (hdr->nlmsg_type != RTM_NEWROUTE)
437 if (hdr->nlmsg_type != RTM_NEWRULE)
446 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
449 if (type == RTM_DELRULE)
450 D(SYSTEM, "Remove a rule\n");
452 D(SYSTEM, "Remove %s from device %s\n",
453 type == RTM_DELADDR ? "an address" : "a route",
455 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
456 hdr = nlmsg_hdr(clr->msg);
457 hdr->nlmsg_type = type;
458 hdr->nlmsg_flags = NLM_F_REQUEST;
460 if (!nl_send_auto_complete(sock_rtnl, clr->msg))
461 nl_wait_for_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_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1072 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
1074 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1078 if (cmd == RTM_NEWROUTE) {
1079 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1081 if (!dev) { // Add null-route
1082 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1083 rtm.rtm_type = RTN_UNREACHABLE;
1087 msg = nlmsg_alloc_simple(cmd, flags);
1091 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1094 nla_put(msg, RTA_DST, alen, &route->addr);
1096 if (route->metric > 0)
1097 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1100 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1103 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1106 nla_put_u32(msg, RTA_TABLE, table);
1108 return system_rtnl_call(msg);
1111 int system_add_route(struct device *dev, struct device_route *route)
1113 return system_rt(dev, route, RTM_NEWROUTE);
1116 int system_del_route(struct device *dev, struct device_route *route)
1118 return system_rt(dev, route, RTM_DELROUTE);
1121 int system_flush_routes(void)
1123 const char *names[] = {
1124 "/proc/sys/net/ipv4/route/flush",
1125 "/proc/sys/net/ipv6/route/flush"
1129 for (i = 0; i < ARRAY_SIZE(names); i++) {
1130 fd = open(names[i], O_WRONLY);
1140 bool system_resolve_rt_table(const char *name, unsigned int *id)
1144 unsigned int n, table = RT_TABLE_UNSPEC;
1146 /* first try to parse table as number */
1147 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1150 /* handle well known aliases */
1151 else if (!strcmp(name, "default"))
1152 table = RT_TABLE_DEFAULT;
1153 else if (!strcmp(name, "main"))
1154 table = RT_TABLE_MAIN;
1155 else if (!strcmp(name, "local"))
1156 table = RT_TABLE_LOCAL;
1158 /* try to look up name in /etc/iproute2/rt_tables */
1159 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1161 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1163 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1166 n = strtoul(e, NULL, 10);
1167 e = strtok(NULL, " \t\n");
1169 if (e && !strcmp(e, name))
1179 if (table == RT_TABLE_UNSPEC)
1182 /* do not consider main table special */
1183 if (table == RT_TABLE_MAIN)
1184 table = RT_TABLE_UNSPEC;
1190 static int system_iprule(struct iprule *rule, int cmd)
1192 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1195 struct rtmsg rtm = {
1196 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1197 .rtm_protocol = RTPROT_STATIC,
1198 .rtm_scope = RT_SCOPE_UNIVERSE,
1199 .rtm_table = RT_TABLE_UNSPEC,
1200 .rtm_type = RTN_UNSPEC,
1204 if (cmd == RTM_NEWRULE) {
1205 rtm.rtm_type = RTN_UNICAST;
1206 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1210 rtm.rtm_flags |= FIB_RULE_INVERT;
1212 if (rule->flags & IPRULE_SRC)
1213 rtm.rtm_src_len = rule->src_mask;
1215 if (rule->flags & IPRULE_DEST)
1216 rtm.rtm_dst_len = rule->dest_mask;
1218 if (rule->flags & IPRULE_TOS)
1219 rtm.rtm_tos = rule->tos;
1221 if (rule->flags & IPRULE_LOOKUP) {
1222 if (rule->lookup < 256)
1223 rtm.rtm_table = rule->lookup;
1226 if (rule->flags & IPRULE_ACTION)
1227 rtm.rtm_type = rule->action;
1228 else if (rule->flags & IPRULE_GOTO)
1229 rtm.rtm_type = FR_ACT_GOTO;
1230 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1231 rtm.rtm_type = FR_ACT_NOP;
1233 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1238 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1240 if (rule->flags & IPRULE_IN)
1241 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1243 if (rule->flags & IPRULE_OUT)
1244 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1246 if (rule->flags & IPRULE_SRC)
1247 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1249 if (rule->flags & IPRULE_DEST)
1250 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1252 if (rule->flags & IPRULE_PRIORITY)
1253 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1254 else if (cmd == RTM_NEWRULE)
1255 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1257 if (rule->flags & IPRULE_FWMARK)
1258 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1260 if (rule->flags & IPRULE_FWMASK)
1261 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1263 if (rule->flags & IPRULE_LOOKUP) {
1264 if (rule->lookup >= 256)
1265 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1268 if (rule->flags & IPRULE_GOTO)
1269 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1271 return system_rtnl_call(msg);
1274 int system_add_iprule(struct iprule *rule)
1276 return system_iprule(rule, RTM_NEWRULE);
1279 int system_del_iprule(struct iprule *rule)
1281 return system_iprule(rule, RTM_DELRULE);
1284 int system_flush_iprules(void)
1289 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1290 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1292 memset(&rule, 0, sizeof(rule));
1295 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1298 rule.lookup = RT_TABLE_LOCAL;
1299 rv |= system_iprule(&rule, RTM_NEWRULE);
1301 rule.priority = 32766;
1302 rule.lookup = RT_TABLE_MAIN;
1303 rv |= system_iprule(&rule, RTM_NEWRULE);
1305 rule.priority = 32767;
1306 rule.lookup = RT_TABLE_DEFAULT;
1307 rv |= system_iprule(&rule, RTM_NEWRULE);
1310 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1313 rule.lookup = RT_TABLE_LOCAL;
1314 rv |= system_iprule(&rule, RTM_NEWRULE);
1316 rule.priority = 32766;
1317 rule.lookup = RT_TABLE_MAIN;
1318 rv |= system_iprule(&rule, RTM_NEWRULE);
1323 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1328 if (!strcmp(action, "local"))
1330 else if (!strcmp(action, "nat"))
1332 else if (!strcmp(action, "broadcast"))
1334 else if (!strcmp(action, "anycast"))
1336 else if (!strcmp(action, "multicast"))
1338 else if (!strcmp(action, "prohibit"))
1340 else if (!strcmp(action, "unreachable"))
1341 n = RTN_UNREACHABLE;
1342 else if (!strcmp(action, "blackhole"))
1344 else if (!strcmp(action, "xresolve"))
1346 else if (!strcmp(action, "unicast"))
1348 else if (!strcmp(action, "throw"))
1350 else if (!strcmp(action, "failed_policy"))
1351 n = RTN_FAILED_POLICY;
1353 n = strtoul(action, &e, 0);
1354 if (!e || *e || e == action || n > 255)
1362 time_t system_get_rtime(void)
1367 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1370 if (gettimeofday(&tv, NULL) == 0)
1377 #define IP_DF 0x4000
1380 static int tunnel_ioctl(const char *name, int cmd, void *p)
1384 memset(&ifr, 0, sizeof(ifr));
1385 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1386 ifr.ifr_ifru.ifru_data = p;
1387 return ioctl(sock_ioctl, cmd, &ifr);
1390 int system_del_ip_tunnel(const char *name)
1392 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
1395 int system_update_ipv6_mtu(struct device *dev, int mtu)
1399 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
1402 int fd = open(buf, O_RDWR);
1403 ssize_t len = read(fd, buf, sizeof(buf) - 1);
1410 if (!mtu || ret <= mtu)
1413 lseek(fd, 0, SEEK_SET);
1414 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) <= 0)
1423 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
1425 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
1426 struct blob_attr *cur;
1429 system_del_ip_tunnel(name);
1431 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
1432 blob_data(attr), blob_len(attr));
1434 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
1436 str = blobmsg_data(cur);
1438 unsigned int ttl = 0;
1439 if ((cur = tb[TUNNEL_ATTR_TTL]) && (ttl = blobmsg_get_u32(cur)) > 255)
1442 unsigned int link = 0;
1443 if ((cur = tb[TUNNEL_ATTR_LINK])) {
1444 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
1448 if (iface->l3_dev.dev)
1449 link = iface->l3_dev.dev->ifindex;
1453 if (!strcmp(str, "sit")) {
1454 struct ip_tunnel_parm p = {
1459 .frag_off = htons(IP_DF),
1460 .protocol = IPPROTO_IPV6,
1465 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
1466 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
1469 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
1470 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
1473 strncpy(p.name, name, sizeof(p.name));
1474 if (tunnel_ioctl("sit0", SIOCADDTUNNEL, &p) < 0)
1478 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
1480 struct ip_tunnel_6rd p6;
1482 memset(&p6, 0, sizeof(p6));
1484 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
1485 &p6.prefix, &mask) || mask > 128)
1487 p6.prefixlen = mask;
1489 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
1490 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
1491 &p6.relay_prefix, &mask) || mask > 32)
1493 p6.relay_prefixlen = mask;
1496 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
1497 system_del_ip_tunnel(name);
1502 } else if (!strcmp(str, "ipip6")) {
1503 struct ip6_tnl_parm p = {
1505 .proto = IPPROTO_IPIP,
1506 .hop_limit = (ttl) ? ttl : 64,
1510 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
1511 inet_pton(AF_INET6, blobmsg_data(cur), &p.laddr) < 1)
1514 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
1515 inet_pton(AF_INET6, blobmsg_data(cur), &p.raddr) < 1)
1518 strncpy(p.name, name, sizeof(p.name));
1519 if (tunnel_ioctl("ip6tnl0", SIOCADDTUNNEL, &p) < 0)