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);
319 if (!dev || dev->type->keep_link_status)
322 if (!system_get_dev_sysctl("/sys/class/net/%s/carrier", dev->ifname, buf, sizeof(buf)))
323 link_state = strtoul(buf, NULL, 0);
325 device_set_link(dev, link_state ? true : false);
332 handle_hotplug_msg(char *data, int size)
334 const char *subsystem = NULL, *interface = NULL;
335 char *cur, *end, *sep;
340 if (!strncmp(data, "add@", 4))
342 else if (!strncmp(data, "remove@", 7))
347 skip = strlen(data) + 1;
350 for (cur = data + skip; cur < end; cur += skip) {
351 skip = strlen(cur) + 1;
353 sep = strchr(cur, '=');
358 if (!strcmp(cur, "INTERFACE"))
360 else if (!strcmp(cur, "SUBSYSTEM")) {
362 if (strcmp(subsystem, "net") != 0)
365 if (subsystem && interface)
371 dev = device_get(interface, false);
375 if (dev->type != &simple_device_type)
378 if (add && system_if_force_external(dev->ifname))
381 device_set_present(dev, add);
385 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
387 struct event_socket *ev = container_of(u, struct event_socket, uloop);
388 struct sockaddr_nl nla;
389 unsigned char *buf = NULL;
392 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
394 handle_hotplug_msg((char *) buf, size);
400 static int system_rtnl_call(struct nl_msg *msg)
404 ret = nl_send_auto_complete(sock_rtnl, msg);
410 return nl_wait_for_ack(sock_rtnl);
413 int system_bridge_delbr(struct device *bridge)
415 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
418 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
422 memset(&ifr, 0, sizeof(ifr));
424 ifr.ifr_ifindex = dev->ifindex;
427 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
428 return ioctl(sock_ioctl, cmd, &ifr);
431 static bool system_is_bridge(const char *name, char *buf, int buflen)
435 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
436 if (stat(buf, &st) < 0)
442 static char *system_get_bridge(const char *name, char *buf, int buflen)
448 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
449 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
453 len = readlink(gl.gl_pathv[0], buf, buflen);
461 path = strrchr(buf, '/');
468 static void system_bridge_set_wireless(const char *bridge, const char *dev)
470 snprintf(dev_buf, sizeof(dev_buf),
471 "/sys/devices/virtual/net/%s/brif/%s/multicast_to_unicast",
473 system_set_sysctl(dev_buf, "1");
476 int system_bridge_addif(struct device *bridge, struct device *dev)
481 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
482 if (!oldbr || strcmp(oldbr, bridge->ifname) != 0)
483 ret = system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
486 system_bridge_set_wireless(bridge->ifname, dev->ifname);
491 int system_bridge_delif(struct device *bridge, struct device *dev)
493 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
496 int system_if_resolve(struct device *dev)
499 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
500 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
501 return ifr.ifr_ifindex;
506 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
510 memset(&ifr, 0, sizeof(ifr));
511 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
512 ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
513 ifr.ifr_flags |= add;
514 ifr.ifr_flags &= ~rem;
515 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
527 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
529 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
531 return ifa->ifa_index == ifindex;
534 static bool check_route(struct nlmsghdr *hdr, int ifindex)
536 struct rtmsg *r = NLMSG_DATA(hdr);
537 struct nlattr *tb[__RTA_MAX];
539 if (r->rtm_protocol == RTPROT_KERNEL &&
540 r->rtm_family == AF_INET6)
543 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
547 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
550 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
555 static int cb_clear_event(struct nl_msg *msg, void *arg)
557 struct clear_data *clr = arg;
558 struct nlmsghdr *hdr = nlmsg_hdr(msg);
559 bool (*cb)(struct nlmsghdr *, int ifindex);
565 if (hdr->nlmsg_type != RTM_NEWADDR)
572 if (hdr->nlmsg_type != RTM_NEWROUTE)
579 if (hdr->nlmsg_type != RTM_NEWRULE)
588 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
591 if (type == RTM_DELRULE)
592 D(SYSTEM, "Remove a rule\n");
594 D(SYSTEM, "Remove %s from device %s\n",
595 type == RTM_DELADDR ? "an address" : "a route",
597 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
598 hdr = nlmsg_hdr(clr->msg);
599 hdr->nlmsg_type = type;
600 hdr->nlmsg_flags = NLM_F_REQUEST;
602 nl_socket_disable_auto_ack(sock_rtnl);
603 nl_send_auto_complete(sock_rtnl, clr->msg);
604 nl_socket_enable_auto_ack(sock_rtnl);
610 cb_finish_event(struct nl_msg *msg, void *arg)
618 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
621 *pending = err->error;
626 system_if_clear_entries(struct device *dev, int type, int af)
628 struct clear_data clr;
629 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
632 .rtm_flags = RTM_F_CLONED,
634 int flags = NLM_F_DUMP;
643 clr.size = sizeof(struct rtgenmsg);
646 clr.size = sizeof(struct rtmsg);
655 clr.msg = nlmsg_alloc_simple(type, flags);
659 nlmsg_append(clr.msg, &rtm, clr.size, 0);
660 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
661 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
662 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
664 nl_send_auto_complete(sock_rtnl, clr.msg);
666 nl_recvmsgs(sock_rtnl, cb);
674 * Clear bridge (membership) state and bring down device
676 void system_if_clear_state(struct device *dev)
678 static char buf[256];
681 device_set_ifindex(dev, system_if_resolve(dev));
682 if (dev->external || !dev->ifindex)
685 system_if_flags(dev->ifname, 0, IFF_UP);
687 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
688 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
689 system_bridge_delbr(dev);
693 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
695 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
696 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
699 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
700 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
701 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
702 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
703 system_set_disable_ipv6(dev, "0");
706 static inline unsigned long
707 sec_to_jiffies(int val)
709 return (unsigned long) val * 100;
712 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
714 unsigned long args[4] = {};
716 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
719 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
720 args[1] = !!cfg->stp;
721 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
723 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
724 args[1] = sec_to_jiffies(cfg->forward_delay);
725 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
727 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
728 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
730 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier",
731 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
733 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
734 args[1] = cfg->priority;
735 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
737 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
738 args[0] = BRCTL_SET_AGEING_TIME;
739 args[1] = sec_to_jiffies(cfg->ageing_time);
740 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
743 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
744 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
745 args[1] = sec_to_jiffies(cfg->hello_time);
746 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
749 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
750 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
751 args[1] = sec_to_jiffies(cfg->max_age);
752 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
758 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
761 struct nlattr *linkinfo, *data;
762 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
763 int ifindex = system_if_resolve(dev);
765 static const struct {
767 enum macvlan_mode val;
769 { "private", MACVLAN_MODE_PRIVATE },
770 { "vepa", MACVLAN_MODE_VEPA },
771 { "bridge", MACVLAN_MODE_BRIDGE },
772 { "passthru", MACVLAN_MODE_PASSTHRU },
778 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
783 nlmsg_append(msg, &iim, sizeof(iim), 0);
785 if (cfg->flags & MACVLAN_OPT_MACADDR)
786 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
787 nla_put_string(msg, IFLA_IFNAME, macvlan->ifname);
788 nla_put_u32(msg, IFLA_LINK, ifindex);
790 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
791 goto nla_put_failure;
793 nla_put_string(msg, IFLA_INFO_KIND, "macvlan");
795 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
796 goto nla_put_failure;
799 for (i = 0; i < ARRAY_SIZE(modes); i++) {
800 if (strcmp(cfg->mode, modes[i].name) != 0)
803 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
808 nla_nest_end(msg, data);
809 nla_nest_end(msg, linkinfo);
811 rv = system_rtnl_call(msg);
813 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
822 static int system_link_del(const char *ifname)
825 struct ifinfomsg iim = {
826 .ifi_family = AF_UNSPEC,
830 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
835 nlmsg_append(msg, &iim, sizeof(iim), 0);
836 nla_put_string(msg, IFLA_IFNAME, ifname);
837 return system_rtnl_call(msg);
840 int system_macvlan_del(struct device *macvlan)
842 return system_link_del(macvlan->ifname);
845 static int system_vlan(struct device *dev, int id)
847 struct vlan_ioctl_args ifr = {
848 .cmd = SET_VLAN_NAME_TYPE_CMD,
849 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
852 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
855 ifr.cmd = DEL_VLAN_CMD;
858 ifr.cmd = ADD_VLAN_CMD;
861 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
862 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
865 int system_vlan_add(struct device *dev, int id)
867 return system_vlan(dev, id);
870 int system_vlan_del(struct device *dev)
872 return system_vlan(dev, -1);
875 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
878 struct nlattr *linkinfo, *data;
879 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
880 int ifindex = system_if_resolve(dev);
886 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
891 nlmsg_append(msg, &iim, sizeof(iim), 0);
892 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
893 nla_put_u32(msg, IFLA_LINK, ifindex);
895 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
896 goto nla_put_failure;
898 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
900 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
901 goto nla_put_failure;
903 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
905 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
906 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
908 if(cfg->proto == VLAN_PROTO_8021AD)
909 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);
912 nla_nest_end(msg, data);
913 nla_nest_end(msg, linkinfo);
915 rv = system_rtnl_call(msg);
917 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
926 int system_vlandev_del(struct device *vlandev)
928 return system_link_del(vlandev->ifname);
932 system_if_get_settings(struct device *dev, struct device_settings *s)
937 memset(&ifr, 0, sizeof(ifr));
938 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
940 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
941 s->mtu = ifr.ifr_mtu;
942 s->flags |= DEV_OPT_MTU;
945 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
946 s->txqueuelen = ifr.ifr_qlen;
947 s->flags |= DEV_OPT_TXQUEUELEN;
950 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
951 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
952 s->flags |= DEV_OPT_MACADDR;
955 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
956 s->ipv6 = !strtoul(buf, NULL, 0);
957 s->flags |= DEV_OPT_IPV6;
960 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
961 s->promisc = ifr.ifr_flags & IFF_PROMISC;
962 s->flags |= DEV_OPT_PROMISC;
967 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
974 memset(&ifr, 0, sizeof(ifr));
975 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
976 if (s->flags & DEV_OPT_MTU & apply_mask) {
977 ifr.ifr_mtu = s->mtu;
978 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
979 s->flags &= ~DEV_OPT_MTU;
981 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
982 ifr.ifr_qlen = s->txqueuelen;
983 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
984 s->flags &= ~DEV_OPT_TXQUEUELEN;
986 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
987 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
988 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
989 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
990 s->flags &= ~DEV_OPT_MACADDR;
992 if (s->flags & DEV_OPT_IPV6 & apply_mask)
993 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
994 if (s->flags & DEV_OPT_PROMISC & apply_mask) {
995 if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
996 !s->promisc ? IFF_PROMISC : 0) < 0)
997 s->flags &= ~DEV_OPT_PROMISC;
1001 int system_if_up(struct device *dev)
1003 system_if_get_settings(dev, &dev->orig_settings);
1004 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
1005 return system_if_flags(dev->ifname, IFF_UP, 0);
1008 int system_if_down(struct device *dev)
1010 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
1011 dev->orig_settings.flags &= dev->settings.flags;
1012 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
1016 struct if_check_data {
1022 #ifndef IFF_LOWER_UP
1023 #define IFF_LOWER_UP 0x10000
1026 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1028 struct nlmsghdr *nh = nlmsg_hdr(msg);
1029 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1030 struct if_check_data *chk = (struct if_check_data *)arg;
1032 if (nh->nlmsg_type != RTM_NEWLINK)
1035 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1036 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1041 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1043 struct if_check_data *chk = (struct if_check_data *)arg;
1048 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1050 struct if_check_data *chk = (struct if_check_data *)arg;
1052 device_set_present(chk->dev, false);
1053 device_set_link(chk->dev, false);
1054 chk->pending = err->error;
1059 int system_if_check(struct device *dev)
1061 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1063 struct ifinfomsg ifi = {
1064 .ifi_family = AF_UNSPEC,
1067 struct if_check_data chk = {
1073 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1074 if (!msg || nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1075 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1078 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1079 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1080 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1082 nl_send_auto_complete(sock_rtnl, msg);
1083 while (chk.pending > 0)
1084 nl_recvmsgs(sock_rtnl, cb);
1095 system_if_get_parent(struct device *dev)
1097 char buf[64], *devname;
1098 int ifindex, iflink, len;
1101 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1102 f = fopen(buf, "r");
1106 len = fread(buf, 1, sizeof(buf) - 1, f);
1113 iflink = strtoul(buf, NULL, 0);
1114 ifindex = system_if_resolve(dev);
1115 if (!iflink || iflink == ifindex)
1118 devname = if_indextoname(iflink, buf);
1122 return device_get(devname, true);
1126 read_string_file(int dir_fd, const char *file, char *buf, int len)
1132 fd = openat(dir_fd, file, O_RDONLY);
1137 len = read(fd, buf, len - 1);
1141 } else if (len > 0) {
1144 c = strchr(buf, '\n');
1157 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1162 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1164 *val = strtoull(buf, NULL, 0);
1169 /* Assume advertised flags == supported flags */
1170 static const struct {
1173 } ethtool_link_modes[] = {
1174 { ADVERTISED_10baseT_Half, "10H" },
1175 { ADVERTISED_10baseT_Full, "10F" },
1176 { ADVERTISED_100baseT_Half, "100H" },
1177 { ADVERTISED_100baseT_Full, "100F" },
1178 { ADVERTISED_1000baseT_Half, "1000H" },
1179 { ADVERTISED_1000baseT_Full, "1000F" },
1182 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1185 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1186 if (mask & ethtool_link_modes[i].mask)
1187 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1192 system_if_force_external(const char *ifname)
1197 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1198 return stat(buf, &s) == 0;
1202 system_if_dump_info(struct device *dev, struct blob_buf *b)
1204 struct ethtool_cmd ecmd;
1210 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
1211 dir_fd = open(buf, O_DIRECTORY);
1213 memset(&ecmd, 0, sizeof(ecmd));
1214 memset(&ifr, 0, sizeof(ifr));
1215 strcpy(ifr.ifr_name, dev->ifname);
1216 ifr.ifr_data = (caddr_t) &ecmd;
1217 ecmd.cmd = ETHTOOL_GSET;
1219 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1220 c = blobmsg_open_array(b, "link-advertising");
1221 system_add_link_modes(b, ecmd.advertising);
1222 blobmsg_close_array(b, c);
1224 c = blobmsg_open_array(b, "link-supported");
1225 system_add_link_modes(b, ecmd.supported);
1226 blobmsg_close_array(b, c);
1228 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1229 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1230 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1231 blobmsg_add_string_buffer(b);
1239 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1241 const char *const counters[] = {
1242 "collisions", "rx_frame_errors", "tx_compressed",
1243 "multicast", "rx_length_errors", "tx_dropped",
1244 "rx_bytes", "rx_missed_errors", "tx_errors",
1245 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1246 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1247 "rx_dropped", "tx_aborted_errors", "tx_packets",
1248 "rx_errors", "tx_bytes", "tx_window_errors",
1249 "rx_fifo_errors", "tx_carrier_errors",
1256 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1257 stats_dir = open(buf, O_DIRECTORY);
1261 for (i = 0; i < ARRAY_SIZE(counters); i++)
1262 if (read_uint64_file(stats_dir, counters[i], &val))
1263 blobmsg_add_u64(b, counters[i], val);
1269 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1271 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1272 int alen = v4 ? 4 : 16;
1273 unsigned int flags = 0;
1274 struct ifaddrmsg ifa = {
1275 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1276 .ifa_prefixlen = addr->mask,
1277 .ifa_index = dev->ifindex,
1281 if (cmd == RTM_NEWADDR)
1282 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1284 msg = nlmsg_alloc_simple(cmd, flags);
1288 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1289 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1291 if (addr->broadcast)
1292 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1293 if (addr->point_to_point)
1294 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1296 time_t now = system_get_rtime();
1297 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1299 if (addr->preferred_until) {
1300 int64_t preferred = addr->preferred_until - now;
1303 else if (preferred > UINT32_MAX)
1304 preferred = UINT32_MAX;
1306 cinfo.ifa_prefered = preferred;
1309 if (addr->valid_until) {
1310 int64_t valid = addr->valid_until - now;
1313 else if (valid > UINT32_MAX)
1316 cinfo.ifa_valid = valid;
1319 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1322 return system_rtnl_call(msg);
1325 int system_add_address(struct device *dev, struct device_addr *addr)
1327 return system_addr(dev, addr, RTM_NEWADDR);
1330 int system_del_address(struct device *dev, struct device_addr *addr)
1332 return system_addr(dev, addr, RTM_DELADDR);
1335 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1337 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1339 unsigned int flags = 0;
1342 have_gw = !!route->nexthop.in.s_addr;
1344 have_gw = route->nexthop.in6.s6_addr32[0] ||
1345 route->nexthop.in6.s6_addr32[1] ||
1346 route->nexthop.in6.s6_addr32[2] ||
1347 route->nexthop.in6.s6_addr32[3];
1349 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1350 ? route->table : RT_TABLE_MAIN;
1352 struct rtmsg rtm = {
1353 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1354 .rtm_dst_len = route->mask,
1355 .rtm_src_len = route->sourcemask,
1356 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1357 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
1358 .rtm_scope = RT_SCOPE_NOWHERE,
1359 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1360 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1364 if (cmd == RTM_NEWROUTE) {
1365 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1367 if (!dev) { // Add null-route
1368 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1369 rtm.rtm_type = RTN_UNREACHABLE;
1372 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1375 if (route->flags & DEVROUTE_TYPE) {
1376 rtm.rtm_type = route->type;
1377 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
1378 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
1379 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
1380 rtm.rtm_table = RT_TABLE_LOCAL;
1383 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT)
1384 rtm.rtm_scope = RT_SCOPE_HOST;
1385 else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
1386 rtm.rtm_type == RTN_ANYCAST)
1387 rtm.rtm_scope = RT_SCOPE_LINK;
1390 msg = nlmsg_alloc_simple(cmd, flags);
1394 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1397 nla_put(msg, RTA_DST, alen, &route->addr);
1399 if (route->sourcemask)
1400 nla_put(msg, RTA_SRC, alen, &route->source);
1402 if (route->metric > 0)
1403 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1406 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1409 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1412 nla_put_u32(msg, RTA_TABLE, table);
1414 if (route->flags & DEVROUTE_MTU) {
1415 struct nlattr *metrics;
1417 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1418 goto nla_put_failure;
1420 nla_put_u32(msg, RTAX_MTU, route->mtu);
1422 nla_nest_end(msg, metrics);
1425 return system_rtnl_call(msg);
1432 int system_add_route(struct device *dev, struct device_route *route)
1434 return system_rt(dev, route, RTM_NEWROUTE);
1437 int system_del_route(struct device *dev, struct device_route *route)
1439 return system_rt(dev, route, RTM_DELROUTE);
1442 int system_flush_routes(void)
1444 const char *names[] = {
1445 "/proc/sys/net/ipv4/route/flush",
1446 "/proc/sys/net/ipv6/route/flush"
1450 for (i = 0; i < ARRAY_SIZE(names); i++) {
1451 fd = open(names[i], O_WRONLY);
1455 if (write(fd, "-1", 2)) {}
1461 bool system_resolve_rt_type(const char *type, unsigned int *id)
1463 return system_rtn_aton(type, id);
1466 bool system_resolve_rt_table(const char *name, unsigned int *id)
1470 unsigned int n, table = RT_TABLE_UNSPEC;
1472 /* first try to parse table as number */
1473 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1476 /* handle well known aliases */
1477 else if (!strcmp(name, "default"))
1478 table = RT_TABLE_DEFAULT;
1479 else if (!strcmp(name, "main"))
1480 table = RT_TABLE_MAIN;
1481 else if (!strcmp(name, "local"))
1482 table = RT_TABLE_LOCAL;
1484 /* try to look up name in /etc/iproute2/rt_tables */
1485 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1487 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1489 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1492 n = strtoul(e, NULL, 10);
1493 e = strtok(NULL, " \t\n");
1495 if (e && !strcmp(e, name))
1505 if (table == RT_TABLE_UNSPEC)
1512 bool system_is_default_rt_table(unsigned int id)
1514 return (id == RT_TABLE_MAIN);
1517 static int system_iprule(struct iprule *rule, int cmd)
1519 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1522 struct rtmsg rtm = {
1523 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1524 .rtm_protocol = RTPROT_STATIC,
1525 .rtm_scope = RT_SCOPE_UNIVERSE,
1526 .rtm_table = RT_TABLE_UNSPEC,
1527 .rtm_type = RTN_UNSPEC,
1531 if (cmd == RTM_NEWRULE) {
1532 rtm.rtm_type = RTN_UNICAST;
1533 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1537 rtm.rtm_flags |= FIB_RULE_INVERT;
1539 if (rule->flags & IPRULE_SRC)
1540 rtm.rtm_src_len = rule->src_mask;
1542 if (rule->flags & IPRULE_DEST)
1543 rtm.rtm_dst_len = rule->dest_mask;
1545 if (rule->flags & IPRULE_TOS)
1546 rtm.rtm_tos = rule->tos;
1548 if (rule->flags & IPRULE_LOOKUP) {
1549 if (rule->lookup < 256)
1550 rtm.rtm_table = rule->lookup;
1553 if (rule->flags & IPRULE_ACTION)
1554 rtm.rtm_type = rule->action;
1555 else if (rule->flags & IPRULE_GOTO)
1556 rtm.rtm_type = FR_ACT_GOTO;
1557 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1558 rtm.rtm_type = FR_ACT_NOP;
1560 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1565 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1567 if (rule->flags & IPRULE_IN)
1568 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1570 if (rule->flags & IPRULE_OUT)
1571 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1573 if (rule->flags & IPRULE_SRC)
1574 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1576 if (rule->flags & IPRULE_DEST)
1577 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1579 if (rule->flags & IPRULE_PRIORITY)
1580 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1581 else if (cmd == RTM_NEWRULE)
1582 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1584 if (rule->flags & IPRULE_FWMARK)
1585 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1587 if (rule->flags & IPRULE_FWMASK)
1588 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1590 if (rule->flags & IPRULE_LOOKUP) {
1591 if (rule->lookup >= 256)
1592 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1595 if (rule->flags & IPRULE_GOTO)
1596 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1598 return system_rtnl_call(msg);
1601 int system_add_iprule(struct iprule *rule)
1603 return system_iprule(rule, RTM_NEWRULE);
1606 int system_del_iprule(struct iprule *rule)
1608 return system_iprule(rule, RTM_DELRULE);
1611 int system_flush_iprules(void)
1616 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1617 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1619 memset(&rule, 0, sizeof(rule));
1622 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1625 rule.lookup = RT_TABLE_LOCAL;
1626 rv |= system_iprule(&rule, RTM_NEWRULE);
1628 rule.priority = 32766;
1629 rule.lookup = RT_TABLE_MAIN;
1630 rv |= system_iprule(&rule, RTM_NEWRULE);
1632 rule.priority = 32767;
1633 rule.lookup = RT_TABLE_DEFAULT;
1634 rv |= system_iprule(&rule, RTM_NEWRULE);
1637 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1640 rule.lookup = RT_TABLE_LOCAL;
1641 rv |= system_iprule(&rule, RTM_NEWRULE);
1643 rule.priority = 32766;
1644 rule.lookup = RT_TABLE_MAIN;
1645 rv |= system_iprule(&rule, RTM_NEWRULE);
1650 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1652 return system_rtn_aton(action, id);
1655 time_t system_get_rtime(void)
1660 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1663 if (gettimeofday(&tv, NULL) == 0)
1670 #define IP_DF 0x4000
1673 static int tunnel_ioctl(const char *name, int cmd, void *p)
1677 memset(&ifr, 0, sizeof(ifr));
1678 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1679 ifr.ifr_ifru.ifru_data = p;
1680 return ioctl(sock_ioctl, cmd, &ifr);
1683 #ifdef IFLA_IPTUN_MAX
1684 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
1685 static int system_add_gre_tunnel(const char *name, const char *kind,
1686 const unsigned int link, struct blob_attr **tb, bool v6)
1689 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
1690 struct blob_attr *cur;
1691 uint32_t ikey = 0, okey = 0, flags = 0, flowinfo = 0;
1692 uint16_t iflags = 0, oflags = 0;
1694 int ret = 0, ttl = 64;
1696 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
1700 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
1701 nla_put_string(nlm, IFLA_IFNAME, name);
1703 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
1709 nla_put_string(nlm, IFLA_INFO_KIND, kind);
1710 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
1717 nla_put_u32(nlm, IFLA_GRE_LINK, link);
1719 if ((cur = tb[TUNNEL_ATTR_TTL]))
1720 ttl = blobmsg_get_u32(cur);
1722 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
1724 if ((cur = tb[TUNNEL_ATTR_TOS])) {
1725 char *str = blobmsg_get_string(cur);
1726 if (strcmp(str, "inherit")) {
1729 if (!system_tos_aton(str, &uval)) {
1735 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
1740 flags |= IP6_TNL_F_USE_ORIG_TCLASS;
1746 if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) {
1747 uint8_t icsum, ocsum, iseqno, oseqno;
1748 if (sscanf(blobmsg_get_string(cur), "%u,%u,%hhu,%hhu,%hhu,%hhu",
1749 &ikey, &okey, &icsum, &ocsum, &iseqno, &oseqno) < 6) {
1774 struct in6_addr in6buf;
1775 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1776 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1780 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
1783 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
1784 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1788 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
1790 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, 4);
1793 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
1796 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags);
1798 struct in_addr inbuf;
1801 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1802 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
1806 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
1809 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
1810 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
1814 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
1816 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
1818 okey = inbuf.s_addr;
1823 ikey = inbuf.s_addr;
1829 if ((cur = tb[TUNNEL_ATTR_DF]))
1830 set_df = blobmsg_get_bool(cur);
1832 /* ttl !=0 and nopmtudisc are incompatible */
1833 if (ttl && !set_df) {
1838 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
1840 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
1844 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
1847 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
1850 nla_put_u32(nlm, IFLA_GRE_OKEY, okey);
1853 nla_put_u32(nlm, IFLA_GRE_IKEY, ikey);
1855 nla_nest_end(nlm, infodata);
1856 nla_nest_end(nlm, linkinfo);
1858 return system_rtnl_call(nlm);
1866 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
1868 struct blob_attr *cur;
1870 struct ip_tunnel_parm p = {
1879 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
1880 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
1883 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
1884 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
1887 if ((cur = tb[TUNNEL_ATTR_DF]))
1888 set_df = blobmsg_get_bool(cur);
1890 if ((cur = tb[TUNNEL_ATTR_TTL]))
1891 p.iph.ttl = blobmsg_get_u32(cur);
1893 if ((cur = tb[TUNNEL_ATTR_TOS])) {
1894 char *str = blobmsg_get_string(cur);
1895 if (strcmp(str, "inherit")) {
1898 if (!system_tos_aton(str, &uval))
1906 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
1907 /* ttl !=0 and nopmtudisc are incompatible */
1908 if (p.iph.ttl && p.iph.frag_off == 0)
1911 strncpy(p.name, name, sizeof(p.name));
1913 switch (p.iph.protocol) {
1915 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
1917 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
1924 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
1926 struct blob_attr *cur;
1929 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
1931 str = blobmsg_data(cur);
1933 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
1934 !strcmp(str, "greip6") || !strcmp(str, "gretapip6"))
1935 return system_link_del(name);
1937 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
1940 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
1942 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
1944 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
1945 blob_data(attr), blob_len(attr));
1947 return __system_del_ip_tunnel(name, tb);
1950 int system_update_ipv6_mtu(struct device *dev, int mtu)
1954 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
1957 int fd = open(buf, O_RDWR);
1958 ssize_t len = read(fd, buf, sizeof(buf) - 1);
1965 if (!mtu || ret <= mtu)
1968 lseek(fd, 0, SEEK_SET);
1969 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) <= 0)
1977 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
1979 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
1980 struct blob_attr *cur;
1983 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
1984 blob_data(attr), blob_len(attr));
1986 __system_del_ip_tunnel(name, tb);
1988 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
1990 str = blobmsg_data(cur);
1992 unsigned int ttl = 0;
1993 if ((cur = tb[TUNNEL_ATTR_TTL])) {
1994 ttl = blobmsg_get_u32(cur);
1999 unsigned int link = 0;
2000 if ((cur = tb[TUNNEL_ATTR_LINK])) {
2001 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
2005 if (iface->l3_dev.dev)
2006 link = iface->l3_dev.dev->ifindex;
2009 if (!strcmp(str, "sit")) {
2010 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
2014 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
2016 struct ip_tunnel_6rd p6;
2018 memset(&p6, 0, sizeof(p6));
2020 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
2021 &p6.prefix, &mask) || mask > 128)
2023 p6.prefixlen = mask;
2025 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
2026 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
2027 &p6.relay_prefix, &mask) || mask > 32)
2029 p6.relay_prefixlen = mask;
2032 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
2033 __system_del_ip_tunnel(name, tb);
2038 #ifdef IFLA_IPTUN_MAX
2039 } else if (!strcmp(str, "ipip6")) {
2040 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2041 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2042 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2048 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2049 nla_put_string(nlm, IFLA_IFNAME, name);
2052 nla_put_u32(nlm, IFLA_LINK, link);
2054 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2059 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2060 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2067 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2069 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2070 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2071 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
2073 struct in6_addr in6buf;
2074 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2075 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2079 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2082 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2083 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2087 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2090 #ifdef IFLA_IPTUN_FMR_MAX
2091 if ((cur = tb[TUNNEL_ATTR_FMRS])) {
2092 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2094 struct blob_attr *fmr;
2095 unsigned rem, fmrcnt = 0;
2096 blobmsg_for_each_attr(fmr, cur, rem) {
2097 if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
2100 unsigned ip4len, ip6len, ealen, offset = 6;
2104 if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
2105 ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) {
2110 struct in6_addr ip6prefix;
2111 struct in_addr ip4prefix;
2112 if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
2113 inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) {
2118 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2120 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2121 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2122 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2123 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2124 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2125 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2127 nla_nest_end(nlm, rule);
2130 nla_nest_end(nlm, fmrs);
2134 nla_nest_end(nlm, infodata);
2135 nla_nest_end(nlm, linkinfo);
2137 return system_rtnl_call(nlm);
2141 } else if (!strcmp(str, "greip")) {
2142 return system_add_gre_tunnel(name, "gre", link, tb, false);
2143 } else if (!strcmp(str, "gretapip")) {
2144 return system_add_gre_tunnel(name, "gretap", link, tb, false);
2145 } else if (!strcmp(str, "greip6")) {
2146 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
2147 } else if (!strcmp(str, "gretapip6")) {
2148 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
2150 } else if (!strcmp(str, "ipip")) {
2151 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);