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 if (cfg->flags & BRIDGE_OPT_PRIORITY) {
585 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
586 args[1] = cfg->priority;
587 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
590 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
591 args[0] = BRCTL_SET_AGEING_TIME;
592 args[1] = sec_to_jiffies(cfg->ageing_time);
593 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
596 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
597 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
598 args[1] = sec_to_jiffies(cfg->hello_time);
599 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
602 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
603 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
604 args[1] = sec_to_jiffies(cfg->max_age);
605 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
611 static int system_vlan(struct device *dev, int id)
613 struct vlan_ioctl_args ifr = {
614 .cmd = SET_VLAN_NAME_TYPE_CMD,
615 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
618 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
621 ifr.cmd = DEL_VLAN_CMD;
624 ifr.cmd = ADD_VLAN_CMD;
627 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
628 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
631 int system_vlan_add(struct device *dev, int id)
633 return system_vlan(dev, id);
636 int system_vlan_del(struct device *dev)
638 return system_vlan(dev, -1);
642 system_if_get_settings(struct device *dev, struct device_settings *s)
646 memset(&ifr, 0, sizeof(ifr));
647 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
649 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
650 s->mtu = ifr.ifr_mtu;
651 s->flags |= DEV_OPT_MTU;
654 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
655 s->txqueuelen = ifr.ifr_qlen;
656 s->flags |= DEV_OPT_TXQUEUELEN;
659 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
660 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
661 s->flags |= DEV_OPT_MACADDR;
666 system_if_apply_settings(struct device *dev, struct device_settings *s)
670 memset(&ifr, 0, sizeof(ifr));
671 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
672 if (s->flags & DEV_OPT_MTU) {
673 ifr.ifr_mtu = s->mtu;
674 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
675 s->flags &= ~DEV_OPT_MTU;
677 if (s->flags & DEV_OPT_TXQUEUELEN) {
678 ifr.ifr_qlen = s->txqueuelen;
679 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
680 s->flags &= ~DEV_OPT_TXQUEUELEN;
682 if ((s->flags & DEV_OPT_MACADDR) && !dev->external) {
683 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
684 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
685 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
686 s->flags &= ~DEV_OPT_MACADDR;
690 int system_if_up(struct device *dev)
692 system_if_get_settings(dev, &dev->orig_settings);
693 system_if_apply_settings(dev, &dev->settings);
694 dev->ifindex = system_if_resolve(dev);
695 return system_if_flags(dev->ifname, IFF_UP, 0);
698 int system_if_down(struct device *dev)
700 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
701 dev->orig_settings.flags &= dev->settings.flags;
702 system_if_apply_settings(dev, &dev->orig_settings);
706 int system_if_check(struct device *dev)
708 device_set_present(dev, (system_if_resolve(dev) > 0));
713 system_if_get_parent(struct device *dev)
715 char buf[64], *devname;
716 int ifindex, iflink, len;
719 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
724 len = fread(buf, 1, sizeof(buf) - 1, f);
731 iflink = strtoul(buf, NULL, 0);
732 ifindex = system_if_resolve(dev);
733 if (!iflink || iflink == ifindex)
736 devname = if_indextoname(iflink, buf);
740 return device_get(devname, true);
744 read_string_file(int dir_fd, const char *file, char *buf, int len)
750 fd = openat(dir_fd, file, O_RDONLY);
755 len = read(fd, buf, len - 1);
759 } else if (len > 0) {
762 c = strchr(buf, '\n');
775 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
780 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
782 *val = strtoull(buf, NULL, 0);
787 /* Assume advertised flags == supported flags */
788 static const struct {
791 } ethtool_link_modes[] = {
792 { ADVERTISED_10baseT_Half, "10H" },
793 { ADVERTISED_10baseT_Full, "10F" },
794 { ADVERTISED_100baseT_Half, "100H" },
795 { ADVERTISED_100baseT_Full, "100F" },
796 { ADVERTISED_1000baseT_Half, "1000H" },
797 { ADVERTISED_1000baseT_Full, "1000F" },
800 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
803 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
804 if (mask & ethtool_link_modes[i].mask)
805 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
810 system_if_force_external(const char *ifname)
815 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
816 return stat(buf, &s) == 0;
820 system_if_dump_info(struct device *dev, struct blob_buf *b)
822 struct ethtool_cmd ecmd;
829 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
830 dir_fd = open(buf, O_DIRECTORY);
832 if (read_uint64_file(dir_fd, "carrier", &val))
833 blobmsg_add_u8(b, "link", !!val);
835 memset(&ecmd, 0, sizeof(ecmd));
836 memset(&ifr, 0, sizeof(ifr));
837 strcpy(ifr.ifr_name, dev->ifname);
838 ifr.ifr_data = (caddr_t) &ecmd;
839 ecmd.cmd = ETHTOOL_GSET;
841 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
842 c = blobmsg_open_array(b, "link-advertising");
843 system_add_link_modes(b, ecmd.advertising);
844 blobmsg_close_array(b, c);
846 c = blobmsg_open_array(b, "link-supported");
847 system_add_link_modes(b, ecmd.supported);
848 blobmsg_close_array(b, c);
850 s = blobmsg_alloc_string_buffer(b, "speed", 8);
851 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
852 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
853 blobmsg_add_string_buffer(b);
861 system_if_dump_stats(struct device *dev, struct blob_buf *b)
863 const char *const counters[] = {
864 "collisions", "rx_frame_errors", "tx_compressed",
865 "multicast", "rx_length_errors", "tx_dropped",
866 "rx_bytes", "rx_missed_errors", "tx_errors",
867 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
868 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
869 "rx_dropped", "tx_aborted_errors", "tx_packets",
870 "rx_errors", "tx_bytes", "tx_window_errors",
871 "rx_fifo_errors", "tx_carrier_errors",
878 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
879 stats_dir = open(buf, O_DIRECTORY);
883 for (i = 0; i < ARRAY_SIZE(counters); i++)
884 if (read_uint64_file(stats_dir, counters[i], &val))
885 blobmsg_add_u64(b, counters[i], val);
891 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
893 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
894 int alen = v4 ? 4 : 16;
895 unsigned int flags = 0;
896 struct ifaddrmsg ifa = {
897 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
898 .ifa_prefixlen = addr->mask,
899 .ifa_index = dev->ifindex,
903 if (cmd == RTM_NEWADDR)
904 flags |= NLM_F_CREATE | NLM_F_REPLACE;
906 msg = nlmsg_alloc_simple(cmd, flags);
910 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
911 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
914 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
915 if (addr->point_to_point)
916 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
918 time_t now = system_get_rtime();
919 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
921 if (addr->preferred_until) {
922 int preferred = addr->preferred_until - now;
926 cinfo.ifa_prefered = preferred;
929 if (addr->valid_until) {
930 int valid = addr->valid_until - now;
934 cinfo.ifa_valid = valid;
937 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
940 return system_rtnl_call(msg);
943 int system_add_address(struct device *dev, struct device_addr *addr)
945 return system_addr(dev, addr, RTM_NEWADDR);
948 int system_del_address(struct device *dev, struct device_addr *addr)
950 return system_addr(dev, addr, RTM_DELADDR);
953 static int system_rt(struct device *dev, struct device_route *route, int cmd)
955 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
957 unsigned int flags = 0;
960 have_gw = !!route->nexthop.in.s_addr;
962 have_gw = route->nexthop.in6.s6_addr32[0] ||
963 route->nexthop.in6.s6_addr32[1] ||
964 route->nexthop.in6.s6_addr32[2] ||
965 route->nexthop.in6.s6_addr32[3];
967 unsigned char scope = (cmd == RTM_DELROUTE) ? RT_SCOPE_NOWHERE :
968 (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
970 unsigned int table = (route->flags & DEVROUTE_TABLE) ? route->table : RT_TABLE_MAIN;
973 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
974 .rtm_dst_len = route->mask,
975 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
976 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
978 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
982 if (cmd == RTM_NEWROUTE) {
983 flags |= NLM_F_CREATE | NLM_F_REPLACE;
985 if (!dev) { // Add null-route
986 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
987 rtm.rtm_type = RTN_UNREACHABLE;
991 msg = nlmsg_alloc_simple(cmd, flags);
995 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
998 nla_put(msg, RTA_DST, alen, &route->addr);
1000 if (route->metric > 0)
1001 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1004 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1007 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1010 nla_put_u32(msg, RTA_TABLE, table);
1012 return system_rtnl_call(msg);
1015 int system_add_route(struct device *dev, struct device_route *route)
1017 return system_rt(dev, route, RTM_NEWROUTE);
1020 int system_del_route(struct device *dev, struct device_route *route)
1022 return system_rt(dev, route, RTM_DELROUTE);
1025 int system_flush_routes(void)
1027 const char *names[] = {
1028 "/proc/sys/net/ipv4/route/flush",
1029 "/proc/sys/net/ipv6/route/flush"
1033 for (i = 0; i < ARRAY_SIZE(names); i++) {
1034 fd = open(names[i], O_WRONLY);
1044 bool system_resolve_rt_table(const char *name, unsigned int *id)
1048 unsigned int n, table = RT_TABLE_UNSPEC;
1050 /* first try to parse table as number */
1051 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1054 /* handle well known aliases */
1055 else if (!strcmp(name, "default"))
1056 table = RT_TABLE_DEFAULT;
1057 else if (!strcmp(name, "main"))
1058 table = RT_TABLE_MAIN;
1059 else if (!strcmp(name, "local"))
1060 table = RT_TABLE_LOCAL;
1062 /* try to look up name in /etc/iproute2/rt_tables */
1063 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1065 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1067 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1070 n = strtoul(e, NULL, 10);
1071 e = strtok(NULL, " \t\n");
1073 if (e && !strcmp(e, name))
1083 if (table == RT_TABLE_UNSPEC)
1086 /* do not consider main table special */
1087 if (table == RT_TABLE_MAIN)
1088 table = RT_TABLE_UNSPEC;
1094 static int system_iprule(struct iprule *rule, int cmd)
1096 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1099 struct rtmsg rtm = {
1100 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1101 .rtm_protocol = RTPROT_STATIC,
1102 .rtm_scope = RT_SCOPE_UNIVERSE,
1103 .rtm_table = RT_TABLE_UNSPEC,
1104 .rtm_type = RTN_UNSPEC,
1108 if (cmd == RTM_NEWRULE) {
1109 rtm.rtm_type = RTN_UNICAST;
1110 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1114 rtm.rtm_flags |= FIB_RULE_INVERT;
1116 if (rule->flags & IPRULE_SRC)
1117 rtm.rtm_src_len = rule->src_mask;
1119 if (rule->flags & IPRULE_DEST)
1120 rtm.rtm_dst_len = rule->dest_mask;
1122 if (rule->flags & IPRULE_TOS)
1123 rtm.rtm_tos = rule->tos;
1125 if (rule->flags & IPRULE_LOOKUP) {
1126 if (rule->lookup < 256)
1127 rtm.rtm_table = rule->lookup;
1130 if (rule->flags & IPRULE_ACTION)
1131 rtm.rtm_type = rule->action;
1132 else if (rule->flags & IPRULE_GOTO)
1133 rtm.rtm_type = FR_ACT_GOTO;
1134 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1135 rtm.rtm_type = FR_ACT_NOP;
1137 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1142 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1144 if (rule->flags & IPRULE_IN)
1145 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1147 if (rule->flags & IPRULE_OUT)
1148 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1150 if (rule->flags & IPRULE_SRC)
1151 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1153 if (rule->flags & IPRULE_DEST)
1154 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1156 if (rule->flags & IPRULE_PRIORITY)
1157 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1158 else if (cmd == RTM_NEWRULE)
1159 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1161 if (rule->flags & IPRULE_FWMARK)
1162 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1164 if (rule->flags & IPRULE_FWMASK)
1165 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1167 if (rule->flags & IPRULE_LOOKUP) {
1168 if (rule->lookup >= 256)
1169 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1172 if (rule->flags & IPRULE_GOTO)
1173 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1175 return system_rtnl_call(msg);
1178 int system_add_iprule(struct iprule *rule)
1180 return system_iprule(rule, RTM_NEWRULE);
1183 int system_del_iprule(struct iprule *rule)
1185 return system_iprule(rule, RTM_DELRULE);
1188 int system_flush_iprules(void)
1193 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1194 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1196 memset(&rule, 0, sizeof(rule));
1199 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1202 rule.lookup = RT_TABLE_LOCAL;
1203 rv |= system_iprule(&rule, RTM_NEWRULE);
1205 rule.priority = 32766;
1206 rule.lookup = RT_TABLE_MAIN;
1207 rv |= system_iprule(&rule, RTM_NEWRULE);
1209 rule.priority = 32767;
1210 rule.lookup = RT_TABLE_DEFAULT;
1211 rv |= system_iprule(&rule, RTM_NEWRULE);
1214 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1217 rule.lookup = RT_TABLE_LOCAL;
1218 rv |= system_iprule(&rule, RTM_NEWRULE);
1220 rule.priority = 32766;
1221 rule.lookup = RT_TABLE_MAIN;
1222 rv |= system_iprule(&rule, RTM_NEWRULE);
1227 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1232 if (!strcmp(action, "local"))
1234 else if (!strcmp(action, "nat"))
1236 else if (!strcmp(action, "broadcast"))
1238 else if (!strcmp(action, "anycast"))
1240 else if (!strcmp(action, "multicast"))
1242 else if (!strcmp(action, "prohibit"))
1244 else if (!strcmp(action, "unreachable"))
1245 n = RTN_UNREACHABLE;
1246 else if (!strcmp(action, "blackhole"))
1248 else if (!strcmp(action, "xresolve"))
1250 else if (!strcmp(action, "unicast"))
1252 else if (!strcmp(action, "throw"))
1255 n = strtoul(action, &e, 0);
1256 if (!e || *e || e == action || n > 255)
1264 time_t system_get_rtime(void)
1269 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1272 if (gettimeofday(&tv, NULL) == 0)
1279 #define IP_DF 0x4000
1282 static void tunnel_parm_init(struct ip_tunnel_parm *p)
1284 memset(p, 0, sizeof(*p));
1287 p->iph.frag_off = htons(IP_DF);
1290 static int tunnel_ioctl(const char *name, int cmd, void *p)
1294 memset(&ifr, 0, sizeof(ifr));
1295 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1296 ifr.ifr_ifru.ifru_data = p;
1297 return ioctl(sock_ioctl, cmd, &ifr);
1300 int system_del_ip_tunnel(const char *name)
1302 struct ip_tunnel_parm p;
1304 tunnel_parm_init(&p);
1305 return tunnel_ioctl(name, SIOCDELTUNNEL, &p);
1308 int system_update_ipv6_mtu(struct device *dev, int mtu)
1312 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
1315 int fd = open(buf, O_RDWR);
1316 ssize_t len = read(fd, buf, sizeof(buf) - 1);
1323 if (!mtu || ret <= mtu)
1326 lseek(fd, 0, SEEK_SET);
1327 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) <= 0)
1335 static int parse_ipaddr(struct blob_attr *attr, __be32 *addr)
1340 return inet_pton(AF_INET, blobmsg_data(attr), (void *) addr);
1344 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
1346 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
1347 struct blob_attr *cur;
1348 struct ip_tunnel_parm p;
1349 const char *base, *str;
1352 system_del_ip_tunnel(name);
1354 tunnel_parm_init(&p);
1356 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
1357 blob_data(attr), blob_len(attr));
1359 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
1361 str = blobmsg_data(cur);
1362 is_sit = !strcmp(str, "sit");
1365 p.iph.protocol = IPPROTO_IPV6;
1370 if (!parse_ipaddr(tb[TUNNEL_ATTR_LOCAL], &p.iph.saddr))
1373 if (!parse_ipaddr(tb[TUNNEL_ATTR_REMOTE], &p.iph.daddr))
1376 if ((cur = tb[TUNNEL_ATTR_TTL])) {
1377 unsigned int val = blobmsg_get_u32(cur);
1385 strncpy(p.name, name, sizeof(p.name));
1386 if (tunnel_ioctl(base, SIOCADDTUNNEL, &p) < 0)
1390 cur = tb[TUNNEL_ATTR_6RD_PREFIX];
1391 if (cur && is_sit) {
1393 struct ip_tunnel_6rd p6;
1395 memset(&p6, 0, sizeof(p6));
1397 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
1398 &p6.prefix, &mask) || mask > 128)
1400 p6.prefixlen = mask;
1402 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
1403 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
1404 &p6.relay_prefix, &mask) || mask > 32)
1406 p6.relay_prefixlen = mask;
1409 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
1410 system_del_ip_tunnel(name);