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)
454 len = readlink(gl.gl_pathv[0], buf, buflen);
462 path = strrchr(buf, '/');
469 static void system_bridge_set_wireless(const char *bridge, const char *dev)
471 snprintf(dev_buf, sizeof(dev_buf),
472 "/sys/devices/virtual/net/%s/brif/%s/multicast_to_unicast",
474 system_set_sysctl(dev_buf, "1");
477 int system_bridge_addif(struct device *bridge, struct device *dev)
482 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
483 if (!oldbr || strcmp(oldbr, bridge->ifname) != 0)
484 ret = system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
487 system_bridge_set_wireless(bridge->ifname, dev->ifname);
492 int system_bridge_delif(struct device *bridge, struct device *dev)
494 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
497 static int system_if_resolve(struct device *dev)
500 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
501 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
502 return ifr.ifr_ifindex;
507 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
511 memset(&ifr, 0, sizeof(ifr));
512 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
513 ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
514 ifr.ifr_flags |= add;
515 ifr.ifr_flags &= ~rem;
516 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
528 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
530 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
532 return ifa->ifa_index == ifindex;
535 static bool check_route(struct nlmsghdr *hdr, int ifindex)
537 struct rtmsg *r = NLMSG_DATA(hdr);
538 struct nlattr *tb[__RTA_MAX];
540 if (r->rtm_protocol == RTPROT_KERNEL &&
541 r->rtm_family == AF_INET6)
544 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
548 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
551 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
556 static int cb_clear_event(struct nl_msg *msg, void *arg)
558 struct clear_data *clr = arg;
559 struct nlmsghdr *hdr = nlmsg_hdr(msg);
560 bool (*cb)(struct nlmsghdr *, int ifindex);
566 if (hdr->nlmsg_type != RTM_NEWADDR)
573 if (hdr->nlmsg_type != RTM_NEWROUTE)
580 if (hdr->nlmsg_type != RTM_NEWRULE)
589 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
592 if (type == RTM_DELRULE)
593 D(SYSTEM, "Remove a rule\n");
595 D(SYSTEM, "Remove %s from device %s\n",
596 type == RTM_DELADDR ? "an address" : "a route",
598 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
599 hdr = nlmsg_hdr(clr->msg);
600 hdr->nlmsg_type = type;
601 hdr->nlmsg_flags = NLM_F_REQUEST;
603 nl_socket_disable_auto_ack(sock_rtnl);
604 nl_send_auto_complete(sock_rtnl, clr->msg);
605 nl_socket_enable_auto_ack(sock_rtnl);
611 cb_finish_event(struct nl_msg *msg, void *arg)
619 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
622 *pending = err->error;
627 system_if_clear_entries(struct device *dev, int type, int af)
629 struct clear_data clr;
630 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
633 .rtm_flags = RTM_F_CLONED,
635 int flags = NLM_F_DUMP;
644 clr.size = sizeof(struct rtgenmsg);
647 clr.size = sizeof(struct rtmsg);
656 clr.msg = nlmsg_alloc_simple(type, flags);
660 nlmsg_append(clr.msg, &rtm, clr.size, 0);
661 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
662 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
663 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
665 nl_send_auto_complete(sock_rtnl, clr.msg);
667 nl_recvmsgs(sock_rtnl, cb);
675 * Clear bridge (membership) state and bring down device
677 void system_if_clear_state(struct device *dev)
679 static char buf[256];
682 device_set_ifindex(dev, system_if_resolve(dev));
683 if (dev->external || !dev->ifindex)
686 system_if_flags(dev->ifname, 0, IFF_UP);
688 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
689 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
690 system_bridge_delbr(dev);
694 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
696 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
697 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
700 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
701 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
702 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
703 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
704 system_set_disable_ipv6(dev, "0");
707 static inline unsigned long
708 sec_to_jiffies(int val)
710 return (unsigned long) val * 100;
713 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
715 unsigned long args[4] = {};
717 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
720 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
721 args[1] = !!cfg->stp;
722 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
724 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
725 args[1] = sec_to_jiffies(cfg->forward_delay);
726 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
728 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
729 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
731 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier",
732 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
734 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
735 args[1] = cfg->priority;
736 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
738 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
739 args[0] = BRCTL_SET_AGEING_TIME;
740 args[1] = sec_to_jiffies(cfg->ageing_time);
741 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
744 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
745 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
746 args[1] = sec_to_jiffies(cfg->hello_time);
747 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
750 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
751 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
752 args[1] = sec_to_jiffies(cfg->max_age);
753 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
759 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
762 struct nlattr *linkinfo, *data;
763 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
764 int ifindex = system_if_resolve(dev);
766 static const struct {
768 enum macvlan_mode val;
770 { "private", MACVLAN_MODE_PRIVATE },
771 { "vepa", MACVLAN_MODE_VEPA },
772 { "bridge", MACVLAN_MODE_BRIDGE },
773 { "passthru", MACVLAN_MODE_PASSTHRU },
779 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
784 nlmsg_append(msg, &iim, sizeof(iim), 0);
786 if (cfg->flags & MACVLAN_OPT_MACADDR)
787 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
788 nla_put_string(msg, IFLA_IFNAME, macvlan->ifname);
789 nla_put_u32(msg, IFLA_LINK, ifindex);
791 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
792 goto nla_put_failure;
794 nla_put_string(msg, IFLA_INFO_KIND, "macvlan");
796 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
797 goto nla_put_failure;
800 for (i = 0; i < ARRAY_SIZE(modes); i++) {
801 if (strcmp(cfg->mode, modes[i].name) != 0)
804 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
809 nla_nest_end(msg, data);
810 nla_nest_end(msg, linkinfo);
812 rv = system_rtnl_call(msg);
814 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
823 static int system_link_del(const char *ifname)
826 struct ifinfomsg iim = {
827 .ifi_family = AF_UNSPEC,
831 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
836 nlmsg_append(msg, &iim, sizeof(iim), 0);
837 nla_put_string(msg, IFLA_IFNAME, ifname);
838 return system_rtnl_call(msg);
841 int system_macvlan_del(struct device *macvlan)
843 return system_link_del(macvlan->ifname);
846 static int system_vlan(struct device *dev, int id)
848 struct vlan_ioctl_args ifr = {
849 .cmd = SET_VLAN_NAME_TYPE_CMD,
850 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
853 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
856 ifr.cmd = DEL_VLAN_CMD;
859 ifr.cmd = ADD_VLAN_CMD;
862 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
863 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
866 int system_vlan_add(struct device *dev, int id)
868 return system_vlan(dev, id);
871 int system_vlan_del(struct device *dev)
873 return system_vlan(dev, -1);
876 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
879 struct nlattr *linkinfo, *data;
880 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
881 int ifindex = system_if_resolve(dev);
887 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
892 nlmsg_append(msg, &iim, sizeof(iim), 0);
893 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
894 nla_put_u32(msg, IFLA_LINK, ifindex);
896 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
897 goto nla_put_failure;
899 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
901 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
902 goto nla_put_failure;
904 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
906 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
907 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
909 if(cfg->proto == VLAN_PROTO_8021AD)
910 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);
913 nla_nest_end(msg, data);
914 nla_nest_end(msg, linkinfo);
916 rv = system_rtnl_call(msg);
918 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
927 int system_vlandev_del(struct device *vlandev)
929 return system_link_del(vlandev->ifname);
933 system_if_get_settings(struct device *dev, struct device_settings *s)
938 memset(&ifr, 0, sizeof(ifr));
939 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
941 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
942 s->mtu = ifr.ifr_mtu;
943 s->flags |= DEV_OPT_MTU;
946 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
947 s->txqueuelen = ifr.ifr_qlen;
948 s->flags |= DEV_OPT_TXQUEUELEN;
951 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
952 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
953 s->flags |= DEV_OPT_MACADDR;
956 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
957 s->ipv6 = !strtoul(buf, NULL, 0);
958 s->flags |= DEV_OPT_IPV6;
961 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
962 s->promisc = ifr.ifr_flags & IFF_PROMISC;
963 s->flags |= DEV_OPT_PROMISC;
968 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
975 memset(&ifr, 0, sizeof(ifr));
976 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
977 if (s->flags & DEV_OPT_MTU & apply_mask) {
978 ifr.ifr_mtu = s->mtu;
979 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
980 s->flags &= ~DEV_OPT_MTU;
982 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
983 ifr.ifr_qlen = s->txqueuelen;
984 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
985 s->flags &= ~DEV_OPT_TXQUEUELEN;
987 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
988 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
989 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
990 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
991 s->flags &= ~DEV_OPT_MACADDR;
993 if (s->flags & DEV_OPT_IPV6 & apply_mask)
994 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
995 if (s->flags & DEV_OPT_PROMISC & apply_mask) {
996 if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
997 !s->promisc ? IFF_PROMISC : 0) < 0)
998 s->flags &= ~DEV_OPT_PROMISC;
1002 int system_if_up(struct device *dev)
1004 system_if_get_settings(dev, &dev->orig_settings);
1005 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
1006 device_set_ifindex(dev, system_if_resolve(dev));
1007 return system_if_flags(dev->ifname, IFF_UP, 0);
1010 int system_if_down(struct device *dev)
1012 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
1013 dev->orig_settings.flags &= dev->settings.flags;
1014 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
1018 struct if_check_data {
1024 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1026 struct nlmsghdr *nh = nlmsg_hdr(msg);
1027 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1028 struct if_check_data *chk = (struct if_check_data *)arg;
1030 if (nh->nlmsg_type != RTM_NEWLINK)
1033 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1034 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1039 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1041 struct if_check_data *chk = (struct if_check_data *)arg;
1046 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1048 struct if_check_data *chk = (struct if_check_data *)arg;
1050 device_set_present(chk->dev, false);
1051 device_set_link(chk->dev, false);
1052 chk->pending = err->error;
1057 int system_if_check(struct device *dev)
1059 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1061 struct ifinfomsg ifi = {
1062 .ifi_family = AF_UNSPEC,
1065 struct if_check_data chk = {
1071 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1072 if (!msg || nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1073 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1076 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1077 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1078 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1080 nl_send_auto_complete(sock_rtnl, msg);
1081 while (chk.pending > 0)
1082 nl_recvmsgs(sock_rtnl, cb);
1093 system_if_get_parent(struct device *dev)
1095 char buf[64], *devname;
1096 int ifindex, iflink, len;
1099 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1100 f = fopen(buf, "r");
1104 len = fread(buf, 1, sizeof(buf) - 1, f);
1111 iflink = strtoul(buf, NULL, 0);
1112 ifindex = system_if_resolve(dev);
1113 if (!iflink || iflink == ifindex)
1116 devname = if_indextoname(iflink, buf);
1120 return device_get(devname, true);
1124 read_string_file(int dir_fd, const char *file, char *buf, int len)
1130 fd = openat(dir_fd, file, O_RDONLY);
1135 len = read(fd, buf, len - 1);
1139 } else if (len > 0) {
1142 c = strchr(buf, '\n');
1155 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1160 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1162 *val = strtoull(buf, NULL, 0);
1167 /* Assume advertised flags == supported flags */
1168 static const struct {
1171 } ethtool_link_modes[] = {
1172 { ADVERTISED_10baseT_Half, "10H" },
1173 { ADVERTISED_10baseT_Full, "10F" },
1174 { ADVERTISED_100baseT_Half, "100H" },
1175 { ADVERTISED_100baseT_Full, "100F" },
1176 { ADVERTISED_1000baseT_Half, "1000H" },
1177 { ADVERTISED_1000baseT_Full, "1000F" },
1180 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1183 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1184 if (mask & ethtool_link_modes[i].mask)
1185 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1190 system_if_force_external(const char *ifname)
1195 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1196 return stat(buf, &s) == 0;
1200 system_if_dump_info(struct device *dev, struct blob_buf *b)
1202 struct ethtool_cmd ecmd;
1208 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
1209 dir_fd = open(buf, O_DIRECTORY);
1211 memset(&ecmd, 0, sizeof(ecmd));
1212 memset(&ifr, 0, sizeof(ifr));
1213 strcpy(ifr.ifr_name, dev->ifname);
1214 ifr.ifr_data = (caddr_t) &ecmd;
1215 ecmd.cmd = ETHTOOL_GSET;
1217 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1218 c = blobmsg_open_array(b, "link-advertising");
1219 system_add_link_modes(b, ecmd.advertising);
1220 blobmsg_close_array(b, c);
1222 c = blobmsg_open_array(b, "link-supported");
1223 system_add_link_modes(b, ecmd.supported);
1224 blobmsg_close_array(b, c);
1226 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1227 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1228 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1229 blobmsg_add_string_buffer(b);
1237 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1239 const char *const counters[] = {
1240 "collisions", "rx_frame_errors", "tx_compressed",
1241 "multicast", "rx_length_errors", "tx_dropped",
1242 "rx_bytes", "rx_missed_errors", "tx_errors",
1243 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1244 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1245 "rx_dropped", "tx_aborted_errors", "tx_packets",
1246 "rx_errors", "tx_bytes", "tx_window_errors",
1247 "rx_fifo_errors", "tx_carrier_errors",
1254 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1255 stats_dir = open(buf, O_DIRECTORY);
1259 for (i = 0; i < ARRAY_SIZE(counters); i++)
1260 if (read_uint64_file(stats_dir, counters[i], &val))
1261 blobmsg_add_u64(b, counters[i], val);
1267 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1269 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1270 int alen = v4 ? 4 : 16;
1271 unsigned int flags = 0;
1272 struct ifaddrmsg ifa = {
1273 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1274 .ifa_prefixlen = addr->mask,
1275 .ifa_index = dev->ifindex,
1279 if (cmd == RTM_NEWADDR)
1280 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1282 msg = nlmsg_alloc_simple(cmd, flags);
1286 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1287 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1289 if (addr->broadcast)
1290 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1291 if (addr->point_to_point)
1292 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1294 time_t now = system_get_rtime();
1295 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1297 if (addr->preferred_until) {
1298 int64_t preferred = addr->preferred_until - now;
1301 else if (preferred > UINT32_MAX)
1302 preferred = UINT32_MAX;
1304 cinfo.ifa_prefered = preferred;
1307 if (addr->valid_until) {
1308 int64_t valid = addr->valid_until - now;
1311 else if (valid > UINT32_MAX)
1314 cinfo.ifa_valid = valid;
1317 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1320 return system_rtnl_call(msg);
1323 int system_add_address(struct device *dev, struct device_addr *addr)
1325 return system_addr(dev, addr, RTM_NEWADDR);
1328 int system_del_address(struct device *dev, struct device_addr *addr)
1330 return system_addr(dev, addr, RTM_DELADDR);
1333 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1335 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1337 unsigned int flags = 0;
1340 have_gw = !!route->nexthop.in.s_addr;
1342 have_gw = route->nexthop.in6.s6_addr32[0] ||
1343 route->nexthop.in6.s6_addr32[1] ||
1344 route->nexthop.in6.s6_addr32[2] ||
1345 route->nexthop.in6.s6_addr32[3];
1347 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1348 ? route->table : RT_TABLE_MAIN;
1350 struct rtmsg rtm = {
1351 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1352 .rtm_dst_len = route->mask,
1353 .rtm_src_len = route->sourcemask,
1354 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1355 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
1356 .rtm_scope = RT_SCOPE_NOWHERE,
1357 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1358 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1362 if (cmd == RTM_NEWROUTE) {
1363 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1365 if (!dev) { // Add null-route
1366 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1367 rtm.rtm_type = RTN_UNREACHABLE;
1370 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1373 if (route->flags & DEVROUTE_TYPE) {
1374 rtm.rtm_type = route->type;
1375 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
1376 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
1377 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
1378 rtm.rtm_table = RT_TABLE_LOCAL;
1381 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT)
1382 rtm.rtm_scope = RT_SCOPE_HOST;
1383 else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
1384 rtm.rtm_type == RTN_ANYCAST)
1385 rtm.rtm_scope = RT_SCOPE_LINK;
1388 msg = nlmsg_alloc_simple(cmd, flags);
1392 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1395 nla_put(msg, RTA_DST, alen, &route->addr);
1397 if (route->sourcemask)
1398 nla_put(msg, RTA_SRC, alen, &route->source);
1400 if (route->metric > 0)
1401 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1404 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1407 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1410 nla_put_u32(msg, RTA_TABLE, table);
1412 if (route->flags & DEVROUTE_MTU) {
1413 struct nlattr *metrics;
1415 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1416 goto nla_put_failure;
1418 nla_put_u32(msg, RTAX_MTU, route->mtu);
1420 nla_nest_end(msg, metrics);
1423 return system_rtnl_call(msg);
1430 int system_add_route(struct device *dev, struct device_route *route)
1432 return system_rt(dev, route, RTM_NEWROUTE);
1435 int system_del_route(struct device *dev, struct device_route *route)
1437 return system_rt(dev, route, RTM_DELROUTE);
1440 int system_flush_routes(void)
1442 const char *names[] = {
1443 "/proc/sys/net/ipv4/route/flush",
1444 "/proc/sys/net/ipv6/route/flush"
1448 for (i = 0; i < ARRAY_SIZE(names); i++) {
1449 fd = open(names[i], O_WRONLY);
1453 if (write(fd, "-1", 2)) {}
1459 bool system_resolve_rt_type(const char *type, unsigned int *id)
1461 return system_rtn_aton(type, id);
1464 bool system_resolve_rt_table(const char *name, unsigned int *id)
1468 unsigned int n, table = RT_TABLE_UNSPEC;
1470 /* first try to parse table as number */
1471 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1474 /* handle well known aliases */
1475 else if (!strcmp(name, "default"))
1476 table = RT_TABLE_DEFAULT;
1477 else if (!strcmp(name, "main"))
1478 table = RT_TABLE_MAIN;
1479 else if (!strcmp(name, "local"))
1480 table = RT_TABLE_LOCAL;
1482 /* try to look up name in /etc/iproute2/rt_tables */
1483 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1485 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1487 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1490 n = strtoul(e, NULL, 10);
1491 e = strtok(NULL, " \t\n");
1493 if (e && !strcmp(e, name))
1503 if (table == RT_TABLE_UNSPEC)
1510 bool system_is_default_rt_table(unsigned int id)
1512 return (id == RT_TABLE_MAIN);
1515 static int system_iprule(struct iprule *rule, int cmd)
1517 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1520 struct rtmsg rtm = {
1521 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1522 .rtm_protocol = RTPROT_STATIC,
1523 .rtm_scope = RT_SCOPE_UNIVERSE,
1524 .rtm_table = RT_TABLE_UNSPEC,
1525 .rtm_type = RTN_UNSPEC,
1529 if (cmd == RTM_NEWRULE) {
1530 rtm.rtm_type = RTN_UNICAST;
1531 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1535 rtm.rtm_flags |= FIB_RULE_INVERT;
1537 if (rule->flags & IPRULE_SRC)
1538 rtm.rtm_src_len = rule->src_mask;
1540 if (rule->flags & IPRULE_DEST)
1541 rtm.rtm_dst_len = rule->dest_mask;
1543 if (rule->flags & IPRULE_TOS)
1544 rtm.rtm_tos = rule->tos;
1546 if (rule->flags & IPRULE_LOOKUP) {
1547 if (rule->lookup < 256)
1548 rtm.rtm_table = rule->lookup;
1551 if (rule->flags & IPRULE_ACTION)
1552 rtm.rtm_type = rule->action;
1553 else if (rule->flags & IPRULE_GOTO)
1554 rtm.rtm_type = FR_ACT_GOTO;
1555 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1556 rtm.rtm_type = FR_ACT_NOP;
1558 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1563 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1565 if (rule->flags & IPRULE_IN)
1566 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1568 if (rule->flags & IPRULE_OUT)
1569 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1571 if (rule->flags & IPRULE_SRC)
1572 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1574 if (rule->flags & IPRULE_DEST)
1575 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1577 if (rule->flags & IPRULE_PRIORITY)
1578 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1579 else if (cmd == RTM_NEWRULE)
1580 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1582 if (rule->flags & IPRULE_FWMARK)
1583 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1585 if (rule->flags & IPRULE_FWMASK)
1586 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1588 if (rule->flags & IPRULE_LOOKUP) {
1589 if (rule->lookup >= 256)
1590 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1593 if (rule->flags & IPRULE_GOTO)
1594 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1596 return system_rtnl_call(msg);
1599 int system_add_iprule(struct iprule *rule)
1601 return system_iprule(rule, RTM_NEWRULE);
1604 int system_del_iprule(struct iprule *rule)
1606 return system_iprule(rule, RTM_DELRULE);
1609 int system_flush_iprules(void)
1614 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1615 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1617 memset(&rule, 0, sizeof(rule));
1620 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1623 rule.lookup = RT_TABLE_LOCAL;
1624 rv |= system_iprule(&rule, RTM_NEWRULE);
1626 rule.priority = 32766;
1627 rule.lookup = RT_TABLE_MAIN;
1628 rv |= system_iprule(&rule, RTM_NEWRULE);
1630 rule.priority = 32767;
1631 rule.lookup = RT_TABLE_DEFAULT;
1632 rv |= system_iprule(&rule, RTM_NEWRULE);
1635 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1638 rule.lookup = RT_TABLE_LOCAL;
1639 rv |= system_iprule(&rule, RTM_NEWRULE);
1641 rule.priority = 32766;
1642 rule.lookup = RT_TABLE_MAIN;
1643 rv |= system_iprule(&rule, RTM_NEWRULE);
1648 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1650 return system_rtn_aton(action, id);
1653 time_t system_get_rtime(void)
1658 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1661 if (gettimeofday(&tv, NULL) == 0)
1668 #define IP_DF 0x4000
1671 static int tunnel_ioctl(const char *name, int cmd, void *p)
1675 memset(&ifr, 0, sizeof(ifr));
1676 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1677 ifr.ifr_ifru.ifru_data = p;
1678 return ioctl(sock_ioctl, cmd, &ifr);
1681 #ifdef IFLA_IPTUN_MAX
1682 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
1683 static int system_add_gre_tunnel(const char *name, const char *kind,
1684 const unsigned int link, struct blob_attr **tb, bool v6)
1687 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
1688 struct blob_attr *cur;
1689 uint32_t ikey = 0, okey = 0, flags = 0, flowinfo = 0;
1690 uint16_t iflags = 0, oflags = 0;
1692 int ret = 0, ttl = 64;
1694 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
1698 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
1699 nla_put_string(nlm, IFLA_IFNAME, name);
1701 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
1707 nla_put_string(nlm, IFLA_INFO_KIND, kind);
1708 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
1715 nla_put_u32(nlm, IFLA_GRE_LINK, link);
1717 if ((cur = tb[TUNNEL_ATTR_TTL]))
1718 ttl = blobmsg_get_u32(cur);
1720 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
1722 if ((cur = tb[TUNNEL_ATTR_TOS])) {
1723 char *str = blobmsg_get_string(cur);
1724 if (strcmp(str, "inherit")) {
1727 if (!system_tos_aton(str, &uval)) {
1733 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
1738 flags |= IP6_TNL_F_USE_ORIG_TCLASS;
1744 if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) {
1745 uint8_t icsum, ocsum, iseqno, oseqno;
1746 if (sscanf(blobmsg_get_string(cur), "%u,%u,%hhu,%hhu,%hhu,%hhu",
1747 &ikey, &okey, &icsum, &ocsum, &iseqno, &oseqno) < 6) {
1772 struct in6_addr in6buf;
1773 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1774 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1778 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
1781 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
1782 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1786 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
1788 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, 4);
1791 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
1794 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags);
1796 struct in_addr inbuf;
1799 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1800 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
1804 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
1807 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
1808 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
1812 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
1814 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
1816 okey = inbuf.s_addr;
1821 ikey = inbuf.s_addr;
1827 if ((cur = tb[TUNNEL_ATTR_DF]))
1828 set_df = blobmsg_get_bool(cur);
1830 /* ttl !=0 and nopmtudisc are incompatible */
1831 if (ttl && !set_df) {
1836 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
1838 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
1842 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
1845 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
1848 nla_put_u32(nlm, IFLA_GRE_OKEY, okey);
1851 nla_put_u32(nlm, IFLA_GRE_IKEY, ikey);
1853 nla_nest_end(nlm, infodata);
1854 nla_nest_end(nlm, linkinfo);
1856 return system_rtnl_call(nlm);
1864 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
1866 struct blob_attr *cur;
1868 struct ip_tunnel_parm p = {
1877 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
1878 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
1881 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
1882 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
1885 if ((cur = tb[TUNNEL_ATTR_DF]))
1886 set_df = blobmsg_get_bool(cur);
1888 if ((cur = tb[TUNNEL_ATTR_TTL]))
1889 p.iph.ttl = blobmsg_get_u32(cur);
1891 if ((cur = tb[TUNNEL_ATTR_TOS])) {
1892 char *str = blobmsg_get_string(cur);
1893 if (strcmp(str, "inherit")) {
1896 if (!system_tos_aton(str, &uval))
1904 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
1905 /* ttl !=0 and nopmtudisc are incompatible */
1906 if (p.iph.ttl && p.iph.frag_off == 0)
1909 strncpy(p.name, name, sizeof(p.name));
1911 switch (p.iph.protocol) {
1913 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
1915 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
1922 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
1924 struct blob_attr *cur;
1927 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
1929 str = blobmsg_data(cur);
1931 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
1932 !strcmp(str, "greip6") || !strcmp(str, "gretapip6"))
1933 return system_link_del(name);
1935 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
1938 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
1940 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
1942 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
1943 blob_data(attr), blob_len(attr));
1945 return __system_del_ip_tunnel(name, tb);
1948 int system_update_ipv6_mtu(struct device *dev, int mtu)
1952 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
1955 int fd = open(buf, O_RDWR);
1956 ssize_t len = read(fd, buf, sizeof(buf) - 1);
1963 if (!mtu || ret <= mtu)
1966 lseek(fd, 0, SEEK_SET);
1967 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) <= 0)
1975 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
1977 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
1978 struct blob_attr *cur;
1981 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
1982 blob_data(attr), blob_len(attr));
1984 __system_del_ip_tunnel(name, tb);
1986 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
1988 str = blobmsg_data(cur);
1990 unsigned int ttl = 0;
1991 if ((cur = tb[TUNNEL_ATTR_TTL])) {
1992 ttl = blobmsg_get_u32(cur);
1997 unsigned int link = 0;
1998 if ((cur = tb[TUNNEL_ATTR_LINK])) {
1999 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
2003 if (iface->l3_dev.dev)
2004 link = iface->l3_dev.dev->ifindex;
2007 if (!strcmp(str, "sit")) {
2008 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
2012 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
2014 struct ip_tunnel_6rd p6;
2016 memset(&p6, 0, sizeof(p6));
2018 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
2019 &p6.prefix, &mask) || mask > 128)
2021 p6.prefixlen = mask;
2023 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
2024 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
2025 &p6.relay_prefix, &mask) || mask > 32)
2027 p6.relay_prefixlen = mask;
2030 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
2031 __system_del_ip_tunnel(name, tb);
2036 #ifdef IFLA_IPTUN_MAX
2037 } else if (!strcmp(str, "ipip6")) {
2038 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2039 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2040 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2046 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2047 nla_put_string(nlm, IFLA_IFNAME, name);
2050 nla_put_u32(nlm, IFLA_LINK, link);
2052 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2057 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2058 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2065 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2067 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2068 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2069 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
2071 struct in6_addr in6buf;
2072 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2073 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2077 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2080 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2081 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2085 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2088 #ifdef IFLA_IPTUN_FMR_MAX
2089 if ((cur = tb[TUNNEL_ATTR_FMRS])) {
2090 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2092 struct blob_attr *fmr;
2093 unsigned rem, fmrcnt = 0;
2094 blobmsg_for_each_attr(fmr, cur, rem) {
2095 if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
2098 unsigned ip4len, ip6len, ealen, offset = 6;
2102 if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
2103 ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) {
2108 struct in6_addr ip6prefix;
2109 struct in_addr ip4prefix;
2110 if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
2111 inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) {
2116 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2118 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2119 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2120 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2121 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2122 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2123 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2125 nla_nest_end(nlm, rule);
2128 nla_nest_end(nlm, fmrs);
2132 nla_nest_end(nlm, infodata);
2133 nla_nest_end(nlm, linkinfo);
2135 return system_rtnl_call(nlm);
2139 } else if (!strcmp(str, "greip")) {
2140 return system_add_gre_tunnel(name, "gre", link, tb, false);
2141 } else if (!strcmp(str, "gretapip")) {
2142 return system_add_gre_tunnel(name, "gretap", link, tb, false);
2143 } else if (!strcmp(str, "greip6")) {
2144 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
2145 } else if (!strcmp(str, "gretapip6")) {
2146 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
2148 } else if (!strcmp(str, "ipip")) {
2149 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);