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 if (route->flags & DEVROUTE_MTU) {
1264 struct nlattr *metrics;
1266 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1267 goto nla_put_failure;
1269 nla_put_u32(msg, RTAX_MTU, route->mtu);
1271 nla_nest_end(msg, metrics);
1274 return system_rtnl_call(msg);
1281 int system_add_route(struct device *dev, struct device_route *route)
1283 return system_rt(dev, route, RTM_NEWROUTE);
1286 int system_del_route(struct device *dev, struct device_route *route)
1288 return system_rt(dev, route, RTM_DELROUTE);
1291 int system_flush_routes(void)
1293 const char *names[] = {
1294 "/proc/sys/net/ipv4/route/flush",
1295 "/proc/sys/net/ipv6/route/flush"
1299 for (i = 0; i < ARRAY_SIZE(names); i++) {
1300 fd = open(names[i], O_WRONLY);
1304 if (write(fd, "-1", 2)) {}
1310 bool system_resolve_rt_table(const char *name, unsigned int *id)
1314 unsigned int n, table = RT_TABLE_UNSPEC;
1316 /* first try to parse table as number */
1317 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1320 /* handle well known aliases */
1321 else if (!strcmp(name, "default"))
1322 table = RT_TABLE_DEFAULT;
1323 else if (!strcmp(name, "main"))
1324 table = RT_TABLE_MAIN;
1325 else if (!strcmp(name, "local"))
1326 table = RT_TABLE_LOCAL;
1328 /* try to look up name in /etc/iproute2/rt_tables */
1329 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1331 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1333 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1336 n = strtoul(e, NULL, 10);
1337 e = strtok(NULL, " \t\n");
1339 if (e && !strcmp(e, name))
1349 if (table == RT_TABLE_UNSPEC)
1352 /* do not consider main table special */
1353 if (table == RT_TABLE_MAIN)
1354 table = RT_TABLE_UNSPEC;
1360 static int system_iprule(struct iprule *rule, int cmd)
1362 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1365 struct rtmsg rtm = {
1366 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1367 .rtm_protocol = RTPROT_STATIC,
1368 .rtm_scope = RT_SCOPE_UNIVERSE,
1369 .rtm_table = RT_TABLE_UNSPEC,
1370 .rtm_type = RTN_UNSPEC,
1374 if (cmd == RTM_NEWRULE) {
1375 rtm.rtm_type = RTN_UNICAST;
1376 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1380 rtm.rtm_flags |= FIB_RULE_INVERT;
1382 if (rule->flags & IPRULE_SRC)
1383 rtm.rtm_src_len = rule->src_mask;
1385 if (rule->flags & IPRULE_DEST)
1386 rtm.rtm_dst_len = rule->dest_mask;
1388 if (rule->flags & IPRULE_TOS)
1389 rtm.rtm_tos = rule->tos;
1391 if (rule->flags & IPRULE_LOOKUP) {
1392 if (rule->lookup < 256)
1393 rtm.rtm_table = rule->lookup;
1396 if (rule->flags & IPRULE_ACTION)
1397 rtm.rtm_type = rule->action;
1398 else if (rule->flags & IPRULE_GOTO)
1399 rtm.rtm_type = FR_ACT_GOTO;
1400 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1401 rtm.rtm_type = FR_ACT_NOP;
1403 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1408 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1410 if (rule->flags & IPRULE_IN)
1411 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1413 if (rule->flags & IPRULE_OUT)
1414 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1416 if (rule->flags & IPRULE_SRC)
1417 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1419 if (rule->flags & IPRULE_DEST)
1420 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1422 if (rule->flags & IPRULE_PRIORITY)
1423 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1424 else if (cmd == RTM_NEWRULE)
1425 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1427 if (rule->flags & IPRULE_FWMARK)
1428 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1430 if (rule->flags & IPRULE_FWMASK)
1431 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1433 if (rule->flags & IPRULE_LOOKUP) {
1434 if (rule->lookup >= 256)
1435 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1438 if (rule->flags & IPRULE_GOTO)
1439 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1441 return system_rtnl_call(msg);
1444 int system_add_iprule(struct iprule *rule)
1446 return system_iprule(rule, RTM_NEWRULE);
1449 int system_del_iprule(struct iprule *rule)
1451 return system_iprule(rule, RTM_DELRULE);
1454 int system_flush_iprules(void)
1459 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1460 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1462 memset(&rule, 0, sizeof(rule));
1465 rule.flags = IPRULE_INET4 | 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);
1475 rule.priority = 32767;
1476 rule.lookup = RT_TABLE_DEFAULT;
1477 rv |= system_iprule(&rule, RTM_NEWRULE);
1480 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1483 rule.lookup = RT_TABLE_LOCAL;
1484 rv |= system_iprule(&rule, RTM_NEWRULE);
1486 rule.priority = 32766;
1487 rule.lookup = RT_TABLE_MAIN;
1488 rv |= system_iprule(&rule, RTM_NEWRULE);
1493 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1498 if (!strcmp(action, "local"))
1500 else if (!strcmp(action, "nat"))
1502 else if (!strcmp(action, "broadcast"))
1504 else if (!strcmp(action, "anycast"))
1506 else if (!strcmp(action, "multicast"))
1508 else if (!strcmp(action, "prohibit"))
1510 else if (!strcmp(action, "unreachable"))
1511 n = RTN_UNREACHABLE;
1512 else if (!strcmp(action, "blackhole"))
1514 else if (!strcmp(action, "xresolve"))
1516 else if (!strcmp(action, "unicast"))
1518 else if (!strcmp(action, "throw"))
1520 else if (!strcmp(action, "failed_policy"))
1521 n = RTN_FAILED_POLICY;
1523 n = strtoul(action, &e, 0);
1524 if (!e || *e || e == action || n > 255)
1532 time_t system_get_rtime(void)
1537 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1540 if (gettimeofday(&tv, NULL) == 0)
1547 #define IP_DF 0x4000
1550 static int tunnel_ioctl(const char *name, int cmd, void *p)
1554 memset(&ifr, 0, sizeof(ifr));
1555 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1556 ifr.ifr_ifru.ifru_data = p;
1557 return ioctl(sock_ioctl, cmd, &ifr);
1560 int system_del_ip_tunnel(const char *name)
1562 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
1565 int system_update_ipv6_mtu(struct device *dev, int mtu)
1569 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
1572 int fd = open(buf, O_RDWR);
1573 ssize_t len = read(fd, buf, sizeof(buf) - 1);
1580 if (!mtu || ret <= mtu)
1583 lseek(fd, 0, SEEK_SET);
1584 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) <= 0)
1592 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
1594 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
1595 struct blob_attr *cur;
1599 system_del_ip_tunnel(name);
1601 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
1602 blob_data(attr), blob_len(attr));
1604 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
1606 str = blobmsg_data(cur);
1608 if ((cur = tb[TUNNEL_ATTR_DF]))
1609 set_df = blobmsg_get_bool(cur);
1611 unsigned int ttl = 0;
1612 if ((cur = tb[TUNNEL_ATTR_TTL])) {
1613 ttl = blobmsg_get_u32(cur);
1614 if (ttl > 255 || (!set_df && ttl))
1618 unsigned int link = 0;
1619 if ((cur = tb[TUNNEL_ATTR_LINK])) {
1620 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
1624 if (iface->l3_dev.dev)
1625 link = iface->l3_dev.dev->ifindex;
1628 if (!strcmp(str, "sit")) {
1629 struct ip_tunnel_parm p = {
1634 .frag_off = set_df ? htons(IP_DF) : 0,
1635 .protocol = IPPROTO_IPV6,
1640 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
1641 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
1644 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
1645 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
1648 strncpy(p.name, name, sizeof(p.name));
1649 if (tunnel_ioctl("sit0", SIOCADDTUNNEL, &p) < 0)
1653 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
1655 struct ip_tunnel_6rd p6;
1657 memset(&p6, 0, sizeof(p6));
1659 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
1660 &p6.prefix, &mask) || mask > 128)
1662 p6.prefixlen = mask;
1664 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
1665 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
1666 &p6.relay_prefix, &mask) || mask > 32)
1668 p6.relay_prefixlen = mask;
1671 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
1672 system_del_ip_tunnel(name);
1677 } else if (!strcmp(str, "ipip6")) {
1678 struct ip6_tnl_parm p = {
1680 .proto = IPPROTO_IPIP,
1681 .hop_limit = (ttl) ? ttl : 64,
1685 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
1686 inet_pton(AF_INET6, blobmsg_data(cur), &p.laddr) < 1)
1689 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
1690 inet_pton(AF_INET6, blobmsg_data(cur), &p.raddr) < 1)
1693 strncpy(p.name, name, sizeof(p.name));
1694 if (tunnel_ioctl("ip6tnl0", SIOCADDTUNNEL, &p) < 0)