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 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
1023 s->txqueuelen = ifr.ifr_qlen;
1024 s->flags |= DEV_OPT_TXQUEUELEN;
1027 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
1028 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
1029 s->flags |= DEV_OPT_MACADDR;
1032 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
1033 s->ipv6 = !strtoul(buf, NULL, 0);
1034 s->flags |= DEV_OPT_IPV6;
1037 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
1038 s->promisc = ifr.ifr_flags & IFF_PROMISC;
1039 s->flags |= DEV_OPT_PROMISC;
1042 if (!system_get_rpfilter(dev, buf, sizeof(buf))) {
1043 s->rpfilter = strtoul(buf, NULL, 0);
1044 s->flags |= DEV_OPT_RPFILTER;
1047 if (!system_get_acceptlocal(dev, buf, sizeof(buf))) {
1048 s->acceptlocal = strtoul(buf, NULL, 0);
1049 s->flags |= DEV_OPT_ACCEPTLOCAL;
1052 if (!system_get_igmpversion(dev, buf, sizeof(buf))) {
1053 s->igmpversion = strtoul(buf, NULL, 0);
1054 s->flags |= DEV_OPT_IGMPVERSION;
1057 if (!system_get_mldversion(dev, buf, sizeof(buf))) {
1058 s->mldversion = strtoul(buf, NULL, 0);
1059 s->flags |= DEV_OPT_MLDVERSION;
1062 if (!system_get_neigh4reachabletime(dev, buf, sizeof(buf))) {
1063 s->neigh4reachabletime = strtoul(buf, NULL, 0);
1064 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1067 if (!system_get_neigh6reachabletime(dev, buf, sizeof(buf))) {
1068 s->neigh6reachabletime = strtoul(buf, NULL, 0);
1069 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1074 system_if_set_rps_xps_val(const char *path, int val)
1080 if (glob(path, 0, NULL, &gl))
1083 snprintf(val_buf, sizeof(val_buf), "%x", val);
1084 for (i = 0; i < gl.gl_pathc; i++)
1085 system_set_sysctl(gl.gl_pathv[i], val_buf);
1089 system_if_apply_rps_xps(struct device *dev, struct device_settings *s)
1091 long n_cpus = sysconf(_SC_NPROCESSORS_ONLN);
1097 val = (1 << n_cpus) - 1;
1098 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/rps_cpus", dev->ifname);
1099 system_if_set_rps_xps_val(dev_buf, s->rps ? val : 0);
1101 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/xps_cpus", dev->ifname);
1102 system_if_set_rps_xps_val(dev_buf, s->xps ? val : 0);
1106 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
1110 memset(&ifr, 0, sizeof(ifr));
1111 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1112 if (s->flags & DEV_OPT_MTU & apply_mask) {
1113 ifr.ifr_mtu = s->mtu;
1114 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
1115 s->flags &= ~DEV_OPT_MTU;
1117 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
1118 ifr.ifr_qlen = s->txqueuelen;
1119 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
1120 s->flags &= ~DEV_OPT_TXQUEUELEN;
1122 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
1123 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
1124 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
1125 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
1126 s->flags &= ~DEV_OPT_MACADDR;
1128 if (s->flags & DEV_OPT_IPV6 & apply_mask)
1129 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
1130 if (s->flags & DEV_OPT_PROMISC & apply_mask) {
1131 if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
1132 !s->promisc ? IFF_PROMISC : 0) < 0)
1133 s->flags &= ~DEV_OPT_PROMISC;
1135 if (s->flags & DEV_OPT_RPFILTER & apply_mask) {
1138 snprintf(buf, sizeof(buf), "%d", s->rpfilter);
1139 system_set_rpfilter(dev, buf);
1141 if (s->flags & DEV_OPT_ACCEPTLOCAL & apply_mask)
1142 system_set_acceptlocal(dev, s->acceptlocal ? "1" : "0");
1143 if (s->flags & DEV_OPT_IGMPVERSION & apply_mask) {
1146 snprintf(buf, sizeof(buf), "%d", s->igmpversion);
1147 system_set_igmpversion(dev, buf);
1149 if (s->flags & DEV_OPT_MLDVERSION & apply_mask) {
1152 snprintf(buf, sizeof(buf), "%d", s->mldversion);
1153 system_set_mldversion(dev, buf);
1155 if (s->flags & DEV_OPT_NEIGHREACHABLETIME & apply_mask) {
1158 snprintf(buf, sizeof(buf), "%d", s->neigh4reachabletime);
1159 system_set_neigh4reachabletime(dev, buf);
1160 snprintf(buf, sizeof(buf), "%d", s->neigh6reachabletime);
1161 system_set_neigh6reachabletime(dev, buf);
1164 system_if_apply_rps_xps(dev, s);
1167 int system_if_up(struct device *dev)
1169 system_if_get_settings(dev, &dev->orig_settings);
1170 /* Only keep orig settings based on what needs to be set */
1171 dev->orig_settings.flags &= dev->settings.flags;
1172 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
1173 return system_if_flags(dev->ifname, IFF_UP, 0);
1176 int system_if_down(struct device *dev)
1178 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
1179 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
1183 struct if_check_data {
1189 #ifndef IFF_LOWER_UP
1190 #define IFF_LOWER_UP 0x10000
1193 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1195 struct nlmsghdr *nh = nlmsg_hdr(msg);
1196 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1197 struct if_check_data *chk = (struct if_check_data *)arg;
1199 if (nh->nlmsg_type != RTM_NEWLINK)
1202 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1203 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1208 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1210 struct if_check_data *chk = (struct if_check_data *)arg;
1215 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1217 struct if_check_data *chk = (struct if_check_data *)arg;
1219 device_set_present(chk->dev, false);
1220 device_set_link(chk->dev, false);
1221 chk->pending = err->error;
1226 int system_if_check(struct device *dev)
1228 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1230 struct ifinfomsg ifi = {
1231 .ifi_family = AF_UNSPEC,
1234 struct if_check_data chk = {
1240 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1241 if (!msg || nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1242 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1245 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1246 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1247 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1249 nl_send_auto_complete(sock_rtnl, msg);
1250 while (chk.pending > 0)
1251 nl_recvmsgs(sock_rtnl, cb);
1262 system_if_get_parent(struct device *dev)
1264 char buf[64], *devname;
1265 int ifindex, iflink, len;
1268 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1269 f = fopen(buf, "r");
1273 len = fread(buf, 1, sizeof(buf) - 1, f);
1280 iflink = strtoul(buf, NULL, 0);
1281 ifindex = system_if_resolve(dev);
1282 if (!iflink || iflink == ifindex)
1285 devname = if_indextoname(iflink, buf);
1289 return device_get(devname, true);
1293 read_string_file(int dir_fd, const char *file, char *buf, int len)
1299 fd = openat(dir_fd, file, O_RDONLY);
1304 len = read(fd, buf, len - 1);
1308 } else if (len > 0) {
1311 c = strchr(buf, '\n');
1324 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1329 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1331 *val = strtoull(buf, NULL, 0);
1336 /* Assume advertised flags == supported flags */
1337 static const struct {
1340 } ethtool_link_modes[] = {
1341 { ADVERTISED_10baseT_Half, "10H" },
1342 { ADVERTISED_10baseT_Full, "10F" },
1343 { ADVERTISED_100baseT_Half, "100H" },
1344 { ADVERTISED_100baseT_Full, "100F" },
1345 { ADVERTISED_1000baseT_Half, "1000H" },
1346 { ADVERTISED_1000baseT_Full, "1000F" },
1349 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1352 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1353 if (mask & ethtool_link_modes[i].mask)
1354 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1359 system_if_force_external(const char *ifname)
1364 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1365 return stat(buf, &s) == 0;
1369 system_if_dump_info(struct device *dev, struct blob_buf *b)
1371 struct ethtool_cmd ecmd;
1377 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
1378 dir_fd = open(buf, O_DIRECTORY);
1380 memset(&ecmd, 0, sizeof(ecmd));
1381 memset(&ifr, 0, sizeof(ifr));
1382 strcpy(ifr.ifr_name, dev->ifname);
1383 ifr.ifr_data = (caddr_t) &ecmd;
1384 ecmd.cmd = ETHTOOL_GSET;
1386 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1387 c = blobmsg_open_array(b, "link-advertising");
1388 system_add_link_modes(b, ecmd.advertising);
1389 blobmsg_close_array(b, c);
1391 c = blobmsg_open_array(b, "link-supported");
1392 system_add_link_modes(b, ecmd.supported);
1393 blobmsg_close_array(b, c);
1395 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1396 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1397 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1398 blobmsg_add_string_buffer(b);
1406 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1408 const char *const counters[] = {
1409 "collisions", "rx_frame_errors", "tx_compressed",
1410 "multicast", "rx_length_errors", "tx_dropped",
1411 "rx_bytes", "rx_missed_errors", "tx_errors",
1412 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1413 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1414 "rx_dropped", "tx_aborted_errors", "tx_packets",
1415 "rx_errors", "tx_bytes", "tx_window_errors",
1416 "rx_fifo_errors", "tx_carrier_errors",
1423 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1424 stats_dir = open(buf, O_DIRECTORY);
1428 for (i = 0; i < ARRAY_SIZE(counters); i++)
1429 if (read_uint64_file(stats_dir, counters[i], &val))
1430 blobmsg_add_u64(b, counters[i], val);
1436 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1438 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1439 int alen = v4 ? 4 : 16;
1440 unsigned int flags = 0;
1441 struct ifaddrmsg ifa = {
1442 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1443 .ifa_prefixlen = addr->mask,
1444 .ifa_index = dev->ifindex,
1448 if (cmd == RTM_NEWADDR)
1449 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1451 msg = nlmsg_alloc_simple(cmd, flags);
1455 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1456 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1458 if (addr->broadcast)
1459 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1460 if (addr->point_to_point)
1461 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1463 time_t now = system_get_rtime();
1464 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1466 if (addr->preferred_until) {
1467 int64_t preferred = addr->preferred_until - now;
1470 else if (preferred > UINT32_MAX)
1471 preferred = UINT32_MAX;
1473 cinfo.ifa_prefered = preferred;
1476 if (addr->valid_until) {
1477 int64_t valid = addr->valid_until - now;
1480 else if (valid > UINT32_MAX)
1483 cinfo.ifa_valid = valid;
1486 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1488 if (cmd == RTM_NEWADDR && (addr->flags & DEVADDR_OFFLINK))
1489 nla_put_u32(msg, IFA_FLAGS, IFA_F_NOPREFIXROUTE);
1492 return system_rtnl_call(msg);
1495 int system_add_address(struct device *dev, struct device_addr *addr)
1497 return system_addr(dev, addr, RTM_NEWADDR);
1500 int system_del_address(struct device *dev, struct device_addr *addr)
1502 return system_addr(dev, addr, RTM_DELADDR);
1505 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1507 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1509 unsigned int flags = 0;
1512 have_gw = !!route->nexthop.in.s_addr;
1514 have_gw = route->nexthop.in6.s6_addr32[0] ||
1515 route->nexthop.in6.s6_addr32[1] ||
1516 route->nexthop.in6.s6_addr32[2] ||
1517 route->nexthop.in6.s6_addr32[3];
1519 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1520 ? route->table : RT_TABLE_MAIN;
1522 struct rtmsg rtm = {
1523 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1524 .rtm_dst_len = route->mask,
1525 .rtm_src_len = route->sourcemask,
1526 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1527 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
1528 .rtm_scope = RT_SCOPE_NOWHERE,
1529 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1530 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1534 if (cmd == RTM_NEWROUTE) {
1535 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1537 if (!dev) { // Add null-route
1538 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1539 rtm.rtm_type = RTN_UNREACHABLE;
1542 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1545 if (route->flags & DEVROUTE_TYPE) {
1546 rtm.rtm_type = route->type;
1547 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
1548 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
1549 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
1550 rtm.rtm_table = RT_TABLE_LOCAL;
1553 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT) {
1554 rtm.rtm_scope = RT_SCOPE_HOST;
1555 } else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
1556 rtm.rtm_type == RTN_ANYCAST) {
1557 rtm.rtm_scope = RT_SCOPE_LINK;
1558 } else if (rtm.rtm_type == RTN_BLACKHOLE || rtm.rtm_type == RTN_UNREACHABLE ||
1559 rtm.rtm_type == RTN_PROHIBIT || rtm.rtm_type == RTN_FAILED_POLICY) {
1560 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1565 msg = nlmsg_alloc_simple(cmd, flags);
1569 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1572 nla_put(msg, RTA_DST, alen, &route->addr);
1574 if (route->sourcemask) {
1575 if (rtm.rtm_family == AF_INET)
1576 nla_put(msg, RTA_PREFSRC, alen, &route->source);
1578 nla_put(msg, RTA_SRC, alen, &route->source);
1581 if (route->metric > 0)
1582 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1585 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1588 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1591 nla_put_u32(msg, RTA_TABLE, table);
1593 if (route->flags & DEVROUTE_MTU) {
1594 struct nlattr *metrics;
1596 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1597 goto nla_put_failure;
1599 nla_put_u32(msg, RTAX_MTU, route->mtu);
1601 nla_nest_end(msg, metrics);
1604 return system_rtnl_call(msg);
1611 int system_add_route(struct device *dev, struct device_route *route)
1613 return system_rt(dev, route, RTM_NEWROUTE);
1616 int system_del_route(struct device *dev, struct device_route *route)
1618 return system_rt(dev, route, RTM_DELROUTE);
1621 int system_flush_routes(void)
1623 const char *names[] = {
1624 "/proc/sys/net/ipv4/route/flush",
1625 "/proc/sys/net/ipv6/route/flush"
1629 for (i = 0; i < ARRAY_SIZE(names); i++) {
1630 fd = open(names[i], O_WRONLY);
1634 if (write(fd, "-1", 2)) {}
1640 bool system_resolve_rt_type(const char *type, unsigned int *id)
1642 return system_rtn_aton(type, id);
1645 bool system_resolve_rt_table(const char *name, unsigned int *id)
1649 unsigned int n, table = RT_TABLE_UNSPEC;
1651 /* first try to parse table as number */
1652 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1655 /* handle well known aliases */
1656 else if (!strcmp(name, "default"))
1657 table = RT_TABLE_DEFAULT;
1658 else if (!strcmp(name, "main"))
1659 table = RT_TABLE_MAIN;
1660 else if (!strcmp(name, "local"))
1661 table = RT_TABLE_LOCAL;
1662 else if (!strcmp(name, "prelocal"))
1663 table = RT_TABLE_PRELOCAL;
1665 /* try to look up name in /etc/iproute2/rt_tables */
1666 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1668 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1670 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1673 n = strtoul(e, NULL, 10);
1674 e = strtok(NULL, " \t\n");
1676 if (e && !strcmp(e, name))
1686 if (table == RT_TABLE_UNSPEC)
1693 bool system_is_default_rt_table(unsigned int id)
1695 return (id == RT_TABLE_MAIN);
1698 bool system_resolve_rpfilter(const char *filter, unsigned int *id)
1703 if (!strcmp(filter, "strict"))
1705 else if (!strcmp(filter, "loose"))
1708 n = strtoul(filter, &e, 0);
1709 if (*e || e == filter || n > 2)
1717 static int system_iprule(struct iprule *rule, int cmd)
1719 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1722 struct rtmsg rtm = {
1723 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1724 .rtm_protocol = RTPROT_STATIC,
1725 .rtm_scope = RT_SCOPE_UNIVERSE,
1726 .rtm_table = RT_TABLE_UNSPEC,
1727 .rtm_type = RTN_UNSPEC,
1731 if (cmd == RTM_NEWRULE) {
1732 rtm.rtm_type = RTN_UNICAST;
1733 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1737 rtm.rtm_flags |= FIB_RULE_INVERT;
1739 if (rule->flags & IPRULE_SRC)
1740 rtm.rtm_src_len = rule->src_mask;
1742 if (rule->flags & IPRULE_DEST)
1743 rtm.rtm_dst_len = rule->dest_mask;
1745 if (rule->flags & IPRULE_TOS)
1746 rtm.rtm_tos = rule->tos;
1748 if (rule->flags & IPRULE_LOOKUP) {
1749 if (rule->lookup < 256)
1750 rtm.rtm_table = rule->lookup;
1753 if (rule->flags & IPRULE_ACTION)
1754 rtm.rtm_type = rule->action;
1755 else if (rule->flags & IPRULE_GOTO)
1756 rtm.rtm_type = FR_ACT_GOTO;
1757 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1758 rtm.rtm_type = FR_ACT_NOP;
1760 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1765 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1767 if (rule->flags & IPRULE_IN)
1768 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1770 if (rule->flags & IPRULE_OUT)
1771 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1773 if (rule->flags & IPRULE_SRC)
1774 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1776 if (rule->flags & IPRULE_DEST)
1777 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1779 if (rule->flags & IPRULE_PRIORITY)
1780 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1781 else if (cmd == RTM_NEWRULE)
1782 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1784 if (rule->flags & IPRULE_FWMARK)
1785 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1787 if (rule->flags & IPRULE_FWMASK)
1788 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1790 if (rule->flags & IPRULE_LOOKUP) {
1791 if (rule->lookup >= 256)
1792 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1795 if (rule->flags & IPRULE_GOTO)
1796 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1798 return system_rtnl_call(msg);
1801 int system_add_iprule(struct iprule *rule)
1803 return system_iprule(rule, RTM_NEWRULE);
1806 int system_del_iprule(struct iprule *rule)
1808 return system_iprule(rule, RTM_DELRULE);
1811 int system_flush_iprules(void)
1816 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1817 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1819 memset(&rule, 0, sizeof(rule));
1822 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1825 rule.lookup = RT_TABLE_PRELOCAL;
1826 rv |= system_iprule(&rule, RTM_NEWRULE);
1829 rule.lookup = RT_TABLE_LOCAL;
1830 rv |= system_iprule(&rule, RTM_NEWRULE);
1832 rule.priority = 32766;
1833 rule.lookup = RT_TABLE_MAIN;
1834 rv |= system_iprule(&rule, RTM_NEWRULE);
1836 rule.priority = 32767;
1837 rule.lookup = RT_TABLE_DEFAULT;
1838 rv |= system_iprule(&rule, RTM_NEWRULE);
1841 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1844 rule.lookup = RT_TABLE_PRELOCAL;
1845 rv |= system_iprule(&rule, RTM_NEWRULE);
1848 rule.lookup = RT_TABLE_LOCAL;
1849 rv |= system_iprule(&rule, RTM_NEWRULE);
1851 rule.priority = 32766;
1852 rule.lookup = RT_TABLE_MAIN;
1853 rv |= system_iprule(&rule, RTM_NEWRULE);
1858 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1860 return system_rtn_aton(action, id);
1863 time_t system_get_rtime(void)
1868 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1871 if (gettimeofday(&tv, NULL) == 0)
1878 #define IP_DF 0x4000
1881 static int tunnel_ioctl(const char *name, int cmd, void *p)
1885 memset(&ifr, 0, sizeof(ifr));
1886 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1887 ifr.ifr_ifru.ifru_data = p;
1888 return ioctl(sock_ioctl, cmd, &ifr);
1891 #ifdef IFLA_IPTUN_MAX
1892 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
1893 static int system_add_gre_tunnel(const char *name, const char *kind,
1894 const unsigned int link, struct blob_attr **tb, bool v6)
1897 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
1898 struct blob_attr *cur;
1899 uint32_t ikey = 0, okey = 0, flags = 0, flowinfo = 0;
1900 uint16_t iflags = 0, oflags = 0;
1902 int ret = 0, ttl = 64;
1904 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
1908 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
1909 nla_put_string(nlm, IFLA_IFNAME, name);
1911 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
1917 nla_put_string(nlm, IFLA_INFO_KIND, kind);
1918 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
1925 nla_put_u32(nlm, IFLA_GRE_LINK, link);
1927 if ((cur = tb[TUNNEL_ATTR_TTL]))
1928 ttl = blobmsg_get_u32(cur);
1930 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
1932 if ((cur = tb[TUNNEL_ATTR_TOS])) {
1933 char *str = blobmsg_get_string(cur);
1934 if (strcmp(str, "inherit")) {
1937 if (!system_tos_aton(str, &uval)) {
1943 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
1948 flags |= IP6_TNL_F_USE_ORIG_TCLASS;
1954 if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) {
1955 uint8_t icsum, ocsum, iseqno, oseqno;
1956 if (sscanf(blobmsg_get_string(cur), "%u,%u,%hhu,%hhu,%hhu,%hhu",
1957 &ikey, &okey, &icsum, &ocsum, &iseqno, &oseqno) < 6) {
1982 struct in6_addr in6buf;
1983 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1984 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1988 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
1991 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
1992 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1996 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
1998 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, 4);
2001 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
2004 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags);
2006 struct in_addr inbuf;
2009 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2010 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2014 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
2017 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2018 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2022 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
2024 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
2026 okey = inbuf.s_addr;
2031 ikey = inbuf.s_addr;
2037 if ((cur = tb[TUNNEL_ATTR_DF]))
2038 set_df = blobmsg_get_bool(cur);
2040 /* ttl !=0 and nopmtudisc are incompatible */
2041 if (ttl && !set_df) {
2046 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
2048 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
2052 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
2055 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
2058 nla_put_u32(nlm, IFLA_GRE_OKEY, okey);
2061 nla_put_u32(nlm, IFLA_GRE_IKEY, ikey);
2063 nla_nest_end(nlm, infodata);
2064 nla_nest_end(nlm, linkinfo);
2066 return system_rtnl_call(nlm);
2074 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
2076 struct blob_attr *cur;
2078 struct ip_tunnel_parm p = {
2087 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
2088 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
2091 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
2092 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
2095 if ((cur = tb[TUNNEL_ATTR_DF]))
2096 set_df = blobmsg_get_bool(cur);
2098 if ((cur = tb[TUNNEL_ATTR_TTL]))
2099 p.iph.ttl = blobmsg_get_u32(cur);
2101 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2102 char *str = blobmsg_get_string(cur);
2103 if (strcmp(str, "inherit")) {
2106 if (!system_tos_aton(str, &uval))
2114 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
2115 /* ttl !=0 and nopmtudisc are incompatible */
2116 if (p.iph.ttl && p.iph.frag_off == 0)
2119 strncpy(p.name, name, sizeof(p.name));
2121 switch (p.iph.protocol) {
2123 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
2125 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
2132 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
2134 struct blob_attr *cur;
2137 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2139 str = blobmsg_data(cur);
2141 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
2142 !strcmp(str, "greip6") || !strcmp(str, "gretapip6"))
2143 return system_link_del(name);
2145 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
2148 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
2150 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2152 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2153 blob_data(attr), blob_len(attr));
2155 return __system_del_ip_tunnel(name, tb);
2158 int system_update_ipv6_mtu(struct device *dev, int mtu)
2162 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
2165 int fd = open(buf, O_RDWR);
2166 ssize_t len = read(fd, buf, sizeof(buf) - 1);
2173 if (!mtu || ret <= mtu)
2176 lseek(fd, 0, SEEK_SET);
2177 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) <= 0)
2185 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
2187 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2188 struct blob_attr *cur;
2191 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2192 blob_data(attr), blob_len(attr));
2194 __system_del_ip_tunnel(name, tb);
2196 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2198 str = blobmsg_data(cur);
2200 unsigned int ttl = 0;
2201 if ((cur = tb[TUNNEL_ATTR_TTL])) {
2202 ttl = blobmsg_get_u32(cur);
2207 unsigned int link = 0;
2208 if ((cur = tb[TUNNEL_ATTR_LINK])) {
2209 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
2213 if (iface->l3_dev.dev)
2214 link = iface->l3_dev.dev->ifindex;
2217 if (!strcmp(str, "sit")) {
2218 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
2222 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
2224 struct ip_tunnel_6rd p6;
2226 memset(&p6, 0, sizeof(p6));
2228 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
2229 &p6.prefix, &mask) || mask > 128)
2231 p6.prefixlen = mask;
2233 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
2234 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
2235 &p6.relay_prefix, &mask) || mask > 32)
2237 p6.relay_prefixlen = mask;
2240 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
2241 __system_del_ip_tunnel(name, tb);
2246 #ifdef IFLA_IPTUN_MAX
2247 } else if (!strcmp(str, "ipip6")) {
2248 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2249 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2250 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2256 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2257 nla_put_string(nlm, IFLA_IFNAME, name);
2260 nla_put_u32(nlm, IFLA_LINK, link);
2262 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2267 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2268 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2275 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2277 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2278 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2279 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
2281 struct in6_addr in6buf;
2282 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2283 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2287 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2290 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2291 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2295 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2298 #ifdef IFLA_IPTUN_FMR_MAX
2299 if ((cur = tb[TUNNEL_ATTR_FMRS])) {
2300 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2302 struct blob_attr *fmr;
2303 unsigned rem, fmrcnt = 0;
2304 blobmsg_for_each_attr(fmr, cur, rem) {
2305 if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
2308 unsigned ip4len, ip6len, ealen, offset = 6;
2312 if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
2313 ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) {
2318 struct in6_addr ip6prefix;
2319 struct in_addr ip4prefix;
2320 if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
2321 inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) {
2326 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2328 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2329 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2330 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2331 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2332 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2333 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2335 nla_nest_end(nlm, rule);
2338 nla_nest_end(nlm, fmrs);
2342 nla_nest_end(nlm, infodata);
2343 nla_nest_end(nlm, linkinfo);
2345 return system_rtnl_call(nlm);
2349 } else if (!strcmp(str, "greip")) {
2350 return system_add_gre_tunnel(name, "gre", link, tb, false);
2351 } else if (!strcmp(str, "gretapip")) {
2352 return system_add_gre_tunnel(name, "gretap", link, tb, false);
2353 } else if (!strcmp(str, "greip6")) {
2354 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
2355 } else if (!strcmp(str, "gretapip6")) {
2356 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
2358 } else if (!strcmp(str, "ipip")) {
2359 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);