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 /* Only keep orig settings based on what needs to be set */
1037 dev->orig_settings.flags &= dev->settings.flags;
1038 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
1039 return system_if_flags(dev->ifname, IFF_UP, 0);
1042 int system_if_down(struct device *dev)
1044 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
1045 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
1049 struct if_check_data {
1055 #ifndef IFF_LOWER_UP
1056 #define IFF_LOWER_UP 0x10000
1059 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1061 struct nlmsghdr *nh = nlmsg_hdr(msg);
1062 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1063 struct if_check_data *chk = (struct if_check_data *)arg;
1065 if (nh->nlmsg_type != RTM_NEWLINK)
1068 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1069 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1074 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1076 struct if_check_data *chk = (struct if_check_data *)arg;
1081 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1083 struct if_check_data *chk = (struct if_check_data *)arg;
1085 device_set_present(chk->dev, false);
1086 device_set_link(chk->dev, false);
1087 chk->pending = err->error;
1092 int system_if_check(struct device *dev)
1094 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1096 struct ifinfomsg ifi = {
1097 .ifi_family = AF_UNSPEC,
1100 struct if_check_data chk = {
1106 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1107 if (!msg || nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1108 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1111 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1112 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1113 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1115 nl_send_auto_complete(sock_rtnl, msg);
1116 while (chk.pending > 0)
1117 nl_recvmsgs(sock_rtnl, cb);
1128 system_if_get_parent(struct device *dev)
1130 char buf[64], *devname;
1131 int ifindex, iflink, len;
1134 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1135 f = fopen(buf, "r");
1139 len = fread(buf, 1, sizeof(buf) - 1, f);
1146 iflink = strtoul(buf, NULL, 0);
1147 ifindex = system_if_resolve(dev);
1148 if (!iflink || iflink == ifindex)
1151 devname = if_indextoname(iflink, buf);
1155 return device_get(devname, true);
1159 read_string_file(int dir_fd, const char *file, char *buf, int len)
1165 fd = openat(dir_fd, file, O_RDONLY);
1170 len = read(fd, buf, len - 1);
1174 } else if (len > 0) {
1177 c = strchr(buf, '\n');
1190 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1195 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1197 *val = strtoull(buf, NULL, 0);
1202 /* Assume advertised flags == supported flags */
1203 static const struct {
1206 } ethtool_link_modes[] = {
1207 { ADVERTISED_10baseT_Half, "10H" },
1208 { ADVERTISED_10baseT_Full, "10F" },
1209 { ADVERTISED_100baseT_Half, "100H" },
1210 { ADVERTISED_100baseT_Full, "100F" },
1211 { ADVERTISED_1000baseT_Half, "1000H" },
1212 { ADVERTISED_1000baseT_Full, "1000F" },
1215 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1218 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1219 if (mask & ethtool_link_modes[i].mask)
1220 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1225 system_if_force_external(const char *ifname)
1230 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1231 return stat(buf, &s) == 0;
1235 system_if_dump_info(struct device *dev, struct blob_buf *b)
1237 struct ethtool_cmd ecmd;
1243 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
1244 dir_fd = open(buf, O_DIRECTORY);
1246 memset(&ecmd, 0, sizeof(ecmd));
1247 memset(&ifr, 0, sizeof(ifr));
1248 strcpy(ifr.ifr_name, dev->ifname);
1249 ifr.ifr_data = (caddr_t) &ecmd;
1250 ecmd.cmd = ETHTOOL_GSET;
1252 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1253 c = blobmsg_open_array(b, "link-advertising");
1254 system_add_link_modes(b, ecmd.advertising);
1255 blobmsg_close_array(b, c);
1257 c = blobmsg_open_array(b, "link-supported");
1258 system_add_link_modes(b, ecmd.supported);
1259 blobmsg_close_array(b, c);
1261 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1262 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1263 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1264 blobmsg_add_string_buffer(b);
1272 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1274 const char *const counters[] = {
1275 "collisions", "rx_frame_errors", "tx_compressed",
1276 "multicast", "rx_length_errors", "tx_dropped",
1277 "rx_bytes", "rx_missed_errors", "tx_errors",
1278 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1279 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1280 "rx_dropped", "tx_aborted_errors", "tx_packets",
1281 "rx_errors", "tx_bytes", "tx_window_errors",
1282 "rx_fifo_errors", "tx_carrier_errors",
1289 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1290 stats_dir = open(buf, O_DIRECTORY);
1294 for (i = 0; i < ARRAY_SIZE(counters); i++)
1295 if (read_uint64_file(stats_dir, counters[i], &val))
1296 blobmsg_add_u64(b, counters[i], val);
1302 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1304 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1305 int alen = v4 ? 4 : 16;
1306 unsigned int flags = 0;
1307 struct ifaddrmsg ifa = {
1308 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1309 .ifa_prefixlen = addr->mask,
1310 .ifa_index = dev->ifindex,
1314 if (cmd == RTM_NEWADDR)
1315 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1317 msg = nlmsg_alloc_simple(cmd, flags);
1321 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1322 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1324 if (addr->broadcast)
1325 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1326 if (addr->point_to_point)
1327 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1329 time_t now = system_get_rtime();
1330 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1332 if (addr->preferred_until) {
1333 int64_t preferred = addr->preferred_until - now;
1336 else if (preferred > UINT32_MAX)
1337 preferred = UINT32_MAX;
1339 cinfo.ifa_prefered = preferred;
1342 if (addr->valid_until) {
1343 int64_t valid = addr->valid_until - now;
1346 else if (valid > UINT32_MAX)
1349 cinfo.ifa_valid = valid;
1352 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1355 return system_rtnl_call(msg);
1358 int system_add_address(struct device *dev, struct device_addr *addr)
1360 return system_addr(dev, addr, RTM_NEWADDR);
1363 int system_del_address(struct device *dev, struct device_addr *addr)
1365 return system_addr(dev, addr, RTM_DELADDR);
1368 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1370 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1372 unsigned int flags = 0;
1375 have_gw = !!route->nexthop.in.s_addr;
1377 have_gw = route->nexthop.in6.s6_addr32[0] ||
1378 route->nexthop.in6.s6_addr32[1] ||
1379 route->nexthop.in6.s6_addr32[2] ||
1380 route->nexthop.in6.s6_addr32[3];
1382 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1383 ? route->table : RT_TABLE_MAIN;
1385 struct rtmsg rtm = {
1386 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1387 .rtm_dst_len = route->mask,
1388 .rtm_src_len = route->sourcemask,
1389 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1390 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
1391 .rtm_scope = RT_SCOPE_NOWHERE,
1392 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1393 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1397 if (cmd == RTM_NEWROUTE) {
1398 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1400 if (!dev) { // Add null-route
1401 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1402 rtm.rtm_type = RTN_UNREACHABLE;
1405 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1408 if (route->flags & DEVROUTE_TYPE) {
1409 rtm.rtm_type = route->type;
1410 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
1411 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
1412 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
1413 rtm.rtm_table = RT_TABLE_LOCAL;
1416 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT) {
1417 rtm.rtm_scope = RT_SCOPE_HOST;
1418 } else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
1419 rtm.rtm_type == RTN_ANYCAST) {
1420 rtm.rtm_scope = RT_SCOPE_LINK;
1421 } else if (rtm.rtm_type == RTN_BLACKHOLE || rtm.rtm_type == RTN_UNREACHABLE ||
1422 rtm.rtm_type == RTN_PROHIBIT || rtm.rtm_type == RTN_FAILED_POLICY) {
1423 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1428 msg = nlmsg_alloc_simple(cmd, flags);
1432 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1435 nla_put(msg, RTA_DST, alen, &route->addr);
1437 if (route->sourcemask) {
1438 if (rtm.rtm_family == AF_INET)
1439 nla_put(msg, RTA_PREFSRC, alen, &route->source);
1441 nla_put(msg, RTA_SRC, alen, &route->source);
1444 if (route->metric > 0)
1445 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1448 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1451 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1454 nla_put_u32(msg, RTA_TABLE, table);
1456 if (route->flags & DEVROUTE_MTU) {
1457 struct nlattr *metrics;
1459 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1460 goto nla_put_failure;
1462 nla_put_u32(msg, RTAX_MTU, route->mtu);
1464 nla_nest_end(msg, metrics);
1467 return system_rtnl_call(msg);
1474 int system_add_route(struct device *dev, struct device_route *route)
1476 return system_rt(dev, route, RTM_NEWROUTE);
1479 int system_del_route(struct device *dev, struct device_route *route)
1481 return system_rt(dev, route, RTM_DELROUTE);
1484 int system_flush_routes(void)
1486 const char *names[] = {
1487 "/proc/sys/net/ipv4/route/flush",
1488 "/proc/sys/net/ipv6/route/flush"
1492 for (i = 0; i < ARRAY_SIZE(names); i++) {
1493 fd = open(names[i], O_WRONLY);
1497 if (write(fd, "-1", 2)) {}
1503 bool system_resolve_rt_type(const char *type, unsigned int *id)
1505 return system_rtn_aton(type, id);
1508 bool system_resolve_rt_table(const char *name, unsigned int *id)
1512 unsigned int n, table = RT_TABLE_UNSPEC;
1514 /* first try to parse table as number */
1515 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1518 /* handle well known aliases */
1519 else if (!strcmp(name, "default"))
1520 table = RT_TABLE_DEFAULT;
1521 else if (!strcmp(name, "main"))
1522 table = RT_TABLE_MAIN;
1523 else if (!strcmp(name, "local"))
1524 table = RT_TABLE_LOCAL;
1526 /* try to look up name in /etc/iproute2/rt_tables */
1527 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1529 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1531 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1534 n = strtoul(e, NULL, 10);
1535 e = strtok(NULL, " \t\n");
1537 if (e && !strcmp(e, name))
1547 if (table == RT_TABLE_UNSPEC)
1554 bool system_is_default_rt_table(unsigned int id)
1556 return (id == RT_TABLE_MAIN);
1559 bool system_resolve_rpfilter(const char *filter, unsigned int *id)
1564 if (!strcmp(filter, "strict"))
1566 else if (!strcmp(filter, "loose"))
1569 n = strtoul(filter, &e, 0);
1570 if (*e || e == filter || n > 2)
1578 static int system_iprule(struct iprule *rule, int cmd)
1580 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1583 struct rtmsg rtm = {
1584 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1585 .rtm_protocol = RTPROT_STATIC,
1586 .rtm_scope = RT_SCOPE_UNIVERSE,
1587 .rtm_table = RT_TABLE_UNSPEC,
1588 .rtm_type = RTN_UNSPEC,
1592 if (cmd == RTM_NEWRULE) {
1593 rtm.rtm_type = RTN_UNICAST;
1594 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1598 rtm.rtm_flags |= FIB_RULE_INVERT;
1600 if (rule->flags & IPRULE_SRC)
1601 rtm.rtm_src_len = rule->src_mask;
1603 if (rule->flags & IPRULE_DEST)
1604 rtm.rtm_dst_len = rule->dest_mask;
1606 if (rule->flags & IPRULE_TOS)
1607 rtm.rtm_tos = rule->tos;
1609 if (rule->flags & IPRULE_LOOKUP) {
1610 if (rule->lookup < 256)
1611 rtm.rtm_table = rule->lookup;
1614 if (rule->flags & IPRULE_ACTION)
1615 rtm.rtm_type = rule->action;
1616 else if (rule->flags & IPRULE_GOTO)
1617 rtm.rtm_type = FR_ACT_GOTO;
1618 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1619 rtm.rtm_type = FR_ACT_NOP;
1621 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1626 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1628 if (rule->flags & IPRULE_IN)
1629 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1631 if (rule->flags & IPRULE_OUT)
1632 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1634 if (rule->flags & IPRULE_SRC)
1635 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1637 if (rule->flags & IPRULE_DEST)
1638 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1640 if (rule->flags & IPRULE_PRIORITY)
1641 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1642 else if (cmd == RTM_NEWRULE)
1643 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1645 if (rule->flags & IPRULE_FWMARK)
1646 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1648 if (rule->flags & IPRULE_FWMASK)
1649 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1651 if (rule->flags & IPRULE_LOOKUP) {
1652 if (rule->lookup >= 256)
1653 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1656 if (rule->flags & IPRULE_GOTO)
1657 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1659 return system_rtnl_call(msg);
1662 int system_add_iprule(struct iprule *rule)
1664 return system_iprule(rule, RTM_NEWRULE);
1667 int system_del_iprule(struct iprule *rule)
1669 return system_iprule(rule, RTM_DELRULE);
1672 int system_flush_iprules(void)
1677 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1678 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1680 memset(&rule, 0, sizeof(rule));
1683 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1686 rule.lookup = RT_TABLE_LOCAL;
1687 rv |= system_iprule(&rule, RTM_NEWRULE);
1689 rule.priority = 32766;
1690 rule.lookup = RT_TABLE_MAIN;
1691 rv |= system_iprule(&rule, RTM_NEWRULE);
1693 rule.priority = 32767;
1694 rule.lookup = RT_TABLE_DEFAULT;
1695 rv |= system_iprule(&rule, RTM_NEWRULE);
1698 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1701 rule.lookup = RT_TABLE_LOCAL;
1702 rv |= system_iprule(&rule, RTM_NEWRULE);
1704 rule.priority = 32766;
1705 rule.lookup = RT_TABLE_MAIN;
1706 rv |= system_iprule(&rule, RTM_NEWRULE);
1711 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1713 return system_rtn_aton(action, id);
1716 time_t system_get_rtime(void)
1721 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1724 if (gettimeofday(&tv, NULL) == 0)
1731 #define IP_DF 0x4000
1734 static int tunnel_ioctl(const char *name, int cmd, void *p)
1738 memset(&ifr, 0, sizeof(ifr));
1739 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1740 ifr.ifr_ifru.ifru_data = p;
1741 return ioctl(sock_ioctl, cmd, &ifr);
1744 #ifdef IFLA_IPTUN_MAX
1745 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
1746 static int system_add_gre_tunnel(const char *name, const char *kind,
1747 const unsigned int link, struct blob_attr **tb, bool v6)
1750 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
1751 struct blob_attr *cur;
1752 uint32_t ikey = 0, okey = 0, flags = 0, flowinfo = 0;
1753 uint16_t iflags = 0, oflags = 0;
1755 int ret = 0, ttl = 64;
1757 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
1761 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
1762 nla_put_string(nlm, IFLA_IFNAME, name);
1764 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
1770 nla_put_string(nlm, IFLA_INFO_KIND, kind);
1771 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
1778 nla_put_u32(nlm, IFLA_GRE_LINK, link);
1780 if ((cur = tb[TUNNEL_ATTR_TTL]))
1781 ttl = blobmsg_get_u32(cur);
1783 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
1785 if ((cur = tb[TUNNEL_ATTR_TOS])) {
1786 char *str = blobmsg_get_string(cur);
1787 if (strcmp(str, "inherit")) {
1790 if (!system_tos_aton(str, &uval)) {
1796 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
1801 flags |= IP6_TNL_F_USE_ORIG_TCLASS;
1807 if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) {
1808 uint8_t icsum, ocsum, iseqno, oseqno;
1809 if (sscanf(blobmsg_get_string(cur), "%u,%u,%hhu,%hhu,%hhu,%hhu",
1810 &ikey, &okey, &icsum, &ocsum, &iseqno, &oseqno) < 6) {
1835 struct in6_addr in6buf;
1836 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1837 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1841 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
1844 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
1845 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1849 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
1851 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, 4);
1854 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
1857 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags);
1859 struct in_addr inbuf;
1862 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1863 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
1867 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
1870 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
1871 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
1875 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
1877 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
1879 okey = inbuf.s_addr;
1884 ikey = inbuf.s_addr;
1890 if ((cur = tb[TUNNEL_ATTR_DF]))
1891 set_df = blobmsg_get_bool(cur);
1893 /* ttl !=0 and nopmtudisc are incompatible */
1894 if (ttl && !set_df) {
1899 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
1901 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
1905 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
1908 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
1911 nla_put_u32(nlm, IFLA_GRE_OKEY, okey);
1914 nla_put_u32(nlm, IFLA_GRE_IKEY, ikey);
1916 nla_nest_end(nlm, infodata);
1917 nla_nest_end(nlm, linkinfo);
1919 return system_rtnl_call(nlm);
1927 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
1929 struct blob_attr *cur;
1931 struct ip_tunnel_parm p = {
1940 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
1941 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
1944 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
1945 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
1948 if ((cur = tb[TUNNEL_ATTR_DF]))
1949 set_df = blobmsg_get_bool(cur);
1951 if ((cur = tb[TUNNEL_ATTR_TTL]))
1952 p.iph.ttl = blobmsg_get_u32(cur);
1954 if ((cur = tb[TUNNEL_ATTR_TOS])) {
1955 char *str = blobmsg_get_string(cur);
1956 if (strcmp(str, "inherit")) {
1959 if (!system_tos_aton(str, &uval))
1967 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
1968 /* ttl !=0 and nopmtudisc are incompatible */
1969 if (p.iph.ttl && p.iph.frag_off == 0)
1972 strncpy(p.name, name, sizeof(p.name));
1974 switch (p.iph.protocol) {
1976 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
1978 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
1985 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
1987 struct blob_attr *cur;
1990 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
1992 str = blobmsg_data(cur);
1994 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
1995 !strcmp(str, "greip6") || !strcmp(str, "gretapip6"))
1996 return system_link_del(name);
1998 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
2001 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
2003 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2005 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2006 blob_data(attr), blob_len(attr));
2008 return __system_del_ip_tunnel(name, tb);
2011 int system_update_ipv6_mtu(struct device *dev, int mtu)
2015 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
2018 int fd = open(buf, O_RDWR);
2019 ssize_t len = read(fd, buf, sizeof(buf) - 1);
2026 if (!mtu || ret <= mtu)
2029 lseek(fd, 0, SEEK_SET);
2030 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) <= 0)
2038 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
2040 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2041 struct blob_attr *cur;
2044 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2045 blob_data(attr), blob_len(attr));
2047 __system_del_ip_tunnel(name, tb);
2049 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2051 str = blobmsg_data(cur);
2053 unsigned int ttl = 0;
2054 if ((cur = tb[TUNNEL_ATTR_TTL])) {
2055 ttl = blobmsg_get_u32(cur);
2060 unsigned int link = 0;
2061 if ((cur = tb[TUNNEL_ATTR_LINK])) {
2062 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
2066 if (iface->l3_dev.dev)
2067 link = iface->l3_dev.dev->ifindex;
2070 if (!strcmp(str, "sit")) {
2071 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
2075 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
2077 struct ip_tunnel_6rd p6;
2079 memset(&p6, 0, sizeof(p6));
2081 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
2082 &p6.prefix, &mask) || mask > 128)
2084 p6.prefixlen = mask;
2086 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
2087 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
2088 &p6.relay_prefix, &mask) || mask > 32)
2090 p6.relay_prefixlen = mask;
2093 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
2094 __system_del_ip_tunnel(name, tb);
2099 #ifdef IFLA_IPTUN_MAX
2100 } else if (!strcmp(str, "ipip6")) {
2101 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2102 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2103 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2109 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2110 nla_put_string(nlm, IFLA_IFNAME, name);
2113 nla_put_u32(nlm, IFLA_LINK, link);
2115 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2120 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2121 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2128 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2130 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2131 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2132 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
2134 struct in6_addr in6buf;
2135 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2136 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2140 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2143 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2144 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2148 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2151 #ifdef IFLA_IPTUN_FMR_MAX
2152 if ((cur = tb[TUNNEL_ATTR_FMRS])) {
2153 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2155 struct blob_attr *fmr;
2156 unsigned rem, fmrcnt = 0;
2157 blobmsg_for_each_attr(fmr, cur, rem) {
2158 if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
2161 unsigned ip4len, ip6len, ealen, offset = 6;
2165 if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
2166 ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) {
2171 struct in6_addr ip6prefix;
2172 struct in_addr ip4prefix;
2173 if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
2174 inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) {
2179 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2181 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2182 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2183 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2184 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2185 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2186 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2188 nla_nest_end(nlm, rule);
2191 nla_nest_end(nlm, fmrs);
2195 nla_nest_end(nlm, infodata);
2196 nla_nest_end(nlm, linkinfo);
2198 return system_rtnl_call(nlm);
2202 } else if (!strcmp(str, "greip")) {
2203 return system_add_gre_tunnel(name, "gre", link, tb, false);
2204 } else if (!strcmp(str, "gretapip")) {
2205 return system_add_gre_tunnel(name, "gretap", link, tb, false);
2206 } else if (!strcmp(str, "greip6")) {
2207 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
2208 } else if (!strcmp(str, "gretapip6")) {
2209 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
2211 } else if (!strcmp(str, "ipip")) {
2212 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);