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))
167 int system_init(void)
169 static struct event_socket rtnl_event;
170 static struct event_socket hotplug_event;
172 sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0);
173 system_fd_set_cloexec(sock_ioctl);
175 // Prepare socket for routing / address control
176 sock_rtnl = create_socket(NETLINK_ROUTE, 0);
180 if (!create_event_socket(&rtnl_event, NETLINK_ROUTE, cb_rtnl_event))
183 if (!create_raw_event_socket(&hotplug_event, NETLINK_KOBJECT_UEVENT, 1,
184 handle_hotplug_event, 0))
187 // Receive network link events form kernel
188 nl_socket_add_membership(rtnl_event.sock, RTNLGRP_LINK);
193 static void system_set_sysctl(const char *path, const char *val)
197 fd = open(path, O_WRONLY);
201 if (write(fd, val, strlen(val))) {}
205 static void system_set_dev_sysctl(const char *path, const char *device, const char *val)
207 snprintf(dev_buf, sizeof(dev_buf), path, device);
208 system_set_sysctl(dev_buf, val);
211 static void system_set_disable_ipv6(struct device *dev, const char *val)
213 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val);
216 static int system_get_sysctl(const char *path, char *buf, const size_t buf_sz)
218 int fd = -1, ret = -1;
220 fd = open(path, O_RDONLY);
224 ssize_t len = read(fd, buf, buf_sz - 1);
238 system_get_dev_sysctl(const char *path, const char *device, char *buf, const size_t buf_sz)
240 snprintf(dev_buf, sizeof(dev_buf), path, device);
241 return system_get_sysctl(dev_buf, buf, buf_sz);
244 static int system_get_disable_ipv6(struct device *dev, char *buf, const size_t buf_sz)
246 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6",
247 dev->ifname, buf, buf_sz);
251 #define IFF_LOWER_UP 0x10000
254 // Evaluate netlink messages
255 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
257 struct nlmsghdr *nh = nlmsg_hdr(msg);
258 struct ifinfomsg *ifi = NLMSG_DATA(nh);
259 struct nlattr *nla[__IFLA_MAX];
261 if (nh->nlmsg_type != RTM_NEWLINK)
264 nlmsg_parse(nh, sizeof(*ifi), nla, __IFLA_MAX - 1, NULL);
265 if (!nla[IFLA_IFNAME])
268 struct device *dev = device_get(nla_data(nla[IFLA_IFNAME]), false);
272 device_set_ifindex(dev, ifi->ifi_index);
273 device_set_link(dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
280 handle_hotplug_msg(char *data, int size)
282 const char *subsystem = NULL, *interface = NULL;
283 char *cur, *end, *sep;
288 if (!strncmp(data, "add@", 4))
290 else if (!strncmp(data, "remove@", 7))
295 skip = strlen(data) + 1;
298 for (cur = data + skip; cur < end; cur += skip) {
299 skip = strlen(cur) + 1;
301 sep = strchr(cur, '=');
306 if (!strcmp(cur, "INTERFACE"))
308 else if (!strcmp(cur, "SUBSYSTEM")) {
310 if (strcmp(subsystem, "net") != 0)
313 if (subsystem && interface)
319 dev = device_get(interface, false);
323 if (dev->type != &simple_device_type)
326 if (add && system_if_force_external(dev->ifname))
329 device_set_present(dev, add);
333 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
335 struct event_socket *ev = container_of(u, struct event_socket, uloop);
336 struct sockaddr_nl nla;
337 unsigned char *buf = NULL;
340 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
342 handle_hotplug_msg((char *) buf, size);
348 static int system_rtnl_call(struct nl_msg *msg)
352 ret = nl_send_auto_complete(sock_rtnl, msg);
358 return nl_wait_for_ack(sock_rtnl);
361 int system_bridge_delbr(struct device *bridge)
363 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
366 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
370 memset(&ifr, 0, sizeof(ifr));
372 ifr.ifr_ifindex = dev->ifindex;
375 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
376 return ioctl(sock_ioctl, cmd, &ifr);
379 static bool system_is_bridge(const char *name, char *buf, int buflen)
383 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
384 if (stat(buf, &st) < 0)
390 static char *system_get_bridge(const char *name, char *buf, int buflen)
396 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
397 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
400 if (gl.gl_pathc == 0)
403 len = readlink(gl.gl_pathv[0], buf, buflen);
408 path = strrchr(buf, '/');
415 int system_bridge_addif(struct device *bridge, struct device *dev)
419 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
420 if (oldbr && !strcmp(oldbr, bridge->ifname))
423 return system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
426 int system_bridge_delif(struct device *bridge, struct device *dev)
428 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
431 static int system_if_resolve(struct device *dev)
434 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
435 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
436 return ifr.ifr_ifindex;
441 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
445 memset(&ifr, 0, sizeof(ifr));
446 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
447 ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
448 ifr.ifr_flags |= add;
449 ifr.ifr_flags &= ~rem;
450 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
462 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
464 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
466 return ifa->ifa_index == ifindex;
469 static bool check_route(struct nlmsghdr *hdr, int ifindex)
471 struct rtmsg *r = NLMSG_DATA(hdr);
472 struct nlattr *tb[__RTA_MAX];
474 if (r->rtm_protocol == RTPROT_KERNEL &&
475 r->rtm_family == AF_INET6)
478 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
482 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
485 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
490 static int cb_clear_event(struct nl_msg *msg, void *arg)
492 struct clear_data *clr = arg;
493 struct nlmsghdr *hdr = nlmsg_hdr(msg);
494 bool (*cb)(struct nlmsghdr *, int ifindex);
500 if (hdr->nlmsg_type != RTM_NEWADDR)
507 if (hdr->nlmsg_type != RTM_NEWROUTE)
514 if (hdr->nlmsg_type != RTM_NEWRULE)
523 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
526 if (type == RTM_DELRULE)
527 D(SYSTEM, "Remove a rule\n");
529 D(SYSTEM, "Remove %s from device %s\n",
530 type == RTM_DELADDR ? "an address" : "a route",
532 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
533 hdr = nlmsg_hdr(clr->msg);
534 hdr->nlmsg_type = type;
535 hdr->nlmsg_flags = NLM_F_REQUEST;
537 nl_socket_disable_auto_ack(sock_rtnl);
538 nl_send_auto_complete(sock_rtnl, clr->msg);
539 nl_socket_enable_auto_ack(sock_rtnl);
545 cb_finish_event(struct nl_msg *msg, void *arg)
553 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
556 *pending = err->error;
561 system_if_clear_entries(struct device *dev, int type, int af)
563 struct clear_data clr;
564 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
567 .rtm_flags = RTM_F_CLONED,
569 int flags = NLM_F_DUMP;
578 clr.size = sizeof(struct rtgenmsg);
581 clr.size = sizeof(struct rtmsg);
590 clr.msg = nlmsg_alloc_simple(type, flags);
594 nlmsg_append(clr.msg, &rtm, clr.size, 0);
595 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
596 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
597 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
599 nl_send_auto_complete(sock_rtnl, clr.msg);
601 nl_recvmsgs(sock_rtnl, cb);
609 * Clear bridge (membership) state and bring down device
611 void system_if_clear_state(struct device *dev)
613 static char buf[256];
616 device_set_ifindex(dev, system_if_resolve(dev));
617 if (dev->external || !dev->ifindex)
620 system_if_flags(dev->ifname, 0, IFF_UP);
622 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
623 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
624 system_bridge_delbr(dev);
628 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
630 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
631 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
634 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
635 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
636 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
637 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
638 system_set_disable_ipv6(dev, "0");
641 static inline unsigned long
642 sec_to_jiffies(int val)
644 return (unsigned long) val * 100;
647 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
649 unsigned long args[4] = {};
651 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
654 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
655 args[1] = !!cfg->stp;
656 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
658 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
659 args[1] = sec_to_jiffies(cfg->forward_delay);
660 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
662 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
663 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
665 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
666 args[1] = cfg->priority;
667 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
669 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
670 args[0] = BRCTL_SET_AGEING_TIME;
671 args[1] = sec_to_jiffies(cfg->ageing_time);
672 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
675 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
676 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
677 args[1] = sec_to_jiffies(cfg->hello_time);
678 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
681 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
682 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
683 args[1] = sec_to_jiffies(cfg->max_age);
684 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
690 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
693 struct nlattr *linkinfo, *data;
694 struct ifinfomsg iim = { .ifi_family = AF_INET };
695 int ifindex = system_if_resolve(dev);
697 static const struct {
699 enum macvlan_mode val;
701 { "private", MACVLAN_MODE_PRIVATE },
702 { "vepa", MACVLAN_MODE_VEPA },
703 { "bridge", MACVLAN_MODE_BRIDGE },
704 { "passthru", MACVLAN_MODE_PASSTHRU },
710 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
715 nlmsg_append(msg, &iim, sizeof(iim), 0);
717 if (cfg->flags & MACVLAN_OPT_MACADDR)
718 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
719 nla_put(msg, IFLA_IFNAME, IFNAMSIZ, macvlan->ifname);
720 nla_put_u32(msg, IFLA_LINK, ifindex);
722 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
723 goto nla_put_failure;
725 nla_put(msg, IFLA_INFO_KIND, strlen("macvlan"), "macvlan");
727 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
728 goto nla_put_failure;
731 for (i = 0; i < ARRAY_SIZE(modes); i++) {
732 if (strcmp(cfg->mode, modes[i].name) != 0)
735 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
740 nla_nest_end(msg, data);
741 nla_nest_end(msg, linkinfo);
743 rv = system_rtnl_call(msg);
745 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
754 int system_macvlan_del(struct device *macvlan)
757 struct ifinfomsg iim;
759 iim.ifi_family = AF_INET;
762 msg = nlmsg_alloc_simple(RTM_DELLINK, 0);
767 nlmsg_append(msg, &iim, sizeof(iim), 0);
769 nla_put(msg, IFLA_INFO_KIND, strlen("macvlan"), "macvlan");
770 nla_put(msg, IFLA_IFNAME, sizeof(macvlan->ifname), macvlan->ifname);
772 system_rtnl_call(msg);
777 static int system_vlan(struct device *dev, int id)
779 struct vlan_ioctl_args ifr = {
780 .cmd = SET_VLAN_NAME_TYPE_CMD,
781 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
784 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
787 ifr.cmd = DEL_VLAN_CMD;
790 ifr.cmd = ADD_VLAN_CMD;
793 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
794 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
797 int system_vlan_add(struct device *dev, int id)
799 return system_vlan(dev, id);
802 int system_vlan_del(struct device *dev)
804 return system_vlan(dev, -1);
807 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
810 struct nlattr *linkinfo, *data;
811 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
812 int ifindex = system_if_resolve(dev);
818 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
823 nlmsg_append(msg, &iim, sizeof(iim), 0);
824 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
825 nla_put_u32(msg, IFLA_LINK, ifindex);
827 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
828 goto nla_put_failure;
830 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
832 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
833 goto nla_put_failure;
835 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
837 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
838 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
840 if(cfg->proto == VLAN_PROTO_8021AD)
841 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);
844 nla_nest_end(msg, data);
845 nla_nest_end(msg, linkinfo);
847 rv = system_rtnl_call(msg);
849 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
858 int system_vlandev_del(struct device *vlandev)
861 struct ifinfomsg iim = {
862 .ifi_family = AF_UNSPEC,
866 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
871 nlmsg_append(msg, &iim, sizeof(iim), 0);
873 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
875 system_rtnl_call(msg);
881 system_if_get_settings(struct device *dev, struct device_settings *s)
886 memset(&ifr, 0, sizeof(ifr));
887 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
889 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
890 s->mtu = ifr.ifr_mtu;
891 s->flags |= DEV_OPT_MTU;
894 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
895 s->txqueuelen = ifr.ifr_qlen;
896 s->flags |= DEV_OPT_TXQUEUELEN;
899 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
900 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
901 s->flags |= DEV_OPT_MACADDR;
904 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
905 s->ipv6 = !strtoul(buf, NULL, 0);
906 s->flags |= DEV_OPT_IPV6;
911 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
918 memset(&ifr, 0, sizeof(ifr));
919 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
920 if (s->flags & DEV_OPT_MTU & apply_mask) {
921 ifr.ifr_mtu = s->mtu;
922 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
923 s->flags &= ~DEV_OPT_MTU;
925 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
926 ifr.ifr_qlen = s->txqueuelen;
927 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
928 s->flags &= ~DEV_OPT_TXQUEUELEN;
930 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
931 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
932 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
933 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
934 s->flags &= ~DEV_OPT_MACADDR;
936 if (s->flags & DEV_OPT_IPV6 & apply_mask)
937 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
940 int system_if_up(struct device *dev)
942 system_if_get_settings(dev, &dev->orig_settings);
943 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
944 device_set_ifindex(dev, system_if_resolve(dev));
945 return system_if_flags(dev->ifname, IFF_UP, 0);
948 int system_if_down(struct device *dev)
950 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
951 dev->orig_settings.flags &= dev->settings.flags;
952 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
956 struct if_check_data {
962 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
964 struct nlmsghdr *nh = nlmsg_hdr(msg);
965 struct ifinfomsg *ifi = NLMSG_DATA(nh);
966 struct if_check_data *chk = (struct if_check_data *)arg;
968 if (nh->nlmsg_type != RTM_NEWLINK)
971 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
972 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
977 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
979 struct if_check_data *chk = (struct if_check_data *)arg;
984 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
986 struct if_check_data *chk = (struct if_check_data *)arg;
988 device_set_present(chk->dev, false);
989 device_set_link(chk->dev, false);
990 chk->pending = err->error;
995 int system_if_check(struct device *dev)
997 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
999 struct ifinfomsg ifi = {
1000 .ifi_family = AF_UNSPEC,
1003 struct if_check_data chk = {
1009 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1010 if (!msg || nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1011 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1014 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1015 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1016 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1018 nl_send_auto_complete(sock_rtnl, msg);
1019 while (chk.pending > 0)
1020 nl_recvmsgs(sock_rtnl, cb);
1031 system_if_get_parent(struct device *dev)
1033 char buf[64], *devname;
1034 int ifindex, iflink, len;
1037 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1038 f = fopen(buf, "r");
1042 len = fread(buf, 1, sizeof(buf) - 1, f);
1049 iflink = strtoul(buf, NULL, 0);
1050 ifindex = system_if_resolve(dev);
1051 if (!iflink || iflink == ifindex)
1054 devname = if_indextoname(iflink, buf);
1058 return device_get(devname, true);
1062 read_string_file(int dir_fd, const char *file, char *buf, int len)
1068 fd = openat(dir_fd, file, O_RDONLY);
1073 len = read(fd, buf, len - 1);
1077 } else if (len > 0) {
1080 c = strchr(buf, '\n');
1093 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1098 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1100 *val = strtoull(buf, NULL, 0);
1105 /* Assume advertised flags == supported flags */
1106 static const struct {
1109 } ethtool_link_modes[] = {
1110 { ADVERTISED_10baseT_Half, "10H" },
1111 { ADVERTISED_10baseT_Full, "10F" },
1112 { ADVERTISED_100baseT_Half, "100H" },
1113 { ADVERTISED_100baseT_Full, "100F" },
1114 { ADVERTISED_1000baseT_Half, "1000H" },
1115 { ADVERTISED_1000baseT_Full, "1000F" },
1118 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1121 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1122 if (mask & ethtool_link_modes[i].mask)
1123 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1128 system_if_force_external(const char *ifname)
1133 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1134 return stat(buf, &s) == 0;
1138 system_if_dump_info(struct device *dev, struct blob_buf *b)
1140 struct ethtool_cmd ecmd;
1146 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
1147 dir_fd = open(buf, O_DIRECTORY);
1149 memset(&ecmd, 0, sizeof(ecmd));
1150 memset(&ifr, 0, sizeof(ifr));
1151 strcpy(ifr.ifr_name, dev->ifname);
1152 ifr.ifr_data = (caddr_t) &ecmd;
1153 ecmd.cmd = ETHTOOL_GSET;
1155 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1156 c = blobmsg_open_array(b, "link-advertising");
1157 system_add_link_modes(b, ecmd.advertising);
1158 blobmsg_close_array(b, c);
1160 c = blobmsg_open_array(b, "link-supported");
1161 system_add_link_modes(b, ecmd.supported);
1162 blobmsg_close_array(b, c);
1164 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1165 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1166 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1167 blobmsg_add_string_buffer(b);
1175 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1177 const char *const counters[] = {
1178 "collisions", "rx_frame_errors", "tx_compressed",
1179 "multicast", "rx_length_errors", "tx_dropped",
1180 "rx_bytes", "rx_missed_errors", "tx_errors",
1181 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1182 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1183 "rx_dropped", "tx_aborted_errors", "tx_packets",
1184 "rx_errors", "tx_bytes", "tx_window_errors",
1185 "rx_fifo_errors", "tx_carrier_errors",
1192 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1193 stats_dir = open(buf, O_DIRECTORY);
1197 for (i = 0; i < ARRAY_SIZE(counters); i++)
1198 if (read_uint64_file(stats_dir, counters[i], &val))
1199 blobmsg_add_u64(b, counters[i], val);
1205 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1207 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1208 int alen = v4 ? 4 : 16;
1209 unsigned int flags = 0;
1210 struct ifaddrmsg ifa = {
1211 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1212 .ifa_prefixlen = addr->mask,
1213 .ifa_index = dev->ifindex,
1217 if (cmd == RTM_NEWADDR)
1218 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1220 msg = nlmsg_alloc_simple(cmd, flags);
1224 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1225 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1227 if (addr->broadcast)
1228 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1229 if (addr->point_to_point)
1230 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1232 time_t now = system_get_rtime();
1233 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1235 if (addr->preferred_until) {
1236 int64_t preferred = addr->preferred_until - now;
1239 else if (preferred > UINT32_MAX)
1240 preferred = UINT32_MAX;
1242 cinfo.ifa_prefered = preferred;
1245 if (addr->valid_until) {
1246 int64_t valid = addr->valid_until - now;
1249 else if (valid > UINT32_MAX)
1252 cinfo.ifa_valid = valid;
1255 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1258 return system_rtnl_call(msg);
1261 int system_add_address(struct device *dev, struct device_addr *addr)
1263 return system_addr(dev, addr, RTM_NEWADDR);
1266 int system_del_address(struct device *dev, struct device_addr *addr)
1268 return system_addr(dev, addr, RTM_DELADDR);
1271 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1273 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1275 unsigned int flags = 0;
1278 have_gw = !!route->nexthop.in.s_addr;
1280 have_gw = route->nexthop.in6.s6_addr32[0] ||
1281 route->nexthop.in6.s6_addr32[1] ||
1282 route->nexthop.in6.s6_addr32[2] ||
1283 route->nexthop.in6.s6_addr32[3];
1285 unsigned char scope = (cmd == RTM_DELROUTE) ? RT_SCOPE_NOWHERE :
1286 (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1288 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1289 ? route->table : RT_TABLE_MAIN;
1291 struct rtmsg rtm = {
1292 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1293 .rtm_dst_len = route->mask,
1294 .rtm_src_len = route->sourcemask,
1295 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1296 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
1298 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1299 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1303 if (cmd == RTM_NEWROUTE) {
1304 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1306 if (!dev) { // Add null-route
1307 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1308 rtm.rtm_type = RTN_UNREACHABLE;
1312 msg = nlmsg_alloc_simple(cmd, flags);
1316 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1319 nla_put(msg, RTA_DST, alen, &route->addr);
1321 if (route->sourcemask)
1322 nla_put(msg, RTA_SRC, alen, &route->source);
1324 if (route->metric > 0)
1325 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1328 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1331 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1334 nla_put_u32(msg, RTA_TABLE, table);
1336 if (route->flags & DEVROUTE_MTU) {
1337 struct nlattr *metrics;
1339 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1340 goto nla_put_failure;
1342 nla_put_u32(msg, RTAX_MTU, route->mtu);
1344 nla_nest_end(msg, metrics);
1347 return system_rtnl_call(msg);
1354 int system_add_route(struct device *dev, struct device_route *route)
1356 return system_rt(dev, route, RTM_NEWROUTE);
1359 int system_del_route(struct device *dev, struct device_route *route)
1361 return system_rt(dev, route, RTM_DELROUTE);
1364 int system_flush_routes(void)
1366 const char *names[] = {
1367 "/proc/sys/net/ipv4/route/flush",
1368 "/proc/sys/net/ipv6/route/flush"
1372 for (i = 0; i < ARRAY_SIZE(names); i++) {
1373 fd = open(names[i], O_WRONLY);
1377 if (write(fd, "-1", 2)) {}
1383 bool system_resolve_rt_table(const char *name, unsigned int *id)
1387 unsigned int n, table = RT_TABLE_UNSPEC;
1389 /* first try to parse table as number */
1390 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1393 /* handle well known aliases */
1394 else if (!strcmp(name, "default"))
1395 table = RT_TABLE_DEFAULT;
1396 else if (!strcmp(name, "main"))
1397 table = RT_TABLE_MAIN;
1398 else if (!strcmp(name, "local"))
1399 table = RT_TABLE_LOCAL;
1401 /* try to look up name in /etc/iproute2/rt_tables */
1402 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1404 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1406 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1409 n = strtoul(e, NULL, 10);
1410 e = strtok(NULL, " \t\n");
1412 if (e && !strcmp(e, name))
1422 if (table == RT_TABLE_UNSPEC)
1425 /* do not consider main table special */
1426 if (table == RT_TABLE_MAIN)
1427 table = RT_TABLE_UNSPEC;
1433 static int system_iprule(struct iprule *rule, int cmd)
1435 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1438 struct rtmsg rtm = {
1439 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1440 .rtm_protocol = RTPROT_STATIC,
1441 .rtm_scope = RT_SCOPE_UNIVERSE,
1442 .rtm_table = RT_TABLE_UNSPEC,
1443 .rtm_type = RTN_UNSPEC,
1447 if (cmd == RTM_NEWRULE) {
1448 rtm.rtm_type = RTN_UNICAST;
1449 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1453 rtm.rtm_flags |= FIB_RULE_INVERT;
1455 if (rule->flags & IPRULE_SRC)
1456 rtm.rtm_src_len = rule->src_mask;
1458 if (rule->flags & IPRULE_DEST)
1459 rtm.rtm_dst_len = rule->dest_mask;
1461 if (rule->flags & IPRULE_TOS)
1462 rtm.rtm_tos = rule->tos;
1464 if (rule->flags & IPRULE_LOOKUP) {
1465 if (rule->lookup < 256)
1466 rtm.rtm_table = rule->lookup;
1469 if (rule->flags & IPRULE_ACTION)
1470 rtm.rtm_type = rule->action;
1471 else if (rule->flags & IPRULE_GOTO)
1472 rtm.rtm_type = FR_ACT_GOTO;
1473 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1474 rtm.rtm_type = FR_ACT_NOP;
1476 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1481 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1483 if (rule->flags & IPRULE_IN)
1484 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1486 if (rule->flags & IPRULE_OUT)
1487 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1489 if (rule->flags & IPRULE_SRC)
1490 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1492 if (rule->flags & IPRULE_DEST)
1493 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1495 if (rule->flags & IPRULE_PRIORITY)
1496 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1497 else if (cmd == RTM_NEWRULE)
1498 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1500 if (rule->flags & IPRULE_FWMARK)
1501 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1503 if (rule->flags & IPRULE_FWMASK)
1504 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1506 if (rule->flags & IPRULE_LOOKUP) {
1507 if (rule->lookup >= 256)
1508 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1511 if (rule->flags & IPRULE_GOTO)
1512 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1514 return system_rtnl_call(msg);
1517 int system_add_iprule(struct iprule *rule)
1519 return system_iprule(rule, RTM_NEWRULE);
1522 int system_del_iprule(struct iprule *rule)
1524 return system_iprule(rule, RTM_DELRULE);
1527 int system_flush_iprules(void)
1532 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1533 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1535 memset(&rule, 0, sizeof(rule));
1538 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1541 rule.lookup = RT_TABLE_LOCAL;
1542 rv |= system_iprule(&rule, RTM_NEWRULE);
1544 rule.priority = 32766;
1545 rule.lookup = RT_TABLE_MAIN;
1546 rv |= system_iprule(&rule, RTM_NEWRULE);
1548 rule.priority = 32767;
1549 rule.lookup = RT_TABLE_DEFAULT;
1550 rv |= system_iprule(&rule, RTM_NEWRULE);
1553 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1556 rule.lookup = RT_TABLE_LOCAL;
1557 rv |= system_iprule(&rule, RTM_NEWRULE);
1559 rule.priority = 32766;
1560 rule.lookup = RT_TABLE_MAIN;
1561 rv |= system_iprule(&rule, RTM_NEWRULE);
1566 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1571 if (!strcmp(action, "local"))
1573 else if (!strcmp(action, "nat"))
1575 else if (!strcmp(action, "broadcast"))
1577 else if (!strcmp(action, "anycast"))
1579 else if (!strcmp(action, "multicast"))
1581 else if (!strcmp(action, "prohibit"))
1583 else if (!strcmp(action, "unreachable"))
1584 n = RTN_UNREACHABLE;
1585 else if (!strcmp(action, "blackhole"))
1587 else if (!strcmp(action, "xresolve"))
1589 else if (!strcmp(action, "unicast"))
1591 else if (!strcmp(action, "throw"))
1593 else if (!strcmp(action, "failed_policy"))
1594 n = RTN_FAILED_POLICY;
1596 n = strtoul(action, &e, 0);
1597 if (!e || *e || e == action || n > 255)
1605 time_t system_get_rtime(void)
1610 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1613 if (gettimeofday(&tv, NULL) == 0)
1620 #define IP_DF 0x4000
1623 static int tunnel_ioctl(const char *name, int cmd, void *p)
1627 memset(&ifr, 0, sizeof(ifr));
1628 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1629 ifr.ifr_ifru.ifru_data = p;
1630 return ioctl(sock_ioctl, cmd, &ifr);
1633 int system_del_ip_tunnel(const char *name)
1635 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
1638 int system_update_ipv6_mtu(struct device *dev, int mtu)
1642 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
1645 int fd = open(buf, O_RDWR);
1646 ssize_t len = read(fd, buf, sizeof(buf) - 1);
1653 if (!mtu || ret <= mtu)
1656 lseek(fd, 0, SEEK_SET);
1657 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) <= 0)
1665 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
1667 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
1668 struct blob_attr *cur;
1672 system_del_ip_tunnel(name);
1674 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
1675 blob_data(attr), blob_len(attr));
1677 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
1679 str = blobmsg_data(cur);
1681 if ((cur = tb[TUNNEL_ATTR_DF]))
1682 set_df = blobmsg_get_bool(cur);
1684 unsigned int ttl = 0;
1685 if ((cur = tb[TUNNEL_ATTR_TTL])) {
1686 ttl = blobmsg_get_u32(cur);
1687 if (ttl > 255 || (!set_df && ttl))
1691 unsigned int link = 0;
1692 if ((cur = tb[TUNNEL_ATTR_LINK])) {
1693 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
1697 if (iface->l3_dev.dev)
1698 link = iface->l3_dev.dev->ifindex;
1701 if (!strcmp(str, "sit")) {
1702 struct ip_tunnel_parm p = {
1707 .frag_off = set_df ? htons(IP_DF) : 0,
1708 .protocol = IPPROTO_IPV6,
1713 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
1714 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
1717 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
1718 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
1721 strncpy(p.name, name, sizeof(p.name));
1722 if (tunnel_ioctl("sit0", SIOCADDTUNNEL, &p) < 0)
1726 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
1728 struct ip_tunnel_6rd p6;
1730 memset(&p6, 0, sizeof(p6));
1732 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
1733 &p6.prefix, &mask) || mask > 128)
1735 p6.prefixlen = mask;
1737 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
1738 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
1739 &p6.relay_prefix, &mask) || mask > 32)
1741 p6.relay_prefixlen = mask;
1744 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
1745 system_del_ip_tunnel(name);
1750 } else if (!strcmp(str, "ipip6")) {
1751 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
1752 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
1754 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
1755 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
1756 nla_put_string(nlm, IFLA_IFNAME, name);
1759 nla_put_u32(nlm, IFLA_LINK, link);
1761 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
1762 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
1763 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
1766 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
1768 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
1769 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
1770 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
1772 struct in6_addr in6buf;
1773 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1774 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1)
1776 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
1779 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
1780 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1)
1782 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
1785 #ifdef IFLA_IPTUN_FMR_MAX
1786 if ((cur = tb[TUNNEL_ATTR_FMRS])) {
1787 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
1789 struct blob_attr *fmr;
1790 unsigned rem, fmrcnt = 0;
1791 blobmsg_for_each_attr(fmr, cur, rem) {
1792 if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
1795 unsigned ip4len, ip6len, ealen, offset = 6;
1799 if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
1800 ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5)
1803 struct in6_addr ip6prefix;
1804 struct in_addr ip4prefix;
1805 if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
1806 inet_pton(AF_INET, ip4buf, &ip4prefix) != 1)
1809 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
1811 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
1812 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
1813 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
1814 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
1815 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
1816 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
1818 nla_nest_end(nlm, rule);
1821 nla_nest_end(nlm, fmrs);
1825 nla_nest_end(nlm, infodata);
1826 nla_nest_end(nlm, linkinfo);
1828 return system_rtnl_call(nlm);