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 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 if (!nl_send_auto_complete(sock_rtnl, clr->msg))
460 nl_wait_for_ack(sock_rtnl);
466 cb_finish_event(struct nl_msg *msg, void *arg)
474 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
477 *pending = err->error;
482 system_if_clear_entries(struct device *dev, int type, int af)
484 struct clear_data clr;
485 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
488 .rtm_flags = RTM_F_CLONED,
490 int flags = NLM_F_DUMP;
499 clr.size = sizeof(struct rtgenmsg);
502 clr.size = sizeof(struct rtmsg);
511 clr.msg = nlmsg_alloc_simple(type, flags);
515 nlmsg_append(clr.msg, &rtm, clr.size, 0);
516 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
517 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
518 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
520 nl_send_auto_complete(sock_rtnl, clr.msg);
522 nl_recvmsgs(sock_rtnl, cb);
530 * Clear bridge (membership) state and bring down device
532 void system_if_clear_state(struct device *dev)
534 static char buf[256];
540 dev->ifindex = system_if_resolve(dev);
544 system_if_flags(dev->ifname, 0, IFF_UP);
546 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
547 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
548 system_bridge_delbr(dev);
552 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
554 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
555 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
558 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
559 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
560 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
561 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
562 system_set_disable_ipv6(dev, "0");
565 static inline unsigned long
566 sec_to_jiffies(int val)
568 return (unsigned long) val * 100;
571 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
573 unsigned long args[4] = {};
575 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
578 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
579 args[1] = !!cfg->stp;
580 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
582 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
583 args[1] = sec_to_jiffies(cfg->forward_delay);
584 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
586 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
587 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
589 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
590 args[1] = cfg->priority;
591 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
593 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
594 args[0] = BRCTL_SET_AGEING_TIME;
595 args[1] = sec_to_jiffies(cfg->ageing_time);
596 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
599 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
600 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
601 args[1] = sec_to_jiffies(cfg->hello_time);
602 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
605 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
606 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
607 args[1] = sec_to_jiffies(cfg->max_age);
608 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
614 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
617 struct nlattr *linkinfo, *data;
618 struct ifinfomsg iim = { .ifi_family = AF_INET };
619 int ifindex = system_if_resolve(dev);
621 static const struct {
623 enum macvlan_mode val;
625 { "private", MACVLAN_MODE_PRIVATE },
626 { "vepa", MACVLAN_MODE_VEPA },
627 { "bridge", MACVLAN_MODE_BRIDGE },
628 { "passthru", MACVLAN_MODE_PASSTHRU },
634 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
639 nlmsg_append(msg, &iim, sizeof(iim), 0);
641 if (cfg->flags & MACVLAN_OPT_MACADDR)
642 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
643 nla_put(msg, IFLA_IFNAME, IFNAMSIZ, macvlan->ifname);
644 nla_put_u32(msg, IFLA_LINK, ifindex);
646 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
647 goto nla_put_failure;
649 nla_put(msg, IFLA_INFO_KIND, strlen("macvlan"), "macvlan");
651 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
652 goto nla_put_failure;
655 for (i = 0; i < ARRAY_SIZE(modes); i++) {
656 if (strcmp(cfg->mode, modes[i].name) != 0)
659 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
664 nla_nest_end(msg, data);
665 nla_nest_end(msg, linkinfo);
667 rv = system_rtnl_call(msg);
669 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
678 int system_macvlan_del(struct device *macvlan)
681 struct ifinfomsg iim;
683 iim.ifi_family = AF_INET;
686 msg = nlmsg_alloc_simple(RTM_DELLINK, 0);
691 nlmsg_append(msg, &iim, sizeof(iim), 0);
693 nla_put(msg, IFLA_INFO_KIND, strlen("macvlan"), "macvlan");
694 nla_put(msg, IFLA_IFNAME, sizeof(macvlan->ifname), macvlan->ifname);
696 system_rtnl_call(msg);
701 static int system_vlan(struct device *dev, int id)
703 struct vlan_ioctl_args ifr = {
704 .cmd = SET_VLAN_NAME_TYPE_CMD,
705 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
708 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
711 ifr.cmd = DEL_VLAN_CMD;
714 ifr.cmd = ADD_VLAN_CMD;
717 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
718 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
721 int system_vlan_add(struct device *dev, int id)
723 return system_vlan(dev, id);
726 int system_vlan_del(struct device *dev)
728 return system_vlan(dev, -1);
732 system_if_get_settings(struct device *dev, struct device_settings *s)
736 memset(&ifr, 0, sizeof(ifr));
737 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
739 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
740 s->mtu = ifr.ifr_mtu;
741 s->flags |= DEV_OPT_MTU;
744 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
745 s->txqueuelen = ifr.ifr_qlen;
746 s->flags |= DEV_OPT_TXQUEUELEN;
749 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
750 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
751 s->flags |= DEV_OPT_MACADDR;
756 system_if_apply_settings(struct device *dev, struct device_settings *s)
760 memset(&ifr, 0, sizeof(ifr));
761 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
762 if (s->flags & DEV_OPT_MTU) {
763 ifr.ifr_mtu = s->mtu;
764 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
765 s->flags &= ~DEV_OPT_MTU;
767 if (s->flags & DEV_OPT_TXQUEUELEN) {
768 ifr.ifr_qlen = s->txqueuelen;
769 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
770 s->flags &= ~DEV_OPT_TXQUEUELEN;
772 if ((s->flags & DEV_OPT_MACADDR) && !dev->external) {
773 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
774 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
775 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
776 s->flags &= ~DEV_OPT_MACADDR;
780 int system_if_up(struct device *dev)
782 system_if_get_settings(dev, &dev->orig_settings);
783 system_if_apply_settings(dev, &dev->settings);
784 dev->ifindex = system_if_resolve(dev);
785 return system_if_flags(dev->ifname, IFF_UP, 0);
788 int system_if_down(struct device *dev)
790 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
791 dev->orig_settings.flags &= dev->settings.flags;
792 system_if_apply_settings(dev, &dev->orig_settings);
796 int system_if_check(struct device *dev)
798 device_set_present(dev, (system_if_resolve(dev) > 0));
803 system_if_get_parent(struct device *dev)
805 char buf[64], *devname;
806 int ifindex, iflink, len;
809 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
814 len = fread(buf, 1, sizeof(buf) - 1, f);
821 iflink = strtoul(buf, NULL, 0);
822 ifindex = system_if_resolve(dev);
823 if (!iflink || iflink == ifindex)
826 devname = if_indextoname(iflink, buf);
830 return device_get(devname, true);
834 read_string_file(int dir_fd, const char *file, char *buf, int len)
840 fd = openat(dir_fd, file, O_RDONLY);
845 len = read(fd, buf, len - 1);
849 } else if (len > 0) {
852 c = strchr(buf, '\n');
865 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
870 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
872 *val = strtoull(buf, NULL, 0);
877 /* Assume advertised flags == supported flags */
878 static const struct {
881 } ethtool_link_modes[] = {
882 { ADVERTISED_10baseT_Half, "10H" },
883 { ADVERTISED_10baseT_Full, "10F" },
884 { ADVERTISED_100baseT_Half, "100H" },
885 { ADVERTISED_100baseT_Full, "100F" },
886 { ADVERTISED_1000baseT_Half, "1000H" },
887 { ADVERTISED_1000baseT_Full, "1000F" },
890 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
893 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
894 if (mask & ethtool_link_modes[i].mask)
895 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
900 system_if_force_external(const char *ifname)
905 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
906 return stat(buf, &s) == 0;
910 system_if_dump_info(struct device *dev, struct blob_buf *b)
912 struct ethtool_cmd ecmd;
919 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
920 dir_fd = open(buf, O_DIRECTORY);
922 if (read_uint64_file(dir_fd, "carrier", &val))
923 blobmsg_add_u8(b, "link", !!val);
925 memset(&ecmd, 0, sizeof(ecmd));
926 memset(&ifr, 0, sizeof(ifr));
927 strcpy(ifr.ifr_name, dev->ifname);
928 ifr.ifr_data = (caddr_t) &ecmd;
929 ecmd.cmd = ETHTOOL_GSET;
931 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
932 c = blobmsg_open_array(b, "link-advertising");
933 system_add_link_modes(b, ecmd.advertising);
934 blobmsg_close_array(b, c);
936 c = blobmsg_open_array(b, "link-supported");
937 system_add_link_modes(b, ecmd.supported);
938 blobmsg_close_array(b, c);
940 s = blobmsg_alloc_string_buffer(b, "speed", 8);
941 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
942 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
943 blobmsg_add_string_buffer(b);
951 system_if_dump_stats(struct device *dev, struct blob_buf *b)
953 const char *const counters[] = {
954 "collisions", "rx_frame_errors", "tx_compressed",
955 "multicast", "rx_length_errors", "tx_dropped",
956 "rx_bytes", "rx_missed_errors", "tx_errors",
957 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
958 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
959 "rx_dropped", "tx_aborted_errors", "tx_packets",
960 "rx_errors", "tx_bytes", "tx_window_errors",
961 "rx_fifo_errors", "tx_carrier_errors",
968 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
969 stats_dir = open(buf, O_DIRECTORY);
973 for (i = 0; i < ARRAY_SIZE(counters); i++)
974 if (read_uint64_file(stats_dir, counters[i], &val))
975 blobmsg_add_u64(b, counters[i], val);
981 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
983 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
984 int alen = v4 ? 4 : 16;
985 unsigned int flags = 0;
986 struct ifaddrmsg ifa = {
987 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
988 .ifa_prefixlen = addr->mask,
989 .ifa_index = dev->ifindex,
993 if (cmd == RTM_NEWADDR)
994 flags |= NLM_F_CREATE | NLM_F_REPLACE;
996 msg = nlmsg_alloc_simple(cmd, flags);
1000 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1001 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1003 if (addr->broadcast)
1004 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1005 if (addr->point_to_point)
1006 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1008 time_t now = system_get_rtime();
1009 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1011 if (addr->preferred_until) {
1012 int64_t preferred = addr->preferred_until - now;
1015 else if (preferred > UINT32_MAX)
1016 preferred = UINT32_MAX;
1018 cinfo.ifa_prefered = preferred;
1021 if (addr->valid_until) {
1022 int64_t valid = addr->valid_until - now;
1025 else if (valid > UINT32_MAX)
1028 cinfo.ifa_valid = valid;
1031 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1034 return system_rtnl_call(msg);
1037 int system_add_address(struct device *dev, struct device_addr *addr)
1039 return system_addr(dev, addr, RTM_NEWADDR);
1042 int system_del_address(struct device *dev, struct device_addr *addr)
1044 return system_addr(dev, addr, RTM_DELADDR);
1047 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1049 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1051 unsigned int flags = 0;
1054 have_gw = !!route->nexthop.in.s_addr;
1056 have_gw = route->nexthop.in6.s6_addr32[0] ||
1057 route->nexthop.in6.s6_addr32[1] ||
1058 route->nexthop.in6.s6_addr32[2] ||
1059 route->nexthop.in6.s6_addr32[3];
1061 unsigned char scope = (cmd == RTM_DELROUTE) ? RT_SCOPE_NOWHERE :
1062 (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1064 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1065 ? route->table : RT_TABLE_MAIN;
1067 struct rtmsg rtm = {
1068 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1069 .rtm_dst_len = route->mask,
1070 .rtm_src_len = route->sourcemask,
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->sourcemask)
1097 nla_put(msg, RTA_SRC, alen, &route->source);
1099 if (route->metric > 0)
1100 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1103 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1106 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1109 nla_put_u32(msg, RTA_TABLE, table);
1111 return system_rtnl_call(msg);
1114 int system_add_route(struct device *dev, struct device_route *route)
1116 return system_rt(dev, route, RTM_NEWROUTE);
1119 int system_del_route(struct device *dev, struct device_route *route)
1121 return system_rt(dev, route, RTM_DELROUTE);
1124 int system_flush_routes(void)
1126 const char *names[] = {
1127 "/proc/sys/net/ipv4/route/flush",
1128 "/proc/sys/net/ipv6/route/flush"
1132 for (i = 0; i < ARRAY_SIZE(names); i++) {
1133 fd = open(names[i], O_WRONLY);
1143 bool system_resolve_rt_table(const char *name, unsigned int *id)
1147 unsigned int n, table = RT_TABLE_UNSPEC;
1149 /* first try to parse table as number */
1150 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1153 /* handle well known aliases */
1154 else if (!strcmp(name, "default"))
1155 table = RT_TABLE_DEFAULT;
1156 else if (!strcmp(name, "main"))
1157 table = RT_TABLE_MAIN;
1158 else if (!strcmp(name, "local"))
1159 table = RT_TABLE_LOCAL;
1161 /* try to look up name in /etc/iproute2/rt_tables */
1162 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1164 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1166 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1169 n = strtoul(e, NULL, 10);
1170 e = strtok(NULL, " \t\n");
1172 if (e && !strcmp(e, name))
1182 if (table == RT_TABLE_UNSPEC)
1185 /* do not consider main table special */
1186 if (table == RT_TABLE_MAIN)
1187 table = RT_TABLE_UNSPEC;
1193 static int system_iprule(struct iprule *rule, int cmd)
1195 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1198 struct rtmsg rtm = {
1199 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1200 .rtm_protocol = RTPROT_STATIC,
1201 .rtm_scope = RT_SCOPE_UNIVERSE,
1202 .rtm_table = RT_TABLE_UNSPEC,
1203 .rtm_type = RTN_UNSPEC,
1207 if (cmd == RTM_NEWRULE) {
1208 rtm.rtm_type = RTN_UNICAST;
1209 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1213 rtm.rtm_flags |= FIB_RULE_INVERT;
1215 if (rule->flags & IPRULE_SRC)
1216 rtm.rtm_src_len = rule->src_mask;
1218 if (rule->flags & IPRULE_DEST)
1219 rtm.rtm_dst_len = rule->dest_mask;
1221 if (rule->flags & IPRULE_TOS)
1222 rtm.rtm_tos = rule->tos;
1224 if (rule->flags & IPRULE_LOOKUP) {
1225 if (rule->lookup < 256)
1226 rtm.rtm_table = rule->lookup;
1229 if (rule->flags & IPRULE_ACTION)
1230 rtm.rtm_type = rule->action;
1231 else if (rule->flags & IPRULE_GOTO)
1232 rtm.rtm_type = FR_ACT_GOTO;
1233 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1234 rtm.rtm_type = FR_ACT_NOP;
1236 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1241 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1243 if (rule->flags & IPRULE_IN)
1244 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1246 if (rule->flags & IPRULE_OUT)
1247 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1249 if (rule->flags & IPRULE_SRC)
1250 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1252 if (rule->flags & IPRULE_DEST)
1253 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1255 if (rule->flags & IPRULE_PRIORITY)
1256 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1257 else if (cmd == RTM_NEWRULE)
1258 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1260 if (rule->flags & IPRULE_FWMARK)
1261 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1263 if (rule->flags & IPRULE_FWMASK)
1264 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1266 if (rule->flags & IPRULE_LOOKUP) {
1267 if (rule->lookup >= 256)
1268 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1271 if (rule->flags & IPRULE_GOTO)
1272 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1274 return system_rtnl_call(msg);
1277 int system_add_iprule(struct iprule *rule)
1279 return system_iprule(rule, RTM_NEWRULE);
1282 int system_del_iprule(struct iprule *rule)
1284 return system_iprule(rule, RTM_DELRULE);
1287 int system_flush_iprules(void)
1292 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1293 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1295 memset(&rule, 0, sizeof(rule));
1298 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1301 rule.lookup = RT_TABLE_LOCAL;
1302 rv |= system_iprule(&rule, RTM_NEWRULE);
1304 rule.priority = 32766;
1305 rule.lookup = RT_TABLE_MAIN;
1306 rv |= system_iprule(&rule, RTM_NEWRULE);
1308 rule.priority = 32767;
1309 rule.lookup = RT_TABLE_DEFAULT;
1310 rv |= system_iprule(&rule, RTM_NEWRULE);
1313 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1316 rule.lookup = RT_TABLE_LOCAL;
1317 rv |= system_iprule(&rule, RTM_NEWRULE);
1319 rule.priority = 32766;
1320 rule.lookup = RT_TABLE_MAIN;
1321 rv |= system_iprule(&rule, RTM_NEWRULE);
1326 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1331 if (!strcmp(action, "local"))
1333 else if (!strcmp(action, "nat"))
1335 else if (!strcmp(action, "broadcast"))
1337 else if (!strcmp(action, "anycast"))
1339 else if (!strcmp(action, "multicast"))
1341 else if (!strcmp(action, "prohibit"))
1343 else if (!strcmp(action, "unreachable"))
1344 n = RTN_UNREACHABLE;
1345 else if (!strcmp(action, "blackhole"))
1347 else if (!strcmp(action, "xresolve"))
1349 else if (!strcmp(action, "unicast"))
1351 else if (!strcmp(action, "throw"))
1353 else if (!strcmp(action, "failed_policy"))
1354 n = RTN_FAILED_POLICY;
1356 n = strtoul(action, &e, 0);
1357 if (!e || *e || e == action || n > 255)
1365 time_t system_get_rtime(void)
1370 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1373 if (gettimeofday(&tv, NULL) == 0)
1380 #define IP_DF 0x4000
1383 static int tunnel_ioctl(const char *name, int cmd, void *p)
1387 memset(&ifr, 0, sizeof(ifr));
1388 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1389 ifr.ifr_ifru.ifru_data = p;
1390 return ioctl(sock_ioctl, cmd, &ifr);
1393 int system_del_ip_tunnel(const char *name)
1395 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
1398 int system_update_ipv6_mtu(struct device *dev, int mtu)
1402 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
1405 int fd = open(buf, O_RDWR);
1406 ssize_t len = read(fd, buf, sizeof(buf) - 1);
1413 if (!mtu || ret <= mtu)
1416 lseek(fd, 0, SEEK_SET);
1417 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) <= 0)
1425 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
1427 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
1428 struct blob_attr *cur;
1432 system_del_ip_tunnel(name);
1434 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
1435 blob_data(attr), blob_len(attr));
1437 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
1439 str = blobmsg_data(cur);
1441 if ((cur = tb[TUNNEL_ATTR_DF]))
1442 set_df = blobmsg_get_bool(cur);
1444 unsigned int ttl = 0;
1445 if ((cur = tb[TUNNEL_ATTR_TTL])) {
1446 ttl = blobmsg_get_u32(cur);
1447 if (ttl > 255 || (!set_df && ttl))
1451 unsigned int link = 0;
1452 if ((cur = tb[TUNNEL_ATTR_LINK])) {
1453 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
1457 if (iface->l3_dev.dev)
1458 link = iface->l3_dev.dev->ifindex;
1461 if (!strcmp(str, "sit")) {
1462 struct ip_tunnel_parm p = {
1467 .frag_off = set_df ? htons(IP_DF) : 0,
1468 .protocol = IPPROTO_IPV6,
1473 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
1474 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
1477 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
1478 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
1481 strncpy(p.name, name, sizeof(p.name));
1482 if (tunnel_ioctl("sit0", SIOCADDTUNNEL, &p) < 0)
1486 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
1488 struct ip_tunnel_6rd p6;
1490 memset(&p6, 0, sizeof(p6));
1492 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
1493 &p6.prefix, &mask) || mask > 128)
1495 p6.prefixlen = mask;
1497 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
1498 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
1499 &p6.relay_prefix, &mask) || mask > 32)
1501 p6.relay_prefixlen = mask;
1504 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
1505 system_del_ip_tunnel(name);
1510 } else if (!strcmp(str, "ipip6")) {
1511 struct ip6_tnl_parm p = {
1513 .proto = IPPROTO_IPIP,
1514 .hop_limit = (ttl) ? ttl : 64,
1518 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
1519 inet_pton(AF_INET6, blobmsg_data(cur), &p.laddr) < 1)
1522 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
1523 inet_pton(AF_INET6, blobmsg_data(cur), &p.raddr) < 1)
1526 strncpy(p.name, name, sizeof(p.name));
1527 if (tunnel_ioctl("ip6tnl0", SIOCADDTUNNEL, &p) < 0)