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
51 #include <netlink/msg.h>
52 #include <netlink/attr.h>
53 #include <netlink/socket.h>
54 #include <libubox/uloop.h>
61 struct uloop_fd uloop;
66 static int sock_ioctl = -1;
67 static struct nl_sock *sock_rtnl = NULL;
69 static int cb_rtnl_event(struct nl_msg *msg, void *arg);
70 static void handle_hotplug_event(struct uloop_fd *u, unsigned int events);
72 static char dev_buf[256];
75 handler_nl_event(struct uloop_fd *u, unsigned int events)
77 struct event_socket *ev = container_of(u, struct event_socket, uloop);
79 socklen_t errlen = sizeof(err);
82 nl_recvmsgs_default(ev->sock);
86 if (getsockopt(u->fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen))
91 // Increase rx buffer size on netlink socket
93 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
96 // Request full dump since some info got dropped
97 struct rtgenmsg msg = { .rtgen_family = AF_UNSPEC };
98 nl_send_simple(ev->sock, RTM_GETLINK, NLM_F_DUMP, &msg, sizeof(msg));
108 uloop_fd_delete(&ev->uloop);
112 static struct nl_sock *
113 create_socket(int protocol, int groups)
115 struct nl_sock *sock;
117 sock = nl_socket_alloc();
122 nl_join_groups(sock, groups);
124 if (nl_connect(sock, protocol))
131 create_raw_event_socket(struct event_socket *ev, int protocol, int groups,
132 uloop_fd_handler cb, int flags)
134 ev->sock = create_socket(protocol, groups);
138 ev->uloop.fd = nl_socket_get_fd(ev->sock);
140 if (uloop_fd_add(&ev->uloop, ULOOP_READ|flags))
147 create_event_socket(struct event_socket *ev, int protocol,
148 int (*cb)(struct nl_msg *msg, void *arg))
150 if (!create_raw_event_socket(ev, protocol, 0, handler_nl_event, ULOOP_ERROR_CB))
153 // Install the valid custom callback handler
154 nl_socket_modify_cb(ev->sock, NL_CB_VALID, NL_CB_CUSTOM, cb, NULL);
156 // Disable sequence number checking on event sockets
157 nl_socket_disable_seq_check(ev->sock);
159 // Increase rx buffer size to 65K on event sockets
161 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
168 system_rtn_aton(const char *src, unsigned int *dst)
173 if (!strcmp(src, "local"))
175 else if (!strcmp(src, "nat"))
177 else if (!strcmp(src, "broadcast"))
179 else if (!strcmp(src, "anycast"))
181 else if (!strcmp(src, "multicast"))
183 else if (!strcmp(src, "prohibit"))
185 else if (!strcmp(src, "unreachable"))
187 else if (!strcmp(src, "blackhole"))
189 else if (!strcmp(src, "xresolve"))
191 else if (!strcmp(src, "unicast"))
193 else if (!strcmp(src, "throw"))
195 else if (!strcmp(src, "failed_policy"))
196 n = RTN_FAILED_POLICY;
198 n = strtoul(src, &e, 0);
199 if (!e || *e || e == src || n > 255)
208 system_tos_aton(const char *src, unsigned *dst)
212 *dst = strtoul(src, &e, 16);
213 if (e == src || *e || *dst > 255)
219 int system_init(void)
221 static struct event_socket rtnl_event;
222 static struct event_socket hotplug_event;
224 sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0);
225 system_fd_set_cloexec(sock_ioctl);
227 // Prepare socket for routing / address control
228 sock_rtnl = create_socket(NETLINK_ROUTE, 0);
232 if (!create_event_socket(&rtnl_event, NETLINK_ROUTE, cb_rtnl_event))
235 if (!create_raw_event_socket(&hotplug_event, NETLINK_KOBJECT_UEVENT, 1,
236 handle_hotplug_event, 0))
239 // Receive network link events form kernel
240 nl_socket_add_membership(rtnl_event.sock, RTNLGRP_LINK);
245 static void system_set_sysctl(const char *path, const char *val)
249 fd = open(path, O_WRONLY);
253 if (write(fd, val, strlen(val))) {}
257 static void system_set_dev_sysctl(const char *path, const char *device, const char *val)
259 snprintf(dev_buf, sizeof(dev_buf), path, device);
260 system_set_sysctl(dev_buf, val);
263 static void system_set_disable_ipv6(struct device *dev, const char *val)
265 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val);
268 static void system_set_rpfilter(struct device *dev, const char *val)
270 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter", dev->ifname, val);
273 static void system_set_acceptlocal(struct device *dev, const char *val)
275 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local", dev->ifname, val);
278 static void system_set_igmpversion(struct device *dev, const char *val)
280 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version", dev->ifname, val);
283 static void system_set_mldversion(struct device *dev, const char *val)
285 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version", dev->ifname, val);
288 static void system_set_neigh4reachabletime(struct device *dev, const char *val)
290 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms", dev->ifname, val);
293 static void system_set_neigh6reachabletime(struct device *dev, const char *val)
295 system_set_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms", dev->ifname, val);
298 static int system_get_sysctl(const char *path, char *buf, const size_t buf_sz)
300 int fd = -1, ret = -1;
302 fd = open(path, O_RDONLY);
306 ssize_t len = read(fd, buf, buf_sz - 1);
320 system_get_dev_sysctl(const char *path, const char *device, char *buf, const size_t buf_sz)
322 snprintf(dev_buf, sizeof(dev_buf), path, device);
323 return system_get_sysctl(dev_buf, buf, buf_sz);
326 static int system_get_disable_ipv6(struct device *dev, char *buf, const size_t buf_sz)
328 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6",
329 dev->ifname, buf, buf_sz);
332 static int system_get_rpfilter(struct device *dev, char *buf, const size_t buf_sz)
334 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter",
335 dev->ifname, buf, buf_sz);
338 static int system_get_acceptlocal(struct device *dev, char *buf, const size_t buf_sz)
340 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local",
341 dev->ifname, buf, buf_sz);
344 static int system_get_igmpversion(struct device *dev, char *buf, const size_t buf_sz)
346 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version",
347 dev->ifname, buf, buf_sz);
350 static int system_get_mldversion(struct device *dev, char *buf, const size_t buf_sz)
352 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version",
353 dev->ifname, buf, buf_sz);
356 static int system_get_neigh4reachabletime(struct device *dev, char *buf, const size_t buf_sz)
358 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms",
359 dev->ifname, buf, buf_sz);
362 static int system_get_neigh6reachabletime(struct device *dev, char *buf, const size_t buf_sz)
364 return system_get_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms",
365 dev->ifname, buf, buf_sz);
368 // Evaluate netlink messages
369 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
371 struct nlmsghdr *nh = nlmsg_hdr(msg);
372 struct ifinfomsg *ifi = NLMSG_DATA(nh);
373 struct nlattr *nla[__IFLA_MAX];
377 if (nh->nlmsg_type != RTM_NEWLINK)
380 nlmsg_parse(nh, sizeof(*ifi), nla, __IFLA_MAX - 1, NULL);
381 if (!nla[IFLA_IFNAME])
384 struct device *dev = device_get(nla_data(nla[IFLA_IFNAME]), false);
385 if (!dev || dev->type->keep_link_status)
388 if (!system_get_dev_sysctl("/sys/class/net/%s/carrier", dev->ifname, buf, sizeof(buf)))
389 link_state = strtoul(buf, NULL, 0);
391 device_set_link(dev, link_state ? true : false);
398 handle_hotplug_msg(char *data, int size)
400 const char *subsystem = NULL, *interface = NULL;
401 char *cur, *end, *sep;
406 if (!strncmp(data, "add@", 4))
408 else if (!strncmp(data, "remove@", 7))
413 skip = strlen(data) + 1;
416 for (cur = data + skip; cur < end; cur += skip) {
417 skip = strlen(cur) + 1;
419 sep = strchr(cur, '=');
424 if (!strcmp(cur, "INTERFACE"))
426 else if (!strcmp(cur, "SUBSYSTEM")) {
428 if (strcmp(subsystem, "net") != 0)
431 if (subsystem && interface)
437 dev = device_get(interface, false);
441 if (dev->type != &simple_device_type)
444 if (add && system_if_force_external(dev->ifname))
447 device_set_present(dev, add);
451 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
453 struct event_socket *ev = container_of(u, struct event_socket, uloop);
454 struct sockaddr_nl nla;
455 unsigned char *buf = NULL;
458 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
460 handle_hotplug_msg((char *) buf, size);
466 static int system_rtnl_call(struct nl_msg *msg)
470 ret = nl_send_auto_complete(sock_rtnl, msg);
476 return nl_wait_for_ack(sock_rtnl);
479 int system_bridge_delbr(struct device *bridge)
481 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
484 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
488 memset(&ifr, 0, sizeof(ifr));
490 ifr.ifr_ifindex = dev->ifindex;
493 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
494 return ioctl(sock_ioctl, cmd, &ifr);
497 static bool system_is_bridge(const char *name, char *buf, int buflen)
501 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
502 if (stat(buf, &st) < 0)
508 static char *system_get_bridge(const char *name, char *buf, int buflen)
514 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
515 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
519 len = readlink(gl.gl_pathv[0], buf, buflen);
527 path = strrchr(buf, '/');
534 static void system_bridge_set_wireless(const char *bridge, const char *dev)
536 snprintf(dev_buf, sizeof(dev_buf),
537 "/sys/devices/virtual/net/%s/brif/%s/multicast_to_unicast",
539 system_set_sysctl(dev_buf, "1");
542 int system_bridge_addif(struct device *bridge, struct device *dev)
547 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
548 if (!oldbr || strcmp(oldbr, bridge->ifname) != 0)
549 ret = system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
552 system_bridge_set_wireless(bridge->ifname, dev->ifname);
557 int system_bridge_delif(struct device *bridge, struct device *dev)
559 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
562 int system_if_resolve(struct device *dev)
565 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
566 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
567 return ifr.ifr_ifindex;
572 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
576 memset(&ifr, 0, sizeof(ifr));
577 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
578 ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
579 ifr.ifr_flags |= add;
580 ifr.ifr_flags &= ~rem;
581 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
593 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
595 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
597 return ifa->ifa_index == ifindex;
600 static bool check_route(struct nlmsghdr *hdr, int ifindex)
602 struct rtmsg *r = NLMSG_DATA(hdr);
603 struct nlattr *tb[__RTA_MAX];
605 if (r->rtm_protocol == RTPROT_KERNEL &&
606 r->rtm_family == AF_INET6)
609 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
613 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
616 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
621 static int cb_clear_event(struct nl_msg *msg, void *arg)
623 struct clear_data *clr = arg;
624 struct nlmsghdr *hdr = nlmsg_hdr(msg);
625 bool (*cb)(struct nlmsghdr *, int ifindex);
631 if (hdr->nlmsg_type != RTM_NEWADDR)
638 if (hdr->nlmsg_type != RTM_NEWROUTE)
645 if (hdr->nlmsg_type != RTM_NEWRULE)
654 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
657 if (type == RTM_DELRULE)
658 D(SYSTEM, "Remove a rule\n");
660 D(SYSTEM, "Remove %s from device %s\n",
661 type == RTM_DELADDR ? "an address" : "a route",
663 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
664 hdr = nlmsg_hdr(clr->msg);
665 hdr->nlmsg_type = type;
666 hdr->nlmsg_flags = NLM_F_REQUEST;
668 nl_socket_disable_auto_ack(sock_rtnl);
669 nl_send_auto_complete(sock_rtnl, clr->msg);
670 nl_socket_enable_auto_ack(sock_rtnl);
676 cb_finish_event(struct nl_msg *msg, void *arg)
684 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
687 *pending = err->error;
692 system_if_clear_entries(struct device *dev, int type, int af)
694 struct clear_data clr;
695 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
698 .rtm_flags = RTM_F_CLONED,
700 int flags = NLM_F_DUMP;
709 clr.size = sizeof(struct rtgenmsg);
712 clr.size = sizeof(struct rtmsg);
721 clr.msg = nlmsg_alloc_simple(type, flags);
725 nlmsg_append(clr.msg, &rtm, clr.size, 0);
726 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
727 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
728 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
730 nl_send_auto_complete(sock_rtnl, clr.msg);
732 nl_recvmsgs(sock_rtnl, cb);
740 * Clear bridge (membership) state and bring down device
742 void system_if_clear_state(struct device *dev)
744 static char buf[256];
747 device_set_ifindex(dev, system_if_resolve(dev));
748 if (dev->external || !dev->ifindex)
751 system_if_flags(dev->ifname, 0, IFF_UP);
753 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
754 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
755 system_bridge_delbr(dev);
759 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
761 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
762 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
765 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
766 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
767 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
768 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
769 system_set_disable_ipv6(dev, "0");
772 static inline unsigned long
773 sec_to_jiffies(int val)
775 return (unsigned long) val * 100;
778 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
780 unsigned long args[4] = {};
782 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
785 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
786 args[1] = !!cfg->stp;
787 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
789 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
790 args[1] = sec_to_jiffies(cfg->forward_delay);
791 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
793 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
794 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
796 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier",
797 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
799 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
800 args[1] = cfg->priority;
801 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
803 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
804 args[0] = BRCTL_SET_AGEING_TIME;
805 args[1] = sec_to_jiffies(cfg->ageing_time);
806 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
809 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
810 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
811 args[1] = sec_to_jiffies(cfg->hello_time);
812 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
815 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
816 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
817 args[1] = sec_to_jiffies(cfg->max_age);
818 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
824 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
827 struct nlattr *linkinfo, *data;
828 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
830 static const struct {
832 enum macvlan_mode val;
834 { "private", MACVLAN_MODE_PRIVATE },
835 { "vepa", MACVLAN_MODE_VEPA },
836 { "bridge", MACVLAN_MODE_BRIDGE },
837 { "passthru", MACVLAN_MODE_PASSTHRU },
840 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
845 nlmsg_append(msg, &iim, sizeof(iim), 0);
847 if (cfg->flags & MACVLAN_OPT_MACADDR)
848 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
849 nla_put_string(msg, IFLA_IFNAME, macvlan->ifname);
850 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
852 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
853 goto nla_put_failure;
855 nla_put_string(msg, IFLA_INFO_KIND, "macvlan");
857 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
858 goto nla_put_failure;
861 for (i = 0; i < ARRAY_SIZE(modes); i++) {
862 if (strcmp(cfg->mode, modes[i].name) != 0)
865 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
870 nla_nest_end(msg, data);
871 nla_nest_end(msg, linkinfo);
873 rv = system_rtnl_call(msg);
875 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
884 static int system_link_del(const char *ifname)
887 struct ifinfomsg iim = {
888 .ifi_family = AF_UNSPEC,
892 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
897 nlmsg_append(msg, &iim, sizeof(iim), 0);
898 nla_put_string(msg, IFLA_IFNAME, ifname);
899 return system_rtnl_call(msg);
902 int system_macvlan_del(struct device *macvlan)
904 return system_link_del(macvlan->ifname);
907 static int system_vlan(struct device *dev, int id)
909 struct vlan_ioctl_args ifr = {
910 .cmd = SET_VLAN_NAME_TYPE_CMD,
911 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
914 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
917 ifr.cmd = DEL_VLAN_CMD;
920 ifr.cmd = ADD_VLAN_CMD;
923 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
924 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
927 int system_vlan_add(struct device *dev, int id)
929 return system_vlan(dev, id);
932 int system_vlan_del(struct device *dev)
934 return system_vlan(dev, -1);
937 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
940 struct nlattr *linkinfo, *data;
941 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
944 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
949 nlmsg_append(msg, &iim, sizeof(iim), 0);
950 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
951 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
953 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
954 goto nla_put_failure;
956 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
958 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
959 goto nla_put_failure;
961 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
963 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
964 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
966 if(cfg->proto == VLAN_PROTO_8021AD)
967 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);
970 nla_nest_end(msg, data);
971 nla_nest_end(msg, linkinfo);
973 rv = system_rtnl_call(msg);
975 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
984 int system_vlandev_del(struct device *vlandev)
986 return system_link_del(vlandev->ifname);
990 system_if_get_settings(struct device *dev, struct device_settings *s)
995 memset(&ifr, 0, sizeof(ifr));
996 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
998 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
999 s->mtu = ifr.ifr_mtu;
1000 s->flags |= DEV_OPT_MTU;
1003 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
1004 s->txqueuelen = ifr.ifr_qlen;
1005 s->flags |= DEV_OPT_TXQUEUELEN;
1008 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
1009 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
1010 s->flags |= DEV_OPT_MACADDR;
1013 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
1014 s->ipv6 = !strtoul(buf, NULL, 0);
1015 s->flags |= DEV_OPT_IPV6;
1018 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
1019 s->promisc = ifr.ifr_flags & IFF_PROMISC;
1020 s->flags |= DEV_OPT_PROMISC;
1023 if (!system_get_rpfilter(dev, buf, sizeof(buf))) {
1024 s->rpfilter = strtoul(buf, NULL, 0);
1025 s->flags |= DEV_OPT_RPFILTER;
1028 if (!system_get_acceptlocal(dev, buf, sizeof(buf))) {
1029 s->acceptlocal = strtoul(buf, NULL, 0);
1030 s->flags |= DEV_OPT_ACCEPTLOCAL;
1033 if (!system_get_igmpversion(dev, buf, sizeof(buf))) {
1034 s->igmpversion = strtoul(buf, NULL, 0);
1035 s->flags |= DEV_OPT_IGMPVERSION;
1038 if (!system_get_mldversion(dev, buf, sizeof(buf))) {
1039 s->mldversion = strtoul(buf, NULL, 0);
1040 s->flags |= DEV_OPT_MLDVERSION;
1043 if (!system_get_neigh4reachabletime(dev, buf, sizeof(buf))) {
1044 s->neigh4reachabletime = strtoul(buf, NULL, 0);
1045 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1048 if (!system_get_neigh6reachabletime(dev, buf, sizeof(buf))) {
1049 s->neigh6reachabletime = strtoul(buf, NULL, 0);
1050 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1055 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
1062 memset(&ifr, 0, sizeof(ifr));
1063 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1064 if (s->flags & DEV_OPT_MTU & apply_mask) {
1065 ifr.ifr_mtu = s->mtu;
1066 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
1067 s->flags &= ~DEV_OPT_MTU;
1069 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
1070 ifr.ifr_qlen = s->txqueuelen;
1071 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
1072 s->flags &= ~DEV_OPT_TXQUEUELEN;
1074 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
1075 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
1076 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
1077 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
1078 s->flags &= ~DEV_OPT_MACADDR;
1080 if (s->flags & DEV_OPT_IPV6 & apply_mask)
1081 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
1082 if (s->flags & DEV_OPT_PROMISC & apply_mask) {
1083 if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
1084 !s->promisc ? IFF_PROMISC : 0) < 0)
1085 s->flags &= ~DEV_OPT_PROMISC;
1087 if (s->flags & DEV_OPT_RPFILTER & apply_mask) {
1090 snprintf(buf, sizeof(buf), "%d", s->rpfilter);
1091 system_set_rpfilter(dev, buf);
1093 if (s->flags & DEV_OPT_ACCEPTLOCAL & apply_mask)
1094 system_set_acceptlocal(dev, s->acceptlocal ? "1" : "0");
1095 if (s->flags & DEV_OPT_IGMPVERSION & apply_mask) {
1098 snprintf(buf, sizeof(buf), "%d", s->igmpversion);
1099 system_set_igmpversion(dev, buf);
1101 if (s->flags & DEV_OPT_MLDVERSION & apply_mask) {
1104 snprintf(buf, sizeof(buf), "%d", s->mldversion);
1105 system_set_mldversion(dev, buf);
1107 if (s->flags & DEV_OPT_NEIGHREACHABLETIME & apply_mask) {
1110 snprintf(buf, sizeof(buf), "%d", s->neigh4reachabletime);
1111 system_set_neigh4reachabletime(dev, buf);
1112 snprintf(buf, sizeof(buf), "%d", s->neigh6reachabletime);
1113 system_set_neigh6reachabletime(dev, buf);
1117 int system_if_up(struct device *dev)
1119 system_if_get_settings(dev, &dev->orig_settings);
1120 /* Only keep orig settings based on what needs to be set */
1121 dev->orig_settings.flags &= dev->settings.flags;
1122 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
1123 return system_if_flags(dev->ifname, IFF_UP, 0);
1126 int system_if_down(struct device *dev)
1128 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
1129 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
1133 struct if_check_data {
1139 #ifndef IFF_LOWER_UP
1140 #define IFF_LOWER_UP 0x10000
1143 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1145 struct nlmsghdr *nh = nlmsg_hdr(msg);
1146 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1147 struct if_check_data *chk = (struct if_check_data *)arg;
1149 if (nh->nlmsg_type != RTM_NEWLINK)
1152 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1153 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1158 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1160 struct if_check_data *chk = (struct if_check_data *)arg;
1165 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1167 struct if_check_data *chk = (struct if_check_data *)arg;
1169 device_set_present(chk->dev, false);
1170 device_set_link(chk->dev, false);
1171 chk->pending = err->error;
1176 int system_if_check(struct device *dev)
1178 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1180 struct ifinfomsg ifi = {
1181 .ifi_family = AF_UNSPEC,
1184 struct if_check_data chk = {
1190 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1191 if (!msg || nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1192 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1195 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1196 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1197 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1199 nl_send_auto_complete(sock_rtnl, msg);
1200 while (chk.pending > 0)
1201 nl_recvmsgs(sock_rtnl, cb);
1212 system_if_get_parent(struct device *dev)
1214 char buf[64], *devname;
1215 int ifindex, iflink, len;
1218 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1219 f = fopen(buf, "r");
1223 len = fread(buf, 1, sizeof(buf) - 1, f);
1230 iflink = strtoul(buf, NULL, 0);
1231 ifindex = system_if_resolve(dev);
1232 if (!iflink || iflink == ifindex)
1235 devname = if_indextoname(iflink, buf);
1239 return device_get(devname, true);
1243 read_string_file(int dir_fd, const char *file, char *buf, int len)
1249 fd = openat(dir_fd, file, O_RDONLY);
1254 len = read(fd, buf, len - 1);
1258 } else if (len > 0) {
1261 c = strchr(buf, '\n');
1274 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1279 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1281 *val = strtoull(buf, NULL, 0);
1286 /* Assume advertised flags == supported flags */
1287 static const struct {
1290 } ethtool_link_modes[] = {
1291 { ADVERTISED_10baseT_Half, "10H" },
1292 { ADVERTISED_10baseT_Full, "10F" },
1293 { ADVERTISED_100baseT_Half, "100H" },
1294 { ADVERTISED_100baseT_Full, "100F" },
1295 { ADVERTISED_1000baseT_Half, "1000H" },
1296 { ADVERTISED_1000baseT_Full, "1000F" },
1299 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1302 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1303 if (mask & ethtool_link_modes[i].mask)
1304 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1309 system_if_force_external(const char *ifname)
1314 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1315 return stat(buf, &s) == 0;
1319 system_if_dump_info(struct device *dev, struct blob_buf *b)
1321 struct ethtool_cmd ecmd;
1327 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
1328 dir_fd = open(buf, O_DIRECTORY);
1330 memset(&ecmd, 0, sizeof(ecmd));
1331 memset(&ifr, 0, sizeof(ifr));
1332 strcpy(ifr.ifr_name, dev->ifname);
1333 ifr.ifr_data = (caddr_t) &ecmd;
1334 ecmd.cmd = ETHTOOL_GSET;
1336 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1337 c = blobmsg_open_array(b, "link-advertising");
1338 system_add_link_modes(b, ecmd.advertising);
1339 blobmsg_close_array(b, c);
1341 c = blobmsg_open_array(b, "link-supported");
1342 system_add_link_modes(b, ecmd.supported);
1343 blobmsg_close_array(b, c);
1345 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1346 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1347 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1348 blobmsg_add_string_buffer(b);
1356 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1358 const char *const counters[] = {
1359 "collisions", "rx_frame_errors", "tx_compressed",
1360 "multicast", "rx_length_errors", "tx_dropped",
1361 "rx_bytes", "rx_missed_errors", "tx_errors",
1362 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1363 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1364 "rx_dropped", "tx_aborted_errors", "tx_packets",
1365 "rx_errors", "tx_bytes", "tx_window_errors",
1366 "rx_fifo_errors", "tx_carrier_errors",
1373 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1374 stats_dir = open(buf, O_DIRECTORY);
1378 for (i = 0; i < ARRAY_SIZE(counters); i++)
1379 if (read_uint64_file(stats_dir, counters[i], &val))
1380 blobmsg_add_u64(b, counters[i], val);
1386 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1388 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1389 int alen = v4 ? 4 : 16;
1390 unsigned int flags = 0;
1391 struct ifaddrmsg ifa = {
1392 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1393 .ifa_prefixlen = addr->mask,
1394 .ifa_index = dev->ifindex,
1398 if (cmd == RTM_NEWADDR)
1399 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1401 msg = nlmsg_alloc_simple(cmd, flags);
1405 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1406 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1408 if (addr->broadcast)
1409 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1410 if (addr->point_to_point)
1411 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1413 time_t now = system_get_rtime();
1414 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1416 if (addr->preferred_until) {
1417 int64_t preferred = addr->preferred_until - now;
1420 else if (preferred > UINT32_MAX)
1421 preferred = UINT32_MAX;
1423 cinfo.ifa_prefered = preferred;
1426 if (addr->valid_until) {
1427 int64_t valid = addr->valid_until - now;
1430 else if (valid > UINT32_MAX)
1433 cinfo.ifa_valid = valid;
1436 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1439 return system_rtnl_call(msg);
1442 int system_add_address(struct device *dev, struct device_addr *addr)
1444 return system_addr(dev, addr, RTM_NEWADDR);
1447 int system_del_address(struct device *dev, struct device_addr *addr)
1449 return system_addr(dev, addr, RTM_DELADDR);
1452 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1454 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1456 unsigned int flags = 0;
1459 have_gw = !!route->nexthop.in.s_addr;
1461 have_gw = route->nexthop.in6.s6_addr32[0] ||
1462 route->nexthop.in6.s6_addr32[1] ||
1463 route->nexthop.in6.s6_addr32[2] ||
1464 route->nexthop.in6.s6_addr32[3];
1466 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1467 ? route->table : RT_TABLE_MAIN;
1469 struct rtmsg rtm = {
1470 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1471 .rtm_dst_len = route->mask,
1472 .rtm_src_len = route->sourcemask,
1473 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1474 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
1475 .rtm_scope = RT_SCOPE_NOWHERE,
1476 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1477 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1481 if (cmd == RTM_NEWROUTE) {
1482 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1484 if (!dev) { // Add null-route
1485 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1486 rtm.rtm_type = RTN_UNREACHABLE;
1489 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1492 if (route->flags & DEVROUTE_TYPE) {
1493 rtm.rtm_type = route->type;
1494 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
1495 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
1496 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
1497 rtm.rtm_table = RT_TABLE_LOCAL;
1500 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT) {
1501 rtm.rtm_scope = RT_SCOPE_HOST;
1502 } else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
1503 rtm.rtm_type == RTN_ANYCAST) {
1504 rtm.rtm_scope = RT_SCOPE_LINK;
1505 } else if (rtm.rtm_type == RTN_BLACKHOLE || rtm.rtm_type == RTN_UNREACHABLE ||
1506 rtm.rtm_type == RTN_PROHIBIT || rtm.rtm_type == RTN_FAILED_POLICY) {
1507 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1512 msg = nlmsg_alloc_simple(cmd, flags);
1516 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1519 nla_put(msg, RTA_DST, alen, &route->addr);
1521 if (route->sourcemask) {
1522 if (rtm.rtm_family == AF_INET)
1523 nla_put(msg, RTA_PREFSRC, alen, &route->source);
1525 nla_put(msg, RTA_SRC, alen, &route->source);
1528 if (route->metric > 0)
1529 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1532 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1535 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1538 nla_put_u32(msg, RTA_TABLE, table);
1540 if (route->flags & DEVROUTE_MTU) {
1541 struct nlattr *metrics;
1543 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1544 goto nla_put_failure;
1546 nla_put_u32(msg, RTAX_MTU, route->mtu);
1548 nla_nest_end(msg, metrics);
1551 return system_rtnl_call(msg);
1558 int system_add_route(struct device *dev, struct device_route *route)
1560 return system_rt(dev, route, RTM_NEWROUTE);
1563 int system_del_route(struct device *dev, struct device_route *route)
1565 return system_rt(dev, route, RTM_DELROUTE);
1568 int system_flush_routes(void)
1570 const char *names[] = {
1571 "/proc/sys/net/ipv4/route/flush",
1572 "/proc/sys/net/ipv6/route/flush"
1576 for (i = 0; i < ARRAY_SIZE(names); i++) {
1577 fd = open(names[i], O_WRONLY);
1581 if (write(fd, "-1", 2)) {}
1587 bool system_resolve_rt_type(const char *type, unsigned int *id)
1589 return system_rtn_aton(type, id);
1592 bool system_resolve_rt_table(const char *name, unsigned int *id)
1596 unsigned int n, table = RT_TABLE_UNSPEC;
1598 /* first try to parse table as number */
1599 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1602 /* handle well known aliases */
1603 else if (!strcmp(name, "default"))
1604 table = RT_TABLE_DEFAULT;
1605 else if (!strcmp(name, "main"))
1606 table = RT_TABLE_MAIN;
1607 else if (!strcmp(name, "local"))
1608 table = RT_TABLE_LOCAL;
1610 /* try to look up name in /etc/iproute2/rt_tables */
1611 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1613 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1615 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1618 n = strtoul(e, NULL, 10);
1619 e = strtok(NULL, " \t\n");
1621 if (e && !strcmp(e, name))
1631 if (table == RT_TABLE_UNSPEC)
1638 bool system_is_default_rt_table(unsigned int id)
1640 return (id == RT_TABLE_MAIN);
1643 bool system_resolve_rpfilter(const char *filter, unsigned int *id)
1648 if (!strcmp(filter, "strict"))
1650 else if (!strcmp(filter, "loose"))
1653 n = strtoul(filter, &e, 0);
1654 if (*e || e == filter || n > 2)
1662 static int system_iprule(struct iprule *rule, int cmd)
1664 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1667 struct rtmsg rtm = {
1668 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1669 .rtm_protocol = RTPROT_STATIC,
1670 .rtm_scope = RT_SCOPE_UNIVERSE,
1671 .rtm_table = RT_TABLE_UNSPEC,
1672 .rtm_type = RTN_UNSPEC,
1676 if (cmd == RTM_NEWRULE) {
1677 rtm.rtm_type = RTN_UNICAST;
1678 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1682 rtm.rtm_flags |= FIB_RULE_INVERT;
1684 if (rule->flags & IPRULE_SRC)
1685 rtm.rtm_src_len = rule->src_mask;
1687 if (rule->flags & IPRULE_DEST)
1688 rtm.rtm_dst_len = rule->dest_mask;
1690 if (rule->flags & IPRULE_TOS)
1691 rtm.rtm_tos = rule->tos;
1693 if (rule->flags & IPRULE_LOOKUP) {
1694 if (rule->lookup < 256)
1695 rtm.rtm_table = rule->lookup;
1698 if (rule->flags & IPRULE_ACTION)
1699 rtm.rtm_type = rule->action;
1700 else if (rule->flags & IPRULE_GOTO)
1701 rtm.rtm_type = FR_ACT_GOTO;
1702 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1703 rtm.rtm_type = FR_ACT_NOP;
1705 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1710 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1712 if (rule->flags & IPRULE_IN)
1713 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1715 if (rule->flags & IPRULE_OUT)
1716 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1718 if (rule->flags & IPRULE_SRC)
1719 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1721 if (rule->flags & IPRULE_DEST)
1722 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1724 if (rule->flags & IPRULE_PRIORITY)
1725 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1726 else if (cmd == RTM_NEWRULE)
1727 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1729 if (rule->flags & IPRULE_FWMARK)
1730 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1732 if (rule->flags & IPRULE_FWMASK)
1733 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1735 if (rule->flags & IPRULE_LOOKUP) {
1736 if (rule->lookup >= 256)
1737 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1740 if (rule->flags & IPRULE_GOTO)
1741 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1743 return system_rtnl_call(msg);
1746 int system_add_iprule(struct iprule *rule)
1748 return system_iprule(rule, RTM_NEWRULE);
1751 int system_del_iprule(struct iprule *rule)
1753 return system_iprule(rule, RTM_DELRULE);
1756 int system_flush_iprules(void)
1761 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1762 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1764 memset(&rule, 0, sizeof(rule));
1767 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1770 rule.lookup = RT_TABLE_LOCAL;
1771 rv |= system_iprule(&rule, RTM_NEWRULE);
1773 rule.priority = 32766;
1774 rule.lookup = RT_TABLE_MAIN;
1775 rv |= system_iprule(&rule, RTM_NEWRULE);
1777 rule.priority = 32767;
1778 rule.lookup = RT_TABLE_DEFAULT;
1779 rv |= system_iprule(&rule, RTM_NEWRULE);
1782 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1785 rule.lookup = RT_TABLE_LOCAL;
1786 rv |= system_iprule(&rule, RTM_NEWRULE);
1788 rule.priority = 32766;
1789 rule.lookup = RT_TABLE_MAIN;
1790 rv |= system_iprule(&rule, RTM_NEWRULE);
1795 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1797 return system_rtn_aton(action, id);
1800 time_t system_get_rtime(void)
1805 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1808 if (gettimeofday(&tv, NULL) == 0)
1815 #define IP_DF 0x4000
1818 static int tunnel_ioctl(const char *name, int cmd, void *p)
1822 memset(&ifr, 0, sizeof(ifr));
1823 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1824 ifr.ifr_ifru.ifru_data = p;
1825 return ioctl(sock_ioctl, cmd, &ifr);
1828 #ifdef IFLA_IPTUN_MAX
1829 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
1830 static int system_add_gre_tunnel(const char *name, const char *kind,
1831 const unsigned int link, struct blob_attr **tb, bool v6)
1834 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
1835 struct blob_attr *cur;
1836 uint32_t ikey = 0, okey = 0, flags = 0, flowinfo = 0;
1837 uint16_t iflags = 0, oflags = 0;
1839 int ret = 0, ttl = 64;
1841 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
1845 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
1846 nla_put_string(nlm, IFLA_IFNAME, name);
1848 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
1854 nla_put_string(nlm, IFLA_INFO_KIND, kind);
1855 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
1862 nla_put_u32(nlm, IFLA_GRE_LINK, link);
1864 if ((cur = tb[TUNNEL_ATTR_TTL]))
1865 ttl = blobmsg_get_u32(cur);
1867 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
1869 if ((cur = tb[TUNNEL_ATTR_TOS])) {
1870 char *str = blobmsg_get_string(cur);
1871 if (strcmp(str, "inherit")) {
1874 if (!system_tos_aton(str, &uval)) {
1880 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
1885 flags |= IP6_TNL_F_USE_ORIG_TCLASS;
1891 if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) {
1892 uint8_t icsum, ocsum, iseqno, oseqno;
1893 if (sscanf(blobmsg_get_string(cur), "%u,%u,%hhu,%hhu,%hhu,%hhu",
1894 &ikey, &okey, &icsum, &ocsum, &iseqno, &oseqno) < 6) {
1919 struct in6_addr in6buf;
1920 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1921 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1925 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
1928 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
1929 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1933 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
1935 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, 4);
1938 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
1941 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags);
1943 struct in_addr inbuf;
1946 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1947 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
1951 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
1954 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
1955 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
1959 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
1961 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
1963 okey = inbuf.s_addr;
1968 ikey = inbuf.s_addr;
1974 if ((cur = tb[TUNNEL_ATTR_DF]))
1975 set_df = blobmsg_get_bool(cur);
1977 /* ttl !=0 and nopmtudisc are incompatible */
1978 if (ttl && !set_df) {
1983 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
1985 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
1989 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
1992 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
1995 nla_put_u32(nlm, IFLA_GRE_OKEY, okey);
1998 nla_put_u32(nlm, IFLA_GRE_IKEY, ikey);
2000 nla_nest_end(nlm, infodata);
2001 nla_nest_end(nlm, linkinfo);
2003 return system_rtnl_call(nlm);
2011 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
2013 struct blob_attr *cur;
2015 struct ip_tunnel_parm p = {
2024 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
2025 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
2028 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
2029 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
2032 if ((cur = tb[TUNNEL_ATTR_DF]))
2033 set_df = blobmsg_get_bool(cur);
2035 if ((cur = tb[TUNNEL_ATTR_TTL]))
2036 p.iph.ttl = blobmsg_get_u32(cur);
2038 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2039 char *str = blobmsg_get_string(cur);
2040 if (strcmp(str, "inherit")) {
2043 if (!system_tos_aton(str, &uval))
2051 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
2052 /* ttl !=0 and nopmtudisc are incompatible */
2053 if (p.iph.ttl && p.iph.frag_off == 0)
2056 strncpy(p.name, name, sizeof(p.name));
2058 switch (p.iph.protocol) {
2060 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
2062 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
2069 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
2071 struct blob_attr *cur;
2074 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2076 str = blobmsg_data(cur);
2078 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
2079 !strcmp(str, "greip6") || !strcmp(str, "gretapip6"))
2080 return system_link_del(name);
2082 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
2085 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
2087 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2089 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2090 blob_data(attr), blob_len(attr));
2092 return __system_del_ip_tunnel(name, tb);
2095 int system_update_ipv6_mtu(struct device *dev, int mtu)
2099 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
2102 int fd = open(buf, O_RDWR);
2103 ssize_t len = read(fd, buf, sizeof(buf) - 1);
2110 if (!mtu || ret <= mtu)
2113 lseek(fd, 0, SEEK_SET);
2114 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) <= 0)
2122 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
2124 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2125 struct blob_attr *cur;
2128 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2129 blob_data(attr), blob_len(attr));
2131 __system_del_ip_tunnel(name, tb);
2133 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2135 str = blobmsg_data(cur);
2137 unsigned int ttl = 0;
2138 if ((cur = tb[TUNNEL_ATTR_TTL])) {
2139 ttl = blobmsg_get_u32(cur);
2144 unsigned int link = 0;
2145 if ((cur = tb[TUNNEL_ATTR_LINK])) {
2146 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
2150 if (iface->l3_dev.dev)
2151 link = iface->l3_dev.dev->ifindex;
2154 if (!strcmp(str, "sit")) {
2155 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
2159 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
2161 struct ip_tunnel_6rd p6;
2163 memset(&p6, 0, sizeof(p6));
2165 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
2166 &p6.prefix, &mask) || mask > 128)
2168 p6.prefixlen = mask;
2170 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
2171 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
2172 &p6.relay_prefix, &mask) || mask > 32)
2174 p6.relay_prefixlen = mask;
2177 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
2178 __system_del_ip_tunnel(name, tb);
2183 #ifdef IFLA_IPTUN_MAX
2184 } else if (!strcmp(str, "ipip6")) {
2185 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2186 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2187 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2193 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2194 nla_put_string(nlm, IFLA_IFNAME, name);
2197 nla_put_u32(nlm, IFLA_LINK, link);
2199 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2204 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2205 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2212 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2214 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2215 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2216 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
2218 struct in6_addr in6buf;
2219 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2220 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2224 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2227 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2228 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2232 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2235 #ifdef IFLA_IPTUN_FMR_MAX
2236 if ((cur = tb[TUNNEL_ATTR_FMRS])) {
2237 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2239 struct blob_attr *fmr;
2240 unsigned rem, fmrcnt = 0;
2241 blobmsg_for_each_attr(fmr, cur, rem) {
2242 if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
2245 unsigned ip4len, ip6len, ealen, offset = 6;
2249 if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
2250 ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) {
2255 struct in6_addr ip6prefix;
2256 struct in_addr ip4prefix;
2257 if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
2258 inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) {
2263 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2265 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2266 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2267 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2268 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2269 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2270 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2272 nla_nest_end(nlm, rule);
2275 nla_nest_end(nlm, fmrs);
2279 nla_nest_end(nlm, infodata);
2280 nla_nest_end(nlm, linkinfo);
2282 return system_rtnl_call(nlm);
2286 } else if (!strcmp(str, "greip")) {
2287 return system_add_gre_tunnel(name, "gre", link, tb, false);
2288 } else if (!strcmp(str, "gretapip")) {
2289 return system_add_gre_tunnel(name, "gretap", link, tb, false);
2290 } else if (!strcmp(str, "greip6")) {
2291 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
2292 } else if (!strcmp(str, "gretapip6")) {
2293 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
2295 } else if (!strcmp(str, "ipip")) {
2296 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);