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_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1071 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
1073 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1077 if (cmd == RTM_NEWROUTE) {
1078 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1080 if (!dev) { // Add null-route
1081 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1082 rtm.rtm_type = RTN_UNREACHABLE;
1086 msg = nlmsg_alloc_simple(cmd, flags);
1090 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1093 nla_put(msg, RTA_DST, alen, &route->addr);
1095 if (route->metric > 0)
1096 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1099 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1102 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1105 nla_put_u32(msg, RTA_TABLE, table);
1107 return system_rtnl_call(msg);
1110 int system_add_route(struct device *dev, struct device_route *route)
1112 return system_rt(dev, route, RTM_NEWROUTE);
1115 int system_del_route(struct device *dev, struct device_route *route)
1117 return system_rt(dev, route, RTM_DELROUTE);
1120 int system_flush_routes(void)
1122 const char *names[] = {
1123 "/proc/sys/net/ipv4/route/flush",
1124 "/proc/sys/net/ipv6/route/flush"
1128 for (i = 0; i < ARRAY_SIZE(names); i++) {
1129 fd = open(names[i], O_WRONLY);
1139 bool system_resolve_rt_table(const char *name, unsigned int *id)
1143 unsigned int n, table = RT_TABLE_UNSPEC;
1145 /* first try to parse table as number */
1146 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1149 /* handle well known aliases */
1150 else if (!strcmp(name, "default"))
1151 table = RT_TABLE_DEFAULT;
1152 else if (!strcmp(name, "main"))
1153 table = RT_TABLE_MAIN;
1154 else if (!strcmp(name, "local"))
1155 table = RT_TABLE_LOCAL;
1157 /* try to look up name in /etc/iproute2/rt_tables */
1158 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1160 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1162 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1165 n = strtoul(e, NULL, 10);
1166 e = strtok(NULL, " \t\n");
1168 if (e && !strcmp(e, name))
1178 if (table == RT_TABLE_UNSPEC)
1181 /* do not consider main table special */
1182 if (table == RT_TABLE_MAIN)
1183 table = RT_TABLE_UNSPEC;
1189 static int system_iprule(struct iprule *rule, int cmd)
1191 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1194 struct rtmsg rtm = {
1195 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1196 .rtm_protocol = RTPROT_STATIC,
1197 .rtm_scope = RT_SCOPE_UNIVERSE,
1198 .rtm_table = RT_TABLE_UNSPEC,
1199 .rtm_type = RTN_UNSPEC,
1203 if (cmd == RTM_NEWRULE) {
1204 rtm.rtm_type = RTN_UNICAST;
1205 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1209 rtm.rtm_flags |= FIB_RULE_INVERT;
1211 if (rule->flags & IPRULE_SRC)
1212 rtm.rtm_src_len = rule->src_mask;
1214 if (rule->flags & IPRULE_DEST)
1215 rtm.rtm_dst_len = rule->dest_mask;
1217 if (rule->flags & IPRULE_TOS)
1218 rtm.rtm_tos = rule->tos;
1220 if (rule->flags & IPRULE_LOOKUP) {
1221 if (rule->lookup < 256)
1222 rtm.rtm_table = rule->lookup;
1225 if (rule->flags & IPRULE_ACTION)
1226 rtm.rtm_type = rule->action;
1227 else if (rule->flags & IPRULE_GOTO)
1228 rtm.rtm_type = FR_ACT_GOTO;
1229 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1230 rtm.rtm_type = FR_ACT_NOP;
1232 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1237 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1239 if (rule->flags & IPRULE_IN)
1240 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1242 if (rule->flags & IPRULE_OUT)
1243 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1245 if (rule->flags & IPRULE_SRC)
1246 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1248 if (rule->flags & IPRULE_DEST)
1249 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1251 if (rule->flags & IPRULE_PRIORITY)
1252 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1253 else if (cmd == RTM_NEWRULE)
1254 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1256 if (rule->flags & IPRULE_FWMARK)
1257 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1259 if (rule->flags & IPRULE_FWMASK)
1260 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1262 if (rule->flags & IPRULE_LOOKUP) {
1263 if (rule->lookup >= 256)
1264 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1267 if (rule->flags & IPRULE_GOTO)
1268 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1270 return system_rtnl_call(msg);
1273 int system_add_iprule(struct iprule *rule)
1275 return system_iprule(rule, RTM_NEWRULE);
1278 int system_del_iprule(struct iprule *rule)
1280 return system_iprule(rule, RTM_DELRULE);
1283 int system_flush_iprules(void)
1288 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1289 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1291 memset(&rule, 0, sizeof(rule));
1294 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1297 rule.lookup = RT_TABLE_LOCAL;
1298 rv |= system_iprule(&rule, RTM_NEWRULE);
1300 rule.priority = 32766;
1301 rule.lookup = RT_TABLE_MAIN;
1302 rv |= system_iprule(&rule, RTM_NEWRULE);
1304 rule.priority = 32767;
1305 rule.lookup = RT_TABLE_DEFAULT;
1306 rv |= system_iprule(&rule, RTM_NEWRULE);
1309 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1312 rule.lookup = RT_TABLE_LOCAL;
1313 rv |= system_iprule(&rule, RTM_NEWRULE);
1315 rule.priority = 32766;
1316 rule.lookup = RT_TABLE_MAIN;
1317 rv |= system_iprule(&rule, RTM_NEWRULE);
1322 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1327 if (!strcmp(action, "local"))
1329 else if (!strcmp(action, "nat"))
1331 else if (!strcmp(action, "broadcast"))
1333 else if (!strcmp(action, "anycast"))
1335 else if (!strcmp(action, "multicast"))
1337 else if (!strcmp(action, "prohibit"))
1339 else if (!strcmp(action, "unreachable"))
1340 n = RTN_UNREACHABLE;
1341 else if (!strcmp(action, "blackhole"))
1343 else if (!strcmp(action, "xresolve"))
1345 else if (!strcmp(action, "unicast"))
1347 else if (!strcmp(action, "throw"))
1349 else if (!strcmp(action, "failed_policy"))
1350 n = RTN_FAILED_POLICY;
1352 n = strtoul(action, &e, 0);
1353 if (!e || *e || e == action || n > 255)
1361 time_t system_get_rtime(void)
1366 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1369 if (gettimeofday(&tv, NULL) == 0)
1376 #define IP_DF 0x4000
1379 static int tunnel_ioctl(const char *name, int cmd, void *p)
1383 memset(&ifr, 0, sizeof(ifr));
1384 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1385 ifr.ifr_ifru.ifru_data = p;
1386 return ioctl(sock_ioctl, cmd, &ifr);
1389 int system_del_ip_tunnel(const char *name)
1391 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
1394 int system_update_ipv6_mtu(struct device *dev, int mtu)
1398 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
1401 int fd = open(buf, O_RDWR);
1402 ssize_t len = read(fd, buf, sizeof(buf) - 1);
1409 if (!mtu || ret <= mtu)
1412 lseek(fd, 0, SEEK_SET);
1413 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) <= 0)
1421 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
1423 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
1424 struct blob_attr *cur;
1428 system_del_ip_tunnel(name);
1430 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
1431 blob_data(attr), blob_len(attr));
1433 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
1435 str = blobmsg_data(cur);
1437 if ((cur = tb[TUNNEL_ATTR_DF]))
1438 set_df = blobmsg_get_bool(cur);
1440 unsigned int ttl = 0;
1441 if ((cur = tb[TUNNEL_ATTR_TTL])) {
1442 ttl = blobmsg_get_u32(cur);
1443 if (ttl > 255 || (!set_df && ttl))
1447 unsigned int link = 0;
1448 if ((cur = tb[TUNNEL_ATTR_LINK])) {
1449 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
1453 if (iface->l3_dev.dev)
1454 link = iface->l3_dev.dev->ifindex;
1457 if (!strcmp(str, "sit")) {
1458 struct ip_tunnel_parm p = {
1463 .frag_off = set_df ? htons(IP_DF) : 0,
1464 .protocol = IPPROTO_IPV6,
1469 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
1470 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
1473 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
1474 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
1477 strncpy(p.name, name, sizeof(p.name));
1478 if (tunnel_ioctl("sit0", SIOCADDTUNNEL, &p) < 0)
1482 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
1484 struct ip_tunnel_6rd p6;
1486 memset(&p6, 0, sizeof(p6));
1488 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
1489 &p6.prefix, &mask) || mask > 128)
1491 p6.prefixlen = mask;
1493 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
1494 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
1495 &p6.relay_prefix, &mask) || mask > 32)
1497 p6.relay_prefixlen = mask;
1500 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
1501 system_del_ip_tunnel(name);
1506 } else if (!strcmp(str, "ipip6")) {
1507 struct ip6_tnl_parm p = {
1509 .proto = IPPROTO_IPIP,
1510 .hop_limit = (ttl) ? ttl : 64,
1514 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
1515 inet_pton(AF_INET6, blobmsg_data(cur), &p.laddr) < 1)
1518 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
1519 inet_pton(AF_INET6, blobmsg_data(cur), &p.raddr) < 1)
1522 strncpy(p.name, name, sizeof(p.name));
1523 if (tunnel_ioctl("ip6tnl0", SIOCADDTUNNEL, &p) < 0)