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 void system_set_dadtransmits(struct device *dev, const char *val)
315 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits", dev->ifname, val);
318 static void system_bridge_set_multicast_to_unicast(struct device *dev, const char *val)
320 system_set_dev_sysctl("/sys/class/net/%s/brport/multicast_to_unicast", dev->ifname, val);
323 static void system_bridge_set_hairpin_mode(struct device *dev, const char *val)
325 system_set_dev_sysctl("/sys/class/net/%s/brport/hairpin_mode", dev->ifname, val);
328 static int system_get_sysctl(const char *path, char *buf, const size_t buf_sz)
330 int fd = -1, ret = -1;
332 fd = open(path, O_RDONLY);
336 ssize_t len = read(fd, buf, buf_sz - 1);
350 system_get_dev_sysctl(const char *path, const char *device, char *buf, const size_t buf_sz)
352 snprintf(dev_buf, sizeof(dev_buf), path, device);
353 return system_get_sysctl(dev_buf, buf, buf_sz);
356 static int system_get_disable_ipv6(struct device *dev, char *buf, const size_t buf_sz)
358 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6",
359 dev->ifname, buf, buf_sz);
362 static int system_get_rpfilter(struct device *dev, char *buf, const size_t buf_sz)
364 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter",
365 dev->ifname, buf, buf_sz);
368 static int system_get_acceptlocal(struct device *dev, char *buf, const size_t buf_sz)
370 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local",
371 dev->ifname, buf, buf_sz);
374 static int system_get_igmpversion(struct device *dev, char *buf, const size_t buf_sz)
376 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version",
377 dev->ifname, buf, buf_sz);
380 static int system_get_mldversion(struct device *dev, char *buf, const size_t buf_sz)
382 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version",
383 dev->ifname, buf, buf_sz);
386 static int system_get_neigh4reachabletime(struct device *dev, char *buf, const size_t buf_sz)
388 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms",
389 dev->ifname, buf, buf_sz);
392 static int system_get_neigh6reachabletime(struct device *dev, char *buf, const size_t buf_sz)
394 return system_get_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms",
395 dev->ifname, buf, buf_sz);
398 static int system_get_dadtransmits(struct device *dev, char *buf, const size_t buf_sz)
400 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits",
401 dev->ifname, buf, buf_sz);
404 // Evaluate netlink messages
405 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
407 struct nlmsghdr *nh = nlmsg_hdr(msg);
408 struct nlattr *nla[__IFLA_MAX];
412 if (nh->nlmsg_type != RTM_NEWLINK)
415 nlmsg_parse(nh, sizeof(struct ifinfomsg), nla, __IFLA_MAX - 1, NULL);
416 if (!nla[IFLA_IFNAME])
419 struct device *dev = device_get(nla_data(nla[IFLA_IFNAME]), false);
420 if (!dev || dev->type->keep_link_status)
423 if (!system_get_dev_sysctl("/sys/class/net/%s/carrier", dev->ifname, buf, sizeof(buf)))
424 link_state = strtoul(buf, NULL, 0);
426 device_set_link(dev, link_state ? true : false);
433 handle_hotplug_msg(char *data, int size)
435 const char *subsystem = NULL, *interface = NULL;
436 char *cur, *end, *sep;
441 if (!strncmp(data, "add@", 4))
443 else if (!strncmp(data, "remove@", 7))
448 skip = strlen(data) + 1;
451 for (cur = data + skip; cur < end; cur += skip) {
452 skip = strlen(cur) + 1;
454 sep = strchr(cur, '=');
459 if (!strcmp(cur, "INTERFACE"))
461 else if (!strcmp(cur, "SUBSYSTEM")) {
463 if (strcmp(subsystem, "net") != 0)
466 if (subsystem && interface)
472 dev = device_get(interface, false);
476 if (dev->type != &simple_device_type)
479 if (add && system_if_force_external(dev->ifname))
482 device_set_present(dev, add);
486 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
488 struct event_socket *ev = container_of(u, struct event_socket, uloop);
489 struct sockaddr_nl nla;
490 unsigned char *buf = NULL;
493 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
495 handle_hotplug_msg((char *) buf, size);
501 static int system_rtnl_call(struct nl_msg *msg)
505 ret = nl_send_auto_complete(sock_rtnl, msg);
511 return nl_wait_for_ack(sock_rtnl);
514 int system_bridge_delbr(struct device *bridge)
516 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
519 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
523 memset(&ifr, 0, sizeof(ifr));
525 ifr.ifr_ifindex = dev->ifindex;
528 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
529 return ioctl(sock_ioctl, cmd, &ifr);
532 static bool system_is_bridge(const char *name, char *buf, int buflen)
536 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
537 if (stat(buf, &st) < 0)
543 static char *system_get_bridge(const char *name, char *buf, int buflen)
549 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
550 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
554 len = readlink(gl.gl_pathv[0], buf, buflen);
562 path = strrchr(buf, '/');
570 system_bridge_set_wireless(struct device *dev)
574 if (dev->wireless_isolate)
577 system_bridge_set_multicast_to_unicast(dev, "1");
578 system_bridge_set_hairpin_mode(dev, hairpin ? "1" : "0");
581 int system_bridge_addif(struct device *bridge, struct device *dev)
586 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
587 if (!oldbr || strcmp(oldbr, bridge->ifname) != 0)
588 ret = system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
591 system_bridge_set_wireless(dev);
596 int system_bridge_delif(struct device *bridge, struct device *dev)
598 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
601 int system_if_resolve(struct device *dev)
604 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
605 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
606 return ifr.ifr_ifindex;
611 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
615 memset(&ifr, 0, sizeof(ifr));
616 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
617 ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
618 ifr.ifr_flags |= add;
619 ifr.ifr_flags &= ~rem;
620 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
632 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
634 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
636 return ifa->ifa_index == ifindex;
639 static bool check_route(struct nlmsghdr *hdr, int ifindex)
641 struct rtmsg *r = NLMSG_DATA(hdr);
642 struct nlattr *tb[__RTA_MAX];
644 if (r->rtm_protocol == RTPROT_KERNEL &&
645 r->rtm_family == AF_INET6)
648 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
652 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
655 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
660 static int cb_clear_event(struct nl_msg *msg, void *arg)
662 struct clear_data *clr = arg;
663 struct nlmsghdr *hdr = nlmsg_hdr(msg);
664 bool (*cb)(struct nlmsghdr *, int ifindex);
670 if (hdr->nlmsg_type != RTM_NEWADDR)
677 if (hdr->nlmsg_type != RTM_NEWROUTE)
684 if (hdr->nlmsg_type != RTM_NEWRULE)
693 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
696 if (type == RTM_DELRULE)
697 D(SYSTEM, "Remove a rule\n");
699 D(SYSTEM, "Remove %s from device %s\n",
700 type == RTM_DELADDR ? "an address" : "a route",
702 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
703 hdr = nlmsg_hdr(clr->msg);
704 hdr->nlmsg_type = type;
705 hdr->nlmsg_flags = NLM_F_REQUEST;
707 nl_socket_disable_auto_ack(sock_rtnl);
708 nl_send_auto_complete(sock_rtnl, clr->msg);
709 nl_socket_enable_auto_ack(sock_rtnl);
715 cb_finish_event(struct nl_msg *msg, void *arg)
723 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
726 *pending = err->error;
731 system_if_clear_entries(struct device *dev, int type, int af)
733 struct clear_data clr;
734 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
737 .rtm_flags = RTM_F_CLONED,
739 int flags = NLM_F_DUMP;
748 clr.size = sizeof(struct rtgenmsg);
751 clr.size = sizeof(struct rtmsg);
760 clr.msg = nlmsg_alloc_simple(type, flags);
764 nlmsg_append(clr.msg, &rtm, clr.size, 0);
765 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
766 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
767 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
769 nl_send_auto_complete(sock_rtnl, clr.msg);
771 nl_recvmsgs(sock_rtnl, cb);
779 * Clear bridge (membership) state and bring down device
781 void system_if_clear_state(struct device *dev)
783 static char buf[256];
786 device_set_ifindex(dev, system_if_resolve(dev));
787 if (dev->external || !dev->ifindex)
790 system_if_flags(dev->ifname, 0, IFF_UP);
792 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
793 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
794 system_bridge_delbr(dev);
798 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
800 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
801 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
804 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
805 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
806 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
807 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
808 system_set_disable_ipv6(dev, "0");
811 static inline unsigned long
812 sec_to_jiffies(int val)
814 return (unsigned long) val * 100;
817 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
820 unsigned long args[4] = {};
822 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
825 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
826 args[1] = !!cfg->stp;
827 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
829 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
830 args[1] = sec_to_jiffies(cfg->forward_delay);
831 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
833 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
834 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
836 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier",
837 bridge->ifname, cfg->multicast_querier ? "1" : "0");
839 snprintf(buf, sizeof(buf), "%i", cfg->hash_max);
840 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/hash_max",
841 bridge->ifname, buf);
843 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
844 args[1] = cfg->priority;
845 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
847 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
848 args[0] = BRCTL_SET_AGEING_TIME;
849 args[1] = sec_to_jiffies(cfg->ageing_time);
850 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
853 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
854 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
855 args[1] = sec_to_jiffies(cfg->hello_time);
856 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
859 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
860 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
861 args[1] = sec_to_jiffies(cfg->max_age);
862 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
868 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
871 struct nlattr *linkinfo, *data;
872 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
874 static const struct {
876 enum macvlan_mode val;
878 { "private", MACVLAN_MODE_PRIVATE },
879 { "vepa", MACVLAN_MODE_VEPA },
880 { "bridge", MACVLAN_MODE_BRIDGE },
881 { "passthru", MACVLAN_MODE_PASSTHRU },
884 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
889 nlmsg_append(msg, &iim, sizeof(iim), 0);
891 if (cfg->flags & MACVLAN_OPT_MACADDR)
892 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
893 nla_put_string(msg, IFLA_IFNAME, macvlan->ifname);
894 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
896 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
897 goto nla_put_failure;
899 nla_put_string(msg, IFLA_INFO_KIND, "macvlan");
901 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
902 goto nla_put_failure;
905 for (i = 0; i < ARRAY_SIZE(modes); i++) {
906 if (strcmp(cfg->mode, modes[i].name) != 0)
909 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
914 nla_nest_end(msg, data);
915 nla_nest_end(msg, linkinfo);
917 rv = system_rtnl_call(msg);
919 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
928 static int system_link_del(const char *ifname)
931 struct ifinfomsg iim = {
932 .ifi_family = AF_UNSPEC,
936 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
941 nlmsg_append(msg, &iim, sizeof(iim), 0);
942 nla_put_string(msg, IFLA_IFNAME, ifname);
943 return system_rtnl_call(msg);
946 int system_macvlan_del(struct device *macvlan)
948 return system_link_del(macvlan->ifname);
951 static int system_vlan(struct device *dev, int id)
953 struct vlan_ioctl_args ifr = {
954 .cmd = SET_VLAN_NAME_TYPE_CMD,
955 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
958 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
961 ifr.cmd = DEL_VLAN_CMD;
964 ifr.cmd = ADD_VLAN_CMD;
967 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
968 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
971 int system_vlan_add(struct device *dev, int id)
973 return system_vlan(dev, id);
976 int system_vlan_del(struct device *dev)
978 return system_vlan(dev, -1);
981 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
984 struct nlattr *linkinfo, *data;
985 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
988 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
993 nlmsg_append(msg, &iim, sizeof(iim), 0);
994 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
995 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
997 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
998 goto nla_put_failure;
1000 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
1002 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1003 goto nla_put_failure;
1005 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
1007 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
1008 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
1010 if(cfg->proto == VLAN_PROTO_8021AD)
1011 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);
1014 nla_nest_end(msg, data);
1015 nla_nest_end(msg, linkinfo);
1017 rv = system_rtnl_call(msg);
1019 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
1028 int system_vlandev_del(struct device *vlandev)
1030 return system_link_del(vlandev->ifname);
1034 system_if_get_settings(struct device *dev, struct device_settings *s)
1039 memset(&ifr, 0, sizeof(ifr));
1040 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1042 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
1043 s->mtu = ifr.ifr_mtu;
1044 s->flags |= DEV_OPT_MTU;
1047 s->mtu6 = system_update_ipv6_mtu(dev, 0);
1049 s->flags |= DEV_OPT_MTU6;
1051 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
1052 s->txqueuelen = ifr.ifr_qlen;
1053 s->flags |= DEV_OPT_TXQUEUELEN;
1056 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
1057 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
1058 s->flags |= DEV_OPT_MACADDR;
1061 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
1062 s->ipv6 = !strtoul(buf, NULL, 0);
1063 s->flags |= DEV_OPT_IPV6;
1066 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
1067 s->promisc = ifr.ifr_flags & IFF_PROMISC;
1068 s->flags |= DEV_OPT_PROMISC;
1071 if (!system_get_rpfilter(dev, buf, sizeof(buf))) {
1072 s->rpfilter = strtoul(buf, NULL, 0);
1073 s->flags |= DEV_OPT_RPFILTER;
1076 if (!system_get_acceptlocal(dev, buf, sizeof(buf))) {
1077 s->acceptlocal = strtoul(buf, NULL, 0);
1078 s->flags |= DEV_OPT_ACCEPTLOCAL;
1081 if (!system_get_igmpversion(dev, buf, sizeof(buf))) {
1082 s->igmpversion = strtoul(buf, NULL, 0);
1083 s->flags |= DEV_OPT_IGMPVERSION;
1086 if (!system_get_mldversion(dev, buf, sizeof(buf))) {
1087 s->mldversion = strtoul(buf, NULL, 0);
1088 s->flags |= DEV_OPT_MLDVERSION;
1091 if (!system_get_neigh4reachabletime(dev, buf, sizeof(buf))) {
1092 s->neigh4reachabletime = strtoul(buf, NULL, 0);
1093 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1096 if (!system_get_neigh6reachabletime(dev, buf, sizeof(buf))) {
1097 s->neigh6reachabletime = strtoul(buf, NULL, 0);
1098 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1101 if (!system_get_dadtransmits(dev, buf, sizeof(buf))) {
1102 s->dadtransmits = strtoul(buf, NULL, 0);
1103 s->flags |= DEV_OPT_DADTRANSMITS;
1108 system_if_set_rps_xps_val(const char *path, int val)
1114 if (glob(path, 0, NULL, &gl))
1117 snprintf(val_buf, sizeof(val_buf), "%x", val);
1118 for (i = 0; i < gl.gl_pathc; i++)
1119 system_set_sysctl(gl.gl_pathv[i], val_buf);
1123 system_if_apply_rps_xps(struct device *dev, struct device_settings *s)
1125 long n_cpus = sysconf(_SC_NPROCESSORS_ONLN);
1131 val = (1 << n_cpus) - 1;
1132 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/rps_cpus", dev->ifname);
1133 system_if_set_rps_xps_val(dev_buf, s->rps ? val : 0);
1135 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/xps_cpus", dev->ifname);
1136 system_if_set_rps_xps_val(dev_buf, s->xps ? val : 0);
1140 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
1145 memset(&ifr, 0, sizeof(ifr));
1146 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1147 if (s->flags & DEV_OPT_MTU & apply_mask) {
1148 ifr.ifr_mtu = s->mtu;
1149 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
1150 s->flags &= ~DEV_OPT_MTU;
1152 if (s->flags & DEV_OPT_MTU6 & apply_mask) {
1153 system_update_ipv6_mtu(dev, s->mtu6);
1155 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
1156 ifr.ifr_qlen = s->txqueuelen;
1157 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
1158 s->flags &= ~DEV_OPT_TXQUEUELEN;
1160 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
1161 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
1162 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
1163 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
1164 s->flags &= ~DEV_OPT_MACADDR;
1166 if (s->flags & DEV_OPT_IPV6 & apply_mask)
1167 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
1168 if (s->flags & DEV_OPT_PROMISC & apply_mask) {
1169 if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
1170 !s->promisc ? IFF_PROMISC : 0) < 0)
1171 s->flags &= ~DEV_OPT_PROMISC;
1173 if (s->flags & DEV_OPT_RPFILTER & apply_mask) {
1174 snprintf(buf, sizeof(buf), "%d", s->rpfilter);
1175 system_set_rpfilter(dev, buf);
1177 if (s->flags & DEV_OPT_ACCEPTLOCAL & apply_mask)
1178 system_set_acceptlocal(dev, s->acceptlocal ? "1" : "0");
1179 if (s->flags & DEV_OPT_IGMPVERSION & apply_mask) {
1180 snprintf(buf, sizeof(buf), "%d", s->igmpversion);
1181 system_set_igmpversion(dev, buf);
1183 if (s->flags & DEV_OPT_MLDVERSION & apply_mask) {
1184 snprintf(buf, sizeof(buf), "%d", s->mldversion);
1185 system_set_mldversion(dev, buf);
1187 if (s->flags & DEV_OPT_NEIGHREACHABLETIME & apply_mask) {
1188 snprintf(buf, sizeof(buf), "%d", s->neigh4reachabletime);
1189 system_set_neigh4reachabletime(dev, buf);
1190 snprintf(buf, sizeof(buf), "%d", s->neigh6reachabletime);
1191 system_set_neigh6reachabletime(dev, buf);
1193 if (s->flags & DEV_OPT_DADTRANSMITS & apply_mask) {
1194 snprintf(buf, sizeof(buf), "%d", s->dadtransmits);
1195 system_set_dadtransmits(dev, buf);
1198 system_if_apply_rps_xps(dev, s);
1201 int system_if_up(struct device *dev)
1203 system_if_get_settings(dev, &dev->orig_settings);
1204 /* Only keep orig settings based on what needs to be set */
1205 dev->orig_settings.flags &= dev->settings.flags;
1206 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
1207 return system_if_flags(dev->ifname, IFF_UP, 0);
1210 int system_if_down(struct device *dev)
1212 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
1213 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
1217 struct if_check_data {
1223 #ifndef IFF_LOWER_UP
1224 #define IFF_LOWER_UP 0x10000
1227 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1229 struct nlmsghdr *nh = nlmsg_hdr(msg);
1230 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1231 struct if_check_data *chk = (struct if_check_data *)arg;
1233 if (nh->nlmsg_type != RTM_NEWLINK)
1236 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1237 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1242 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1244 struct if_check_data *chk = (struct if_check_data *)arg;
1249 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1251 struct if_check_data *chk = (struct if_check_data *)arg;
1253 device_set_present(chk->dev, false);
1254 device_set_link(chk->dev, false);
1255 chk->pending = err->error;
1260 int system_if_check(struct device *dev)
1262 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1264 struct ifinfomsg ifi = {
1265 .ifi_family = AF_UNSPEC,
1268 struct if_check_data chk = {
1274 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1275 if (!msg || nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1276 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1279 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1280 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1281 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1283 nl_send_auto_complete(sock_rtnl, msg);
1284 while (chk.pending > 0)
1285 nl_recvmsgs(sock_rtnl, cb);
1296 system_if_get_parent(struct device *dev)
1298 char buf[64], *devname;
1299 int ifindex, iflink, len;
1302 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1303 f = fopen(buf, "r");
1307 len = fread(buf, 1, sizeof(buf) - 1, f);
1314 iflink = strtoul(buf, NULL, 0);
1315 ifindex = system_if_resolve(dev);
1316 if (!iflink || iflink == ifindex)
1319 devname = if_indextoname(iflink, buf);
1323 return device_get(devname, true);
1327 read_string_file(int dir_fd, const char *file, char *buf, int len)
1333 fd = openat(dir_fd, file, O_RDONLY);
1338 len = read(fd, buf, len - 1);
1342 } else if (len > 0) {
1345 c = strchr(buf, '\n');
1358 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1363 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1365 *val = strtoull(buf, NULL, 0);
1370 /* Assume advertised flags == supported flags */
1371 static const struct {
1374 } ethtool_link_modes[] = {
1375 { ADVERTISED_10baseT_Half, "10H" },
1376 { ADVERTISED_10baseT_Full, "10F" },
1377 { ADVERTISED_100baseT_Half, "100H" },
1378 { ADVERTISED_100baseT_Full, "100F" },
1379 { ADVERTISED_1000baseT_Half, "1000H" },
1380 { ADVERTISED_1000baseT_Full, "1000F" },
1383 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1386 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1387 if (mask & ethtool_link_modes[i].mask)
1388 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1393 system_if_force_external(const char *ifname)
1398 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1399 return stat(buf, &s) == 0;
1403 system_if_dump_info(struct device *dev, struct blob_buf *b)
1405 struct ethtool_cmd ecmd;
1411 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
1412 dir_fd = open(buf, O_DIRECTORY);
1414 memset(&ecmd, 0, sizeof(ecmd));
1415 memset(&ifr, 0, sizeof(ifr));
1416 strcpy(ifr.ifr_name, dev->ifname);
1417 ifr.ifr_data = (caddr_t) &ecmd;
1418 ecmd.cmd = ETHTOOL_GSET;
1420 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1421 c = blobmsg_open_array(b, "link-advertising");
1422 system_add_link_modes(b, ecmd.advertising);
1423 blobmsg_close_array(b, c);
1425 c = blobmsg_open_array(b, "link-supported");
1426 system_add_link_modes(b, ecmd.supported);
1427 blobmsg_close_array(b, c);
1429 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1430 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1431 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1432 blobmsg_add_string_buffer(b);
1440 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1442 const char *const counters[] = {
1443 "collisions", "rx_frame_errors", "tx_compressed",
1444 "multicast", "rx_length_errors", "tx_dropped",
1445 "rx_bytes", "rx_missed_errors", "tx_errors",
1446 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1447 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1448 "rx_dropped", "tx_aborted_errors", "tx_packets",
1449 "rx_errors", "tx_bytes", "tx_window_errors",
1450 "rx_fifo_errors", "tx_carrier_errors",
1457 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1458 stats_dir = open(buf, O_DIRECTORY);
1462 for (i = 0; i < ARRAY_SIZE(counters); i++)
1463 if (read_uint64_file(stats_dir, counters[i], &val))
1464 blobmsg_add_u64(b, counters[i], val);
1470 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1472 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1473 int alen = v4 ? 4 : 16;
1474 unsigned int flags = 0;
1475 struct ifaddrmsg ifa = {
1476 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1477 .ifa_prefixlen = addr->mask,
1478 .ifa_index = dev->ifindex,
1482 if (cmd == RTM_NEWADDR)
1483 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1485 msg = nlmsg_alloc_simple(cmd, flags);
1489 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1490 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1492 if (addr->broadcast)
1493 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1494 if (addr->point_to_point)
1495 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1497 time_t now = system_get_rtime();
1498 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1500 if (addr->preferred_until) {
1501 int64_t preferred = addr->preferred_until - now;
1504 else if (preferred > UINT32_MAX)
1505 preferred = UINT32_MAX;
1507 cinfo.ifa_prefered = preferred;
1510 if (addr->valid_until) {
1511 int64_t valid = addr->valid_until - now;
1514 else if (valid > UINT32_MAX)
1517 cinfo.ifa_valid = valid;
1520 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1522 if (cmd == RTM_NEWADDR && (addr->flags & DEVADDR_OFFLINK))
1523 nla_put_u32(msg, IFA_FLAGS, IFA_F_NOPREFIXROUTE);
1526 return system_rtnl_call(msg);
1529 int system_add_address(struct device *dev, struct device_addr *addr)
1531 return system_addr(dev, addr, RTM_NEWADDR);
1534 int system_del_address(struct device *dev, struct device_addr *addr)
1536 return system_addr(dev, addr, RTM_DELADDR);
1539 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1541 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1543 unsigned int flags = 0;
1546 have_gw = !!route->nexthop.in.s_addr;
1548 have_gw = route->nexthop.in6.s6_addr32[0] ||
1549 route->nexthop.in6.s6_addr32[1] ||
1550 route->nexthop.in6.s6_addr32[2] ||
1551 route->nexthop.in6.s6_addr32[3];
1553 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1554 ? route->table : RT_TABLE_MAIN;
1556 struct rtmsg rtm = {
1557 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1558 .rtm_dst_len = route->mask,
1559 .rtm_src_len = route->sourcemask,
1560 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1561 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
1562 .rtm_scope = RT_SCOPE_NOWHERE,
1563 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1564 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1568 if (cmd == RTM_NEWROUTE) {
1569 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1571 if (!dev) { // Add null-route
1572 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1573 rtm.rtm_type = RTN_UNREACHABLE;
1576 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1579 if (route->flags & DEVROUTE_TYPE) {
1580 rtm.rtm_type = route->type;
1581 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
1582 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
1583 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
1584 rtm.rtm_table = RT_TABLE_LOCAL;
1587 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT) {
1588 rtm.rtm_scope = RT_SCOPE_HOST;
1589 } else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
1590 rtm.rtm_type == RTN_ANYCAST) {
1591 rtm.rtm_scope = RT_SCOPE_LINK;
1592 } else if (rtm.rtm_type == RTN_BLACKHOLE || rtm.rtm_type == RTN_UNREACHABLE ||
1593 rtm.rtm_type == RTN_PROHIBIT || rtm.rtm_type == RTN_FAILED_POLICY) {
1594 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1599 msg = nlmsg_alloc_simple(cmd, flags);
1603 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1606 nla_put(msg, RTA_DST, alen, &route->addr);
1608 if (route->sourcemask) {
1609 if (rtm.rtm_family == AF_INET)
1610 nla_put(msg, RTA_PREFSRC, alen, &route->source);
1612 nla_put(msg, RTA_SRC, alen, &route->source);
1615 if (route->metric > 0)
1616 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1619 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1622 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1625 nla_put_u32(msg, RTA_TABLE, table);
1627 if (route->flags & DEVROUTE_MTU) {
1628 struct nlattr *metrics;
1630 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1631 goto nla_put_failure;
1633 nla_put_u32(msg, RTAX_MTU, route->mtu);
1635 nla_nest_end(msg, metrics);
1638 return system_rtnl_call(msg);
1645 int system_add_route(struct device *dev, struct device_route *route)
1647 return system_rt(dev, route, RTM_NEWROUTE);
1650 int system_del_route(struct device *dev, struct device_route *route)
1652 return system_rt(dev, route, RTM_DELROUTE);
1655 int system_flush_routes(void)
1657 const char *names[] = {
1658 "/proc/sys/net/ipv4/route/flush",
1659 "/proc/sys/net/ipv6/route/flush"
1663 for (i = 0; i < ARRAY_SIZE(names); i++) {
1664 fd = open(names[i], O_WRONLY);
1668 if (write(fd, "-1", 2)) {}
1674 bool system_resolve_rt_type(const char *type, unsigned int *id)
1676 return system_rtn_aton(type, id);
1679 bool system_resolve_rt_table(const char *name, unsigned int *id)
1683 unsigned int n, table = RT_TABLE_UNSPEC;
1685 /* first try to parse table as number */
1686 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1689 /* handle well known aliases */
1690 else if (!strcmp(name, "default"))
1691 table = RT_TABLE_DEFAULT;
1692 else if (!strcmp(name, "main"))
1693 table = RT_TABLE_MAIN;
1694 else if (!strcmp(name, "local"))
1695 table = RT_TABLE_LOCAL;
1696 else if (!strcmp(name, "prelocal"))
1697 table = RT_TABLE_PRELOCAL;
1699 /* try to look up name in /etc/iproute2/rt_tables */
1700 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1702 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1704 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1707 n = strtoul(e, NULL, 10);
1708 e = strtok(NULL, " \t\n");
1710 if (e && !strcmp(e, name))
1720 if (table == RT_TABLE_UNSPEC)
1727 bool system_is_default_rt_table(unsigned int id)
1729 return (id == RT_TABLE_MAIN);
1732 bool system_resolve_rpfilter(const char *filter, unsigned int *id)
1737 if (!strcmp(filter, "strict"))
1739 else if (!strcmp(filter, "loose"))
1742 n = strtoul(filter, &e, 0);
1743 if (*e || e == filter || n > 2)
1751 static int system_iprule(struct iprule *rule, int cmd)
1753 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1756 struct rtmsg rtm = {
1757 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1758 .rtm_protocol = RTPROT_STATIC,
1759 .rtm_scope = RT_SCOPE_UNIVERSE,
1760 .rtm_table = RT_TABLE_UNSPEC,
1761 .rtm_type = RTN_UNSPEC,
1765 if (cmd == RTM_NEWRULE) {
1766 rtm.rtm_type = RTN_UNICAST;
1767 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1771 rtm.rtm_flags |= FIB_RULE_INVERT;
1773 if (rule->flags & IPRULE_SRC)
1774 rtm.rtm_src_len = rule->src_mask;
1776 if (rule->flags & IPRULE_DEST)
1777 rtm.rtm_dst_len = rule->dest_mask;
1779 if (rule->flags & IPRULE_TOS)
1780 rtm.rtm_tos = rule->tos;
1782 if (rule->flags & IPRULE_LOOKUP) {
1783 if (rule->lookup < 256)
1784 rtm.rtm_table = rule->lookup;
1787 if (rule->flags & IPRULE_ACTION)
1788 rtm.rtm_type = rule->action;
1789 else if (rule->flags & IPRULE_GOTO)
1790 rtm.rtm_type = FR_ACT_GOTO;
1791 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1792 rtm.rtm_type = FR_ACT_NOP;
1794 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1799 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1801 if (rule->flags & IPRULE_IN)
1802 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1804 if (rule->flags & IPRULE_OUT)
1805 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1807 if (rule->flags & IPRULE_SRC)
1808 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1810 if (rule->flags & IPRULE_DEST)
1811 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1813 if (rule->flags & IPRULE_PRIORITY)
1814 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1815 else if (cmd == RTM_NEWRULE)
1816 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1818 if (rule->flags & IPRULE_FWMARK)
1819 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1821 if (rule->flags & IPRULE_FWMASK)
1822 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1824 if (rule->flags & IPRULE_LOOKUP) {
1825 if (rule->lookup >= 256)
1826 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1829 if (rule->flags & IPRULE_GOTO)
1830 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1832 return system_rtnl_call(msg);
1835 int system_add_iprule(struct iprule *rule)
1837 return system_iprule(rule, RTM_NEWRULE);
1840 int system_del_iprule(struct iprule *rule)
1842 return system_iprule(rule, RTM_DELRULE);
1845 int system_flush_iprules(void)
1850 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1851 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1853 memset(&rule, 0, sizeof(rule));
1856 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1859 rule.lookup = RT_TABLE_PRELOCAL;
1860 rv |= system_iprule(&rule, RTM_NEWRULE);
1863 rule.lookup = RT_TABLE_LOCAL;
1864 rv |= system_iprule(&rule, RTM_NEWRULE);
1866 rule.priority = 32766;
1867 rule.lookup = RT_TABLE_MAIN;
1868 rv |= system_iprule(&rule, RTM_NEWRULE);
1870 rule.priority = 32767;
1871 rule.lookup = RT_TABLE_DEFAULT;
1872 rv |= system_iprule(&rule, RTM_NEWRULE);
1875 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1878 rule.lookup = RT_TABLE_PRELOCAL;
1879 rv |= system_iprule(&rule, RTM_NEWRULE);
1882 rule.lookup = RT_TABLE_LOCAL;
1883 rv |= system_iprule(&rule, RTM_NEWRULE);
1885 rule.priority = 32766;
1886 rule.lookup = RT_TABLE_MAIN;
1887 rv |= system_iprule(&rule, RTM_NEWRULE);
1892 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1894 return system_rtn_aton(action, id);
1897 time_t system_get_rtime(void)
1902 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1905 if (gettimeofday(&tv, NULL) == 0)
1912 #define IP_DF 0x4000
1915 static int tunnel_ioctl(const char *name, int cmd, void *p)
1919 memset(&ifr, 0, sizeof(ifr));
1920 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1921 ifr.ifr_ifru.ifru_data = p;
1922 return ioctl(sock_ioctl, cmd, &ifr);
1925 #ifdef IFLA_IPTUN_MAX
1926 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
1927 static int system_add_gre_tunnel(const char *name, const char *kind,
1928 const unsigned int link, struct blob_attr **tb, bool v6)
1931 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
1932 struct blob_attr *cur;
1933 uint32_t ikey = 0, okey = 0, flags = 0, flowinfo = 0;
1934 uint16_t iflags = 0, oflags = 0;
1936 int ret = 0, ttl = 64;
1938 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
1942 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
1943 nla_put_string(nlm, IFLA_IFNAME, name);
1945 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
1951 nla_put_string(nlm, IFLA_INFO_KIND, kind);
1952 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
1959 nla_put_u32(nlm, IFLA_GRE_LINK, link);
1961 if ((cur = tb[TUNNEL_ATTR_TTL]))
1962 ttl = blobmsg_get_u32(cur);
1964 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
1966 if ((cur = tb[TUNNEL_ATTR_TOS])) {
1967 char *str = blobmsg_get_string(cur);
1968 if (strcmp(str, "inherit")) {
1971 if (!system_tos_aton(str, &uval)) {
1977 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
1982 flags |= IP6_TNL_F_USE_ORIG_TCLASS;
1988 if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) {
1989 uint8_t icsum, ocsum, iseqno, oseqno;
1990 if (sscanf(blobmsg_get_string(cur), "%u,%u,%hhu,%hhu,%hhu,%hhu",
1991 &ikey, &okey, &icsum, &ocsum, &iseqno, &oseqno) < 6) {
2016 struct in6_addr in6buf;
2017 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2018 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2022 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
2025 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2026 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2030 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
2032 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, 4);
2035 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
2038 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags);
2040 struct in_addr inbuf;
2043 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2044 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2048 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
2051 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2052 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2056 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
2058 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
2060 okey = inbuf.s_addr;
2065 ikey = inbuf.s_addr;
2071 if ((cur = tb[TUNNEL_ATTR_DF]))
2072 set_df = blobmsg_get_bool(cur);
2074 /* ttl !=0 and nopmtudisc are incompatible */
2075 if (ttl && !set_df) {
2080 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
2082 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
2086 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
2089 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
2092 nla_put_u32(nlm, IFLA_GRE_OKEY, okey);
2095 nla_put_u32(nlm, IFLA_GRE_IKEY, ikey);
2097 nla_nest_end(nlm, infodata);
2098 nla_nest_end(nlm, linkinfo);
2100 return system_rtnl_call(nlm);
2108 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
2110 struct blob_attr *cur;
2112 struct ip_tunnel_parm p = {
2121 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
2122 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
2125 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
2126 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
2129 if ((cur = tb[TUNNEL_ATTR_DF]))
2130 set_df = blobmsg_get_bool(cur);
2132 if ((cur = tb[TUNNEL_ATTR_TTL]))
2133 p.iph.ttl = blobmsg_get_u32(cur);
2135 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2136 char *str = blobmsg_get_string(cur);
2137 if (strcmp(str, "inherit")) {
2140 if (!system_tos_aton(str, &uval))
2148 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
2149 /* ttl !=0 and nopmtudisc are incompatible */
2150 if (p.iph.ttl && p.iph.frag_off == 0)
2153 strncpy(p.name, name, sizeof(p.name));
2155 switch (p.iph.protocol) {
2157 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
2159 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
2166 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
2168 struct blob_attr *cur;
2171 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2173 str = blobmsg_data(cur);
2175 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
2176 !strcmp(str, "greip6") || !strcmp(str, "gretapip6"))
2177 return system_link_del(name);
2179 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
2182 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
2184 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2186 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2187 blob_data(attr), blob_len(attr));
2189 return __system_del_ip_tunnel(name, tb);
2192 int system_update_ipv6_mtu(struct device *dev, int mtu)
2196 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
2199 int fd = open(buf, O_RDWR);
2202 ssize_t len = read(fd, buf, sizeof(buf) - 1);
2209 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) > 0)
2218 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
2220 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2221 struct blob_attr *cur;
2224 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2225 blob_data(attr), blob_len(attr));
2227 __system_del_ip_tunnel(name, tb);
2229 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2231 str = blobmsg_data(cur);
2233 unsigned int ttl = 0;
2234 if ((cur = tb[TUNNEL_ATTR_TTL])) {
2235 ttl = blobmsg_get_u32(cur);
2240 unsigned int link = 0;
2241 if ((cur = tb[TUNNEL_ATTR_LINK])) {
2242 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
2246 if (iface->l3_dev.dev)
2247 link = iface->l3_dev.dev->ifindex;
2250 if (!strcmp(str, "sit")) {
2251 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
2255 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
2257 struct ip_tunnel_6rd p6;
2259 memset(&p6, 0, sizeof(p6));
2261 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
2262 &p6.prefix, &mask) || mask > 128)
2264 p6.prefixlen = mask;
2266 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
2267 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
2268 &p6.relay_prefix, &mask) || mask > 32)
2270 p6.relay_prefixlen = mask;
2273 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
2274 __system_del_ip_tunnel(name, tb);
2279 #ifdef IFLA_IPTUN_MAX
2280 } else if (!strcmp(str, "ipip6")) {
2281 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2282 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2283 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2289 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2290 nla_put_string(nlm, IFLA_IFNAME, name);
2293 nla_put_u32(nlm, IFLA_LINK, link);
2295 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2300 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2301 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2308 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2310 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2311 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2312 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
2314 struct in6_addr in6buf;
2315 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2316 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2320 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2323 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2324 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2328 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2331 #ifdef IFLA_IPTUN_FMR_MAX
2332 if ((cur = tb[TUNNEL_ATTR_FMRS])) {
2333 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2335 struct blob_attr *fmr;
2336 unsigned rem, fmrcnt = 0;
2337 blobmsg_for_each_attr(fmr, cur, rem) {
2338 if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
2341 unsigned ip4len, ip6len, ealen, offset = 6;
2345 if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
2346 ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) {
2351 struct in6_addr ip6prefix;
2352 struct in_addr ip4prefix;
2353 if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
2354 inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) {
2359 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2361 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2362 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2363 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2364 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2365 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2366 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2368 nla_nest_end(nlm, rule);
2371 nla_nest_end(nlm, fmrs);
2375 nla_nest_end(nlm, infodata);
2376 nla_nest_end(nlm, linkinfo);
2378 return system_rtnl_call(nlm);
2382 } else if (!strcmp(str, "greip")) {
2383 return system_add_gre_tunnel(name, "gre", link, tb, false);
2384 } else if (!strcmp(str, "gretapip")) {
2385 return system_add_gre_tunnel(name, "gretap", link, tb, false);
2386 } else if (!strcmp(str, "greip6")) {
2387 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
2388 } else if (!strcmp(str, "gretapip6")) {
2389 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
2391 } else if (!strcmp(str, "ipip")) {
2392 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);