2 * netifd - network interface daemon
3 * Copyright (C) 2012 Felix Fietkau <nbd@openwrt.org>
4 * Copyright (C) 2013 Jo-Philipp Wich <jow@openwrt.org>
5 * Copyright (C) 2013 Steven Barth <steven@midlink.org>
6 * Copyright (C) 2014 Gioacchino Mazzurco <gio@eigenlab.org>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2
10 * as published by the Free Software Foundation
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
19 #include <sys/socket.h>
20 #include <sys/ioctl.h>
22 #include <sys/syscall.h>
25 #include <net/if_arp.h>
27 #include <arpa/inet.h>
28 #include <netinet/in.h>
30 #include <linux/rtnetlink.h>
31 #include <linux/sockios.h>
33 #include <linux/if_link.h>
34 #include <linux/if_vlan.h>
35 #include <linux/if_bridge.h>
36 #include <linux/if_tunnel.h>
37 #include <linux/ip6_tunnel.h>
38 #include <linux/ethtool.h>
39 #include <linux/fib_rules.h>
40 #include <linux/version.h>
42 #ifndef RTN_FAILED_POLICY
43 #define RTN_FAILED_POLICY 12
51 #include <netlink/msg.h>
52 #include <netlink/attr.h>
53 #include <netlink/socket.h>
54 #include <libubox/uloop.h>
61 struct uloop_fd uloop;
66 static int sock_ioctl = -1;
67 static struct nl_sock *sock_rtnl = NULL;
69 static int cb_rtnl_event(struct nl_msg *msg, void *arg);
70 static void handle_hotplug_event(struct uloop_fd *u, unsigned int events);
72 static char dev_buf[256];
75 handler_nl_event(struct uloop_fd *u, unsigned int events)
77 struct event_socket *ev = container_of(u, struct event_socket, uloop);
79 socklen_t errlen = sizeof(err);
82 nl_recvmsgs_default(ev->sock);
86 if (getsockopt(u->fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen))
91 // Increase rx buffer size on netlink socket
93 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
96 // Request full dump since some info got dropped
97 struct rtgenmsg msg = { .rtgen_family = AF_UNSPEC };
98 nl_send_simple(ev->sock, RTM_GETLINK, NLM_F_DUMP, &msg, sizeof(msg));
108 uloop_fd_delete(&ev->uloop);
112 static struct nl_sock *
113 create_socket(int protocol, int groups)
115 struct nl_sock *sock;
117 sock = nl_socket_alloc();
122 nl_join_groups(sock, groups);
124 if (nl_connect(sock, protocol))
131 create_raw_event_socket(struct event_socket *ev, int protocol, int groups,
132 uloop_fd_handler cb, int flags)
134 ev->sock = create_socket(protocol, groups);
138 ev->uloop.fd = nl_socket_get_fd(ev->sock);
140 if (uloop_fd_add(&ev->uloop, ULOOP_READ|flags))
147 create_event_socket(struct event_socket *ev, int protocol,
148 int (*cb)(struct nl_msg *msg, void *arg))
150 if (!create_raw_event_socket(ev, protocol, 0, handler_nl_event, ULOOP_ERROR_CB))
153 // Install the valid custom callback handler
154 nl_socket_modify_cb(ev->sock, NL_CB_VALID, NL_CB_CUSTOM, cb, NULL);
156 // Disable sequence number checking on event sockets
157 nl_socket_disable_seq_check(ev->sock);
159 // Increase rx buffer size to 65K on event sockets
161 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
168 system_rtn_aton(const char *src, unsigned int *dst)
173 if (!strcmp(src, "local"))
175 else if (!strcmp(src, "nat"))
177 else if (!strcmp(src, "broadcast"))
179 else if (!strcmp(src, "anycast"))
181 else if (!strcmp(src, "multicast"))
183 else if (!strcmp(src, "prohibit"))
185 else if (!strcmp(src, "unreachable"))
187 else if (!strcmp(src, "blackhole"))
189 else if (!strcmp(src, "xresolve"))
191 else if (!strcmp(src, "unicast"))
193 else if (!strcmp(src, "throw"))
195 else if (!strcmp(src, "failed_policy"))
196 n = RTN_FAILED_POLICY;
198 n = strtoul(src, &e, 0);
199 if (!e || *e || e == src || n > 255)
208 system_tos_aton(const char *src, unsigned *dst)
212 *dst = strtoul(src, &e, 16);
213 if (e == src || *e || *dst > 255)
219 int system_init(void)
221 static struct event_socket rtnl_event;
222 static struct event_socket hotplug_event;
224 sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0);
225 system_fd_set_cloexec(sock_ioctl);
227 // Prepare socket for routing / address control
228 sock_rtnl = create_socket(NETLINK_ROUTE, 0);
232 if (!create_event_socket(&rtnl_event, NETLINK_ROUTE, cb_rtnl_event))
235 if (!create_raw_event_socket(&hotplug_event, NETLINK_KOBJECT_UEVENT, 1,
236 handle_hotplug_event, 0))
239 // Receive network link events form kernel
240 nl_socket_add_membership(rtnl_event.sock, RTNLGRP_LINK);
245 static void system_set_sysctl(const char *path, const char *val)
249 fd = open(path, O_WRONLY);
253 if (write(fd, val, strlen(val))) {}
257 static void system_set_dev_sysctl(const char *path, const char *device, const char *val)
259 snprintf(dev_buf, sizeof(dev_buf), path, device);
260 system_set_sysctl(dev_buf, val);
263 static void system_set_disable_ipv6(struct device *dev, const char *val)
265 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val);
268 static void system_set_rpfilter(struct device *dev, const char *val)
270 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter", dev->ifname, val);
273 static void system_set_acceptlocal(struct device *dev, const char *val)
275 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local", dev->ifname, val);
278 static int system_get_sysctl(const char *path, char *buf, const size_t buf_sz)
280 int fd = -1, ret = -1;
282 fd = open(path, O_RDONLY);
286 ssize_t len = read(fd, buf, buf_sz - 1);
300 system_get_dev_sysctl(const char *path, const char *device, char *buf, const size_t buf_sz)
302 snprintf(dev_buf, sizeof(dev_buf), path, device);
303 return system_get_sysctl(dev_buf, buf, buf_sz);
306 static int system_get_disable_ipv6(struct device *dev, char *buf, const size_t buf_sz)
308 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6",
309 dev->ifname, buf, buf_sz);
312 static int system_get_rpfilter(struct device *dev, char *buf, const size_t buf_sz)
314 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter",
315 dev->ifname, buf, buf_sz);
318 static int system_get_acceptlocal(struct device *dev, char *buf, const size_t buf_sz)
320 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local",
321 dev->ifname, buf, buf_sz);
324 // Evaluate netlink messages
325 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
327 struct nlmsghdr *nh = nlmsg_hdr(msg);
328 struct ifinfomsg *ifi = NLMSG_DATA(nh);
329 struct nlattr *nla[__IFLA_MAX];
333 if (nh->nlmsg_type != RTM_NEWLINK)
336 nlmsg_parse(nh, sizeof(*ifi), nla, __IFLA_MAX - 1, NULL);
337 if (!nla[IFLA_IFNAME])
340 struct device *dev = device_get(nla_data(nla[IFLA_IFNAME]), false);
341 if (!dev || dev->type->keep_link_status)
344 if (!system_get_dev_sysctl("/sys/class/net/%s/carrier", dev->ifname, buf, sizeof(buf)))
345 link_state = strtoul(buf, NULL, 0);
347 device_set_link(dev, link_state ? true : false);
354 handle_hotplug_msg(char *data, int size)
356 const char *subsystem = NULL, *interface = NULL;
357 char *cur, *end, *sep;
362 if (!strncmp(data, "add@", 4))
364 else if (!strncmp(data, "remove@", 7))
369 skip = strlen(data) + 1;
372 for (cur = data + skip; cur < end; cur += skip) {
373 skip = strlen(cur) + 1;
375 sep = strchr(cur, '=');
380 if (!strcmp(cur, "INTERFACE"))
382 else if (!strcmp(cur, "SUBSYSTEM")) {
384 if (strcmp(subsystem, "net") != 0)
387 if (subsystem && interface)
393 dev = device_get(interface, false);
397 if (dev->type != &simple_device_type)
400 if (add && system_if_force_external(dev->ifname))
403 device_set_present(dev, add);
407 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
409 struct event_socket *ev = container_of(u, struct event_socket, uloop);
410 struct sockaddr_nl nla;
411 unsigned char *buf = NULL;
414 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
416 handle_hotplug_msg((char *) buf, size);
422 static int system_rtnl_call(struct nl_msg *msg)
426 ret = nl_send_auto_complete(sock_rtnl, msg);
432 return nl_wait_for_ack(sock_rtnl);
435 int system_bridge_delbr(struct device *bridge)
437 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
440 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
444 memset(&ifr, 0, sizeof(ifr));
446 ifr.ifr_ifindex = dev->ifindex;
449 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
450 return ioctl(sock_ioctl, cmd, &ifr);
453 static bool system_is_bridge(const char *name, char *buf, int buflen)
457 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
458 if (stat(buf, &st) < 0)
464 static char *system_get_bridge(const char *name, char *buf, int buflen)
470 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
471 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
475 len = readlink(gl.gl_pathv[0], buf, buflen);
483 path = strrchr(buf, '/');
490 static void system_bridge_set_wireless(const char *bridge, const char *dev)
492 snprintf(dev_buf, sizeof(dev_buf),
493 "/sys/devices/virtual/net/%s/brif/%s/multicast_to_unicast",
495 system_set_sysctl(dev_buf, "1");
498 int system_bridge_addif(struct device *bridge, struct device *dev)
503 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
504 if (!oldbr || strcmp(oldbr, bridge->ifname) != 0)
505 ret = system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
508 system_bridge_set_wireless(bridge->ifname, dev->ifname);
513 int system_bridge_delif(struct device *bridge, struct device *dev)
515 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
518 int system_if_resolve(struct device *dev)
521 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
522 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
523 return ifr.ifr_ifindex;
528 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
532 memset(&ifr, 0, sizeof(ifr));
533 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
534 ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
535 ifr.ifr_flags |= add;
536 ifr.ifr_flags &= ~rem;
537 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
549 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
551 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
553 return ifa->ifa_index == ifindex;
556 static bool check_route(struct nlmsghdr *hdr, int ifindex)
558 struct rtmsg *r = NLMSG_DATA(hdr);
559 struct nlattr *tb[__RTA_MAX];
561 if (r->rtm_protocol == RTPROT_KERNEL &&
562 r->rtm_family == AF_INET6)
565 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
569 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
572 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
577 static int cb_clear_event(struct nl_msg *msg, void *arg)
579 struct clear_data *clr = arg;
580 struct nlmsghdr *hdr = nlmsg_hdr(msg);
581 bool (*cb)(struct nlmsghdr *, int ifindex);
587 if (hdr->nlmsg_type != RTM_NEWADDR)
594 if (hdr->nlmsg_type != RTM_NEWROUTE)
601 if (hdr->nlmsg_type != RTM_NEWRULE)
610 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
613 if (type == RTM_DELRULE)
614 D(SYSTEM, "Remove a rule\n");
616 D(SYSTEM, "Remove %s from device %s\n",
617 type == RTM_DELADDR ? "an address" : "a route",
619 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
620 hdr = nlmsg_hdr(clr->msg);
621 hdr->nlmsg_type = type;
622 hdr->nlmsg_flags = NLM_F_REQUEST;
624 nl_socket_disable_auto_ack(sock_rtnl);
625 nl_send_auto_complete(sock_rtnl, clr->msg);
626 nl_socket_enable_auto_ack(sock_rtnl);
632 cb_finish_event(struct nl_msg *msg, void *arg)
640 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
643 *pending = err->error;
648 system_if_clear_entries(struct device *dev, int type, int af)
650 struct clear_data clr;
651 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
654 .rtm_flags = RTM_F_CLONED,
656 int flags = NLM_F_DUMP;
665 clr.size = sizeof(struct rtgenmsg);
668 clr.size = sizeof(struct rtmsg);
677 clr.msg = nlmsg_alloc_simple(type, flags);
681 nlmsg_append(clr.msg, &rtm, clr.size, 0);
682 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
683 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
684 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
686 nl_send_auto_complete(sock_rtnl, clr.msg);
688 nl_recvmsgs(sock_rtnl, cb);
696 * Clear bridge (membership) state and bring down device
698 void system_if_clear_state(struct device *dev)
700 static char buf[256];
703 device_set_ifindex(dev, system_if_resolve(dev));
704 if (dev->external || !dev->ifindex)
707 system_if_flags(dev->ifname, 0, IFF_UP);
709 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
710 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
711 system_bridge_delbr(dev);
715 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
717 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
718 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
721 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
722 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
723 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
724 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
725 system_set_disable_ipv6(dev, "0");
728 static inline unsigned long
729 sec_to_jiffies(int val)
731 return (unsigned long) val * 100;
734 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
736 unsigned long args[4] = {};
738 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
741 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
742 args[1] = !!cfg->stp;
743 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
745 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
746 args[1] = sec_to_jiffies(cfg->forward_delay);
747 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
749 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
750 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
752 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier",
753 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
755 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
756 args[1] = cfg->priority;
757 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
759 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
760 args[0] = BRCTL_SET_AGEING_TIME;
761 args[1] = sec_to_jiffies(cfg->ageing_time);
762 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
765 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
766 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
767 args[1] = sec_to_jiffies(cfg->hello_time);
768 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
771 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
772 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
773 args[1] = sec_to_jiffies(cfg->max_age);
774 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
780 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
783 struct nlattr *linkinfo, *data;
784 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
786 static const struct {
788 enum macvlan_mode val;
790 { "private", MACVLAN_MODE_PRIVATE },
791 { "vepa", MACVLAN_MODE_VEPA },
792 { "bridge", MACVLAN_MODE_BRIDGE },
793 { "passthru", MACVLAN_MODE_PASSTHRU },
796 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
801 nlmsg_append(msg, &iim, sizeof(iim), 0);
803 if (cfg->flags & MACVLAN_OPT_MACADDR)
804 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
805 nla_put_string(msg, IFLA_IFNAME, macvlan->ifname);
806 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
808 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
809 goto nla_put_failure;
811 nla_put_string(msg, IFLA_INFO_KIND, "macvlan");
813 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
814 goto nla_put_failure;
817 for (i = 0; i < ARRAY_SIZE(modes); i++) {
818 if (strcmp(cfg->mode, modes[i].name) != 0)
821 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
826 nla_nest_end(msg, data);
827 nla_nest_end(msg, linkinfo);
829 rv = system_rtnl_call(msg);
831 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
840 static int system_link_del(const char *ifname)
843 struct ifinfomsg iim = {
844 .ifi_family = AF_UNSPEC,
848 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
853 nlmsg_append(msg, &iim, sizeof(iim), 0);
854 nla_put_string(msg, IFLA_IFNAME, ifname);
855 return system_rtnl_call(msg);
858 int system_macvlan_del(struct device *macvlan)
860 return system_link_del(macvlan->ifname);
863 static int system_vlan(struct device *dev, int id)
865 struct vlan_ioctl_args ifr = {
866 .cmd = SET_VLAN_NAME_TYPE_CMD,
867 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
870 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
873 ifr.cmd = DEL_VLAN_CMD;
876 ifr.cmd = ADD_VLAN_CMD;
879 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
880 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
883 int system_vlan_add(struct device *dev, int id)
885 return system_vlan(dev, id);
888 int system_vlan_del(struct device *dev)
890 return system_vlan(dev, -1);
893 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
896 struct nlattr *linkinfo, *data;
897 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
900 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
905 nlmsg_append(msg, &iim, sizeof(iim), 0);
906 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
907 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
909 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
910 goto nla_put_failure;
912 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
914 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
915 goto nla_put_failure;
917 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
919 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
920 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
922 if(cfg->proto == VLAN_PROTO_8021AD)
923 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);
926 nla_nest_end(msg, data);
927 nla_nest_end(msg, linkinfo);
929 rv = system_rtnl_call(msg);
931 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
940 int system_vlandev_del(struct device *vlandev)
942 return system_link_del(vlandev->ifname);
946 system_if_get_settings(struct device *dev, struct device_settings *s)
951 memset(&ifr, 0, sizeof(ifr));
952 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
954 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
955 s->mtu = ifr.ifr_mtu;
956 s->flags |= DEV_OPT_MTU;
959 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
960 s->txqueuelen = ifr.ifr_qlen;
961 s->flags |= DEV_OPT_TXQUEUELEN;
964 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
965 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
966 s->flags |= DEV_OPT_MACADDR;
969 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
970 s->ipv6 = !strtoul(buf, NULL, 0);
971 s->flags |= DEV_OPT_IPV6;
974 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
975 s->promisc = ifr.ifr_flags & IFF_PROMISC;
976 s->flags |= DEV_OPT_PROMISC;
979 if (!system_get_rpfilter(dev, buf, sizeof(buf))) {
980 s->rpfilter = strtoul(buf, NULL, 0);
981 s->flags |= DEV_OPT_RPFILTER;
984 if (!system_get_acceptlocal(dev, buf, sizeof(buf))) {
985 s->acceptlocal = strtoul(buf, NULL, 0);
986 s->flags |= DEV_OPT_ACCEPTLOCAL;
991 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
998 memset(&ifr, 0, sizeof(ifr));
999 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1000 if (s->flags & DEV_OPT_MTU & apply_mask) {
1001 ifr.ifr_mtu = s->mtu;
1002 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
1003 s->flags &= ~DEV_OPT_MTU;
1005 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
1006 ifr.ifr_qlen = s->txqueuelen;
1007 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
1008 s->flags &= ~DEV_OPT_TXQUEUELEN;
1010 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
1011 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
1012 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
1013 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
1014 s->flags &= ~DEV_OPT_MACADDR;
1016 if (s->flags & DEV_OPT_IPV6 & apply_mask)
1017 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
1018 if (s->flags & DEV_OPT_PROMISC & apply_mask) {
1019 if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
1020 !s->promisc ? IFF_PROMISC : 0) < 0)
1021 s->flags &= ~DEV_OPT_PROMISC;
1023 if (s->flags & DEV_OPT_RPFILTER & apply_mask) {
1026 snprintf(buf, sizeof(buf), "%d", s->rpfilter);
1027 system_set_rpfilter(dev, buf);
1029 if (s->flags & DEV_OPT_ACCEPTLOCAL & apply_mask)
1030 system_set_acceptlocal(dev, s->acceptlocal ? "1" : "0");
1033 int system_if_up(struct device *dev)
1035 system_if_get_settings(dev, &dev->orig_settings);
1036 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
1037 return system_if_flags(dev->ifname, IFF_UP, 0);
1040 int system_if_down(struct device *dev)
1042 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
1043 dev->orig_settings.flags &= dev->settings.flags;
1044 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
1048 struct if_check_data {
1054 #ifndef IFF_LOWER_UP
1055 #define IFF_LOWER_UP 0x10000
1058 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1060 struct nlmsghdr *nh = nlmsg_hdr(msg);
1061 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1062 struct if_check_data *chk = (struct if_check_data *)arg;
1064 if (nh->nlmsg_type != RTM_NEWLINK)
1067 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1068 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1073 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1075 struct if_check_data *chk = (struct if_check_data *)arg;
1080 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1082 struct if_check_data *chk = (struct if_check_data *)arg;
1084 device_set_present(chk->dev, false);
1085 device_set_link(chk->dev, false);
1086 chk->pending = err->error;
1091 int system_if_check(struct device *dev)
1093 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1095 struct ifinfomsg ifi = {
1096 .ifi_family = AF_UNSPEC,
1099 struct if_check_data chk = {
1105 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1106 if (!msg || nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1107 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1110 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1111 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1112 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1114 nl_send_auto_complete(sock_rtnl, msg);
1115 while (chk.pending > 0)
1116 nl_recvmsgs(sock_rtnl, cb);
1127 system_if_get_parent(struct device *dev)
1129 char buf[64], *devname;
1130 int ifindex, iflink, len;
1133 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1134 f = fopen(buf, "r");
1138 len = fread(buf, 1, sizeof(buf) - 1, f);
1145 iflink = strtoul(buf, NULL, 0);
1146 ifindex = system_if_resolve(dev);
1147 if (!iflink || iflink == ifindex)
1150 devname = if_indextoname(iflink, buf);
1154 return device_get(devname, true);
1158 read_string_file(int dir_fd, const char *file, char *buf, int len)
1164 fd = openat(dir_fd, file, O_RDONLY);
1169 len = read(fd, buf, len - 1);
1173 } else if (len > 0) {
1176 c = strchr(buf, '\n');
1189 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1194 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1196 *val = strtoull(buf, NULL, 0);
1201 /* Assume advertised flags == supported flags */
1202 static const struct {
1205 } ethtool_link_modes[] = {
1206 { ADVERTISED_10baseT_Half, "10H" },
1207 { ADVERTISED_10baseT_Full, "10F" },
1208 { ADVERTISED_100baseT_Half, "100H" },
1209 { ADVERTISED_100baseT_Full, "100F" },
1210 { ADVERTISED_1000baseT_Half, "1000H" },
1211 { ADVERTISED_1000baseT_Full, "1000F" },
1214 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1217 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1218 if (mask & ethtool_link_modes[i].mask)
1219 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1224 system_if_force_external(const char *ifname)
1229 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1230 return stat(buf, &s) == 0;
1234 system_if_dump_info(struct device *dev, struct blob_buf *b)
1236 struct ethtool_cmd ecmd;
1242 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
1243 dir_fd = open(buf, O_DIRECTORY);
1245 memset(&ecmd, 0, sizeof(ecmd));
1246 memset(&ifr, 0, sizeof(ifr));
1247 strcpy(ifr.ifr_name, dev->ifname);
1248 ifr.ifr_data = (caddr_t) &ecmd;
1249 ecmd.cmd = ETHTOOL_GSET;
1251 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1252 c = blobmsg_open_array(b, "link-advertising");
1253 system_add_link_modes(b, ecmd.advertising);
1254 blobmsg_close_array(b, c);
1256 c = blobmsg_open_array(b, "link-supported");
1257 system_add_link_modes(b, ecmd.supported);
1258 blobmsg_close_array(b, c);
1260 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1261 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1262 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1263 blobmsg_add_string_buffer(b);
1271 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1273 const char *const counters[] = {
1274 "collisions", "rx_frame_errors", "tx_compressed",
1275 "multicast", "rx_length_errors", "tx_dropped",
1276 "rx_bytes", "rx_missed_errors", "tx_errors",
1277 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1278 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1279 "rx_dropped", "tx_aborted_errors", "tx_packets",
1280 "rx_errors", "tx_bytes", "tx_window_errors",
1281 "rx_fifo_errors", "tx_carrier_errors",
1288 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1289 stats_dir = open(buf, O_DIRECTORY);
1293 for (i = 0; i < ARRAY_SIZE(counters); i++)
1294 if (read_uint64_file(stats_dir, counters[i], &val))
1295 blobmsg_add_u64(b, counters[i], val);
1301 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1303 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1304 int alen = v4 ? 4 : 16;
1305 unsigned int flags = 0;
1306 struct ifaddrmsg ifa = {
1307 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1308 .ifa_prefixlen = addr->mask,
1309 .ifa_index = dev->ifindex,
1313 if (cmd == RTM_NEWADDR)
1314 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1316 msg = nlmsg_alloc_simple(cmd, flags);
1320 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1321 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1323 if (addr->broadcast)
1324 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1325 if (addr->point_to_point)
1326 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1328 time_t now = system_get_rtime();
1329 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1331 if (addr->preferred_until) {
1332 int64_t preferred = addr->preferred_until - now;
1335 else if (preferred > UINT32_MAX)
1336 preferred = UINT32_MAX;
1338 cinfo.ifa_prefered = preferred;
1341 if (addr->valid_until) {
1342 int64_t valid = addr->valid_until - now;
1345 else if (valid > UINT32_MAX)
1348 cinfo.ifa_valid = valid;
1351 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1354 return system_rtnl_call(msg);
1357 int system_add_address(struct device *dev, struct device_addr *addr)
1359 return system_addr(dev, addr, RTM_NEWADDR);
1362 int system_del_address(struct device *dev, struct device_addr *addr)
1364 return system_addr(dev, addr, RTM_DELADDR);
1367 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1369 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1371 unsigned int flags = 0;
1374 have_gw = !!route->nexthop.in.s_addr;
1376 have_gw = route->nexthop.in6.s6_addr32[0] ||
1377 route->nexthop.in6.s6_addr32[1] ||
1378 route->nexthop.in6.s6_addr32[2] ||
1379 route->nexthop.in6.s6_addr32[3];
1381 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1382 ? route->table : RT_TABLE_MAIN;
1384 struct rtmsg rtm = {
1385 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1386 .rtm_dst_len = route->mask,
1387 .rtm_src_len = route->sourcemask,
1388 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1389 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
1390 .rtm_scope = RT_SCOPE_NOWHERE,
1391 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1392 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1396 if (cmd == RTM_NEWROUTE) {
1397 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1399 if (!dev) { // Add null-route
1400 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1401 rtm.rtm_type = RTN_UNREACHABLE;
1404 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1407 if (route->flags & DEVROUTE_TYPE) {
1408 rtm.rtm_type = route->type;
1409 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
1410 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
1411 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
1412 rtm.rtm_table = RT_TABLE_LOCAL;
1415 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT)
1416 rtm.rtm_scope = RT_SCOPE_HOST;
1417 else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
1418 rtm.rtm_type == RTN_ANYCAST)
1419 rtm.rtm_scope = RT_SCOPE_LINK;
1422 msg = nlmsg_alloc_simple(cmd, flags);
1426 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1429 nla_put(msg, RTA_DST, alen, &route->addr);
1431 if (route->sourcemask)
1432 nla_put(msg, RTA_SRC, alen, &route->source);
1434 if (route->metric > 0)
1435 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1438 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1441 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1444 nla_put_u32(msg, RTA_TABLE, table);
1446 if (route->flags & DEVROUTE_MTU) {
1447 struct nlattr *metrics;
1449 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1450 goto nla_put_failure;
1452 nla_put_u32(msg, RTAX_MTU, route->mtu);
1454 nla_nest_end(msg, metrics);
1457 return system_rtnl_call(msg);
1464 int system_add_route(struct device *dev, struct device_route *route)
1466 return system_rt(dev, route, RTM_NEWROUTE);
1469 int system_del_route(struct device *dev, struct device_route *route)
1471 return system_rt(dev, route, RTM_DELROUTE);
1474 int system_flush_routes(void)
1476 const char *names[] = {
1477 "/proc/sys/net/ipv4/route/flush",
1478 "/proc/sys/net/ipv6/route/flush"
1482 for (i = 0; i < ARRAY_SIZE(names); i++) {
1483 fd = open(names[i], O_WRONLY);
1487 if (write(fd, "-1", 2)) {}
1493 bool system_resolve_rt_type(const char *type, unsigned int *id)
1495 return system_rtn_aton(type, id);
1498 bool system_resolve_rt_table(const char *name, unsigned int *id)
1502 unsigned int n, table = RT_TABLE_UNSPEC;
1504 /* first try to parse table as number */
1505 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1508 /* handle well known aliases */
1509 else if (!strcmp(name, "default"))
1510 table = RT_TABLE_DEFAULT;
1511 else if (!strcmp(name, "main"))
1512 table = RT_TABLE_MAIN;
1513 else if (!strcmp(name, "local"))
1514 table = RT_TABLE_LOCAL;
1516 /* try to look up name in /etc/iproute2/rt_tables */
1517 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1519 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1521 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1524 n = strtoul(e, NULL, 10);
1525 e = strtok(NULL, " \t\n");
1527 if (e && !strcmp(e, name))
1537 if (table == RT_TABLE_UNSPEC)
1544 bool system_is_default_rt_table(unsigned int id)
1546 return (id == RT_TABLE_MAIN);
1549 bool system_resolve_rpfilter(const char *filter, unsigned int *id)
1554 if (!strcmp(filter, "strict"))
1556 else if (!strcmp(filter, "loose"))
1559 n = strtoul(filter, &e, 0);
1560 if (*e || e == filter || n > 2)
1568 static int system_iprule(struct iprule *rule, int cmd)
1570 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1573 struct rtmsg rtm = {
1574 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1575 .rtm_protocol = RTPROT_STATIC,
1576 .rtm_scope = RT_SCOPE_UNIVERSE,
1577 .rtm_table = RT_TABLE_UNSPEC,
1578 .rtm_type = RTN_UNSPEC,
1582 if (cmd == RTM_NEWRULE) {
1583 rtm.rtm_type = RTN_UNICAST;
1584 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1588 rtm.rtm_flags |= FIB_RULE_INVERT;
1590 if (rule->flags & IPRULE_SRC)
1591 rtm.rtm_src_len = rule->src_mask;
1593 if (rule->flags & IPRULE_DEST)
1594 rtm.rtm_dst_len = rule->dest_mask;
1596 if (rule->flags & IPRULE_TOS)
1597 rtm.rtm_tos = rule->tos;
1599 if (rule->flags & IPRULE_LOOKUP) {
1600 if (rule->lookup < 256)
1601 rtm.rtm_table = rule->lookup;
1604 if (rule->flags & IPRULE_ACTION)
1605 rtm.rtm_type = rule->action;
1606 else if (rule->flags & IPRULE_GOTO)
1607 rtm.rtm_type = FR_ACT_GOTO;
1608 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1609 rtm.rtm_type = FR_ACT_NOP;
1611 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1616 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1618 if (rule->flags & IPRULE_IN)
1619 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1621 if (rule->flags & IPRULE_OUT)
1622 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1624 if (rule->flags & IPRULE_SRC)
1625 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1627 if (rule->flags & IPRULE_DEST)
1628 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1630 if (rule->flags & IPRULE_PRIORITY)
1631 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1632 else if (cmd == RTM_NEWRULE)
1633 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1635 if (rule->flags & IPRULE_FWMARK)
1636 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1638 if (rule->flags & IPRULE_FWMASK)
1639 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1641 if (rule->flags & IPRULE_LOOKUP) {
1642 if (rule->lookup >= 256)
1643 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1646 if (rule->flags & IPRULE_GOTO)
1647 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1649 return system_rtnl_call(msg);
1652 int system_add_iprule(struct iprule *rule)
1654 return system_iprule(rule, RTM_NEWRULE);
1657 int system_del_iprule(struct iprule *rule)
1659 return system_iprule(rule, RTM_DELRULE);
1662 int system_flush_iprules(void)
1667 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1668 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1670 memset(&rule, 0, sizeof(rule));
1673 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1676 rule.lookup = RT_TABLE_LOCAL;
1677 rv |= system_iprule(&rule, RTM_NEWRULE);
1679 rule.priority = 32766;
1680 rule.lookup = RT_TABLE_MAIN;
1681 rv |= system_iprule(&rule, RTM_NEWRULE);
1683 rule.priority = 32767;
1684 rule.lookup = RT_TABLE_DEFAULT;
1685 rv |= system_iprule(&rule, RTM_NEWRULE);
1688 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1691 rule.lookup = RT_TABLE_LOCAL;
1692 rv |= system_iprule(&rule, RTM_NEWRULE);
1694 rule.priority = 32766;
1695 rule.lookup = RT_TABLE_MAIN;
1696 rv |= system_iprule(&rule, RTM_NEWRULE);
1701 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1703 return system_rtn_aton(action, id);
1706 time_t system_get_rtime(void)
1711 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1714 if (gettimeofday(&tv, NULL) == 0)
1721 #define IP_DF 0x4000
1724 static int tunnel_ioctl(const char *name, int cmd, void *p)
1728 memset(&ifr, 0, sizeof(ifr));
1729 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1730 ifr.ifr_ifru.ifru_data = p;
1731 return ioctl(sock_ioctl, cmd, &ifr);
1734 #ifdef IFLA_IPTUN_MAX
1735 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
1736 static int system_add_gre_tunnel(const char *name, const char *kind,
1737 const unsigned int link, struct blob_attr **tb, bool v6)
1740 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
1741 struct blob_attr *cur;
1742 uint32_t ikey = 0, okey = 0, flags = 0, flowinfo = 0;
1743 uint16_t iflags = 0, oflags = 0;
1745 int ret = 0, ttl = 64;
1747 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
1751 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
1752 nla_put_string(nlm, IFLA_IFNAME, name);
1754 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
1760 nla_put_string(nlm, IFLA_INFO_KIND, kind);
1761 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
1768 nla_put_u32(nlm, IFLA_GRE_LINK, link);
1770 if ((cur = tb[TUNNEL_ATTR_TTL]))
1771 ttl = blobmsg_get_u32(cur);
1773 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
1775 if ((cur = tb[TUNNEL_ATTR_TOS])) {
1776 char *str = blobmsg_get_string(cur);
1777 if (strcmp(str, "inherit")) {
1780 if (!system_tos_aton(str, &uval)) {
1786 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
1791 flags |= IP6_TNL_F_USE_ORIG_TCLASS;
1797 if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) {
1798 uint8_t icsum, ocsum, iseqno, oseqno;
1799 if (sscanf(blobmsg_get_string(cur), "%u,%u,%hhu,%hhu,%hhu,%hhu",
1800 &ikey, &okey, &icsum, &ocsum, &iseqno, &oseqno) < 6) {
1825 struct in6_addr in6buf;
1826 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1827 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1831 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
1834 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
1835 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1839 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
1841 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, 4);
1844 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
1847 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags);
1849 struct in_addr inbuf;
1852 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1853 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
1857 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
1860 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
1861 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
1865 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
1867 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
1869 okey = inbuf.s_addr;
1874 ikey = inbuf.s_addr;
1880 if ((cur = tb[TUNNEL_ATTR_DF]))
1881 set_df = blobmsg_get_bool(cur);
1883 /* ttl !=0 and nopmtudisc are incompatible */
1884 if (ttl && !set_df) {
1889 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
1891 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
1895 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
1898 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
1901 nla_put_u32(nlm, IFLA_GRE_OKEY, okey);
1904 nla_put_u32(nlm, IFLA_GRE_IKEY, ikey);
1906 nla_nest_end(nlm, infodata);
1907 nla_nest_end(nlm, linkinfo);
1909 return system_rtnl_call(nlm);
1917 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
1919 struct blob_attr *cur;
1921 struct ip_tunnel_parm p = {
1930 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
1931 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
1934 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
1935 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
1938 if ((cur = tb[TUNNEL_ATTR_DF]))
1939 set_df = blobmsg_get_bool(cur);
1941 if ((cur = tb[TUNNEL_ATTR_TTL]))
1942 p.iph.ttl = blobmsg_get_u32(cur);
1944 if ((cur = tb[TUNNEL_ATTR_TOS])) {
1945 char *str = blobmsg_get_string(cur);
1946 if (strcmp(str, "inherit")) {
1949 if (!system_tos_aton(str, &uval))
1957 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
1958 /* ttl !=0 and nopmtudisc are incompatible */
1959 if (p.iph.ttl && p.iph.frag_off == 0)
1962 strncpy(p.name, name, sizeof(p.name));
1964 switch (p.iph.protocol) {
1966 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
1968 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
1975 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
1977 struct blob_attr *cur;
1980 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
1982 str = blobmsg_data(cur);
1984 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
1985 !strcmp(str, "greip6") || !strcmp(str, "gretapip6"))
1986 return system_link_del(name);
1988 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
1991 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
1993 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
1995 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
1996 blob_data(attr), blob_len(attr));
1998 return __system_del_ip_tunnel(name, tb);
2001 int system_update_ipv6_mtu(struct device *dev, int mtu)
2005 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
2008 int fd = open(buf, O_RDWR);
2009 ssize_t len = read(fd, buf, sizeof(buf) - 1);
2016 if (!mtu || ret <= mtu)
2019 lseek(fd, 0, SEEK_SET);
2020 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) <= 0)
2028 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
2030 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2031 struct blob_attr *cur;
2034 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2035 blob_data(attr), blob_len(attr));
2037 __system_del_ip_tunnel(name, tb);
2039 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2041 str = blobmsg_data(cur);
2043 unsigned int ttl = 0;
2044 if ((cur = tb[TUNNEL_ATTR_TTL])) {
2045 ttl = blobmsg_get_u32(cur);
2050 unsigned int link = 0;
2051 if ((cur = tb[TUNNEL_ATTR_LINK])) {
2052 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
2056 if (iface->l3_dev.dev)
2057 link = iface->l3_dev.dev->ifindex;
2060 if (!strcmp(str, "sit")) {
2061 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
2065 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
2067 struct ip_tunnel_6rd p6;
2069 memset(&p6, 0, sizeof(p6));
2071 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
2072 &p6.prefix, &mask) || mask > 128)
2074 p6.prefixlen = mask;
2076 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
2077 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
2078 &p6.relay_prefix, &mask) || mask > 32)
2080 p6.relay_prefixlen = mask;
2083 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
2084 __system_del_ip_tunnel(name, tb);
2089 #ifdef IFLA_IPTUN_MAX
2090 } else if (!strcmp(str, "ipip6")) {
2091 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2092 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2093 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2099 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2100 nla_put_string(nlm, IFLA_IFNAME, name);
2103 nla_put_u32(nlm, IFLA_LINK, link);
2105 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2110 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2111 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2118 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2120 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2121 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2122 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
2124 struct in6_addr in6buf;
2125 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2126 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2130 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2133 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2134 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2138 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2141 #ifdef IFLA_IPTUN_FMR_MAX
2142 if ((cur = tb[TUNNEL_ATTR_FMRS])) {
2143 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2145 struct blob_attr *fmr;
2146 unsigned rem, fmrcnt = 0;
2147 blobmsg_for_each_attr(fmr, cur, rem) {
2148 if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
2151 unsigned ip4len, ip6len, ealen, offset = 6;
2155 if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
2156 ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) {
2161 struct in6_addr ip6prefix;
2162 struct in_addr ip4prefix;
2163 if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
2164 inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) {
2169 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2171 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2172 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2173 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2174 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2175 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2176 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2178 nla_nest_end(nlm, rule);
2181 nla_nest_end(nlm, fmrs);
2185 nla_nest_end(nlm, infodata);
2186 nla_nest_end(nlm, linkinfo);
2188 return system_rtnl_call(nlm);
2192 } else if (!strcmp(str, "greip")) {
2193 return system_add_gre_tunnel(name, "gre", link, tb, false);
2194 } else if (!strcmp(str, "gretapip")) {
2195 return system_add_gre_tunnel(name, "gretap", link, tb, false);
2196 } else if (!strcmp(str, "greip6")) {
2197 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
2198 } else if (!strcmp(str, "gretapip6")) {
2199 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
2201 } else if (!strcmp(str, "ipip")) {
2202 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);