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/ethtool.h>
36 #include <linux/fib_rules.h>
44 #include <netlink/msg.h>
45 #include <netlink/attr.h>
46 #include <netlink/socket.h>
47 #include <libubox/uloop.h>
54 struct uloop_fd uloop;
59 static int sock_ioctl = -1;
60 static struct nl_sock *sock_rtnl = NULL;
62 static int cb_rtnl_event(struct nl_msg *msg, void *arg);
63 static void handle_hotplug_event(struct uloop_fd *u, unsigned int events);
65 static char dev_buf[256];
68 handler_nl_event(struct uloop_fd *u, unsigned int events)
70 struct event_socket *ev = container_of(u, struct event_socket, uloop);
71 nl_recvmsgs(ev->sock, ev->cb);
74 static struct nl_sock *
75 create_socket(int protocol, int groups)
79 sock = nl_socket_alloc();
84 nl_join_groups(sock, groups);
86 if (nl_connect(sock, protocol))
93 create_raw_event_socket(struct event_socket *ev, int protocol, int groups,
96 ev->sock = create_socket(protocol, groups);
100 ev->uloop.fd = nl_socket_get_fd(ev->sock);
102 uloop_fd_add(&ev->uloop, ULOOP_READ | ULOOP_EDGE_TRIGGER);
107 create_event_socket(struct event_socket *ev, int protocol,
108 int (*cb)(struct nl_msg *msg, void *arg))
110 // Prepare socket for link events
111 ev->cb = nl_cb_alloc(NL_CB_DEFAULT);
115 nl_cb_set(ev->cb, NL_CB_VALID, NL_CB_CUSTOM, cb, NULL);
117 return create_raw_event_socket(ev, protocol, 0, handler_nl_event);
120 int system_init(void)
122 static struct event_socket rtnl_event;
123 static struct event_socket hotplug_event;
125 sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0);
126 fcntl(sock_ioctl, F_SETFD, fcntl(sock_ioctl, F_GETFD) | FD_CLOEXEC);
128 // Prepare socket for routing / address control
129 sock_rtnl = create_socket(NETLINK_ROUTE, 0);
133 if (!create_event_socket(&rtnl_event, NETLINK_ROUTE, cb_rtnl_event))
136 if (!create_raw_event_socket(&hotplug_event, NETLINK_KOBJECT_UEVENT, 1,
137 handle_hotplug_event))
140 // Receive network link events form kernel
141 nl_socket_add_membership(rtnl_event.sock, RTNLGRP_LINK);
146 static void system_set_sysctl(const char *path, const char *val)
150 fd = open(path, O_WRONLY);
154 write(fd, val, strlen(val));
158 static void system_set_dev_sysctl(const char *path, const char *device, const char *val)
160 snprintf(dev_buf, sizeof(dev_buf), path, device);
161 system_set_sysctl(dev_buf, val);
164 static void system_set_disable_ipv6(struct device *dev, const char *val)
166 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val);
169 // Evaluate netlink messages
170 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
172 struct nlmsghdr *nh = nlmsg_hdr(msg);
173 struct ifinfomsg *ifi = NLMSG_DATA(nh);
174 struct nlattr *nla[__IFLA_MAX];
176 if (nh->nlmsg_type != RTM_DELLINK && nh->nlmsg_type != RTM_NEWLINK)
179 nlmsg_parse(nh, sizeof(*ifi), nla, __IFLA_MAX - 1, NULL);
180 if (!nla[IFLA_IFNAME])
183 struct device *dev = device_get(RTA_DATA(nla[IFLA_IFNAME]), false);
187 dev->ifindex = ifi->ifi_index;
188 /* TODO: parse link status */
195 handle_hotplug_msg(char *data, int size)
197 const char *subsystem = NULL, *interface = NULL;
198 char *cur, *end, *sep;
203 if (!strncmp(data, "add@", 4))
205 else if (!strncmp(data, "remove@", 7))
210 skip = strlen(data) + 1;
213 for (cur = data + skip; cur < end; cur += skip) {
214 skip = strlen(cur) + 1;
216 sep = strchr(cur, '=');
221 if (!strcmp(cur, "INTERFACE"))
223 else if (!strcmp(cur, "SUBSYSTEM")) {
225 if (strcmp(subsystem, "net") != 0)
228 if (subsystem && interface)
234 dev = device_get(interface, false);
238 if (dev->type != &simple_device_type)
241 if (add && system_if_force_external(dev->ifname))
244 device_set_present(dev, add);
248 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
250 struct event_socket *ev = container_of(u, struct event_socket, uloop);
251 struct sockaddr_nl nla;
252 unsigned char *buf = NULL;
255 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
257 handle_hotplug_msg((char *) buf, size);
263 static int system_rtnl_call(struct nl_msg *msg)
267 ret = nl_send_auto_complete(sock_rtnl, msg);
273 return nl_wait_for_ack(sock_rtnl);
276 int system_bridge_delbr(struct device *bridge)
278 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
281 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
285 memset(&ifr, 0, sizeof(ifr));
287 ifr.ifr_ifindex = dev->ifindex;
290 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
291 return ioctl(sock_ioctl, cmd, &ifr);
294 static bool system_is_bridge(const char *name, char *buf, int buflen)
298 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
299 if (stat(buf, &st) < 0)
305 static char *system_get_bridge(const char *name, char *buf, int buflen)
311 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
312 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
315 if (gl.gl_pathc == 0)
318 len = readlink(gl.gl_pathv[0], buf, buflen);
323 path = strrchr(buf, '/');
330 int system_bridge_addif(struct device *bridge, struct device *dev)
334 system_set_disable_ipv6(dev, "1");
335 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
336 if (oldbr && !strcmp(oldbr, bridge->ifname))
339 return system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
342 int system_bridge_delif(struct device *bridge, struct device *dev)
344 system_set_disable_ipv6(dev, "0");
345 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
348 static int system_if_resolve(struct device *dev)
351 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
352 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
353 return ifr.ifr_ifindex;
358 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
362 memset(&ifr, 0, sizeof(ifr));
363 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
364 ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
365 ifr.ifr_flags |= add;
366 ifr.ifr_flags &= ~rem;
367 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
379 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
381 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
383 return ifa->ifa_index == ifindex;
386 static bool check_route(struct nlmsghdr *hdr, int ifindex)
388 struct rtmsg *r = NLMSG_DATA(hdr);
389 struct nlattr *tb[__RTA_MAX];
391 if (r->rtm_protocol == RTPROT_KERNEL &&
392 r->rtm_family == AF_INET6)
395 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
399 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
402 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
407 static int cb_clear_event(struct nl_msg *msg, void *arg)
409 struct clear_data *clr = arg;
410 struct nlmsghdr *hdr = nlmsg_hdr(msg);
411 bool (*cb)(struct nlmsghdr *, int ifindex);
417 if (hdr->nlmsg_type != RTM_NEWADDR)
424 if (hdr->nlmsg_type != RTM_NEWROUTE)
431 if (hdr->nlmsg_type != RTM_NEWRULE)
440 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
443 if (type == RTM_DELRULE)
444 D(SYSTEM, "Remove a rule\n");
446 D(SYSTEM, "Remove %s from device %s\n",
447 type == RTM_DELADDR ? "an address" : "a route",
449 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
450 hdr = nlmsg_hdr(clr->msg);
451 hdr->nlmsg_type = type;
452 hdr->nlmsg_flags = NLM_F_REQUEST;
454 if (!nl_send_auto_complete(sock_rtnl, clr->msg))
455 nl_wait_for_ack(sock_rtnl);
461 cb_finish_event(struct nl_msg *msg, void *arg)
469 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
472 *pending = err->error;
477 system_if_clear_entries(struct device *dev, int type, int af)
479 struct clear_data clr;
480 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
483 .rtm_flags = RTM_F_CLONED,
485 int flags = NLM_F_DUMP;
494 clr.size = sizeof(struct rtgenmsg);
497 clr.size = sizeof(struct rtmsg);
506 clr.msg = nlmsg_alloc_simple(type, flags);
510 nlmsg_append(clr.msg, &rtm, clr.size, 0);
511 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
512 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
513 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
515 nl_send_auto_complete(sock_rtnl, clr.msg);
517 nl_recvmsgs(sock_rtnl, cb);
525 * Clear bridge (membership) state and bring down device
527 void system_if_clear_state(struct device *dev)
529 static char buf[256];
535 dev->ifindex = system_if_resolve(dev);
539 system_if_flags(dev->ifname, 0, IFF_UP);
541 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
542 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
543 system_bridge_delbr(dev);
547 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
549 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
550 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
553 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
554 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
555 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
556 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
557 system_set_disable_ipv6(dev, "0");
560 static inline unsigned long
561 sec_to_jiffies(int val)
563 return (unsigned long) val * 100;
566 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
568 unsigned long args[4] = {};
570 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
573 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
574 args[1] = !!cfg->stp;
575 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
577 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
578 args[1] = sec_to_jiffies(cfg->forward_delay);
579 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
581 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
582 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
584 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
585 args[1] = cfg->priority;
586 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
588 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
589 args[0] = BRCTL_SET_AGEING_TIME;
590 args[1] = sec_to_jiffies(cfg->ageing_time);
591 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
594 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
595 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
596 args[1] = sec_to_jiffies(cfg->hello_time);
597 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
600 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
601 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
602 args[1] = sec_to_jiffies(cfg->max_age);
603 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
609 static int system_vlan(struct device *dev, int id)
611 struct vlan_ioctl_args ifr = {
612 .cmd = SET_VLAN_NAME_TYPE_CMD,
613 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
616 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
619 ifr.cmd = DEL_VLAN_CMD;
622 ifr.cmd = ADD_VLAN_CMD;
625 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
626 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
629 int system_vlan_add(struct device *dev, int id)
631 return system_vlan(dev, id);
634 int system_vlan_del(struct device *dev)
636 return system_vlan(dev, -1);
640 system_if_get_settings(struct device *dev, struct device_settings *s)
644 memset(&ifr, 0, sizeof(ifr));
645 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
647 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
648 s->mtu = ifr.ifr_mtu;
649 s->flags |= DEV_OPT_MTU;
652 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
653 s->txqueuelen = ifr.ifr_qlen;
654 s->flags |= DEV_OPT_TXQUEUELEN;
657 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
658 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
659 s->flags |= DEV_OPT_MACADDR;
664 system_if_apply_settings(struct device *dev, struct device_settings *s)
668 memset(&ifr, 0, sizeof(ifr));
669 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
670 if (s->flags & DEV_OPT_MTU) {
671 ifr.ifr_mtu = s->mtu;
672 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
673 s->flags &= ~DEV_OPT_MTU;
675 if (s->flags & DEV_OPT_TXQUEUELEN) {
676 ifr.ifr_qlen = s->txqueuelen;
677 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
678 s->flags &= ~DEV_OPT_TXQUEUELEN;
680 if ((s->flags & DEV_OPT_MACADDR) && !dev->external) {
681 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
682 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
683 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
684 s->flags &= ~DEV_OPT_MACADDR;
688 int system_if_up(struct device *dev)
690 system_if_get_settings(dev, &dev->orig_settings);
691 system_if_apply_settings(dev, &dev->settings);
692 dev->ifindex = system_if_resolve(dev);
693 return system_if_flags(dev->ifname, IFF_UP, 0);
696 int system_if_down(struct device *dev)
698 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
699 dev->orig_settings.flags &= dev->settings.flags;
700 system_if_apply_settings(dev, &dev->orig_settings);
704 int system_if_check(struct device *dev)
706 device_set_present(dev, (system_if_resolve(dev) > 0));
711 system_if_get_parent(struct device *dev)
713 char buf[64], *devname;
714 int ifindex, iflink, len;
717 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
722 len = fread(buf, 1, sizeof(buf) - 1, f);
729 iflink = strtoul(buf, NULL, 0);
730 ifindex = system_if_resolve(dev);
731 if (!iflink || iflink == ifindex)
734 devname = if_indextoname(iflink, buf);
738 return device_get(devname, true);
742 read_string_file(int dir_fd, const char *file, char *buf, int len)
748 fd = openat(dir_fd, file, O_RDONLY);
753 len = read(fd, buf, len - 1);
757 } else if (len > 0) {
760 c = strchr(buf, '\n');
773 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
778 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
780 *val = strtoull(buf, NULL, 0);
785 /* Assume advertised flags == supported flags */
786 static const struct {
789 } ethtool_link_modes[] = {
790 { ADVERTISED_10baseT_Half, "10H" },
791 { ADVERTISED_10baseT_Full, "10F" },
792 { ADVERTISED_100baseT_Half, "100H" },
793 { ADVERTISED_100baseT_Full, "100F" },
794 { ADVERTISED_1000baseT_Half, "1000H" },
795 { ADVERTISED_1000baseT_Full, "1000F" },
798 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
801 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
802 if (mask & ethtool_link_modes[i].mask)
803 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
808 system_if_force_external(const char *ifname)
813 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
814 return stat(buf, &s) == 0;
818 system_if_dump_info(struct device *dev, struct blob_buf *b)
820 struct ethtool_cmd ecmd;
827 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
828 dir_fd = open(buf, O_DIRECTORY);
830 if (read_uint64_file(dir_fd, "carrier", &val))
831 blobmsg_add_u8(b, "link", !!val);
833 memset(&ecmd, 0, sizeof(ecmd));
834 memset(&ifr, 0, sizeof(ifr));
835 strcpy(ifr.ifr_name, dev->ifname);
836 ifr.ifr_data = (caddr_t) &ecmd;
837 ecmd.cmd = ETHTOOL_GSET;
839 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
840 c = blobmsg_open_array(b, "link-advertising");
841 system_add_link_modes(b, ecmd.advertising);
842 blobmsg_close_array(b, c);
844 c = blobmsg_open_array(b, "link-supported");
845 system_add_link_modes(b, ecmd.supported);
846 blobmsg_close_array(b, c);
848 s = blobmsg_alloc_string_buffer(b, "speed", 8);
849 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
850 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
851 blobmsg_add_string_buffer(b);
859 system_if_dump_stats(struct device *dev, struct blob_buf *b)
861 const char *const counters[] = {
862 "collisions", "rx_frame_errors", "tx_compressed",
863 "multicast", "rx_length_errors", "tx_dropped",
864 "rx_bytes", "rx_missed_errors", "tx_errors",
865 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
866 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
867 "rx_dropped", "tx_aborted_errors", "tx_packets",
868 "rx_errors", "tx_bytes", "tx_window_errors",
869 "rx_fifo_errors", "tx_carrier_errors",
876 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
877 stats_dir = open(buf, O_DIRECTORY);
881 for (i = 0; i < ARRAY_SIZE(counters); i++)
882 if (read_uint64_file(stats_dir, counters[i], &val))
883 blobmsg_add_u64(b, counters[i], val);
889 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
891 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
892 int alen = v4 ? 4 : 16;
893 unsigned int flags = 0;
894 struct ifaddrmsg ifa = {
895 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
896 .ifa_prefixlen = addr->mask,
897 .ifa_index = dev->ifindex,
901 if (cmd == RTM_NEWADDR)
902 flags |= NLM_F_CREATE | NLM_F_REPLACE;
904 msg = nlmsg_alloc_simple(cmd, flags);
908 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
909 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
912 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
913 if (addr->point_to_point)
914 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
916 time_t now = system_get_rtime();
917 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
919 if (addr->preferred_until) {
920 int preferred = addr->preferred_until - now;
924 cinfo.ifa_prefered = preferred;
927 if (addr->valid_until) {
928 int valid = addr->valid_until - now;
932 cinfo.ifa_valid = valid;
935 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
938 return system_rtnl_call(msg);
941 int system_add_address(struct device *dev, struct device_addr *addr)
943 return system_addr(dev, addr, RTM_NEWADDR);
946 int system_del_address(struct device *dev, struct device_addr *addr)
948 return system_addr(dev, addr, RTM_DELADDR);
951 static int system_rt(struct device *dev, struct device_route *route, int cmd)
953 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
955 unsigned int flags = 0;
958 have_gw = !!route->nexthop.in.s_addr;
960 have_gw = route->nexthop.in6.s6_addr32[0] ||
961 route->nexthop.in6.s6_addr32[1] ||
962 route->nexthop.in6.s6_addr32[2] ||
963 route->nexthop.in6.s6_addr32[3];
965 unsigned char scope = (cmd == RTM_DELROUTE) ? RT_SCOPE_NOWHERE :
966 (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
968 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
969 ? route->table : RT_TABLE_MAIN;
972 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
973 .rtm_dst_len = route->mask,
974 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
975 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
977 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
981 if (cmd == RTM_NEWROUTE) {
982 flags |= NLM_F_CREATE | NLM_F_REPLACE;
984 if (!dev) { // Add null-route
985 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
986 rtm.rtm_type = RTN_UNREACHABLE;
990 msg = nlmsg_alloc_simple(cmd, flags);
994 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
997 nla_put(msg, RTA_DST, alen, &route->addr);
999 if (route->metric > 0)
1000 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1003 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1006 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1009 nla_put_u32(msg, RTA_TABLE, table);
1011 return system_rtnl_call(msg);
1014 int system_add_route(struct device *dev, struct device_route *route)
1016 return system_rt(dev, route, RTM_NEWROUTE);
1019 int system_del_route(struct device *dev, struct device_route *route)
1021 return system_rt(dev, route, RTM_DELROUTE);
1024 int system_flush_routes(void)
1026 const char *names[] = {
1027 "/proc/sys/net/ipv4/route/flush",
1028 "/proc/sys/net/ipv6/route/flush"
1032 for (i = 0; i < ARRAY_SIZE(names); i++) {
1033 fd = open(names[i], O_WRONLY);
1043 bool system_resolve_rt_table(const char *name, unsigned int *id)
1047 unsigned int n, table = RT_TABLE_UNSPEC;
1049 /* first try to parse table as number */
1050 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1053 /* handle well known aliases */
1054 else if (!strcmp(name, "default"))
1055 table = RT_TABLE_DEFAULT;
1056 else if (!strcmp(name, "main"))
1057 table = RT_TABLE_MAIN;
1058 else if (!strcmp(name, "local"))
1059 table = RT_TABLE_LOCAL;
1061 /* try to look up name in /etc/iproute2/rt_tables */
1062 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1064 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1066 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1069 n = strtoul(e, NULL, 10);
1070 e = strtok(NULL, " \t\n");
1072 if (e && !strcmp(e, name))
1082 if (table == RT_TABLE_UNSPEC)
1085 /* do not consider main table special */
1086 if (table == RT_TABLE_MAIN)
1087 table = RT_TABLE_UNSPEC;
1093 static int system_iprule(struct iprule *rule, int cmd)
1095 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1098 struct rtmsg rtm = {
1099 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1100 .rtm_protocol = RTPROT_STATIC,
1101 .rtm_scope = RT_SCOPE_UNIVERSE,
1102 .rtm_table = RT_TABLE_UNSPEC,
1103 .rtm_type = RTN_UNSPEC,
1107 if (cmd == RTM_NEWRULE) {
1108 rtm.rtm_type = RTN_UNICAST;
1109 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1113 rtm.rtm_flags |= FIB_RULE_INVERT;
1115 if (rule->flags & IPRULE_SRC)
1116 rtm.rtm_src_len = rule->src_mask;
1118 if (rule->flags & IPRULE_DEST)
1119 rtm.rtm_dst_len = rule->dest_mask;
1121 if (rule->flags & IPRULE_TOS)
1122 rtm.rtm_tos = rule->tos;
1124 if (rule->flags & IPRULE_LOOKUP) {
1125 if (rule->lookup < 256)
1126 rtm.rtm_table = rule->lookup;
1129 if (rule->flags & IPRULE_ACTION)
1130 rtm.rtm_type = rule->action;
1131 else if (rule->flags & IPRULE_GOTO)
1132 rtm.rtm_type = FR_ACT_GOTO;
1133 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1134 rtm.rtm_type = FR_ACT_NOP;
1136 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1141 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1143 if (rule->flags & IPRULE_IN)
1144 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1146 if (rule->flags & IPRULE_OUT)
1147 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1149 if (rule->flags & IPRULE_SRC)
1150 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1152 if (rule->flags & IPRULE_DEST)
1153 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1155 if (rule->flags & IPRULE_PRIORITY)
1156 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1157 else if (cmd == RTM_NEWRULE)
1158 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1160 if (rule->flags & IPRULE_FWMARK)
1161 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1163 if (rule->flags & IPRULE_FWMASK)
1164 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1166 if (rule->flags & IPRULE_LOOKUP) {
1167 if (rule->lookup >= 256)
1168 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1171 if (rule->flags & IPRULE_GOTO)
1172 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1174 return system_rtnl_call(msg);
1177 int system_add_iprule(struct iprule *rule)
1179 return system_iprule(rule, RTM_NEWRULE);
1182 int system_del_iprule(struct iprule *rule)
1184 return system_iprule(rule, RTM_DELRULE);
1187 int system_flush_iprules(void)
1192 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1193 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1195 memset(&rule, 0, sizeof(rule));
1198 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1201 rule.lookup = RT_TABLE_LOCAL;
1202 rv |= system_iprule(&rule, RTM_NEWRULE);
1204 rule.priority = 32766;
1205 rule.lookup = RT_TABLE_MAIN;
1206 rv |= system_iprule(&rule, RTM_NEWRULE);
1208 rule.priority = 32767;
1209 rule.lookup = RT_TABLE_DEFAULT;
1210 rv |= system_iprule(&rule, RTM_NEWRULE);
1213 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1216 rule.lookup = RT_TABLE_LOCAL;
1217 rv |= system_iprule(&rule, RTM_NEWRULE);
1219 rule.priority = 32766;
1220 rule.lookup = RT_TABLE_MAIN;
1221 rv |= system_iprule(&rule, RTM_NEWRULE);
1226 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1231 if (!strcmp(action, "local"))
1233 else if (!strcmp(action, "nat"))
1235 else if (!strcmp(action, "broadcast"))
1237 else if (!strcmp(action, "anycast"))
1239 else if (!strcmp(action, "multicast"))
1241 else if (!strcmp(action, "prohibit"))
1243 else if (!strcmp(action, "unreachable"))
1244 n = RTN_UNREACHABLE;
1245 else if (!strcmp(action, "blackhole"))
1247 else if (!strcmp(action, "xresolve"))
1249 else if (!strcmp(action, "unicast"))
1251 else if (!strcmp(action, "throw"))
1254 n = strtoul(action, &e, 0);
1255 if (!e || *e || e == action || n > 255)
1263 time_t system_get_rtime(void)
1268 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1271 if (gettimeofday(&tv, NULL) == 0)
1278 #define IP_DF 0x4000
1281 static void tunnel_parm_init(struct ip_tunnel_parm *p)
1283 memset(p, 0, sizeof(*p));
1286 p->iph.frag_off = htons(IP_DF);
1289 static int tunnel_ioctl(const char *name, int cmd, void *p)
1293 memset(&ifr, 0, sizeof(ifr));
1294 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1295 ifr.ifr_ifru.ifru_data = p;
1296 return ioctl(sock_ioctl, cmd, &ifr);
1299 int system_del_ip_tunnel(const char *name)
1301 struct ip_tunnel_parm p;
1303 tunnel_parm_init(&p);
1304 return tunnel_ioctl(name, SIOCDELTUNNEL, &p);
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)
1334 static int parse_ipaddr(struct blob_attr *attr, __be32 *addr)
1339 return inet_pton(AF_INET, blobmsg_data(attr), (void *) addr);
1343 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
1345 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
1346 struct blob_attr *cur;
1347 struct ip_tunnel_parm p;
1348 const char *base, *str;
1351 system_del_ip_tunnel(name);
1353 tunnel_parm_init(&p);
1355 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
1356 blob_data(attr), blob_len(attr));
1358 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
1360 str = blobmsg_data(cur);
1361 is_sit = !strcmp(str, "sit");
1364 p.iph.protocol = IPPROTO_IPV6;
1369 if (!parse_ipaddr(tb[TUNNEL_ATTR_LOCAL], &p.iph.saddr))
1372 if (!parse_ipaddr(tb[TUNNEL_ATTR_REMOTE], &p.iph.daddr))
1375 if ((cur = tb[TUNNEL_ATTR_TTL])) {
1376 unsigned int val = blobmsg_get_u32(cur);
1384 strncpy(p.name, name, sizeof(p.name));
1385 if (tunnel_ioctl(base, SIOCADDTUNNEL, &p) < 0)
1389 cur = tb[TUNNEL_ATTR_6RD_PREFIX];
1390 if (cur && is_sit) {
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);