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_INET };
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(msg, IFLA_IFNAME, IFNAMSIZ, 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(msg, IFLA_INFO_KIND, strlen("vlan"), "vlan");
833 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
834 goto nla_put_failure;
836 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
838 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
839 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
841 if(cfg->proto == VLAN_PROTO_8021AD)
842 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);
845 nla_nest_end(msg, data);
846 nla_nest_end(msg, linkinfo);
848 rv = system_rtnl_call(msg);
850 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
859 int system_vlandev_del(struct device *vlandev)
862 struct ifinfomsg iim;
864 iim.ifi_family = AF_INET;
867 msg = nlmsg_alloc_simple(RTM_DELLINK, 0);
872 nlmsg_append(msg, &iim, sizeof(iim), 0);
874 nla_put(msg, IFLA_INFO_KIND, strlen("vlan"), "vlan");
875 nla_put(msg, IFLA_IFNAME, sizeof(vlandev->ifname), vlandev->ifname);
877 system_rtnl_call(msg);
883 system_if_get_settings(struct device *dev, struct device_settings *s)
888 memset(&ifr, 0, sizeof(ifr));
889 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
891 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
892 s->mtu = ifr.ifr_mtu;
893 s->flags |= DEV_OPT_MTU;
896 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
897 s->txqueuelen = ifr.ifr_qlen;
898 s->flags |= DEV_OPT_TXQUEUELEN;
901 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
902 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
903 s->flags |= DEV_OPT_MACADDR;
906 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
907 s->ipv6 = !strtoul(buf, NULL, 0);
908 s->flags |= DEV_OPT_IPV6;
913 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
920 memset(&ifr, 0, sizeof(ifr));
921 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
922 if (s->flags & DEV_OPT_MTU & apply_mask) {
923 ifr.ifr_mtu = s->mtu;
924 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
925 s->flags &= ~DEV_OPT_MTU;
927 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
928 ifr.ifr_qlen = s->txqueuelen;
929 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
930 s->flags &= ~DEV_OPT_TXQUEUELEN;
932 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
933 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
934 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
935 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
936 s->flags &= ~DEV_OPT_MACADDR;
938 if (s->flags & DEV_OPT_IPV6 & apply_mask)
939 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
942 int system_if_up(struct device *dev)
944 system_if_get_settings(dev, &dev->orig_settings);
945 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
946 device_set_ifindex(dev, system_if_resolve(dev));
947 return system_if_flags(dev->ifname, IFF_UP, 0);
950 int system_if_down(struct device *dev)
952 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
953 dev->orig_settings.flags &= dev->settings.flags;
954 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
958 struct if_check_data {
964 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
966 struct nlmsghdr *nh = nlmsg_hdr(msg);
967 struct ifinfomsg *ifi = NLMSG_DATA(nh);
968 struct if_check_data *chk = (struct if_check_data *)arg;
970 if (nh->nlmsg_type != RTM_NEWLINK)
973 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
974 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
979 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
981 struct if_check_data *chk = (struct if_check_data *)arg;
986 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
988 struct if_check_data *chk = (struct if_check_data *)arg;
990 device_set_present(chk->dev, false);
991 device_set_link(chk->dev, false);
992 chk->pending = err->error;
997 int system_if_check(struct device *dev)
999 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1001 struct ifinfomsg ifi = {
1002 .ifi_family = AF_UNSPEC,
1005 struct if_check_data chk = {
1011 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1012 if (!msg || nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1013 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1016 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1017 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1018 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1020 nl_send_auto_complete(sock_rtnl, msg);
1021 while (chk.pending > 0)
1022 nl_recvmsgs(sock_rtnl, cb);
1033 system_if_get_parent(struct device *dev)
1035 char buf[64], *devname;
1036 int ifindex, iflink, len;
1039 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1040 f = fopen(buf, "r");
1044 len = fread(buf, 1, sizeof(buf) - 1, f);
1051 iflink = strtoul(buf, NULL, 0);
1052 ifindex = system_if_resolve(dev);
1053 if (!iflink || iflink == ifindex)
1056 devname = if_indextoname(iflink, buf);
1060 return device_get(devname, true);
1064 read_string_file(int dir_fd, const char *file, char *buf, int len)
1070 fd = openat(dir_fd, file, O_RDONLY);
1075 len = read(fd, buf, len - 1);
1079 } else if (len > 0) {
1082 c = strchr(buf, '\n');
1095 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1100 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1102 *val = strtoull(buf, NULL, 0);
1107 /* Assume advertised flags == supported flags */
1108 static const struct {
1111 } ethtool_link_modes[] = {
1112 { ADVERTISED_10baseT_Half, "10H" },
1113 { ADVERTISED_10baseT_Full, "10F" },
1114 { ADVERTISED_100baseT_Half, "100H" },
1115 { ADVERTISED_100baseT_Full, "100F" },
1116 { ADVERTISED_1000baseT_Half, "1000H" },
1117 { ADVERTISED_1000baseT_Full, "1000F" },
1120 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1123 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1124 if (mask & ethtool_link_modes[i].mask)
1125 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1130 system_if_force_external(const char *ifname)
1135 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1136 return stat(buf, &s) == 0;
1140 system_if_dump_info(struct device *dev, struct blob_buf *b)
1142 struct ethtool_cmd ecmd;
1148 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
1149 dir_fd = open(buf, O_DIRECTORY);
1151 memset(&ecmd, 0, sizeof(ecmd));
1152 memset(&ifr, 0, sizeof(ifr));
1153 strcpy(ifr.ifr_name, dev->ifname);
1154 ifr.ifr_data = (caddr_t) &ecmd;
1155 ecmd.cmd = ETHTOOL_GSET;
1157 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1158 c = blobmsg_open_array(b, "link-advertising");
1159 system_add_link_modes(b, ecmd.advertising);
1160 blobmsg_close_array(b, c);
1162 c = blobmsg_open_array(b, "link-supported");
1163 system_add_link_modes(b, ecmd.supported);
1164 blobmsg_close_array(b, c);
1166 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1167 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1168 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1169 blobmsg_add_string_buffer(b);
1177 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1179 const char *const counters[] = {
1180 "collisions", "rx_frame_errors", "tx_compressed",
1181 "multicast", "rx_length_errors", "tx_dropped",
1182 "rx_bytes", "rx_missed_errors", "tx_errors",
1183 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1184 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1185 "rx_dropped", "tx_aborted_errors", "tx_packets",
1186 "rx_errors", "tx_bytes", "tx_window_errors",
1187 "rx_fifo_errors", "tx_carrier_errors",
1194 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1195 stats_dir = open(buf, O_DIRECTORY);
1199 for (i = 0; i < ARRAY_SIZE(counters); i++)
1200 if (read_uint64_file(stats_dir, counters[i], &val))
1201 blobmsg_add_u64(b, counters[i], val);
1207 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1209 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1210 int alen = v4 ? 4 : 16;
1211 unsigned int flags = 0;
1212 struct ifaddrmsg ifa = {
1213 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1214 .ifa_prefixlen = addr->mask,
1215 .ifa_index = dev->ifindex,
1219 if (cmd == RTM_NEWADDR)
1220 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1222 msg = nlmsg_alloc_simple(cmd, flags);
1226 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1227 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1229 if (addr->broadcast)
1230 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1231 if (addr->point_to_point)
1232 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1234 time_t now = system_get_rtime();
1235 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1237 if (addr->preferred_until) {
1238 int64_t preferred = addr->preferred_until - now;
1241 else if (preferred > UINT32_MAX)
1242 preferred = UINT32_MAX;
1244 cinfo.ifa_prefered = preferred;
1247 if (addr->valid_until) {
1248 int64_t valid = addr->valid_until - now;
1251 else if (valid > UINT32_MAX)
1254 cinfo.ifa_valid = valid;
1257 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1260 return system_rtnl_call(msg);
1263 int system_add_address(struct device *dev, struct device_addr *addr)
1265 return system_addr(dev, addr, RTM_NEWADDR);
1268 int system_del_address(struct device *dev, struct device_addr *addr)
1270 return system_addr(dev, addr, RTM_DELADDR);
1273 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1275 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1277 unsigned int flags = 0;
1280 have_gw = !!route->nexthop.in.s_addr;
1282 have_gw = route->nexthop.in6.s6_addr32[0] ||
1283 route->nexthop.in6.s6_addr32[1] ||
1284 route->nexthop.in6.s6_addr32[2] ||
1285 route->nexthop.in6.s6_addr32[3];
1287 unsigned char scope = (cmd == RTM_DELROUTE) ? RT_SCOPE_NOWHERE :
1288 (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1290 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1291 ? route->table : RT_TABLE_MAIN;
1293 struct rtmsg rtm = {
1294 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1295 .rtm_dst_len = route->mask,
1296 .rtm_src_len = route->sourcemask,
1297 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1298 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
1300 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1301 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1305 if (cmd == RTM_NEWROUTE) {
1306 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1308 if (!dev) { // Add null-route
1309 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1310 rtm.rtm_type = RTN_UNREACHABLE;
1314 msg = nlmsg_alloc_simple(cmd, flags);
1318 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1321 nla_put(msg, RTA_DST, alen, &route->addr);
1323 if (route->sourcemask)
1324 nla_put(msg, RTA_SRC, alen, &route->source);
1326 if (route->metric > 0)
1327 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1330 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1333 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1336 nla_put_u32(msg, RTA_TABLE, table);
1338 if (route->flags & DEVROUTE_MTU) {
1339 struct nlattr *metrics;
1341 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1342 goto nla_put_failure;
1344 nla_put_u32(msg, RTAX_MTU, route->mtu);
1346 nla_nest_end(msg, metrics);
1349 return system_rtnl_call(msg);
1356 int system_add_route(struct device *dev, struct device_route *route)
1358 return system_rt(dev, route, RTM_NEWROUTE);
1361 int system_del_route(struct device *dev, struct device_route *route)
1363 return system_rt(dev, route, RTM_DELROUTE);
1366 int system_flush_routes(void)
1368 const char *names[] = {
1369 "/proc/sys/net/ipv4/route/flush",
1370 "/proc/sys/net/ipv6/route/flush"
1374 for (i = 0; i < ARRAY_SIZE(names); i++) {
1375 fd = open(names[i], O_WRONLY);
1379 if (write(fd, "-1", 2)) {}
1385 bool system_resolve_rt_table(const char *name, unsigned int *id)
1389 unsigned int n, table = RT_TABLE_UNSPEC;
1391 /* first try to parse table as number */
1392 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1395 /* handle well known aliases */
1396 else if (!strcmp(name, "default"))
1397 table = RT_TABLE_DEFAULT;
1398 else if (!strcmp(name, "main"))
1399 table = RT_TABLE_MAIN;
1400 else if (!strcmp(name, "local"))
1401 table = RT_TABLE_LOCAL;
1403 /* try to look up name in /etc/iproute2/rt_tables */
1404 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1406 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1408 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1411 n = strtoul(e, NULL, 10);
1412 e = strtok(NULL, " \t\n");
1414 if (e && !strcmp(e, name))
1424 if (table == RT_TABLE_UNSPEC)
1427 /* do not consider main table special */
1428 if (table == RT_TABLE_MAIN)
1429 table = RT_TABLE_UNSPEC;
1435 static int system_iprule(struct iprule *rule, int cmd)
1437 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1440 struct rtmsg rtm = {
1441 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1442 .rtm_protocol = RTPROT_STATIC,
1443 .rtm_scope = RT_SCOPE_UNIVERSE,
1444 .rtm_table = RT_TABLE_UNSPEC,
1445 .rtm_type = RTN_UNSPEC,
1449 if (cmd == RTM_NEWRULE) {
1450 rtm.rtm_type = RTN_UNICAST;
1451 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1455 rtm.rtm_flags |= FIB_RULE_INVERT;
1457 if (rule->flags & IPRULE_SRC)
1458 rtm.rtm_src_len = rule->src_mask;
1460 if (rule->flags & IPRULE_DEST)
1461 rtm.rtm_dst_len = rule->dest_mask;
1463 if (rule->flags & IPRULE_TOS)
1464 rtm.rtm_tos = rule->tos;
1466 if (rule->flags & IPRULE_LOOKUP) {
1467 if (rule->lookup < 256)
1468 rtm.rtm_table = rule->lookup;
1471 if (rule->flags & IPRULE_ACTION)
1472 rtm.rtm_type = rule->action;
1473 else if (rule->flags & IPRULE_GOTO)
1474 rtm.rtm_type = FR_ACT_GOTO;
1475 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1476 rtm.rtm_type = FR_ACT_NOP;
1478 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1483 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1485 if (rule->flags & IPRULE_IN)
1486 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1488 if (rule->flags & IPRULE_OUT)
1489 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1491 if (rule->flags & IPRULE_SRC)
1492 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1494 if (rule->flags & IPRULE_DEST)
1495 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1497 if (rule->flags & IPRULE_PRIORITY)
1498 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1499 else if (cmd == RTM_NEWRULE)
1500 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1502 if (rule->flags & IPRULE_FWMARK)
1503 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1505 if (rule->flags & IPRULE_FWMASK)
1506 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1508 if (rule->flags & IPRULE_LOOKUP) {
1509 if (rule->lookup >= 256)
1510 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1513 if (rule->flags & IPRULE_GOTO)
1514 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1516 return system_rtnl_call(msg);
1519 int system_add_iprule(struct iprule *rule)
1521 return system_iprule(rule, RTM_NEWRULE);
1524 int system_del_iprule(struct iprule *rule)
1526 return system_iprule(rule, RTM_DELRULE);
1529 int system_flush_iprules(void)
1534 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1535 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1537 memset(&rule, 0, sizeof(rule));
1540 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1543 rule.lookup = RT_TABLE_LOCAL;
1544 rv |= system_iprule(&rule, RTM_NEWRULE);
1546 rule.priority = 32766;
1547 rule.lookup = RT_TABLE_MAIN;
1548 rv |= system_iprule(&rule, RTM_NEWRULE);
1550 rule.priority = 32767;
1551 rule.lookup = RT_TABLE_DEFAULT;
1552 rv |= system_iprule(&rule, RTM_NEWRULE);
1555 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1558 rule.lookup = RT_TABLE_LOCAL;
1559 rv |= system_iprule(&rule, RTM_NEWRULE);
1561 rule.priority = 32766;
1562 rule.lookup = RT_TABLE_MAIN;
1563 rv |= system_iprule(&rule, RTM_NEWRULE);
1568 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1573 if (!strcmp(action, "local"))
1575 else if (!strcmp(action, "nat"))
1577 else if (!strcmp(action, "broadcast"))
1579 else if (!strcmp(action, "anycast"))
1581 else if (!strcmp(action, "multicast"))
1583 else if (!strcmp(action, "prohibit"))
1585 else if (!strcmp(action, "unreachable"))
1586 n = RTN_UNREACHABLE;
1587 else if (!strcmp(action, "blackhole"))
1589 else if (!strcmp(action, "xresolve"))
1591 else if (!strcmp(action, "unicast"))
1593 else if (!strcmp(action, "throw"))
1595 else if (!strcmp(action, "failed_policy"))
1596 n = RTN_FAILED_POLICY;
1598 n = strtoul(action, &e, 0);
1599 if (!e || *e || e == action || n > 255)
1607 time_t system_get_rtime(void)
1612 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1615 if (gettimeofday(&tv, NULL) == 0)
1622 #define IP_DF 0x4000
1625 static int tunnel_ioctl(const char *name, int cmd, void *p)
1629 memset(&ifr, 0, sizeof(ifr));
1630 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1631 ifr.ifr_ifru.ifru_data = p;
1632 return ioctl(sock_ioctl, cmd, &ifr);
1635 int system_del_ip_tunnel(const char *name)
1637 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
1640 int system_update_ipv6_mtu(struct device *dev, int mtu)
1644 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
1647 int fd = open(buf, O_RDWR);
1648 ssize_t len = read(fd, buf, sizeof(buf) - 1);
1655 if (!mtu || ret <= mtu)
1658 lseek(fd, 0, SEEK_SET);
1659 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) <= 0)
1667 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
1669 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
1670 struct blob_attr *cur;
1674 system_del_ip_tunnel(name);
1676 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
1677 blob_data(attr), blob_len(attr));
1679 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
1681 str = blobmsg_data(cur);
1683 if ((cur = tb[TUNNEL_ATTR_DF]))
1684 set_df = blobmsg_get_bool(cur);
1686 unsigned int ttl = 0;
1687 if ((cur = tb[TUNNEL_ATTR_TTL])) {
1688 ttl = blobmsg_get_u32(cur);
1689 if (ttl > 255 || (!set_df && ttl))
1693 unsigned int link = 0;
1694 if ((cur = tb[TUNNEL_ATTR_LINK])) {
1695 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
1699 if (iface->l3_dev.dev)
1700 link = iface->l3_dev.dev->ifindex;
1703 if (!strcmp(str, "sit")) {
1704 struct ip_tunnel_parm p = {
1709 .frag_off = set_df ? htons(IP_DF) : 0,
1710 .protocol = IPPROTO_IPV6,
1715 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
1716 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
1719 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
1720 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
1723 strncpy(p.name, name, sizeof(p.name));
1724 if (tunnel_ioctl("sit0", SIOCADDTUNNEL, &p) < 0)
1728 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
1730 struct ip_tunnel_6rd p6;
1732 memset(&p6, 0, sizeof(p6));
1734 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
1735 &p6.prefix, &mask) || mask > 128)
1737 p6.prefixlen = mask;
1739 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
1740 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
1741 &p6.relay_prefix, &mask) || mask > 32)
1743 p6.relay_prefixlen = mask;
1746 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
1747 system_del_ip_tunnel(name);
1752 } else if (!strcmp(str, "ipip6")) {
1753 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
1754 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
1756 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
1757 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
1758 nla_put_string(nlm, IFLA_IFNAME, name);
1761 nla_put_u32(nlm, IFLA_LINK, link);
1763 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
1764 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
1765 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
1768 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
1770 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
1771 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
1772 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
1774 struct in6_addr in6buf;
1775 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1776 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1)
1778 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
1781 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
1782 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1)
1784 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
1787 #ifdef IFLA_IPTUN_FMR_MAX
1788 if ((cur = tb[TUNNEL_ATTR_FMRS])) {
1789 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
1791 struct blob_attr *fmr;
1792 unsigned rem, fmrcnt = 0;
1793 blobmsg_for_each_attr(fmr, cur, rem) {
1794 if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
1797 unsigned ip4len, ip6len, ealen, offset = 6;
1801 if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
1802 ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5)
1805 struct in6_addr ip6prefix;
1806 struct in_addr ip4prefix;
1807 if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
1808 inet_pton(AF_INET, ip4buf, &ip4prefix) != 1)
1811 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
1813 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
1814 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
1815 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
1816 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
1817 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
1818 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
1820 nla_nest_end(nlm, rule);
1823 nla_nest_end(nlm, fmrs);
1827 nla_nest_end(nlm, infodata);
1828 nla_nest_end(nlm, linkinfo);
1830 return system_rtnl_call(nlm);