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) ? route->table : RT_TABLE_MAIN;
971 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
972 .rtm_dst_len = route->mask,
973 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
974 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
976 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
980 if (cmd == RTM_NEWROUTE) {
981 flags |= NLM_F_CREATE | NLM_F_REPLACE;
983 if (!dev) { // Add null-route
984 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
985 rtm.rtm_type = RTN_UNREACHABLE;
989 msg = nlmsg_alloc_simple(cmd, flags);
993 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
996 nla_put(msg, RTA_DST, alen, &route->addr);
998 if (route->metric > 0)
999 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1002 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1005 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1008 nla_put_u32(msg, RTA_TABLE, table);
1010 return system_rtnl_call(msg);
1013 int system_add_route(struct device *dev, struct device_route *route)
1015 return system_rt(dev, route, RTM_NEWROUTE);
1018 int system_del_route(struct device *dev, struct device_route *route)
1020 return system_rt(dev, route, RTM_DELROUTE);
1023 int system_flush_routes(void)
1025 const char *names[] = {
1026 "/proc/sys/net/ipv4/route/flush",
1027 "/proc/sys/net/ipv6/route/flush"
1031 for (i = 0; i < ARRAY_SIZE(names); i++) {
1032 fd = open(names[i], O_WRONLY);
1042 bool system_resolve_rt_table(const char *name, unsigned int *id)
1046 unsigned int n, table = RT_TABLE_UNSPEC;
1048 /* first try to parse table as number */
1049 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1052 /* handle well known aliases */
1053 else if (!strcmp(name, "default"))
1054 table = RT_TABLE_DEFAULT;
1055 else if (!strcmp(name, "main"))
1056 table = RT_TABLE_MAIN;
1057 else if (!strcmp(name, "local"))
1058 table = RT_TABLE_LOCAL;
1060 /* try to look up name in /etc/iproute2/rt_tables */
1061 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1063 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1065 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1068 n = strtoul(e, NULL, 10);
1069 e = strtok(NULL, " \t\n");
1071 if (e && !strcmp(e, name))
1081 if (table == RT_TABLE_UNSPEC)
1084 /* do not consider main table special */
1085 if (table == RT_TABLE_MAIN)
1086 table = RT_TABLE_UNSPEC;
1092 static int system_iprule(struct iprule *rule, int cmd)
1094 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1097 struct rtmsg rtm = {
1098 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1099 .rtm_protocol = RTPROT_STATIC,
1100 .rtm_scope = RT_SCOPE_UNIVERSE,
1101 .rtm_table = RT_TABLE_UNSPEC,
1102 .rtm_type = RTN_UNSPEC,
1106 if (cmd == RTM_NEWRULE) {
1107 rtm.rtm_type = RTN_UNICAST;
1108 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1112 rtm.rtm_flags |= FIB_RULE_INVERT;
1114 if (rule->flags & IPRULE_SRC)
1115 rtm.rtm_src_len = rule->src_mask;
1117 if (rule->flags & IPRULE_DEST)
1118 rtm.rtm_dst_len = rule->dest_mask;
1120 if (rule->flags & IPRULE_TOS)
1121 rtm.rtm_tos = rule->tos;
1123 if (rule->flags & IPRULE_LOOKUP) {
1124 if (rule->lookup < 256)
1125 rtm.rtm_table = rule->lookup;
1128 if (rule->flags & IPRULE_ACTION)
1129 rtm.rtm_type = rule->action;
1130 else if (rule->flags & IPRULE_GOTO)
1131 rtm.rtm_type = FR_ACT_GOTO;
1132 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1133 rtm.rtm_type = FR_ACT_NOP;
1135 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1140 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1142 if (rule->flags & IPRULE_IN)
1143 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1145 if (rule->flags & IPRULE_OUT)
1146 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1148 if (rule->flags & IPRULE_SRC)
1149 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1151 if (rule->flags & IPRULE_DEST)
1152 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1154 if (rule->flags & IPRULE_PRIORITY)
1155 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1156 else if (cmd == RTM_NEWRULE)
1157 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1159 if (rule->flags & IPRULE_FWMARK)
1160 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1162 if (rule->flags & IPRULE_FWMASK)
1163 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1165 if (rule->flags & IPRULE_LOOKUP) {
1166 if (rule->lookup >= 256)
1167 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1170 if (rule->flags & IPRULE_GOTO)
1171 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1173 return system_rtnl_call(msg);
1176 int system_add_iprule(struct iprule *rule)
1178 return system_iprule(rule, RTM_NEWRULE);
1181 int system_del_iprule(struct iprule *rule)
1183 return system_iprule(rule, RTM_DELRULE);
1186 int system_flush_iprules(void)
1191 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1192 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1194 memset(&rule, 0, sizeof(rule));
1197 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1200 rule.lookup = RT_TABLE_LOCAL;
1201 rv |= system_iprule(&rule, RTM_NEWRULE);
1203 rule.priority = 32766;
1204 rule.lookup = RT_TABLE_MAIN;
1205 rv |= system_iprule(&rule, RTM_NEWRULE);
1207 rule.priority = 32767;
1208 rule.lookup = RT_TABLE_DEFAULT;
1209 rv |= system_iprule(&rule, RTM_NEWRULE);
1212 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1215 rule.lookup = RT_TABLE_LOCAL;
1216 rv |= system_iprule(&rule, RTM_NEWRULE);
1218 rule.priority = 32766;
1219 rule.lookup = RT_TABLE_MAIN;
1220 rv |= system_iprule(&rule, RTM_NEWRULE);
1225 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1230 if (!strcmp(action, "local"))
1232 else if (!strcmp(action, "nat"))
1234 else if (!strcmp(action, "broadcast"))
1236 else if (!strcmp(action, "anycast"))
1238 else if (!strcmp(action, "multicast"))
1240 else if (!strcmp(action, "prohibit"))
1242 else if (!strcmp(action, "unreachable"))
1243 n = RTN_UNREACHABLE;
1244 else if (!strcmp(action, "blackhole"))
1246 else if (!strcmp(action, "xresolve"))
1248 else if (!strcmp(action, "unicast"))
1250 else if (!strcmp(action, "throw"))
1253 n = strtoul(action, &e, 0);
1254 if (!e || *e || e == action || n > 255)
1262 time_t system_get_rtime(void)
1267 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1270 if (gettimeofday(&tv, NULL) == 0)
1277 #define IP_DF 0x4000
1280 static void tunnel_parm_init(struct ip_tunnel_parm *p)
1282 memset(p, 0, sizeof(*p));
1285 p->iph.frag_off = htons(IP_DF);
1288 static int tunnel_ioctl(const char *name, int cmd, void *p)
1292 memset(&ifr, 0, sizeof(ifr));
1293 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1294 ifr.ifr_ifru.ifru_data = p;
1295 return ioctl(sock_ioctl, cmd, &ifr);
1298 int system_del_ip_tunnel(const char *name)
1300 struct ip_tunnel_parm p;
1302 tunnel_parm_init(&p);
1303 return tunnel_ioctl(name, SIOCDELTUNNEL, &p);
1306 int system_update_ipv6_mtu(struct device *dev, int mtu)
1310 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
1313 int fd = open(buf, O_RDWR);
1314 ssize_t len = read(fd, buf, sizeof(buf) - 1);
1321 if (!mtu || ret <= mtu)
1324 lseek(fd, 0, SEEK_SET);
1325 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) <= 0)
1333 static int parse_ipaddr(struct blob_attr *attr, __be32 *addr)
1338 return inet_pton(AF_INET, blobmsg_data(attr), (void *) addr);
1342 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
1344 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
1345 struct blob_attr *cur;
1346 struct ip_tunnel_parm p;
1347 const char *base, *str;
1350 system_del_ip_tunnel(name);
1352 tunnel_parm_init(&p);
1354 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
1355 blob_data(attr), blob_len(attr));
1357 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
1359 str = blobmsg_data(cur);
1360 is_sit = !strcmp(str, "sit");
1363 p.iph.protocol = IPPROTO_IPV6;
1368 if (!parse_ipaddr(tb[TUNNEL_ATTR_LOCAL], &p.iph.saddr))
1371 if (!parse_ipaddr(tb[TUNNEL_ATTR_REMOTE], &p.iph.daddr))
1374 if ((cur = tb[TUNNEL_ATTR_TTL])) {
1375 unsigned int val = blobmsg_get_u32(cur);
1383 strncpy(p.name, name, sizeof(p.name));
1384 if (tunnel_ioctl(base, SIOCADDTUNNEL, &p) < 0)
1388 cur = tb[TUNNEL_ATTR_6RD_PREFIX];
1389 if (cur && is_sit) {
1391 struct ip_tunnel_6rd p6;
1393 memset(&p6, 0, sizeof(p6));
1395 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
1396 &p6.prefix, &mask) || mask > 128)
1398 p6.prefixlen = mask;
1400 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
1401 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
1402 &p6.relay_prefix, &mask) || mask > 32)
1404 p6.relay_prefixlen = mask;
1407 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
1408 system_del_ip_tunnel(name);