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>
45 #include <netlink/msg.h>
46 #include <netlink/attr.h>
47 #include <netlink/socket.h>
48 #include <libubox/uloop.h>
55 struct uloop_fd uloop;
60 static int sock_ioctl = -1;
61 static struct nl_sock *sock_rtnl = NULL;
63 static int cb_rtnl_event(struct nl_msg *msg, void *arg);
64 static void handle_hotplug_event(struct uloop_fd *u, unsigned int events);
66 static char dev_buf[256];
69 handler_nl_event(struct uloop_fd *u, unsigned int events)
71 struct event_socket *ev = container_of(u, struct event_socket, uloop);
72 nl_recvmsgs(ev->sock, ev->cb);
75 static struct nl_sock *
76 create_socket(int protocol, int groups)
80 sock = nl_socket_alloc();
85 nl_join_groups(sock, groups);
87 if (nl_connect(sock, protocol))
94 create_raw_event_socket(struct event_socket *ev, int protocol, int groups,
97 ev->sock = create_socket(protocol, groups);
101 ev->uloop.fd = nl_socket_get_fd(ev->sock);
103 uloop_fd_add(&ev->uloop, ULOOP_READ | ULOOP_EDGE_TRIGGER);
108 create_event_socket(struct event_socket *ev, int protocol,
109 int (*cb)(struct nl_msg *msg, void *arg))
111 // Prepare socket for link events
112 ev->cb = nl_cb_alloc(NL_CB_DEFAULT);
116 nl_cb_set(ev->cb, NL_CB_VALID, NL_CB_CUSTOM, cb, NULL);
118 return create_raw_event_socket(ev, protocol, 0, handler_nl_event);
121 int system_init(void)
123 static struct event_socket rtnl_event;
124 static struct event_socket hotplug_event;
126 sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0);
127 fcntl(sock_ioctl, F_SETFD, fcntl(sock_ioctl, F_GETFD) | FD_CLOEXEC);
129 // Prepare socket for routing / address control
130 sock_rtnl = create_socket(NETLINK_ROUTE, 0);
134 if (!create_event_socket(&rtnl_event, NETLINK_ROUTE, cb_rtnl_event))
137 if (!create_raw_event_socket(&hotplug_event, NETLINK_KOBJECT_UEVENT, 1,
138 handle_hotplug_event))
141 // Receive network link events form kernel
142 nl_socket_add_membership(rtnl_event.sock, RTNLGRP_LINK);
147 static void system_set_sysctl(const char *path, const char *val)
151 fd = open(path, O_WRONLY);
155 write(fd, val, strlen(val));
159 static void system_set_dev_sysctl(const char *path, const char *device, const char *val)
161 snprintf(dev_buf, sizeof(dev_buf), path, device);
162 system_set_sysctl(dev_buf, val);
165 static void system_set_disable_ipv6(struct device *dev, const char *val)
167 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val);
170 // Evaluate netlink messages
171 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
173 struct nlmsghdr *nh = nlmsg_hdr(msg);
174 struct ifinfomsg *ifi = NLMSG_DATA(nh);
175 struct nlattr *nla[__IFLA_MAX];
177 if (nh->nlmsg_type != RTM_DELLINK && nh->nlmsg_type != RTM_NEWLINK)
180 nlmsg_parse(nh, sizeof(*ifi), nla, __IFLA_MAX - 1, NULL);
181 if (!nla[IFLA_IFNAME])
184 struct device *dev = device_get(RTA_DATA(nla[IFLA_IFNAME]), false);
188 dev->ifindex = ifi->ifi_index;
189 /* TODO: parse link status */
196 handle_hotplug_msg(char *data, int size)
198 const char *subsystem = NULL, *interface = NULL;
199 char *cur, *end, *sep;
204 if (!strncmp(data, "add@", 4))
206 else if (!strncmp(data, "remove@", 7))
211 skip = strlen(data) + 1;
214 for (cur = data + skip; cur < end; cur += skip) {
215 skip = strlen(cur) + 1;
217 sep = strchr(cur, '=');
222 if (!strcmp(cur, "INTERFACE"))
224 else if (!strcmp(cur, "SUBSYSTEM")) {
226 if (strcmp(subsystem, "net") != 0)
229 if (subsystem && interface)
235 dev = device_get(interface, false);
239 if (dev->type != &simple_device_type)
242 if (add && system_if_force_external(dev->ifname))
245 device_set_present(dev, add);
249 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
251 struct event_socket *ev = container_of(u, struct event_socket, uloop);
252 struct sockaddr_nl nla;
253 unsigned char *buf = NULL;
256 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
258 handle_hotplug_msg((char *) buf, size);
264 static int system_rtnl_call(struct nl_msg *msg)
268 ret = nl_send_auto_complete(sock_rtnl, msg);
274 return nl_wait_for_ack(sock_rtnl);
277 int system_bridge_delbr(struct device *bridge)
279 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
282 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
286 memset(&ifr, 0, sizeof(ifr));
288 ifr.ifr_ifindex = dev->ifindex;
291 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
292 return ioctl(sock_ioctl, cmd, &ifr);
295 static bool system_is_bridge(const char *name, char *buf, int buflen)
299 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
300 if (stat(buf, &st) < 0)
306 static char *system_get_bridge(const char *name, char *buf, int buflen)
312 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
313 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
316 if (gl.gl_pathc == 0)
319 len = readlink(gl.gl_pathv[0], buf, buflen);
324 path = strrchr(buf, '/');
331 int system_bridge_addif(struct device *bridge, struct device *dev)
335 system_set_disable_ipv6(dev, "1");
336 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
337 if (oldbr && !strcmp(oldbr, bridge->ifname))
340 return system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
343 int system_bridge_delif(struct device *bridge, struct device *dev)
345 system_set_disable_ipv6(dev, "0");
346 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
349 static int system_if_resolve(struct device *dev)
352 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
353 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
354 return ifr.ifr_ifindex;
359 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
363 memset(&ifr, 0, sizeof(ifr));
364 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
365 ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
366 ifr.ifr_flags |= add;
367 ifr.ifr_flags &= ~rem;
368 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
380 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
382 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
384 return ifa->ifa_index == ifindex;
387 static bool check_route(struct nlmsghdr *hdr, int ifindex)
389 struct rtmsg *r = NLMSG_DATA(hdr);
390 struct nlattr *tb[__RTA_MAX];
392 if (r->rtm_protocol == RTPROT_KERNEL &&
393 r->rtm_family == AF_INET6)
396 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
400 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
403 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
408 static int cb_clear_event(struct nl_msg *msg, void *arg)
410 struct clear_data *clr = arg;
411 struct nlmsghdr *hdr = nlmsg_hdr(msg);
412 bool (*cb)(struct nlmsghdr *, int ifindex);
418 if (hdr->nlmsg_type != RTM_NEWADDR)
425 if (hdr->nlmsg_type != RTM_NEWROUTE)
432 if (hdr->nlmsg_type != RTM_NEWRULE)
441 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
444 if (type == RTM_DELRULE)
445 D(SYSTEM, "Remove a rule\n");
447 D(SYSTEM, "Remove %s from device %s\n",
448 type == RTM_DELADDR ? "an address" : "a route",
450 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
451 hdr = nlmsg_hdr(clr->msg);
452 hdr->nlmsg_type = type;
453 hdr->nlmsg_flags = NLM_F_REQUEST;
455 if (!nl_send_auto_complete(sock_rtnl, clr->msg))
456 nl_wait_for_ack(sock_rtnl);
462 cb_finish_event(struct nl_msg *msg, void *arg)
470 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
473 *pending = err->error;
478 system_if_clear_entries(struct device *dev, int type, int af)
480 struct clear_data clr;
481 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
484 .rtm_flags = RTM_F_CLONED,
486 int flags = NLM_F_DUMP;
495 clr.size = sizeof(struct rtgenmsg);
498 clr.size = sizeof(struct rtmsg);
507 clr.msg = nlmsg_alloc_simple(type, flags);
511 nlmsg_append(clr.msg, &rtm, clr.size, 0);
512 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
513 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
514 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
516 nl_send_auto_complete(sock_rtnl, clr.msg);
518 nl_recvmsgs(sock_rtnl, cb);
526 * Clear bridge (membership) state and bring down device
528 void system_if_clear_state(struct device *dev)
530 static char buf[256];
536 dev->ifindex = system_if_resolve(dev);
540 system_if_flags(dev->ifname, 0, IFF_UP);
542 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
543 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
544 system_bridge_delbr(dev);
548 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
550 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
551 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
554 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
555 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
556 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
557 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
558 system_set_disable_ipv6(dev, "0");
561 static inline unsigned long
562 sec_to_jiffies(int val)
564 return (unsigned long) val * 100;
567 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
569 unsigned long args[4] = {};
571 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
574 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
575 args[1] = !!cfg->stp;
576 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
578 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
579 args[1] = sec_to_jiffies(cfg->forward_delay);
580 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
582 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
583 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
585 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
586 args[1] = cfg->priority;
587 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
589 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
590 args[0] = BRCTL_SET_AGEING_TIME;
591 args[1] = sec_to_jiffies(cfg->ageing_time);
592 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
595 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
596 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
597 args[1] = sec_to_jiffies(cfg->hello_time);
598 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
601 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
602 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
603 args[1] = sec_to_jiffies(cfg->max_age);
604 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
610 static int system_vlan(struct device *dev, int id)
612 struct vlan_ioctl_args ifr = {
613 .cmd = SET_VLAN_NAME_TYPE_CMD,
614 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
617 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
620 ifr.cmd = DEL_VLAN_CMD;
623 ifr.cmd = ADD_VLAN_CMD;
626 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
627 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
630 int system_vlan_add(struct device *dev, int id)
632 return system_vlan(dev, id);
635 int system_vlan_del(struct device *dev)
637 return system_vlan(dev, -1);
641 system_if_get_settings(struct device *dev, struct device_settings *s)
645 memset(&ifr, 0, sizeof(ifr));
646 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
648 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
649 s->mtu = ifr.ifr_mtu;
650 s->flags |= DEV_OPT_MTU;
653 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
654 s->txqueuelen = ifr.ifr_qlen;
655 s->flags |= DEV_OPT_TXQUEUELEN;
658 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
659 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
660 s->flags |= DEV_OPT_MACADDR;
665 system_if_apply_settings(struct device *dev, struct device_settings *s)
669 memset(&ifr, 0, sizeof(ifr));
670 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
671 if (s->flags & DEV_OPT_MTU) {
672 ifr.ifr_mtu = s->mtu;
673 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
674 s->flags &= ~DEV_OPT_MTU;
676 if (s->flags & DEV_OPT_TXQUEUELEN) {
677 ifr.ifr_qlen = s->txqueuelen;
678 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
679 s->flags &= ~DEV_OPT_TXQUEUELEN;
681 if ((s->flags & DEV_OPT_MACADDR) && !dev->external) {
682 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
683 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
684 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
685 s->flags &= ~DEV_OPT_MACADDR;
689 int system_if_up(struct device *dev)
691 system_if_get_settings(dev, &dev->orig_settings);
692 system_if_apply_settings(dev, &dev->settings);
693 dev->ifindex = system_if_resolve(dev);
694 return system_if_flags(dev->ifname, IFF_UP, 0);
697 int system_if_down(struct device *dev)
699 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
700 dev->orig_settings.flags &= dev->settings.flags;
701 system_if_apply_settings(dev, &dev->orig_settings);
705 int system_if_check(struct device *dev)
707 device_set_present(dev, (system_if_resolve(dev) > 0));
712 system_if_get_parent(struct device *dev)
714 char buf[64], *devname;
715 int ifindex, iflink, len;
718 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
723 len = fread(buf, 1, sizeof(buf) - 1, f);
730 iflink = strtoul(buf, NULL, 0);
731 ifindex = system_if_resolve(dev);
732 if (!iflink || iflink == ifindex)
735 devname = if_indextoname(iflink, buf);
739 return device_get(devname, true);
743 read_string_file(int dir_fd, const char *file, char *buf, int len)
749 fd = openat(dir_fd, file, O_RDONLY);
754 len = read(fd, buf, len - 1);
758 } else if (len > 0) {
761 c = strchr(buf, '\n');
774 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
779 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
781 *val = strtoull(buf, NULL, 0);
786 /* Assume advertised flags == supported flags */
787 static const struct {
790 } ethtool_link_modes[] = {
791 { ADVERTISED_10baseT_Half, "10H" },
792 { ADVERTISED_10baseT_Full, "10F" },
793 { ADVERTISED_100baseT_Half, "100H" },
794 { ADVERTISED_100baseT_Full, "100F" },
795 { ADVERTISED_1000baseT_Half, "1000H" },
796 { ADVERTISED_1000baseT_Full, "1000F" },
799 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
802 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
803 if (mask & ethtool_link_modes[i].mask)
804 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
809 system_if_force_external(const char *ifname)
814 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
815 return stat(buf, &s) == 0;
819 system_if_dump_info(struct device *dev, struct blob_buf *b)
821 struct ethtool_cmd ecmd;
828 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
829 dir_fd = open(buf, O_DIRECTORY);
831 if (read_uint64_file(dir_fd, "carrier", &val))
832 blobmsg_add_u8(b, "link", !!val);
834 memset(&ecmd, 0, sizeof(ecmd));
835 memset(&ifr, 0, sizeof(ifr));
836 strcpy(ifr.ifr_name, dev->ifname);
837 ifr.ifr_data = (caddr_t) &ecmd;
838 ecmd.cmd = ETHTOOL_GSET;
840 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
841 c = blobmsg_open_array(b, "link-advertising");
842 system_add_link_modes(b, ecmd.advertising);
843 blobmsg_close_array(b, c);
845 c = blobmsg_open_array(b, "link-supported");
846 system_add_link_modes(b, ecmd.supported);
847 blobmsg_close_array(b, c);
849 s = blobmsg_alloc_string_buffer(b, "speed", 8);
850 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
851 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
852 blobmsg_add_string_buffer(b);
860 system_if_dump_stats(struct device *dev, struct blob_buf *b)
862 const char *const counters[] = {
863 "collisions", "rx_frame_errors", "tx_compressed",
864 "multicast", "rx_length_errors", "tx_dropped",
865 "rx_bytes", "rx_missed_errors", "tx_errors",
866 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
867 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
868 "rx_dropped", "tx_aborted_errors", "tx_packets",
869 "rx_errors", "tx_bytes", "tx_window_errors",
870 "rx_fifo_errors", "tx_carrier_errors",
877 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
878 stats_dir = open(buf, O_DIRECTORY);
882 for (i = 0; i < ARRAY_SIZE(counters); i++)
883 if (read_uint64_file(stats_dir, counters[i], &val))
884 blobmsg_add_u64(b, counters[i], val);
890 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
892 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
893 int alen = v4 ? 4 : 16;
894 unsigned int flags = 0;
895 struct ifaddrmsg ifa = {
896 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
897 .ifa_prefixlen = addr->mask,
898 .ifa_index = dev->ifindex,
902 if (cmd == RTM_NEWADDR)
903 flags |= NLM_F_CREATE | NLM_F_REPLACE;
905 msg = nlmsg_alloc_simple(cmd, flags);
909 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
910 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
913 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
914 if (addr->point_to_point)
915 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
917 time_t now = system_get_rtime();
918 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
920 if (addr->preferred_until) {
921 int64_t preferred = addr->preferred_until - now;
924 else if (preferred > UINT32_MAX)
925 preferred = UINT32_MAX;
927 cinfo.ifa_prefered = preferred;
930 if (addr->valid_until) {
931 int64_t valid = addr->valid_until - now;
934 else if (valid > UINT32_MAX)
937 cinfo.ifa_valid = valid;
940 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
943 return system_rtnl_call(msg);
946 int system_add_address(struct device *dev, struct device_addr *addr)
948 return system_addr(dev, addr, RTM_NEWADDR);
951 int system_del_address(struct device *dev, struct device_addr *addr)
953 return system_addr(dev, addr, RTM_DELADDR);
956 static int system_rt(struct device *dev, struct device_route *route, int cmd)
958 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
960 unsigned int flags = 0;
963 have_gw = !!route->nexthop.in.s_addr;
965 have_gw = route->nexthop.in6.s6_addr32[0] ||
966 route->nexthop.in6.s6_addr32[1] ||
967 route->nexthop.in6.s6_addr32[2] ||
968 route->nexthop.in6.s6_addr32[3];
970 unsigned char scope = (cmd == RTM_DELROUTE) ? RT_SCOPE_NOWHERE :
971 (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
973 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
974 ? route->table : RT_TABLE_MAIN;
977 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
978 .rtm_dst_len = route->mask,
979 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
980 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
982 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
986 if (cmd == RTM_NEWROUTE) {
987 flags |= NLM_F_CREATE | NLM_F_REPLACE;
989 if (!dev) { // Add null-route
990 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
991 rtm.rtm_type = RTN_UNREACHABLE;
995 msg = nlmsg_alloc_simple(cmd, flags);
999 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1002 nla_put(msg, RTA_DST, alen, &route->addr);
1004 if (route->metric > 0)
1005 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1008 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1011 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1014 nla_put_u32(msg, RTA_TABLE, table);
1016 return system_rtnl_call(msg);
1019 int system_add_route(struct device *dev, struct device_route *route)
1021 return system_rt(dev, route, RTM_NEWROUTE);
1024 int system_del_route(struct device *dev, struct device_route *route)
1026 return system_rt(dev, route, RTM_DELROUTE);
1029 int system_flush_routes(void)
1031 const char *names[] = {
1032 "/proc/sys/net/ipv4/route/flush",
1033 "/proc/sys/net/ipv6/route/flush"
1037 for (i = 0; i < ARRAY_SIZE(names); i++) {
1038 fd = open(names[i], O_WRONLY);
1048 bool system_resolve_rt_table(const char *name, unsigned int *id)
1052 unsigned int n, table = RT_TABLE_UNSPEC;
1054 /* first try to parse table as number */
1055 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1058 /* handle well known aliases */
1059 else if (!strcmp(name, "default"))
1060 table = RT_TABLE_DEFAULT;
1061 else if (!strcmp(name, "main"))
1062 table = RT_TABLE_MAIN;
1063 else if (!strcmp(name, "local"))
1064 table = RT_TABLE_LOCAL;
1066 /* try to look up name in /etc/iproute2/rt_tables */
1067 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1069 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1071 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1074 n = strtoul(e, NULL, 10);
1075 e = strtok(NULL, " \t\n");
1077 if (e && !strcmp(e, name))
1087 if (table == RT_TABLE_UNSPEC)
1090 /* do not consider main table special */
1091 if (table == RT_TABLE_MAIN)
1092 table = RT_TABLE_UNSPEC;
1098 static int system_iprule(struct iprule *rule, int cmd)
1100 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1103 struct rtmsg rtm = {
1104 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1105 .rtm_protocol = RTPROT_STATIC,
1106 .rtm_scope = RT_SCOPE_UNIVERSE,
1107 .rtm_table = RT_TABLE_UNSPEC,
1108 .rtm_type = RTN_UNSPEC,
1112 if (cmd == RTM_NEWRULE) {
1113 rtm.rtm_type = RTN_UNICAST;
1114 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1118 rtm.rtm_flags |= FIB_RULE_INVERT;
1120 if (rule->flags & IPRULE_SRC)
1121 rtm.rtm_src_len = rule->src_mask;
1123 if (rule->flags & IPRULE_DEST)
1124 rtm.rtm_dst_len = rule->dest_mask;
1126 if (rule->flags & IPRULE_TOS)
1127 rtm.rtm_tos = rule->tos;
1129 if (rule->flags & IPRULE_LOOKUP) {
1130 if (rule->lookup < 256)
1131 rtm.rtm_table = rule->lookup;
1134 if (rule->flags & IPRULE_ACTION)
1135 rtm.rtm_type = rule->action;
1136 else if (rule->flags & IPRULE_GOTO)
1137 rtm.rtm_type = FR_ACT_GOTO;
1138 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1139 rtm.rtm_type = FR_ACT_NOP;
1141 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1146 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1148 if (rule->flags & IPRULE_IN)
1149 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1151 if (rule->flags & IPRULE_OUT)
1152 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1154 if (rule->flags & IPRULE_SRC)
1155 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1157 if (rule->flags & IPRULE_DEST)
1158 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1160 if (rule->flags & IPRULE_PRIORITY)
1161 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1162 else if (cmd == RTM_NEWRULE)
1163 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1165 if (rule->flags & IPRULE_FWMARK)
1166 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1168 if (rule->flags & IPRULE_FWMASK)
1169 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1171 if (rule->flags & IPRULE_LOOKUP) {
1172 if (rule->lookup >= 256)
1173 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1176 if (rule->flags & IPRULE_GOTO)
1177 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1179 return system_rtnl_call(msg);
1182 int system_add_iprule(struct iprule *rule)
1184 return system_iprule(rule, RTM_NEWRULE);
1187 int system_del_iprule(struct iprule *rule)
1189 return system_iprule(rule, RTM_DELRULE);
1192 int system_flush_iprules(void)
1197 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1198 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1200 memset(&rule, 0, sizeof(rule));
1203 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1206 rule.lookup = RT_TABLE_LOCAL;
1207 rv |= system_iprule(&rule, RTM_NEWRULE);
1209 rule.priority = 32766;
1210 rule.lookup = RT_TABLE_MAIN;
1211 rv |= system_iprule(&rule, RTM_NEWRULE);
1213 rule.priority = 32767;
1214 rule.lookup = RT_TABLE_DEFAULT;
1215 rv |= system_iprule(&rule, RTM_NEWRULE);
1218 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1221 rule.lookup = RT_TABLE_LOCAL;
1222 rv |= system_iprule(&rule, RTM_NEWRULE);
1224 rule.priority = 32766;
1225 rule.lookup = RT_TABLE_MAIN;
1226 rv |= system_iprule(&rule, RTM_NEWRULE);
1231 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1236 if (!strcmp(action, "local"))
1238 else if (!strcmp(action, "nat"))
1240 else if (!strcmp(action, "broadcast"))
1242 else if (!strcmp(action, "anycast"))
1244 else if (!strcmp(action, "multicast"))
1246 else if (!strcmp(action, "prohibit"))
1248 else if (!strcmp(action, "unreachable"))
1249 n = RTN_UNREACHABLE;
1250 else if (!strcmp(action, "blackhole"))
1252 else if (!strcmp(action, "xresolve"))
1254 else if (!strcmp(action, "unicast"))
1256 else if (!strcmp(action, "throw"))
1259 n = strtoul(action, &e, 0);
1260 if (!e || *e || e == action || n > 255)
1268 time_t system_get_rtime(void)
1273 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1276 if (gettimeofday(&tv, NULL) == 0)
1283 #define IP_DF 0x4000
1286 static int tunnel_ioctl(const char *name, int cmd, void *p)
1290 memset(&ifr, 0, sizeof(ifr));
1291 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1292 ifr.ifr_ifru.ifru_data = p;
1293 return ioctl(sock_ioctl, cmd, &ifr);
1296 int system_del_ip_tunnel(const char *name)
1298 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
1301 int system_update_ipv6_mtu(struct device *dev, int mtu)
1305 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
1308 int fd = open(buf, O_RDWR);
1309 ssize_t len = read(fd, buf, sizeof(buf) - 1);
1316 if (!mtu || ret <= mtu)
1319 lseek(fd, 0, SEEK_SET);
1320 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) <= 0)
1329 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
1331 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
1332 struct blob_attr *cur;
1335 system_del_ip_tunnel(name);
1337 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
1338 blob_data(attr), blob_len(attr));
1340 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
1342 str = blobmsg_data(cur);
1344 unsigned int ttl = 0;
1345 if ((cur = tb[TUNNEL_ATTR_TTL]) && (ttl = blobmsg_get_u32(cur)) > 255)
1348 unsigned int link = 0;
1349 if ((cur = tb[TUNNEL_ATTR_LINK])) {
1350 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
1354 if (iface->l3_dev.dev)
1355 link = iface->l3_dev.dev->ifindex;
1359 if (!strcmp(str, "sit")) {
1360 struct ip_tunnel_parm p = {
1365 .frag_off = htons(IP_DF),
1366 .protocol = IPPROTO_IPV6,
1371 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
1372 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
1375 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
1376 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
1379 strncpy(p.name, name, sizeof(p.name));
1380 if (tunnel_ioctl("sit0", SIOCADDTUNNEL, &p) < 0)
1384 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
1386 struct ip_tunnel_6rd p6;
1388 memset(&p6, 0, sizeof(p6));
1390 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
1391 &p6.prefix, &mask) || mask > 128)
1393 p6.prefixlen = mask;
1395 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
1396 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
1397 &p6.relay_prefix, &mask) || mask > 32)
1399 p6.relay_prefixlen = mask;
1402 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
1403 system_del_ip_tunnel(name);
1408 } else if (!strcmp(str, "ipip6")) {
1409 struct ip6_tnl_parm p = {
1411 .proto = IPPROTO_IPIP,
1412 .hop_limit = (ttl) ? ttl : 64,
1416 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
1417 inet_pton(AF_INET6, blobmsg_data(cur), &p.laddr) < 1)
1420 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
1421 inet_pton(AF_INET6, blobmsg_data(cur), &p.raddr) < 1)
1424 strncpy(p.name, name, sizeof(p.name));
1425 if (tunnel_ioctl("ip6tnl0", SIOCADDTUNNEL, &p) < 0)