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_link.h>
34 #include <linux/if_vlan.h>
35 #include <linux/if_bridge.h>
36 #include <linux/if_tunnel.h>
37 #include <linux/ip6_tunnel.h>
38 #include <linux/ethtool.h>
39 #include <linux/fib_rules.h>
40 #include <linux/version.h>
42 #ifndef RTN_FAILED_POLICY
43 #define RTN_FAILED_POLICY 12
46 #ifndef RT_TABLE_PRELOCAL
47 #define RT_TABLE_PRELOCAL 128
55 #include <netlink/msg.h>
56 #include <netlink/attr.h>
57 #include <netlink/socket.h>
58 #include <libubox/uloop.h>
65 struct uloop_fd uloop;
70 static int sock_ioctl = -1;
71 static struct nl_sock *sock_rtnl = NULL;
73 static int cb_rtnl_event(struct nl_msg *msg, void *arg);
74 static void handle_hotplug_event(struct uloop_fd *u, unsigned int events);
76 static char dev_buf[256];
79 handler_nl_event(struct uloop_fd *u, unsigned int events)
81 struct event_socket *ev = container_of(u, struct event_socket, uloop);
83 socklen_t errlen = sizeof(err);
86 nl_recvmsgs_default(ev->sock);
90 if (getsockopt(u->fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen))
95 // Increase rx buffer size on netlink socket
97 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
100 // Request full dump since some info got dropped
101 struct rtgenmsg msg = { .rtgen_family = AF_UNSPEC };
102 nl_send_simple(ev->sock, RTM_GETLINK, NLM_F_DUMP, &msg, sizeof(msg));
112 uloop_fd_delete(&ev->uloop);
116 static struct nl_sock *
117 create_socket(int protocol, int groups)
119 struct nl_sock *sock;
121 sock = nl_socket_alloc();
126 nl_join_groups(sock, groups);
128 if (nl_connect(sock, protocol))
135 create_raw_event_socket(struct event_socket *ev, int protocol, int groups,
136 uloop_fd_handler cb, int flags)
138 ev->sock = create_socket(protocol, groups);
142 ev->uloop.fd = nl_socket_get_fd(ev->sock);
144 if (uloop_fd_add(&ev->uloop, ULOOP_READ|flags))
151 create_event_socket(struct event_socket *ev, int protocol,
152 int (*cb)(struct nl_msg *msg, void *arg))
154 if (!create_raw_event_socket(ev, protocol, 0, handler_nl_event, ULOOP_ERROR_CB))
157 // Install the valid custom callback handler
158 nl_socket_modify_cb(ev->sock, NL_CB_VALID, NL_CB_CUSTOM, cb, NULL);
160 // Disable sequence number checking on event sockets
161 nl_socket_disable_seq_check(ev->sock);
163 // Increase rx buffer size to 65K on event sockets
165 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
172 system_rtn_aton(const char *src, unsigned int *dst)
177 if (!strcmp(src, "local"))
179 else if (!strcmp(src, "nat"))
181 else if (!strcmp(src, "broadcast"))
183 else if (!strcmp(src, "anycast"))
185 else if (!strcmp(src, "multicast"))
187 else if (!strcmp(src, "prohibit"))
189 else if (!strcmp(src, "unreachable"))
191 else if (!strcmp(src, "blackhole"))
193 else if (!strcmp(src, "xresolve"))
195 else if (!strcmp(src, "unicast"))
197 else if (!strcmp(src, "throw"))
199 else if (!strcmp(src, "failed_policy"))
200 n = RTN_FAILED_POLICY;
202 n = strtoul(src, &e, 0);
203 if (!e || *e || e == src || n > 255)
212 system_tos_aton(const char *src, unsigned *dst)
216 *dst = strtoul(src, &e, 16);
217 if (e == src || *e || *dst > 255)
223 int system_init(void)
225 static struct event_socket rtnl_event;
226 static struct event_socket hotplug_event;
228 sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0);
229 system_fd_set_cloexec(sock_ioctl);
231 // Prepare socket for routing / address control
232 sock_rtnl = create_socket(NETLINK_ROUTE, 0);
236 if (!create_event_socket(&rtnl_event, NETLINK_ROUTE, cb_rtnl_event))
239 if (!create_raw_event_socket(&hotplug_event, NETLINK_KOBJECT_UEVENT, 1,
240 handle_hotplug_event, 0))
243 // Receive network link events form kernel
244 nl_socket_add_membership(rtnl_event.sock, RTNLGRP_LINK);
249 static void system_set_sysctl(const char *path, const char *val)
253 fd = open(path, O_WRONLY);
257 if (write(fd, val, strlen(val))) {}
261 static void system_set_dev_sysctl(const char *path, const char *device, const char *val)
263 snprintf(dev_buf, sizeof(dev_buf), path, device);
264 system_set_sysctl(dev_buf, val);
267 static void system_set_disable_ipv6(struct device *dev, const char *val)
269 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val);
272 static void system_set_rpfilter(struct device *dev, const char *val)
274 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter", dev->ifname, val);
277 static void system_set_acceptlocal(struct device *dev, const char *val)
279 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local", dev->ifname, val);
282 static void system_set_igmpversion(struct device *dev, const char *val)
284 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version", dev->ifname, val);
287 static void system_set_mldversion(struct device *dev, const char *val)
289 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version", dev->ifname, val);
292 static void system_set_neigh4reachabletime(struct device *dev, const char *val)
294 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms", dev->ifname, val);
297 static void system_set_neigh6reachabletime(struct device *dev, const char *val)
299 system_set_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms", dev->ifname, val);
302 static int system_get_sysctl(const char *path, char *buf, const size_t buf_sz)
304 int fd = -1, ret = -1;
306 fd = open(path, O_RDONLY);
310 ssize_t len = read(fd, buf, buf_sz - 1);
324 system_get_dev_sysctl(const char *path, const char *device, char *buf, const size_t buf_sz)
326 snprintf(dev_buf, sizeof(dev_buf), path, device);
327 return system_get_sysctl(dev_buf, buf, buf_sz);
330 static int system_get_disable_ipv6(struct device *dev, char *buf, const size_t buf_sz)
332 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6",
333 dev->ifname, buf, buf_sz);
336 static int system_get_rpfilter(struct device *dev, char *buf, const size_t buf_sz)
338 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter",
339 dev->ifname, buf, buf_sz);
342 static int system_get_acceptlocal(struct device *dev, char *buf, const size_t buf_sz)
344 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local",
345 dev->ifname, buf, buf_sz);
348 static int system_get_igmpversion(struct device *dev, char *buf, const size_t buf_sz)
350 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version",
351 dev->ifname, buf, buf_sz);
354 static int system_get_mldversion(struct device *dev, char *buf, const size_t buf_sz)
356 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version",
357 dev->ifname, buf, buf_sz);
360 static int system_get_neigh4reachabletime(struct device *dev, char *buf, const size_t buf_sz)
362 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms",
363 dev->ifname, buf, buf_sz);
366 static int system_get_neigh6reachabletime(struct device *dev, char *buf, const size_t buf_sz)
368 return system_get_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms",
369 dev->ifname, buf, buf_sz);
372 // Evaluate netlink messages
373 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
375 struct nlmsghdr *nh = nlmsg_hdr(msg);
376 struct ifinfomsg *ifi = NLMSG_DATA(nh);
377 struct nlattr *nla[__IFLA_MAX];
381 if (nh->nlmsg_type != RTM_NEWLINK)
384 nlmsg_parse(nh, sizeof(*ifi), nla, __IFLA_MAX - 1, NULL);
385 if (!nla[IFLA_IFNAME])
388 struct device *dev = device_get(nla_data(nla[IFLA_IFNAME]), false);
389 if (!dev || dev->type->keep_link_status)
392 if (!system_get_dev_sysctl("/sys/class/net/%s/carrier", dev->ifname, buf, sizeof(buf)))
393 link_state = strtoul(buf, NULL, 0);
395 device_set_link(dev, link_state ? true : false);
402 handle_hotplug_msg(char *data, int size)
404 const char *subsystem = NULL, *interface = NULL;
405 char *cur, *end, *sep;
410 if (!strncmp(data, "add@", 4))
412 else if (!strncmp(data, "remove@", 7))
417 skip = strlen(data) + 1;
420 for (cur = data + skip; cur < end; cur += skip) {
421 skip = strlen(cur) + 1;
423 sep = strchr(cur, '=');
428 if (!strcmp(cur, "INTERFACE"))
430 else if (!strcmp(cur, "SUBSYSTEM")) {
432 if (strcmp(subsystem, "net") != 0)
435 if (subsystem && interface)
441 dev = device_get(interface, false);
445 if (dev->type != &simple_device_type)
448 if (add && system_if_force_external(dev->ifname))
451 device_set_present(dev, add);
455 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
457 struct event_socket *ev = container_of(u, struct event_socket, uloop);
458 struct sockaddr_nl nla;
459 unsigned char *buf = NULL;
462 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
464 handle_hotplug_msg((char *) buf, size);
470 static int system_rtnl_call(struct nl_msg *msg)
474 ret = nl_send_auto_complete(sock_rtnl, msg);
480 return nl_wait_for_ack(sock_rtnl);
483 int system_bridge_delbr(struct device *bridge)
485 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
488 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
492 memset(&ifr, 0, sizeof(ifr));
494 ifr.ifr_ifindex = dev->ifindex;
497 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
498 return ioctl(sock_ioctl, cmd, &ifr);
501 static bool system_is_bridge(const char *name, char *buf, int buflen)
505 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
506 if (stat(buf, &st) < 0)
512 static char *system_get_bridge(const char *name, char *buf, int buflen)
518 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
519 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
523 len = readlink(gl.gl_pathv[0], buf, buflen);
531 path = strrchr(buf, '/');
538 static void system_bridge_set_wireless(const char *bridge, const char *dev)
540 snprintf(dev_buf, sizeof(dev_buf),
541 "/sys/devices/virtual/net/%s/brif/%s/multicast_to_unicast",
543 system_set_sysctl(dev_buf, "1");
546 int system_bridge_addif(struct device *bridge, struct device *dev)
551 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
552 if (!oldbr || strcmp(oldbr, bridge->ifname) != 0)
553 ret = system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
556 system_bridge_set_wireless(bridge->ifname, dev->ifname);
561 int system_bridge_delif(struct device *bridge, struct device *dev)
563 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
566 int system_if_resolve(struct device *dev)
569 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
570 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
571 return ifr.ifr_ifindex;
576 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
580 memset(&ifr, 0, sizeof(ifr));
581 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
582 ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
583 ifr.ifr_flags |= add;
584 ifr.ifr_flags &= ~rem;
585 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
597 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
599 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
601 return ifa->ifa_index == ifindex;
604 static bool check_route(struct nlmsghdr *hdr, int ifindex)
606 struct rtmsg *r = NLMSG_DATA(hdr);
607 struct nlattr *tb[__RTA_MAX];
609 if (r->rtm_protocol == RTPROT_KERNEL &&
610 r->rtm_family == AF_INET6)
613 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
617 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
620 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
625 static int cb_clear_event(struct nl_msg *msg, void *arg)
627 struct clear_data *clr = arg;
628 struct nlmsghdr *hdr = nlmsg_hdr(msg);
629 bool (*cb)(struct nlmsghdr *, int ifindex);
635 if (hdr->nlmsg_type != RTM_NEWADDR)
642 if (hdr->nlmsg_type != RTM_NEWROUTE)
649 if (hdr->nlmsg_type != RTM_NEWRULE)
658 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
661 if (type == RTM_DELRULE)
662 D(SYSTEM, "Remove a rule\n");
664 D(SYSTEM, "Remove %s from device %s\n",
665 type == RTM_DELADDR ? "an address" : "a route",
667 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
668 hdr = nlmsg_hdr(clr->msg);
669 hdr->nlmsg_type = type;
670 hdr->nlmsg_flags = NLM_F_REQUEST;
672 nl_socket_disable_auto_ack(sock_rtnl);
673 nl_send_auto_complete(sock_rtnl, clr->msg);
674 nl_socket_enable_auto_ack(sock_rtnl);
680 cb_finish_event(struct nl_msg *msg, void *arg)
688 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
691 *pending = err->error;
696 system_if_clear_entries(struct device *dev, int type, int af)
698 struct clear_data clr;
699 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
702 .rtm_flags = RTM_F_CLONED,
704 int flags = NLM_F_DUMP;
713 clr.size = sizeof(struct rtgenmsg);
716 clr.size = sizeof(struct rtmsg);
725 clr.msg = nlmsg_alloc_simple(type, flags);
729 nlmsg_append(clr.msg, &rtm, clr.size, 0);
730 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
731 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
732 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
734 nl_send_auto_complete(sock_rtnl, clr.msg);
736 nl_recvmsgs(sock_rtnl, cb);
744 * Clear bridge (membership) state and bring down device
746 void system_if_clear_state(struct device *dev)
748 static char buf[256];
751 device_set_ifindex(dev, system_if_resolve(dev));
752 if (dev->external || !dev->ifindex)
755 system_if_flags(dev->ifname, 0, IFF_UP);
757 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
758 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
759 system_bridge_delbr(dev);
763 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
765 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
766 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
769 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
770 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
771 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
772 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
773 system_set_disable_ipv6(dev, "0");
776 static inline unsigned long
777 sec_to_jiffies(int val)
779 return (unsigned long) val * 100;
782 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
784 unsigned long args[4] = {};
786 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
789 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
790 args[1] = !!cfg->stp;
791 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
793 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
794 args[1] = sec_to_jiffies(cfg->forward_delay);
795 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
797 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
798 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
800 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier",
801 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
803 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
804 args[1] = cfg->priority;
805 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
807 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
808 args[0] = BRCTL_SET_AGEING_TIME;
809 args[1] = sec_to_jiffies(cfg->ageing_time);
810 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
813 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
814 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
815 args[1] = sec_to_jiffies(cfg->hello_time);
816 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
819 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
820 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
821 args[1] = sec_to_jiffies(cfg->max_age);
822 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
828 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
831 struct nlattr *linkinfo, *data;
832 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
834 static const struct {
836 enum macvlan_mode val;
838 { "private", MACVLAN_MODE_PRIVATE },
839 { "vepa", MACVLAN_MODE_VEPA },
840 { "bridge", MACVLAN_MODE_BRIDGE },
841 { "passthru", MACVLAN_MODE_PASSTHRU },
844 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
849 nlmsg_append(msg, &iim, sizeof(iim), 0);
851 if (cfg->flags & MACVLAN_OPT_MACADDR)
852 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
853 nla_put_string(msg, IFLA_IFNAME, macvlan->ifname);
854 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
856 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
857 goto nla_put_failure;
859 nla_put_string(msg, IFLA_INFO_KIND, "macvlan");
861 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
862 goto nla_put_failure;
865 for (i = 0; i < ARRAY_SIZE(modes); i++) {
866 if (strcmp(cfg->mode, modes[i].name) != 0)
869 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
874 nla_nest_end(msg, data);
875 nla_nest_end(msg, linkinfo);
877 rv = system_rtnl_call(msg);
879 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
888 static int system_link_del(const char *ifname)
891 struct ifinfomsg iim = {
892 .ifi_family = AF_UNSPEC,
896 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
901 nlmsg_append(msg, &iim, sizeof(iim), 0);
902 nla_put_string(msg, IFLA_IFNAME, ifname);
903 return system_rtnl_call(msg);
906 int system_macvlan_del(struct device *macvlan)
908 return system_link_del(macvlan->ifname);
911 static int system_vlan(struct device *dev, int id)
913 struct vlan_ioctl_args ifr = {
914 .cmd = SET_VLAN_NAME_TYPE_CMD,
915 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
918 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
921 ifr.cmd = DEL_VLAN_CMD;
924 ifr.cmd = ADD_VLAN_CMD;
927 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
928 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
931 int system_vlan_add(struct device *dev, int id)
933 return system_vlan(dev, id);
936 int system_vlan_del(struct device *dev)
938 return system_vlan(dev, -1);
941 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
944 struct nlattr *linkinfo, *data;
945 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
948 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
953 nlmsg_append(msg, &iim, sizeof(iim), 0);
954 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
955 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
957 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
958 goto nla_put_failure;
960 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
962 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
963 goto nla_put_failure;
965 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
967 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
968 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
970 if(cfg->proto == VLAN_PROTO_8021AD)
971 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);
974 nla_nest_end(msg, data);
975 nla_nest_end(msg, linkinfo);
977 rv = system_rtnl_call(msg);
979 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
988 int system_vlandev_del(struct device *vlandev)
990 return system_link_del(vlandev->ifname);
994 system_if_get_settings(struct device *dev, struct device_settings *s)
999 memset(&ifr, 0, sizeof(ifr));
1000 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1002 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
1003 s->mtu = ifr.ifr_mtu;
1004 s->flags |= DEV_OPT_MTU;
1007 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
1008 s->txqueuelen = ifr.ifr_qlen;
1009 s->flags |= DEV_OPT_TXQUEUELEN;
1012 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
1013 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
1014 s->flags |= DEV_OPT_MACADDR;
1017 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
1018 s->ipv6 = !strtoul(buf, NULL, 0);
1019 s->flags |= DEV_OPT_IPV6;
1022 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
1023 s->promisc = ifr.ifr_flags & IFF_PROMISC;
1024 s->flags |= DEV_OPT_PROMISC;
1027 if (!system_get_rpfilter(dev, buf, sizeof(buf))) {
1028 s->rpfilter = strtoul(buf, NULL, 0);
1029 s->flags |= DEV_OPT_RPFILTER;
1032 if (!system_get_acceptlocal(dev, buf, sizeof(buf))) {
1033 s->acceptlocal = strtoul(buf, NULL, 0);
1034 s->flags |= DEV_OPT_ACCEPTLOCAL;
1037 if (!system_get_igmpversion(dev, buf, sizeof(buf))) {
1038 s->igmpversion = strtoul(buf, NULL, 0);
1039 s->flags |= DEV_OPT_IGMPVERSION;
1042 if (!system_get_mldversion(dev, buf, sizeof(buf))) {
1043 s->mldversion = strtoul(buf, NULL, 0);
1044 s->flags |= DEV_OPT_MLDVERSION;
1047 if (!system_get_neigh4reachabletime(dev, buf, sizeof(buf))) {
1048 s->neigh4reachabletime = strtoul(buf, NULL, 0);
1049 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1052 if (!system_get_neigh6reachabletime(dev, buf, sizeof(buf))) {
1053 s->neigh6reachabletime = strtoul(buf, NULL, 0);
1054 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1059 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
1066 memset(&ifr, 0, sizeof(ifr));
1067 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1068 if (s->flags & DEV_OPT_MTU & apply_mask) {
1069 ifr.ifr_mtu = s->mtu;
1070 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
1071 s->flags &= ~DEV_OPT_MTU;
1073 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
1074 ifr.ifr_qlen = s->txqueuelen;
1075 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
1076 s->flags &= ~DEV_OPT_TXQUEUELEN;
1078 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
1079 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
1080 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
1081 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
1082 s->flags &= ~DEV_OPT_MACADDR;
1084 if (s->flags & DEV_OPT_IPV6 & apply_mask)
1085 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
1086 if (s->flags & DEV_OPT_PROMISC & apply_mask) {
1087 if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
1088 !s->promisc ? IFF_PROMISC : 0) < 0)
1089 s->flags &= ~DEV_OPT_PROMISC;
1091 if (s->flags & DEV_OPT_RPFILTER & apply_mask) {
1094 snprintf(buf, sizeof(buf), "%d", s->rpfilter);
1095 system_set_rpfilter(dev, buf);
1097 if (s->flags & DEV_OPT_ACCEPTLOCAL & apply_mask)
1098 system_set_acceptlocal(dev, s->acceptlocal ? "1" : "0");
1099 if (s->flags & DEV_OPT_IGMPVERSION & apply_mask) {
1102 snprintf(buf, sizeof(buf), "%d", s->igmpversion);
1103 system_set_igmpversion(dev, buf);
1105 if (s->flags & DEV_OPT_MLDVERSION & apply_mask) {
1108 snprintf(buf, sizeof(buf), "%d", s->mldversion);
1109 system_set_mldversion(dev, buf);
1111 if (s->flags & DEV_OPT_NEIGHREACHABLETIME & apply_mask) {
1114 snprintf(buf, sizeof(buf), "%d", s->neigh4reachabletime);
1115 system_set_neigh4reachabletime(dev, buf);
1116 snprintf(buf, sizeof(buf), "%d", s->neigh6reachabletime);
1117 system_set_neigh6reachabletime(dev, buf);
1121 int system_if_up(struct device *dev)
1123 system_if_get_settings(dev, &dev->orig_settings);
1124 /* Only keep orig settings based on what needs to be set */
1125 dev->orig_settings.flags &= dev->settings.flags;
1126 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
1127 return system_if_flags(dev->ifname, IFF_UP, 0);
1130 int system_if_down(struct device *dev)
1132 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
1133 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
1137 struct if_check_data {
1143 #ifndef IFF_LOWER_UP
1144 #define IFF_LOWER_UP 0x10000
1147 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1149 struct nlmsghdr *nh = nlmsg_hdr(msg);
1150 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1151 struct if_check_data *chk = (struct if_check_data *)arg;
1153 if (nh->nlmsg_type != RTM_NEWLINK)
1156 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1157 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1162 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1164 struct if_check_data *chk = (struct if_check_data *)arg;
1169 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1171 struct if_check_data *chk = (struct if_check_data *)arg;
1173 device_set_present(chk->dev, false);
1174 device_set_link(chk->dev, false);
1175 chk->pending = err->error;
1180 int system_if_check(struct device *dev)
1182 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1184 struct ifinfomsg ifi = {
1185 .ifi_family = AF_UNSPEC,
1188 struct if_check_data chk = {
1194 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1195 if (!msg || nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1196 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1199 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1200 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1201 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1203 nl_send_auto_complete(sock_rtnl, msg);
1204 while (chk.pending > 0)
1205 nl_recvmsgs(sock_rtnl, cb);
1216 system_if_get_parent(struct device *dev)
1218 char buf[64], *devname;
1219 int ifindex, iflink, len;
1222 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1223 f = fopen(buf, "r");
1227 len = fread(buf, 1, sizeof(buf) - 1, f);
1234 iflink = strtoul(buf, NULL, 0);
1235 ifindex = system_if_resolve(dev);
1236 if (!iflink || iflink == ifindex)
1239 devname = if_indextoname(iflink, buf);
1243 return device_get(devname, true);
1247 read_string_file(int dir_fd, const char *file, char *buf, int len)
1253 fd = openat(dir_fd, file, O_RDONLY);
1258 len = read(fd, buf, len - 1);
1262 } else if (len > 0) {
1265 c = strchr(buf, '\n');
1278 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1283 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1285 *val = strtoull(buf, NULL, 0);
1290 /* Assume advertised flags == supported flags */
1291 static const struct {
1294 } ethtool_link_modes[] = {
1295 { ADVERTISED_10baseT_Half, "10H" },
1296 { ADVERTISED_10baseT_Full, "10F" },
1297 { ADVERTISED_100baseT_Half, "100H" },
1298 { ADVERTISED_100baseT_Full, "100F" },
1299 { ADVERTISED_1000baseT_Half, "1000H" },
1300 { ADVERTISED_1000baseT_Full, "1000F" },
1303 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1306 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1307 if (mask & ethtool_link_modes[i].mask)
1308 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1313 system_if_force_external(const char *ifname)
1318 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1319 return stat(buf, &s) == 0;
1323 system_if_dump_info(struct device *dev, struct blob_buf *b)
1325 struct ethtool_cmd ecmd;
1331 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
1332 dir_fd = open(buf, O_DIRECTORY);
1334 memset(&ecmd, 0, sizeof(ecmd));
1335 memset(&ifr, 0, sizeof(ifr));
1336 strcpy(ifr.ifr_name, dev->ifname);
1337 ifr.ifr_data = (caddr_t) &ecmd;
1338 ecmd.cmd = ETHTOOL_GSET;
1340 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1341 c = blobmsg_open_array(b, "link-advertising");
1342 system_add_link_modes(b, ecmd.advertising);
1343 blobmsg_close_array(b, c);
1345 c = blobmsg_open_array(b, "link-supported");
1346 system_add_link_modes(b, ecmd.supported);
1347 blobmsg_close_array(b, c);
1349 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1350 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1351 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1352 blobmsg_add_string_buffer(b);
1360 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1362 const char *const counters[] = {
1363 "collisions", "rx_frame_errors", "tx_compressed",
1364 "multicast", "rx_length_errors", "tx_dropped",
1365 "rx_bytes", "rx_missed_errors", "tx_errors",
1366 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1367 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1368 "rx_dropped", "tx_aborted_errors", "tx_packets",
1369 "rx_errors", "tx_bytes", "tx_window_errors",
1370 "rx_fifo_errors", "tx_carrier_errors",
1377 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1378 stats_dir = open(buf, O_DIRECTORY);
1382 for (i = 0; i < ARRAY_SIZE(counters); i++)
1383 if (read_uint64_file(stats_dir, counters[i], &val))
1384 blobmsg_add_u64(b, counters[i], val);
1390 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1392 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1393 int alen = v4 ? 4 : 16;
1394 unsigned int flags = 0;
1395 struct ifaddrmsg ifa = {
1396 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1397 .ifa_prefixlen = addr->mask,
1398 .ifa_index = dev->ifindex,
1402 if (cmd == RTM_NEWADDR)
1403 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1405 msg = nlmsg_alloc_simple(cmd, flags);
1409 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1410 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1412 if (addr->broadcast)
1413 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1414 if (addr->point_to_point)
1415 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1417 time_t now = system_get_rtime();
1418 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1420 if (addr->preferred_until) {
1421 int64_t preferred = addr->preferred_until - now;
1424 else if (preferred > UINT32_MAX)
1425 preferred = UINT32_MAX;
1427 cinfo.ifa_prefered = preferred;
1430 if (addr->valid_until) {
1431 int64_t valid = addr->valid_until - now;
1434 else if (valid > UINT32_MAX)
1437 cinfo.ifa_valid = valid;
1440 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1443 return system_rtnl_call(msg);
1446 int system_add_address(struct device *dev, struct device_addr *addr)
1448 return system_addr(dev, addr, RTM_NEWADDR);
1451 int system_del_address(struct device *dev, struct device_addr *addr)
1453 return system_addr(dev, addr, RTM_DELADDR);
1456 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1458 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1460 unsigned int flags = 0;
1463 have_gw = !!route->nexthop.in.s_addr;
1465 have_gw = route->nexthop.in6.s6_addr32[0] ||
1466 route->nexthop.in6.s6_addr32[1] ||
1467 route->nexthop.in6.s6_addr32[2] ||
1468 route->nexthop.in6.s6_addr32[3];
1470 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1471 ? route->table : RT_TABLE_MAIN;
1473 struct rtmsg rtm = {
1474 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1475 .rtm_dst_len = route->mask,
1476 .rtm_src_len = route->sourcemask,
1477 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1478 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
1479 .rtm_scope = RT_SCOPE_NOWHERE,
1480 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1481 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1485 if (cmd == RTM_NEWROUTE) {
1486 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1488 if (!dev) { // Add null-route
1489 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1490 rtm.rtm_type = RTN_UNREACHABLE;
1493 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1496 if (route->flags & DEVROUTE_TYPE) {
1497 rtm.rtm_type = route->type;
1498 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
1499 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
1500 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
1501 rtm.rtm_table = RT_TABLE_LOCAL;
1504 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT) {
1505 rtm.rtm_scope = RT_SCOPE_HOST;
1506 } else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
1507 rtm.rtm_type == RTN_ANYCAST) {
1508 rtm.rtm_scope = RT_SCOPE_LINK;
1509 } else if (rtm.rtm_type == RTN_BLACKHOLE || rtm.rtm_type == RTN_UNREACHABLE ||
1510 rtm.rtm_type == RTN_PROHIBIT || rtm.rtm_type == RTN_FAILED_POLICY) {
1511 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1516 msg = nlmsg_alloc_simple(cmd, flags);
1520 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1523 nla_put(msg, RTA_DST, alen, &route->addr);
1525 if (route->sourcemask) {
1526 if (rtm.rtm_family == AF_INET)
1527 nla_put(msg, RTA_PREFSRC, alen, &route->source);
1529 nla_put(msg, RTA_SRC, alen, &route->source);
1532 if (route->metric > 0)
1533 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1536 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1539 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1542 nla_put_u32(msg, RTA_TABLE, table);
1544 if (route->flags & DEVROUTE_MTU) {
1545 struct nlattr *metrics;
1547 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1548 goto nla_put_failure;
1550 nla_put_u32(msg, RTAX_MTU, route->mtu);
1552 nla_nest_end(msg, metrics);
1555 return system_rtnl_call(msg);
1562 int system_add_route(struct device *dev, struct device_route *route)
1564 return system_rt(dev, route, RTM_NEWROUTE);
1567 int system_del_route(struct device *dev, struct device_route *route)
1569 return system_rt(dev, route, RTM_DELROUTE);
1572 int system_flush_routes(void)
1574 const char *names[] = {
1575 "/proc/sys/net/ipv4/route/flush",
1576 "/proc/sys/net/ipv6/route/flush"
1580 for (i = 0; i < ARRAY_SIZE(names); i++) {
1581 fd = open(names[i], O_WRONLY);
1585 if (write(fd, "-1", 2)) {}
1591 bool system_resolve_rt_type(const char *type, unsigned int *id)
1593 return system_rtn_aton(type, id);
1596 bool system_resolve_rt_table(const char *name, unsigned int *id)
1600 unsigned int n, table = RT_TABLE_UNSPEC;
1602 /* first try to parse table as number */
1603 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1606 /* handle well known aliases */
1607 else if (!strcmp(name, "default"))
1608 table = RT_TABLE_DEFAULT;
1609 else if (!strcmp(name, "main"))
1610 table = RT_TABLE_MAIN;
1611 else if (!strcmp(name, "local"))
1612 table = RT_TABLE_LOCAL;
1613 else if (!strcmp(name, "prelocal"))
1614 table = RT_TABLE_PRELOCAL;
1616 /* try to look up name in /etc/iproute2/rt_tables */
1617 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1619 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1621 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1624 n = strtoul(e, NULL, 10);
1625 e = strtok(NULL, " \t\n");
1627 if (e && !strcmp(e, name))
1637 if (table == RT_TABLE_UNSPEC)
1644 bool system_is_default_rt_table(unsigned int id)
1646 return (id == RT_TABLE_MAIN);
1649 bool system_resolve_rpfilter(const char *filter, unsigned int *id)
1654 if (!strcmp(filter, "strict"))
1656 else if (!strcmp(filter, "loose"))
1659 n = strtoul(filter, &e, 0);
1660 if (*e || e == filter || n > 2)
1668 static int system_iprule(struct iprule *rule, int cmd)
1670 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1673 struct rtmsg rtm = {
1674 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1675 .rtm_protocol = RTPROT_STATIC,
1676 .rtm_scope = RT_SCOPE_UNIVERSE,
1677 .rtm_table = RT_TABLE_UNSPEC,
1678 .rtm_type = RTN_UNSPEC,
1682 if (cmd == RTM_NEWRULE) {
1683 rtm.rtm_type = RTN_UNICAST;
1684 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1688 rtm.rtm_flags |= FIB_RULE_INVERT;
1690 if (rule->flags & IPRULE_SRC)
1691 rtm.rtm_src_len = rule->src_mask;
1693 if (rule->flags & IPRULE_DEST)
1694 rtm.rtm_dst_len = rule->dest_mask;
1696 if (rule->flags & IPRULE_TOS)
1697 rtm.rtm_tos = rule->tos;
1699 if (rule->flags & IPRULE_LOOKUP) {
1700 if (rule->lookup < 256)
1701 rtm.rtm_table = rule->lookup;
1704 if (rule->flags & IPRULE_ACTION)
1705 rtm.rtm_type = rule->action;
1706 else if (rule->flags & IPRULE_GOTO)
1707 rtm.rtm_type = FR_ACT_GOTO;
1708 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1709 rtm.rtm_type = FR_ACT_NOP;
1711 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1716 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1718 if (rule->flags & IPRULE_IN)
1719 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1721 if (rule->flags & IPRULE_OUT)
1722 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1724 if (rule->flags & IPRULE_SRC)
1725 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1727 if (rule->flags & IPRULE_DEST)
1728 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1730 if (rule->flags & IPRULE_PRIORITY)
1731 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1732 else if (cmd == RTM_NEWRULE)
1733 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1735 if (rule->flags & IPRULE_FWMARK)
1736 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1738 if (rule->flags & IPRULE_FWMASK)
1739 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1741 if (rule->flags & IPRULE_LOOKUP) {
1742 if (rule->lookup >= 256)
1743 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1746 if (rule->flags & IPRULE_GOTO)
1747 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1749 return system_rtnl_call(msg);
1752 int system_add_iprule(struct iprule *rule)
1754 return system_iprule(rule, RTM_NEWRULE);
1757 int system_del_iprule(struct iprule *rule)
1759 return system_iprule(rule, RTM_DELRULE);
1762 int system_flush_iprules(void)
1767 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1768 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1770 memset(&rule, 0, sizeof(rule));
1773 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1776 rule.lookup = RT_TABLE_PRELOCAL;
1777 rv |= system_iprule(&rule, RTM_NEWRULE);
1780 rule.lookup = RT_TABLE_LOCAL;
1781 rv |= system_iprule(&rule, RTM_NEWRULE);
1783 rule.priority = 32766;
1784 rule.lookup = RT_TABLE_MAIN;
1785 rv |= system_iprule(&rule, RTM_NEWRULE);
1787 rule.priority = 32767;
1788 rule.lookup = RT_TABLE_DEFAULT;
1789 rv |= system_iprule(&rule, RTM_NEWRULE);
1792 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1795 rule.lookup = RT_TABLE_PRELOCAL;
1796 rv |= system_iprule(&rule, RTM_NEWRULE);
1799 rule.lookup = RT_TABLE_LOCAL;
1800 rv |= system_iprule(&rule, RTM_NEWRULE);
1802 rule.priority = 32766;
1803 rule.lookup = RT_TABLE_MAIN;
1804 rv |= system_iprule(&rule, RTM_NEWRULE);
1809 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1811 return system_rtn_aton(action, id);
1814 time_t system_get_rtime(void)
1819 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1822 if (gettimeofday(&tv, NULL) == 0)
1829 #define IP_DF 0x4000
1832 static int tunnel_ioctl(const char *name, int cmd, void *p)
1836 memset(&ifr, 0, sizeof(ifr));
1837 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1838 ifr.ifr_ifru.ifru_data = p;
1839 return ioctl(sock_ioctl, cmd, &ifr);
1842 #ifdef IFLA_IPTUN_MAX
1843 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
1844 static int system_add_gre_tunnel(const char *name, const char *kind,
1845 const unsigned int link, struct blob_attr **tb, bool v6)
1848 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
1849 struct blob_attr *cur;
1850 uint32_t ikey = 0, okey = 0, flags = 0, flowinfo = 0;
1851 uint16_t iflags = 0, oflags = 0;
1853 int ret = 0, ttl = 64;
1855 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
1859 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
1860 nla_put_string(nlm, IFLA_IFNAME, name);
1862 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
1868 nla_put_string(nlm, IFLA_INFO_KIND, kind);
1869 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
1876 nla_put_u32(nlm, IFLA_GRE_LINK, link);
1878 if ((cur = tb[TUNNEL_ATTR_TTL]))
1879 ttl = blobmsg_get_u32(cur);
1881 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
1883 if ((cur = tb[TUNNEL_ATTR_TOS])) {
1884 char *str = blobmsg_get_string(cur);
1885 if (strcmp(str, "inherit")) {
1888 if (!system_tos_aton(str, &uval)) {
1894 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
1899 flags |= IP6_TNL_F_USE_ORIG_TCLASS;
1905 if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) {
1906 uint8_t icsum, ocsum, iseqno, oseqno;
1907 if (sscanf(blobmsg_get_string(cur), "%u,%u,%hhu,%hhu,%hhu,%hhu",
1908 &ikey, &okey, &icsum, &ocsum, &iseqno, &oseqno) < 6) {
1933 struct in6_addr in6buf;
1934 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1935 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1939 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
1942 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
1943 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1947 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
1949 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, 4);
1952 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
1955 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags);
1957 struct in_addr inbuf;
1960 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1961 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
1965 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
1968 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
1969 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
1973 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
1975 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
1977 okey = inbuf.s_addr;
1982 ikey = inbuf.s_addr;
1988 if ((cur = tb[TUNNEL_ATTR_DF]))
1989 set_df = blobmsg_get_bool(cur);
1991 /* ttl !=0 and nopmtudisc are incompatible */
1992 if (ttl && !set_df) {
1997 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
1999 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
2003 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
2006 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
2009 nla_put_u32(nlm, IFLA_GRE_OKEY, okey);
2012 nla_put_u32(nlm, IFLA_GRE_IKEY, ikey);
2014 nla_nest_end(nlm, infodata);
2015 nla_nest_end(nlm, linkinfo);
2017 return system_rtnl_call(nlm);
2025 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
2027 struct blob_attr *cur;
2029 struct ip_tunnel_parm p = {
2038 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
2039 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
2042 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
2043 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
2046 if ((cur = tb[TUNNEL_ATTR_DF]))
2047 set_df = blobmsg_get_bool(cur);
2049 if ((cur = tb[TUNNEL_ATTR_TTL]))
2050 p.iph.ttl = blobmsg_get_u32(cur);
2052 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2053 char *str = blobmsg_get_string(cur);
2054 if (strcmp(str, "inherit")) {
2057 if (!system_tos_aton(str, &uval))
2065 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
2066 /* ttl !=0 and nopmtudisc are incompatible */
2067 if (p.iph.ttl && p.iph.frag_off == 0)
2070 strncpy(p.name, name, sizeof(p.name));
2072 switch (p.iph.protocol) {
2074 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
2076 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
2083 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
2085 struct blob_attr *cur;
2088 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2090 str = blobmsg_data(cur);
2092 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
2093 !strcmp(str, "greip6") || !strcmp(str, "gretapip6"))
2094 return system_link_del(name);
2096 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
2099 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
2101 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2103 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2104 blob_data(attr), blob_len(attr));
2106 return __system_del_ip_tunnel(name, tb);
2109 int system_update_ipv6_mtu(struct device *dev, int mtu)
2113 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
2116 int fd = open(buf, O_RDWR);
2117 ssize_t len = read(fd, buf, sizeof(buf) - 1);
2124 if (!mtu || ret <= mtu)
2127 lseek(fd, 0, SEEK_SET);
2128 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) <= 0)
2136 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
2138 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2139 struct blob_attr *cur;
2142 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2143 blob_data(attr), blob_len(attr));
2145 __system_del_ip_tunnel(name, tb);
2147 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2149 str = blobmsg_data(cur);
2151 unsigned int ttl = 0;
2152 if ((cur = tb[TUNNEL_ATTR_TTL])) {
2153 ttl = blobmsg_get_u32(cur);
2158 unsigned int link = 0;
2159 if ((cur = tb[TUNNEL_ATTR_LINK])) {
2160 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
2164 if (iface->l3_dev.dev)
2165 link = iface->l3_dev.dev->ifindex;
2168 if (!strcmp(str, "sit")) {
2169 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
2173 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
2175 struct ip_tunnel_6rd p6;
2177 memset(&p6, 0, sizeof(p6));
2179 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
2180 &p6.prefix, &mask) || mask > 128)
2182 p6.prefixlen = mask;
2184 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
2185 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
2186 &p6.relay_prefix, &mask) || mask > 32)
2188 p6.relay_prefixlen = mask;
2191 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
2192 __system_del_ip_tunnel(name, tb);
2197 #ifdef IFLA_IPTUN_MAX
2198 } else if (!strcmp(str, "ipip6")) {
2199 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2200 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2201 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2207 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2208 nla_put_string(nlm, IFLA_IFNAME, name);
2211 nla_put_u32(nlm, IFLA_LINK, link);
2213 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2218 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2219 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2226 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2228 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2229 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2230 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
2232 struct in6_addr in6buf;
2233 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2234 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2238 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2241 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2242 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2246 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2249 #ifdef IFLA_IPTUN_FMR_MAX
2250 if ((cur = tb[TUNNEL_ATTR_FMRS])) {
2251 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2253 struct blob_attr *fmr;
2254 unsigned rem, fmrcnt = 0;
2255 blobmsg_for_each_attr(fmr, cur, rem) {
2256 if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
2259 unsigned ip4len, ip6len, ealen, offset = 6;
2263 if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
2264 ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) {
2269 struct in6_addr ip6prefix;
2270 struct in_addr ip4prefix;
2271 if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
2272 inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) {
2277 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2279 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2280 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2281 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2282 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2283 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2284 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2286 nla_nest_end(nlm, rule);
2289 nla_nest_end(nlm, fmrs);
2293 nla_nest_end(nlm, infodata);
2294 nla_nest_end(nlm, linkinfo);
2296 return system_rtnl_call(nlm);
2300 } else if (!strcmp(str, "greip")) {
2301 return system_add_gre_tunnel(name, "gre", link, tb, false);
2302 } else if (!strcmp(str, "gretapip")) {
2303 return system_add_gre_tunnel(name, "gretap", link, tb, false);
2304 } else if (!strcmp(str, "greip6")) {
2305 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
2306 } else if (!strcmp(str, "gretapip6")) {
2307 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
2309 } else if (!strcmp(str, "ipip")) {
2310 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);