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 int system_get_sysctl(const char *path, char *buf, const size_t buf_sz)
270 int fd = -1, ret = -1;
272 fd = open(path, O_RDONLY);
276 ssize_t len = read(fd, buf, buf_sz - 1);
290 system_get_dev_sysctl(const char *path, const char *device, char *buf, const size_t buf_sz)
292 snprintf(dev_buf, sizeof(dev_buf), path, device);
293 return system_get_sysctl(dev_buf, buf, buf_sz);
296 static int system_get_disable_ipv6(struct device *dev, char *buf, const size_t buf_sz)
298 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6",
299 dev->ifname, buf, buf_sz);
302 // Evaluate netlink messages
303 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
305 struct nlmsghdr *nh = nlmsg_hdr(msg);
306 struct ifinfomsg *ifi = NLMSG_DATA(nh);
307 struct nlattr *nla[__IFLA_MAX];
311 if (nh->nlmsg_type != RTM_NEWLINK)
314 nlmsg_parse(nh, sizeof(*ifi), nla, __IFLA_MAX - 1, NULL);
315 if (!nla[IFLA_IFNAME])
318 struct device *dev = device_get(nla_data(nla[IFLA_IFNAME]), false);
322 device_set_ifindex(dev, ifi->ifi_index);
323 if (dev->type->keep_link_status)
326 if (!system_get_dev_sysctl("/sys/class/net/%s/carrier", dev->ifname, buf, sizeof(buf)))
327 link_state = strtoul(buf, NULL, 0);
329 device_set_link(dev, link_state ? true : false);
336 handle_hotplug_msg(char *data, int size)
338 const char *subsystem = NULL, *interface = NULL;
339 char *cur, *end, *sep;
344 if (!strncmp(data, "add@", 4))
346 else if (!strncmp(data, "remove@", 7))
351 skip = strlen(data) + 1;
354 for (cur = data + skip; cur < end; cur += skip) {
355 skip = strlen(cur) + 1;
357 sep = strchr(cur, '=');
362 if (!strcmp(cur, "INTERFACE"))
364 else if (!strcmp(cur, "SUBSYSTEM")) {
366 if (strcmp(subsystem, "net") != 0)
369 if (subsystem && interface)
375 dev = device_get(interface, false);
379 if (dev->type != &simple_device_type)
382 if (add && system_if_force_external(dev->ifname))
385 device_set_present(dev, add);
389 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
391 struct event_socket *ev = container_of(u, struct event_socket, uloop);
392 struct sockaddr_nl nla;
393 unsigned char *buf = NULL;
396 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
398 handle_hotplug_msg((char *) buf, size);
404 static int system_rtnl_call(struct nl_msg *msg)
408 ret = nl_send_auto_complete(sock_rtnl, msg);
414 return nl_wait_for_ack(sock_rtnl);
417 int system_bridge_delbr(struct device *bridge)
419 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
422 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
426 memset(&ifr, 0, sizeof(ifr));
428 ifr.ifr_ifindex = dev->ifindex;
431 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
432 return ioctl(sock_ioctl, cmd, &ifr);
435 static bool system_is_bridge(const char *name, char *buf, int buflen)
439 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
440 if (stat(buf, &st) < 0)
446 static char *system_get_bridge(const char *name, char *buf, int buflen)
452 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
453 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
457 len = readlink(gl.gl_pathv[0], buf, buflen);
465 path = strrchr(buf, '/');
472 static void system_bridge_set_wireless(const char *bridge, const char *dev)
474 snprintf(dev_buf, sizeof(dev_buf),
475 "/sys/devices/virtual/net/%s/brif/%s/multicast_to_unicast",
477 system_set_sysctl(dev_buf, "1");
480 int system_bridge_addif(struct device *bridge, struct device *dev)
485 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
486 if (!oldbr || strcmp(oldbr, bridge->ifname) != 0)
487 ret = system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
490 system_bridge_set_wireless(bridge->ifname, dev->ifname);
495 int system_bridge_delif(struct device *bridge, struct device *dev)
497 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
500 static int system_if_resolve(struct device *dev)
503 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
504 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
505 return ifr.ifr_ifindex;
510 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
514 memset(&ifr, 0, sizeof(ifr));
515 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
516 ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
517 ifr.ifr_flags |= add;
518 ifr.ifr_flags &= ~rem;
519 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
531 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
533 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
535 return ifa->ifa_index == ifindex;
538 static bool check_route(struct nlmsghdr *hdr, int ifindex)
540 struct rtmsg *r = NLMSG_DATA(hdr);
541 struct nlattr *tb[__RTA_MAX];
543 if (r->rtm_protocol == RTPROT_KERNEL &&
544 r->rtm_family == AF_INET6)
547 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
551 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
554 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
559 static int cb_clear_event(struct nl_msg *msg, void *arg)
561 struct clear_data *clr = arg;
562 struct nlmsghdr *hdr = nlmsg_hdr(msg);
563 bool (*cb)(struct nlmsghdr *, int ifindex);
569 if (hdr->nlmsg_type != RTM_NEWADDR)
576 if (hdr->nlmsg_type != RTM_NEWROUTE)
583 if (hdr->nlmsg_type != RTM_NEWRULE)
592 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
595 if (type == RTM_DELRULE)
596 D(SYSTEM, "Remove a rule\n");
598 D(SYSTEM, "Remove %s from device %s\n",
599 type == RTM_DELADDR ? "an address" : "a route",
601 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
602 hdr = nlmsg_hdr(clr->msg);
603 hdr->nlmsg_type = type;
604 hdr->nlmsg_flags = NLM_F_REQUEST;
606 nl_socket_disable_auto_ack(sock_rtnl);
607 nl_send_auto_complete(sock_rtnl, clr->msg);
608 nl_socket_enable_auto_ack(sock_rtnl);
614 cb_finish_event(struct nl_msg *msg, void *arg)
622 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
625 *pending = err->error;
630 system_if_clear_entries(struct device *dev, int type, int af)
632 struct clear_data clr;
633 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
636 .rtm_flags = RTM_F_CLONED,
638 int flags = NLM_F_DUMP;
647 clr.size = sizeof(struct rtgenmsg);
650 clr.size = sizeof(struct rtmsg);
659 clr.msg = nlmsg_alloc_simple(type, flags);
663 nlmsg_append(clr.msg, &rtm, clr.size, 0);
664 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
665 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
666 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
668 nl_send_auto_complete(sock_rtnl, clr.msg);
670 nl_recvmsgs(sock_rtnl, cb);
678 * Clear bridge (membership) state and bring down device
680 void system_if_clear_state(struct device *dev)
682 static char buf[256];
685 device_set_ifindex(dev, system_if_resolve(dev));
686 if (dev->external || !dev->ifindex)
689 system_if_flags(dev->ifname, 0, IFF_UP);
691 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
692 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
693 system_bridge_delbr(dev);
697 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
699 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
700 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
703 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
704 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
705 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
706 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
707 system_set_disable_ipv6(dev, "0");
710 static inline unsigned long
711 sec_to_jiffies(int val)
713 return (unsigned long) val * 100;
716 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
718 unsigned long args[4] = {};
720 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
723 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
724 args[1] = !!cfg->stp;
725 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
727 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
728 args[1] = sec_to_jiffies(cfg->forward_delay);
729 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
731 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
732 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
734 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier",
735 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
737 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
738 args[1] = cfg->priority;
739 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
741 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
742 args[0] = BRCTL_SET_AGEING_TIME;
743 args[1] = sec_to_jiffies(cfg->ageing_time);
744 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
747 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
748 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
749 args[1] = sec_to_jiffies(cfg->hello_time);
750 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
753 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
754 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
755 args[1] = sec_to_jiffies(cfg->max_age);
756 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
762 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
765 struct nlattr *linkinfo, *data;
766 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
767 int ifindex = system_if_resolve(dev);
769 static const struct {
771 enum macvlan_mode val;
773 { "private", MACVLAN_MODE_PRIVATE },
774 { "vepa", MACVLAN_MODE_VEPA },
775 { "bridge", MACVLAN_MODE_BRIDGE },
776 { "passthru", MACVLAN_MODE_PASSTHRU },
782 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
787 nlmsg_append(msg, &iim, sizeof(iim), 0);
789 if (cfg->flags & MACVLAN_OPT_MACADDR)
790 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
791 nla_put_string(msg, IFLA_IFNAME, macvlan->ifname);
792 nla_put_u32(msg, IFLA_LINK, ifindex);
794 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
795 goto nla_put_failure;
797 nla_put_string(msg, IFLA_INFO_KIND, "macvlan");
799 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
800 goto nla_put_failure;
803 for (i = 0; i < ARRAY_SIZE(modes); i++) {
804 if (strcmp(cfg->mode, modes[i].name) != 0)
807 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
812 nla_nest_end(msg, data);
813 nla_nest_end(msg, linkinfo);
815 rv = system_rtnl_call(msg);
817 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
826 static int system_link_del(const char *ifname)
829 struct ifinfomsg iim = {
830 .ifi_family = AF_UNSPEC,
834 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
839 nlmsg_append(msg, &iim, sizeof(iim), 0);
840 nla_put_string(msg, IFLA_IFNAME, ifname);
841 return system_rtnl_call(msg);
844 int system_macvlan_del(struct device *macvlan)
846 return system_link_del(macvlan->ifname);
849 static int system_vlan(struct device *dev, int id)
851 struct vlan_ioctl_args ifr = {
852 .cmd = SET_VLAN_NAME_TYPE_CMD,
853 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
856 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
859 ifr.cmd = DEL_VLAN_CMD;
862 ifr.cmd = ADD_VLAN_CMD;
865 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
866 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
869 int system_vlan_add(struct device *dev, int id)
871 return system_vlan(dev, id);
874 int system_vlan_del(struct device *dev)
876 return system_vlan(dev, -1);
879 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
882 struct nlattr *linkinfo, *data;
883 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
884 int ifindex = system_if_resolve(dev);
890 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
895 nlmsg_append(msg, &iim, sizeof(iim), 0);
896 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
897 nla_put_u32(msg, IFLA_LINK, ifindex);
899 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
900 goto nla_put_failure;
902 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
904 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
905 goto nla_put_failure;
907 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
909 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
910 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
912 if(cfg->proto == VLAN_PROTO_8021AD)
913 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);
916 nla_nest_end(msg, data);
917 nla_nest_end(msg, linkinfo);
919 rv = system_rtnl_call(msg);
921 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
930 int system_vlandev_del(struct device *vlandev)
932 return system_link_del(vlandev->ifname);
936 system_if_get_settings(struct device *dev, struct device_settings *s)
941 memset(&ifr, 0, sizeof(ifr));
942 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
944 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
945 s->mtu = ifr.ifr_mtu;
946 s->flags |= DEV_OPT_MTU;
949 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
950 s->txqueuelen = ifr.ifr_qlen;
951 s->flags |= DEV_OPT_TXQUEUELEN;
954 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
955 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
956 s->flags |= DEV_OPT_MACADDR;
959 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
960 s->ipv6 = !strtoul(buf, NULL, 0);
961 s->flags |= DEV_OPT_IPV6;
964 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
965 s->promisc = ifr.ifr_flags & IFF_PROMISC;
966 s->flags |= DEV_OPT_PROMISC;
971 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
978 memset(&ifr, 0, sizeof(ifr));
979 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
980 if (s->flags & DEV_OPT_MTU & apply_mask) {
981 ifr.ifr_mtu = s->mtu;
982 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
983 s->flags &= ~DEV_OPT_MTU;
985 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
986 ifr.ifr_qlen = s->txqueuelen;
987 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
988 s->flags &= ~DEV_OPT_TXQUEUELEN;
990 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
991 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
992 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
993 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
994 s->flags &= ~DEV_OPT_MACADDR;
996 if (s->flags & DEV_OPT_IPV6 & apply_mask)
997 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
998 if (s->flags & DEV_OPT_PROMISC & apply_mask) {
999 if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
1000 !s->promisc ? IFF_PROMISC : 0) < 0)
1001 s->flags &= ~DEV_OPT_PROMISC;
1005 int system_if_up(struct device *dev)
1007 system_if_get_settings(dev, &dev->orig_settings);
1008 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
1009 device_set_ifindex(dev, system_if_resolve(dev));
1010 return system_if_flags(dev->ifname, IFF_UP, 0);
1013 int system_if_down(struct device *dev)
1015 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
1016 dev->orig_settings.flags &= dev->settings.flags;
1017 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
1021 struct if_check_data {
1027 #ifndef IFF_LOWER_UP
1028 #define IFF_LOWER_UP 0x10000
1031 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1033 struct nlmsghdr *nh = nlmsg_hdr(msg);
1034 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1035 struct if_check_data *chk = (struct if_check_data *)arg;
1037 if (nh->nlmsg_type != RTM_NEWLINK)
1040 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1041 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1046 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1048 struct if_check_data *chk = (struct if_check_data *)arg;
1053 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1055 struct if_check_data *chk = (struct if_check_data *)arg;
1057 device_set_present(chk->dev, false);
1058 device_set_link(chk->dev, false);
1059 chk->pending = err->error;
1064 int system_if_check(struct device *dev)
1066 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1068 struct ifinfomsg ifi = {
1069 .ifi_family = AF_UNSPEC,
1072 struct if_check_data chk = {
1078 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1079 if (!msg || nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1080 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1083 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1084 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1085 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1087 nl_send_auto_complete(sock_rtnl, msg);
1088 while (chk.pending > 0)
1089 nl_recvmsgs(sock_rtnl, cb);
1100 system_if_get_parent(struct device *dev)
1102 char buf[64], *devname;
1103 int ifindex, iflink, len;
1106 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1107 f = fopen(buf, "r");
1111 len = fread(buf, 1, sizeof(buf) - 1, f);
1118 iflink = strtoul(buf, NULL, 0);
1119 ifindex = system_if_resolve(dev);
1120 if (!iflink || iflink == ifindex)
1123 devname = if_indextoname(iflink, buf);
1127 return device_get(devname, true);
1131 read_string_file(int dir_fd, const char *file, char *buf, int len)
1137 fd = openat(dir_fd, file, O_RDONLY);
1142 len = read(fd, buf, len - 1);
1146 } else if (len > 0) {
1149 c = strchr(buf, '\n');
1162 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1167 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1169 *val = strtoull(buf, NULL, 0);
1174 /* Assume advertised flags == supported flags */
1175 static const struct {
1178 } ethtool_link_modes[] = {
1179 { ADVERTISED_10baseT_Half, "10H" },
1180 { ADVERTISED_10baseT_Full, "10F" },
1181 { ADVERTISED_100baseT_Half, "100H" },
1182 { ADVERTISED_100baseT_Full, "100F" },
1183 { ADVERTISED_1000baseT_Half, "1000H" },
1184 { ADVERTISED_1000baseT_Full, "1000F" },
1187 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1190 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1191 if (mask & ethtool_link_modes[i].mask)
1192 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1197 system_if_force_external(const char *ifname)
1202 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1203 return stat(buf, &s) == 0;
1207 system_if_dump_info(struct device *dev, struct blob_buf *b)
1209 struct ethtool_cmd ecmd;
1215 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
1216 dir_fd = open(buf, O_DIRECTORY);
1218 memset(&ecmd, 0, sizeof(ecmd));
1219 memset(&ifr, 0, sizeof(ifr));
1220 strcpy(ifr.ifr_name, dev->ifname);
1221 ifr.ifr_data = (caddr_t) &ecmd;
1222 ecmd.cmd = ETHTOOL_GSET;
1224 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1225 c = blobmsg_open_array(b, "link-advertising");
1226 system_add_link_modes(b, ecmd.advertising);
1227 blobmsg_close_array(b, c);
1229 c = blobmsg_open_array(b, "link-supported");
1230 system_add_link_modes(b, ecmd.supported);
1231 blobmsg_close_array(b, c);
1233 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1234 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1235 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1236 blobmsg_add_string_buffer(b);
1244 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1246 const char *const counters[] = {
1247 "collisions", "rx_frame_errors", "tx_compressed",
1248 "multicast", "rx_length_errors", "tx_dropped",
1249 "rx_bytes", "rx_missed_errors", "tx_errors",
1250 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1251 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1252 "rx_dropped", "tx_aborted_errors", "tx_packets",
1253 "rx_errors", "tx_bytes", "tx_window_errors",
1254 "rx_fifo_errors", "tx_carrier_errors",
1261 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1262 stats_dir = open(buf, O_DIRECTORY);
1266 for (i = 0; i < ARRAY_SIZE(counters); i++)
1267 if (read_uint64_file(stats_dir, counters[i], &val))
1268 blobmsg_add_u64(b, counters[i], val);
1274 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1276 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1277 int alen = v4 ? 4 : 16;
1278 unsigned int flags = 0;
1279 struct ifaddrmsg ifa = {
1280 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1281 .ifa_prefixlen = addr->mask,
1282 .ifa_index = dev->ifindex,
1286 if (cmd == RTM_NEWADDR)
1287 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1289 msg = nlmsg_alloc_simple(cmd, flags);
1293 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1294 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1296 if (addr->broadcast)
1297 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1298 if (addr->point_to_point)
1299 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1301 time_t now = system_get_rtime();
1302 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1304 if (addr->preferred_until) {
1305 int64_t preferred = addr->preferred_until - now;
1308 else if (preferred > UINT32_MAX)
1309 preferred = UINT32_MAX;
1311 cinfo.ifa_prefered = preferred;
1314 if (addr->valid_until) {
1315 int64_t valid = addr->valid_until - now;
1318 else if (valid > UINT32_MAX)
1321 cinfo.ifa_valid = valid;
1324 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1327 return system_rtnl_call(msg);
1330 int system_add_address(struct device *dev, struct device_addr *addr)
1332 return system_addr(dev, addr, RTM_NEWADDR);
1335 int system_del_address(struct device *dev, struct device_addr *addr)
1337 return system_addr(dev, addr, RTM_DELADDR);
1340 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1342 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1344 unsigned int flags = 0;
1347 have_gw = !!route->nexthop.in.s_addr;
1349 have_gw = route->nexthop.in6.s6_addr32[0] ||
1350 route->nexthop.in6.s6_addr32[1] ||
1351 route->nexthop.in6.s6_addr32[2] ||
1352 route->nexthop.in6.s6_addr32[3];
1354 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1355 ? route->table : RT_TABLE_MAIN;
1357 struct rtmsg rtm = {
1358 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1359 .rtm_dst_len = route->mask,
1360 .rtm_src_len = route->sourcemask,
1361 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1362 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
1363 .rtm_scope = RT_SCOPE_NOWHERE,
1364 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1365 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1369 if (cmd == RTM_NEWROUTE) {
1370 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1372 if (!dev) { // Add null-route
1373 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1374 rtm.rtm_type = RTN_UNREACHABLE;
1377 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1380 if (route->flags & DEVROUTE_TYPE) {
1381 rtm.rtm_type = route->type;
1382 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
1383 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
1384 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
1385 rtm.rtm_table = RT_TABLE_LOCAL;
1388 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT)
1389 rtm.rtm_scope = RT_SCOPE_HOST;
1390 else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
1391 rtm.rtm_type == RTN_ANYCAST)
1392 rtm.rtm_scope = RT_SCOPE_LINK;
1395 msg = nlmsg_alloc_simple(cmd, flags);
1399 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1402 nla_put(msg, RTA_DST, alen, &route->addr);
1404 if (route->sourcemask)
1405 nla_put(msg, RTA_SRC, alen, &route->source);
1407 if (route->metric > 0)
1408 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1411 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1414 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1417 nla_put_u32(msg, RTA_TABLE, table);
1419 if (route->flags & DEVROUTE_MTU) {
1420 struct nlattr *metrics;
1422 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1423 goto nla_put_failure;
1425 nla_put_u32(msg, RTAX_MTU, route->mtu);
1427 nla_nest_end(msg, metrics);
1430 return system_rtnl_call(msg);
1437 int system_add_route(struct device *dev, struct device_route *route)
1439 return system_rt(dev, route, RTM_NEWROUTE);
1442 int system_del_route(struct device *dev, struct device_route *route)
1444 return system_rt(dev, route, RTM_DELROUTE);
1447 int system_flush_routes(void)
1449 const char *names[] = {
1450 "/proc/sys/net/ipv4/route/flush",
1451 "/proc/sys/net/ipv6/route/flush"
1455 for (i = 0; i < ARRAY_SIZE(names); i++) {
1456 fd = open(names[i], O_WRONLY);
1460 if (write(fd, "-1", 2)) {}
1466 bool system_resolve_rt_type(const char *type, unsigned int *id)
1468 return system_rtn_aton(type, id);
1471 bool system_resolve_rt_table(const char *name, unsigned int *id)
1475 unsigned int n, table = RT_TABLE_UNSPEC;
1477 /* first try to parse table as number */
1478 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1481 /* handle well known aliases */
1482 else if (!strcmp(name, "default"))
1483 table = RT_TABLE_DEFAULT;
1484 else if (!strcmp(name, "main"))
1485 table = RT_TABLE_MAIN;
1486 else if (!strcmp(name, "local"))
1487 table = RT_TABLE_LOCAL;
1489 /* try to look up name in /etc/iproute2/rt_tables */
1490 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1492 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1494 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1497 n = strtoul(e, NULL, 10);
1498 e = strtok(NULL, " \t\n");
1500 if (e && !strcmp(e, name))
1510 if (table == RT_TABLE_UNSPEC)
1517 bool system_is_default_rt_table(unsigned int id)
1519 return (id == RT_TABLE_MAIN);
1522 static int system_iprule(struct iprule *rule, int cmd)
1524 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1527 struct rtmsg rtm = {
1528 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1529 .rtm_protocol = RTPROT_STATIC,
1530 .rtm_scope = RT_SCOPE_UNIVERSE,
1531 .rtm_table = RT_TABLE_UNSPEC,
1532 .rtm_type = RTN_UNSPEC,
1536 if (cmd == RTM_NEWRULE) {
1537 rtm.rtm_type = RTN_UNICAST;
1538 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1542 rtm.rtm_flags |= FIB_RULE_INVERT;
1544 if (rule->flags & IPRULE_SRC)
1545 rtm.rtm_src_len = rule->src_mask;
1547 if (rule->flags & IPRULE_DEST)
1548 rtm.rtm_dst_len = rule->dest_mask;
1550 if (rule->flags & IPRULE_TOS)
1551 rtm.rtm_tos = rule->tos;
1553 if (rule->flags & IPRULE_LOOKUP) {
1554 if (rule->lookup < 256)
1555 rtm.rtm_table = rule->lookup;
1558 if (rule->flags & IPRULE_ACTION)
1559 rtm.rtm_type = rule->action;
1560 else if (rule->flags & IPRULE_GOTO)
1561 rtm.rtm_type = FR_ACT_GOTO;
1562 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1563 rtm.rtm_type = FR_ACT_NOP;
1565 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1570 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1572 if (rule->flags & IPRULE_IN)
1573 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1575 if (rule->flags & IPRULE_OUT)
1576 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1578 if (rule->flags & IPRULE_SRC)
1579 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1581 if (rule->flags & IPRULE_DEST)
1582 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1584 if (rule->flags & IPRULE_PRIORITY)
1585 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1586 else if (cmd == RTM_NEWRULE)
1587 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1589 if (rule->flags & IPRULE_FWMARK)
1590 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1592 if (rule->flags & IPRULE_FWMASK)
1593 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1595 if (rule->flags & IPRULE_LOOKUP) {
1596 if (rule->lookup >= 256)
1597 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1600 if (rule->flags & IPRULE_GOTO)
1601 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1603 return system_rtnl_call(msg);
1606 int system_add_iprule(struct iprule *rule)
1608 return system_iprule(rule, RTM_NEWRULE);
1611 int system_del_iprule(struct iprule *rule)
1613 return system_iprule(rule, RTM_DELRULE);
1616 int system_flush_iprules(void)
1621 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1622 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1624 memset(&rule, 0, sizeof(rule));
1627 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1630 rule.lookup = RT_TABLE_LOCAL;
1631 rv |= system_iprule(&rule, RTM_NEWRULE);
1633 rule.priority = 32766;
1634 rule.lookup = RT_TABLE_MAIN;
1635 rv |= system_iprule(&rule, RTM_NEWRULE);
1637 rule.priority = 32767;
1638 rule.lookup = RT_TABLE_DEFAULT;
1639 rv |= system_iprule(&rule, RTM_NEWRULE);
1642 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1645 rule.lookup = RT_TABLE_LOCAL;
1646 rv |= system_iprule(&rule, RTM_NEWRULE);
1648 rule.priority = 32766;
1649 rule.lookup = RT_TABLE_MAIN;
1650 rv |= system_iprule(&rule, RTM_NEWRULE);
1655 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1657 return system_rtn_aton(action, id);
1660 time_t system_get_rtime(void)
1665 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1668 if (gettimeofday(&tv, NULL) == 0)
1675 #define IP_DF 0x4000
1678 static int tunnel_ioctl(const char *name, int cmd, void *p)
1682 memset(&ifr, 0, sizeof(ifr));
1683 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1684 ifr.ifr_ifru.ifru_data = p;
1685 return ioctl(sock_ioctl, cmd, &ifr);
1688 #ifdef IFLA_IPTUN_MAX
1689 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
1690 static int system_add_gre_tunnel(const char *name, const char *kind,
1691 const unsigned int link, struct blob_attr **tb, bool v6)
1694 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
1695 struct blob_attr *cur;
1696 uint32_t ikey = 0, okey = 0, flags = 0, flowinfo = 0;
1697 uint16_t iflags = 0, oflags = 0;
1699 int ret = 0, ttl = 64;
1701 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
1705 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
1706 nla_put_string(nlm, IFLA_IFNAME, name);
1708 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
1714 nla_put_string(nlm, IFLA_INFO_KIND, kind);
1715 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
1722 nla_put_u32(nlm, IFLA_GRE_LINK, link);
1724 if ((cur = tb[TUNNEL_ATTR_TTL]))
1725 ttl = blobmsg_get_u32(cur);
1727 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
1729 if ((cur = tb[TUNNEL_ATTR_TOS])) {
1730 char *str = blobmsg_get_string(cur);
1731 if (strcmp(str, "inherit")) {
1734 if (!system_tos_aton(str, &uval)) {
1740 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
1745 flags |= IP6_TNL_F_USE_ORIG_TCLASS;
1751 if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) {
1752 uint8_t icsum, ocsum, iseqno, oseqno;
1753 if (sscanf(blobmsg_get_string(cur), "%u,%u,%hhu,%hhu,%hhu,%hhu",
1754 &ikey, &okey, &icsum, &ocsum, &iseqno, &oseqno) < 6) {
1779 struct in6_addr in6buf;
1780 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1781 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1785 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
1788 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
1789 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1793 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
1795 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, 4);
1798 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
1801 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags);
1803 struct in_addr inbuf;
1806 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1807 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
1811 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
1814 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
1815 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
1819 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
1821 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
1823 okey = inbuf.s_addr;
1828 ikey = inbuf.s_addr;
1834 if ((cur = tb[TUNNEL_ATTR_DF]))
1835 set_df = blobmsg_get_bool(cur);
1837 /* ttl !=0 and nopmtudisc are incompatible */
1838 if (ttl && !set_df) {
1843 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
1845 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
1849 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
1852 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
1855 nla_put_u32(nlm, IFLA_GRE_OKEY, okey);
1858 nla_put_u32(nlm, IFLA_GRE_IKEY, ikey);
1860 nla_nest_end(nlm, infodata);
1861 nla_nest_end(nlm, linkinfo);
1863 return system_rtnl_call(nlm);
1871 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
1873 struct blob_attr *cur;
1875 struct ip_tunnel_parm p = {
1884 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
1885 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
1888 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
1889 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
1892 if ((cur = tb[TUNNEL_ATTR_DF]))
1893 set_df = blobmsg_get_bool(cur);
1895 if ((cur = tb[TUNNEL_ATTR_TTL]))
1896 p.iph.ttl = blobmsg_get_u32(cur);
1898 if ((cur = tb[TUNNEL_ATTR_TOS])) {
1899 char *str = blobmsg_get_string(cur);
1900 if (strcmp(str, "inherit")) {
1903 if (!system_tos_aton(str, &uval))
1911 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
1912 /* ttl !=0 and nopmtudisc are incompatible */
1913 if (p.iph.ttl && p.iph.frag_off == 0)
1916 strncpy(p.name, name, sizeof(p.name));
1918 switch (p.iph.protocol) {
1920 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
1922 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
1929 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
1931 struct blob_attr *cur;
1934 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
1936 str = blobmsg_data(cur);
1938 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
1939 !strcmp(str, "greip6") || !strcmp(str, "gretapip6"))
1940 return system_link_del(name);
1942 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
1945 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
1947 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
1949 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
1950 blob_data(attr), blob_len(attr));
1952 return __system_del_ip_tunnel(name, tb);
1955 int system_update_ipv6_mtu(struct device *dev, int mtu)
1959 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
1962 int fd = open(buf, O_RDWR);
1963 ssize_t len = read(fd, buf, sizeof(buf) - 1);
1970 if (!mtu || ret <= mtu)
1973 lseek(fd, 0, SEEK_SET);
1974 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) <= 0)
1982 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
1984 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
1985 struct blob_attr *cur;
1988 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
1989 blob_data(attr), blob_len(attr));
1991 __system_del_ip_tunnel(name, tb);
1993 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
1995 str = blobmsg_data(cur);
1997 unsigned int ttl = 0;
1998 if ((cur = tb[TUNNEL_ATTR_TTL])) {
1999 ttl = blobmsg_get_u32(cur);
2004 unsigned int link = 0;
2005 if ((cur = tb[TUNNEL_ATTR_LINK])) {
2006 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
2010 if (iface->l3_dev.dev)
2011 link = iface->l3_dev.dev->ifindex;
2014 if (!strcmp(str, "sit")) {
2015 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
2019 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
2021 struct ip_tunnel_6rd p6;
2023 memset(&p6, 0, sizeof(p6));
2025 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
2026 &p6.prefix, &mask) || mask > 128)
2028 p6.prefixlen = mask;
2030 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
2031 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
2032 &p6.relay_prefix, &mask) || mask > 32)
2034 p6.relay_prefixlen = mask;
2037 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
2038 __system_del_ip_tunnel(name, tb);
2043 #ifdef IFLA_IPTUN_MAX
2044 } else if (!strcmp(str, "ipip6")) {
2045 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2046 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2047 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2053 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2054 nla_put_string(nlm, IFLA_IFNAME, name);
2057 nla_put_u32(nlm, IFLA_LINK, link);
2059 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2064 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2065 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2072 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2074 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2075 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2076 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
2078 struct in6_addr in6buf;
2079 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2080 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2084 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2087 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2088 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2092 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2095 #ifdef IFLA_IPTUN_FMR_MAX
2096 if ((cur = tb[TUNNEL_ATTR_FMRS])) {
2097 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2099 struct blob_attr *fmr;
2100 unsigned rem, fmrcnt = 0;
2101 blobmsg_for_each_attr(fmr, cur, rem) {
2102 if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
2105 unsigned ip4len, ip6len, ealen, offset = 6;
2109 if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
2110 ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) {
2115 struct in6_addr ip6prefix;
2116 struct in_addr ip4prefix;
2117 if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
2118 inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) {
2123 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2125 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2126 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2127 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2128 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2129 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2130 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2132 nla_nest_end(nlm, rule);
2135 nla_nest_end(nlm, fmrs);
2139 nla_nest_end(nlm, infodata);
2140 nla_nest_end(nlm, linkinfo);
2142 return system_rtnl_call(nlm);
2146 } else if (!strcmp(str, "greip")) {
2147 return system_add_gre_tunnel(name, "gre", link, tb, false);
2148 } else if (!strcmp(str, "gretapip")) {
2149 return system_add_gre_tunnel(name, "gretap", link, tb, false);
2150 } else if (!strcmp(str, "greip6")) {
2151 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
2152 } else if (!strcmp(str, "gretapip6")) {
2153 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
2155 } else if (!strcmp(str, "ipip")) {
2156 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);