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_link.h>
33 #include <linux/if_vlan.h>
34 #include <linux/if_bridge.h>
35 #include <linux/if_tunnel.h>
36 #include <linux/ip6_tunnel.h>
37 #include <linux/ethtool.h>
38 #include <linux/fib_rules.h>
40 #ifndef RTN_FAILED_POLICY
41 #define RTN_FAILED_POLICY 12
49 #include <netlink/msg.h>
50 #include <netlink/attr.h>
51 #include <netlink/socket.h>
52 #include <libubox/uloop.h>
59 struct uloop_fd uloop;
64 static int sock_ioctl = -1;
65 static struct nl_sock *sock_rtnl = NULL;
67 static int cb_rtnl_event(struct nl_msg *msg, void *arg);
68 static void handle_hotplug_event(struct uloop_fd *u, unsigned int events);
70 static char dev_buf[256];
73 handler_nl_event(struct uloop_fd *u, unsigned int events)
75 struct event_socket *ev = container_of(u, struct event_socket, uloop);
77 socklen_t errlen = sizeof(err);
80 nl_recvmsgs_default(ev->sock);
84 if (getsockopt(u->fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen))
89 // Increase rx buffer size on netlink socket
91 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
94 // Request full dump since some info got dropped
95 struct rtgenmsg msg = { .rtgen_family = AF_UNSPEC };
96 nl_send_simple(ev->sock, RTM_GETLINK, NLM_F_DUMP, &msg, sizeof(msg));
106 uloop_fd_delete(&ev->uloop);
110 static struct nl_sock *
111 create_socket(int protocol, int groups)
113 struct nl_sock *sock;
115 sock = nl_socket_alloc();
120 nl_join_groups(sock, groups);
122 if (nl_connect(sock, protocol))
129 create_raw_event_socket(struct event_socket *ev, int protocol, int groups,
130 uloop_fd_handler cb, int flags)
132 ev->sock = create_socket(protocol, groups);
136 ev->uloop.fd = nl_socket_get_fd(ev->sock);
138 if (uloop_fd_add(&ev->uloop, ULOOP_READ|flags))
145 create_event_socket(struct event_socket *ev, int protocol,
146 int (*cb)(struct nl_msg *msg, void *arg))
148 if (!create_raw_event_socket(ev, protocol, 0, handler_nl_event, ULOOP_ERROR_CB))
151 // Install the valid custom callback handler
152 nl_socket_modify_cb(ev->sock, NL_CB_VALID, NL_CB_CUSTOM, cb, NULL);
154 // Disable sequence number checking on event sockets
155 nl_socket_disable_seq_check(ev->sock);
157 // Increase rx buffer size to 65K on event sockets
159 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
165 int system_init(void)
167 static struct event_socket rtnl_event;
168 static struct event_socket hotplug_event;
170 sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0);
171 system_fd_set_cloexec(sock_ioctl);
173 // Prepare socket for routing / address control
174 sock_rtnl = create_socket(NETLINK_ROUTE, 0);
178 if (!create_event_socket(&rtnl_event, NETLINK_ROUTE, cb_rtnl_event))
181 if (!create_raw_event_socket(&hotplug_event, NETLINK_KOBJECT_UEVENT, 1,
182 handle_hotplug_event, 0))
185 // Receive network link events form kernel
186 nl_socket_add_membership(rtnl_event.sock, RTNLGRP_LINK);
191 static void system_set_sysctl(const char *path, const char *val)
195 fd = open(path, O_WRONLY);
199 if (write(fd, val, strlen(val))) {}
203 static void system_set_dev_sysctl(const char *path, const char *device, const char *val)
205 snprintf(dev_buf, sizeof(dev_buf), path, device);
206 system_set_sysctl(dev_buf, val);
209 static void system_set_disable_ipv6(struct device *dev, const char *val)
211 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val);
214 static int system_get_sysctl(const char *path, char *buf, const size_t buf_sz)
216 int fd = -1, ret = -1;
218 fd = open(path, O_RDONLY);
222 ssize_t len = read(fd, buf, buf_sz - 1);
236 system_get_dev_sysctl(const char *path, const char *device, char *buf, const size_t buf_sz)
238 snprintf(dev_buf, sizeof(dev_buf), path, device);
239 return system_get_sysctl(dev_buf, buf, buf_sz);
242 static int system_get_disable_ipv6(struct device *dev, char *buf, const size_t buf_sz)
244 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6",
245 dev->ifname, buf, buf_sz);
249 #define IFF_LOWER_UP 0x10000
252 // Evaluate netlink messages
253 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
255 struct nlmsghdr *nh = nlmsg_hdr(msg);
256 struct ifinfomsg *ifi = NLMSG_DATA(nh);
257 struct nlattr *nla[__IFLA_MAX];
259 if (nh->nlmsg_type != RTM_NEWLINK)
262 nlmsg_parse(nh, sizeof(*ifi), nla, __IFLA_MAX - 1, NULL);
263 if (!nla[IFLA_IFNAME])
266 struct device *dev = device_get(nla_data(nla[IFLA_IFNAME]), false);
270 device_set_ifindex(dev, ifi->ifi_index);
271 device_set_link(dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
278 handle_hotplug_msg(char *data, int size)
280 const char *subsystem = NULL, *interface = NULL;
281 char *cur, *end, *sep;
286 if (!strncmp(data, "add@", 4))
288 else if (!strncmp(data, "remove@", 7))
293 skip = strlen(data) + 1;
296 for (cur = data + skip; cur < end; cur += skip) {
297 skip = strlen(cur) + 1;
299 sep = strchr(cur, '=');
304 if (!strcmp(cur, "INTERFACE"))
306 else if (!strcmp(cur, "SUBSYSTEM")) {
308 if (strcmp(subsystem, "net") != 0)
311 if (subsystem && interface)
317 dev = device_get(interface, false);
321 if (dev->type != &simple_device_type)
324 if (add && system_if_force_external(dev->ifname))
327 device_set_present(dev, add);
331 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
333 struct event_socket *ev = container_of(u, struct event_socket, uloop);
334 struct sockaddr_nl nla;
335 unsigned char *buf = NULL;
338 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
340 handle_hotplug_msg((char *) buf, size);
346 static int system_rtnl_call(struct nl_msg *msg)
350 ret = nl_send_auto_complete(sock_rtnl, msg);
356 return nl_wait_for_ack(sock_rtnl);
359 int system_bridge_delbr(struct device *bridge)
361 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
364 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
368 memset(&ifr, 0, sizeof(ifr));
370 ifr.ifr_ifindex = dev->ifindex;
373 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
374 return ioctl(sock_ioctl, cmd, &ifr);
377 static bool system_is_bridge(const char *name, char *buf, int buflen)
381 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
382 if (stat(buf, &st) < 0)
388 static char *system_get_bridge(const char *name, char *buf, int buflen)
394 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
395 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
398 if (gl.gl_pathc == 0)
401 len = readlink(gl.gl_pathv[0], buf, buflen);
406 path = strrchr(buf, '/');
413 int system_bridge_addif(struct device *bridge, struct device *dev)
417 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
418 if (oldbr && !strcmp(oldbr, bridge->ifname))
421 return system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
424 int system_bridge_delif(struct device *bridge, struct device *dev)
426 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
429 static int system_if_resolve(struct device *dev)
432 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
433 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
434 return ifr.ifr_ifindex;
439 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
443 memset(&ifr, 0, sizeof(ifr));
444 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
445 ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
446 ifr.ifr_flags |= add;
447 ifr.ifr_flags &= ~rem;
448 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
460 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
462 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
464 return ifa->ifa_index == ifindex;
467 static bool check_route(struct nlmsghdr *hdr, int ifindex)
469 struct rtmsg *r = NLMSG_DATA(hdr);
470 struct nlattr *tb[__RTA_MAX];
472 if (r->rtm_protocol == RTPROT_KERNEL &&
473 r->rtm_family == AF_INET6)
476 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
480 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
483 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
488 static int cb_clear_event(struct nl_msg *msg, void *arg)
490 struct clear_data *clr = arg;
491 struct nlmsghdr *hdr = nlmsg_hdr(msg);
492 bool (*cb)(struct nlmsghdr *, int ifindex);
498 if (hdr->nlmsg_type != RTM_NEWADDR)
505 if (hdr->nlmsg_type != RTM_NEWROUTE)
512 if (hdr->nlmsg_type != RTM_NEWRULE)
521 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
524 if (type == RTM_DELRULE)
525 D(SYSTEM, "Remove a rule\n");
527 D(SYSTEM, "Remove %s from device %s\n",
528 type == RTM_DELADDR ? "an address" : "a route",
530 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
531 hdr = nlmsg_hdr(clr->msg);
532 hdr->nlmsg_type = type;
533 hdr->nlmsg_flags = NLM_F_REQUEST;
535 nl_socket_disable_auto_ack(sock_rtnl);
536 nl_send_auto_complete(sock_rtnl, clr->msg);
537 nl_socket_enable_auto_ack(sock_rtnl);
543 cb_finish_event(struct nl_msg *msg, void *arg)
551 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
554 *pending = err->error;
559 system_if_clear_entries(struct device *dev, int type, int af)
561 struct clear_data clr;
562 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
565 .rtm_flags = RTM_F_CLONED,
567 int flags = NLM_F_DUMP;
576 clr.size = sizeof(struct rtgenmsg);
579 clr.size = sizeof(struct rtmsg);
588 clr.msg = nlmsg_alloc_simple(type, flags);
592 nlmsg_append(clr.msg, &rtm, clr.size, 0);
593 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
594 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
595 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
597 nl_send_auto_complete(sock_rtnl, clr.msg);
599 nl_recvmsgs(sock_rtnl, cb);
607 * Clear bridge (membership) state and bring down device
609 void system_if_clear_state(struct device *dev)
611 static char buf[256];
617 device_set_ifindex(dev, system_if_resolve(dev));
621 system_if_flags(dev->ifname, 0, IFF_UP);
623 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
624 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
625 system_bridge_delbr(dev);
629 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
631 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
632 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
635 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
636 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
637 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
638 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
639 system_set_disable_ipv6(dev, "0");
642 static inline unsigned long
643 sec_to_jiffies(int val)
645 return (unsigned long) val * 100;
648 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
650 unsigned long args[4] = {};
652 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
655 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
656 args[1] = !!cfg->stp;
657 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
659 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
660 args[1] = sec_to_jiffies(cfg->forward_delay);
661 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
663 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
664 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
666 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
667 args[1] = cfg->priority;
668 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
670 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
671 args[0] = BRCTL_SET_AGEING_TIME;
672 args[1] = sec_to_jiffies(cfg->ageing_time);
673 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
676 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
677 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
678 args[1] = sec_to_jiffies(cfg->hello_time);
679 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
682 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
683 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
684 args[1] = sec_to_jiffies(cfg->max_age);
685 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
691 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
694 struct nlattr *linkinfo, *data;
695 struct ifinfomsg iim = { .ifi_family = AF_INET };
696 int ifindex = system_if_resolve(dev);
698 static const struct {
700 enum macvlan_mode val;
702 { "private", MACVLAN_MODE_PRIVATE },
703 { "vepa", MACVLAN_MODE_VEPA },
704 { "bridge", MACVLAN_MODE_BRIDGE },
705 { "passthru", MACVLAN_MODE_PASSTHRU },
711 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
716 nlmsg_append(msg, &iim, sizeof(iim), 0);
718 if (cfg->flags & MACVLAN_OPT_MACADDR)
719 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
720 nla_put(msg, IFLA_IFNAME, IFNAMSIZ, macvlan->ifname);
721 nla_put_u32(msg, IFLA_LINK, ifindex);
723 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
724 goto nla_put_failure;
726 nla_put(msg, IFLA_INFO_KIND, strlen("macvlan"), "macvlan");
728 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
729 goto nla_put_failure;
732 for (i = 0; i < ARRAY_SIZE(modes); i++) {
733 if (strcmp(cfg->mode, modes[i].name) != 0)
736 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
741 nla_nest_end(msg, data);
742 nla_nest_end(msg, linkinfo);
744 rv = system_rtnl_call(msg);
746 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
755 int system_macvlan_del(struct device *macvlan)
758 struct ifinfomsg iim;
760 iim.ifi_family = AF_INET;
763 msg = nlmsg_alloc_simple(RTM_DELLINK, 0);
768 nlmsg_append(msg, &iim, sizeof(iim), 0);
770 nla_put(msg, IFLA_INFO_KIND, strlen("macvlan"), "macvlan");
771 nla_put(msg, IFLA_IFNAME, sizeof(macvlan->ifname), macvlan->ifname);
773 system_rtnl_call(msg);
778 static int system_vlan(struct device *dev, int id)
780 struct vlan_ioctl_args ifr = {
781 .cmd = SET_VLAN_NAME_TYPE_CMD,
782 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
785 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
788 ifr.cmd = DEL_VLAN_CMD;
791 ifr.cmd = ADD_VLAN_CMD;
794 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
795 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
798 int system_vlan_add(struct device *dev, int id)
800 return system_vlan(dev, id);
803 int system_vlan_del(struct device *dev)
805 return system_vlan(dev, -1);
809 system_if_get_settings(struct device *dev, struct device_settings *s)
814 memset(&ifr, 0, sizeof(ifr));
815 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
817 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
818 s->mtu = ifr.ifr_mtu;
819 s->flags |= DEV_OPT_MTU;
822 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
823 s->txqueuelen = ifr.ifr_qlen;
824 s->flags |= DEV_OPT_TXQUEUELEN;
827 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
828 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
829 s->flags |= DEV_OPT_MACADDR;
832 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
833 s->ipv6 = !strtoul(buf, NULL, 0);
834 s->flags |= DEV_OPT_IPV6;
839 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
846 memset(&ifr, 0, sizeof(ifr));
847 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
848 if (s->flags & DEV_OPT_MTU & apply_mask) {
849 ifr.ifr_mtu = s->mtu;
850 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
851 s->flags &= ~DEV_OPT_MTU;
853 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
854 ifr.ifr_qlen = s->txqueuelen;
855 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
856 s->flags &= ~DEV_OPT_TXQUEUELEN;
858 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
859 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
860 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
861 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
862 s->flags &= ~DEV_OPT_MACADDR;
864 if (s->flags & DEV_OPT_IPV6 & apply_mask)
865 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
868 int system_if_up(struct device *dev)
870 system_if_get_settings(dev, &dev->orig_settings);
871 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
872 device_set_ifindex(dev, system_if_resolve(dev));
873 return system_if_flags(dev->ifname, IFF_UP, 0);
876 int system_if_down(struct device *dev)
878 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
879 dev->orig_settings.flags &= dev->settings.flags;
880 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
884 struct if_check_data {
890 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
892 struct nlmsghdr *nh = nlmsg_hdr(msg);
893 struct ifinfomsg *ifi = NLMSG_DATA(nh);
894 struct if_check_data *chk = (struct if_check_data *)arg;
896 if (nh->nlmsg_type != RTM_NEWLINK)
899 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
900 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
905 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
907 struct if_check_data *chk = (struct if_check_data *)arg;
912 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
914 struct if_check_data *chk = (struct if_check_data *)arg;
916 device_set_present(chk->dev, false);
917 device_set_link(chk->dev, false);
918 chk->pending = err->error;
923 int system_if_check(struct device *dev)
925 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
927 struct ifinfomsg ifi = {
928 .ifi_family = AF_UNSPEC,
931 struct if_check_data chk = {
937 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
938 if (!msg || nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
939 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
942 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
943 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
944 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
946 nl_send_auto_complete(sock_rtnl, msg);
947 while (chk.pending > 0)
948 nl_recvmsgs(sock_rtnl, cb);
959 system_if_get_parent(struct device *dev)
961 char buf[64], *devname;
962 int ifindex, iflink, len;
965 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
970 len = fread(buf, 1, sizeof(buf) - 1, f);
977 iflink = strtoul(buf, NULL, 0);
978 ifindex = system_if_resolve(dev);
979 if (!iflink || iflink == ifindex)
982 devname = if_indextoname(iflink, buf);
986 return device_get(devname, true);
990 read_string_file(int dir_fd, const char *file, char *buf, int len)
996 fd = openat(dir_fd, file, O_RDONLY);
1001 len = read(fd, buf, len - 1);
1005 } else if (len > 0) {
1008 c = strchr(buf, '\n');
1021 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1026 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1028 *val = strtoull(buf, NULL, 0);
1033 /* Assume advertised flags == supported flags */
1034 static const struct {
1037 } ethtool_link_modes[] = {
1038 { ADVERTISED_10baseT_Half, "10H" },
1039 { ADVERTISED_10baseT_Full, "10F" },
1040 { ADVERTISED_100baseT_Half, "100H" },
1041 { ADVERTISED_100baseT_Full, "100F" },
1042 { ADVERTISED_1000baseT_Half, "1000H" },
1043 { ADVERTISED_1000baseT_Full, "1000F" },
1046 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1049 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1050 if (mask & ethtool_link_modes[i].mask)
1051 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1056 system_if_force_external(const char *ifname)
1061 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1062 return stat(buf, &s) == 0;
1066 system_if_dump_info(struct device *dev, struct blob_buf *b)
1068 struct ethtool_cmd ecmd;
1074 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
1075 dir_fd = open(buf, O_DIRECTORY);
1077 memset(&ecmd, 0, sizeof(ecmd));
1078 memset(&ifr, 0, sizeof(ifr));
1079 strcpy(ifr.ifr_name, dev->ifname);
1080 ifr.ifr_data = (caddr_t) &ecmd;
1081 ecmd.cmd = ETHTOOL_GSET;
1083 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1084 c = blobmsg_open_array(b, "link-advertising");
1085 system_add_link_modes(b, ecmd.advertising);
1086 blobmsg_close_array(b, c);
1088 c = blobmsg_open_array(b, "link-supported");
1089 system_add_link_modes(b, ecmd.supported);
1090 blobmsg_close_array(b, c);
1092 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1093 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1094 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1095 blobmsg_add_string_buffer(b);
1103 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1105 const char *const counters[] = {
1106 "collisions", "rx_frame_errors", "tx_compressed",
1107 "multicast", "rx_length_errors", "tx_dropped",
1108 "rx_bytes", "rx_missed_errors", "tx_errors",
1109 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1110 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1111 "rx_dropped", "tx_aborted_errors", "tx_packets",
1112 "rx_errors", "tx_bytes", "tx_window_errors",
1113 "rx_fifo_errors", "tx_carrier_errors",
1120 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1121 stats_dir = open(buf, O_DIRECTORY);
1125 for (i = 0; i < ARRAY_SIZE(counters); i++)
1126 if (read_uint64_file(stats_dir, counters[i], &val))
1127 blobmsg_add_u64(b, counters[i], val);
1133 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1135 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1136 int alen = v4 ? 4 : 16;
1137 unsigned int flags = 0;
1138 struct ifaddrmsg ifa = {
1139 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1140 .ifa_prefixlen = addr->mask,
1141 .ifa_index = dev->ifindex,
1145 if (cmd == RTM_NEWADDR)
1146 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1148 msg = nlmsg_alloc_simple(cmd, flags);
1152 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1153 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1155 if (addr->broadcast)
1156 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1157 if (addr->point_to_point)
1158 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1160 time_t now = system_get_rtime();
1161 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1163 if (addr->preferred_until) {
1164 int64_t preferred = addr->preferred_until - now;
1167 else if (preferred > UINT32_MAX)
1168 preferred = UINT32_MAX;
1170 cinfo.ifa_prefered = preferred;
1173 if (addr->valid_until) {
1174 int64_t valid = addr->valid_until - now;
1177 else if (valid > UINT32_MAX)
1180 cinfo.ifa_valid = valid;
1183 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1186 return system_rtnl_call(msg);
1189 int system_add_address(struct device *dev, struct device_addr *addr)
1191 return system_addr(dev, addr, RTM_NEWADDR);
1194 int system_del_address(struct device *dev, struct device_addr *addr)
1196 return system_addr(dev, addr, RTM_DELADDR);
1199 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1201 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1203 unsigned int flags = 0;
1206 have_gw = !!route->nexthop.in.s_addr;
1208 have_gw = route->nexthop.in6.s6_addr32[0] ||
1209 route->nexthop.in6.s6_addr32[1] ||
1210 route->nexthop.in6.s6_addr32[2] ||
1211 route->nexthop.in6.s6_addr32[3];
1213 unsigned char scope = (cmd == RTM_DELROUTE) ? RT_SCOPE_NOWHERE :
1214 (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1216 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1217 ? route->table : RT_TABLE_MAIN;
1219 struct rtmsg rtm = {
1220 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1221 .rtm_dst_len = route->mask,
1222 .rtm_src_len = route->sourcemask,
1223 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1224 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
1226 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1230 if (cmd == RTM_NEWROUTE) {
1231 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1233 if (!dev) { // Add null-route
1234 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1235 rtm.rtm_type = RTN_UNREACHABLE;
1239 msg = nlmsg_alloc_simple(cmd, flags);
1243 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1246 nla_put(msg, RTA_DST, alen, &route->addr);
1248 if (route->sourcemask)
1249 nla_put(msg, RTA_SRC, alen, &route->source);
1251 if (route->metric > 0)
1252 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1255 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1258 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1261 nla_put_u32(msg, RTA_TABLE, table);
1263 return system_rtnl_call(msg);
1266 int system_add_route(struct device *dev, struct device_route *route)
1268 return system_rt(dev, route, RTM_NEWROUTE);
1271 int system_del_route(struct device *dev, struct device_route *route)
1273 return system_rt(dev, route, RTM_DELROUTE);
1276 int system_flush_routes(void)
1278 const char *names[] = {
1279 "/proc/sys/net/ipv4/route/flush",
1280 "/proc/sys/net/ipv6/route/flush"
1284 for (i = 0; i < ARRAY_SIZE(names); i++) {
1285 fd = open(names[i], O_WRONLY);
1289 if (write(fd, "-1", 2)) {}
1295 bool system_resolve_rt_table(const char *name, unsigned int *id)
1299 unsigned int n, table = RT_TABLE_UNSPEC;
1301 /* first try to parse table as number */
1302 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1305 /* handle well known aliases */
1306 else if (!strcmp(name, "default"))
1307 table = RT_TABLE_DEFAULT;
1308 else if (!strcmp(name, "main"))
1309 table = RT_TABLE_MAIN;
1310 else if (!strcmp(name, "local"))
1311 table = RT_TABLE_LOCAL;
1313 /* try to look up name in /etc/iproute2/rt_tables */
1314 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1316 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1318 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1321 n = strtoul(e, NULL, 10);
1322 e = strtok(NULL, " \t\n");
1324 if (e && !strcmp(e, name))
1334 if (table == RT_TABLE_UNSPEC)
1337 /* do not consider main table special */
1338 if (table == RT_TABLE_MAIN)
1339 table = RT_TABLE_UNSPEC;
1345 static int system_iprule(struct iprule *rule, int cmd)
1347 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1350 struct rtmsg rtm = {
1351 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1352 .rtm_protocol = RTPROT_STATIC,
1353 .rtm_scope = RT_SCOPE_UNIVERSE,
1354 .rtm_table = RT_TABLE_UNSPEC,
1355 .rtm_type = RTN_UNSPEC,
1359 if (cmd == RTM_NEWRULE) {
1360 rtm.rtm_type = RTN_UNICAST;
1361 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1365 rtm.rtm_flags |= FIB_RULE_INVERT;
1367 if (rule->flags & IPRULE_SRC)
1368 rtm.rtm_src_len = rule->src_mask;
1370 if (rule->flags & IPRULE_DEST)
1371 rtm.rtm_dst_len = rule->dest_mask;
1373 if (rule->flags & IPRULE_TOS)
1374 rtm.rtm_tos = rule->tos;
1376 if (rule->flags & IPRULE_LOOKUP) {
1377 if (rule->lookup < 256)
1378 rtm.rtm_table = rule->lookup;
1381 if (rule->flags & IPRULE_ACTION)
1382 rtm.rtm_type = rule->action;
1383 else if (rule->flags & IPRULE_GOTO)
1384 rtm.rtm_type = FR_ACT_GOTO;
1385 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1386 rtm.rtm_type = FR_ACT_NOP;
1388 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1393 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1395 if (rule->flags & IPRULE_IN)
1396 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1398 if (rule->flags & IPRULE_OUT)
1399 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1401 if (rule->flags & IPRULE_SRC)
1402 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1404 if (rule->flags & IPRULE_DEST)
1405 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1407 if (rule->flags & IPRULE_PRIORITY)
1408 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1409 else if (cmd == RTM_NEWRULE)
1410 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1412 if (rule->flags & IPRULE_FWMARK)
1413 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1415 if (rule->flags & IPRULE_FWMASK)
1416 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1418 if (rule->flags & IPRULE_LOOKUP) {
1419 if (rule->lookup >= 256)
1420 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1423 if (rule->flags & IPRULE_GOTO)
1424 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1426 return system_rtnl_call(msg);
1429 int system_add_iprule(struct iprule *rule)
1431 return system_iprule(rule, RTM_NEWRULE);
1434 int system_del_iprule(struct iprule *rule)
1436 return system_iprule(rule, RTM_DELRULE);
1439 int system_flush_iprules(void)
1444 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1445 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1447 memset(&rule, 0, sizeof(rule));
1450 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1453 rule.lookup = RT_TABLE_LOCAL;
1454 rv |= system_iprule(&rule, RTM_NEWRULE);
1456 rule.priority = 32766;
1457 rule.lookup = RT_TABLE_MAIN;
1458 rv |= system_iprule(&rule, RTM_NEWRULE);
1460 rule.priority = 32767;
1461 rule.lookup = RT_TABLE_DEFAULT;
1462 rv |= system_iprule(&rule, RTM_NEWRULE);
1465 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1468 rule.lookup = RT_TABLE_LOCAL;
1469 rv |= system_iprule(&rule, RTM_NEWRULE);
1471 rule.priority = 32766;
1472 rule.lookup = RT_TABLE_MAIN;
1473 rv |= system_iprule(&rule, RTM_NEWRULE);
1478 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1483 if (!strcmp(action, "local"))
1485 else if (!strcmp(action, "nat"))
1487 else if (!strcmp(action, "broadcast"))
1489 else if (!strcmp(action, "anycast"))
1491 else if (!strcmp(action, "multicast"))
1493 else if (!strcmp(action, "prohibit"))
1495 else if (!strcmp(action, "unreachable"))
1496 n = RTN_UNREACHABLE;
1497 else if (!strcmp(action, "blackhole"))
1499 else if (!strcmp(action, "xresolve"))
1501 else if (!strcmp(action, "unicast"))
1503 else if (!strcmp(action, "throw"))
1505 else if (!strcmp(action, "failed_policy"))
1506 n = RTN_FAILED_POLICY;
1508 n = strtoul(action, &e, 0);
1509 if (!e || *e || e == action || n > 255)
1517 time_t system_get_rtime(void)
1522 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1525 if (gettimeofday(&tv, NULL) == 0)
1532 #define IP_DF 0x4000
1535 static int tunnel_ioctl(const char *name, int cmd, void *p)
1539 memset(&ifr, 0, sizeof(ifr));
1540 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1541 ifr.ifr_ifru.ifru_data = p;
1542 return ioctl(sock_ioctl, cmd, &ifr);
1545 int system_del_ip_tunnel(const char *name)
1547 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
1550 int system_update_ipv6_mtu(struct device *dev, int mtu)
1554 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
1557 int fd = open(buf, O_RDWR);
1558 ssize_t len = read(fd, buf, sizeof(buf) - 1);
1565 if (!mtu || ret <= mtu)
1568 lseek(fd, 0, SEEK_SET);
1569 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) <= 0)
1577 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
1579 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
1580 struct blob_attr *cur;
1584 system_del_ip_tunnel(name);
1586 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
1587 blob_data(attr), blob_len(attr));
1589 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
1591 str = blobmsg_data(cur);
1593 if ((cur = tb[TUNNEL_ATTR_DF]))
1594 set_df = blobmsg_get_bool(cur);
1596 unsigned int ttl = 0;
1597 if ((cur = tb[TUNNEL_ATTR_TTL])) {
1598 ttl = blobmsg_get_u32(cur);
1599 if (ttl > 255 || (!set_df && ttl))
1603 unsigned int link = 0;
1604 if ((cur = tb[TUNNEL_ATTR_LINK])) {
1605 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
1609 if (iface->l3_dev.dev)
1610 link = iface->l3_dev.dev->ifindex;
1613 if (!strcmp(str, "sit")) {
1614 struct ip_tunnel_parm p = {
1619 .frag_off = set_df ? htons(IP_DF) : 0,
1620 .protocol = IPPROTO_IPV6,
1625 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
1626 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
1629 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
1630 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
1633 strncpy(p.name, name, sizeof(p.name));
1634 if (tunnel_ioctl("sit0", SIOCADDTUNNEL, &p) < 0)
1638 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
1640 struct ip_tunnel_6rd p6;
1642 memset(&p6, 0, sizeof(p6));
1644 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
1645 &p6.prefix, &mask) || mask > 128)
1647 p6.prefixlen = mask;
1649 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
1650 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
1651 &p6.relay_prefix, &mask) || mask > 32)
1653 p6.relay_prefixlen = mask;
1656 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
1657 system_del_ip_tunnel(name);
1662 } else if (!strcmp(str, "ipip6")) {
1663 struct ip6_tnl_parm p = {
1665 .proto = IPPROTO_IPIP,
1666 .hop_limit = (ttl) ? ttl : 64,
1670 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
1671 inet_pton(AF_INET6, blobmsg_data(cur), &p.laddr) < 1)
1674 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
1675 inet_pton(AF_INET6, blobmsg_data(cur), &p.raddr) < 1)
1678 strncpy(p.name, name, sizeof(p.name));
1679 if (tunnel_ioctl("ip6tnl0", SIOCADDTUNNEL, &p) < 0)