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_AGEING_TIME) {
585 args[0] = BRCTL_SET_AGEING_TIME;
586 args[1] = sec_to_jiffies(cfg->ageing_time);
587 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
590 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
591 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
592 args[1] = sec_to_jiffies(cfg->hello_time);
593 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
596 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
597 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
598 args[1] = sec_to_jiffies(cfg->max_age);
599 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
605 static int system_vlan(struct device *dev, int id)
607 struct vlan_ioctl_args ifr = {
608 .cmd = SET_VLAN_NAME_TYPE_CMD,
609 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
612 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
615 ifr.cmd = DEL_VLAN_CMD;
618 ifr.cmd = ADD_VLAN_CMD;
621 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
622 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
625 int system_vlan_add(struct device *dev, int id)
627 return system_vlan(dev, id);
630 int system_vlan_del(struct device *dev)
632 return system_vlan(dev, -1);
636 system_if_get_settings(struct device *dev, struct device_settings *s)
640 memset(&ifr, 0, sizeof(ifr));
641 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
643 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
644 s->mtu = ifr.ifr_mtu;
645 s->flags |= DEV_OPT_MTU;
648 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
649 s->txqueuelen = ifr.ifr_qlen;
650 s->flags |= DEV_OPT_TXQUEUELEN;
653 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
654 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
655 s->flags |= DEV_OPT_MACADDR;
660 system_if_apply_settings(struct device *dev, struct device_settings *s)
664 memset(&ifr, 0, sizeof(ifr));
665 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
666 if (s->flags & DEV_OPT_MTU) {
667 ifr.ifr_mtu = s->mtu;
668 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
669 s->flags &= ~DEV_OPT_MTU;
671 if (s->flags & DEV_OPT_TXQUEUELEN) {
672 ifr.ifr_qlen = s->txqueuelen;
673 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
674 s->flags &= ~DEV_OPT_TXQUEUELEN;
676 if ((s->flags & DEV_OPT_MACADDR) && !dev->external) {
677 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
678 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
679 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
680 s->flags &= ~DEV_OPT_MACADDR;
684 int system_if_up(struct device *dev)
686 system_if_get_settings(dev, &dev->orig_settings);
687 system_if_apply_settings(dev, &dev->settings);
688 dev->ifindex = system_if_resolve(dev);
689 return system_if_flags(dev->ifname, IFF_UP, 0);
692 int system_if_down(struct device *dev)
694 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
695 dev->orig_settings.flags &= dev->settings.flags;
696 system_if_apply_settings(dev, &dev->orig_settings);
700 int system_if_check(struct device *dev)
702 device_set_present(dev, (system_if_resolve(dev) > 0));
707 system_if_get_parent(struct device *dev)
709 char buf[64], *devname;
710 int ifindex, iflink, len;
713 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
718 len = fread(buf, 1, sizeof(buf) - 1, f);
725 iflink = strtoul(buf, NULL, 0);
726 ifindex = system_if_resolve(dev);
727 if (!iflink || iflink == ifindex)
730 devname = if_indextoname(iflink, buf);
734 return device_get(devname, true);
738 read_string_file(int dir_fd, const char *file, char *buf, int len)
744 fd = openat(dir_fd, file, O_RDONLY);
749 len = read(fd, buf, len - 1);
753 } else if (len > 0) {
756 c = strchr(buf, '\n');
769 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
774 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
776 *val = strtoull(buf, NULL, 0);
781 /* Assume advertised flags == supported flags */
782 static const struct {
785 } ethtool_link_modes[] = {
786 { ADVERTISED_10baseT_Half, "10H" },
787 { ADVERTISED_10baseT_Full, "10F" },
788 { ADVERTISED_100baseT_Half, "100H" },
789 { ADVERTISED_100baseT_Full, "100F" },
790 { ADVERTISED_1000baseT_Half, "1000H" },
791 { ADVERTISED_1000baseT_Full, "1000F" },
794 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
797 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
798 if (mask & ethtool_link_modes[i].mask)
799 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
804 system_if_force_external(const char *ifname)
809 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
810 return stat(buf, &s) == 0;
814 system_if_dump_info(struct device *dev, struct blob_buf *b)
816 struct ethtool_cmd ecmd;
823 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
824 dir_fd = open(buf, O_DIRECTORY);
826 if (read_uint64_file(dir_fd, "carrier", &val))
827 blobmsg_add_u8(b, "link", !!val);
829 memset(&ecmd, 0, sizeof(ecmd));
830 memset(&ifr, 0, sizeof(ifr));
831 strcpy(ifr.ifr_name, dev->ifname);
832 ifr.ifr_data = (caddr_t) &ecmd;
833 ecmd.cmd = ETHTOOL_GSET;
835 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
836 c = blobmsg_open_array(b, "link-advertising");
837 system_add_link_modes(b, ecmd.advertising);
838 blobmsg_close_array(b, c);
840 c = blobmsg_open_array(b, "link-supported");
841 system_add_link_modes(b, ecmd.supported);
842 blobmsg_close_array(b, c);
844 s = blobmsg_alloc_string_buffer(b, "speed", 8);
845 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
846 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
847 blobmsg_add_string_buffer(b);
855 system_if_dump_stats(struct device *dev, struct blob_buf *b)
857 const char *const counters[] = {
858 "collisions", "rx_frame_errors", "tx_compressed",
859 "multicast", "rx_length_errors", "tx_dropped",
860 "rx_bytes", "rx_missed_errors", "tx_errors",
861 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
862 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
863 "rx_dropped", "tx_aborted_errors", "tx_packets",
864 "rx_errors", "tx_bytes", "tx_window_errors",
865 "rx_fifo_errors", "tx_carrier_errors",
872 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
873 stats_dir = open(buf, O_DIRECTORY);
877 for (i = 0; i < ARRAY_SIZE(counters); i++)
878 if (read_uint64_file(stats_dir, counters[i], &val))
879 blobmsg_add_u64(b, counters[i], val);
885 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
887 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
888 int alen = v4 ? 4 : 16;
889 unsigned int flags = 0;
890 struct ifaddrmsg ifa = {
891 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
892 .ifa_prefixlen = addr->mask,
893 .ifa_index = dev->ifindex,
897 if (cmd == RTM_NEWADDR)
898 flags |= NLM_F_CREATE | NLM_F_REPLACE;
900 msg = nlmsg_alloc_simple(cmd, flags);
904 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
905 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
908 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
909 if (addr->point_to_point)
910 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
912 time_t now = system_get_rtime();
913 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
915 if (addr->preferred_until) {
916 int preferred = addr->preferred_until - now;
920 cinfo.ifa_prefered = preferred;
923 if (addr->valid_until) {
924 int valid = addr->valid_until - now;
928 cinfo.ifa_valid = valid;
931 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
934 return system_rtnl_call(msg);
937 int system_add_address(struct device *dev, struct device_addr *addr)
939 return system_addr(dev, addr, RTM_NEWADDR);
942 int system_del_address(struct device *dev, struct device_addr *addr)
944 return system_addr(dev, addr, RTM_DELADDR);
947 static int system_rt(struct device *dev, struct device_route *route, int cmd)
949 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
951 unsigned int flags = 0;
954 have_gw = !!route->nexthop.in.s_addr;
956 have_gw = route->nexthop.in6.s6_addr32[0] ||
957 route->nexthop.in6.s6_addr32[1] ||
958 route->nexthop.in6.s6_addr32[2] ||
959 route->nexthop.in6.s6_addr32[3];
961 unsigned char scope = (cmd == RTM_DELROUTE) ? RT_SCOPE_NOWHERE :
962 (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
964 unsigned int table = (route->flags & DEVROUTE_TABLE) ? route->table : RT_TABLE_MAIN;
967 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
968 .rtm_dst_len = route->mask,
969 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
970 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
972 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
976 if (cmd == RTM_NEWROUTE) {
977 flags |= NLM_F_CREATE | NLM_F_REPLACE;
979 if (!dev) { // Add null-route
980 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
981 rtm.rtm_type = RTN_UNREACHABLE;
985 msg = nlmsg_alloc_simple(cmd, flags);
989 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
992 nla_put(msg, RTA_DST, alen, &route->addr);
994 if (route->metric > 0)
995 nla_put_u32(msg, RTA_PRIORITY, route->metric);
998 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1001 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1004 nla_put_u32(msg, RTA_TABLE, table);
1006 return system_rtnl_call(msg);
1009 int system_add_route(struct device *dev, struct device_route *route)
1011 return system_rt(dev, route, RTM_NEWROUTE);
1014 int system_del_route(struct device *dev, struct device_route *route)
1016 return system_rt(dev, route, RTM_DELROUTE);
1019 int system_flush_routes(void)
1021 const char *names[] = {
1022 "/proc/sys/net/ipv4/route/flush",
1023 "/proc/sys/net/ipv6/route/flush"
1027 for (i = 0; i < ARRAY_SIZE(names); i++) {
1028 fd = open(names[i], O_WRONLY);
1038 bool system_resolve_rt_table(const char *name, unsigned int *id)
1042 unsigned int n, table = RT_TABLE_UNSPEC;
1044 /* first try to parse table as number */
1045 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1048 /* handle well known aliases */
1049 else if (!strcmp(name, "default"))
1050 table = RT_TABLE_DEFAULT;
1051 else if (!strcmp(name, "main"))
1052 table = RT_TABLE_MAIN;
1053 else if (!strcmp(name, "local"))
1054 table = RT_TABLE_LOCAL;
1056 /* try to look up name in /etc/iproute2/rt_tables */
1057 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1059 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1061 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1064 n = strtoul(e, NULL, 10);
1065 e = strtok(NULL, " \t\n");
1067 if (e && !strcmp(e, name))
1077 if (table == RT_TABLE_UNSPEC)
1080 /* do not consider main table special */
1081 if (table == RT_TABLE_MAIN)
1082 table = RT_TABLE_UNSPEC;
1088 static int system_iprule(struct iprule *rule, int cmd)
1090 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1093 struct rtmsg rtm = {
1094 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1095 .rtm_protocol = RTPROT_STATIC,
1096 .rtm_scope = RT_SCOPE_UNIVERSE,
1097 .rtm_table = RT_TABLE_UNSPEC,
1098 .rtm_type = RTN_UNSPEC,
1102 if (cmd == RTM_NEWRULE) {
1103 rtm.rtm_type = RTN_UNICAST;
1104 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1108 rtm.rtm_flags |= FIB_RULE_INVERT;
1110 if (rule->flags & IPRULE_SRC)
1111 rtm.rtm_src_len = rule->src_mask;
1113 if (rule->flags & IPRULE_DEST)
1114 rtm.rtm_dst_len = rule->dest_mask;
1116 if (rule->flags & IPRULE_TOS)
1117 rtm.rtm_tos = rule->tos;
1119 if (rule->flags & IPRULE_LOOKUP) {
1120 if (rule->lookup < 256)
1121 rtm.rtm_table = rule->lookup;
1124 if (rule->flags & IPRULE_ACTION)
1125 rtm.rtm_type = rule->action;
1126 else if (rule->flags & IPRULE_GOTO)
1127 rtm.rtm_type = FR_ACT_GOTO;
1128 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1129 rtm.rtm_type = FR_ACT_NOP;
1131 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1136 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1138 if (rule->flags & IPRULE_IN)
1139 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1141 if (rule->flags & IPRULE_OUT)
1142 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1144 if (rule->flags & IPRULE_SRC)
1145 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1147 if (rule->flags & IPRULE_DEST)
1148 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1150 if (rule->flags & IPRULE_PRIORITY)
1151 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1153 if (rule->flags & IPRULE_FWMARK)
1154 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1156 if (rule->flags & IPRULE_FWMASK)
1157 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1159 if (rule->flags & IPRULE_LOOKUP) {
1160 if (rule->lookup >= 256)
1161 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1164 if (rule->flags & IPRULE_GOTO)
1165 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1167 return system_rtnl_call(msg);
1170 int system_add_iprule(struct iprule *rule)
1172 return system_iprule(rule, RTM_NEWRULE);
1175 int system_del_iprule(struct iprule *rule)
1177 return system_iprule(rule, RTM_DELRULE);
1180 int system_flush_iprules(void)
1185 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1186 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1188 memset(&rule, 0, sizeof(rule));
1191 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1194 rule.lookup = RT_TABLE_LOCAL;
1195 rv |= system_iprule(&rule, RTM_NEWRULE);
1197 rule.priority = 32766;
1198 rule.lookup = RT_TABLE_MAIN;
1199 rv |= system_iprule(&rule, RTM_NEWRULE);
1201 rule.priority = 32767;
1202 rule.lookup = RT_TABLE_DEFAULT;
1203 rv |= system_iprule(&rule, RTM_NEWRULE);
1206 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1209 rule.lookup = RT_TABLE_LOCAL;
1210 rv |= system_iprule(&rule, RTM_NEWRULE);
1212 rule.priority = 32766;
1213 rule.lookup = RT_TABLE_MAIN;
1214 rv |= system_iprule(&rule, RTM_NEWRULE);
1219 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1224 if (!strcmp(action, "local"))
1226 else if (!strcmp(action, "nat"))
1228 else if (!strcmp(action, "broadcast"))
1230 else if (!strcmp(action, "anycast"))
1232 else if (!strcmp(action, "multicast"))
1234 else if (!strcmp(action, "prohibit"))
1236 else if (!strcmp(action, "unreachable"))
1237 n = RTN_UNREACHABLE;
1238 else if (!strcmp(action, "blackhole"))
1240 else if (!strcmp(action, "xresolve"))
1242 else if (!strcmp(action, "unicast"))
1244 else if (!strcmp(action, "throw"))
1247 n = strtoul(action, &e, 0);
1248 if (!e || *e || e == action || n > 255)
1256 time_t system_get_rtime(void)
1261 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1264 if (gettimeofday(&tv, NULL) == 0)
1271 #define IP_DF 0x4000
1274 static void tunnel_parm_init(struct ip_tunnel_parm *p)
1276 memset(p, 0, sizeof(*p));
1279 p->iph.frag_off = htons(IP_DF);
1282 static int tunnel_ioctl(const char *name, int cmd, void *p)
1286 memset(&ifr, 0, sizeof(ifr));
1287 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1288 ifr.ifr_ifru.ifru_data = p;
1289 return ioctl(sock_ioctl, cmd, &ifr);
1292 int system_del_ip_tunnel(const char *name)
1294 struct ip_tunnel_parm p;
1296 tunnel_parm_init(&p);
1297 return tunnel_ioctl(name, SIOCDELTUNNEL, &p);
1300 int system_update_ipv6_mtu(struct device *dev, int mtu)
1304 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
1307 int fd = open(buf, O_RDWR);
1308 ssize_t len = read(fd, buf, sizeof(buf) - 1);
1315 if (!mtu || ret <= mtu)
1318 lseek(fd, 0, SEEK_SET);
1319 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) <= 0)
1327 static int parse_ipaddr(struct blob_attr *attr, __be32 *addr)
1332 return inet_pton(AF_INET, blobmsg_data(attr), (void *) addr);
1336 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
1338 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
1339 struct blob_attr *cur;
1340 struct ip_tunnel_parm p;
1341 const char *base, *str;
1344 system_del_ip_tunnel(name);
1346 tunnel_parm_init(&p);
1348 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
1349 blob_data(attr), blob_len(attr));
1351 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
1353 str = blobmsg_data(cur);
1354 is_sit = !strcmp(str, "sit");
1357 p.iph.protocol = IPPROTO_IPV6;
1362 if (!parse_ipaddr(tb[TUNNEL_ATTR_LOCAL], &p.iph.saddr))
1365 if (!parse_ipaddr(tb[TUNNEL_ATTR_REMOTE], &p.iph.daddr))
1368 if ((cur = tb[TUNNEL_ATTR_TTL])) {
1369 unsigned int val = blobmsg_get_u32(cur);
1377 strncpy(p.name, name, sizeof(p.name));
1378 if (tunnel_ioctl(base, SIOCADDTUNNEL, &p) < 0)
1382 cur = tb[TUNNEL_ATTR_6RD_PREFIX];
1383 if (cur && is_sit) {
1385 struct ip_tunnel_6rd p6;
1387 memset(&p6, 0, sizeof(p6));
1389 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
1390 &p6.prefix, &mask) || mask > 128)
1392 p6.prefixlen = mask;
1394 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
1395 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
1396 &p6.relay_prefix, &mask) || mask > 32)
1398 p6.relay_prefixlen = mask;
1401 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
1402 system_del_ip_tunnel(name);