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)
207 int system_init(void)
209 static struct event_socket rtnl_event;
210 static struct event_socket hotplug_event;
212 sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0);
213 system_fd_set_cloexec(sock_ioctl);
215 // Prepare socket for routing / address control
216 sock_rtnl = create_socket(NETLINK_ROUTE, 0);
220 if (!create_event_socket(&rtnl_event, NETLINK_ROUTE, cb_rtnl_event))
223 if (!create_raw_event_socket(&hotplug_event, NETLINK_KOBJECT_UEVENT, 1,
224 handle_hotplug_event, 0))
227 // Receive network link events form kernel
228 nl_socket_add_membership(rtnl_event.sock, RTNLGRP_LINK);
233 static void system_set_sysctl(const char *path, const char *val)
237 fd = open(path, O_WRONLY);
241 if (write(fd, val, strlen(val))) {}
245 static void system_set_dev_sysctl(const char *path, const char *device, const char *val)
247 snprintf(dev_buf, sizeof(dev_buf), path, device);
248 system_set_sysctl(dev_buf, val);
251 static void system_set_disable_ipv6(struct device *dev, const char *val)
253 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val);
256 static int system_get_sysctl(const char *path, char *buf, const size_t buf_sz)
258 int fd = -1, ret = -1;
260 fd = open(path, O_RDONLY);
264 ssize_t len = read(fd, buf, buf_sz - 1);
278 system_get_dev_sysctl(const char *path, const char *device, char *buf, const size_t buf_sz)
280 snprintf(dev_buf, sizeof(dev_buf), path, device);
281 return system_get_sysctl(dev_buf, buf, buf_sz);
284 static int system_get_disable_ipv6(struct device *dev, char *buf, const size_t buf_sz)
286 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6",
287 dev->ifname, buf, buf_sz);
291 #define IFF_LOWER_UP 0x10000
294 // Evaluate netlink messages
295 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
297 struct nlmsghdr *nh = nlmsg_hdr(msg);
298 struct ifinfomsg *ifi = NLMSG_DATA(nh);
299 struct nlattr *nla[__IFLA_MAX];
301 if (nh->nlmsg_type != RTM_NEWLINK)
304 nlmsg_parse(nh, sizeof(*ifi), nla, __IFLA_MAX - 1, NULL);
305 if (!nla[IFLA_IFNAME])
308 struct device *dev = device_get(nla_data(nla[IFLA_IFNAME]), false);
312 device_set_ifindex(dev, ifi->ifi_index);
313 device_set_link(dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
320 handle_hotplug_msg(char *data, int size)
322 const char *subsystem = NULL, *interface = NULL;
323 char *cur, *end, *sep;
328 if (!strncmp(data, "add@", 4))
330 else if (!strncmp(data, "remove@", 7))
335 skip = strlen(data) + 1;
338 for (cur = data + skip; cur < end; cur += skip) {
339 skip = strlen(cur) + 1;
341 sep = strchr(cur, '=');
346 if (!strcmp(cur, "INTERFACE"))
348 else if (!strcmp(cur, "SUBSYSTEM")) {
350 if (strcmp(subsystem, "net") != 0)
353 if (subsystem && interface)
359 dev = device_get(interface, false);
363 if (dev->type != &simple_device_type)
366 if (add && system_if_force_external(dev->ifname))
369 device_set_present(dev, add);
373 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
375 struct event_socket *ev = container_of(u, struct event_socket, uloop);
376 struct sockaddr_nl nla;
377 unsigned char *buf = NULL;
380 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
382 handle_hotplug_msg((char *) buf, size);
388 static int system_rtnl_call(struct nl_msg *msg)
392 ret = nl_send_auto_complete(sock_rtnl, msg);
398 return nl_wait_for_ack(sock_rtnl);
401 int system_bridge_delbr(struct device *bridge)
403 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
406 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
410 memset(&ifr, 0, sizeof(ifr));
412 ifr.ifr_ifindex = dev->ifindex;
415 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
416 return ioctl(sock_ioctl, cmd, &ifr);
419 static bool system_is_bridge(const char *name, char *buf, int buflen)
423 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
424 if (stat(buf, &st) < 0)
430 static char *system_get_bridge(const char *name, char *buf, int buflen)
436 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
437 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
440 if (gl.gl_pathc == 0)
443 len = readlink(gl.gl_pathv[0], buf, buflen);
448 path = strrchr(buf, '/');
455 int system_bridge_addif(struct device *bridge, struct device *dev)
459 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
460 if (oldbr && !strcmp(oldbr, bridge->ifname))
463 return system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
466 int system_bridge_delif(struct device *bridge, struct device *dev)
468 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
471 static int system_if_resolve(struct device *dev)
474 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
475 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
476 return ifr.ifr_ifindex;
481 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
485 memset(&ifr, 0, sizeof(ifr));
486 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
487 ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
488 ifr.ifr_flags |= add;
489 ifr.ifr_flags &= ~rem;
490 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
502 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
504 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
506 return ifa->ifa_index == ifindex;
509 static bool check_route(struct nlmsghdr *hdr, int ifindex)
511 struct rtmsg *r = NLMSG_DATA(hdr);
512 struct nlattr *tb[__RTA_MAX];
514 if (r->rtm_protocol == RTPROT_KERNEL &&
515 r->rtm_family == AF_INET6)
518 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
522 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
525 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
530 static int cb_clear_event(struct nl_msg *msg, void *arg)
532 struct clear_data *clr = arg;
533 struct nlmsghdr *hdr = nlmsg_hdr(msg);
534 bool (*cb)(struct nlmsghdr *, int ifindex);
540 if (hdr->nlmsg_type != RTM_NEWADDR)
547 if (hdr->nlmsg_type != RTM_NEWROUTE)
554 if (hdr->nlmsg_type != RTM_NEWRULE)
563 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
566 if (type == RTM_DELRULE)
567 D(SYSTEM, "Remove a rule\n");
569 D(SYSTEM, "Remove %s from device %s\n",
570 type == RTM_DELADDR ? "an address" : "a route",
572 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
573 hdr = nlmsg_hdr(clr->msg);
574 hdr->nlmsg_type = type;
575 hdr->nlmsg_flags = NLM_F_REQUEST;
577 nl_socket_disable_auto_ack(sock_rtnl);
578 nl_send_auto_complete(sock_rtnl, clr->msg);
579 nl_socket_enable_auto_ack(sock_rtnl);
585 cb_finish_event(struct nl_msg *msg, void *arg)
593 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
596 *pending = err->error;
601 system_if_clear_entries(struct device *dev, int type, int af)
603 struct clear_data clr;
604 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
607 .rtm_flags = RTM_F_CLONED,
609 int flags = NLM_F_DUMP;
618 clr.size = sizeof(struct rtgenmsg);
621 clr.size = sizeof(struct rtmsg);
630 clr.msg = nlmsg_alloc_simple(type, flags);
634 nlmsg_append(clr.msg, &rtm, clr.size, 0);
635 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
636 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
637 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
639 nl_send_auto_complete(sock_rtnl, clr.msg);
641 nl_recvmsgs(sock_rtnl, cb);
649 * Clear bridge (membership) state and bring down device
651 void system_if_clear_state(struct device *dev)
653 static char buf[256];
656 device_set_ifindex(dev, system_if_resolve(dev));
657 if (dev->external || !dev->ifindex)
660 system_if_flags(dev->ifname, 0, IFF_UP);
662 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
663 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
664 system_bridge_delbr(dev);
668 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
670 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
671 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
674 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
675 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
676 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
677 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
678 system_set_disable_ipv6(dev, "0");
681 static inline unsigned long
682 sec_to_jiffies(int val)
684 return (unsigned long) val * 100;
687 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
689 unsigned long args[4] = {};
691 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
694 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
695 args[1] = !!cfg->stp;
696 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
698 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
699 args[1] = sec_to_jiffies(cfg->forward_delay);
700 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
702 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
703 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
705 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
706 args[1] = cfg->priority;
707 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
709 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
710 args[0] = BRCTL_SET_AGEING_TIME;
711 args[1] = sec_to_jiffies(cfg->ageing_time);
712 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
715 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
716 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
717 args[1] = sec_to_jiffies(cfg->hello_time);
718 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
721 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
722 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
723 args[1] = sec_to_jiffies(cfg->max_age);
724 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
730 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
733 struct nlattr *linkinfo, *data;
734 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
735 int ifindex = system_if_resolve(dev);
737 static const struct {
739 enum macvlan_mode val;
741 { "private", MACVLAN_MODE_PRIVATE },
742 { "vepa", MACVLAN_MODE_VEPA },
743 { "bridge", MACVLAN_MODE_BRIDGE },
744 { "passthru", MACVLAN_MODE_PASSTHRU },
750 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
755 nlmsg_append(msg, &iim, sizeof(iim), 0);
757 if (cfg->flags & MACVLAN_OPT_MACADDR)
758 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
759 nla_put_string(msg, IFLA_IFNAME, macvlan->ifname);
760 nla_put_u32(msg, IFLA_LINK, ifindex);
762 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
763 goto nla_put_failure;
765 nla_put_string(msg, IFLA_INFO_KIND, "macvlan");
767 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
768 goto nla_put_failure;
771 for (i = 0; i < ARRAY_SIZE(modes); i++) {
772 if (strcmp(cfg->mode, modes[i].name) != 0)
775 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
780 nla_nest_end(msg, data);
781 nla_nest_end(msg, linkinfo);
783 rv = system_rtnl_call(msg);
785 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
794 int system_macvlan_del(struct device *macvlan)
797 struct ifinfomsg iim = {
798 .ifi_family = AF_UNSPEC,
802 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
807 nlmsg_append(msg, &iim, sizeof(iim), 0);
809 nla_put_string(msg, IFLA_IFNAME, macvlan->ifname);
811 system_rtnl_call(msg);
816 static int system_vlan(struct device *dev, int id)
818 struct vlan_ioctl_args ifr = {
819 .cmd = SET_VLAN_NAME_TYPE_CMD,
820 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
823 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
826 ifr.cmd = DEL_VLAN_CMD;
829 ifr.cmd = ADD_VLAN_CMD;
832 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
833 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
836 int system_vlan_add(struct device *dev, int id)
838 return system_vlan(dev, id);
841 int system_vlan_del(struct device *dev)
843 return system_vlan(dev, -1);
846 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
849 struct nlattr *linkinfo, *data;
850 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
851 int ifindex = system_if_resolve(dev);
857 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
862 nlmsg_append(msg, &iim, sizeof(iim), 0);
863 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
864 nla_put_u32(msg, IFLA_LINK, ifindex);
866 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
867 goto nla_put_failure;
869 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
871 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
872 goto nla_put_failure;
874 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
876 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
877 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
879 if(cfg->proto == VLAN_PROTO_8021AD)
880 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);
883 nla_nest_end(msg, data);
884 nla_nest_end(msg, linkinfo);
886 rv = system_rtnl_call(msg);
888 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
897 int system_vlandev_del(struct device *vlandev)
900 struct ifinfomsg iim = {
901 .ifi_family = AF_UNSPEC,
905 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
910 nlmsg_append(msg, &iim, sizeof(iim), 0);
912 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
914 system_rtnl_call(msg);
920 system_if_get_settings(struct device *dev, struct device_settings *s)
925 memset(&ifr, 0, sizeof(ifr));
926 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
928 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
929 s->mtu = ifr.ifr_mtu;
930 s->flags |= DEV_OPT_MTU;
933 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
934 s->txqueuelen = ifr.ifr_qlen;
935 s->flags |= DEV_OPT_TXQUEUELEN;
938 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
939 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
940 s->flags |= DEV_OPT_MACADDR;
943 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
944 s->ipv6 = !strtoul(buf, NULL, 0);
945 s->flags |= DEV_OPT_IPV6;
950 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
957 memset(&ifr, 0, sizeof(ifr));
958 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
959 if (s->flags & DEV_OPT_MTU & apply_mask) {
960 ifr.ifr_mtu = s->mtu;
961 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
962 s->flags &= ~DEV_OPT_MTU;
964 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
965 ifr.ifr_qlen = s->txqueuelen;
966 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
967 s->flags &= ~DEV_OPT_TXQUEUELEN;
969 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
970 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
971 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
972 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
973 s->flags &= ~DEV_OPT_MACADDR;
975 if (s->flags & DEV_OPT_IPV6 & apply_mask)
976 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
979 int system_if_up(struct device *dev)
981 system_if_get_settings(dev, &dev->orig_settings);
982 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
983 device_set_ifindex(dev, system_if_resolve(dev));
984 return system_if_flags(dev->ifname, IFF_UP, 0);
987 int system_if_down(struct device *dev)
989 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
990 dev->orig_settings.flags &= dev->settings.flags;
991 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
995 struct if_check_data {
1001 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1003 struct nlmsghdr *nh = nlmsg_hdr(msg);
1004 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1005 struct if_check_data *chk = (struct if_check_data *)arg;
1007 if (nh->nlmsg_type != RTM_NEWLINK)
1010 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1011 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1016 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1018 struct if_check_data *chk = (struct if_check_data *)arg;
1023 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1025 struct if_check_data *chk = (struct if_check_data *)arg;
1027 device_set_present(chk->dev, false);
1028 device_set_link(chk->dev, false);
1029 chk->pending = err->error;
1034 int system_if_check(struct device *dev)
1036 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1038 struct ifinfomsg ifi = {
1039 .ifi_family = AF_UNSPEC,
1042 struct if_check_data chk = {
1048 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1049 if (!msg || nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1050 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1053 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1054 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1055 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1057 nl_send_auto_complete(sock_rtnl, msg);
1058 while (chk.pending > 0)
1059 nl_recvmsgs(sock_rtnl, cb);
1070 system_if_get_parent(struct device *dev)
1072 char buf[64], *devname;
1073 int ifindex, iflink, len;
1076 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1077 f = fopen(buf, "r");
1081 len = fread(buf, 1, sizeof(buf) - 1, f);
1088 iflink = strtoul(buf, NULL, 0);
1089 ifindex = system_if_resolve(dev);
1090 if (!iflink || iflink == ifindex)
1093 devname = if_indextoname(iflink, buf);
1097 return device_get(devname, true);
1101 read_string_file(int dir_fd, const char *file, char *buf, int len)
1107 fd = openat(dir_fd, file, O_RDONLY);
1112 len = read(fd, buf, len - 1);
1116 } else if (len > 0) {
1119 c = strchr(buf, '\n');
1132 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1137 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1139 *val = strtoull(buf, NULL, 0);
1144 /* Assume advertised flags == supported flags */
1145 static const struct {
1148 } ethtool_link_modes[] = {
1149 { ADVERTISED_10baseT_Half, "10H" },
1150 { ADVERTISED_10baseT_Full, "10F" },
1151 { ADVERTISED_100baseT_Half, "100H" },
1152 { ADVERTISED_100baseT_Full, "100F" },
1153 { ADVERTISED_1000baseT_Half, "1000H" },
1154 { ADVERTISED_1000baseT_Full, "1000F" },
1157 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1160 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1161 if (mask & ethtool_link_modes[i].mask)
1162 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1167 system_if_force_external(const char *ifname)
1172 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1173 return stat(buf, &s) == 0;
1177 system_if_dump_info(struct device *dev, struct blob_buf *b)
1179 struct ethtool_cmd ecmd;
1185 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
1186 dir_fd = open(buf, O_DIRECTORY);
1188 memset(&ecmd, 0, sizeof(ecmd));
1189 memset(&ifr, 0, sizeof(ifr));
1190 strcpy(ifr.ifr_name, dev->ifname);
1191 ifr.ifr_data = (caddr_t) &ecmd;
1192 ecmd.cmd = ETHTOOL_GSET;
1194 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1195 c = blobmsg_open_array(b, "link-advertising");
1196 system_add_link_modes(b, ecmd.advertising);
1197 blobmsg_close_array(b, c);
1199 c = blobmsg_open_array(b, "link-supported");
1200 system_add_link_modes(b, ecmd.supported);
1201 blobmsg_close_array(b, c);
1203 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1204 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1205 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1206 blobmsg_add_string_buffer(b);
1214 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1216 const char *const counters[] = {
1217 "collisions", "rx_frame_errors", "tx_compressed",
1218 "multicast", "rx_length_errors", "tx_dropped",
1219 "rx_bytes", "rx_missed_errors", "tx_errors",
1220 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1221 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1222 "rx_dropped", "tx_aborted_errors", "tx_packets",
1223 "rx_errors", "tx_bytes", "tx_window_errors",
1224 "rx_fifo_errors", "tx_carrier_errors",
1231 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1232 stats_dir = open(buf, O_DIRECTORY);
1236 for (i = 0; i < ARRAY_SIZE(counters); i++)
1237 if (read_uint64_file(stats_dir, counters[i], &val))
1238 blobmsg_add_u64(b, counters[i], val);
1244 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1246 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1247 int alen = v4 ? 4 : 16;
1248 unsigned int flags = 0;
1249 struct ifaddrmsg ifa = {
1250 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1251 .ifa_prefixlen = addr->mask,
1252 .ifa_index = dev->ifindex,
1256 if (cmd == RTM_NEWADDR)
1257 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1259 msg = nlmsg_alloc_simple(cmd, flags);
1263 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1264 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1266 if (addr->broadcast)
1267 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1268 if (addr->point_to_point)
1269 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1271 time_t now = system_get_rtime();
1272 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1274 if (addr->preferred_until) {
1275 int64_t preferred = addr->preferred_until - now;
1278 else if (preferred > UINT32_MAX)
1279 preferred = UINT32_MAX;
1281 cinfo.ifa_prefered = preferred;
1284 if (addr->valid_until) {
1285 int64_t valid = addr->valid_until - now;
1288 else if (valid > UINT32_MAX)
1291 cinfo.ifa_valid = valid;
1294 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1297 return system_rtnl_call(msg);
1300 int system_add_address(struct device *dev, struct device_addr *addr)
1302 return system_addr(dev, addr, RTM_NEWADDR);
1305 int system_del_address(struct device *dev, struct device_addr *addr)
1307 return system_addr(dev, addr, RTM_DELADDR);
1310 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1312 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1314 unsigned int flags = 0;
1317 have_gw = !!route->nexthop.in.s_addr;
1319 have_gw = route->nexthop.in6.s6_addr32[0] ||
1320 route->nexthop.in6.s6_addr32[1] ||
1321 route->nexthop.in6.s6_addr32[2] ||
1322 route->nexthop.in6.s6_addr32[3];
1324 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1325 ? route->table : RT_TABLE_MAIN;
1327 struct rtmsg rtm = {
1328 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1329 .rtm_dst_len = route->mask,
1330 .rtm_src_len = route->sourcemask,
1331 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1332 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
1333 .rtm_scope = RT_SCOPE_NOWHERE,
1334 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1335 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1339 if (cmd == RTM_NEWROUTE) {
1340 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1342 if (!dev) { // Add null-route
1343 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1344 rtm.rtm_type = RTN_UNREACHABLE;
1347 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1350 if (route->flags & DEVROUTE_TYPE) {
1351 rtm.rtm_type = route->type;
1352 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
1353 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
1354 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
1355 rtm.rtm_table = RT_TABLE_LOCAL;
1358 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT)
1359 rtm.rtm_scope = RT_SCOPE_HOST;
1360 else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
1361 rtm.rtm_type == RTN_ANYCAST)
1362 rtm.rtm_scope = RT_SCOPE_LINK;
1365 msg = nlmsg_alloc_simple(cmd, flags);
1369 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1372 nla_put(msg, RTA_DST, alen, &route->addr);
1374 if (route->sourcemask)
1375 nla_put(msg, RTA_SRC, alen, &route->source);
1377 if (route->metric > 0)
1378 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1381 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1384 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1387 nla_put_u32(msg, RTA_TABLE, table);
1389 if (route->flags & DEVROUTE_MTU) {
1390 struct nlattr *metrics;
1392 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1393 goto nla_put_failure;
1395 nla_put_u32(msg, RTAX_MTU, route->mtu);
1397 nla_nest_end(msg, metrics);
1400 return system_rtnl_call(msg);
1407 int system_add_route(struct device *dev, struct device_route *route)
1409 return system_rt(dev, route, RTM_NEWROUTE);
1412 int system_del_route(struct device *dev, struct device_route *route)
1414 return system_rt(dev, route, RTM_DELROUTE);
1417 int system_flush_routes(void)
1419 const char *names[] = {
1420 "/proc/sys/net/ipv4/route/flush",
1421 "/proc/sys/net/ipv6/route/flush"
1425 for (i = 0; i < ARRAY_SIZE(names); i++) {
1426 fd = open(names[i], O_WRONLY);
1430 if (write(fd, "-1", 2)) {}
1436 bool system_resolve_rt_type(const char *type, unsigned int *id)
1438 return system_rtn_aton(type, id);
1441 bool system_resolve_rt_table(const char *name, unsigned int *id)
1445 unsigned int n, table = RT_TABLE_UNSPEC;
1447 /* first try to parse table as number */
1448 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1451 /* handle well known aliases */
1452 else if (!strcmp(name, "default"))
1453 table = RT_TABLE_DEFAULT;
1454 else if (!strcmp(name, "main"))
1455 table = RT_TABLE_MAIN;
1456 else if (!strcmp(name, "local"))
1457 table = RT_TABLE_LOCAL;
1459 /* try to look up name in /etc/iproute2/rt_tables */
1460 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1462 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1464 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1467 n = strtoul(e, NULL, 10);
1468 e = strtok(NULL, " \t\n");
1470 if (e && !strcmp(e, name))
1480 if (table == RT_TABLE_UNSPEC)
1483 /* do not consider main table special */
1484 if (table == RT_TABLE_MAIN)
1485 table = RT_TABLE_UNSPEC;
1491 static int system_iprule(struct iprule *rule, int cmd)
1493 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1496 struct rtmsg rtm = {
1497 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1498 .rtm_protocol = RTPROT_STATIC,
1499 .rtm_scope = RT_SCOPE_UNIVERSE,
1500 .rtm_table = RT_TABLE_UNSPEC,
1501 .rtm_type = RTN_UNSPEC,
1505 if (cmd == RTM_NEWRULE) {
1506 rtm.rtm_type = RTN_UNICAST;
1507 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1511 rtm.rtm_flags |= FIB_RULE_INVERT;
1513 if (rule->flags & IPRULE_SRC)
1514 rtm.rtm_src_len = rule->src_mask;
1516 if (rule->flags & IPRULE_DEST)
1517 rtm.rtm_dst_len = rule->dest_mask;
1519 if (rule->flags & IPRULE_TOS)
1520 rtm.rtm_tos = rule->tos;
1522 if (rule->flags & IPRULE_LOOKUP) {
1523 if (rule->lookup < 256)
1524 rtm.rtm_table = rule->lookup;
1527 if (rule->flags & IPRULE_ACTION)
1528 rtm.rtm_type = rule->action;
1529 else if (rule->flags & IPRULE_GOTO)
1530 rtm.rtm_type = FR_ACT_GOTO;
1531 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1532 rtm.rtm_type = FR_ACT_NOP;
1534 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1539 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1541 if (rule->flags & IPRULE_IN)
1542 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1544 if (rule->flags & IPRULE_OUT)
1545 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1547 if (rule->flags & IPRULE_SRC)
1548 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1550 if (rule->flags & IPRULE_DEST)
1551 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1553 if (rule->flags & IPRULE_PRIORITY)
1554 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1555 else if (cmd == RTM_NEWRULE)
1556 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1558 if (rule->flags & IPRULE_FWMARK)
1559 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1561 if (rule->flags & IPRULE_FWMASK)
1562 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1564 if (rule->flags & IPRULE_LOOKUP) {
1565 if (rule->lookup >= 256)
1566 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1569 if (rule->flags & IPRULE_GOTO)
1570 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1572 return system_rtnl_call(msg);
1575 int system_add_iprule(struct iprule *rule)
1577 return system_iprule(rule, RTM_NEWRULE);
1580 int system_del_iprule(struct iprule *rule)
1582 return system_iprule(rule, RTM_DELRULE);
1585 int system_flush_iprules(void)
1590 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1591 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1593 memset(&rule, 0, sizeof(rule));
1596 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1599 rule.lookup = RT_TABLE_LOCAL;
1600 rv |= system_iprule(&rule, RTM_NEWRULE);
1602 rule.priority = 32766;
1603 rule.lookup = RT_TABLE_MAIN;
1604 rv |= system_iprule(&rule, RTM_NEWRULE);
1606 rule.priority = 32767;
1607 rule.lookup = RT_TABLE_DEFAULT;
1608 rv |= system_iprule(&rule, RTM_NEWRULE);
1611 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1614 rule.lookup = RT_TABLE_LOCAL;
1615 rv |= system_iprule(&rule, RTM_NEWRULE);
1617 rule.priority = 32766;
1618 rule.lookup = RT_TABLE_MAIN;
1619 rv |= system_iprule(&rule, RTM_NEWRULE);
1624 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1626 return system_rtn_aton(action, id);
1629 time_t system_get_rtime(void)
1634 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1637 if (gettimeofday(&tv, NULL) == 0)
1644 #define IP_DF 0x4000
1647 static int tunnel_ioctl(const char *name, int cmd, void *p)
1651 memset(&ifr, 0, sizeof(ifr));
1652 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1653 ifr.ifr_ifru.ifru_data = p;
1654 return ioctl(sock_ioctl, cmd, &ifr);
1657 int system_del_ip_tunnel(const char *name)
1659 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
1662 int system_update_ipv6_mtu(struct device *dev, int mtu)
1666 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
1669 int fd = open(buf, O_RDWR);
1670 ssize_t len = read(fd, buf, sizeof(buf) - 1);
1677 if (!mtu || ret <= mtu)
1680 lseek(fd, 0, SEEK_SET);
1681 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) <= 0)
1689 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
1691 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
1692 struct blob_attr *cur;
1696 system_del_ip_tunnel(name);
1698 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
1699 blob_data(attr), blob_len(attr));
1701 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
1703 str = blobmsg_data(cur);
1705 if ((cur = tb[TUNNEL_ATTR_DF]))
1706 set_df = blobmsg_get_bool(cur);
1708 unsigned int ttl = 0;
1709 if ((cur = tb[TUNNEL_ATTR_TTL])) {
1710 ttl = blobmsg_get_u32(cur);
1711 if (ttl > 255 || (!set_df && ttl))
1715 unsigned int link = 0;
1716 if ((cur = tb[TUNNEL_ATTR_LINK])) {
1717 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
1721 if (iface->l3_dev.dev)
1722 link = iface->l3_dev.dev->ifindex;
1725 if (!strcmp(str, "sit")) {
1726 struct ip_tunnel_parm p = {
1731 .frag_off = set_df ? htons(IP_DF) : 0,
1732 .protocol = IPPROTO_IPV6,
1737 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
1738 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
1741 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
1742 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
1745 strncpy(p.name, name, sizeof(p.name));
1746 if (tunnel_ioctl("sit0", SIOCADDTUNNEL, &p) < 0)
1750 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
1752 struct ip_tunnel_6rd p6;
1754 memset(&p6, 0, sizeof(p6));
1756 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
1757 &p6.prefix, &mask) || mask > 128)
1759 p6.prefixlen = mask;
1761 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
1762 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
1763 &p6.relay_prefix, &mask) || mask > 32)
1765 p6.relay_prefixlen = mask;
1768 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
1769 system_del_ip_tunnel(name);
1774 } else if (!strcmp(str, "ipip6")) {
1775 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
1776 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
1777 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
1783 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
1784 nla_put_string(nlm, IFLA_IFNAME, name);
1787 nla_put_u32(nlm, IFLA_LINK, link);
1789 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
1794 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
1795 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
1802 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
1804 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
1805 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
1806 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
1808 struct in6_addr in6buf;
1809 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1810 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1814 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
1817 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
1818 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1822 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
1825 #ifdef IFLA_IPTUN_FMR_MAX
1826 if ((cur = tb[TUNNEL_ATTR_FMRS])) {
1827 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
1829 struct blob_attr *fmr;
1830 unsigned rem, fmrcnt = 0;
1831 blobmsg_for_each_attr(fmr, cur, rem) {
1832 if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
1835 unsigned ip4len, ip6len, ealen, offset = 6;
1839 if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
1840 ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) {
1845 struct in6_addr ip6prefix;
1846 struct in_addr ip4prefix;
1847 if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
1848 inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) {
1853 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
1855 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
1856 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
1857 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
1858 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
1859 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
1860 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
1862 nla_nest_end(nlm, rule);
1865 nla_nest_end(nlm, fmrs);
1869 nla_nest_end(nlm, infodata);
1870 nla_nest_end(nlm, linkinfo);
1872 return system_rtnl_call(nlm);