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_vlan.h>
33 #include <linux/if_bridge.h>
34 #include <linux/if_tunnel.h>
35 #include <linux/ip6_tunnel.h>
36 #include <linux/ethtool.h>
37 #include <linux/fib_rules.h>
39 #ifndef RTN_FAILED_POLICY
40 #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 static int system_vlan(struct device *dev, int id)
616 struct vlan_ioctl_args ifr = {
617 .cmd = SET_VLAN_NAME_TYPE_CMD,
618 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
621 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
624 ifr.cmd = DEL_VLAN_CMD;
627 ifr.cmd = ADD_VLAN_CMD;
630 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
631 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
634 int system_vlan_add(struct device *dev, int id)
636 return system_vlan(dev, id);
639 int system_vlan_del(struct device *dev)
641 return system_vlan(dev, -1);
645 system_if_get_settings(struct device *dev, struct device_settings *s)
649 memset(&ifr, 0, sizeof(ifr));
650 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
652 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
653 s->mtu = ifr.ifr_mtu;
654 s->flags |= DEV_OPT_MTU;
657 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
658 s->txqueuelen = ifr.ifr_qlen;
659 s->flags |= DEV_OPT_TXQUEUELEN;
662 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
663 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
664 s->flags |= DEV_OPT_MACADDR;
669 system_if_apply_settings(struct device *dev, struct device_settings *s)
673 memset(&ifr, 0, sizeof(ifr));
674 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
675 if (s->flags & DEV_OPT_MTU) {
676 ifr.ifr_mtu = s->mtu;
677 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
678 s->flags &= ~DEV_OPT_MTU;
680 if (s->flags & DEV_OPT_TXQUEUELEN) {
681 ifr.ifr_qlen = s->txqueuelen;
682 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
683 s->flags &= ~DEV_OPT_TXQUEUELEN;
685 if ((s->flags & DEV_OPT_MACADDR) && !dev->external) {
686 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
687 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
688 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
689 s->flags &= ~DEV_OPT_MACADDR;
693 int system_if_up(struct device *dev)
695 system_if_get_settings(dev, &dev->orig_settings);
696 system_if_apply_settings(dev, &dev->settings);
697 dev->ifindex = system_if_resolve(dev);
698 return system_if_flags(dev->ifname, IFF_UP, 0);
701 int system_if_down(struct device *dev)
703 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
704 dev->orig_settings.flags &= dev->settings.flags;
705 system_if_apply_settings(dev, &dev->orig_settings);
709 int system_if_check(struct device *dev)
711 device_set_present(dev, (system_if_resolve(dev) > 0));
716 system_if_get_parent(struct device *dev)
718 char buf[64], *devname;
719 int ifindex, iflink, len;
722 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
727 len = fread(buf, 1, sizeof(buf) - 1, f);
734 iflink = strtoul(buf, NULL, 0);
735 ifindex = system_if_resolve(dev);
736 if (!iflink || iflink == ifindex)
739 devname = if_indextoname(iflink, buf);
743 return device_get(devname, true);
747 read_string_file(int dir_fd, const char *file, char *buf, int len)
753 fd = openat(dir_fd, file, O_RDONLY);
758 len = read(fd, buf, len - 1);
762 } else if (len > 0) {
765 c = strchr(buf, '\n');
778 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
783 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
785 *val = strtoull(buf, NULL, 0);
790 /* Assume advertised flags == supported flags */
791 static const struct {
794 } ethtool_link_modes[] = {
795 { ADVERTISED_10baseT_Half, "10H" },
796 { ADVERTISED_10baseT_Full, "10F" },
797 { ADVERTISED_100baseT_Half, "100H" },
798 { ADVERTISED_100baseT_Full, "100F" },
799 { ADVERTISED_1000baseT_Half, "1000H" },
800 { ADVERTISED_1000baseT_Full, "1000F" },
803 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
806 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
807 if (mask & ethtool_link_modes[i].mask)
808 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
813 system_if_force_external(const char *ifname)
818 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
819 return stat(buf, &s) == 0;
823 system_if_dump_info(struct device *dev, struct blob_buf *b)
825 struct ethtool_cmd ecmd;
832 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
833 dir_fd = open(buf, O_DIRECTORY);
835 if (read_uint64_file(dir_fd, "carrier", &val))
836 blobmsg_add_u8(b, "link", !!val);
838 memset(&ecmd, 0, sizeof(ecmd));
839 memset(&ifr, 0, sizeof(ifr));
840 strcpy(ifr.ifr_name, dev->ifname);
841 ifr.ifr_data = (caddr_t) &ecmd;
842 ecmd.cmd = ETHTOOL_GSET;
844 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
845 c = blobmsg_open_array(b, "link-advertising");
846 system_add_link_modes(b, ecmd.advertising);
847 blobmsg_close_array(b, c);
849 c = blobmsg_open_array(b, "link-supported");
850 system_add_link_modes(b, ecmd.supported);
851 blobmsg_close_array(b, c);
853 s = blobmsg_alloc_string_buffer(b, "speed", 8);
854 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
855 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
856 blobmsg_add_string_buffer(b);
864 system_if_dump_stats(struct device *dev, struct blob_buf *b)
866 const char *const counters[] = {
867 "collisions", "rx_frame_errors", "tx_compressed",
868 "multicast", "rx_length_errors", "tx_dropped",
869 "rx_bytes", "rx_missed_errors", "tx_errors",
870 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
871 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
872 "rx_dropped", "tx_aborted_errors", "tx_packets",
873 "rx_errors", "tx_bytes", "tx_window_errors",
874 "rx_fifo_errors", "tx_carrier_errors",
881 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
882 stats_dir = open(buf, O_DIRECTORY);
886 for (i = 0; i < ARRAY_SIZE(counters); i++)
887 if (read_uint64_file(stats_dir, counters[i], &val))
888 blobmsg_add_u64(b, counters[i], val);
894 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
896 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
897 int alen = v4 ? 4 : 16;
898 unsigned int flags = 0;
899 struct ifaddrmsg ifa = {
900 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
901 .ifa_prefixlen = addr->mask,
902 .ifa_index = dev->ifindex,
906 if (cmd == RTM_NEWADDR)
907 flags |= NLM_F_CREATE | NLM_F_REPLACE;
909 msg = nlmsg_alloc_simple(cmd, flags);
913 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
914 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
917 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
918 if (addr->point_to_point)
919 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
921 time_t now = system_get_rtime();
922 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
924 if (addr->preferred_until) {
925 int64_t preferred = addr->preferred_until - now;
928 else if (preferred > UINT32_MAX)
929 preferred = UINT32_MAX;
931 cinfo.ifa_prefered = preferred;
934 if (addr->valid_until) {
935 int64_t valid = addr->valid_until - now;
938 else if (valid > UINT32_MAX)
941 cinfo.ifa_valid = valid;
944 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
947 return system_rtnl_call(msg);
950 int system_add_address(struct device *dev, struct device_addr *addr)
952 return system_addr(dev, addr, RTM_NEWADDR);
955 int system_del_address(struct device *dev, struct device_addr *addr)
957 return system_addr(dev, addr, RTM_DELADDR);
960 static int system_rt(struct device *dev, struct device_route *route, int cmd)
962 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
964 unsigned int flags = 0;
967 have_gw = !!route->nexthop.in.s_addr;
969 have_gw = route->nexthop.in6.s6_addr32[0] ||
970 route->nexthop.in6.s6_addr32[1] ||
971 route->nexthop.in6.s6_addr32[2] ||
972 route->nexthop.in6.s6_addr32[3];
974 unsigned char scope = (cmd == RTM_DELROUTE) ? RT_SCOPE_NOWHERE :
975 (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
977 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
978 ? route->table : RT_TABLE_MAIN;
981 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
982 .rtm_dst_len = route->mask,
983 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
984 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
986 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
990 if (cmd == RTM_NEWROUTE) {
991 flags |= NLM_F_CREATE | NLM_F_REPLACE;
993 if (!dev) { // Add null-route
994 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
995 rtm.rtm_type = RTN_UNREACHABLE;
999 msg = nlmsg_alloc_simple(cmd, flags);
1003 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1006 nla_put(msg, RTA_DST, alen, &route->addr);
1008 if (route->metric > 0)
1009 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1012 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1015 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1018 nla_put_u32(msg, RTA_TABLE, table);
1020 return system_rtnl_call(msg);
1023 int system_add_route(struct device *dev, struct device_route *route)
1025 return system_rt(dev, route, RTM_NEWROUTE);
1028 int system_del_route(struct device *dev, struct device_route *route)
1030 return system_rt(dev, route, RTM_DELROUTE);
1033 int system_flush_routes(void)
1035 const char *names[] = {
1036 "/proc/sys/net/ipv4/route/flush",
1037 "/proc/sys/net/ipv6/route/flush"
1041 for (i = 0; i < ARRAY_SIZE(names); i++) {
1042 fd = open(names[i], O_WRONLY);
1052 bool system_resolve_rt_table(const char *name, unsigned int *id)
1056 unsigned int n, table = RT_TABLE_UNSPEC;
1058 /* first try to parse table as number */
1059 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1062 /* handle well known aliases */
1063 else if (!strcmp(name, "default"))
1064 table = RT_TABLE_DEFAULT;
1065 else if (!strcmp(name, "main"))
1066 table = RT_TABLE_MAIN;
1067 else if (!strcmp(name, "local"))
1068 table = RT_TABLE_LOCAL;
1070 /* try to look up name in /etc/iproute2/rt_tables */
1071 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1073 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1075 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1078 n = strtoul(e, NULL, 10);
1079 e = strtok(NULL, " \t\n");
1081 if (e && !strcmp(e, name))
1091 if (table == RT_TABLE_UNSPEC)
1094 /* do not consider main table special */
1095 if (table == RT_TABLE_MAIN)
1096 table = RT_TABLE_UNSPEC;
1102 static int system_iprule(struct iprule *rule, int cmd)
1104 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1107 struct rtmsg rtm = {
1108 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1109 .rtm_protocol = RTPROT_STATIC,
1110 .rtm_scope = RT_SCOPE_UNIVERSE,
1111 .rtm_table = RT_TABLE_UNSPEC,
1112 .rtm_type = RTN_UNSPEC,
1116 if (cmd == RTM_NEWRULE) {
1117 rtm.rtm_type = RTN_UNICAST;
1118 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1122 rtm.rtm_flags |= FIB_RULE_INVERT;
1124 if (rule->flags & IPRULE_SRC)
1125 rtm.rtm_src_len = rule->src_mask;
1127 if (rule->flags & IPRULE_DEST)
1128 rtm.rtm_dst_len = rule->dest_mask;
1130 if (rule->flags & IPRULE_TOS)
1131 rtm.rtm_tos = rule->tos;
1133 if (rule->flags & IPRULE_LOOKUP) {
1134 if (rule->lookup < 256)
1135 rtm.rtm_table = rule->lookup;
1138 if (rule->flags & IPRULE_ACTION)
1139 rtm.rtm_type = rule->action;
1140 else if (rule->flags & IPRULE_GOTO)
1141 rtm.rtm_type = FR_ACT_GOTO;
1142 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1143 rtm.rtm_type = FR_ACT_NOP;
1145 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1150 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1152 if (rule->flags & IPRULE_IN)
1153 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1155 if (rule->flags & IPRULE_OUT)
1156 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1158 if (rule->flags & IPRULE_SRC)
1159 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1161 if (rule->flags & IPRULE_DEST)
1162 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1164 if (rule->flags & IPRULE_PRIORITY)
1165 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1166 else if (cmd == RTM_NEWRULE)
1167 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1169 if (rule->flags & IPRULE_FWMARK)
1170 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1172 if (rule->flags & IPRULE_FWMASK)
1173 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1175 if (rule->flags & IPRULE_LOOKUP) {
1176 if (rule->lookup >= 256)
1177 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1180 if (rule->flags & IPRULE_GOTO)
1181 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1183 return system_rtnl_call(msg);
1186 int system_add_iprule(struct iprule *rule)
1188 return system_iprule(rule, RTM_NEWRULE);
1191 int system_del_iprule(struct iprule *rule)
1193 return system_iprule(rule, RTM_DELRULE);
1196 int system_flush_iprules(void)
1201 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1202 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1204 memset(&rule, 0, sizeof(rule));
1207 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1210 rule.lookup = RT_TABLE_LOCAL;
1211 rv |= system_iprule(&rule, RTM_NEWRULE);
1213 rule.priority = 32766;
1214 rule.lookup = RT_TABLE_MAIN;
1215 rv |= system_iprule(&rule, RTM_NEWRULE);
1217 rule.priority = 32767;
1218 rule.lookup = RT_TABLE_DEFAULT;
1219 rv |= system_iprule(&rule, RTM_NEWRULE);
1222 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1225 rule.lookup = RT_TABLE_LOCAL;
1226 rv |= system_iprule(&rule, RTM_NEWRULE);
1228 rule.priority = 32766;
1229 rule.lookup = RT_TABLE_MAIN;
1230 rv |= system_iprule(&rule, RTM_NEWRULE);
1235 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1240 if (!strcmp(action, "local"))
1242 else if (!strcmp(action, "nat"))
1244 else if (!strcmp(action, "broadcast"))
1246 else if (!strcmp(action, "anycast"))
1248 else if (!strcmp(action, "multicast"))
1250 else if (!strcmp(action, "prohibit"))
1252 else if (!strcmp(action, "unreachable"))
1253 n = RTN_UNREACHABLE;
1254 else if (!strcmp(action, "blackhole"))
1256 else if (!strcmp(action, "xresolve"))
1258 else if (!strcmp(action, "unicast"))
1260 else if (!strcmp(action, "throw"))
1262 else if (!strcmp(action, "failed_policy"))
1263 n = RTN_FAILED_POLICY;
1265 n = strtoul(action, &e, 0);
1266 if (!e || *e || e == action || n > 255)
1274 time_t system_get_rtime(void)
1279 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1282 if (gettimeofday(&tv, NULL) == 0)
1289 #define IP_DF 0x4000
1292 static int tunnel_ioctl(const char *name, int cmd, void *p)
1296 memset(&ifr, 0, sizeof(ifr));
1297 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1298 ifr.ifr_ifru.ifru_data = p;
1299 return ioctl(sock_ioctl, cmd, &ifr);
1302 int system_del_ip_tunnel(const char *name)
1304 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
1307 int system_update_ipv6_mtu(struct device *dev, int mtu)
1311 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
1314 int fd = open(buf, O_RDWR);
1315 ssize_t len = read(fd, buf, sizeof(buf) - 1);
1322 if (!mtu || ret <= mtu)
1325 lseek(fd, 0, SEEK_SET);
1326 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) <= 0)
1335 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
1337 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
1338 struct blob_attr *cur;
1341 system_del_ip_tunnel(name);
1343 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
1344 blob_data(attr), blob_len(attr));
1346 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
1348 str = blobmsg_data(cur);
1350 unsigned int ttl = 0;
1351 if ((cur = tb[TUNNEL_ATTR_TTL]) && (ttl = blobmsg_get_u32(cur)) > 255)
1354 unsigned int link = 0;
1355 if ((cur = tb[TUNNEL_ATTR_LINK])) {
1356 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
1360 if (iface->l3_dev.dev)
1361 link = iface->l3_dev.dev->ifindex;
1365 if (!strcmp(str, "sit")) {
1366 struct ip_tunnel_parm p = {
1371 .frag_off = htons(IP_DF),
1372 .protocol = IPPROTO_IPV6,
1377 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
1378 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
1381 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
1382 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
1385 strncpy(p.name, name, sizeof(p.name));
1386 if (tunnel_ioctl("sit0", SIOCADDTUNNEL, &p) < 0)
1390 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
1392 struct ip_tunnel_6rd p6;
1394 memset(&p6, 0, sizeof(p6));
1396 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
1397 &p6.prefix, &mask) || mask > 128)
1399 p6.prefixlen = mask;
1401 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
1402 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
1403 &p6.relay_prefix, &mask) || mask > 32)
1405 p6.relay_prefixlen = mask;
1408 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
1409 system_del_ip_tunnel(name);
1414 } else if (!strcmp(str, "ipip6")) {
1415 struct ip6_tnl_parm p = {
1417 .proto = IPPROTO_IPIP,
1418 .hop_limit = (ttl) ? ttl : 64,
1422 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
1423 inet_pton(AF_INET6, blobmsg_data(cur), &p.laddr) < 1)
1426 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
1427 inet_pton(AF_INET6, blobmsg_data(cur), &p.raddr) < 1)
1430 strncpy(p.name, name, sizeof(p.name));
1431 if (tunnel_ioctl("ip6tnl0", SIOCADDTUNNEL, &p) < 0)