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, };
764 static const struct {
766 enum macvlan_mode val;
768 { "private", MACVLAN_MODE_PRIVATE },
769 { "vepa", MACVLAN_MODE_VEPA },
770 { "bridge", MACVLAN_MODE_BRIDGE },
771 { "passthru", MACVLAN_MODE_PASSTHRU },
774 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
779 nlmsg_append(msg, &iim, sizeof(iim), 0);
781 if (cfg->flags & MACVLAN_OPT_MACADDR)
782 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
783 nla_put_string(msg, IFLA_IFNAME, macvlan->ifname);
784 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
786 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
787 goto nla_put_failure;
789 nla_put_string(msg, IFLA_INFO_KIND, "macvlan");
791 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
792 goto nla_put_failure;
795 for (i = 0; i < ARRAY_SIZE(modes); i++) {
796 if (strcmp(cfg->mode, modes[i].name) != 0)
799 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
804 nla_nest_end(msg, data);
805 nla_nest_end(msg, linkinfo);
807 rv = system_rtnl_call(msg);
809 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
818 static int system_link_del(const char *ifname)
821 struct ifinfomsg iim = {
822 .ifi_family = AF_UNSPEC,
826 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
831 nlmsg_append(msg, &iim, sizeof(iim), 0);
832 nla_put_string(msg, IFLA_IFNAME, ifname);
833 return system_rtnl_call(msg);
836 int system_macvlan_del(struct device *macvlan)
838 return system_link_del(macvlan->ifname);
841 static int system_vlan(struct device *dev, int id)
843 struct vlan_ioctl_args ifr = {
844 .cmd = SET_VLAN_NAME_TYPE_CMD,
845 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
848 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
851 ifr.cmd = DEL_VLAN_CMD;
854 ifr.cmd = ADD_VLAN_CMD;
857 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
858 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
861 int system_vlan_add(struct device *dev, int id)
863 return system_vlan(dev, id);
866 int system_vlan_del(struct device *dev)
868 return system_vlan(dev, -1);
871 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
874 struct nlattr *linkinfo, *data;
875 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
878 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
883 nlmsg_append(msg, &iim, sizeof(iim), 0);
884 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
885 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
887 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
888 goto nla_put_failure;
890 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
892 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
893 goto nla_put_failure;
895 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
897 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
898 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
900 if(cfg->proto == VLAN_PROTO_8021AD)
901 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);
904 nla_nest_end(msg, data);
905 nla_nest_end(msg, linkinfo);
907 rv = system_rtnl_call(msg);
909 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
918 int system_vlandev_del(struct device *vlandev)
920 return system_link_del(vlandev->ifname);
924 system_if_get_settings(struct device *dev, struct device_settings *s)
929 memset(&ifr, 0, sizeof(ifr));
930 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
932 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
933 s->mtu = ifr.ifr_mtu;
934 s->flags |= DEV_OPT_MTU;
937 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
938 s->txqueuelen = ifr.ifr_qlen;
939 s->flags |= DEV_OPT_TXQUEUELEN;
942 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
943 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
944 s->flags |= DEV_OPT_MACADDR;
947 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
948 s->ipv6 = !strtoul(buf, NULL, 0);
949 s->flags |= DEV_OPT_IPV6;
952 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
953 s->promisc = ifr.ifr_flags & IFF_PROMISC;
954 s->flags |= DEV_OPT_PROMISC;
959 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
966 memset(&ifr, 0, sizeof(ifr));
967 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
968 if (s->flags & DEV_OPT_MTU & apply_mask) {
969 ifr.ifr_mtu = s->mtu;
970 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
971 s->flags &= ~DEV_OPT_MTU;
973 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
974 ifr.ifr_qlen = s->txqueuelen;
975 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
976 s->flags &= ~DEV_OPT_TXQUEUELEN;
978 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
979 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
980 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
981 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
982 s->flags &= ~DEV_OPT_MACADDR;
984 if (s->flags & DEV_OPT_IPV6 & apply_mask)
985 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
986 if (s->flags & DEV_OPT_PROMISC & apply_mask) {
987 if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
988 !s->promisc ? IFF_PROMISC : 0) < 0)
989 s->flags &= ~DEV_OPT_PROMISC;
993 int system_if_up(struct device *dev)
995 system_if_get_settings(dev, &dev->orig_settings);
996 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
997 return system_if_flags(dev->ifname, IFF_UP, 0);
1000 int system_if_down(struct device *dev)
1002 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
1003 dev->orig_settings.flags &= dev->settings.flags;
1004 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
1008 struct if_check_data {
1014 #ifndef IFF_LOWER_UP
1015 #define IFF_LOWER_UP 0x10000
1018 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1020 struct nlmsghdr *nh = nlmsg_hdr(msg);
1021 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1022 struct if_check_data *chk = (struct if_check_data *)arg;
1024 if (nh->nlmsg_type != RTM_NEWLINK)
1027 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1028 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1033 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1035 struct if_check_data *chk = (struct if_check_data *)arg;
1040 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1042 struct if_check_data *chk = (struct if_check_data *)arg;
1044 device_set_present(chk->dev, false);
1045 device_set_link(chk->dev, false);
1046 chk->pending = err->error;
1051 int system_if_check(struct device *dev)
1053 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1055 struct ifinfomsg ifi = {
1056 .ifi_family = AF_UNSPEC,
1059 struct if_check_data chk = {
1065 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1066 if (!msg || nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1067 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1070 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1071 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1072 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1074 nl_send_auto_complete(sock_rtnl, msg);
1075 while (chk.pending > 0)
1076 nl_recvmsgs(sock_rtnl, cb);
1087 system_if_get_parent(struct device *dev)
1089 char buf[64], *devname;
1090 int ifindex, iflink, len;
1093 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1094 f = fopen(buf, "r");
1098 len = fread(buf, 1, sizeof(buf) - 1, f);
1105 iflink = strtoul(buf, NULL, 0);
1106 ifindex = system_if_resolve(dev);
1107 if (!iflink || iflink == ifindex)
1110 devname = if_indextoname(iflink, buf);
1114 return device_get(devname, true);
1118 read_string_file(int dir_fd, const char *file, char *buf, int len)
1124 fd = openat(dir_fd, file, O_RDONLY);
1129 len = read(fd, buf, len - 1);
1133 } else if (len > 0) {
1136 c = strchr(buf, '\n');
1149 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1154 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1156 *val = strtoull(buf, NULL, 0);
1161 /* Assume advertised flags == supported flags */
1162 static const struct {
1165 } ethtool_link_modes[] = {
1166 { ADVERTISED_10baseT_Half, "10H" },
1167 { ADVERTISED_10baseT_Full, "10F" },
1168 { ADVERTISED_100baseT_Half, "100H" },
1169 { ADVERTISED_100baseT_Full, "100F" },
1170 { ADVERTISED_1000baseT_Half, "1000H" },
1171 { ADVERTISED_1000baseT_Full, "1000F" },
1174 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1177 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1178 if (mask & ethtool_link_modes[i].mask)
1179 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1184 system_if_force_external(const char *ifname)
1189 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1190 return stat(buf, &s) == 0;
1194 system_if_dump_info(struct device *dev, struct blob_buf *b)
1196 struct ethtool_cmd ecmd;
1202 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
1203 dir_fd = open(buf, O_DIRECTORY);
1205 memset(&ecmd, 0, sizeof(ecmd));
1206 memset(&ifr, 0, sizeof(ifr));
1207 strcpy(ifr.ifr_name, dev->ifname);
1208 ifr.ifr_data = (caddr_t) &ecmd;
1209 ecmd.cmd = ETHTOOL_GSET;
1211 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1212 c = blobmsg_open_array(b, "link-advertising");
1213 system_add_link_modes(b, ecmd.advertising);
1214 blobmsg_close_array(b, c);
1216 c = blobmsg_open_array(b, "link-supported");
1217 system_add_link_modes(b, ecmd.supported);
1218 blobmsg_close_array(b, c);
1220 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1221 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1222 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1223 blobmsg_add_string_buffer(b);
1231 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1233 const char *const counters[] = {
1234 "collisions", "rx_frame_errors", "tx_compressed",
1235 "multicast", "rx_length_errors", "tx_dropped",
1236 "rx_bytes", "rx_missed_errors", "tx_errors",
1237 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1238 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1239 "rx_dropped", "tx_aborted_errors", "tx_packets",
1240 "rx_errors", "tx_bytes", "tx_window_errors",
1241 "rx_fifo_errors", "tx_carrier_errors",
1248 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1249 stats_dir = open(buf, O_DIRECTORY);
1253 for (i = 0; i < ARRAY_SIZE(counters); i++)
1254 if (read_uint64_file(stats_dir, counters[i], &val))
1255 blobmsg_add_u64(b, counters[i], val);
1261 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1263 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1264 int alen = v4 ? 4 : 16;
1265 unsigned int flags = 0;
1266 struct ifaddrmsg ifa = {
1267 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1268 .ifa_prefixlen = addr->mask,
1269 .ifa_index = dev->ifindex,
1273 if (cmd == RTM_NEWADDR)
1274 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1276 msg = nlmsg_alloc_simple(cmd, flags);
1280 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1281 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1283 if (addr->broadcast)
1284 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1285 if (addr->point_to_point)
1286 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1288 time_t now = system_get_rtime();
1289 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1291 if (addr->preferred_until) {
1292 int64_t preferred = addr->preferred_until - now;
1295 else if (preferred > UINT32_MAX)
1296 preferred = UINT32_MAX;
1298 cinfo.ifa_prefered = preferred;
1301 if (addr->valid_until) {
1302 int64_t valid = addr->valid_until - now;
1305 else if (valid > UINT32_MAX)
1308 cinfo.ifa_valid = valid;
1311 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1314 return system_rtnl_call(msg);
1317 int system_add_address(struct device *dev, struct device_addr *addr)
1319 return system_addr(dev, addr, RTM_NEWADDR);
1322 int system_del_address(struct device *dev, struct device_addr *addr)
1324 return system_addr(dev, addr, RTM_DELADDR);
1327 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1329 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1331 unsigned int flags = 0;
1334 have_gw = !!route->nexthop.in.s_addr;
1336 have_gw = route->nexthop.in6.s6_addr32[0] ||
1337 route->nexthop.in6.s6_addr32[1] ||
1338 route->nexthop.in6.s6_addr32[2] ||
1339 route->nexthop.in6.s6_addr32[3];
1341 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1342 ? route->table : RT_TABLE_MAIN;
1344 struct rtmsg rtm = {
1345 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1346 .rtm_dst_len = route->mask,
1347 .rtm_src_len = route->sourcemask,
1348 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1349 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
1350 .rtm_scope = RT_SCOPE_NOWHERE,
1351 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1352 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1356 if (cmd == RTM_NEWROUTE) {
1357 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1359 if (!dev) { // Add null-route
1360 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1361 rtm.rtm_type = RTN_UNREACHABLE;
1364 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1367 if (route->flags & DEVROUTE_TYPE) {
1368 rtm.rtm_type = route->type;
1369 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
1370 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
1371 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
1372 rtm.rtm_table = RT_TABLE_LOCAL;
1375 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT)
1376 rtm.rtm_scope = RT_SCOPE_HOST;
1377 else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
1378 rtm.rtm_type == RTN_ANYCAST)
1379 rtm.rtm_scope = RT_SCOPE_LINK;
1382 msg = nlmsg_alloc_simple(cmd, flags);
1386 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1389 nla_put(msg, RTA_DST, alen, &route->addr);
1391 if (route->sourcemask)
1392 nla_put(msg, RTA_SRC, alen, &route->source);
1394 if (route->metric > 0)
1395 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1398 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1401 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1404 nla_put_u32(msg, RTA_TABLE, table);
1406 if (route->flags & DEVROUTE_MTU) {
1407 struct nlattr *metrics;
1409 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1410 goto nla_put_failure;
1412 nla_put_u32(msg, RTAX_MTU, route->mtu);
1414 nla_nest_end(msg, metrics);
1417 return system_rtnl_call(msg);
1424 int system_add_route(struct device *dev, struct device_route *route)
1426 return system_rt(dev, route, RTM_NEWROUTE);
1429 int system_del_route(struct device *dev, struct device_route *route)
1431 return system_rt(dev, route, RTM_DELROUTE);
1434 int system_flush_routes(void)
1436 const char *names[] = {
1437 "/proc/sys/net/ipv4/route/flush",
1438 "/proc/sys/net/ipv6/route/flush"
1442 for (i = 0; i < ARRAY_SIZE(names); i++) {
1443 fd = open(names[i], O_WRONLY);
1447 if (write(fd, "-1", 2)) {}
1453 bool system_resolve_rt_type(const char *type, unsigned int *id)
1455 return system_rtn_aton(type, id);
1458 bool system_resolve_rt_table(const char *name, unsigned int *id)
1462 unsigned int n, table = RT_TABLE_UNSPEC;
1464 /* first try to parse table as number */
1465 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1468 /* handle well known aliases */
1469 else if (!strcmp(name, "default"))
1470 table = RT_TABLE_DEFAULT;
1471 else if (!strcmp(name, "main"))
1472 table = RT_TABLE_MAIN;
1473 else if (!strcmp(name, "local"))
1474 table = RT_TABLE_LOCAL;
1476 /* try to look up name in /etc/iproute2/rt_tables */
1477 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1479 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1481 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1484 n = strtoul(e, NULL, 10);
1485 e = strtok(NULL, " \t\n");
1487 if (e && !strcmp(e, name))
1497 if (table == RT_TABLE_UNSPEC)
1504 bool system_is_default_rt_table(unsigned int id)
1506 return (id == RT_TABLE_MAIN);
1509 static int system_iprule(struct iprule *rule, int cmd)
1511 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1514 struct rtmsg rtm = {
1515 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1516 .rtm_protocol = RTPROT_STATIC,
1517 .rtm_scope = RT_SCOPE_UNIVERSE,
1518 .rtm_table = RT_TABLE_UNSPEC,
1519 .rtm_type = RTN_UNSPEC,
1523 if (cmd == RTM_NEWRULE) {
1524 rtm.rtm_type = RTN_UNICAST;
1525 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1529 rtm.rtm_flags |= FIB_RULE_INVERT;
1531 if (rule->flags & IPRULE_SRC)
1532 rtm.rtm_src_len = rule->src_mask;
1534 if (rule->flags & IPRULE_DEST)
1535 rtm.rtm_dst_len = rule->dest_mask;
1537 if (rule->flags & IPRULE_TOS)
1538 rtm.rtm_tos = rule->tos;
1540 if (rule->flags & IPRULE_LOOKUP) {
1541 if (rule->lookup < 256)
1542 rtm.rtm_table = rule->lookup;
1545 if (rule->flags & IPRULE_ACTION)
1546 rtm.rtm_type = rule->action;
1547 else if (rule->flags & IPRULE_GOTO)
1548 rtm.rtm_type = FR_ACT_GOTO;
1549 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1550 rtm.rtm_type = FR_ACT_NOP;
1552 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1557 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1559 if (rule->flags & IPRULE_IN)
1560 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1562 if (rule->flags & IPRULE_OUT)
1563 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1565 if (rule->flags & IPRULE_SRC)
1566 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1568 if (rule->flags & IPRULE_DEST)
1569 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1571 if (rule->flags & IPRULE_PRIORITY)
1572 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1573 else if (cmd == RTM_NEWRULE)
1574 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1576 if (rule->flags & IPRULE_FWMARK)
1577 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1579 if (rule->flags & IPRULE_FWMASK)
1580 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1582 if (rule->flags & IPRULE_LOOKUP) {
1583 if (rule->lookup >= 256)
1584 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1587 if (rule->flags & IPRULE_GOTO)
1588 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1590 return system_rtnl_call(msg);
1593 int system_add_iprule(struct iprule *rule)
1595 return system_iprule(rule, RTM_NEWRULE);
1598 int system_del_iprule(struct iprule *rule)
1600 return system_iprule(rule, RTM_DELRULE);
1603 int system_flush_iprules(void)
1608 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1609 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1611 memset(&rule, 0, sizeof(rule));
1614 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1617 rule.lookup = RT_TABLE_LOCAL;
1618 rv |= system_iprule(&rule, RTM_NEWRULE);
1620 rule.priority = 32766;
1621 rule.lookup = RT_TABLE_MAIN;
1622 rv |= system_iprule(&rule, RTM_NEWRULE);
1624 rule.priority = 32767;
1625 rule.lookup = RT_TABLE_DEFAULT;
1626 rv |= system_iprule(&rule, RTM_NEWRULE);
1629 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1632 rule.lookup = RT_TABLE_LOCAL;
1633 rv |= system_iprule(&rule, RTM_NEWRULE);
1635 rule.priority = 32766;
1636 rule.lookup = RT_TABLE_MAIN;
1637 rv |= system_iprule(&rule, RTM_NEWRULE);
1642 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1644 return system_rtn_aton(action, id);
1647 time_t system_get_rtime(void)
1652 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1655 if (gettimeofday(&tv, NULL) == 0)
1662 #define IP_DF 0x4000
1665 static int tunnel_ioctl(const char *name, int cmd, void *p)
1669 memset(&ifr, 0, sizeof(ifr));
1670 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1671 ifr.ifr_ifru.ifru_data = p;
1672 return ioctl(sock_ioctl, cmd, &ifr);
1675 #ifdef IFLA_IPTUN_MAX
1676 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
1677 static int system_add_gre_tunnel(const char *name, const char *kind,
1678 const unsigned int link, struct blob_attr **tb, bool v6)
1681 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
1682 struct blob_attr *cur;
1683 uint32_t ikey = 0, okey = 0, flags = 0, flowinfo = 0;
1684 uint16_t iflags = 0, oflags = 0;
1686 int ret = 0, ttl = 64;
1688 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
1692 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
1693 nla_put_string(nlm, IFLA_IFNAME, name);
1695 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
1701 nla_put_string(nlm, IFLA_INFO_KIND, kind);
1702 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
1709 nla_put_u32(nlm, IFLA_GRE_LINK, link);
1711 if ((cur = tb[TUNNEL_ATTR_TTL]))
1712 ttl = blobmsg_get_u32(cur);
1714 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
1716 if ((cur = tb[TUNNEL_ATTR_TOS])) {
1717 char *str = blobmsg_get_string(cur);
1718 if (strcmp(str, "inherit")) {
1721 if (!system_tos_aton(str, &uval)) {
1727 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
1732 flags |= IP6_TNL_F_USE_ORIG_TCLASS;
1738 if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) {
1739 uint8_t icsum, ocsum, iseqno, oseqno;
1740 if (sscanf(blobmsg_get_string(cur), "%u,%u,%hhu,%hhu,%hhu,%hhu",
1741 &ikey, &okey, &icsum, &ocsum, &iseqno, &oseqno) < 6) {
1766 struct in6_addr in6buf;
1767 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1768 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1772 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
1775 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
1776 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1780 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
1782 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, 4);
1785 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
1788 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags);
1790 struct in_addr inbuf;
1793 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1794 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
1798 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
1801 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
1802 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
1806 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
1808 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
1810 okey = inbuf.s_addr;
1815 ikey = inbuf.s_addr;
1821 if ((cur = tb[TUNNEL_ATTR_DF]))
1822 set_df = blobmsg_get_bool(cur);
1824 /* ttl !=0 and nopmtudisc are incompatible */
1825 if (ttl && !set_df) {
1830 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
1832 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
1836 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
1839 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
1842 nla_put_u32(nlm, IFLA_GRE_OKEY, okey);
1845 nla_put_u32(nlm, IFLA_GRE_IKEY, ikey);
1847 nla_nest_end(nlm, infodata);
1848 nla_nest_end(nlm, linkinfo);
1850 return system_rtnl_call(nlm);
1858 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
1860 struct blob_attr *cur;
1862 struct ip_tunnel_parm p = {
1871 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
1872 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
1875 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
1876 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
1879 if ((cur = tb[TUNNEL_ATTR_DF]))
1880 set_df = blobmsg_get_bool(cur);
1882 if ((cur = tb[TUNNEL_ATTR_TTL]))
1883 p.iph.ttl = blobmsg_get_u32(cur);
1885 if ((cur = tb[TUNNEL_ATTR_TOS])) {
1886 char *str = blobmsg_get_string(cur);
1887 if (strcmp(str, "inherit")) {
1890 if (!system_tos_aton(str, &uval))
1898 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
1899 /* ttl !=0 and nopmtudisc are incompatible */
1900 if (p.iph.ttl && p.iph.frag_off == 0)
1903 strncpy(p.name, name, sizeof(p.name));
1905 switch (p.iph.protocol) {
1907 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
1909 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
1916 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
1918 struct blob_attr *cur;
1921 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
1923 str = blobmsg_data(cur);
1925 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
1926 !strcmp(str, "greip6") || !strcmp(str, "gretapip6"))
1927 return system_link_del(name);
1929 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
1932 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
1934 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
1936 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
1937 blob_data(attr), blob_len(attr));
1939 return __system_del_ip_tunnel(name, tb);
1942 int system_update_ipv6_mtu(struct device *dev, int mtu)
1946 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
1949 int fd = open(buf, O_RDWR);
1950 ssize_t len = read(fd, buf, sizeof(buf) - 1);
1957 if (!mtu || ret <= mtu)
1960 lseek(fd, 0, SEEK_SET);
1961 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) <= 0)
1969 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
1971 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
1972 struct blob_attr *cur;
1975 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
1976 blob_data(attr), blob_len(attr));
1978 __system_del_ip_tunnel(name, tb);
1980 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
1982 str = blobmsg_data(cur);
1984 unsigned int ttl = 0;
1985 if ((cur = tb[TUNNEL_ATTR_TTL])) {
1986 ttl = blobmsg_get_u32(cur);
1991 unsigned int link = 0;
1992 if ((cur = tb[TUNNEL_ATTR_LINK])) {
1993 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
1997 if (iface->l3_dev.dev)
1998 link = iface->l3_dev.dev->ifindex;
2001 if (!strcmp(str, "sit")) {
2002 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
2006 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
2008 struct ip_tunnel_6rd p6;
2010 memset(&p6, 0, sizeof(p6));
2012 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
2013 &p6.prefix, &mask) || mask > 128)
2015 p6.prefixlen = mask;
2017 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
2018 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
2019 &p6.relay_prefix, &mask) || mask > 32)
2021 p6.relay_prefixlen = mask;
2024 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
2025 __system_del_ip_tunnel(name, tb);
2030 #ifdef IFLA_IPTUN_MAX
2031 } else if (!strcmp(str, "ipip6")) {
2032 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2033 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2034 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2040 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2041 nla_put_string(nlm, IFLA_IFNAME, name);
2044 nla_put_u32(nlm, IFLA_LINK, link);
2046 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2051 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2052 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2059 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2061 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2062 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2063 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
2065 struct in6_addr in6buf;
2066 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2067 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2071 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2074 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2075 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2079 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2082 #ifdef IFLA_IPTUN_FMR_MAX
2083 if ((cur = tb[TUNNEL_ATTR_FMRS])) {
2084 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2086 struct blob_attr *fmr;
2087 unsigned rem, fmrcnt = 0;
2088 blobmsg_for_each_attr(fmr, cur, rem) {
2089 if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
2092 unsigned ip4len, ip6len, ealen, offset = 6;
2096 if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
2097 ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) {
2102 struct in6_addr ip6prefix;
2103 struct in_addr ip4prefix;
2104 if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
2105 inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) {
2110 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2112 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2113 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2114 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2115 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2116 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2117 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2119 nla_nest_end(nlm, rule);
2122 nla_nest_end(nlm, fmrs);
2126 nla_nest_end(nlm, infodata);
2127 nla_nest_end(nlm, linkinfo);
2129 return system_rtnl_call(nlm);
2133 } else if (!strcmp(str, "greip")) {
2134 return system_add_gre_tunnel(name, "gre", link, tb, false);
2135 } else if (!strcmp(str, "gretapip")) {
2136 return system_add_gre_tunnel(name, "gretap", link, tb, false);
2137 } else if (!strcmp(str, "greip6")) {
2138 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
2139 } else if (!strcmp(str, "gretapip6")) {
2140 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
2142 } else if (!strcmp(str, "ipip")) {
2143 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);