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_UNSPEC, };
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_string(msg, IFLA_IFNAME, 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_string(msg, IFLA_INFO_KIND, "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 = {
758 .ifi_family = AF_UNSPEC,
762 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
767 nlmsg_append(msg, &iim, sizeof(iim), 0);
769 nla_put_string(msg, IFLA_IFNAME, macvlan->ifname);
771 system_rtnl_call(msg);
776 static int system_vlan(struct device *dev, int id)
778 struct vlan_ioctl_args ifr = {
779 .cmd = SET_VLAN_NAME_TYPE_CMD,
780 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
783 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
786 ifr.cmd = DEL_VLAN_CMD;
789 ifr.cmd = ADD_VLAN_CMD;
792 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
793 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
796 int system_vlan_add(struct device *dev, int id)
798 return system_vlan(dev, id);
801 int system_vlan_del(struct device *dev)
803 return system_vlan(dev, -1);
806 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
809 struct nlattr *linkinfo, *data;
810 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
811 int ifindex = system_if_resolve(dev);
817 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
822 nlmsg_append(msg, &iim, sizeof(iim), 0);
823 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
824 nla_put_u32(msg, IFLA_LINK, ifindex);
826 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
827 goto nla_put_failure;
829 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
831 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
832 goto nla_put_failure;
834 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
836 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
837 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
839 if(cfg->proto == VLAN_PROTO_8021AD)
840 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);
843 nla_nest_end(msg, data);
844 nla_nest_end(msg, linkinfo);
846 rv = system_rtnl_call(msg);
848 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
857 int system_vlandev_del(struct device *vlandev)
860 struct ifinfomsg iim = {
861 .ifi_family = AF_UNSPEC,
865 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
870 nlmsg_append(msg, &iim, sizeof(iim), 0);
872 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
874 system_rtnl_call(msg);
880 system_if_get_settings(struct device *dev, struct device_settings *s)
885 memset(&ifr, 0, sizeof(ifr));
886 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
888 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
889 s->mtu = ifr.ifr_mtu;
890 s->flags |= DEV_OPT_MTU;
893 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
894 s->txqueuelen = ifr.ifr_qlen;
895 s->flags |= DEV_OPT_TXQUEUELEN;
898 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
899 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
900 s->flags |= DEV_OPT_MACADDR;
903 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
904 s->ipv6 = !strtoul(buf, NULL, 0);
905 s->flags |= DEV_OPT_IPV6;
910 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
917 memset(&ifr, 0, sizeof(ifr));
918 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
919 if (s->flags & DEV_OPT_MTU & apply_mask) {
920 ifr.ifr_mtu = s->mtu;
921 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
922 s->flags &= ~DEV_OPT_MTU;
924 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
925 ifr.ifr_qlen = s->txqueuelen;
926 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
927 s->flags &= ~DEV_OPT_TXQUEUELEN;
929 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
930 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
931 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
932 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
933 s->flags &= ~DEV_OPT_MACADDR;
935 if (s->flags & DEV_OPT_IPV6 & apply_mask)
936 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
939 int system_if_up(struct device *dev)
941 system_if_get_settings(dev, &dev->orig_settings);
942 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
943 device_set_ifindex(dev, system_if_resolve(dev));
944 return system_if_flags(dev->ifname, IFF_UP, 0);
947 int system_if_down(struct device *dev)
949 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
950 dev->orig_settings.flags &= dev->settings.flags;
951 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
955 struct if_check_data {
961 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
963 struct nlmsghdr *nh = nlmsg_hdr(msg);
964 struct ifinfomsg *ifi = NLMSG_DATA(nh);
965 struct if_check_data *chk = (struct if_check_data *)arg;
967 if (nh->nlmsg_type != RTM_NEWLINK)
970 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
971 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
976 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
978 struct if_check_data *chk = (struct if_check_data *)arg;
983 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
985 struct if_check_data *chk = (struct if_check_data *)arg;
987 device_set_present(chk->dev, false);
988 device_set_link(chk->dev, false);
989 chk->pending = err->error;
994 int system_if_check(struct device *dev)
996 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
998 struct ifinfomsg ifi = {
999 .ifi_family = AF_UNSPEC,
1002 struct if_check_data chk = {
1008 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1009 if (!msg || nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1010 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1013 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1014 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1015 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1017 nl_send_auto_complete(sock_rtnl, msg);
1018 while (chk.pending > 0)
1019 nl_recvmsgs(sock_rtnl, cb);
1030 system_if_get_parent(struct device *dev)
1032 char buf[64], *devname;
1033 int ifindex, iflink, len;
1036 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1037 f = fopen(buf, "r");
1041 len = fread(buf, 1, sizeof(buf) - 1, f);
1048 iflink = strtoul(buf, NULL, 0);
1049 ifindex = system_if_resolve(dev);
1050 if (!iflink || iflink == ifindex)
1053 devname = if_indextoname(iflink, buf);
1057 return device_get(devname, true);
1061 read_string_file(int dir_fd, const char *file, char *buf, int len)
1067 fd = openat(dir_fd, file, O_RDONLY);
1072 len = read(fd, buf, len - 1);
1076 } else if (len > 0) {
1079 c = strchr(buf, '\n');
1092 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1097 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1099 *val = strtoull(buf, NULL, 0);
1104 /* Assume advertised flags == supported flags */
1105 static const struct {
1108 } ethtool_link_modes[] = {
1109 { ADVERTISED_10baseT_Half, "10H" },
1110 { ADVERTISED_10baseT_Full, "10F" },
1111 { ADVERTISED_100baseT_Half, "100H" },
1112 { ADVERTISED_100baseT_Full, "100F" },
1113 { ADVERTISED_1000baseT_Half, "1000H" },
1114 { ADVERTISED_1000baseT_Full, "1000F" },
1117 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1120 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1121 if (mask & ethtool_link_modes[i].mask)
1122 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1127 system_if_force_external(const char *ifname)
1132 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1133 return stat(buf, &s) == 0;
1137 system_if_dump_info(struct device *dev, struct blob_buf *b)
1139 struct ethtool_cmd ecmd;
1145 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
1146 dir_fd = open(buf, O_DIRECTORY);
1148 memset(&ecmd, 0, sizeof(ecmd));
1149 memset(&ifr, 0, sizeof(ifr));
1150 strcpy(ifr.ifr_name, dev->ifname);
1151 ifr.ifr_data = (caddr_t) &ecmd;
1152 ecmd.cmd = ETHTOOL_GSET;
1154 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1155 c = blobmsg_open_array(b, "link-advertising");
1156 system_add_link_modes(b, ecmd.advertising);
1157 blobmsg_close_array(b, c);
1159 c = blobmsg_open_array(b, "link-supported");
1160 system_add_link_modes(b, ecmd.supported);
1161 blobmsg_close_array(b, c);
1163 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1164 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1165 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1166 blobmsg_add_string_buffer(b);
1174 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1176 const char *const counters[] = {
1177 "collisions", "rx_frame_errors", "tx_compressed",
1178 "multicast", "rx_length_errors", "tx_dropped",
1179 "rx_bytes", "rx_missed_errors", "tx_errors",
1180 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1181 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1182 "rx_dropped", "tx_aborted_errors", "tx_packets",
1183 "rx_errors", "tx_bytes", "tx_window_errors",
1184 "rx_fifo_errors", "tx_carrier_errors",
1191 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1192 stats_dir = open(buf, O_DIRECTORY);
1196 for (i = 0; i < ARRAY_SIZE(counters); i++)
1197 if (read_uint64_file(stats_dir, counters[i], &val))
1198 blobmsg_add_u64(b, counters[i], val);
1204 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1206 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1207 int alen = v4 ? 4 : 16;
1208 unsigned int flags = 0;
1209 struct ifaddrmsg ifa = {
1210 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1211 .ifa_prefixlen = addr->mask,
1212 .ifa_index = dev->ifindex,
1216 if (cmd == RTM_NEWADDR)
1217 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1219 msg = nlmsg_alloc_simple(cmd, flags);
1223 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1224 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1226 if (addr->broadcast)
1227 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1228 if (addr->point_to_point)
1229 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1231 time_t now = system_get_rtime();
1232 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1234 if (addr->preferred_until) {
1235 int64_t preferred = addr->preferred_until - now;
1238 else if (preferred > UINT32_MAX)
1239 preferred = UINT32_MAX;
1241 cinfo.ifa_prefered = preferred;
1244 if (addr->valid_until) {
1245 int64_t valid = addr->valid_until - now;
1248 else if (valid > UINT32_MAX)
1251 cinfo.ifa_valid = valid;
1254 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1257 return system_rtnl_call(msg);
1260 int system_add_address(struct device *dev, struct device_addr *addr)
1262 return system_addr(dev, addr, RTM_NEWADDR);
1265 int system_del_address(struct device *dev, struct device_addr *addr)
1267 return system_addr(dev, addr, RTM_DELADDR);
1270 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1272 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1274 unsigned int flags = 0;
1277 have_gw = !!route->nexthop.in.s_addr;
1279 have_gw = route->nexthop.in6.s6_addr32[0] ||
1280 route->nexthop.in6.s6_addr32[1] ||
1281 route->nexthop.in6.s6_addr32[2] ||
1282 route->nexthop.in6.s6_addr32[3];
1284 unsigned char scope = (cmd == RTM_DELROUTE) ? RT_SCOPE_NOWHERE :
1285 (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1287 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1288 ? route->table : RT_TABLE_MAIN;
1290 struct rtmsg rtm = {
1291 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1292 .rtm_dst_len = route->mask,
1293 .rtm_src_len = route->sourcemask,
1294 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1295 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
1297 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1298 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1302 if (cmd == RTM_NEWROUTE) {
1303 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1305 if (!dev) { // Add null-route
1306 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1307 rtm.rtm_type = RTN_UNREACHABLE;
1311 msg = nlmsg_alloc_simple(cmd, flags);
1315 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1318 nla_put(msg, RTA_DST, alen, &route->addr);
1320 if (route->sourcemask)
1321 nla_put(msg, RTA_SRC, alen, &route->source);
1323 if (route->metric > 0)
1324 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1327 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1330 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1333 nla_put_u32(msg, RTA_TABLE, table);
1335 if (route->flags & DEVROUTE_MTU) {
1336 struct nlattr *metrics;
1338 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1339 goto nla_put_failure;
1341 nla_put_u32(msg, RTAX_MTU, route->mtu);
1343 nla_nest_end(msg, metrics);
1346 return system_rtnl_call(msg);
1353 int system_add_route(struct device *dev, struct device_route *route)
1355 return system_rt(dev, route, RTM_NEWROUTE);
1358 int system_del_route(struct device *dev, struct device_route *route)
1360 return system_rt(dev, route, RTM_DELROUTE);
1363 int system_flush_routes(void)
1365 const char *names[] = {
1366 "/proc/sys/net/ipv4/route/flush",
1367 "/proc/sys/net/ipv6/route/flush"
1371 for (i = 0; i < ARRAY_SIZE(names); i++) {
1372 fd = open(names[i], O_WRONLY);
1376 if (write(fd, "-1", 2)) {}
1382 bool system_resolve_rt_table(const char *name, unsigned int *id)
1386 unsigned int n, table = RT_TABLE_UNSPEC;
1388 /* first try to parse table as number */
1389 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1392 /* handle well known aliases */
1393 else if (!strcmp(name, "default"))
1394 table = RT_TABLE_DEFAULT;
1395 else if (!strcmp(name, "main"))
1396 table = RT_TABLE_MAIN;
1397 else if (!strcmp(name, "local"))
1398 table = RT_TABLE_LOCAL;
1400 /* try to look up name in /etc/iproute2/rt_tables */
1401 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1403 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1405 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1408 n = strtoul(e, NULL, 10);
1409 e = strtok(NULL, " \t\n");
1411 if (e && !strcmp(e, name))
1421 if (table == RT_TABLE_UNSPEC)
1424 /* do not consider main table special */
1425 if (table == RT_TABLE_MAIN)
1426 table = RT_TABLE_UNSPEC;
1432 static int system_iprule(struct iprule *rule, int cmd)
1434 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1437 struct rtmsg rtm = {
1438 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1439 .rtm_protocol = RTPROT_STATIC,
1440 .rtm_scope = RT_SCOPE_UNIVERSE,
1441 .rtm_table = RT_TABLE_UNSPEC,
1442 .rtm_type = RTN_UNSPEC,
1446 if (cmd == RTM_NEWRULE) {
1447 rtm.rtm_type = RTN_UNICAST;
1448 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1452 rtm.rtm_flags |= FIB_RULE_INVERT;
1454 if (rule->flags & IPRULE_SRC)
1455 rtm.rtm_src_len = rule->src_mask;
1457 if (rule->flags & IPRULE_DEST)
1458 rtm.rtm_dst_len = rule->dest_mask;
1460 if (rule->flags & IPRULE_TOS)
1461 rtm.rtm_tos = rule->tos;
1463 if (rule->flags & IPRULE_LOOKUP) {
1464 if (rule->lookup < 256)
1465 rtm.rtm_table = rule->lookup;
1468 if (rule->flags & IPRULE_ACTION)
1469 rtm.rtm_type = rule->action;
1470 else if (rule->flags & IPRULE_GOTO)
1471 rtm.rtm_type = FR_ACT_GOTO;
1472 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1473 rtm.rtm_type = FR_ACT_NOP;
1475 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1480 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1482 if (rule->flags & IPRULE_IN)
1483 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1485 if (rule->flags & IPRULE_OUT)
1486 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1488 if (rule->flags & IPRULE_SRC)
1489 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1491 if (rule->flags & IPRULE_DEST)
1492 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1494 if (rule->flags & IPRULE_PRIORITY)
1495 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1496 else if (cmd == RTM_NEWRULE)
1497 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1499 if (rule->flags & IPRULE_FWMARK)
1500 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1502 if (rule->flags & IPRULE_FWMASK)
1503 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1505 if (rule->flags & IPRULE_LOOKUP) {
1506 if (rule->lookup >= 256)
1507 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1510 if (rule->flags & IPRULE_GOTO)
1511 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1513 return system_rtnl_call(msg);
1516 int system_add_iprule(struct iprule *rule)
1518 return system_iprule(rule, RTM_NEWRULE);
1521 int system_del_iprule(struct iprule *rule)
1523 return system_iprule(rule, RTM_DELRULE);
1526 int system_flush_iprules(void)
1531 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1532 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1534 memset(&rule, 0, sizeof(rule));
1537 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1540 rule.lookup = RT_TABLE_LOCAL;
1541 rv |= system_iprule(&rule, RTM_NEWRULE);
1543 rule.priority = 32766;
1544 rule.lookup = RT_TABLE_MAIN;
1545 rv |= system_iprule(&rule, RTM_NEWRULE);
1547 rule.priority = 32767;
1548 rule.lookup = RT_TABLE_DEFAULT;
1549 rv |= system_iprule(&rule, RTM_NEWRULE);
1552 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1555 rule.lookup = RT_TABLE_LOCAL;
1556 rv |= system_iprule(&rule, RTM_NEWRULE);
1558 rule.priority = 32766;
1559 rule.lookup = RT_TABLE_MAIN;
1560 rv |= system_iprule(&rule, RTM_NEWRULE);
1565 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1570 if (!strcmp(action, "local"))
1572 else if (!strcmp(action, "nat"))
1574 else if (!strcmp(action, "broadcast"))
1576 else if (!strcmp(action, "anycast"))
1578 else if (!strcmp(action, "multicast"))
1580 else if (!strcmp(action, "prohibit"))
1582 else if (!strcmp(action, "unreachable"))
1583 n = RTN_UNREACHABLE;
1584 else if (!strcmp(action, "blackhole"))
1586 else if (!strcmp(action, "xresolve"))
1588 else if (!strcmp(action, "unicast"))
1590 else if (!strcmp(action, "throw"))
1592 else if (!strcmp(action, "failed_policy"))
1593 n = RTN_FAILED_POLICY;
1595 n = strtoul(action, &e, 0);
1596 if (!e || *e || e == action || n > 255)
1604 time_t system_get_rtime(void)
1609 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1612 if (gettimeofday(&tv, NULL) == 0)
1619 #define IP_DF 0x4000
1622 static int tunnel_ioctl(const char *name, int cmd, void *p)
1626 memset(&ifr, 0, sizeof(ifr));
1627 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1628 ifr.ifr_ifru.ifru_data = p;
1629 return ioctl(sock_ioctl, cmd, &ifr);
1632 int system_del_ip_tunnel(const char *name)
1634 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
1637 int system_update_ipv6_mtu(struct device *dev, int mtu)
1641 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
1644 int fd = open(buf, O_RDWR);
1645 ssize_t len = read(fd, buf, sizeof(buf) - 1);
1652 if (!mtu || ret <= mtu)
1655 lseek(fd, 0, SEEK_SET);
1656 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) <= 0)
1664 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
1666 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
1667 struct blob_attr *cur;
1671 system_del_ip_tunnel(name);
1673 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
1674 blob_data(attr), blob_len(attr));
1676 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
1678 str = blobmsg_data(cur);
1680 if ((cur = tb[TUNNEL_ATTR_DF]))
1681 set_df = blobmsg_get_bool(cur);
1683 unsigned int ttl = 0;
1684 if ((cur = tb[TUNNEL_ATTR_TTL])) {
1685 ttl = blobmsg_get_u32(cur);
1686 if (ttl > 255 || (!set_df && ttl))
1690 unsigned int link = 0;
1691 if ((cur = tb[TUNNEL_ATTR_LINK])) {
1692 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
1696 if (iface->l3_dev.dev)
1697 link = iface->l3_dev.dev->ifindex;
1700 if (!strcmp(str, "sit")) {
1701 struct ip_tunnel_parm p = {
1706 .frag_off = set_df ? htons(IP_DF) : 0,
1707 .protocol = IPPROTO_IPV6,
1712 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
1713 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
1716 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
1717 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
1720 strncpy(p.name, name, sizeof(p.name));
1721 if (tunnel_ioctl("sit0", SIOCADDTUNNEL, &p) < 0)
1725 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
1727 struct ip_tunnel_6rd p6;
1729 memset(&p6, 0, sizeof(p6));
1731 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
1732 &p6.prefix, &mask) || mask > 128)
1734 p6.prefixlen = mask;
1736 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
1737 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
1738 &p6.relay_prefix, &mask) || mask > 32)
1740 p6.relay_prefixlen = mask;
1743 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
1744 system_del_ip_tunnel(name);
1749 } else if (!strcmp(str, "ipip6")) {
1750 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
1751 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
1753 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
1754 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
1755 nla_put_string(nlm, IFLA_IFNAME, name);
1758 nla_put_u32(nlm, IFLA_LINK, link);
1760 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
1761 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
1762 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
1765 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
1767 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
1768 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
1769 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
1771 struct in6_addr in6buf;
1772 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1773 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1)
1775 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
1778 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
1779 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1)
1781 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
1784 #ifdef IFLA_IPTUN_FMR_MAX
1785 if ((cur = tb[TUNNEL_ATTR_FMRS])) {
1786 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
1788 struct blob_attr *fmr;
1789 unsigned rem, fmrcnt = 0;
1790 blobmsg_for_each_attr(fmr, cur, rem) {
1791 if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
1794 unsigned ip4len, ip6len, ealen, offset = 6;
1798 if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
1799 ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5)
1802 struct in6_addr ip6prefix;
1803 struct in_addr ip4prefix;
1804 if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
1805 inet_pton(AF_INET, ip4buf, &ip4prefix) != 1)
1808 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
1810 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
1811 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
1812 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
1813 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
1814 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
1815 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
1817 nla_nest_end(nlm, rule);
1820 nla_nest_end(nlm, fmrs);
1824 nla_nest_end(nlm, infodata);
1825 nla_nest_end(nlm, linkinfo);
1827 return system_rtnl_call(nlm);