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 int system_get_sysctl(const char *path, char *buf, const size_t buf_sz)
275 int fd = -1, ret = -1;
277 fd = open(path, O_RDONLY);
281 ssize_t len = read(fd, buf, buf_sz - 1);
295 system_get_dev_sysctl(const char *path, const char *device, char *buf, const size_t buf_sz)
297 snprintf(dev_buf, sizeof(dev_buf), path, device);
298 return system_get_sysctl(dev_buf, buf, buf_sz);
301 static int system_get_disable_ipv6(struct device *dev, char *buf, const size_t buf_sz)
303 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6",
304 dev->ifname, buf, buf_sz);
307 static int system_get_rpfilter(struct device *dev, char *buf, const size_t buf_sz)
309 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter",
310 dev->ifname, buf, buf_sz);
313 // Evaluate netlink messages
314 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
316 struct nlmsghdr *nh = nlmsg_hdr(msg);
317 struct ifinfomsg *ifi = NLMSG_DATA(nh);
318 struct nlattr *nla[__IFLA_MAX];
322 if (nh->nlmsg_type != RTM_NEWLINK)
325 nlmsg_parse(nh, sizeof(*ifi), nla, __IFLA_MAX - 1, NULL);
326 if (!nla[IFLA_IFNAME])
329 struct device *dev = device_get(nla_data(nla[IFLA_IFNAME]), false);
330 if (!dev || dev->type->keep_link_status)
333 if (!system_get_dev_sysctl("/sys/class/net/%s/carrier", dev->ifname, buf, sizeof(buf)))
334 link_state = strtoul(buf, NULL, 0);
336 device_set_link(dev, link_state ? true : false);
343 handle_hotplug_msg(char *data, int size)
345 const char *subsystem = NULL, *interface = NULL;
346 char *cur, *end, *sep;
351 if (!strncmp(data, "add@", 4))
353 else if (!strncmp(data, "remove@", 7))
358 skip = strlen(data) + 1;
361 for (cur = data + skip; cur < end; cur += skip) {
362 skip = strlen(cur) + 1;
364 sep = strchr(cur, '=');
369 if (!strcmp(cur, "INTERFACE"))
371 else if (!strcmp(cur, "SUBSYSTEM")) {
373 if (strcmp(subsystem, "net") != 0)
376 if (subsystem && interface)
382 dev = device_get(interface, false);
386 if (dev->type != &simple_device_type)
389 if (add && system_if_force_external(dev->ifname))
392 device_set_present(dev, add);
396 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
398 struct event_socket *ev = container_of(u, struct event_socket, uloop);
399 struct sockaddr_nl nla;
400 unsigned char *buf = NULL;
403 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
405 handle_hotplug_msg((char *) buf, size);
411 static int system_rtnl_call(struct nl_msg *msg)
415 ret = nl_send_auto_complete(sock_rtnl, msg);
421 return nl_wait_for_ack(sock_rtnl);
424 int system_bridge_delbr(struct device *bridge)
426 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
429 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
433 memset(&ifr, 0, sizeof(ifr));
435 ifr.ifr_ifindex = dev->ifindex;
438 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
439 return ioctl(sock_ioctl, cmd, &ifr);
442 static bool system_is_bridge(const char *name, char *buf, int buflen)
446 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
447 if (stat(buf, &st) < 0)
453 static char *system_get_bridge(const char *name, char *buf, int buflen)
459 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
460 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
464 len = readlink(gl.gl_pathv[0], buf, buflen);
472 path = strrchr(buf, '/');
479 static void system_bridge_set_wireless(const char *bridge, const char *dev)
481 snprintf(dev_buf, sizeof(dev_buf),
482 "/sys/devices/virtual/net/%s/brif/%s/multicast_to_unicast",
484 system_set_sysctl(dev_buf, "1");
487 int system_bridge_addif(struct device *bridge, struct device *dev)
492 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
493 if (!oldbr || strcmp(oldbr, bridge->ifname) != 0)
494 ret = system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
497 system_bridge_set_wireless(bridge->ifname, dev->ifname);
502 int system_bridge_delif(struct device *bridge, struct device *dev)
504 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
507 int system_if_resolve(struct device *dev)
510 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
511 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
512 return ifr.ifr_ifindex;
517 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
521 memset(&ifr, 0, sizeof(ifr));
522 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
523 ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
524 ifr.ifr_flags |= add;
525 ifr.ifr_flags &= ~rem;
526 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
538 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
540 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
542 return ifa->ifa_index == ifindex;
545 static bool check_route(struct nlmsghdr *hdr, int ifindex)
547 struct rtmsg *r = NLMSG_DATA(hdr);
548 struct nlattr *tb[__RTA_MAX];
550 if (r->rtm_protocol == RTPROT_KERNEL &&
551 r->rtm_family == AF_INET6)
554 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
558 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
561 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
566 static int cb_clear_event(struct nl_msg *msg, void *arg)
568 struct clear_data *clr = arg;
569 struct nlmsghdr *hdr = nlmsg_hdr(msg);
570 bool (*cb)(struct nlmsghdr *, int ifindex);
576 if (hdr->nlmsg_type != RTM_NEWADDR)
583 if (hdr->nlmsg_type != RTM_NEWROUTE)
590 if (hdr->nlmsg_type != RTM_NEWRULE)
599 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
602 if (type == RTM_DELRULE)
603 D(SYSTEM, "Remove a rule\n");
605 D(SYSTEM, "Remove %s from device %s\n",
606 type == RTM_DELADDR ? "an address" : "a route",
608 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
609 hdr = nlmsg_hdr(clr->msg);
610 hdr->nlmsg_type = type;
611 hdr->nlmsg_flags = NLM_F_REQUEST;
613 nl_socket_disable_auto_ack(sock_rtnl);
614 nl_send_auto_complete(sock_rtnl, clr->msg);
615 nl_socket_enable_auto_ack(sock_rtnl);
621 cb_finish_event(struct nl_msg *msg, void *arg)
629 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
632 *pending = err->error;
637 system_if_clear_entries(struct device *dev, int type, int af)
639 struct clear_data clr;
640 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
643 .rtm_flags = RTM_F_CLONED,
645 int flags = NLM_F_DUMP;
654 clr.size = sizeof(struct rtgenmsg);
657 clr.size = sizeof(struct rtmsg);
666 clr.msg = nlmsg_alloc_simple(type, flags);
670 nlmsg_append(clr.msg, &rtm, clr.size, 0);
671 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
672 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
673 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
675 nl_send_auto_complete(sock_rtnl, clr.msg);
677 nl_recvmsgs(sock_rtnl, cb);
685 * Clear bridge (membership) state and bring down device
687 void system_if_clear_state(struct device *dev)
689 static char buf[256];
692 device_set_ifindex(dev, system_if_resolve(dev));
693 if (dev->external || !dev->ifindex)
696 system_if_flags(dev->ifname, 0, IFF_UP);
698 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
699 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
700 system_bridge_delbr(dev);
704 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
706 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
707 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
710 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
711 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
712 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
713 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
714 system_set_disable_ipv6(dev, "0");
717 static inline unsigned long
718 sec_to_jiffies(int val)
720 return (unsigned long) val * 100;
723 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
725 unsigned long args[4] = {};
727 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
730 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
731 args[1] = !!cfg->stp;
732 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
734 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
735 args[1] = sec_to_jiffies(cfg->forward_delay);
736 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
738 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
739 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
741 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier",
742 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
744 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
745 args[1] = cfg->priority;
746 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
748 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
749 args[0] = BRCTL_SET_AGEING_TIME;
750 args[1] = sec_to_jiffies(cfg->ageing_time);
751 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
754 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
755 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
756 args[1] = sec_to_jiffies(cfg->hello_time);
757 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
760 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
761 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
762 args[1] = sec_to_jiffies(cfg->max_age);
763 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
769 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
772 struct nlattr *linkinfo, *data;
773 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
775 static const struct {
777 enum macvlan_mode val;
779 { "private", MACVLAN_MODE_PRIVATE },
780 { "vepa", MACVLAN_MODE_VEPA },
781 { "bridge", MACVLAN_MODE_BRIDGE },
782 { "passthru", MACVLAN_MODE_PASSTHRU },
785 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
790 nlmsg_append(msg, &iim, sizeof(iim), 0);
792 if (cfg->flags & MACVLAN_OPT_MACADDR)
793 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
794 nla_put_string(msg, IFLA_IFNAME, macvlan->ifname);
795 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
797 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
798 goto nla_put_failure;
800 nla_put_string(msg, IFLA_INFO_KIND, "macvlan");
802 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
803 goto nla_put_failure;
806 for (i = 0; i < ARRAY_SIZE(modes); i++) {
807 if (strcmp(cfg->mode, modes[i].name) != 0)
810 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
815 nla_nest_end(msg, data);
816 nla_nest_end(msg, linkinfo);
818 rv = system_rtnl_call(msg);
820 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
829 static int system_link_del(const char *ifname)
832 struct ifinfomsg iim = {
833 .ifi_family = AF_UNSPEC,
837 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
842 nlmsg_append(msg, &iim, sizeof(iim), 0);
843 nla_put_string(msg, IFLA_IFNAME, ifname);
844 return system_rtnl_call(msg);
847 int system_macvlan_del(struct device *macvlan)
849 return system_link_del(macvlan->ifname);
852 static int system_vlan(struct device *dev, int id)
854 struct vlan_ioctl_args ifr = {
855 .cmd = SET_VLAN_NAME_TYPE_CMD,
856 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
859 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
862 ifr.cmd = DEL_VLAN_CMD;
865 ifr.cmd = ADD_VLAN_CMD;
868 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
869 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
872 int system_vlan_add(struct device *dev, int id)
874 return system_vlan(dev, id);
877 int system_vlan_del(struct device *dev)
879 return system_vlan(dev, -1);
882 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
885 struct nlattr *linkinfo, *data;
886 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
889 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
894 nlmsg_append(msg, &iim, sizeof(iim), 0);
895 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
896 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
898 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
899 goto nla_put_failure;
901 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
903 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
904 goto nla_put_failure;
906 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
908 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
909 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
911 if(cfg->proto == VLAN_PROTO_8021AD)
912 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);
915 nla_nest_end(msg, data);
916 nla_nest_end(msg, linkinfo);
918 rv = system_rtnl_call(msg);
920 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
929 int system_vlandev_del(struct device *vlandev)
931 return system_link_del(vlandev->ifname);
935 system_if_get_settings(struct device *dev, struct device_settings *s)
940 memset(&ifr, 0, sizeof(ifr));
941 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
943 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
944 s->mtu = ifr.ifr_mtu;
945 s->flags |= DEV_OPT_MTU;
948 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
949 s->txqueuelen = ifr.ifr_qlen;
950 s->flags |= DEV_OPT_TXQUEUELEN;
953 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
954 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
955 s->flags |= DEV_OPT_MACADDR;
958 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
959 s->ipv6 = !strtoul(buf, NULL, 0);
960 s->flags |= DEV_OPT_IPV6;
963 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
964 s->promisc = ifr.ifr_flags & IFF_PROMISC;
965 s->flags |= DEV_OPT_PROMISC;
968 if (!system_get_rpfilter(dev, buf, sizeof(buf))) {
969 s->rpfilter = strtoul(buf, NULL, 0);
970 s->flags |= DEV_OPT_RPFILTER;
975 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
982 memset(&ifr, 0, sizeof(ifr));
983 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
984 if (s->flags & DEV_OPT_MTU & apply_mask) {
985 ifr.ifr_mtu = s->mtu;
986 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
987 s->flags &= ~DEV_OPT_MTU;
989 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
990 ifr.ifr_qlen = s->txqueuelen;
991 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
992 s->flags &= ~DEV_OPT_TXQUEUELEN;
994 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
995 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
996 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
997 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
998 s->flags &= ~DEV_OPT_MACADDR;
1000 if (s->flags & DEV_OPT_IPV6 & apply_mask)
1001 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
1002 if (s->flags & DEV_OPT_PROMISC & apply_mask) {
1003 if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
1004 !s->promisc ? IFF_PROMISC : 0) < 0)
1005 s->flags &= ~DEV_OPT_PROMISC;
1007 if (s->flags & DEV_OPT_RPFILTER & apply_mask) {
1010 snprintf(buf, sizeof(buf), "%d", s->rpfilter);
1011 system_set_rpfilter(dev, buf);
1015 int system_if_up(struct device *dev)
1017 system_if_get_settings(dev, &dev->orig_settings);
1018 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
1019 return system_if_flags(dev->ifname, IFF_UP, 0);
1022 int system_if_down(struct device *dev)
1024 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
1025 dev->orig_settings.flags &= dev->settings.flags;
1026 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
1030 struct if_check_data {
1036 #ifndef IFF_LOWER_UP
1037 #define IFF_LOWER_UP 0x10000
1040 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1042 struct nlmsghdr *nh = nlmsg_hdr(msg);
1043 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1044 struct if_check_data *chk = (struct if_check_data *)arg;
1046 if (nh->nlmsg_type != RTM_NEWLINK)
1049 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1050 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1055 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1057 struct if_check_data *chk = (struct if_check_data *)arg;
1062 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1064 struct if_check_data *chk = (struct if_check_data *)arg;
1066 device_set_present(chk->dev, false);
1067 device_set_link(chk->dev, false);
1068 chk->pending = err->error;
1073 int system_if_check(struct device *dev)
1075 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1077 struct ifinfomsg ifi = {
1078 .ifi_family = AF_UNSPEC,
1081 struct if_check_data chk = {
1087 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1088 if (!msg || nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1089 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1092 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1093 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1094 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1096 nl_send_auto_complete(sock_rtnl, msg);
1097 while (chk.pending > 0)
1098 nl_recvmsgs(sock_rtnl, cb);
1109 system_if_get_parent(struct device *dev)
1111 char buf[64], *devname;
1112 int ifindex, iflink, len;
1115 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1116 f = fopen(buf, "r");
1120 len = fread(buf, 1, sizeof(buf) - 1, f);
1127 iflink = strtoul(buf, NULL, 0);
1128 ifindex = system_if_resolve(dev);
1129 if (!iflink || iflink == ifindex)
1132 devname = if_indextoname(iflink, buf);
1136 return device_get(devname, true);
1140 read_string_file(int dir_fd, const char *file, char *buf, int len)
1146 fd = openat(dir_fd, file, O_RDONLY);
1151 len = read(fd, buf, len - 1);
1155 } else if (len > 0) {
1158 c = strchr(buf, '\n');
1171 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1176 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1178 *val = strtoull(buf, NULL, 0);
1183 /* Assume advertised flags == supported flags */
1184 static const struct {
1187 } ethtool_link_modes[] = {
1188 { ADVERTISED_10baseT_Half, "10H" },
1189 { ADVERTISED_10baseT_Full, "10F" },
1190 { ADVERTISED_100baseT_Half, "100H" },
1191 { ADVERTISED_100baseT_Full, "100F" },
1192 { ADVERTISED_1000baseT_Half, "1000H" },
1193 { ADVERTISED_1000baseT_Full, "1000F" },
1196 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1199 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1200 if (mask & ethtool_link_modes[i].mask)
1201 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1206 system_if_force_external(const char *ifname)
1211 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1212 return stat(buf, &s) == 0;
1216 system_if_dump_info(struct device *dev, struct blob_buf *b)
1218 struct ethtool_cmd ecmd;
1224 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
1225 dir_fd = open(buf, O_DIRECTORY);
1227 memset(&ecmd, 0, sizeof(ecmd));
1228 memset(&ifr, 0, sizeof(ifr));
1229 strcpy(ifr.ifr_name, dev->ifname);
1230 ifr.ifr_data = (caddr_t) &ecmd;
1231 ecmd.cmd = ETHTOOL_GSET;
1233 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1234 c = blobmsg_open_array(b, "link-advertising");
1235 system_add_link_modes(b, ecmd.advertising);
1236 blobmsg_close_array(b, c);
1238 c = blobmsg_open_array(b, "link-supported");
1239 system_add_link_modes(b, ecmd.supported);
1240 blobmsg_close_array(b, c);
1242 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1243 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1244 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1245 blobmsg_add_string_buffer(b);
1253 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1255 const char *const counters[] = {
1256 "collisions", "rx_frame_errors", "tx_compressed",
1257 "multicast", "rx_length_errors", "tx_dropped",
1258 "rx_bytes", "rx_missed_errors", "tx_errors",
1259 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1260 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1261 "rx_dropped", "tx_aborted_errors", "tx_packets",
1262 "rx_errors", "tx_bytes", "tx_window_errors",
1263 "rx_fifo_errors", "tx_carrier_errors",
1270 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1271 stats_dir = open(buf, O_DIRECTORY);
1275 for (i = 0; i < ARRAY_SIZE(counters); i++)
1276 if (read_uint64_file(stats_dir, counters[i], &val))
1277 blobmsg_add_u64(b, counters[i], val);
1283 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1285 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1286 int alen = v4 ? 4 : 16;
1287 unsigned int flags = 0;
1288 struct ifaddrmsg ifa = {
1289 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1290 .ifa_prefixlen = addr->mask,
1291 .ifa_index = dev->ifindex,
1295 if (cmd == RTM_NEWADDR)
1296 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1298 msg = nlmsg_alloc_simple(cmd, flags);
1302 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1303 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1305 if (addr->broadcast)
1306 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1307 if (addr->point_to_point)
1308 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1310 time_t now = system_get_rtime();
1311 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1313 if (addr->preferred_until) {
1314 int64_t preferred = addr->preferred_until - now;
1317 else if (preferred > UINT32_MAX)
1318 preferred = UINT32_MAX;
1320 cinfo.ifa_prefered = preferred;
1323 if (addr->valid_until) {
1324 int64_t valid = addr->valid_until - now;
1327 else if (valid > UINT32_MAX)
1330 cinfo.ifa_valid = valid;
1333 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1336 return system_rtnl_call(msg);
1339 int system_add_address(struct device *dev, struct device_addr *addr)
1341 return system_addr(dev, addr, RTM_NEWADDR);
1344 int system_del_address(struct device *dev, struct device_addr *addr)
1346 return system_addr(dev, addr, RTM_DELADDR);
1349 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1351 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1353 unsigned int flags = 0;
1356 have_gw = !!route->nexthop.in.s_addr;
1358 have_gw = route->nexthop.in6.s6_addr32[0] ||
1359 route->nexthop.in6.s6_addr32[1] ||
1360 route->nexthop.in6.s6_addr32[2] ||
1361 route->nexthop.in6.s6_addr32[3];
1363 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1364 ? route->table : RT_TABLE_MAIN;
1366 struct rtmsg rtm = {
1367 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1368 .rtm_dst_len = route->mask,
1369 .rtm_src_len = route->sourcemask,
1370 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1371 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
1372 .rtm_scope = RT_SCOPE_NOWHERE,
1373 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1374 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1378 if (cmd == RTM_NEWROUTE) {
1379 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1381 if (!dev) { // Add null-route
1382 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1383 rtm.rtm_type = RTN_UNREACHABLE;
1386 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1389 if (route->flags & DEVROUTE_TYPE) {
1390 rtm.rtm_type = route->type;
1391 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
1392 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
1393 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
1394 rtm.rtm_table = RT_TABLE_LOCAL;
1397 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT)
1398 rtm.rtm_scope = RT_SCOPE_HOST;
1399 else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
1400 rtm.rtm_type == RTN_ANYCAST)
1401 rtm.rtm_scope = RT_SCOPE_LINK;
1404 msg = nlmsg_alloc_simple(cmd, flags);
1408 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1411 nla_put(msg, RTA_DST, alen, &route->addr);
1413 if (route->sourcemask)
1414 nla_put(msg, RTA_SRC, alen, &route->source);
1416 if (route->metric > 0)
1417 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1420 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1423 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1426 nla_put_u32(msg, RTA_TABLE, table);
1428 if (route->flags & DEVROUTE_MTU) {
1429 struct nlattr *metrics;
1431 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1432 goto nla_put_failure;
1434 nla_put_u32(msg, RTAX_MTU, route->mtu);
1436 nla_nest_end(msg, metrics);
1439 return system_rtnl_call(msg);
1446 int system_add_route(struct device *dev, struct device_route *route)
1448 return system_rt(dev, route, RTM_NEWROUTE);
1451 int system_del_route(struct device *dev, struct device_route *route)
1453 return system_rt(dev, route, RTM_DELROUTE);
1456 int system_flush_routes(void)
1458 const char *names[] = {
1459 "/proc/sys/net/ipv4/route/flush",
1460 "/proc/sys/net/ipv6/route/flush"
1464 for (i = 0; i < ARRAY_SIZE(names); i++) {
1465 fd = open(names[i], O_WRONLY);
1469 if (write(fd, "-1", 2)) {}
1475 bool system_resolve_rt_type(const char *type, unsigned int *id)
1477 return system_rtn_aton(type, id);
1480 bool system_resolve_rt_table(const char *name, unsigned int *id)
1484 unsigned int n, table = RT_TABLE_UNSPEC;
1486 /* first try to parse table as number */
1487 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1490 /* handle well known aliases */
1491 else if (!strcmp(name, "default"))
1492 table = RT_TABLE_DEFAULT;
1493 else if (!strcmp(name, "main"))
1494 table = RT_TABLE_MAIN;
1495 else if (!strcmp(name, "local"))
1496 table = RT_TABLE_LOCAL;
1498 /* try to look up name in /etc/iproute2/rt_tables */
1499 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1501 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1503 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1506 n = strtoul(e, NULL, 10);
1507 e = strtok(NULL, " \t\n");
1509 if (e && !strcmp(e, name))
1519 if (table == RT_TABLE_UNSPEC)
1526 bool system_is_default_rt_table(unsigned int id)
1528 return (id == RT_TABLE_MAIN);
1531 bool system_resolve_rpfilter(const char *filter, unsigned int *id)
1536 if (!strcmp(filter, "strict"))
1538 else if (!strcmp(filter, "loose"))
1541 n = strtoul(filter, &e, 0);
1542 if (*e || e == filter || n > 2)
1550 static int system_iprule(struct iprule *rule, int cmd)
1552 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1555 struct rtmsg rtm = {
1556 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1557 .rtm_protocol = RTPROT_STATIC,
1558 .rtm_scope = RT_SCOPE_UNIVERSE,
1559 .rtm_table = RT_TABLE_UNSPEC,
1560 .rtm_type = RTN_UNSPEC,
1564 if (cmd == RTM_NEWRULE) {
1565 rtm.rtm_type = RTN_UNICAST;
1566 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1570 rtm.rtm_flags |= FIB_RULE_INVERT;
1572 if (rule->flags & IPRULE_SRC)
1573 rtm.rtm_src_len = rule->src_mask;
1575 if (rule->flags & IPRULE_DEST)
1576 rtm.rtm_dst_len = rule->dest_mask;
1578 if (rule->flags & IPRULE_TOS)
1579 rtm.rtm_tos = rule->tos;
1581 if (rule->flags & IPRULE_LOOKUP) {
1582 if (rule->lookup < 256)
1583 rtm.rtm_table = rule->lookup;
1586 if (rule->flags & IPRULE_ACTION)
1587 rtm.rtm_type = rule->action;
1588 else if (rule->flags & IPRULE_GOTO)
1589 rtm.rtm_type = FR_ACT_GOTO;
1590 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1591 rtm.rtm_type = FR_ACT_NOP;
1593 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1598 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1600 if (rule->flags & IPRULE_IN)
1601 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1603 if (rule->flags & IPRULE_OUT)
1604 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1606 if (rule->flags & IPRULE_SRC)
1607 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1609 if (rule->flags & IPRULE_DEST)
1610 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1612 if (rule->flags & IPRULE_PRIORITY)
1613 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1614 else if (cmd == RTM_NEWRULE)
1615 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1617 if (rule->flags & IPRULE_FWMARK)
1618 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1620 if (rule->flags & IPRULE_FWMASK)
1621 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1623 if (rule->flags & IPRULE_LOOKUP) {
1624 if (rule->lookup >= 256)
1625 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1628 if (rule->flags & IPRULE_GOTO)
1629 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1631 return system_rtnl_call(msg);
1634 int system_add_iprule(struct iprule *rule)
1636 return system_iprule(rule, RTM_NEWRULE);
1639 int system_del_iprule(struct iprule *rule)
1641 return system_iprule(rule, RTM_DELRULE);
1644 int system_flush_iprules(void)
1649 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1650 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1652 memset(&rule, 0, sizeof(rule));
1655 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1658 rule.lookup = RT_TABLE_LOCAL;
1659 rv |= system_iprule(&rule, RTM_NEWRULE);
1661 rule.priority = 32766;
1662 rule.lookup = RT_TABLE_MAIN;
1663 rv |= system_iprule(&rule, RTM_NEWRULE);
1665 rule.priority = 32767;
1666 rule.lookup = RT_TABLE_DEFAULT;
1667 rv |= system_iprule(&rule, RTM_NEWRULE);
1670 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1673 rule.lookup = RT_TABLE_LOCAL;
1674 rv |= system_iprule(&rule, RTM_NEWRULE);
1676 rule.priority = 32766;
1677 rule.lookup = RT_TABLE_MAIN;
1678 rv |= system_iprule(&rule, RTM_NEWRULE);
1683 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1685 return system_rtn_aton(action, id);
1688 time_t system_get_rtime(void)
1693 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1696 if (gettimeofday(&tv, NULL) == 0)
1703 #define IP_DF 0x4000
1706 static int tunnel_ioctl(const char *name, int cmd, void *p)
1710 memset(&ifr, 0, sizeof(ifr));
1711 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1712 ifr.ifr_ifru.ifru_data = p;
1713 return ioctl(sock_ioctl, cmd, &ifr);
1716 #ifdef IFLA_IPTUN_MAX
1717 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
1718 static int system_add_gre_tunnel(const char *name, const char *kind,
1719 const unsigned int link, struct blob_attr **tb, bool v6)
1722 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
1723 struct blob_attr *cur;
1724 uint32_t ikey = 0, okey = 0, flags = 0, flowinfo = 0;
1725 uint16_t iflags = 0, oflags = 0;
1727 int ret = 0, ttl = 64;
1729 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
1733 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
1734 nla_put_string(nlm, IFLA_IFNAME, name);
1736 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
1742 nla_put_string(nlm, IFLA_INFO_KIND, kind);
1743 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
1750 nla_put_u32(nlm, IFLA_GRE_LINK, link);
1752 if ((cur = tb[TUNNEL_ATTR_TTL]))
1753 ttl = blobmsg_get_u32(cur);
1755 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
1757 if ((cur = tb[TUNNEL_ATTR_TOS])) {
1758 char *str = blobmsg_get_string(cur);
1759 if (strcmp(str, "inherit")) {
1762 if (!system_tos_aton(str, &uval)) {
1768 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
1773 flags |= IP6_TNL_F_USE_ORIG_TCLASS;
1779 if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) {
1780 uint8_t icsum, ocsum, iseqno, oseqno;
1781 if (sscanf(blobmsg_get_string(cur), "%u,%u,%hhu,%hhu,%hhu,%hhu",
1782 &ikey, &okey, &icsum, &ocsum, &iseqno, &oseqno) < 6) {
1807 struct in6_addr in6buf;
1808 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1809 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1813 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
1816 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
1817 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1821 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
1823 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, 4);
1826 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
1829 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags);
1831 struct in_addr inbuf;
1834 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1835 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
1839 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
1842 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
1843 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
1847 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
1849 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
1851 okey = inbuf.s_addr;
1856 ikey = inbuf.s_addr;
1862 if ((cur = tb[TUNNEL_ATTR_DF]))
1863 set_df = blobmsg_get_bool(cur);
1865 /* ttl !=0 and nopmtudisc are incompatible */
1866 if (ttl && !set_df) {
1871 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
1873 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
1877 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
1880 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
1883 nla_put_u32(nlm, IFLA_GRE_OKEY, okey);
1886 nla_put_u32(nlm, IFLA_GRE_IKEY, ikey);
1888 nla_nest_end(nlm, infodata);
1889 nla_nest_end(nlm, linkinfo);
1891 return system_rtnl_call(nlm);
1899 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
1901 struct blob_attr *cur;
1903 struct ip_tunnel_parm p = {
1912 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
1913 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
1916 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
1917 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
1920 if ((cur = tb[TUNNEL_ATTR_DF]))
1921 set_df = blobmsg_get_bool(cur);
1923 if ((cur = tb[TUNNEL_ATTR_TTL]))
1924 p.iph.ttl = blobmsg_get_u32(cur);
1926 if ((cur = tb[TUNNEL_ATTR_TOS])) {
1927 char *str = blobmsg_get_string(cur);
1928 if (strcmp(str, "inherit")) {
1931 if (!system_tos_aton(str, &uval))
1939 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
1940 /* ttl !=0 and nopmtudisc are incompatible */
1941 if (p.iph.ttl && p.iph.frag_off == 0)
1944 strncpy(p.name, name, sizeof(p.name));
1946 switch (p.iph.protocol) {
1948 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
1950 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
1957 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
1959 struct blob_attr *cur;
1962 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
1964 str = blobmsg_data(cur);
1966 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
1967 !strcmp(str, "greip6") || !strcmp(str, "gretapip6"))
1968 return system_link_del(name);
1970 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
1973 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
1975 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
1977 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
1978 blob_data(attr), blob_len(attr));
1980 return __system_del_ip_tunnel(name, tb);
1983 int system_update_ipv6_mtu(struct device *dev, int mtu)
1987 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
1990 int fd = open(buf, O_RDWR);
1991 ssize_t len = read(fd, buf, sizeof(buf) - 1);
1998 if (!mtu || ret <= mtu)
2001 lseek(fd, 0, SEEK_SET);
2002 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) <= 0)
2010 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
2012 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2013 struct blob_attr *cur;
2016 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2017 blob_data(attr), blob_len(attr));
2019 __system_del_ip_tunnel(name, tb);
2021 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2023 str = blobmsg_data(cur);
2025 unsigned int ttl = 0;
2026 if ((cur = tb[TUNNEL_ATTR_TTL])) {
2027 ttl = blobmsg_get_u32(cur);
2032 unsigned int link = 0;
2033 if ((cur = tb[TUNNEL_ATTR_LINK])) {
2034 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
2038 if (iface->l3_dev.dev)
2039 link = iface->l3_dev.dev->ifindex;
2042 if (!strcmp(str, "sit")) {
2043 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
2047 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
2049 struct ip_tunnel_6rd p6;
2051 memset(&p6, 0, sizeof(p6));
2053 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
2054 &p6.prefix, &mask) || mask > 128)
2056 p6.prefixlen = mask;
2058 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
2059 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
2060 &p6.relay_prefix, &mask) || mask > 32)
2062 p6.relay_prefixlen = mask;
2065 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
2066 __system_del_ip_tunnel(name, tb);
2071 #ifdef IFLA_IPTUN_MAX
2072 } else if (!strcmp(str, "ipip6")) {
2073 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2074 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2075 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2081 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2082 nla_put_string(nlm, IFLA_IFNAME, name);
2085 nla_put_u32(nlm, IFLA_LINK, link);
2087 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2092 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2093 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2100 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2102 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2103 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2104 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
2106 struct in6_addr in6buf;
2107 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2108 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2112 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2115 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2116 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2120 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2123 #ifdef IFLA_IPTUN_FMR_MAX
2124 if ((cur = tb[TUNNEL_ATTR_FMRS])) {
2125 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2127 struct blob_attr *fmr;
2128 unsigned rem, fmrcnt = 0;
2129 blobmsg_for_each_attr(fmr, cur, rem) {
2130 if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
2133 unsigned ip4len, ip6len, ealen, offset = 6;
2137 if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
2138 ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) {
2143 struct in6_addr ip6prefix;
2144 struct in_addr ip4prefix;
2145 if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
2146 inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) {
2151 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2153 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2154 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2155 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2156 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2157 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2158 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2160 nla_nest_end(nlm, rule);
2163 nla_nest_end(nlm, fmrs);
2167 nla_nest_end(nlm, infodata);
2168 nla_nest_end(nlm, linkinfo);
2170 return system_rtnl_call(nlm);
2174 } else if (!strcmp(str, "greip")) {
2175 return system_add_gre_tunnel(name, "gre", link, tb, false);
2176 } else if (!strcmp(str, "gretapip")) {
2177 return system_add_gre_tunnel(name, "gretap", link, tb, false);
2178 } else if (!strcmp(str, "greip6")) {
2179 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
2180 } else if (!strcmp(str, "gretapip6")) {
2181 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
2183 } else if (!strcmp(str, "ipip")) {
2184 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);