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];
68 static bool iprules_flushed = false;
71 handler_nl_event(struct uloop_fd *u, unsigned int events)
73 struct event_socket *ev = container_of(u, struct event_socket, uloop);
74 nl_recvmsgs(ev->sock, ev->cb);
77 static struct nl_sock *
78 create_socket(int protocol, int groups)
82 sock = nl_socket_alloc();
87 nl_join_groups(sock, groups);
89 if (nl_connect(sock, protocol))
96 create_raw_event_socket(struct event_socket *ev, int protocol, int groups,
99 ev->sock = create_socket(protocol, groups);
103 ev->uloop.fd = nl_socket_get_fd(ev->sock);
105 uloop_fd_add(&ev->uloop, ULOOP_READ | ULOOP_EDGE_TRIGGER);
110 create_event_socket(struct event_socket *ev, int protocol,
111 int (*cb)(struct nl_msg *msg, void *arg))
113 // Prepare socket for link events
114 ev->cb = nl_cb_alloc(NL_CB_DEFAULT);
118 nl_cb_set(ev->cb, NL_CB_VALID, NL_CB_CUSTOM, cb, NULL);
120 return create_raw_event_socket(ev, protocol, 0, handler_nl_event);
123 int system_init(void)
125 static struct event_socket rtnl_event;
126 static struct event_socket hotplug_event;
128 sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0);
129 fcntl(sock_ioctl, F_SETFD, fcntl(sock_ioctl, F_GETFD) | FD_CLOEXEC);
131 // Prepare socket for routing / address control
132 sock_rtnl = create_socket(NETLINK_ROUTE, 0);
136 if (!create_event_socket(&rtnl_event, NETLINK_ROUTE, cb_rtnl_event))
139 if (!create_raw_event_socket(&hotplug_event, NETLINK_KOBJECT_UEVENT, 1,
140 handle_hotplug_event))
143 // Receive network link events form kernel
144 nl_socket_add_membership(rtnl_event.sock, RTNLGRP_LINK);
149 static void system_set_sysctl(const char *path, const char *val)
153 fd = open(path, O_WRONLY);
157 write(fd, val, strlen(val));
161 static void system_set_dev_sysctl(const char *path, const char *device, const char *val)
163 snprintf(dev_buf, sizeof(dev_buf), path, device);
164 system_set_sysctl(dev_buf, val);
167 static void system_set_disable_ipv6(struct device *dev, const char *val)
169 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val);
172 // Evaluate netlink messages
173 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
175 struct nlmsghdr *nh = nlmsg_hdr(msg);
176 struct ifinfomsg *ifi = NLMSG_DATA(nh);
177 struct nlattr *nla[__IFLA_MAX];
179 if (nh->nlmsg_type != RTM_DELLINK && nh->nlmsg_type != RTM_NEWLINK)
182 nlmsg_parse(nh, sizeof(*ifi), nla, __IFLA_MAX - 1, NULL);
183 if (!nla[IFLA_IFNAME])
186 struct device *dev = device_get(RTA_DATA(nla[IFLA_IFNAME]), false);
190 dev->ifindex = ifi->ifi_index;
191 /* TODO: parse link status */
198 handle_hotplug_msg(char *data, int size)
200 const char *subsystem = NULL, *interface = NULL;
201 char *cur, *end, *sep;
206 if (!strncmp(data, "add@", 4))
208 else if (!strncmp(data, "remove@", 7))
213 skip = strlen(data) + 1;
216 for (cur = data + skip; cur < end; cur += skip) {
217 skip = strlen(cur) + 1;
219 sep = strchr(cur, '=');
224 if (!strcmp(cur, "INTERFACE"))
226 else if (!strcmp(cur, "SUBSYSTEM")) {
228 if (strcmp(subsystem, "net") != 0)
231 if (subsystem && interface)
237 dev = device_get(interface, false);
241 if (dev->type != &simple_device_type)
244 if (add && system_if_force_external(dev->ifname))
247 device_set_present(dev, add);
251 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
253 struct event_socket *ev = container_of(u, struct event_socket, uloop);
254 struct sockaddr_nl nla;
255 unsigned char *buf = NULL;
258 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
260 handle_hotplug_msg((char *) buf, size);
266 static int system_rtnl_call(struct nl_msg *msg)
270 ret = nl_send_auto_complete(sock_rtnl, msg);
276 return nl_wait_for_ack(sock_rtnl);
279 int system_bridge_delbr(struct device *bridge)
281 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
284 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
288 memset(&ifr, 0, sizeof(ifr));
290 ifr.ifr_ifindex = dev->ifindex;
293 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
294 return ioctl(sock_ioctl, cmd, &ifr);
297 static bool system_is_bridge(const char *name, char *buf, int buflen)
301 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
302 if (stat(buf, &st) < 0)
308 static char *system_get_bridge(const char *name, char *buf, int buflen)
314 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
315 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
318 if (gl.gl_pathc == 0)
321 len = readlink(gl.gl_pathv[0], buf, buflen);
326 path = strrchr(buf, '/');
333 int system_bridge_addif(struct device *bridge, struct device *dev)
337 system_set_disable_ipv6(dev, "1");
338 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
339 if (oldbr && !strcmp(oldbr, bridge->ifname))
342 return system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
345 int system_bridge_delif(struct device *bridge, struct device *dev)
347 system_set_disable_ipv6(dev, "0");
348 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
351 static int system_if_resolve(struct device *dev)
354 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
355 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
356 return ifr.ifr_ifindex;
361 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
365 memset(&ifr, 0, sizeof(ifr));
366 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
367 ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
368 ifr.ifr_flags |= add;
369 ifr.ifr_flags &= ~rem;
370 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
382 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
384 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
386 return ifa->ifa_index == ifindex;
389 static bool check_route(struct nlmsghdr *hdr, int ifindex)
391 struct rtmsg *r = NLMSG_DATA(hdr);
392 struct nlattr *tb[__RTA_MAX];
394 if (r->rtm_protocol == RTPROT_KERNEL &&
395 r->rtm_family == AF_INET6)
398 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
402 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
405 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
410 static int cb_clear_event(struct nl_msg *msg, void *arg)
412 struct clear_data *clr = arg;
413 struct nlmsghdr *hdr = nlmsg_hdr(msg);
414 bool (*cb)(struct nlmsghdr *, int ifindex);
420 if (hdr->nlmsg_type != RTM_NEWADDR)
427 if (hdr->nlmsg_type != RTM_NEWROUTE)
434 if (hdr->nlmsg_type != RTM_NEWRULE)
443 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
446 if (type == RTM_DELRULE)
447 D(SYSTEM, "Remove a rule\n");
449 D(SYSTEM, "Remove %s from device %s\n",
450 type == RTM_DELADDR ? "an address" : "a route",
452 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
453 hdr = nlmsg_hdr(clr->msg);
454 hdr->nlmsg_type = type;
455 hdr->nlmsg_flags = NLM_F_REQUEST;
457 if (!nl_send_auto_complete(sock_rtnl, clr->msg))
458 nl_wait_for_ack(sock_rtnl);
464 cb_finish_event(struct nl_msg *msg, void *arg)
472 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
475 *pending = err->error;
480 system_if_clear_entries(struct device *dev, int type, int af)
482 struct clear_data clr;
483 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
486 .rtm_flags = RTM_F_CLONED,
488 int flags = NLM_F_DUMP;
497 clr.size = sizeof(struct rtgenmsg);
500 clr.size = sizeof(struct rtmsg);
509 clr.msg = nlmsg_alloc_simple(type, flags);
513 nlmsg_append(clr.msg, &rtm, clr.size, 0);
514 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
515 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
516 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
518 nl_send_auto_complete(sock_rtnl, clr.msg);
520 nl_recvmsgs(sock_rtnl, cb);
528 * Clear bridge (membership) state and bring down device
530 void system_if_clear_state(struct device *dev)
532 static char buf[256];
538 dev->ifindex = system_if_resolve(dev);
542 system_if_flags(dev->ifname, 0, IFF_UP);
544 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
545 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
546 system_bridge_delbr(dev);
550 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
552 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
553 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
556 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
557 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
558 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
559 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
560 system_set_disable_ipv6(dev, "0");
563 static inline unsigned long
564 sec_to_jiffies(int val)
566 return (unsigned long) val * 100;
569 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
571 unsigned long args[4] = {};
573 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
576 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
577 args[1] = !!cfg->stp;
578 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
580 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
581 args[1] = sec_to_jiffies(cfg->forward_delay);
582 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
584 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
585 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
587 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
588 args[1] = cfg->priority;
589 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
591 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
592 args[0] = BRCTL_SET_AGEING_TIME;
593 args[1] = sec_to_jiffies(cfg->ageing_time);
594 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
597 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
598 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
599 args[1] = sec_to_jiffies(cfg->hello_time);
600 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
603 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
604 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
605 args[1] = sec_to_jiffies(cfg->max_age);
606 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
612 static int system_vlan(struct device *dev, int id)
614 struct vlan_ioctl_args ifr = {
615 .cmd = SET_VLAN_NAME_TYPE_CMD,
616 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
619 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
622 ifr.cmd = DEL_VLAN_CMD;
625 ifr.cmd = ADD_VLAN_CMD;
628 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
629 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
632 int system_vlan_add(struct device *dev, int id)
634 return system_vlan(dev, id);
637 int system_vlan_del(struct device *dev)
639 return system_vlan(dev, -1);
643 system_if_get_settings(struct device *dev, struct device_settings *s)
647 memset(&ifr, 0, sizeof(ifr));
648 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
650 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
651 s->mtu = ifr.ifr_mtu;
652 s->flags |= DEV_OPT_MTU;
655 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
656 s->txqueuelen = ifr.ifr_qlen;
657 s->flags |= DEV_OPT_TXQUEUELEN;
660 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
661 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
662 s->flags |= DEV_OPT_MACADDR;
667 system_if_apply_settings(struct device *dev, struct device_settings *s)
671 memset(&ifr, 0, sizeof(ifr));
672 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
673 if (s->flags & DEV_OPT_MTU) {
674 ifr.ifr_mtu = s->mtu;
675 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
676 s->flags &= ~DEV_OPT_MTU;
678 if (s->flags & DEV_OPT_TXQUEUELEN) {
679 ifr.ifr_qlen = s->txqueuelen;
680 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
681 s->flags &= ~DEV_OPT_TXQUEUELEN;
683 if ((s->flags & DEV_OPT_MACADDR) && !dev->external) {
684 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
685 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
686 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
687 s->flags &= ~DEV_OPT_MACADDR;
691 int system_if_up(struct device *dev)
693 system_if_get_settings(dev, &dev->orig_settings);
694 system_if_apply_settings(dev, &dev->settings);
695 dev->ifindex = system_if_resolve(dev);
696 return system_if_flags(dev->ifname, IFF_UP, 0);
699 int system_if_down(struct device *dev)
701 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
702 dev->orig_settings.flags &= dev->settings.flags;
703 system_if_apply_settings(dev, &dev->orig_settings);
707 int system_if_check(struct device *dev)
709 device_set_present(dev, (system_if_resolve(dev) > 0));
714 system_if_get_parent(struct device *dev)
716 char buf[64], *devname;
717 int ifindex, iflink, len;
720 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
725 len = fread(buf, 1, sizeof(buf) - 1, f);
732 iflink = strtoul(buf, NULL, 0);
733 ifindex = system_if_resolve(dev);
734 if (!iflink || iflink == ifindex)
737 devname = if_indextoname(iflink, buf);
741 return device_get(devname, true);
745 read_string_file(int dir_fd, const char *file, char *buf, int len)
751 fd = openat(dir_fd, file, O_RDONLY);
756 len = read(fd, buf, len - 1);
760 } else if (len > 0) {
763 c = strchr(buf, '\n');
776 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
781 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
783 *val = strtoull(buf, NULL, 0);
788 /* Assume advertised flags == supported flags */
789 static const struct {
792 } ethtool_link_modes[] = {
793 { ADVERTISED_10baseT_Half, "10H" },
794 { ADVERTISED_10baseT_Full, "10F" },
795 { ADVERTISED_100baseT_Half, "100H" },
796 { ADVERTISED_100baseT_Full, "100F" },
797 { ADVERTISED_1000baseT_Half, "1000H" },
798 { ADVERTISED_1000baseT_Full, "1000F" },
801 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
804 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
805 if (mask & ethtool_link_modes[i].mask)
806 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
811 system_if_force_external(const char *ifname)
816 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
817 return stat(buf, &s) == 0;
821 system_if_dump_info(struct device *dev, struct blob_buf *b)
823 struct ethtool_cmd ecmd;
830 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
831 dir_fd = open(buf, O_DIRECTORY);
833 if (read_uint64_file(dir_fd, "carrier", &val))
834 blobmsg_add_u8(b, "link", !!val);
836 memset(&ecmd, 0, sizeof(ecmd));
837 memset(&ifr, 0, sizeof(ifr));
838 strcpy(ifr.ifr_name, dev->ifname);
839 ifr.ifr_data = (caddr_t) &ecmd;
840 ecmd.cmd = ETHTOOL_GSET;
842 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
843 c = blobmsg_open_array(b, "link-advertising");
844 system_add_link_modes(b, ecmd.advertising);
845 blobmsg_close_array(b, c);
847 c = blobmsg_open_array(b, "link-supported");
848 system_add_link_modes(b, ecmd.supported);
849 blobmsg_close_array(b, c);
851 s = blobmsg_alloc_string_buffer(b, "speed", 8);
852 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
853 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
854 blobmsg_add_string_buffer(b);
862 system_if_dump_stats(struct device *dev, struct blob_buf *b)
864 const char *const counters[] = {
865 "collisions", "rx_frame_errors", "tx_compressed",
866 "multicast", "rx_length_errors", "tx_dropped",
867 "rx_bytes", "rx_missed_errors", "tx_errors",
868 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
869 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
870 "rx_dropped", "tx_aborted_errors", "tx_packets",
871 "rx_errors", "tx_bytes", "tx_window_errors",
872 "rx_fifo_errors", "tx_carrier_errors",
879 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
880 stats_dir = open(buf, O_DIRECTORY);
884 for (i = 0; i < ARRAY_SIZE(counters); i++)
885 if (read_uint64_file(stats_dir, counters[i], &val))
886 blobmsg_add_u64(b, counters[i], val);
892 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
894 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
895 int alen = v4 ? 4 : 16;
896 unsigned int flags = 0;
897 struct ifaddrmsg ifa = {
898 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
899 .ifa_prefixlen = addr->mask,
900 .ifa_index = dev->ifindex,
904 if (cmd == RTM_NEWADDR)
905 flags |= NLM_F_CREATE | NLM_F_REPLACE;
907 msg = nlmsg_alloc_simple(cmd, flags);
911 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
912 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
915 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
916 if (addr->point_to_point)
917 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
919 time_t now = system_get_rtime();
920 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
922 if (addr->preferred_until) {
923 int preferred = addr->preferred_until - now;
927 cinfo.ifa_prefered = preferred;
930 if (addr->valid_until) {
931 int valid = addr->valid_until - now;
935 cinfo.ifa_valid = valid;
938 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
941 return system_rtnl_call(msg);
944 int system_add_address(struct device *dev, struct device_addr *addr)
946 return system_addr(dev, addr, RTM_NEWADDR);
949 int system_del_address(struct device *dev, struct device_addr *addr)
951 return system_addr(dev, addr, RTM_DELADDR);
954 static int system_rt(struct device *dev, struct device_route *route, int cmd)
956 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
958 unsigned int flags = 0;
961 have_gw = !!route->nexthop.in.s_addr;
963 have_gw = route->nexthop.in6.s6_addr32[0] ||
964 route->nexthop.in6.s6_addr32[1] ||
965 route->nexthop.in6.s6_addr32[2] ||
966 route->nexthop.in6.s6_addr32[3];
968 unsigned char scope = (cmd == RTM_DELROUTE) ? RT_SCOPE_NOWHERE :
969 (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
971 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
972 ? route->table : RT_TABLE_MAIN;
975 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
976 .rtm_dst_len = route->mask,
977 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
978 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
980 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
984 if (cmd == RTM_NEWROUTE) {
985 flags |= NLM_F_CREATE | NLM_F_REPLACE;
987 if (!dev) { // Add null-route
988 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
989 rtm.rtm_type = RTN_UNREACHABLE;
993 msg = nlmsg_alloc_simple(cmd, flags);
997 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1000 nla_put(msg, RTA_DST, alen, &route->addr);
1002 if (route->metric > 0)
1003 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1006 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1009 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1012 nla_put_u32(msg, RTA_TABLE, table);
1014 return system_rtnl_call(msg);
1017 int system_add_route(struct device *dev, struct device_route *route)
1019 return system_rt(dev, route, RTM_NEWROUTE);
1022 int system_del_route(struct device *dev, struct device_route *route)
1024 return system_rt(dev, route, RTM_DELROUTE);
1027 int system_flush_routes(void)
1029 const char *names[] = {
1030 "/proc/sys/net/ipv4/route/flush",
1031 "/proc/sys/net/ipv6/route/flush"
1035 for (i = 0; i < ARRAY_SIZE(names); i++) {
1036 fd = open(names[i], O_WRONLY);
1046 bool system_resolve_rt_table(const char *name, unsigned int *id)
1050 unsigned int n, table = RT_TABLE_UNSPEC;
1052 /* first try to parse table as number */
1053 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1056 /* handle well known aliases */
1057 else if (!strcmp(name, "default"))
1058 table = RT_TABLE_DEFAULT;
1059 else if (!strcmp(name, "main"))
1060 table = RT_TABLE_MAIN;
1061 else if (!strcmp(name, "local"))
1062 table = RT_TABLE_LOCAL;
1064 /* try to look up name in /etc/iproute2/rt_tables */
1065 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1067 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1069 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1072 n = strtoul(e, NULL, 10);
1073 e = strtok(NULL, " \t\n");
1075 if (e && !strcmp(e, name))
1085 if (table == RT_TABLE_UNSPEC)
1088 /* do not consider main table special */
1089 if (table == RT_TABLE_MAIN)
1090 table = RT_TABLE_UNSPEC;
1096 static int system_iprule(struct iprule *rule, int cmd)
1098 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1101 struct rtmsg rtm = {
1102 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1103 .rtm_protocol = RTPROT_STATIC,
1104 .rtm_scope = RT_SCOPE_UNIVERSE,
1105 .rtm_table = RT_TABLE_UNSPEC,
1106 .rtm_type = RTN_UNSPEC,
1110 if (cmd == RTM_NEWRULE) {
1111 rtm.rtm_type = RTN_UNICAST;
1112 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1116 rtm.rtm_flags |= FIB_RULE_INVERT;
1118 if (rule->flags & IPRULE_SRC)
1119 rtm.rtm_src_len = rule->src_mask;
1121 if (rule->flags & IPRULE_DEST)
1122 rtm.rtm_dst_len = rule->dest_mask;
1124 if (rule->flags & IPRULE_TOS)
1125 rtm.rtm_tos = rule->tos;
1127 if (rule->flags & IPRULE_LOOKUP) {
1128 if (rule->lookup < 256)
1129 rtm.rtm_table = rule->lookup;
1132 if (rule->flags & IPRULE_ACTION)
1133 rtm.rtm_type = rule->action;
1134 else if (rule->flags & IPRULE_GOTO)
1135 rtm.rtm_type = FR_ACT_GOTO;
1136 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1137 rtm.rtm_type = FR_ACT_NOP;
1139 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1144 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1146 if (rule->flags & IPRULE_IN)
1147 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1149 if (rule->flags & IPRULE_OUT)
1150 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1152 if (rule->flags & IPRULE_SRC)
1153 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1155 if (rule->flags & IPRULE_DEST)
1156 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1158 if (rule->flags & IPRULE_PRIORITY)
1159 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1160 else if (cmd == RTM_NEWRULE)
1161 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1163 if (rule->flags & IPRULE_FWMARK)
1164 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1166 if (rule->flags & IPRULE_FWMASK)
1167 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1169 if (rule->flags & IPRULE_LOOKUP) {
1170 if (rule->lookup >= 256)
1171 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1174 if (rule->flags & IPRULE_GOTO)
1175 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1177 return system_rtnl_call(msg);
1180 int system_add_iprule(struct iprule *rule)
1182 /* trigger flush of existing rules when adding first rule the first time */
1183 if (!iprules_flushed)
1185 system_flush_iprules();
1186 iprules_flushed = true;
1189 return system_iprule(rule, RTM_NEWRULE);
1192 int system_del_iprule(struct iprule *rule)
1194 return system_iprule(rule, RTM_DELRULE);
1197 int system_flush_iprules(void)
1202 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1203 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1205 memset(&rule, 0, sizeof(rule));
1208 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1211 rule.lookup = RT_TABLE_LOCAL;
1212 rv |= system_iprule(&rule, RTM_NEWRULE);
1214 rule.priority = 32766;
1215 rule.lookup = RT_TABLE_MAIN;
1216 rv |= system_iprule(&rule, RTM_NEWRULE);
1218 rule.priority = 32767;
1219 rule.lookup = RT_TABLE_DEFAULT;
1220 rv |= system_iprule(&rule, RTM_NEWRULE);
1223 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1226 rule.lookup = RT_TABLE_LOCAL;
1227 rv |= system_iprule(&rule, RTM_NEWRULE);
1229 rule.priority = 32766;
1230 rule.lookup = RT_TABLE_MAIN;
1231 rv |= system_iprule(&rule, RTM_NEWRULE);
1236 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1241 if (!strcmp(action, "local"))
1243 else if (!strcmp(action, "nat"))
1245 else if (!strcmp(action, "broadcast"))
1247 else if (!strcmp(action, "anycast"))
1249 else if (!strcmp(action, "multicast"))
1251 else if (!strcmp(action, "prohibit"))
1253 else if (!strcmp(action, "unreachable"))
1254 n = RTN_UNREACHABLE;
1255 else if (!strcmp(action, "blackhole"))
1257 else if (!strcmp(action, "xresolve"))
1259 else if (!strcmp(action, "unicast"))
1261 else if (!strcmp(action, "throw"))
1264 n = strtoul(action, &e, 0);
1265 if (!e || *e || e == action || n > 255)
1273 time_t system_get_rtime(void)
1278 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1281 if (gettimeofday(&tv, NULL) == 0)
1288 #define IP_DF 0x4000
1291 static int tunnel_ioctl(const char *name, int cmd, void *p)
1295 memset(&ifr, 0, sizeof(ifr));
1296 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1297 ifr.ifr_ifru.ifru_data = p;
1298 return ioctl(sock_ioctl, cmd, &ifr);
1301 int system_del_ip_tunnel(const char *name)
1303 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
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)
1334 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
1336 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
1337 struct blob_attr *cur;
1340 system_del_ip_tunnel(name);
1342 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
1343 blob_data(attr), blob_len(attr));
1345 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
1347 str = blobmsg_data(cur);
1349 unsigned int ttl = 0;
1350 if ((cur = tb[TUNNEL_ATTR_TTL]) && (ttl = blobmsg_get_u32(cur)) > 255)
1353 unsigned int link = 0;
1354 if ((cur = tb[TUNNEL_ATTR_LINK])) {
1355 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
1359 if (iface->l3_dev.dev)
1360 link = iface->l3_dev.dev->ifindex;
1364 if (!strcmp(str, "sit")) {
1365 struct ip_tunnel_parm p = {
1370 .frag_off = htons(IP_DF),
1371 .protocol = IPPROTO_IPV6,
1376 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
1377 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
1380 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
1381 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
1384 strncpy(p.name, name, sizeof(p.name));
1385 if (tunnel_ioctl("sit0", SIOCADDTUNNEL, &p) < 0)
1389 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
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);
1413 } else if (!strcmp(str, "ipip6")) {
1414 struct ip6_tnl_parm p = {
1416 .proto = IPPROTO_IPIP,
1417 .hop_limit = (ttl) ? ttl : 64,
1421 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
1422 inet_pton(AF_INET6, blobmsg_data(cur), &p.laddr) < 1)
1425 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
1426 inet_pton(AF_INET6, blobmsg_data(cur), &p.raddr) < 1)
1429 strncpy(p.name, name, sizeof(p.name));
1430 if (tunnel_ioctl("ip6tnl0", SIOCADDTUNNEL, &p) < 0)