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;
1420 } else if (rtm.rtm_type == RTN_BLACKHOLE || rtm.rtm_type == RTN_UNREACHABLE ||
1421 rtm.rtm_type == RTN_PROHIBIT || rtm.rtm_type == RTN_FAILED_POLICY) {
1422 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1427 msg = nlmsg_alloc_simple(cmd, flags);
1431 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1434 nla_put(msg, RTA_DST, alen, &route->addr);
1436 if (route->sourcemask)
1437 nla_put(msg, RTA_SRC, alen, &route->source);
1439 if (route->metric > 0)
1440 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1443 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1446 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1449 nla_put_u32(msg, RTA_TABLE, table);
1451 if (route->flags & DEVROUTE_MTU) {
1452 struct nlattr *metrics;
1454 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1455 goto nla_put_failure;
1457 nla_put_u32(msg, RTAX_MTU, route->mtu);
1459 nla_nest_end(msg, metrics);
1462 return system_rtnl_call(msg);
1469 int system_add_route(struct device *dev, struct device_route *route)
1471 return system_rt(dev, route, RTM_NEWROUTE);
1474 int system_del_route(struct device *dev, struct device_route *route)
1476 return system_rt(dev, route, RTM_DELROUTE);
1479 int system_flush_routes(void)
1481 const char *names[] = {
1482 "/proc/sys/net/ipv4/route/flush",
1483 "/proc/sys/net/ipv6/route/flush"
1487 for (i = 0; i < ARRAY_SIZE(names); i++) {
1488 fd = open(names[i], O_WRONLY);
1492 if (write(fd, "-1", 2)) {}
1498 bool system_resolve_rt_type(const char *type, unsigned int *id)
1500 return system_rtn_aton(type, id);
1503 bool system_resolve_rt_table(const char *name, unsigned int *id)
1507 unsigned int n, table = RT_TABLE_UNSPEC;
1509 /* first try to parse table as number */
1510 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1513 /* handle well known aliases */
1514 else if (!strcmp(name, "default"))
1515 table = RT_TABLE_DEFAULT;
1516 else if (!strcmp(name, "main"))
1517 table = RT_TABLE_MAIN;
1518 else if (!strcmp(name, "local"))
1519 table = RT_TABLE_LOCAL;
1521 /* try to look up name in /etc/iproute2/rt_tables */
1522 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1524 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1526 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1529 n = strtoul(e, NULL, 10);
1530 e = strtok(NULL, " \t\n");
1532 if (e && !strcmp(e, name))
1542 if (table == RT_TABLE_UNSPEC)
1549 bool system_is_default_rt_table(unsigned int id)
1551 return (id == RT_TABLE_MAIN);
1554 bool system_resolve_rpfilter(const char *filter, unsigned int *id)
1559 if (!strcmp(filter, "strict"))
1561 else if (!strcmp(filter, "loose"))
1564 n = strtoul(filter, &e, 0);
1565 if (*e || e == filter || n > 2)
1573 static int system_iprule(struct iprule *rule, int cmd)
1575 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1578 struct rtmsg rtm = {
1579 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1580 .rtm_protocol = RTPROT_STATIC,
1581 .rtm_scope = RT_SCOPE_UNIVERSE,
1582 .rtm_table = RT_TABLE_UNSPEC,
1583 .rtm_type = RTN_UNSPEC,
1587 if (cmd == RTM_NEWRULE) {
1588 rtm.rtm_type = RTN_UNICAST;
1589 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1593 rtm.rtm_flags |= FIB_RULE_INVERT;
1595 if (rule->flags & IPRULE_SRC)
1596 rtm.rtm_src_len = rule->src_mask;
1598 if (rule->flags & IPRULE_DEST)
1599 rtm.rtm_dst_len = rule->dest_mask;
1601 if (rule->flags & IPRULE_TOS)
1602 rtm.rtm_tos = rule->tos;
1604 if (rule->flags & IPRULE_LOOKUP) {
1605 if (rule->lookup < 256)
1606 rtm.rtm_table = rule->lookup;
1609 if (rule->flags & IPRULE_ACTION)
1610 rtm.rtm_type = rule->action;
1611 else if (rule->flags & IPRULE_GOTO)
1612 rtm.rtm_type = FR_ACT_GOTO;
1613 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1614 rtm.rtm_type = FR_ACT_NOP;
1616 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1621 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1623 if (rule->flags & IPRULE_IN)
1624 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1626 if (rule->flags & IPRULE_OUT)
1627 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1629 if (rule->flags & IPRULE_SRC)
1630 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1632 if (rule->flags & IPRULE_DEST)
1633 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1635 if (rule->flags & IPRULE_PRIORITY)
1636 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1637 else if (cmd == RTM_NEWRULE)
1638 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1640 if (rule->flags & IPRULE_FWMARK)
1641 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1643 if (rule->flags & IPRULE_FWMASK)
1644 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1646 if (rule->flags & IPRULE_LOOKUP) {
1647 if (rule->lookup >= 256)
1648 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1651 if (rule->flags & IPRULE_GOTO)
1652 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1654 return system_rtnl_call(msg);
1657 int system_add_iprule(struct iprule *rule)
1659 return system_iprule(rule, RTM_NEWRULE);
1662 int system_del_iprule(struct iprule *rule)
1664 return system_iprule(rule, RTM_DELRULE);
1667 int system_flush_iprules(void)
1672 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1673 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1675 memset(&rule, 0, sizeof(rule));
1678 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1681 rule.lookup = RT_TABLE_LOCAL;
1682 rv |= system_iprule(&rule, RTM_NEWRULE);
1684 rule.priority = 32766;
1685 rule.lookup = RT_TABLE_MAIN;
1686 rv |= system_iprule(&rule, RTM_NEWRULE);
1688 rule.priority = 32767;
1689 rule.lookup = RT_TABLE_DEFAULT;
1690 rv |= system_iprule(&rule, RTM_NEWRULE);
1693 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1696 rule.lookup = RT_TABLE_LOCAL;
1697 rv |= system_iprule(&rule, RTM_NEWRULE);
1699 rule.priority = 32766;
1700 rule.lookup = RT_TABLE_MAIN;
1701 rv |= system_iprule(&rule, RTM_NEWRULE);
1706 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1708 return system_rtn_aton(action, id);
1711 time_t system_get_rtime(void)
1716 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1719 if (gettimeofday(&tv, NULL) == 0)
1726 #define IP_DF 0x4000
1729 static int tunnel_ioctl(const char *name, int cmd, void *p)
1733 memset(&ifr, 0, sizeof(ifr));
1734 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1735 ifr.ifr_ifru.ifru_data = p;
1736 return ioctl(sock_ioctl, cmd, &ifr);
1739 #ifdef IFLA_IPTUN_MAX
1740 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
1741 static int system_add_gre_tunnel(const char *name, const char *kind,
1742 const unsigned int link, struct blob_attr **tb, bool v6)
1745 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
1746 struct blob_attr *cur;
1747 uint32_t ikey = 0, okey = 0, flags = 0, flowinfo = 0;
1748 uint16_t iflags = 0, oflags = 0;
1750 int ret = 0, ttl = 64;
1752 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
1756 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
1757 nla_put_string(nlm, IFLA_IFNAME, name);
1759 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
1765 nla_put_string(nlm, IFLA_INFO_KIND, kind);
1766 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
1773 nla_put_u32(nlm, IFLA_GRE_LINK, link);
1775 if ((cur = tb[TUNNEL_ATTR_TTL]))
1776 ttl = blobmsg_get_u32(cur);
1778 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
1780 if ((cur = tb[TUNNEL_ATTR_TOS])) {
1781 char *str = blobmsg_get_string(cur);
1782 if (strcmp(str, "inherit")) {
1785 if (!system_tos_aton(str, &uval)) {
1791 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
1796 flags |= IP6_TNL_F_USE_ORIG_TCLASS;
1802 if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) {
1803 uint8_t icsum, ocsum, iseqno, oseqno;
1804 if (sscanf(blobmsg_get_string(cur), "%u,%u,%hhu,%hhu,%hhu,%hhu",
1805 &ikey, &okey, &icsum, &ocsum, &iseqno, &oseqno) < 6) {
1830 struct in6_addr in6buf;
1831 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1832 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1836 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
1839 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
1840 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1844 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
1846 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, 4);
1849 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
1852 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags);
1854 struct in_addr inbuf;
1857 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1858 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
1862 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
1865 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
1866 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
1870 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
1872 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
1874 okey = inbuf.s_addr;
1879 ikey = inbuf.s_addr;
1885 if ((cur = tb[TUNNEL_ATTR_DF]))
1886 set_df = blobmsg_get_bool(cur);
1888 /* ttl !=0 and nopmtudisc are incompatible */
1889 if (ttl && !set_df) {
1894 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
1896 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
1900 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
1903 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
1906 nla_put_u32(nlm, IFLA_GRE_OKEY, okey);
1909 nla_put_u32(nlm, IFLA_GRE_IKEY, ikey);
1911 nla_nest_end(nlm, infodata);
1912 nla_nest_end(nlm, linkinfo);
1914 return system_rtnl_call(nlm);
1922 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
1924 struct blob_attr *cur;
1926 struct ip_tunnel_parm p = {
1935 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
1936 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
1939 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
1940 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
1943 if ((cur = tb[TUNNEL_ATTR_DF]))
1944 set_df = blobmsg_get_bool(cur);
1946 if ((cur = tb[TUNNEL_ATTR_TTL]))
1947 p.iph.ttl = blobmsg_get_u32(cur);
1949 if ((cur = tb[TUNNEL_ATTR_TOS])) {
1950 char *str = blobmsg_get_string(cur);
1951 if (strcmp(str, "inherit")) {
1954 if (!system_tos_aton(str, &uval))
1962 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
1963 /* ttl !=0 and nopmtudisc are incompatible */
1964 if (p.iph.ttl && p.iph.frag_off == 0)
1967 strncpy(p.name, name, sizeof(p.name));
1969 switch (p.iph.protocol) {
1971 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
1973 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
1980 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
1982 struct blob_attr *cur;
1985 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
1987 str = blobmsg_data(cur);
1989 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
1990 !strcmp(str, "greip6") || !strcmp(str, "gretapip6"))
1991 return system_link_del(name);
1993 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
1996 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
1998 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2000 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2001 blob_data(attr), blob_len(attr));
2003 return __system_del_ip_tunnel(name, tb);
2006 int system_update_ipv6_mtu(struct device *dev, int mtu)
2010 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
2013 int fd = open(buf, O_RDWR);
2014 ssize_t len = read(fd, buf, sizeof(buf) - 1);
2021 if (!mtu || ret <= mtu)
2024 lseek(fd, 0, SEEK_SET);
2025 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) <= 0)
2033 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
2035 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2036 struct blob_attr *cur;
2039 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2040 blob_data(attr), blob_len(attr));
2042 __system_del_ip_tunnel(name, tb);
2044 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2046 str = blobmsg_data(cur);
2048 unsigned int ttl = 0;
2049 if ((cur = tb[TUNNEL_ATTR_TTL])) {
2050 ttl = blobmsg_get_u32(cur);
2055 unsigned int link = 0;
2056 if ((cur = tb[TUNNEL_ATTR_LINK])) {
2057 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
2061 if (iface->l3_dev.dev)
2062 link = iface->l3_dev.dev->ifindex;
2065 if (!strcmp(str, "sit")) {
2066 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
2070 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
2072 struct ip_tunnel_6rd p6;
2074 memset(&p6, 0, sizeof(p6));
2076 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
2077 &p6.prefix, &mask) || mask > 128)
2079 p6.prefixlen = mask;
2081 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
2082 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
2083 &p6.relay_prefix, &mask) || mask > 32)
2085 p6.relay_prefixlen = mask;
2088 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
2089 __system_del_ip_tunnel(name, tb);
2094 #ifdef IFLA_IPTUN_MAX
2095 } else if (!strcmp(str, "ipip6")) {
2096 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2097 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2098 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2104 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2105 nla_put_string(nlm, IFLA_IFNAME, name);
2108 nla_put_u32(nlm, IFLA_LINK, link);
2110 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2115 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2116 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2123 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2125 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2126 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2127 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
2129 struct in6_addr in6buf;
2130 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2131 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2135 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2138 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2139 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2143 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2146 #ifdef IFLA_IPTUN_FMR_MAX
2147 if ((cur = tb[TUNNEL_ATTR_FMRS])) {
2148 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2150 struct blob_attr *fmr;
2151 unsigned rem, fmrcnt = 0;
2152 blobmsg_for_each_attr(fmr, cur, rem) {
2153 if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
2156 unsigned ip4len, ip6len, ealen, offset = 6;
2160 if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
2161 ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) {
2166 struct in6_addr ip6prefix;
2167 struct in_addr ip4prefix;
2168 if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
2169 inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) {
2174 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2176 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2177 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2178 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2179 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2180 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2181 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2183 nla_nest_end(nlm, rule);
2186 nla_nest_end(nlm, fmrs);
2190 nla_nest_end(nlm, infodata);
2191 nla_nest_end(nlm, linkinfo);
2193 return system_rtnl_call(nlm);
2197 } else if (!strcmp(str, "greip")) {
2198 return system_add_gre_tunnel(name, "gre", link, tb, false);
2199 } else if (!strcmp(str, "gretapip")) {
2200 return system_add_gre_tunnel(name, "gretap", link, tb, false);
2201 } else if (!strcmp(str, "greip6")) {
2202 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
2203 } else if (!strcmp(str, "gretapip6")) {
2204 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
2206 } else if (!strcmp(str, "ipip")) {
2207 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);