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>
6 * Copyright (C) 2014 Gioacchino Mazzurco <gio@eigenlab.org>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2
10 * as published by the Free Software Foundation
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
19 #include <sys/socket.h>
20 #include <sys/ioctl.h>
22 #include <sys/syscall.h>
25 #include <net/if_arp.h>
27 #include <arpa/inet.h>
28 #include <netinet/in.h>
30 #include <linux/rtnetlink.h>
31 #include <linux/sockios.h>
33 #include <linux/if_addr.h>
34 #include <linux/if_link.h>
35 #include <linux/if_vlan.h>
36 #include <linux/if_bridge.h>
37 #include <linux/if_tunnel.h>
38 #include <linux/ip6_tunnel.h>
39 #include <linux/ethtool.h>
40 #include <linux/fib_rules.h>
41 #include <linux/version.h>
43 #ifndef RTN_FAILED_POLICY
44 #define RTN_FAILED_POLICY 12
47 #ifndef RT_TABLE_PRELOCAL
48 #define RT_TABLE_PRELOCAL 128
51 #ifndef IFA_F_NOPREFIXROUTE
52 #define IFA_F_NOPREFIXROUTE 0x200
56 #define IFA_FLAGS (IFA_MULTICAST + 1)
66 #include <netlink/msg.h>
67 #include <netlink/attr.h>
68 #include <netlink/socket.h>
69 #include <libubox/uloop.h>
76 struct uloop_fd uloop;
81 static int sock_ioctl = -1;
82 static struct nl_sock *sock_rtnl = NULL;
84 static int cb_rtnl_event(struct nl_msg *msg, void *arg);
85 static void handle_hotplug_event(struct uloop_fd *u, unsigned int events);
87 static char dev_buf[256];
90 handler_nl_event(struct uloop_fd *u, unsigned int events)
92 struct event_socket *ev = container_of(u, struct event_socket, uloop);
94 socklen_t errlen = sizeof(err);
97 nl_recvmsgs_default(ev->sock);
101 if (getsockopt(u->fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen))
106 // Increase rx buffer size on netlink socket
108 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
111 // Request full dump since some info got dropped
112 struct rtgenmsg msg = { .rtgen_family = AF_UNSPEC };
113 nl_send_simple(ev->sock, RTM_GETLINK, NLM_F_DUMP, &msg, sizeof(msg));
123 uloop_fd_delete(&ev->uloop);
127 static struct nl_sock *
128 create_socket(int protocol, int groups)
130 struct nl_sock *sock;
132 sock = nl_socket_alloc();
137 nl_join_groups(sock, groups);
139 if (nl_connect(sock, protocol))
146 create_raw_event_socket(struct event_socket *ev, int protocol, int groups,
147 uloop_fd_handler cb, int flags)
149 ev->sock = create_socket(protocol, groups);
153 ev->uloop.fd = nl_socket_get_fd(ev->sock);
155 if (uloop_fd_add(&ev->uloop, ULOOP_READ|flags))
162 create_event_socket(struct event_socket *ev, int protocol,
163 int (*cb)(struct nl_msg *msg, void *arg))
165 if (!create_raw_event_socket(ev, protocol, 0, handler_nl_event, ULOOP_ERROR_CB))
168 // Install the valid custom callback handler
169 nl_socket_modify_cb(ev->sock, NL_CB_VALID, NL_CB_CUSTOM, cb, NULL);
171 // Disable sequence number checking on event sockets
172 nl_socket_disable_seq_check(ev->sock);
174 // Increase rx buffer size to 65K on event sockets
176 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
183 system_rtn_aton(const char *src, unsigned int *dst)
188 if (!strcmp(src, "local"))
190 else if (!strcmp(src, "nat"))
192 else if (!strcmp(src, "broadcast"))
194 else if (!strcmp(src, "anycast"))
196 else if (!strcmp(src, "multicast"))
198 else if (!strcmp(src, "prohibit"))
200 else if (!strcmp(src, "unreachable"))
202 else if (!strcmp(src, "blackhole"))
204 else if (!strcmp(src, "xresolve"))
206 else if (!strcmp(src, "unicast"))
208 else if (!strcmp(src, "throw"))
210 else if (!strcmp(src, "failed_policy"))
211 n = RTN_FAILED_POLICY;
213 n = strtoul(src, &e, 0);
214 if (!e || *e || e == src || n > 255)
223 system_tos_aton(const char *src, unsigned *dst)
227 *dst = strtoul(src, &e, 16);
228 if (e == src || *e || *dst > 255)
234 int system_init(void)
236 static struct event_socket rtnl_event;
237 static struct event_socket hotplug_event;
239 sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0);
240 system_fd_set_cloexec(sock_ioctl);
242 // Prepare socket for routing / address control
243 sock_rtnl = create_socket(NETLINK_ROUTE, 0);
247 if (!create_event_socket(&rtnl_event, NETLINK_ROUTE, cb_rtnl_event))
250 if (!create_raw_event_socket(&hotplug_event, NETLINK_KOBJECT_UEVENT, 1,
251 handle_hotplug_event, 0))
254 // Receive network link events form kernel
255 nl_socket_add_membership(rtnl_event.sock, RTNLGRP_LINK);
260 static void system_set_sysctl(const char *path, const char *val)
264 fd = open(path, O_WRONLY);
268 if (write(fd, val, strlen(val))) {}
272 static void system_set_dev_sysctl(const char *path, const char *device, const char *val)
274 snprintf(dev_buf, sizeof(dev_buf), path, device);
275 system_set_sysctl(dev_buf, val);
278 static void system_set_disable_ipv6(struct device *dev, const char *val)
280 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val);
283 static void system_set_rpfilter(struct device *dev, const char *val)
285 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter", dev->ifname, val);
288 static void system_set_acceptlocal(struct device *dev, const char *val)
290 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local", dev->ifname, val);
293 static void system_set_igmpversion(struct device *dev, const char *val)
295 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version", dev->ifname, val);
298 static void system_set_mldversion(struct device *dev, const char *val)
300 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version", dev->ifname, val);
303 static void system_set_neigh4reachabletime(struct device *dev, const char *val)
305 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms", dev->ifname, val);
308 static void system_set_neigh6reachabletime(struct device *dev, const char *val)
310 system_set_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms", dev->ifname, val);
313 static int system_get_sysctl(const char *path, char *buf, const size_t buf_sz)
315 int fd = -1, ret = -1;
317 fd = open(path, O_RDONLY);
321 ssize_t len = read(fd, buf, buf_sz - 1);
335 system_get_dev_sysctl(const char *path, const char *device, char *buf, const size_t buf_sz)
337 snprintf(dev_buf, sizeof(dev_buf), path, device);
338 return system_get_sysctl(dev_buf, buf, buf_sz);
341 static int system_get_disable_ipv6(struct device *dev, char *buf, const size_t buf_sz)
343 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6",
344 dev->ifname, buf, buf_sz);
347 static int system_get_rpfilter(struct device *dev, char *buf, const size_t buf_sz)
349 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter",
350 dev->ifname, buf, buf_sz);
353 static int system_get_acceptlocal(struct device *dev, char *buf, const size_t buf_sz)
355 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local",
356 dev->ifname, buf, buf_sz);
359 static int system_get_igmpversion(struct device *dev, char *buf, const size_t buf_sz)
361 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version",
362 dev->ifname, buf, buf_sz);
365 static int system_get_mldversion(struct device *dev, char *buf, const size_t buf_sz)
367 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version",
368 dev->ifname, buf, buf_sz);
371 static int system_get_neigh4reachabletime(struct device *dev, char *buf, const size_t buf_sz)
373 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms",
374 dev->ifname, buf, buf_sz);
377 static int system_get_neigh6reachabletime(struct device *dev, char *buf, const size_t buf_sz)
379 return system_get_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms",
380 dev->ifname, buf, buf_sz);
383 // Evaluate netlink messages
384 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
386 struct nlmsghdr *nh = nlmsg_hdr(msg);
387 struct nlattr *nla[__IFLA_MAX];
391 if (nh->nlmsg_type != RTM_NEWLINK)
394 nlmsg_parse(nh, sizeof(struct ifinfomsg), nla, __IFLA_MAX - 1, NULL);
395 if (!nla[IFLA_IFNAME])
398 struct device *dev = device_get(nla_data(nla[IFLA_IFNAME]), false);
399 if (!dev || dev->type->keep_link_status)
402 if (!system_get_dev_sysctl("/sys/class/net/%s/carrier", dev->ifname, buf, sizeof(buf)))
403 link_state = strtoul(buf, NULL, 0);
405 device_set_link(dev, link_state ? true : false);
412 handle_hotplug_msg(char *data, int size)
414 const char *subsystem = NULL, *interface = NULL;
415 char *cur, *end, *sep;
420 if (!strncmp(data, "add@", 4))
422 else if (!strncmp(data, "remove@", 7))
427 skip = strlen(data) + 1;
430 for (cur = data + skip; cur < end; cur += skip) {
431 skip = strlen(cur) + 1;
433 sep = strchr(cur, '=');
438 if (!strcmp(cur, "INTERFACE"))
440 else if (!strcmp(cur, "SUBSYSTEM")) {
442 if (strcmp(subsystem, "net") != 0)
445 if (subsystem && interface)
451 dev = device_get(interface, false);
455 if (dev->type != &simple_device_type)
458 if (add && system_if_force_external(dev->ifname))
461 device_set_present(dev, add);
465 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
467 struct event_socket *ev = container_of(u, struct event_socket, uloop);
468 struct sockaddr_nl nla;
469 unsigned char *buf = NULL;
472 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
474 handle_hotplug_msg((char *) buf, size);
480 static int system_rtnl_call(struct nl_msg *msg)
484 ret = nl_send_auto_complete(sock_rtnl, msg);
490 return nl_wait_for_ack(sock_rtnl);
493 int system_bridge_delbr(struct device *bridge)
495 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
498 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
502 memset(&ifr, 0, sizeof(ifr));
504 ifr.ifr_ifindex = dev->ifindex;
507 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
508 return ioctl(sock_ioctl, cmd, &ifr);
511 static bool system_is_bridge(const char *name, char *buf, int buflen)
515 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
516 if (stat(buf, &st) < 0)
522 static char *system_get_bridge(const char *name, char *buf, int buflen)
528 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
529 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
533 len = readlink(gl.gl_pathv[0], buf, buflen);
541 path = strrchr(buf, '/');
548 static void system_bridge_set_wireless(const char *bridge, const char *dev)
550 snprintf(dev_buf, sizeof(dev_buf),
551 "/sys/devices/virtual/net/%s/brif/%s/multicast_to_unicast",
553 system_set_sysctl(dev_buf, "1");
556 int system_bridge_addif(struct device *bridge, struct device *dev)
561 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
562 if (!oldbr || strcmp(oldbr, bridge->ifname) != 0)
563 ret = system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
566 system_bridge_set_wireless(bridge->ifname, dev->ifname);
571 int system_bridge_delif(struct device *bridge, struct device *dev)
573 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
576 int system_if_resolve(struct device *dev)
579 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
580 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
581 return ifr.ifr_ifindex;
586 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
590 memset(&ifr, 0, sizeof(ifr));
591 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
592 ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
593 ifr.ifr_flags |= add;
594 ifr.ifr_flags &= ~rem;
595 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
607 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
609 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
611 return ifa->ifa_index == ifindex;
614 static bool check_route(struct nlmsghdr *hdr, int ifindex)
616 struct rtmsg *r = NLMSG_DATA(hdr);
617 struct nlattr *tb[__RTA_MAX];
619 if (r->rtm_protocol == RTPROT_KERNEL &&
620 r->rtm_family == AF_INET6)
623 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
627 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
630 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
635 static int cb_clear_event(struct nl_msg *msg, void *arg)
637 struct clear_data *clr = arg;
638 struct nlmsghdr *hdr = nlmsg_hdr(msg);
639 bool (*cb)(struct nlmsghdr *, int ifindex);
645 if (hdr->nlmsg_type != RTM_NEWADDR)
652 if (hdr->nlmsg_type != RTM_NEWROUTE)
659 if (hdr->nlmsg_type != RTM_NEWRULE)
668 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
671 if (type == RTM_DELRULE)
672 D(SYSTEM, "Remove a rule\n");
674 D(SYSTEM, "Remove %s from device %s\n",
675 type == RTM_DELADDR ? "an address" : "a route",
677 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
678 hdr = nlmsg_hdr(clr->msg);
679 hdr->nlmsg_type = type;
680 hdr->nlmsg_flags = NLM_F_REQUEST;
682 nl_socket_disable_auto_ack(sock_rtnl);
683 nl_send_auto_complete(sock_rtnl, clr->msg);
684 nl_socket_enable_auto_ack(sock_rtnl);
690 cb_finish_event(struct nl_msg *msg, void *arg)
698 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
701 *pending = err->error;
706 system_if_clear_entries(struct device *dev, int type, int af)
708 struct clear_data clr;
709 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
712 .rtm_flags = RTM_F_CLONED,
714 int flags = NLM_F_DUMP;
723 clr.size = sizeof(struct rtgenmsg);
726 clr.size = sizeof(struct rtmsg);
735 clr.msg = nlmsg_alloc_simple(type, flags);
739 nlmsg_append(clr.msg, &rtm, clr.size, 0);
740 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
741 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
742 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
744 nl_send_auto_complete(sock_rtnl, clr.msg);
746 nl_recvmsgs(sock_rtnl, cb);
754 * Clear bridge (membership) state and bring down device
756 void system_if_clear_state(struct device *dev)
758 static char buf[256];
761 device_set_ifindex(dev, system_if_resolve(dev));
762 if (dev->external || !dev->ifindex)
765 system_if_flags(dev->ifname, 0, IFF_UP);
767 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
768 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
769 system_bridge_delbr(dev);
773 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
775 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
776 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
779 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
780 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
781 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
782 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
783 system_set_disable_ipv6(dev, "0");
786 static inline unsigned long
787 sec_to_jiffies(int val)
789 return (unsigned long) val * 100;
792 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
795 unsigned long args[4] = {};
797 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
800 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
801 args[1] = !!cfg->stp;
802 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
804 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
805 args[1] = sec_to_jiffies(cfg->forward_delay);
806 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
808 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
809 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
811 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier",
812 bridge->ifname, cfg->multicast_querier ? "1" : "0");
814 snprintf(buf, sizeof(buf), "%i", cfg->hash_max);
815 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/hash_max",
816 bridge->ifname, buf);
818 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
819 args[1] = cfg->priority;
820 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
822 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
823 args[0] = BRCTL_SET_AGEING_TIME;
824 args[1] = sec_to_jiffies(cfg->ageing_time);
825 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
828 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
829 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
830 args[1] = sec_to_jiffies(cfg->hello_time);
831 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
834 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
835 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
836 args[1] = sec_to_jiffies(cfg->max_age);
837 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
843 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
846 struct nlattr *linkinfo, *data;
847 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
849 static const struct {
851 enum macvlan_mode val;
853 { "private", MACVLAN_MODE_PRIVATE },
854 { "vepa", MACVLAN_MODE_VEPA },
855 { "bridge", MACVLAN_MODE_BRIDGE },
856 { "passthru", MACVLAN_MODE_PASSTHRU },
859 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
864 nlmsg_append(msg, &iim, sizeof(iim), 0);
866 if (cfg->flags & MACVLAN_OPT_MACADDR)
867 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
868 nla_put_string(msg, IFLA_IFNAME, macvlan->ifname);
869 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
871 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
872 goto nla_put_failure;
874 nla_put_string(msg, IFLA_INFO_KIND, "macvlan");
876 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
877 goto nla_put_failure;
880 for (i = 0; i < ARRAY_SIZE(modes); i++) {
881 if (strcmp(cfg->mode, modes[i].name) != 0)
884 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
889 nla_nest_end(msg, data);
890 nla_nest_end(msg, linkinfo);
892 rv = system_rtnl_call(msg);
894 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
903 static int system_link_del(const char *ifname)
906 struct ifinfomsg iim = {
907 .ifi_family = AF_UNSPEC,
911 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
916 nlmsg_append(msg, &iim, sizeof(iim), 0);
917 nla_put_string(msg, IFLA_IFNAME, ifname);
918 return system_rtnl_call(msg);
921 int system_macvlan_del(struct device *macvlan)
923 return system_link_del(macvlan->ifname);
926 static int system_vlan(struct device *dev, int id)
928 struct vlan_ioctl_args ifr = {
929 .cmd = SET_VLAN_NAME_TYPE_CMD,
930 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
933 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
936 ifr.cmd = DEL_VLAN_CMD;
939 ifr.cmd = ADD_VLAN_CMD;
942 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
943 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
946 int system_vlan_add(struct device *dev, int id)
948 return system_vlan(dev, id);
951 int system_vlan_del(struct device *dev)
953 return system_vlan(dev, -1);
956 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
959 struct nlattr *linkinfo, *data;
960 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
963 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
968 nlmsg_append(msg, &iim, sizeof(iim), 0);
969 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
970 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
972 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
973 goto nla_put_failure;
975 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
977 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
978 goto nla_put_failure;
980 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
982 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
983 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
985 if(cfg->proto == VLAN_PROTO_8021AD)
986 netifd_log_message(L_WARNING, "%s Your kernel is older than linux 3.10.0, 802.1ad is not supported defaulting to 802.1q", vlandev->type->name);
989 nla_nest_end(msg, data);
990 nla_nest_end(msg, linkinfo);
992 rv = system_rtnl_call(msg);
994 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
1003 int system_vlandev_del(struct device *vlandev)
1005 return system_link_del(vlandev->ifname);
1009 system_if_get_settings(struct device *dev, struct device_settings *s)
1014 memset(&ifr, 0, sizeof(ifr));
1015 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1017 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
1018 s->mtu = ifr.ifr_mtu;
1019 s->flags |= DEV_OPT_MTU;
1022 s->mtu6 = system_update_ipv6_mtu(dev, 0);
1024 s->flags |= DEV_OPT_MTU6;
1026 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
1027 s->txqueuelen = ifr.ifr_qlen;
1028 s->flags |= DEV_OPT_TXQUEUELEN;
1031 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
1032 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
1033 s->flags |= DEV_OPT_MACADDR;
1036 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
1037 s->ipv6 = !strtoul(buf, NULL, 0);
1038 s->flags |= DEV_OPT_IPV6;
1041 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
1042 s->promisc = ifr.ifr_flags & IFF_PROMISC;
1043 s->flags |= DEV_OPT_PROMISC;
1046 if (!system_get_rpfilter(dev, buf, sizeof(buf))) {
1047 s->rpfilter = strtoul(buf, NULL, 0);
1048 s->flags |= DEV_OPT_RPFILTER;
1051 if (!system_get_acceptlocal(dev, buf, sizeof(buf))) {
1052 s->acceptlocal = strtoul(buf, NULL, 0);
1053 s->flags |= DEV_OPT_ACCEPTLOCAL;
1056 if (!system_get_igmpversion(dev, buf, sizeof(buf))) {
1057 s->igmpversion = strtoul(buf, NULL, 0);
1058 s->flags |= DEV_OPT_IGMPVERSION;
1061 if (!system_get_mldversion(dev, buf, sizeof(buf))) {
1062 s->mldversion = strtoul(buf, NULL, 0);
1063 s->flags |= DEV_OPT_MLDVERSION;
1066 if (!system_get_neigh4reachabletime(dev, buf, sizeof(buf))) {
1067 s->neigh4reachabletime = strtoul(buf, NULL, 0);
1068 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1071 if (!system_get_neigh6reachabletime(dev, buf, sizeof(buf))) {
1072 s->neigh6reachabletime = strtoul(buf, NULL, 0);
1073 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1078 system_if_set_rps_xps_val(const char *path, int val)
1084 if (glob(path, 0, NULL, &gl))
1087 snprintf(val_buf, sizeof(val_buf), "%x", val);
1088 for (i = 0; i < gl.gl_pathc; i++)
1089 system_set_sysctl(gl.gl_pathv[i], val_buf);
1093 system_if_apply_rps_xps(struct device *dev, struct device_settings *s)
1095 long n_cpus = sysconf(_SC_NPROCESSORS_ONLN);
1101 val = (1 << n_cpus) - 1;
1102 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/rps_cpus", dev->ifname);
1103 system_if_set_rps_xps_val(dev_buf, s->rps ? val : 0);
1105 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/xps_cpus", dev->ifname);
1106 system_if_set_rps_xps_val(dev_buf, s->xps ? val : 0);
1110 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
1114 memset(&ifr, 0, sizeof(ifr));
1115 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1116 if (s->flags & DEV_OPT_MTU & apply_mask) {
1117 ifr.ifr_mtu = s->mtu;
1118 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
1119 s->flags &= ~DEV_OPT_MTU;
1121 if (s->flags & DEV_OPT_MTU6 & apply_mask) {
1122 system_update_ipv6_mtu(dev, s->mtu6);
1124 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
1125 ifr.ifr_qlen = s->txqueuelen;
1126 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
1127 s->flags &= ~DEV_OPT_TXQUEUELEN;
1129 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
1130 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
1131 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
1132 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
1133 s->flags &= ~DEV_OPT_MACADDR;
1135 if (s->flags & DEV_OPT_IPV6 & apply_mask)
1136 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
1137 if (s->flags & DEV_OPT_PROMISC & apply_mask) {
1138 if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
1139 !s->promisc ? IFF_PROMISC : 0) < 0)
1140 s->flags &= ~DEV_OPT_PROMISC;
1142 if (s->flags & DEV_OPT_RPFILTER & apply_mask) {
1145 snprintf(buf, sizeof(buf), "%d", s->rpfilter);
1146 system_set_rpfilter(dev, buf);
1148 if (s->flags & DEV_OPT_ACCEPTLOCAL & apply_mask)
1149 system_set_acceptlocal(dev, s->acceptlocal ? "1" : "0");
1150 if (s->flags & DEV_OPT_IGMPVERSION & apply_mask) {
1153 snprintf(buf, sizeof(buf), "%d", s->igmpversion);
1154 system_set_igmpversion(dev, buf);
1156 if (s->flags & DEV_OPT_MLDVERSION & apply_mask) {
1159 snprintf(buf, sizeof(buf), "%d", s->mldversion);
1160 system_set_mldversion(dev, buf);
1162 if (s->flags & DEV_OPT_NEIGHREACHABLETIME & apply_mask) {
1165 snprintf(buf, sizeof(buf), "%d", s->neigh4reachabletime);
1166 system_set_neigh4reachabletime(dev, buf);
1167 snprintf(buf, sizeof(buf), "%d", s->neigh6reachabletime);
1168 system_set_neigh6reachabletime(dev, buf);
1171 system_if_apply_rps_xps(dev, s);
1174 int system_if_up(struct device *dev)
1176 system_if_get_settings(dev, &dev->orig_settings);
1177 /* Only keep orig settings based on what needs to be set */
1178 dev->orig_settings.flags &= dev->settings.flags;
1179 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
1180 return system_if_flags(dev->ifname, IFF_UP, 0);
1183 int system_if_down(struct device *dev)
1185 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
1186 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
1190 struct if_check_data {
1196 #ifndef IFF_LOWER_UP
1197 #define IFF_LOWER_UP 0x10000
1200 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1202 struct nlmsghdr *nh = nlmsg_hdr(msg);
1203 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1204 struct if_check_data *chk = (struct if_check_data *)arg;
1206 if (nh->nlmsg_type != RTM_NEWLINK)
1209 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1210 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1215 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1217 struct if_check_data *chk = (struct if_check_data *)arg;
1222 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1224 struct if_check_data *chk = (struct if_check_data *)arg;
1226 device_set_present(chk->dev, false);
1227 device_set_link(chk->dev, false);
1228 chk->pending = err->error;
1233 int system_if_check(struct device *dev)
1235 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1237 struct ifinfomsg ifi = {
1238 .ifi_family = AF_UNSPEC,
1241 struct if_check_data chk = {
1247 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1248 if (!msg || nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1249 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1252 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1253 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1254 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1256 nl_send_auto_complete(sock_rtnl, msg);
1257 while (chk.pending > 0)
1258 nl_recvmsgs(sock_rtnl, cb);
1269 system_if_get_parent(struct device *dev)
1271 char buf[64], *devname;
1272 int ifindex, iflink, len;
1275 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1276 f = fopen(buf, "r");
1280 len = fread(buf, 1, sizeof(buf) - 1, f);
1287 iflink = strtoul(buf, NULL, 0);
1288 ifindex = system_if_resolve(dev);
1289 if (!iflink || iflink == ifindex)
1292 devname = if_indextoname(iflink, buf);
1296 return device_get(devname, true);
1300 read_string_file(int dir_fd, const char *file, char *buf, int len)
1306 fd = openat(dir_fd, file, O_RDONLY);
1311 len = read(fd, buf, len - 1);
1315 } else if (len > 0) {
1318 c = strchr(buf, '\n');
1331 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1336 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1338 *val = strtoull(buf, NULL, 0);
1343 /* Assume advertised flags == supported flags */
1344 static const struct {
1347 } ethtool_link_modes[] = {
1348 { ADVERTISED_10baseT_Half, "10H" },
1349 { ADVERTISED_10baseT_Full, "10F" },
1350 { ADVERTISED_100baseT_Half, "100H" },
1351 { ADVERTISED_100baseT_Full, "100F" },
1352 { ADVERTISED_1000baseT_Half, "1000H" },
1353 { ADVERTISED_1000baseT_Full, "1000F" },
1356 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1359 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1360 if (mask & ethtool_link_modes[i].mask)
1361 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1366 system_if_force_external(const char *ifname)
1371 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1372 return stat(buf, &s) == 0;
1376 system_if_dump_info(struct device *dev, struct blob_buf *b)
1378 struct ethtool_cmd ecmd;
1384 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
1385 dir_fd = open(buf, O_DIRECTORY);
1387 memset(&ecmd, 0, sizeof(ecmd));
1388 memset(&ifr, 0, sizeof(ifr));
1389 strcpy(ifr.ifr_name, dev->ifname);
1390 ifr.ifr_data = (caddr_t) &ecmd;
1391 ecmd.cmd = ETHTOOL_GSET;
1393 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1394 c = blobmsg_open_array(b, "link-advertising");
1395 system_add_link_modes(b, ecmd.advertising);
1396 blobmsg_close_array(b, c);
1398 c = blobmsg_open_array(b, "link-supported");
1399 system_add_link_modes(b, ecmd.supported);
1400 blobmsg_close_array(b, c);
1402 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1403 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1404 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1405 blobmsg_add_string_buffer(b);
1413 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1415 const char *const counters[] = {
1416 "collisions", "rx_frame_errors", "tx_compressed",
1417 "multicast", "rx_length_errors", "tx_dropped",
1418 "rx_bytes", "rx_missed_errors", "tx_errors",
1419 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1420 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1421 "rx_dropped", "tx_aborted_errors", "tx_packets",
1422 "rx_errors", "tx_bytes", "tx_window_errors",
1423 "rx_fifo_errors", "tx_carrier_errors",
1430 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1431 stats_dir = open(buf, O_DIRECTORY);
1435 for (i = 0; i < ARRAY_SIZE(counters); i++)
1436 if (read_uint64_file(stats_dir, counters[i], &val))
1437 blobmsg_add_u64(b, counters[i], val);
1443 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1445 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1446 int alen = v4 ? 4 : 16;
1447 unsigned int flags = 0;
1448 struct ifaddrmsg ifa = {
1449 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1450 .ifa_prefixlen = addr->mask,
1451 .ifa_index = dev->ifindex,
1455 if (cmd == RTM_NEWADDR)
1456 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1458 msg = nlmsg_alloc_simple(cmd, flags);
1462 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1463 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1465 if (addr->broadcast)
1466 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1467 if (addr->point_to_point)
1468 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1470 time_t now = system_get_rtime();
1471 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1473 if (addr->preferred_until) {
1474 int64_t preferred = addr->preferred_until - now;
1477 else if (preferred > UINT32_MAX)
1478 preferred = UINT32_MAX;
1480 cinfo.ifa_prefered = preferred;
1483 if (addr->valid_until) {
1484 int64_t valid = addr->valid_until - now;
1487 else if (valid > UINT32_MAX)
1490 cinfo.ifa_valid = valid;
1493 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1495 if (cmd == RTM_NEWADDR && (addr->flags & DEVADDR_OFFLINK))
1496 nla_put_u32(msg, IFA_FLAGS, IFA_F_NOPREFIXROUTE);
1499 return system_rtnl_call(msg);
1502 int system_add_address(struct device *dev, struct device_addr *addr)
1504 return system_addr(dev, addr, RTM_NEWADDR);
1507 int system_del_address(struct device *dev, struct device_addr *addr)
1509 return system_addr(dev, addr, RTM_DELADDR);
1512 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1514 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1516 unsigned int flags = 0;
1519 have_gw = !!route->nexthop.in.s_addr;
1521 have_gw = route->nexthop.in6.s6_addr32[0] ||
1522 route->nexthop.in6.s6_addr32[1] ||
1523 route->nexthop.in6.s6_addr32[2] ||
1524 route->nexthop.in6.s6_addr32[3];
1526 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1527 ? route->table : RT_TABLE_MAIN;
1529 struct rtmsg rtm = {
1530 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1531 .rtm_dst_len = route->mask,
1532 .rtm_src_len = route->sourcemask,
1533 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1534 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
1535 .rtm_scope = RT_SCOPE_NOWHERE,
1536 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1537 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1541 if (cmd == RTM_NEWROUTE) {
1542 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1544 if (!dev) { // Add null-route
1545 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1546 rtm.rtm_type = RTN_UNREACHABLE;
1549 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1552 if (route->flags & DEVROUTE_TYPE) {
1553 rtm.rtm_type = route->type;
1554 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
1555 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
1556 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
1557 rtm.rtm_table = RT_TABLE_LOCAL;
1560 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT) {
1561 rtm.rtm_scope = RT_SCOPE_HOST;
1562 } else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
1563 rtm.rtm_type == RTN_ANYCAST) {
1564 rtm.rtm_scope = RT_SCOPE_LINK;
1565 } else if (rtm.rtm_type == RTN_BLACKHOLE || rtm.rtm_type == RTN_UNREACHABLE ||
1566 rtm.rtm_type == RTN_PROHIBIT || rtm.rtm_type == RTN_FAILED_POLICY) {
1567 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1572 msg = nlmsg_alloc_simple(cmd, flags);
1576 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1579 nla_put(msg, RTA_DST, alen, &route->addr);
1581 if (route->sourcemask) {
1582 if (rtm.rtm_family == AF_INET)
1583 nla_put(msg, RTA_PREFSRC, alen, &route->source);
1585 nla_put(msg, RTA_SRC, alen, &route->source);
1588 if (route->metric > 0)
1589 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1592 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1595 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1598 nla_put_u32(msg, RTA_TABLE, table);
1600 if (route->flags & DEVROUTE_MTU) {
1601 struct nlattr *metrics;
1603 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1604 goto nla_put_failure;
1606 nla_put_u32(msg, RTAX_MTU, route->mtu);
1608 nla_nest_end(msg, metrics);
1611 return system_rtnl_call(msg);
1618 int system_add_route(struct device *dev, struct device_route *route)
1620 return system_rt(dev, route, RTM_NEWROUTE);
1623 int system_del_route(struct device *dev, struct device_route *route)
1625 return system_rt(dev, route, RTM_DELROUTE);
1628 int system_flush_routes(void)
1630 const char *names[] = {
1631 "/proc/sys/net/ipv4/route/flush",
1632 "/proc/sys/net/ipv6/route/flush"
1636 for (i = 0; i < ARRAY_SIZE(names); i++) {
1637 fd = open(names[i], O_WRONLY);
1641 if (write(fd, "-1", 2)) {}
1647 bool system_resolve_rt_type(const char *type, unsigned int *id)
1649 return system_rtn_aton(type, id);
1652 bool system_resolve_rt_table(const char *name, unsigned int *id)
1656 unsigned int n, table = RT_TABLE_UNSPEC;
1658 /* first try to parse table as number */
1659 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1662 /* handle well known aliases */
1663 else if (!strcmp(name, "default"))
1664 table = RT_TABLE_DEFAULT;
1665 else if (!strcmp(name, "main"))
1666 table = RT_TABLE_MAIN;
1667 else if (!strcmp(name, "local"))
1668 table = RT_TABLE_LOCAL;
1669 else if (!strcmp(name, "prelocal"))
1670 table = RT_TABLE_PRELOCAL;
1672 /* try to look up name in /etc/iproute2/rt_tables */
1673 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1675 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1677 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1680 n = strtoul(e, NULL, 10);
1681 e = strtok(NULL, " \t\n");
1683 if (e && !strcmp(e, name))
1693 if (table == RT_TABLE_UNSPEC)
1700 bool system_is_default_rt_table(unsigned int id)
1702 return (id == RT_TABLE_MAIN);
1705 bool system_resolve_rpfilter(const char *filter, unsigned int *id)
1710 if (!strcmp(filter, "strict"))
1712 else if (!strcmp(filter, "loose"))
1715 n = strtoul(filter, &e, 0);
1716 if (*e || e == filter || n > 2)
1724 static int system_iprule(struct iprule *rule, int cmd)
1726 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1729 struct rtmsg rtm = {
1730 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1731 .rtm_protocol = RTPROT_STATIC,
1732 .rtm_scope = RT_SCOPE_UNIVERSE,
1733 .rtm_table = RT_TABLE_UNSPEC,
1734 .rtm_type = RTN_UNSPEC,
1738 if (cmd == RTM_NEWRULE) {
1739 rtm.rtm_type = RTN_UNICAST;
1740 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1744 rtm.rtm_flags |= FIB_RULE_INVERT;
1746 if (rule->flags & IPRULE_SRC)
1747 rtm.rtm_src_len = rule->src_mask;
1749 if (rule->flags & IPRULE_DEST)
1750 rtm.rtm_dst_len = rule->dest_mask;
1752 if (rule->flags & IPRULE_TOS)
1753 rtm.rtm_tos = rule->tos;
1755 if (rule->flags & IPRULE_LOOKUP) {
1756 if (rule->lookup < 256)
1757 rtm.rtm_table = rule->lookup;
1760 if (rule->flags & IPRULE_ACTION)
1761 rtm.rtm_type = rule->action;
1762 else if (rule->flags & IPRULE_GOTO)
1763 rtm.rtm_type = FR_ACT_GOTO;
1764 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1765 rtm.rtm_type = FR_ACT_NOP;
1767 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1772 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1774 if (rule->flags & IPRULE_IN)
1775 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1777 if (rule->flags & IPRULE_OUT)
1778 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1780 if (rule->flags & IPRULE_SRC)
1781 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1783 if (rule->flags & IPRULE_DEST)
1784 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1786 if (rule->flags & IPRULE_PRIORITY)
1787 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1788 else if (cmd == RTM_NEWRULE)
1789 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1791 if (rule->flags & IPRULE_FWMARK)
1792 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1794 if (rule->flags & IPRULE_FWMASK)
1795 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1797 if (rule->flags & IPRULE_LOOKUP) {
1798 if (rule->lookup >= 256)
1799 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1802 if (rule->flags & IPRULE_GOTO)
1803 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1805 return system_rtnl_call(msg);
1808 int system_add_iprule(struct iprule *rule)
1810 return system_iprule(rule, RTM_NEWRULE);
1813 int system_del_iprule(struct iprule *rule)
1815 return system_iprule(rule, RTM_DELRULE);
1818 int system_flush_iprules(void)
1823 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1824 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1826 memset(&rule, 0, sizeof(rule));
1829 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1832 rule.lookup = RT_TABLE_PRELOCAL;
1833 rv |= system_iprule(&rule, RTM_NEWRULE);
1836 rule.lookup = RT_TABLE_LOCAL;
1837 rv |= system_iprule(&rule, RTM_NEWRULE);
1839 rule.priority = 32766;
1840 rule.lookup = RT_TABLE_MAIN;
1841 rv |= system_iprule(&rule, RTM_NEWRULE);
1843 rule.priority = 32767;
1844 rule.lookup = RT_TABLE_DEFAULT;
1845 rv |= system_iprule(&rule, RTM_NEWRULE);
1848 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1851 rule.lookup = RT_TABLE_PRELOCAL;
1852 rv |= system_iprule(&rule, RTM_NEWRULE);
1855 rule.lookup = RT_TABLE_LOCAL;
1856 rv |= system_iprule(&rule, RTM_NEWRULE);
1858 rule.priority = 32766;
1859 rule.lookup = RT_TABLE_MAIN;
1860 rv |= system_iprule(&rule, RTM_NEWRULE);
1865 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1867 return system_rtn_aton(action, id);
1870 time_t system_get_rtime(void)
1875 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1878 if (gettimeofday(&tv, NULL) == 0)
1885 #define IP_DF 0x4000
1888 static int tunnel_ioctl(const char *name, int cmd, void *p)
1892 memset(&ifr, 0, sizeof(ifr));
1893 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1894 ifr.ifr_ifru.ifru_data = p;
1895 return ioctl(sock_ioctl, cmd, &ifr);
1898 #ifdef IFLA_IPTUN_MAX
1899 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
1900 static int system_add_gre_tunnel(const char *name, const char *kind,
1901 const unsigned int link, struct blob_attr **tb, bool v6)
1904 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
1905 struct blob_attr *cur;
1906 uint32_t ikey = 0, okey = 0, flags = 0, flowinfo = 0;
1907 uint16_t iflags = 0, oflags = 0;
1909 int ret = 0, ttl = 64;
1911 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
1915 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
1916 nla_put_string(nlm, IFLA_IFNAME, name);
1918 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
1924 nla_put_string(nlm, IFLA_INFO_KIND, kind);
1925 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
1932 nla_put_u32(nlm, IFLA_GRE_LINK, link);
1934 if ((cur = tb[TUNNEL_ATTR_TTL]))
1935 ttl = blobmsg_get_u32(cur);
1937 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
1939 if ((cur = tb[TUNNEL_ATTR_TOS])) {
1940 char *str = blobmsg_get_string(cur);
1941 if (strcmp(str, "inherit")) {
1944 if (!system_tos_aton(str, &uval)) {
1950 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
1955 flags |= IP6_TNL_F_USE_ORIG_TCLASS;
1961 if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) {
1962 uint8_t icsum, ocsum, iseqno, oseqno;
1963 if (sscanf(blobmsg_get_string(cur), "%u,%u,%hhu,%hhu,%hhu,%hhu",
1964 &ikey, &okey, &icsum, &ocsum, &iseqno, &oseqno) < 6) {
1989 struct in6_addr in6buf;
1990 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1991 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1995 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
1998 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
1999 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2003 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
2005 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, 4);
2008 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
2011 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags);
2013 struct in_addr inbuf;
2016 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2017 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2021 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
2024 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2025 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2029 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
2031 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
2033 okey = inbuf.s_addr;
2038 ikey = inbuf.s_addr;
2044 if ((cur = tb[TUNNEL_ATTR_DF]))
2045 set_df = blobmsg_get_bool(cur);
2047 /* ttl !=0 and nopmtudisc are incompatible */
2048 if (ttl && !set_df) {
2053 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
2055 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
2059 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
2062 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
2065 nla_put_u32(nlm, IFLA_GRE_OKEY, okey);
2068 nla_put_u32(nlm, IFLA_GRE_IKEY, ikey);
2070 nla_nest_end(nlm, infodata);
2071 nla_nest_end(nlm, linkinfo);
2073 return system_rtnl_call(nlm);
2081 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
2083 struct blob_attr *cur;
2085 struct ip_tunnel_parm p = {
2094 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
2095 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
2098 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
2099 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
2102 if ((cur = tb[TUNNEL_ATTR_DF]))
2103 set_df = blobmsg_get_bool(cur);
2105 if ((cur = tb[TUNNEL_ATTR_TTL]))
2106 p.iph.ttl = blobmsg_get_u32(cur);
2108 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2109 char *str = blobmsg_get_string(cur);
2110 if (strcmp(str, "inherit")) {
2113 if (!system_tos_aton(str, &uval))
2121 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
2122 /* ttl !=0 and nopmtudisc are incompatible */
2123 if (p.iph.ttl && p.iph.frag_off == 0)
2126 strncpy(p.name, name, sizeof(p.name));
2128 switch (p.iph.protocol) {
2130 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
2132 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
2139 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
2141 struct blob_attr *cur;
2144 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2146 str = blobmsg_data(cur);
2148 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
2149 !strcmp(str, "greip6") || !strcmp(str, "gretapip6"))
2150 return system_link_del(name);
2152 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
2155 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
2157 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2159 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2160 blob_data(attr), blob_len(attr));
2162 return __system_del_ip_tunnel(name, tb);
2165 int system_update_ipv6_mtu(struct device *dev, int mtu)
2169 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
2172 int fd = open(buf, O_RDWR);
2175 ssize_t len = read(fd, buf, sizeof(buf) - 1);
2182 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) > 0)
2191 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
2193 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2194 struct blob_attr *cur;
2197 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2198 blob_data(attr), blob_len(attr));
2200 __system_del_ip_tunnel(name, tb);
2202 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2204 str = blobmsg_data(cur);
2206 unsigned int ttl = 0;
2207 if ((cur = tb[TUNNEL_ATTR_TTL])) {
2208 ttl = blobmsg_get_u32(cur);
2213 unsigned int link = 0;
2214 if ((cur = tb[TUNNEL_ATTR_LINK])) {
2215 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
2219 if (iface->l3_dev.dev)
2220 link = iface->l3_dev.dev->ifindex;
2223 if (!strcmp(str, "sit")) {
2224 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
2228 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
2230 struct ip_tunnel_6rd p6;
2232 memset(&p6, 0, sizeof(p6));
2234 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
2235 &p6.prefix, &mask) || mask > 128)
2237 p6.prefixlen = mask;
2239 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
2240 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
2241 &p6.relay_prefix, &mask) || mask > 32)
2243 p6.relay_prefixlen = mask;
2246 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
2247 __system_del_ip_tunnel(name, tb);
2252 #ifdef IFLA_IPTUN_MAX
2253 } else if (!strcmp(str, "ipip6")) {
2254 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2255 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2256 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2262 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2263 nla_put_string(nlm, IFLA_IFNAME, name);
2266 nla_put_u32(nlm, IFLA_LINK, link);
2268 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2273 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2274 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2281 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2283 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2284 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2285 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
2287 struct in6_addr in6buf;
2288 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2289 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2293 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2296 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2297 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2301 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2304 #ifdef IFLA_IPTUN_FMR_MAX
2305 if ((cur = tb[TUNNEL_ATTR_FMRS])) {
2306 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2308 struct blob_attr *fmr;
2309 unsigned rem, fmrcnt = 0;
2310 blobmsg_for_each_attr(fmr, cur, rem) {
2311 if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
2314 unsigned ip4len, ip6len, ealen, offset = 6;
2318 if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
2319 ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) {
2324 struct in6_addr ip6prefix;
2325 struct in_addr ip4prefix;
2326 if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
2327 inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) {
2332 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2334 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2335 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2336 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2337 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2338 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2339 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2341 nla_nest_end(nlm, rule);
2344 nla_nest_end(nlm, fmrs);
2348 nla_nest_end(nlm, infodata);
2349 nla_nest_end(nlm, linkinfo);
2351 return system_rtnl_call(nlm);
2355 } else if (!strcmp(str, "greip")) {
2356 return system_add_gre_tunnel(name, "gre", link, tb, false);
2357 } else if (!strcmp(str, "gretapip")) {
2358 return system_add_gre_tunnel(name, "gretap", link, tb, false);
2359 } else if (!strcmp(str, "greip6")) {
2360 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
2361 } else if (!strcmp(str, "gretapip6")) {
2362 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
2364 } else if (!strcmp(str, "ipip")) {
2365 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);