2 * netifd - network interface daemon
3 * Copyright (C) 2012 Felix Fietkau <nbd@openwrt.org>
4 * Copyright (C) 2013 Jo-Philipp Wich <jow@openwrt.org>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2
8 * as published by the Free Software Foundation
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
17 #include <sys/socket.h>
18 #include <sys/ioctl.h>
20 #include <sys/syscall.h>
23 #include <net/if_arp.h>
25 #include <arpa/inet.h>
26 #include <netinet/in.h>
28 #include <linux/rtnetlink.h>
29 #include <linux/sockios.h>
31 #include <linux/if_vlan.h>
32 #include <linux/if_bridge.h>
33 #include <linux/if_tunnel.h>
34 #include <linux/ethtool.h>
35 #include <linux/fib_rules.h>
43 #include <netlink/msg.h>
44 #include <netlink/attr.h>
45 #include <netlink/socket.h>
46 #include <libubox/uloop.h>
53 struct uloop_fd uloop;
58 static int sock_ioctl = -1;
59 static struct nl_sock *sock_rtnl = NULL;
61 static int cb_rtnl_event(struct nl_msg *msg, void *arg);
62 static void handle_hotplug_event(struct uloop_fd *u, unsigned int events);
64 static char dev_buf[256];
67 handler_nl_event(struct uloop_fd *u, unsigned int events)
69 struct event_socket *ev = container_of(u, struct event_socket, uloop);
70 nl_recvmsgs(ev->sock, ev->cb);
73 static struct nl_sock *
74 create_socket(int protocol, int groups)
78 sock = nl_socket_alloc();
83 nl_join_groups(sock, groups);
85 if (nl_connect(sock, protocol))
92 create_raw_event_socket(struct event_socket *ev, int protocol, int groups,
95 ev->sock = create_socket(protocol, groups);
99 ev->uloop.fd = nl_socket_get_fd(ev->sock);
101 uloop_fd_add(&ev->uloop, ULOOP_READ | ULOOP_EDGE_TRIGGER);
106 create_event_socket(struct event_socket *ev, int protocol,
107 int (*cb)(struct nl_msg *msg, void *arg))
109 // Prepare socket for link events
110 ev->cb = nl_cb_alloc(NL_CB_DEFAULT);
114 nl_cb_set(ev->cb, NL_CB_VALID, NL_CB_CUSTOM, cb, NULL);
116 return create_raw_event_socket(ev, protocol, 0, handler_nl_event);
119 int system_init(void)
121 static struct event_socket rtnl_event;
122 static struct event_socket hotplug_event;
124 sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0);
125 fcntl(sock_ioctl, F_SETFD, fcntl(sock_ioctl, F_GETFD) | FD_CLOEXEC);
127 // Prepare socket for routing / address control
128 sock_rtnl = create_socket(NETLINK_ROUTE, 0);
132 if (!create_event_socket(&rtnl_event, NETLINK_ROUTE, cb_rtnl_event))
135 if (!create_raw_event_socket(&hotplug_event, NETLINK_KOBJECT_UEVENT, 1,
136 handle_hotplug_event))
139 // Receive network link events form kernel
140 nl_socket_add_membership(rtnl_event.sock, RTNLGRP_LINK);
145 static void system_set_sysctl(const char *path, const char *val)
149 fd = open(path, O_WRONLY);
153 write(fd, val, strlen(val));
157 static void system_set_dev_sysctl(const char *path, const char *device, const char *val)
159 snprintf(dev_buf, sizeof(dev_buf), path, device);
160 system_set_sysctl(dev_buf, val);
163 static void system_set_disable_ipv6(struct device *dev, const char *val)
165 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val);
168 // Evaluate netlink messages
169 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
171 struct nlmsghdr *nh = nlmsg_hdr(msg);
172 struct ifinfomsg *ifi = NLMSG_DATA(nh);
173 struct nlattr *nla[__IFLA_MAX];
175 if (nh->nlmsg_type != RTM_DELLINK && nh->nlmsg_type != RTM_NEWLINK)
178 nlmsg_parse(nh, sizeof(*ifi), nla, __IFLA_MAX - 1, NULL);
179 if (!nla[IFLA_IFNAME])
182 struct device *dev = device_get(RTA_DATA(nla[IFLA_IFNAME]), false);
186 dev->ifindex = ifi->ifi_index;
187 /* TODO: parse link status */
194 handle_hotplug_msg(char *data, int size)
196 const char *subsystem = NULL, *interface = NULL;
197 char *cur, *end, *sep;
202 if (!strncmp(data, "add@", 4))
204 else if (!strncmp(data, "remove@", 7))
209 skip = strlen(data) + 1;
212 for (cur = data + skip; cur < end; cur += skip) {
213 skip = strlen(cur) + 1;
215 sep = strchr(cur, '=');
220 if (!strcmp(cur, "INTERFACE"))
222 else if (!strcmp(cur, "SUBSYSTEM")) {
224 if (strcmp(subsystem, "net") != 0)
227 if (subsystem && interface)
233 dev = device_get(interface, false);
237 if (dev->type != &simple_device_type)
240 if (add && system_if_force_external(dev->ifname))
243 device_set_present(dev, add);
247 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
249 struct event_socket *ev = container_of(u, struct event_socket, uloop);
250 struct sockaddr_nl nla;
251 unsigned char *buf = NULL;
254 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
256 handle_hotplug_msg((char *) buf, size);
262 static int system_rtnl_call(struct nl_msg *msg)
266 ret = nl_send_auto_complete(sock_rtnl, msg);
272 return nl_wait_for_ack(sock_rtnl);
275 int system_bridge_delbr(struct device *bridge)
277 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
280 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
284 memset(&ifr, 0, sizeof(ifr));
286 ifr.ifr_ifindex = dev->ifindex;
289 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
290 return ioctl(sock_ioctl, cmd, &ifr);
293 static bool system_is_bridge(const char *name, char *buf, int buflen)
297 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
298 if (stat(buf, &st) < 0)
304 static char *system_get_bridge(const char *name, char *buf, int buflen)
310 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
311 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
314 if (gl.gl_pathc == 0)
317 len = readlink(gl.gl_pathv[0], buf, buflen);
322 path = strrchr(buf, '/');
329 int system_bridge_addif(struct device *bridge, struct device *dev)
333 system_set_disable_ipv6(dev, "1");
334 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
335 if (oldbr && !strcmp(oldbr, bridge->ifname))
338 return system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
341 int system_bridge_delif(struct device *bridge, struct device *dev)
343 system_set_disable_ipv6(dev, "0");
344 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
347 static int system_if_resolve(struct device *dev)
350 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
351 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
352 return ifr.ifr_ifindex;
357 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
361 memset(&ifr, 0, sizeof(ifr));
362 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
363 ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
364 ifr.ifr_flags |= add;
365 ifr.ifr_flags &= ~rem;
366 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
378 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
380 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
382 return ifa->ifa_index == ifindex;
385 static bool check_route(struct nlmsghdr *hdr, int ifindex)
387 struct rtmsg *r = NLMSG_DATA(hdr);
388 struct nlattr *tb[__RTA_MAX];
390 if (r->rtm_protocol == RTPROT_KERNEL &&
391 r->rtm_family == AF_INET6)
394 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
398 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
401 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
406 static int cb_clear_event(struct nl_msg *msg, void *arg)
408 struct clear_data *clr = arg;
409 struct nlmsghdr *hdr = nlmsg_hdr(msg);
410 bool (*cb)(struct nlmsghdr *, int ifindex);
416 if (hdr->nlmsg_type != RTM_NEWADDR)
423 if (hdr->nlmsg_type != RTM_NEWROUTE)
430 if (hdr->nlmsg_type != RTM_NEWRULE)
439 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
442 if (type == RTM_DELRULE)
443 D(SYSTEM, "Remove a rule\n");
445 D(SYSTEM, "Remove %s from device %s\n",
446 type == RTM_DELADDR ? "an address" : "a route",
448 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
449 hdr = nlmsg_hdr(clr->msg);
450 hdr->nlmsg_type = type;
451 hdr->nlmsg_flags = NLM_F_REQUEST;
453 if (!nl_send_auto_complete(sock_rtnl, clr->msg))
454 nl_wait_for_ack(sock_rtnl);
460 cb_finish_event(struct nl_msg *msg, void *arg)
468 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
471 *pending = err->error;
476 system_if_clear_entries(struct device *dev, int type, int af)
478 struct clear_data clr;
479 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
482 .rtm_flags = RTM_F_CLONED,
484 int flags = NLM_F_DUMP;
493 clr.size = sizeof(struct rtgenmsg);
496 clr.size = sizeof(struct rtmsg);
505 clr.msg = nlmsg_alloc_simple(type, flags);
509 nlmsg_append(clr.msg, &rtm, clr.size, 0);
510 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
511 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
512 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
514 nl_send_auto_complete(sock_rtnl, clr.msg);
516 nl_recvmsgs(sock_rtnl, cb);
524 * Clear bridge (membership) state and bring down device
526 void system_if_clear_state(struct device *dev)
528 static char buf[256];
534 dev->ifindex = system_if_resolve(dev);
538 system_if_flags(dev->ifname, 0, IFF_UP);
540 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
541 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
542 system_bridge_delbr(dev);
546 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
548 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
549 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
552 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
553 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
554 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
555 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
556 system_set_disable_ipv6(dev, "0");
559 static inline unsigned long
560 sec_to_jiffies(int val)
562 return (unsigned long) val * 100;
565 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
567 unsigned long args[4] = {};
569 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
572 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
573 args[1] = !!cfg->stp;
574 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
576 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
577 args[1] = sec_to_jiffies(cfg->forward_delay);
578 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
580 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
581 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
583 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
584 args[0] = BRCTL_SET_AGEING_TIME;
585 args[1] = sec_to_jiffies(cfg->ageing_time);
586 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
589 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
590 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
591 args[1] = sec_to_jiffies(cfg->hello_time);
592 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
595 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
596 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
597 args[1] = sec_to_jiffies(cfg->max_age);
598 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
604 static int system_vlan(struct device *dev, int id)
606 struct vlan_ioctl_args ifr = {
607 .cmd = SET_VLAN_NAME_TYPE_CMD,
608 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
611 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
614 ifr.cmd = DEL_VLAN_CMD;
617 ifr.cmd = ADD_VLAN_CMD;
620 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
621 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
624 int system_vlan_add(struct device *dev, int id)
626 return system_vlan(dev, id);
629 int system_vlan_del(struct device *dev)
631 return system_vlan(dev, -1);
635 system_if_get_settings(struct device *dev, struct device_settings *s)
639 memset(&ifr, 0, sizeof(ifr));
640 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
642 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
643 s->mtu = ifr.ifr_mtu;
644 s->flags |= DEV_OPT_MTU;
647 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
648 s->txqueuelen = ifr.ifr_qlen;
649 s->flags |= DEV_OPT_TXQUEUELEN;
652 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
653 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
654 s->flags |= DEV_OPT_MACADDR;
659 system_if_apply_settings(struct device *dev, struct device_settings *s)
663 memset(&ifr, 0, sizeof(ifr));
664 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
665 if (s->flags & DEV_OPT_MTU) {
666 ifr.ifr_mtu = s->mtu;
667 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
668 s->flags &= ~DEV_OPT_MTU;
670 if (s->flags & DEV_OPT_TXQUEUELEN) {
671 ifr.ifr_qlen = s->txqueuelen;
672 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
673 s->flags &= ~DEV_OPT_TXQUEUELEN;
675 if ((s->flags & DEV_OPT_MACADDR) && !dev->external) {
676 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
677 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
678 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
679 s->flags &= ~DEV_OPT_MACADDR;
683 int system_if_up(struct device *dev)
685 system_if_get_settings(dev, &dev->orig_settings);
686 system_if_apply_settings(dev, &dev->settings);
687 dev->ifindex = system_if_resolve(dev);
688 return system_if_flags(dev->ifname, IFF_UP, 0);
691 int system_if_down(struct device *dev)
693 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
694 dev->orig_settings.flags &= dev->settings.flags;
695 system_if_apply_settings(dev, &dev->orig_settings);
699 int system_if_check(struct device *dev)
701 device_set_present(dev, (system_if_resolve(dev) > 0));
706 system_if_get_parent(struct device *dev)
708 char buf[64], *devname;
709 int ifindex, iflink, len;
712 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
717 len = fread(buf, 1, sizeof(buf) - 1, f);
724 iflink = strtoul(buf, NULL, 0);
725 ifindex = system_if_resolve(dev);
726 if (!iflink || iflink == ifindex)
729 devname = if_indextoname(iflink, buf);
733 return device_get(devname, true);
737 read_string_file(int dir_fd, const char *file, char *buf, int len)
743 fd = openat(dir_fd, file, O_RDONLY);
748 len = read(fd, buf, len - 1);
752 } else if (len > 0) {
755 c = strchr(buf, '\n');
768 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
773 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
775 *val = strtoull(buf, NULL, 0);
780 /* Assume advertised flags == supported flags */
781 static const struct {
784 } ethtool_link_modes[] = {
785 { ADVERTISED_10baseT_Half, "10H" },
786 { ADVERTISED_10baseT_Full, "10F" },
787 { ADVERTISED_100baseT_Half, "100H" },
788 { ADVERTISED_100baseT_Full, "100F" },
789 { ADVERTISED_1000baseT_Half, "1000H" },
790 { ADVERTISED_1000baseT_Full, "1000F" },
793 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
796 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
797 if (mask & ethtool_link_modes[i].mask)
798 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
803 system_if_force_external(const char *ifname)
808 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
809 return stat(buf, &s) == 0;
813 system_if_dump_info(struct device *dev, struct blob_buf *b)
815 struct ethtool_cmd ecmd;
822 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
823 dir_fd = open(buf, O_DIRECTORY);
825 if (read_uint64_file(dir_fd, "carrier", &val))
826 blobmsg_add_u8(b, "link", !!val);
828 memset(&ecmd, 0, sizeof(ecmd));
829 memset(&ifr, 0, sizeof(ifr));
830 strcpy(ifr.ifr_name, dev->ifname);
831 ifr.ifr_data = (caddr_t) &ecmd;
832 ecmd.cmd = ETHTOOL_GSET;
834 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
835 c = blobmsg_open_array(b, "link-advertising");
836 system_add_link_modes(b, ecmd.advertising);
837 blobmsg_close_array(b, c);
839 c = blobmsg_open_array(b, "link-supported");
840 system_add_link_modes(b, ecmd.supported);
841 blobmsg_close_array(b, c);
843 s = blobmsg_alloc_string_buffer(b, "speed", 8);
844 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
845 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
846 blobmsg_add_string_buffer(b);
854 system_if_dump_stats(struct device *dev, struct blob_buf *b)
856 const char *const counters[] = {
857 "collisions", "rx_frame_errors", "tx_compressed",
858 "multicast", "rx_length_errors", "tx_dropped",
859 "rx_bytes", "rx_missed_errors", "tx_errors",
860 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
861 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
862 "rx_dropped", "tx_aborted_errors", "tx_packets",
863 "rx_errors", "tx_bytes", "tx_window_errors",
864 "rx_fifo_errors", "tx_carrier_errors",
871 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
872 stats_dir = open(buf, O_DIRECTORY);
876 for (i = 0; i < ARRAY_SIZE(counters); i++)
877 if (read_uint64_file(stats_dir, counters[i], &val))
878 blobmsg_add_u64(b, counters[i], val);
884 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
886 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
887 int alen = v4 ? 4 : 16;
888 unsigned int flags = 0;
889 struct ifaddrmsg ifa = {
890 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
891 .ifa_prefixlen = addr->mask,
892 .ifa_index = dev->ifindex,
896 if (cmd == RTM_NEWADDR)
897 flags |= NLM_F_CREATE | NLM_F_REPLACE;
899 msg = nlmsg_alloc_simple(cmd, flags);
903 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
904 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
907 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
908 if (addr->point_to_point)
909 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
911 time_t now = system_get_rtime();
912 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
914 if (addr->preferred_until) {
915 int preferred = addr->preferred_until - now;
919 cinfo.ifa_prefered = preferred;
922 if (addr->valid_until) {
923 int valid = addr->valid_until - now;
927 cinfo.ifa_valid = valid;
930 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
933 return system_rtnl_call(msg);
936 int system_add_address(struct device *dev, struct device_addr *addr)
938 return system_addr(dev, addr, RTM_NEWADDR);
941 int system_del_address(struct device *dev, struct device_addr *addr)
943 return system_addr(dev, addr, RTM_DELADDR);
946 static int system_rt(struct device *dev, struct device_route *route, int cmd)
948 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
950 unsigned int flags = 0;
953 have_gw = !!route->nexthop.in.s_addr;
955 have_gw = route->nexthop.in6.s6_addr32[0] ||
956 route->nexthop.in6.s6_addr32[1] ||
957 route->nexthop.in6.s6_addr32[2] ||
958 route->nexthop.in6.s6_addr32[3];
960 unsigned char scope = (cmd == RTM_DELROUTE) ? RT_SCOPE_NOWHERE :
961 (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
963 unsigned int table = (route->flags & DEVROUTE_TABLE) ? route->table : RT_TABLE_MAIN;
966 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
967 .rtm_dst_len = route->mask,
968 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
969 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
971 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
975 if (cmd == RTM_NEWROUTE) {
976 flags |= NLM_F_CREATE | NLM_F_REPLACE;
978 if (!dev) { // Add null-route
979 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
980 rtm.rtm_type = RTN_UNREACHABLE;
984 msg = nlmsg_alloc_simple(cmd, flags);
988 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
991 nla_put(msg, RTA_DST, alen, &route->addr);
993 if (route->metric > 0)
994 nla_put_u32(msg, RTA_PRIORITY, route->metric);
997 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1000 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1003 nla_put_u32(msg, RTA_TABLE, table);
1005 return system_rtnl_call(msg);
1008 int system_add_route(struct device *dev, struct device_route *route)
1010 return system_rt(dev, route, RTM_NEWROUTE);
1013 int system_del_route(struct device *dev, struct device_route *route)
1015 return system_rt(dev, route, RTM_DELROUTE);
1018 int system_flush_routes(void)
1020 const char *names[] = {
1021 "/proc/sys/net/ipv4/route/flush",
1022 "/proc/sys/net/ipv6/route/flush"
1026 for (i = 0; i < ARRAY_SIZE(names); i++) {
1027 fd = open(names[i], O_WRONLY);
1037 bool system_resolve_rt_table(const char *name, unsigned int *id)
1041 unsigned int n, table = RT_TABLE_UNSPEC;
1043 /* first try to parse table as number */
1044 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1047 /* handle well known aliases */
1048 else if (!strcmp(name, "default"))
1049 table = RT_TABLE_DEFAULT;
1050 else if (!strcmp(name, "main"))
1051 table = RT_TABLE_MAIN;
1052 else if (!strcmp(name, "local"))
1053 table = RT_TABLE_LOCAL;
1055 /* try to look up name in /etc/iproute2/rt_tables */
1056 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1058 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1060 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1063 n = strtoul(e, NULL, 10);
1064 e = strtok(NULL, " \t\n");
1066 if (e && !strcmp(e, name))
1076 if (table == RT_TABLE_UNSPEC)
1079 /* do not consider main table special */
1080 if (table == RT_TABLE_MAIN)
1081 table = RT_TABLE_UNSPEC;
1087 static int system_iprule(struct iprule *rule, int cmd)
1089 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1092 struct rtmsg rtm = {
1093 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1094 .rtm_protocol = RTPROT_STATIC,
1095 .rtm_scope = RT_SCOPE_UNIVERSE,
1096 .rtm_table = RT_TABLE_UNSPEC,
1097 .rtm_type = RTN_UNSPEC,
1101 if (cmd == RTM_NEWRULE) {
1102 rtm.rtm_type = RTN_UNICAST;
1103 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1107 rtm.rtm_flags |= FIB_RULE_INVERT;
1109 if (rule->flags & IPRULE_SRC)
1110 rtm.rtm_src_len = rule->src_mask;
1112 if (rule->flags & IPRULE_DEST)
1113 rtm.rtm_dst_len = rule->dest_mask;
1115 if (rule->flags & IPRULE_TOS)
1116 rtm.rtm_tos = rule->tos;
1118 if (rule->flags & IPRULE_LOOKUP) {
1119 if (rule->lookup < 256)
1120 rtm.rtm_table = rule->lookup;
1123 if (rule->flags & IPRULE_ACTION)
1124 rtm.rtm_type = rule->action;
1125 else if (rule->flags & IPRULE_GOTO)
1126 rtm.rtm_type = FR_ACT_GOTO;
1127 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1128 rtm.rtm_type = FR_ACT_NOP;
1130 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1135 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1137 if (rule->flags & IPRULE_IN)
1138 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1140 if (rule->flags & IPRULE_OUT)
1141 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1143 if (rule->flags & IPRULE_SRC)
1144 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1146 if (rule->flags & IPRULE_DEST)
1147 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1149 if (rule->flags & IPRULE_PRIORITY)
1150 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1152 if (rule->flags & IPRULE_FWMARK)
1153 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1155 if (rule->flags & IPRULE_FWMASK)
1156 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1158 if (rule->flags & IPRULE_LOOKUP) {
1159 if (rule->lookup >= 256)
1160 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1163 if (rule->flags & IPRULE_GOTO)
1164 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1166 return system_rtnl_call(msg);
1169 int system_add_iprule(struct iprule *rule)
1171 return system_iprule(rule, RTM_NEWRULE);
1174 int system_del_iprule(struct iprule *rule)
1176 return system_iprule(rule, RTM_DELRULE);
1179 int system_flush_iprules(void)
1184 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1185 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1187 memset(&rule, 0, sizeof(rule));
1190 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1193 rule.lookup = RT_TABLE_LOCAL;
1194 rv |= system_iprule(&rule, RTM_NEWRULE);
1196 rule.priority = 32766;
1197 rule.lookup = RT_TABLE_MAIN;
1198 rv |= system_iprule(&rule, RTM_NEWRULE);
1200 rule.priority = 32767;
1201 rule.lookup = RT_TABLE_DEFAULT;
1202 rv |= system_iprule(&rule, RTM_NEWRULE);
1205 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1208 rule.lookup = RT_TABLE_LOCAL;
1209 rv |= system_iprule(&rule, RTM_NEWRULE);
1211 rule.priority = 32766;
1212 rule.lookup = RT_TABLE_MAIN;
1213 rv |= system_iprule(&rule, RTM_NEWRULE);
1218 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1223 if (!strcmp(action, "local"))
1225 else if (!strcmp(action, "nat"))
1227 else if (!strcmp(action, "broadcast"))
1229 else if (!strcmp(action, "anycast"))
1231 else if (!strcmp(action, "multicast"))
1233 else if (!strcmp(action, "prohibit"))
1235 else if (!strcmp(action, "unreachable"))
1236 n = RTN_UNREACHABLE;
1237 else if (!strcmp(action, "blackhole"))
1239 else if (!strcmp(action, "xresolve"))
1241 else if (!strcmp(action, "unicast"))
1243 else if (!strcmp(action, "throw"))
1246 n = strtoul(action, &e, 0);
1247 if (!e || *e || e == action || n > 255)
1255 time_t system_get_rtime(void)
1260 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1263 if (gettimeofday(&tv, NULL) == 0)
1270 #define IP_DF 0x4000
1273 static void tunnel_parm_init(struct ip_tunnel_parm *p)
1275 memset(p, 0, sizeof(*p));
1278 p->iph.frag_off = htons(IP_DF);
1281 static int tunnel_ioctl(const char *name, int cmd, void *p)
1285 memset(&ifr, 0, sizeof(ifr));
1286 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1287 ifr.ifr_ifru.ifru_data = p;
1288 return ioctl(sock_ioctl, cmd, &ifr);
1291 int system_del_ip_tunnel(const char *name)
1293 struct ip_tunnel_parm p;
1295 tunnel_parm_init(&p);
1296 return tunnel_ioctl(name, SIOCDELTUNNEL, &p);
1299 int system_update_ipv6_mtu(struct device *dev, int mtu)
1303 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
1306 int fd = open(buf, O_RDWR);
1307 ssize_t len = read(fd, buf, sizeof(buf) - 1);
1314 if (!mtu || ret <= mtu)
1317 lseek(fd, 0, SEEK_SET);
1318 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) <= 0)
1326 static int parse_ipaddr(struct blob_attr *attr, __be32 *addr)
1331 return inet_pton(AF_INET, blobmsg_data(attr), (void *) addr);
1335 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
1337 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
1338 struct blob_attr *cur;
1339 struct ip_tunnel_parm p;
1340 const char *base, *str;
1343 system_del_ip_tunnel(name);
1345 tunnel_parm_init(&p);
1347 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
1348 blob_data(attr), blob_len(attr));
1350 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
1352 str = blobmsg_data(cur);
1353 is_sit = !strcmp(str, "sit");
1356 p.iph.protocol = IPPROTO_IPV6;
1361 if (!parse_ipaddr(tb[TUNNEL_ATTR_LOCAL], &p.iph.saddr))
1364 if (!parse_ipaddr(tb[TUNNEL_ATTR_REMOTE], &p.iph.daddr))
1367 if ((cur = tb[TUNNEL_ATTR_TTL])) {
1368 unsigned int val = blobmsg_get_u32(cur);
1376 strncpy(p.name, name, sizeof(p.name));
1377 if (tunnel_ioctl(base, SIOCADDTUNNEL, &p) < 0)
1381 cur = tb[TUNNEL_ATTR_6RD_PREFIX];
1382 if (cur && is_sit) {
1384 struct ip_tunnel_6rd p6;
1386 memset(&p6, 0, sizeof(p6));
1388 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
1389 &p6.prefix, &mask) || mask > 128)
1391 p6.prefixlen = mask;
1393 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
1394 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
1395 &p6.relay_prefix, &mask) || mask > 32)
1397 p6.relay_prefixlen = mask;
1400 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
1401 system_del_ip_tunnel(name);