2 * netifd - network interface daemon
3 * Copyright (C) 2012 Felix Fietkau <nbd@openwrt.org>
4 * Copyright (C) 2013 Jo-Philipp Wich <jow@openwrt.org>
5 * Copyright (C) 2013 Steven Barth <steven@midlink.org>
6 * Copyright (C) 2014 Gioacchino Mazzurco <gio@eigenlab.org>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2
10 * as published by the Free Software Foundation
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
19 #include <sys/socket.h>
20 #include <sys/ioctl.h>
22 #include <sys/syscall.h>
25 #include <net/if_arp.h>
27 #include <arpa/inet.h>
28 #include <netinet/in.h>
30 #include <linux/rtnetlink.h>
31 #include <linux/sockios.h>
33 #include <linux/if_link.h>
34 #include <linux/if_vlan.h>
35 #include <linux/if_bridge.h>
36 #include <linux/if_tunnel.h>
37 #include <linux/ip6_tunnel.h>
38 #include <linux/ethtool.h>
39 #include <linux/fib_rules.h>
40 #include <linux/version.h>
42 #ifndef RTN_FAILED_POLICY
43 #define RTN_FAILED_POLICY 12
51 #include <netlink/msg.h>
52 #include <netlink/attr.h>
53 #include <netlink/socket.h>
54 #include <libubox/uloop.h>
61 struct uloop_fd uloop;
66 static int sock_ioctl = -1;
67 static struct nl_sock *sock_rtnl = NULL;
69 static int cb_rtnl_event(struct nl_msg *msg, void *arg);
70 static void handle_hotplug_event(struct uloop_fd *u, unsigned int events);
72 static char dev_buf[256];
75 handler_nl_event(struct uloop_fd *u, unsigned int events)
77 struct event_socket *ev = container_of(u, struct event_socket, uloop);
79 socklen_t errlen = sizeof(err);
82 nl_recvmsgs_default(ev->sock);
86 if (getsockopt(u->fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen))
91 // Increase rx buffer size on netlink socket
93 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
96 // Request full dump since some info got dropped
97 struct rtgenmsg msg = { .rtgen_family = AF_UNSPEC };
98 nl_send_simple(ev->sock, RTM_GETLINK, NLM_F_DUMP, &msg, sizeof(msg));
108 uloop_fd_delete(&ev->uloop);
112 static struct nl_sock *
113 create_socket(int protocol, int groups)
115 struct nl_sock *sock;
117 sock = nl_socket_alloc();
122 nl_join_groups(sock, groups);
124 if (nl_connect(sock, protocol))
131 create_raw_event_socket(struct event_socket *ev, int protocol, int groups,
132 uloop_fd_handler cb, int flags)
134 ev->sock = create_socket(protocol, groups);
138 ev->uloop.fd = nl_socket_get_fd(ev->sock);
140 if (uloop_fd_add(&ev->uloop, ULOOP_READ|flags))
147 create_event_socket(struct event_socket *ev, int protocol,
148 int (*cb)(struct nl_msg *msg, void *arg))
150 if (!create_raw_event_socket(ev, protocol, 0, handler_nl_event, ULOOP_ERROR_CB))
153 // Install the valid custom callback handler
154 nl_socket_modify_cb(ev->sock, NL_CB_VALID, NL_CB_CUSTOM, cb, NULL);
156 // Disable sequence number checking on event sockets
157 nl_socket_disable_seq_check(ev->sock);
159 // Increase rx buffer size to 65K on event sockets
161 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
168 system_rtn_aton(const char *src, unsigned int *dst)
173 if (!strcmp(src, "local"))
175 else if (!strcmp(src, "nat"))
177 else if (!strcmp(src, "broadcast"))
179 else if (!strcmp(src, "anycast"))
181 else if (!strcmp(src, "multicast"))
183 else if (!strcmp(src, "prohibit"))
185 else if (!strcmp(src, "unreachable"))
187 else if (!strcmp(src, "blackhole"))
189 else if (!strcmp(src, "xresolve"))
191 else if (!strcmp(src, "unicast"))
193 else if (!strcmp(src, "throw"))
195 else if (!strcmp(src, "failed_policy"))
196 n = RTN_FAILED_POLICY;
198 n = strtoul(src, &e, 0);
199 if (!e || *e || e == src || n > 255)
208 system_tos_aton(const char *src, unsigned *dst)
212 *dst = strtoul(src, &e, 16);
213 if (e == src || *e || *dst > 255)
219 int system_init(void)
221 static struct event_socket rtnl_event;
222 static struct event_socket hotplug_event;
224 sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0);
225 system_fd_set_cloexec(sock_ioctl);
227 // Prepare socket for routing / address control
228 sock_rtnl = create_socket(NETLINK_ROUTE, 0);
232 if (!create_event_socket(&rtnl_event, NETLINK_ROUTE, cb_rtnl_event))
235 if (!create_raw_event_socket(&hotplug_event, NETLINK_KOBJECT_UEVENT, 1,
236 handle_hotplug_event, 0))
239 // Receive network link events form kernel
240 nl_socket_add_membership(rtnl_event.sock, RTNLGRP_LINK);
245 static void system_set_sysctl(const char *path, const char *val)
249 fd = open(path, O_WRONLY);
253 if (write(fd, val, strlen(val))) {}
257 static void system_set_dev_sysctl(const char *path, const char *device, const char *val)
259 snprintf(dev_buf, sizeof(dev_buf), path, device);
260 system_set_sysctl(dev_buf, val);
263 static void system_set_disable_ipv6(struct device *dev, const char *val)
265 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val);
268 static int system_get_sysctl(const char *path, char *buf, const size_t buf_sz)
270 int fd = -1, ret = -1;
272 fd = open(path, O_RDONLY);
276 ssize_t len = read(fd, buf, buf_sz - 1);
290 system_get_dev_sysctl(const char *path, const char *device, char *buf, const size_t buf_sz)
292 snprintf(dev_buf, sizeof(dev_buf), path, device);
293 return system_get_sysctl(dev_buf, buf, buf_sz);
296 static int system_get_disable_ipv6(struct device *dev, char *buf, const size_t buf_sz)
298 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6",
299 dev->ifname, buf, buf_sz);
303 #define IFF_LOWER_UP 0x10000
306 // Evaluate netlink messages
307 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
309 struct nlmsghdr *nh = nlmsg_hdr(msg);
310 struct ifinfomsg *ifi = NLMSG_DATA(nh);
311 struct nlattr *nla[__IFLA_MAX];
313 if (nh->nlmsg_type != RTM_NEWLINK)
316 nlmsg_parse(nh, sizeof(*ifi), nla, __IFLA_MAX - 1, NULL);
317 if (!nla[IFLA_IFNAME])
320 struct device *dev = device_get(nla_data(nla[IFLA_IFNAME]), false);
324 device_set_ifindex(dev, ifi->ifi_index);
325 if (!dev->type->keep_link_status)
326 device_set_link(dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
333 handle_hotplug_msg(char *data, int size)
335 const char *subsystem = NULL, *interface = NULL;
336 char *cur, *end, *sep;
341 if (!strncmp(data, "add@", 4))
343 else if (!strncmp(data, "remove@", 7))
348 skip = strlen(data) + 1;
351 for (cur = data + skip; cur < end; cur += skip) {
352 skip = strlen(cur) + 1;
354 sep = strchr(cur, '=');
359 if (!strcmp(cur, "INTERFACE"))
361 else if (!strcmp(cur, "SUBSYSTEM")) {
363 if (strcmp(subsystem, "net") != 0)
366 if (subsystem && interface)
372 dev = device_get(interface, false);
376 if (dev->type != &simple_device_type)
379 if (add && system_if_force_external(dev->ifname))
382 device_set_present(dev, add);
386 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
388 struct event_socket *ev = container_of(u, struct event_socket, uloop);
389 struct sockaddr_nl nla;
390 unsigned char *buf = NULL;
393 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
395 handle_hotplug_msg((char *) buf, size);
401 static int system_rtnl_call(struct nl_msg *msg)
405 ret = nl_send_auto_complete(sock_rtnl, msg);
411 return nl_wait_for_ack(sock_rtnl);
414 int system_bridge_delbr(struct device *bridge)
416 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
419 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
423 memset(&ifr, 0, sizeof(ifr));
425 ifr.ifr_ifindex = dev->ifindex;
428 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
429 return ioctl(sock_ioctl, cmd, &ifr);
432 static bool system_is_bridge(const char *name, char *buf, int buflen)
436 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
437 if (stat(buf, &st) < 0)
443 static char *system_get_bridge(const char *name, char *buf, int buflen)
449 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
450 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
453 if (gl.gl_pathc == 0)
456 len = readlink(gl.gl_pathv[0], buf, buflen);
461 path = strrchr(buf, '/');
468 static void system_bridge_set_wireless(const char *bridge, const char *dev)
470 snprintf(dev_buf, sizeof(dev_buf),
471 "/sys/devices/virtual/net/%s/brif/%s/multicast_to_unicast",
473 system_set_sysctl(dev_buf, "1");
476 int system_bridge_addif(struct device *bridge, struct device *dev)
481 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
482 if (!oldbr || strcmp(oldbr, bridge->ifname) != 0)
483 ret = system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
486 system_bridge_set_wireless(bridge->ifname, dev->ifname);
491 int system_bridge_delif(struct device *bridge, struct device *dev)
493 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
496 static int system_if_resolve(struct device *dev)
499 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
500 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
501 return ifr.ifr_ifindex;
506 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
510 memset(&ifr, 0, sizeof(ifr));
511 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
512 ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
513 ifr.ifr_flags |= add;
514 ifr.ifr_flags &= ~rem;
515 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
527 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
529 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
531 return ifa->ifa_index == ifindex;
534 static bool check_route(struct nlmsghdr *hdr, int ifindex)
536 struct rtmsg *r = NLMSG_DATA(hdr);
537 struct nlattr *tb[__RTA_MAX];
539 if (r->rtm_protocol == RTPROT_KERNEL &&
540 r->rtm_family == AF_INET6)
543 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
547 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
550 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
555 static int cb_clear_event(struct nl_msg *msg, void *arg)
557 struct clear_data *clr = arg;
558 struct nlmsghdr *hdr = nlmsg_hdr(msg);
559 bool (*cb)(struct nlmsghdr *, int ifindex);
565 if (hdr->nlmsg_type != RTM_NEWADDR)
572 if (hdr->nlmsg_type != RTM_NEWROUTE)
579 if (hdr->nlmsg_type != RTM_NEWRULE)
588 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
591 if (type == RTM_DELRULE)
592 D(SYSTEM, "Remove a rule\n");
594 D(SYSTEM, "Remove %s from device %s\n",
595 type == RTM_DELADDR ? "an address" : "a route",
597 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
598 hdr = nlmsg_hdr(clr->msg);
599 hdr->nlmsg_type = type;
600 hdr->nlmsg_flags = NLM_F_REQUEST;
602 nl_socket_disable_auto_ack(sock_rtnl);
603 nl_send_auto_complete(sock_rtnl, clr->msg);
604 nl_socket_enable_auto_ack(sock_rtnl);
610 cb_finish_event(struct nl_msg *msg, void *arg)
618 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
621 *pending = err->error;
626 system_if_clear_entries(struct device *dev, int type, int af)
628 struct clear_data clr;
629 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
632 .rtm_flags = RTM_F_CLONED,
634 int flags = NLM_F_DUMP;
643 clr.size = sizeof(struct rtgenmsg);
646 clr.size = sizeof(struct rtmsg);
655 clr.msg = nlmsg_alloc_simple(type, flags);
659 nlmsg_append(clr.msg, &rtm, clr.size, 0);
660 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
661 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
662 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
664 nl_send_auto_complete(sock_rtnl, clr.msg);
666 nl_recvmsgs(sock_rtnl, cb);
674 * Clear bridge (membership) state and bring down device
676 void system_if_clear_state(struct device *dev)
678 static char buf[256];
681 device_set_ifindex(dev, system_if_resolve(dev));
682 if (dev->external || !dev->ifindex)
685 system_if_flags(dev->ifname, 0, IFF_UP);
687 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
688 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
689 system_bridge_delbr(dev);
693 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
695 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
696 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
699 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
700 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
701 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
702 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
703 system_set_disable_ipv6(dev, "0");
706 static inline unsigned long
707 sec_to_jiffies(int val)
709 return (unsigned long) val * 100;
712 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
714 unsigned long args[4] = {};
716 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
719 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
720 args[1] = !!cfg->stp;
721 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
723 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
724 args[1] = sec_to_jiffies(cfg->forward_delay);
725 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
727 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
728 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
730 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier",
731 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
733 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
734 args[1] = cfg->priority;
735 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
737 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
738 args[0] = BRCTL_SET_AGEING_TIME;
739 args[1] = sec_to_jiffies(cfg->ageing_time);
740 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
743 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
744 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
745 args[1] = sec_to_jiffies(cfg->hello_time);
746 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
749 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
750 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
751 args[1] = sec_to_jiffies(cfg->max_age);
752 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
758 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
761 struct nlattr *linkinfo, *data;
762 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
763 int ifindex = system_if_resolve(dev);
765 static const struct {
767 enum macvlan_mode val;
769 { "private", MACVLAN_MODE_PRIVATE },
770 { "vepa", MACVLAN_MODE_VEPA },
771 { "bridge", MACVLAN_MODE_BRIDGE },
772 { "passthru", MACVLAN_MODE_PASSTHRU },
778 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
783 nlmsg_append(msg, &iim, sizeof(iim), 0);
785 if (cfg->flags & MACVLAN_OPT_MACADDR)
786 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
787 nla_put_string(msg, IFLA_IFNAME, macvlan->ifname);
788 nla_put_u32(msg, IFLA_LINK, ifindex);
790 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
791 goto nla_put_failure;
793 nla_put_string(msg, IFLA_INFO_KIND, "macvlan");
795 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
796 goto nla_put_failure;
799 for (i = 0; i < ARRAY_SIZE(modes); i++) {
800 if (strcmp(cfg->mode, modes[i].name) != 0)
803 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
808 nla_nest_end(msg, data);
809 nla_nest_end(msg, linkinfo);
811 rv = system_rtnl_call(msg);
813 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
822 static int system_link_del(const char *ifname)
825 struct ifinfomsg iim = {
826 .ifi_family = AF_UNSPEC,
830 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
835 nlmsg_append(msg, &iim, sizeof(iim), 0);
836 nla_put_string(msg, IFLA_IFNAME, ifname);
837 return system_rtnl_call(msg);
840 int system_macvlan_del(struct device *macvlan)
842 return system_link_del(macvlan->ifname);
845 static int system_vlan(struct device *dev, int id)
847 struct vlan_ioctl_args ifr = {
848 .cmd = SET_VLAN_NAME_TYPE_CMD,
849 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
852 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
855 ifr.cmd = DEL_VLAN_CMD;
858 ifr.cmd = ADD_VLAN_CMD;
861 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
862 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
865 int system_vlan_add(struct device *dev, int id)
867 return system_vlan(dev, id);
870 int system_vlan_del(struct device *dev)
872 return system_vlan(dev, -1);
875 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
878 struct nlattr *linkinfo, *data;
879 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
880 int ifindex = system_if_resolve(dev);
886 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
891 nlmsg_append(msg, &iim, sizeof(iim), 0);
892 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
893 nla_put_u32(msg, IFLA_LINK, ifindex);
895 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
896 goto nla_put_failure;
898 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
900 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
901 goto nla_put_failure;
903 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
905 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
906 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
908 if(cfg->proto == VLAN_PROTO_8021AD)
909 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);
912 nla_nest_end(msg, data);
913 nla_nest_end(msg, linkinfo);
915 rv = system_rtnl_call(msg);
917 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
926 int system_vlandev_del(struct device *vlandev)
928 return system_link_del(vlandev->ifname);
932 system_if_get_settings(struct device *dev, struct device_settings *s)
937 memset(&ifr, 0, sizeof(ifr));
938 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
940 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
941 s->mtu = ifr.ifr_mtu;
942 s->flags |= DEV_OPT_MTU;
945 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
946 s->txqueuelen = ifr.ifr_qlen;
947 s->flags |= DEV_OPT_TXQUEUELEN;
950 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
951 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
952 s->flags |= DEV_OPT_MACADDR;
955 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
956 s->ipv6 = !strtoul(buf, NULL, 0);
957 s->flags |= DEV_OPT_IPV6;
960 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
961 s->promisc = ifr.ifr_flags & IFF_PROMISC;
962 s->flags |= DEV_OPT_PROMISC;
967 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
974 memset(&ifr, 0, sizeof(ifr));
975 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
976 if (s->flags & DEV_OPT_MTU & apply_mask) {
977 ifr.ifr_mtu = s->mtu;
978 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
979 s->flags &= ~DEV_OPT_MTU;
981 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
982 ifr.ifr_qlen = s->txqueuelen;
983 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
984 s->flags &= ~DEV_OPT_TXQUEUELEN;
986 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
987 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
988 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
989 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
990 s->flags &= ~DEV_OPT_MACADDR;
992 if (s->flags & DEV_OPT_IPV6 & apply_mask)
993 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
994 if (s->flags & DEV_OPT_PROMISC & apply_mask) {
995 if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
996 !s->promisc ? IFF_PROMISC : 0) < 0)
997 s->flags &= ~DEV_OPT_PROMISC;
1001 int system_if_up(struct device *dev)
1003 system_if_get_settings(dev, &dev->orig_settings);
1004 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
1005 device_set_ifindex(dev, system_if_resolve(dev));
1006 return system_if_flags(dev->ifname, IFF_UP, 0);
1009 int system_if_down(struct device *dev)
1011 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
1012 dev->orig_settings.flags &= dev->settings.flags;
1013 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
1017 struct if_check_data {
1023 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1025 struct nlmsghdr *nh = nlmsg_hdr(msg);
1026 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1027 struct if_check_data *chk = (struct if_check_data *)arg;
1029 if (nh->nlmsg_type != RTM_NEWLINK)
1032 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1033 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1038 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1040 struct if_check_data *chk = (struct if_check_data *)arg;
1045 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1047 struct if_check_data *chk = (struct if_check_data *)arg;
1049 device_set_present(chk->dev, false);
1050 device_set_link(chk->dev, false);
1051 chk->pending = err->error;
1056 int system_if_check(struct device *dev)
1058 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1060 struct ifinfomsg ifi = {
1061 .ifi_family = AF_UNSPEC,
1064 struct if_check_data chk = {
1070 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1071 if (!msg || nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1072 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1075 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1076 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1077 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1079 nl_send_auto_complete(sock_rtnl, msg);
1080 while (chk.pending > 0)
1081 nl_recvmsgs(sock_rtnl, cb);
1092 system_if_get_parent(struct device *dev)
1094 char buf[64], *devname;
1095 int ifindex, iflink, len;
1098 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1099 f = fopen(buf, "r");
1103 len = fread(buf, 1, sizeof(buf) - 1, f);
1110 iflink = strtoul(buf, NULL, 0);
1111 ifindex = system_if_resolve(dev);
1112 if (!iflink || iflink == ifindex)
1115 devname = if_indextoname(iflink, buf);
1119 return device_get(devname, true);
1123 read_string_file(int dir_fd, const char *file, char *buf, int len)
1129 fd = openat(dir_fd, file, O_RDONLY);
1134 len = read(fd, buf, len - 1);
1138 } else if (len > 0) {
1141 c = strchr(buf, '\n');
1154 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1159 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1161 *val = strtoull(buf, NULL, 0);
1166 /* Assume advertised flags == supported flags */
1167 static const struct {
1170 } ethtool_link_modes[] = {
1171 { ADVERTISED_10baseT_Half, "10H" },
1172 { ADVERTISED_10baseT_Full, "10F" },
1173 { ADVERTISED_100baseT_Half, "100H" },
1174 { ADVERTISED_100baseT_Full, "100F" },
1175 { ADVERTISED_1000baseT_Half, "1000H" },
1176 { ADVERTISED_1000baseT_Full, "1000F" },
1179 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1182 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1183 if (mask & ethtool_link_modes[i].mask)
1184 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1189 system_if_force_external(const char *ifname)
1194 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1195 return stat(buf, &s) == 0;
1199 system_if_dump_info(struct device *dev, struct blob_buf *b)
1201 struct ethtool_cmd ecmd;
1207 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
1208 dir_fd = open(buf, O_DIRECTORY);
1210 memset(&ecmd, 0, sizeof(ecmd));
1211 memset(&ifr, 0, sizeof(ifr));
1212 strcpy(ifr.ifr_name, dev->ifname);
1213 ifr.ifr_data = (caddr_t) &ecmd;
1214 ecmd.cmd = ETHTOOL_GSET;
1216 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1217 c = blobmsg_open_array(b, "link-advertising");
1218 system_add_link_modes(b, ecmd.advertising);
1219 blobmsg_close_array(b, c);
1221 c = blobmsg_open_array(b, "link-supported");
1222 system_add_link_modes(b, ecmd.supported);
1223 blobmsg_close_array(b, c);
1225 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1226 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1227 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1228 blobmsg_add_string_buffer(b);
1236 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1238 const char *const counters[] = {
1239 "collisions", "rx_frame_errors", "tx_compressed",
1240 "multicast", "rx_length_errors", "tx_dropped",
1241 "rx_bytes", "rx_missed_errors", "tx_errors",
1242 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1243 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1244 "rx_dropped", "tx_aborted_errors", "tx_packets",
1245 "rx_errors", "tx_bytes", "tx_window_errors",
1246 "rx_fifo_errors", "tx_carrier_errors",
1253 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1254 stats_dir = open(buf, O_DIRECTORY);
1258 for (i = 0; i < ARRAY_SIZE(counters); i++)
1259 if (read_uint64_file(stats_dir, counters[i], &val))
1260 blobmsg_add_u64(b, counters[i], val);
1266 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1268 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1269 int alen = v4 ? 4 : 16;
1270 unsigned int flags = 0;
1271 struct ifaddrmsg ifa = {
1272 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1273 .ifa_prefixlen = addr->mask,
1274 .ifa_index = dev->ifindex,
1278 if (cmd == RTM_NEWADDR)
1279 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1281 msg = nlmsg_alloc_simple(cmd, flags);
1285 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1286 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1288 if (addr->broadcast)
1289 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1290 if (addr->point_to_point)
1291 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1293 time_t now = system_get_rtime();
1294 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1296 if (addr->preferred_until) {
1297 int64_t preferred = addr->preferred_until - now;
1300 else if (preferred > UINT32_MAX)
1301 preferred = UINT32_MAX;
1303 cinfo.ifa_prefered = preferred;
1306 if (addr->valid_until) {
1307 int64_t valid = addr->valid_until - now;
1310 else if (valid > UINT32_MAX)
1313 cinfo.ifa_valid = valid;
1316 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1319 return system_rtnl_call(msg);
1322 int system_add_address(struct device *dev, struct device_addr *addr)
1324 return system_addr(dev, addr, RTM_NEWADDR);
1327 int system_del_address(struct device *dev, struct device_addr *addr)
1329 return system_addr(dev, addr, RTM_DELADDR);
1332 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1334 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1336 unsigned int flags = 0;
1339 have_gw = !!route->nexthop.in.s_addr;
1341 have_gw = route->nexthop.in6.s6_addr32[0] ||
1342 route->nexthop.in6.s6_addr32[1] ||
1343 route->nexthop.in6.s6_addr32[2] ||
1344 route->nexthop.in6.s6_addr32[3];
1346 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1347 ? route->table : RT_TABLE_MAIN;
1349 struct rtmsg rtm = {
1350 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1351 .rtm_dst_len = route->mask,
1352 .rtm_src_len = route->sourcemask,
1353 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1354 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
1355 .rtm_scope = RT_SCOPE_NOWHERE,
1356 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1357 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1361 if (cmd == RTM_NEWROUTE) {
1362 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1364 if (!dev) { // Add null-route
1365 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1366 rtm.rtm_type = RTN_UNREACHABLE;
1369 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1372 if (route->flags & DEVROUTE_TYPE) {
1373 rtm.rtm_type = route->type;
1374 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
1375 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
1376 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
1377 rtm.rtm_table = RT_TABLE_LOCAL;
1380 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT)
1381 rtm.rtm_scope = RT_SCOPE_HOST;
1382 else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
1383 rtm.rtm_type == RTN_ANYCAST)
1384 rtm.rtm_scope = RT_SCOPE_LINK;
1387 msg = nlmsg_alloc_simple(cmd, flags);
1391 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1394 nla_put(msg, RTA_DST, alen, &route->addr);
1396 if (route->sourcemask)
1397 nla_put(msg, RTA_SRC, alen, &route->source);
1399 if (route->metric > 0)
1400 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1403 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1406 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1409 nla_put_u32(msg, RTA_TABLE, table);
1411 if (route->flags & DEVROUTE_MTU) {
1412 struct nlattr *metrics;
1414 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1415 goto nla_put_failure;
1417 nla_put_u32(msg, RTAX_MTU, route->mtu);
1419 nla_nest_end(msg, metrics);
1422 return system_rtnl_call(msg);
1429 int system_add_route(struct device *dev, struct device_route *route)
1431 return system_rt(dev, route, RTM_NEWROUTE);
1434 int system_del_route(struct device *dev, struct device_route *route)
1436 return system_rt(dev, route, RTM_DELROUTE);
1439 int system_flush_routes(void)
1441 const char *names[] = {
1442 "/proc/sys/net/ipv4/route/flush",
1443 "/proc/sys/net/ipv6/route/flush"
1447 for (i = 0; i < ARRAY_SIZE(names); i++) {
1448 fd = open(names[i], O_WRONLY);
1452 if (write(fd, "-1", 2)) {}
1458 bool system_resolve_rt_type(const char *type, unsigned int *id)
1460 return system_rtn_aton(type, id);
1463 bool system_resolve_rt_table(const char *name, unsigned int *id)
1467 unsigned int n, table = RT_TABLE_UNSPEC;
1469 /* first try to parse table as number */
1470 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1473 /* handle well known aliases */
1474 else if (!strcmp(name, "default"))
1475 table = RT_TABLE_DEFAULT;
1476 else if (!strcmp(name, "main"))
1477 table = RT_TABLE_MAIN;
1478 else if (!strcmp(name, "local"))
1479 table = RT_TABLE_LOCAL;
1481 /* try to look up name in /etc/iproute2/rt_tables */
1482 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1484 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1486 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1489 n = strtoul(e, NULL, 10);
1490 e = strtok(NULL, " \t\n");
1492 if (e && !strcmp(e, name))
1502 if (table == RT_TABLE_UNSPEC)
1509 bool system_is_default_rt_table(unsigned int id)
1511 return (id == RT_TABLE_MAIN);
1514 static int system_iprule(struct iprule *rule, int cmd)
1516 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1519 struct rtmsg rtm = {
1520 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1521 .rtm_protocol = RTPROT_STATIC,
1522 .rtm_scope = RT_SCOPE_UNIVERSE,
1523 .rtm_table = RT_TABLE_UNSPEC,
1524 .rtm_type = RTN_UNSPEC,
1528 if (cmd == RTM_NEWRULE) {
1529 rtm.rtm_type = RTN_UNICAST;
1530 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1534 rtm.rtm_flags |= FIB_RULE_INVERT;
1536 if (rule->flags & IPRULE_SRC)
1537 rtm.rtm_src_len = rule->src_mask;
1539 if (rule->flags & IPRULE_DEST)
1540 rtm.rtm_dst_len = rule->dest_mask;
1542 if (rule->flags & IPRULE_TOS)
1543 rtm.rtm_tos = rule->tos;
1545 if (rule->flags & IPRULE_LOOKUP) {
1546 if (rule->lookup < 256)
1547 rtm.rtm_table = rule->lookup;
1550 if (rule->flags & IPRULE_ACTION)
1551 rtm.rtm_type = rule->action;
1552 else if (rule->flags & IPRULE_GOTO)
1553 rtm.rtm_type = FR_ACT_GOTO;
1554 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1555 rtm.rtm_type = FR_ACT_NOP;
1557 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1562 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1564 if (rule->flags & IPRULE_IN)
1565 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1567 if (rule->flags & IPRULE_OUT)
1568 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1570 if (rule->flags & IPRULE_SRC)
1571 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1573 if (rule->flags & IPRULE_DEST)
1574 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1576 if (rule->flags & IPRULE_PRIORITY)
1577 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1578 else if (cmd == RTM_NEWRULE)
1579 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1581 if (rule->flags & IPRULE_FWMARK)
1582 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1584 if (rule->flags & IPRULE_FWMASK)
1585 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1587 if (rule->flags & IPRULE_LOOKUP) {
1588 if (rule->lookup >= 256)
1589 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1592 if (rule->flags & IPRULE_GOTO)
1593 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1595 return system_rtnl_call(msg);
1598 int system_add_iprule(struct iprule *rule)
1600 return system_iprule(rule, RTM_NEWRULE);
1603 int system_del_iprule(struct iprule *rule)
1605 return system_iprule(rule, RTM_DELRULE);
1608 int system_flush_iprules(void)
1613 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1614 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1616 memset(&rule, 0, sizeof(rule));
1619 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1622 rule.lookup = RT_TABLE_LOCAL;
1623 rv |= system_iprule(&rule, RTM_NEWRULE);
1625 rule.priority = 32766;
1626 rule.lookup = RT_TABLE_MAIN;
1627 rv |= system_iprule(&rule, RTM_NEWRULE);
1629 rule.priority = 32767;
1630 rule.lookup = RT_TABLE_DEFAULT;
1631 rv |= system_iprule(&rule, RTM_NEWRULE);
1634 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1637 rule.lookup = RT_TABLE_LOCAL;
1638 rv |= system_iprule(&rule, RTM_NEWRULE);
1640 rule.priority = 32766;
1641 rule.lookup = RT_TABLE_MAIN;
1642 rv |= system_iprule(&rule, RTM_NEWRULE);
1647 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1649 return system_rtn_aton(action, id);
1652 time_t system_get_rtime(void)
1657 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1660 if (gettimeofday(&tv, NULL) == 0)
1667 #define IP_DF 0x4000
1670 static int tunnel_ioctl(const char *name, int cmd, void *p)
1674 memset(&ifr, 0, sizeof(ifr));
1675 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1676 ifr.ifr_ifru.ifru_data = p;
1677 return ioctl(sock_ioctl, cmd, &ifr);
1680 #ifdef IFLA_IPTUN_MAX
1681 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
1682 static int system_add_gre_tunnel(const char *name, const char *kind,
1683 const unsigned int link, struct blob_attr **tb, bool v6)
1686 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
1687 struct blob_attr *cur;
1688 uint32_t ikey = 0, okey = 0, flags = 0, flowinfo = 0;
1689 uint16_t iflags = 0, oflags = 0;
1691 int ret = 0, ttl = 64;
1693 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
1697 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
1698 nla_put_string(nlm, IFLA_IFNAME, name);
1700 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
1706 nla_put_string(nlm, IFLA_INFO_KIND, kind);
1707 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
1714 nla_put_u32(nlm, IFLA_GRE_LINK, link);
1716 if ((cur = tb[TUNNEL_ATTR_TTL]))
1717 ttl = blobmsg_get_u32(cur);
1719 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
1721 if ((cur = tb[TUNNEL_ATTR_TOS])) {
1722 char *str = blobmsg_get_string(cur);
1723 if (strcmp(str, "inherit")) {
1726 if (!system_tos_aton(str, &uval)) {
1732 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
1737 flags |= IP6_TNL_F_USE_ORIG_TCLASS;
1743 if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) {
1744 uint8_t icsum, ocsum, iseqno, oseqno;
1745 if (sscanf(blobmsg_get_string(cur), "%u,%u,%hhu,%hhu,%hhu,%hhu",
1746 &ikey, &okey, &icsum, &ocsum, &iseqno, &oseqno) < 6) {
1771 struct in6_addr in6buf;
1772 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1773 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1777 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
1780 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
1781 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1785 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
1787 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, 4);
1790 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
1793 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags);
1795 struct in_addr inbuf;
1798 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1799 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
1803 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
1806 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
1807 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
1811 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
1813 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
1815 okey = inbuf.s_addr;
1820 ikey = inbuf.s_addr;
1826 if ((cur = tb[TUNNEL_ATTR_DF]))
1827 set_df = blobmsg_get_bool(cur);
1829 /* ttl !=0 and nopmtudisc are incompatible */
1830 if (ttl && !set_df) {
1835 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
1837 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
1841 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
1844 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
1847 nla_put_u32(nlm, IFLA_GRE_OKEY, okey);
1850 nla_put_u32(nlm, IFLA_GRE_IKEY, ikey);
1852 nla_nest_end(nlm, infodata);
1853 nla_nest_end(nlm, linkinfo);
1855 return system_rtnl_call(nlm);
1863 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
1865 struct blob_attr *cur;
1867 struct ip_tunnel_parm p = {
1876 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
1877 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
1880 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
1881 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
1884 if ((cur = tb[TUNNEL_ATTR_DF]))
1885 set_df = blobmsg_get_bool(cur);
1887 if ((cur = tb[TUNNEL_ATTR_TTL]))
1888 p.iph.ttl = blobmsg_get_u32(cur);
1890 if ((cur = tb[TUNNEL_ATTR_TOS])) {
1891 char *str = blobmsg_get_string(cur);
1892 if (strcmp(str, "inherit")) {
1895 if (!system_tos_aton(str, &uval))
1903 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
1904 /* ttl !=0 and nopmtudisc are incompatible */
1905 if (p.iph.ttl && p.iph.frag_off == 0)
1908 strncpy(p.name, name, sizeof(p.name));
1910 switch (p.iph.protocol) {
1912 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
1914 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
1921 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
1923 struct blob_attr *cur;
1926 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
1928 str = blobmsg_data(cur);
1930 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
1931 !strcmp(str, "greip6") || !strcmp(str, "gretapip6"))
1932 return system_link_del(name);
1934 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
1937 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
1939 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
1941 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
1942 blob_data(attr), blob_len(attr));
1944 return __system_del_ip_tunnel(name, tb);
1947 int system_update_ipv6_mtu(struct device *dev, int mtu)
1951 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
1954 int fd = open(buf, O_RDWR);
1955 ssize_t len = read(fd, buf, sizeof(buf) - 1);
1962 if (!mtu || ret <= mtu)
1965 lseek(fd, 0, SEEK_SET);
1966 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) <= 0)
1974 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
1976 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
1977 struct blob_attr *cur;
1980 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
1981 blob_data(attr), blob_len(attr));
1983 __system_del_ip_tunnel(name, tb);
1985 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
1987 str = blobmsg_data(cur);
1989 unsigned int ttl = 0;
1990 if ((cur = tb[TUNNEL_ATTR_TTL])) {
1991 ttl = blobmsg_get_u32(cur);
1996 unsigned int link = 0;
1997 if ((cur = tb[TUNNEL_ATTR_LINK])) {
1998 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
2002 if (iface->l3_dev.dev)
2003 link = iface->l3_dev.dev->ifindex;
2006 if (!strcmp(str, "sit")) {
2007 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
2011 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
2013 struct ip_tunnel_6rd p6;
2015 memset(&p6, 0, sizeof(p6));
2017 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
2018 &p6.prefix, &mask) || mask > 128)
2020 p6.prefixlen = mask;
2022 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
2023 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
2024 &p6.relay_prefix, &mask) || mask > 32)
2026 p6.relay_prefixlen = mask;
2029 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
2030 __system_del_ip_tunnel(name, tb);
2035 #ifdef IFLA_IPTUN_MAX
2036 } else if (!strcmp(str, "ipip6")) {
2037 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2038 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2039 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2045 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2046 nla_put_string(nlm, IFLA_IFNAME, name);
2049 nla_put_u32(nlm, IFLA_LINK, link);
2051 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2056 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2057 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2064 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2066 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2067 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2068 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
2070 struct in6_addr in6buf;
2071 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2072 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2076 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2079 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2080 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2084 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2087 #ifdef IFLA_IPTUN_FMR_MAX
2088 if ((cur = tb[TUNNEL_ATTR_FMRS])) {
2089 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2091 struct blob_attr *fmr;
2092 unsigned rem, fmrcnt = 0;
2093 blobmsg_for_each_attr(fmr, cur, rem) {
2094 if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
2097 unsigned ip4len, ip6len, ealen, offset = 6;
2101 if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
2102 ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) {
2107 struct in6_addr ip6prefix;
2108 struct in_addr ip4prefix;
2109 if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
2110 inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) {
2115 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2117 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2118 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2119 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2120 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2121 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2122 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2124 nla_nest_end(nlm, rule);
2127 nla_nest_end(nlm, fmrs);
2131 nla_nest_end(nlm, infodata);
2132 nla_nest_end(nlm, linkinfo);
2134 return system_rtnl_call(nlm);
2138 } else if (!strcmp(str, "greip")) {
2139 return system_add_gre_tunnel(name, "gre", link, tb, false);
2140 } else if (!strcmp(str, "gretapip")) {
2141 return system_add_gre_tunnel(name, "gretap", link, tb, false);
2142 } else if (!strcmp(str, "greip6")) {
2143 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
2144 } else if (!strcmp(str, "gretapip6")) {
2145 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
2147 } else if (!strcmp(str, "ipip")) {
2148 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);