2 * netifd - network interface daemon
3 * Copyright (C) 2012 Felix Fietkau <nbd@openwrt.org>
4 * Copyright (C) 2013 Jo-Philipp Wich <jow@openwrt.org>
5 * Copyright (C) 2013 Steven Barth <steven@midlink.org>
6 * Copyright (C) 2014 Gioacchino Mazzurco <gio@eigenlab.org>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2
10 * as published by the Free Software Foundation
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
19 #include <sys/socket.h>
20 #include <sys/ioctl.h>
22 #include <sys/syscall.h>
25 #include <net/if_arp.h>
27 #include <arpa/inet.h>
28 #include <netinet/in.h>
30 #include <linux/rtnetlink.h>
31 #include <linux/sockios.h>
33 #include <linux/if_link.h>
34 #include <linux/if_vlan.h>
35 #include <linux/if_bridge.h>
36 #include <linux/if_tunnel.h>
37 #include <linux/ip6_tunnel.h>
38 #include <linux/ethtool.h>
39 #include <linux/fib_rules.h>
40 #include <linux/version.h>
42 #ifndef RTN_FAILED_POLICY
43 #define RTN_FAILED_POLICY 12
51 #include <netlink/msg.h>
52 #include <netlink/attr.h>
53 #include <netlink/socket.h>
54 #include <libubox/uloop.h>
61 struct uloop_fd uloop;
66 static int sock_ioctl = -1;
67 static struct nl_sock *sock_rtnl = NULL;
69 static int cb_rtnl_event(struct nl_msg *msg, void *arg);
70 static void handle_hotplug_event(struct uloop_fd *u, unsigned int events);
72 static char dev_buf[256];
75 handler_nl_event(struct uloop_fd *u, unsigned int events)
77 struct event_socket *ev = container_of(u, struct event_socket, uloop);
79 socklen_t errlen = sizeof(err);
82 nl_recvmsgs_default(ev->sock);
86 if (getsockopt(u->fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen))
91 // Increase rx buffer size on netlink socket
93 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
96 // Request full dump since some info got dropped
97 struct rtgenmsg msg = { .rtgen_family = AF_UNSPEC };
98 nl_send_simple(ev->sock, RTM_GETLINK, NLM_F_DUMP, &msg, sizeof(msg));
108 uloop_fd_delete(&ev->uloop);
112 static struct nl_sock *
113 create_socket(int protocol, int groups)
115 struct nl_sock *sock;
117 sock = nl_socket_alloc();
122 nl_join_groups(sock, groups);
124 if (nl_connect(sock, protocol))
131 create_raw_event_socket(struct event_socket *ev, int protocol, int groups,
132 uloop_fd_handler cb, int flags)
134 ev->sock = create_socket(protocol, groups);
138 ev->uloop.fd = nl_socket_get_fd(ev->sock);
140 if (uloop_fd_add(&ev->uloop, ULOOP_READ|flags))
147 create_event_socket(struct event_socket *ev, int protocol,
148 int (*cb)(struct nl_msg *msg, void *arg))
150 if (!create_raw_event_socket(ev, protocol, 0, handler_nl_event, ULOOP_ERROR_CB))
153 // Install the valid custom callback handler
154 nl_socket_modify_cb(ev->sock, NL_CB_VALID, NL_CB_CUSTOM, cb, NULL);
156 // Disable sequence number checking on event sockets
157 nl_socket_disable_seq_check(ev->sock);
159 // Increase rx buffer size to 65K on event sockets
161 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
168 system_rtn_aton(const char *src, unsigned int *dst)
173 if (!strcmp(src, "local"))
175 else if (!strcmp(src, "nat"))
177 else if (!strcmp(src, "broadcast"))
179 else if (!strcmp(src, "anycast"))
181 else if (!strcmp(src, "multicast"))
183 else if (!strcmp(src, "prohibit"))
185 else if (!strcmp(src, "unreachable"))
187 else if (!strcmp(src, "blackhole"))
189 else if (!strcmp(src, "xresolve"))
191 else if (!strcmp(src, "unicast"))
193 else if (!strcmp(src, "throw"))
195 else if (!strcmp(src, "failed_policy"))
196 n = RTN_FAILED_POLICY;
198 n = strtoul(src, &e, 0);
199 if (!e || *e || e == src || n > 255)
207 int system_init(void)
209 static struct event_socket rtnl_event;
210 static struct event_socket hotplug_event;
212 sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0);
213 system_fd_set_cloexec(sock_ioctl);
215 // Prepare socket for routing / address control
216 sock_rtnl = create_socket(NETLINK_ROUTE, 0);
220 if (!create_event_socket(&rtnl_event, NETLINK_ROUTE, cb_rtnl_event))
223 if (!create_raw_event_socket(&hotplug_event, NETLINK_KOBJECT_UEVENT, 1,
224 handle_hotplug_event, 0))
227 // Receive network link events form kernel
228 nl_socket_add_membership(rtnl_event.sock, RTNLGRP_LINK);
233 static void system_set_sysctl(const char *path, const char *val)
237 fd = open(path, O_WRONLY);
241 if (write(fd, val, strlen(val))) {}
245 static void system_set_dev_sysctl(const char *path, const char *device, const char *val)
247 snprintf(dev_buf, sizeof(dev_buf), path, device);
248 system_set_sysctl(dev_buf, val);
251 static void system_set_disable_ipv6(struct device *dev, const char *val)
253 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val);
256 static int system_get_sysctl(const char *path, char *buf, const size_t buf_sz)
258 int fd = -1, ret = -1;
260 fd = open(path, O_RDONLY);
264 ssize_t len = read(fd, buf, buf_sz - 1);
278 system_get_dev_sysctl(const char *path, const char *device, char *buf, const size_t buf_sz)
280 snprintf(dev_buf, sizeof(dev_buf), path, device);
281 return system_get_sysctl(dev_buf, buf, buf_sz);
284 static int system_get_disable_ipv6(struct device *dev, char *buf, const size_t buf_sz)
286 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6",
287 dev->ifname, buf, buf_sz);
291 #define IFF_LOWER_UP 0x10000
294 // Evaluate netlink messages
295 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
297 struct nlmsghdr *nh = nlmsg_hdr(msg);
298 struct ifinfomsg *ifi = NLMSG_DATA(nh);
299 struct nlattr *nla[__IFLA_MAX];
301 if (nh->nlmsg_type != RTM_NEWLINK)
304 nlmsg_parse(nh, sizeof(*ifi), nla, __IFLA_MAX - 1, NULL);
305 if (!nla[IFLA_IFNAME])
308 struct device *dev = device_get(nla_data(nla[IFLA_IFNAME]), false);
312 device_set_ifindex(dev, ifi->ifi_index);
313 device_set_link(dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
320 handle_hotplug_msg(char *data, int size)
322 const char *subsystem = NULL, *interface = NULL;
323 char *cur, *end, *sep;
328 if (!strncmp(data, "add@", 4))
330 else if (!strncmp(data, "remove@", 7))
335 skip = strlen(data) + 1;
338 for (cur = data + skip; cur < end; cur += skip) {
339 skip = strlen(cur) + 1;
341 sep = strchr(cur, '=');
346 if (!strcmp(cur, "INTERFACE"))
348 else if (!strcmp(cur, "SUBSYSTEM")) {
350 if (strcmp(subsystem, "net") != 0)
353 if (subsystem && interface)
359 dev = device_get(interface, false);
363 if (dev->type != &simple_device_type)
366 if (add && system_if_force_external(dev->ifname))
369 device_set_present(dev, add);
373 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
375 struct event_socket *ev = container_of(u, struct event_socket, uloop);
376 struct sockaddr_nl nla;
377 unsigned char *buf = NULL;
380 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
382 handle_hotplug_msg((char *) buf, size);
388 static int system_rtnl_call(struct nl_msg *msg)
392 ret = nl_send_auto_complete(sock_rtnl, msg);
398 return nl_wait_for_ack(sock_rtnl);
401 int system_bridge_delbr(struct device *bridge)
403 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
406 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
410 memset(&ifr, 0, sizeof(ifr));
412 ifr.ifr_ifindex = dev->ifindex;
415 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
416 return ioctl(sock_ioctl, cmd, &ifr);
419 static bool system_is_bridge(const char *name, char *buf, int buflen)
423 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
424 if (stat(buf, &st) < 0)
430 static char *system_get_bridge(const char *name, char *buf, int buflen)
436 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
437 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
440 if (gl.gl_pathc == 0)
443 len = readlink(gl.gl_pathv[0], buf, buflen);
448 path = strrchr(buf, '/');
455 static void system_bridge_set_wireless(const char *bridge, const char *dev)
457 snprintf(dev_buf, sizeof(dev_buf),
458 "/sys/devices/virtual/net/%s/brif/%s/multicast_to_unicast",
460 system_set_sysctl(dev_buf, "1");
463 int system_bridge_addif(struct device *bridge, struct device *dev)
468 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
469 if (!oldbr || strcmp(oldbr, bridge->ifname) != 0)
470 ret = system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
473 system_bridge_set_wireless(bridge->ifname, dev->ifname);
478 int system_bridge_delif(struct device *bridge, struct device *dev)
480 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
483 static int system_if_resolve(struct device *dev)
486 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
487 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
488 return ifr.ifr_ifindex;
493 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
497 memset(&ifr, 0, sizeof(ifr));
498 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
499 ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
500 ifr.ifr_flags |= add;
501 ifr.ifr_flags &= ~rem;
502 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
514 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
516 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
518 return ifa->ifa_index == ifindex;
521 static bool check_route(struct nlmsghdr *hdr, int ifindex)
523 struct rtmsg *r = NLMSG_DATA(hdr);
524 struct nlattr *tb[__RTA_MAX];
526 if (r->rtm_protocol == RTPROT_KERNEL &&
527 r->rtm_family == AF_INET6)
530 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
534 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
537 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
542 static int cb_clear_event(struct nl_msg *msg, void *arg)
544 struct clear_data *clr = arg;
545 struct nlmsghdr *hdr = nlmsg_hdr(msg);
546 bool (*cb)(struct nlmsghdr *, int ifindex);
552 if (hdr->nlmsg_type != RTM_NEWADDR)
559 if (hdr->nlmsg_type != RTM_NEWROUTE)
566 if (hdr->nlmsg_type != RTM_NEWRULE)
575 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
578 if (type == RTM_DELRULE)
579 D(SYSTEM, "Remove a rule\n");
581 D(SYSTEM, "Remove %s from device %s\n",
582 type == RTM_DELADDR ? "an address" : "a route",
584 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
585 hdr = nlmsg_hdr(clr->msg);
586 hdr->nlmsg_type = type;
587 hdr->nlmsg_flags = NLM_F_REQUEST;
589 nl_socket_disable_auto_ack(sock_rtnl);
590 nl_send_auto_complete(sock_rtnl, clr->msg);
591 nl_socket_enable_auto_ack(sock_rtnl);
597 cb_finish_event(struct nl_msg *msg, void *arg)
605 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
608 *pending = err->error;
613 system_if_clear_entries(struct device *dev, int type, int af)
615 struct clear_data clr;
616 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
619 .rtm_flags = RTM_F_CLONED,
621 int flags = NLM_F_DUMP;
630 clr.size = sizeof(struct rtgenmsg);
633 clr.size = sizeof(struct rtmsg);
642 clr.msg = nlmsg_alloc_simple(type, flags);
646 nlmsg_append(clr.msg, &rtm, clr.size, 0);
647 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
648 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
649 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
651 nl_send_auto_complete(sock_rtnl, clr.msg);
653 nl_recvmsgs(sock_rtnl, cb);
661 * Clear bridge (membership) state and bring down device
663 void system_if_clear_state(struct device *dev)
665 static char buf[256];
668 device_set_ifindex(dev, system_if_resolve(dev));
669 if (dev->external || !dev->ifindex)
672 system_if_flags(dev->ifname, 0, IFF_UP);
674 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
675 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
676 system_bridge_delbr(dev);
680 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
682 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
683 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
686 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
687 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
688 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
689 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
690 system_set_disable_ipv6(dev, "0");
693 static inline unsigned long
694 sec_to_jiffies(int val)
696 return (unsigned long) val * 100;
699 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
701 unsigned long args[4] = {};
703 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
706 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
707 args[1] = !!cfg->stp;
708 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
710 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
711 args[1] = sec_to_jiffies(cfg->forward_delay);
712 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
714 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
715 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
717 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier",
718 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
720 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
721 args[1] = cfg->priority;
722 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
724 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
725 args[0] = BRCTL_SET_AGEING_TIME;
726 args[1] = sec_to_jiffies(cfg->ageing_time);
727 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
730 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
731 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
732 args[1] = sec_to_jiffies(cfg->hello_time);
733 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
736 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
737 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
738 args[1] = sec_to_jiffies(cfg->max_age);
739 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
745 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
748 struct nlattr *linkinfo, *data;
749 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
750 int ifindex = system_if_resolve(dev);
752 static const struct {
754 enum macvlan_mode val;
756 { "private", MACVLAN_MODE_PRIVATE },
757 { "vepa", MACVLAN_MODE_VEPA },
758 { "bridge", MACVLAN_MODE_BRIDGE },
759 { "passthru", MACVLAN_MODE_PASSTHRU },
765 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
770 nlmsg_append(msg, &iim, sizeof(iim), 0);
772 if (cfg->flags & MACVLAN_OPT_MACADDR)
773 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
774 nla_put_string(msg, IFLA_IFNAME, macvlan->ifname);
775 nla_put_u32(msg, IFLA_LINK, ifindex);
777 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
778 goto nla_put_failure;
780 nla_put_string(msg, IFLA_INFO_KIND, "macvlan");
782 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
783 goto nla_put_failure;
786 for (i = 0; i < ARRAY_SIZE(modes); i++) {
787 if (strcmp(cfg->mode, modes[i].name) != 0)
790 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
795 nla_nest_end(msg, data);
796 nla_nest_end(msg, linkinfo);
798 rv = system_rtnl_call(msg);
800 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
809 static int system_link_del(struct device *dev)
812 struct ifinfomsg iim = {
813 .ifi_family = AF_UNSPEC,
817 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
822 nlmsg_append(msg, &iim, sizeof(iim), 0);
823 nla_put_string(msg, IFLA_IFNAME, dev->ifname);
824 return system_rtnl_call(msg);
827 int system_macvlan_del(struct device *macvlan)
829 return system_link_del(macvlan);
832 static int system_vlan(struct device *dev, int id)
834 struct vlan_ioctl_args ifr = {
835 .cmd = SET_VLAN_NAME_TYPE_CMD,
836 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
839 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
842 ifr.cmd = DEL_VLAN_CMD;
845 ifr.cmd = ADD_VLAN_CMD;
848 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
849 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
852 int system_vlan_add(struct device *dev, int id)
854 return system_vlan(dev, id);
857 int system_vlan_del(struct device *dev)
859 return system_vlan(dev, -1);
862 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
865 struct nlattr *linkinfo, *data;
866 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
867 int ifindex = system_if_resolve(dev);
873 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
878 nlmsg_append(msg, &iim, sizeof(iim), 0);
879 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
880 nla_put_u32(msg, IFLA_LINK, ifindex);
882 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
883 goto nla_put_failure;
885 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
887 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
888 goto nla_put_failure;
890 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
892 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
893 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
895 if(cfg->proto == VLAN_PROTO_8021AD)
896 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);
899 nla_nest_end(msg, data);
900 nla_nest_end(msg, linkinfo);
902 rv = system_rtnl_call(msg);
904 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
913 int system_vlandev_del(struct device *vlandev)
915 return system_link_del(vlandev);
919 system_if_get_settings(struct device *dev, struct device_settings *s)
924 memset(&ifr, 0, sizeof(ifr));
925 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
927 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
928 s->mtu = ifr.ifr_mtu;
929 s->flags |= DEV_OPT_MTU;
932 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
933 s->txqueuelen = ifr.ifr_qlen;
934 s->flags |= DEV_OPT_TXQUEUELEN;
937 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
938 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
939 s->flags |= DEV_OPT_MACADDR;
942 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
943 s->ipv6 = !strtoul(buf, NULL, 0);
944 s->flags |= DEV_OPT_IPV6;
949 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
956 memset(&ifr, 0, sizeof(ifr));
957 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
958 if (s->flags & DEV_OPT_MTU & apply_mask) {
959 ifr.ifr_mtu = s->mtu;
960 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
961 s->flags &= ~DEV_OPT_MTU;
963 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
964 ifr.ifr_qlen = s->txqueuelen;
965 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
966 s->flags &= ~DEV_OPT_TXQUEUELEN;
968 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
969 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
970 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
971 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
972 s->flags &= ~DEV_OPT_MACADDR;
974 if (s->flags & DEV_OPT_IPV6 & apply_mask)
975 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
978 int system_if_up(struct device *dev)
980 system_if_get_settings(dev, &dev->orig_settings);
981 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
982 device_set_ifindex(dev, system_if_resolve(dev));
983 return system_if_flags(dev->ifname, IFF_UP, 0);
986 int system_if_down(struct device *dev)
988 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
989 dev->orig_settings.flags &= dev->settings.flags;
990 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
994 struct if_check_data {
1000 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1002 struct nlmsghdr *nh = nlmsg_hdr(msg);
1003 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1004 struct if_check_data *chk = (struct if_check_data *)arg;
1006 if (nh->nlmsg_type != RTM_NEWLINK)
1009 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1010 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1015 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1017 struct if_check_data *chk = (struct if_check_data *)arg;
1022 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1024 struct if_check_data *chk = (struct if_check_data *)arg;
1026 device_set_present(chk->dev, false);
1027 device_set_link(chk->dev, false);
1028 chk->pending = err->error;
1033 int system_if_check(struct device *dev)
1035 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1037 struct ifinfomsg ifi = {
1038 .ifi_family = AF_UNSPEC,
1041 struct if_check_data chk = {
1047 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1048 if (!msg || nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1049 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1052 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1053 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1054 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1056 nl_send_auto_complete(sock_rtnl, msg);
1057 while (chk.pending > 0)
1058 nl_recvmsgs(sock_rtnl, cb);
1069 system_if_get_parent(struct device *dev)
1071 char buf[64], *devname;
1072 int ifindex, iflink, len;
1075 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1076 f = fopen(buf, "r");
1080 len = fread(buf, 1, sizeof(buf) - 1, f);
1087 iflink = strtoul(buf, NULL, 0);
1088 ifindex = system_if_resolve(dev);
1089 if (!iflink || iflink == ifindex)
1092 devname = if_indextoname(iflink, buf);
1096 return device_get(devname, true);
1100 read_string_file(int dir_fd, const char *file, char *buf, int len)
1106 fd = openat(dir_fd, file, O_RDONLY);
1111 len = read(fd, buf, len - 1);
1115 } else if (len > 0) {
1118 c = strchr(buf, '\n');
1131 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1136 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1138 *val = strtoull(buf, NULL, 0);
1143 /* Assume advertised flags == supported flags */
1144 static const struct {
1147 } ethtool_link_modes[] = {
1148 { ADVERTISED_10baseT_Half, "10H" },
1149 { ADVERTISED_10baseT_Full, "10F" },
1150 { ADVERTISED_100baseT_Half, "100H" },
1151 { ADVERTISED_100baseT_Full, "100F" },
1152 { ADVERTISED_1000baseT_Half, "1000H" },
1153 { ADVERTISED_1000baseT_Full, "1000F" },
1156 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1159 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1160 if (mask & ethtool_link_modes[i].mask)
1161 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1166 system_if_force_external(const char *ifname)
1171 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1172 return stat(buf, &s) == 0;
1176 system_if_dump_info(struct device *dev, struct blob_buf *b)
1178 struct ethtool_cmd ecmd;
1184 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
1185 dir_fd = open(buf, O_DIRECTORY);
1187 memset(&ecmd, 0, sizeof(ecmd));
1188 memset(&ifr, 0, sizeof(ifr));
1189 strcpy(ifr.ifr_name, dev->ifname);
1190 ifr.ifr_data = (caddr_t) &ecmd;
1191 ecmd.cmd = ETHTOOL_GSET;
1193 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1194 c = blobmsg_open_array(b, "link-advertising");
1195 system_add_link_modes(b, ecmd.advertising);
1196 blobmsg_close_array(b, c);
1198 c = blobmsg_open_array(b, "link-supported");
1199 system_add_link_modes(b, ecmd.supported);
1200 blobmsg_close_array(b, c);
1202 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1203 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1204 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1205 blobmsg_add_string_buffer(b);
1213 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1215 const char *const counters[] = {
1216 "collisions", "rx_frame_errors", "tx_compressed",
1217 "multicast", "rx_length_errors", "tx_dropped",
1218 "rx_bytes", "rx_missed_errors", "tx_errors",
1219 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1220 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1221 "rx_dropped", "tx_aborted_errors", "tx_packets",
1222 "rx_errors", "tx_bytes", "tx_window_errors",
1223 "rx_fifo_errors", "tx_carrier_errors",
1230 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1231 stats_dir = open(buf, O_DIRECTORY);
1235 for (i = 0; i < ARRAY_SIZE(counters); i++)
1236 if (read_uint64_file(stats_dir, counters[i], &val))
1237 blobmsg_add_u64(b, counters[i], val);
1243 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1245 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1246 int alen = v4 ? 4 : 16;
1247 unsigned int flags = 0;
1248 struct ifaddrmsg ifa = {
1249 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1250 .ifa_prefixlen = addr->mask,
1251 .ifa_index = dev->ifindex,
1255 if (cmd == RTM_NEWADDR)
1256 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1258 msg = nlmsg_alloc_simple(cmd, flags);
1262 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1263 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1265 if (addr->broadcast)
1266 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1267 if (addr->point_to_point)
1268 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1270 time_t now = system_get_rtime();
1271 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1273 if (addr->preferred_until) {
1274 int64_t preferred = addr->preferred_until - now;
1277 else if (preferred > UINT32_MAX)
1278 preferred = UINT32_MAX;
1280 cinfo.ifa_prefered = preferred;
1283 if (addr->valid_until) {
1284 int64_t valid = addr->valid_until - now;
1287 else if (valid > UINT32_MAX)
1290 cinfo.ifa_valid = valid;
1293 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1296 return system_rtnl_call(msg);
1299 int system_add_address(struct device *dev, struct device_addr *addr)
1301 return system_addr(dev, addr, RTM_NEWADDR);
1304 int system_del_address(struct device *dev, struct device_addr *addr)
1306 return system_addr(dev, addr, RTM_DELADDR);
1309 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1311 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1313 unsigned int flags = 0;
1316 have_gw = !!route->nexthop.in.s_addr;
1318 have_gw = route->nexthop.in6.s6_addr32[0] ||
1319 route->nexthop.in6.s6_addr32[1] ||
1320 route->nexthop.in6.s6_addr32[2] ||
1321 route->nexthop.in6.s6_addr32[3];
1323 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1324 ? route->table : RT_TABLE_MAIN;
1326 struct rtmsg rtm = {
1327 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1328 .rtm_dst_len = route->mask,
1329 .rtm_src_len = route->sourcemask,
1330 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1331 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
1332 .rtm_scope = RT_SCOPE_NOWHERE,
1333 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1334 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1338 if (cmd == RTM_NEWROUTE) {
1339 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1341 if (!dev) { // Add null-route
1342 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1343 rtm.rtm_type = RTN_UNREACHABLE;
1346 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1349 if (route->flags & DEVROUTE_TYPE) {
1350 rtm.rtm_type = route->type;
1351 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
1352 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
1353 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
1354 rtm.rtm_table = RT_TABLE_LOCAL;
1357 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT)
1358 rtm.rtm_scope = RT_SCOPE_HOST;
1359 else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
1360 rtm.rtm_type == RTN_ANYCAST)
1361 rtm.rtm_scope = RT_SCOPE_LINK;
1364 msg = nlmsg_alloc_simple(cmd, flags);
1368 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1371 nla_put(msg, RTA_DST, alen, &route->addr);
1373 if (route->sourcemask)
1374 nla_put(msg, RTA_SRC, alen, &route->source);
1376 if (route->metric > 0)
1377 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1380 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1383 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1386 nla_put_u32(msg, RTA_TABLE, table);
1388 if (route->flags & DEVROUTE_MTU) {
1389 struct nlattr *metrics;
1391 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1392 goto nla_put_failure;
1394 nla_put_u32(msg, RTAX_MTU, route->mtu);
1396 nla_nest_end(msg, metrics);
1399 return system_rtnl_call(msg);
1406 int system_add_route(struct device *dev, struct device_route *route)
1408 return system_rt(dev, route, RTM_NEWROUTE);
1411 int system_del_route(struct device *dev, struct device_route *route)
1413 return system_rt(dev, route, RTM_DELROUTE);
1416 int system_flush_routes(void)
1418 const char *names[] = {
1419 "/proc/sys/net/ipv4/route/flush",
1420 "/proc/sys/net/ipv6/route/flush"
1424 for (i = 0; i < ARRAY_SIZE(names); i++) {
1425 fd = open(names[i], O_WRONLY);
1429 if (write(fd, "-1", 2)) {}
1435 bool system_resolve_rt_type(const char *type, unsigned int *id)
1437 return system_rtn_aton(type, id);
1440 bool system_resolve_rt_table(const char *name, unsigned int *id)
1444 unsigned int n, table = RT_TABLE_UNSPEC;
1446 /* first try to parse table as number */
1447 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1450 /* handle well known aliases */
1451 else if (!strcmp(name, "default"))
1452 table = RT_TABLE_DEFAULT;
1453 else if (!strcmp(name, "main"))
1454 table = RT_TABLE_MAIN;
1455 else if (!strcmp(name, "local"))
1456 table = RT_TABLE_LOCAL;
1458 /* try to look up name in /etc/iproute2/rt_tables */
1459 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1461 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1463 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1466 n = strtoul(e, NULL, 10);
1467 e = strtok(NULL, " \t\n");
1469 if (e && !strcmp(e, name))
1479 if (table == RT_TABLE_UNSPEC)
1486 bool system_is_default_rt_table(unsigned int id)
1488 return (id == RT_TABLE_MAIN);
1491 static int system_iprule(struct iprule *rule, int cmd)
1493 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1496 struct rtmsg rtm = {
1497 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1498 .rtm_protocol = RTPROT_STATIC,
1499 .rtm_scope = RT_SCOPE_UNIVERSE,
1500 .rtm_table = RT_TABLE_UNSPEC,
1501 .rtm_type = RTN_UNSPEC,
1505 if (cmd == RTM_NEWRULE) {
1506 rtm.rtm_type = RTN_UNICAST;
1507 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1511 rtm.rtm_flags |= FIB_RULE_INVERT;
1513 if (rule->flags & IPRULE_SRC)
1514 rtm.rtm_src_len = rule->src_mask;
1516 if (rule->flags & IPRULE_DEST)
1517 rtm.rtm_dst_len = rule->dest_mask;
1519 if (rule->flags & IPRULE_TOS)
1520 rtm.rtm_tos = rule->tos;
1522 if (rule->flags & IPRULE_LOOKUP) {
1523 if (rule->lookup < 256)
1524 rtm.rtm_table = rule->lookup;
1527 if (rule->flags & IPRULE_ACTION)
1528 rtm.rtm_type = rule->action;
1529 else if (rule->flags & IPRULE_GOTO)
1530 rtm.rtm_type = FR_ACT_GOTO;
1531 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1532 rtm.rtm_type = FR_ACT_NOP;
1534 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1539 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1541 if (rule->flags & IPRULE_IN)
1542 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1544 if (rule->flags & IPRULE_OUT)
1545 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1547 if (rule->flags & IPRULE_SRC)
1548 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1550 if (rule->flags & IPRULE_DEST)
1551 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1553 if (rule->flags & IPRULE_PRIORITY)
1554 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1555 else if (cmd == RTM_NEWRULE)
1556 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1558 if (rule->flags & IPRULE_FWMARK)
1559 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1561 if (rule->flags & IPRULE_FWMASK)
1562 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1564 if (rule->flags & IPRULE_LOOKUP) {
1565 if (rule->lookup >= 256)
1566 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1569 if (rule->flags & IPRULE_GOTO)
1570 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1572 return system_rtnl_call(msg);
1575 int system_add_iprule(struct iprule *rule)
1577 return system_iprule(rule, RTM_NEWRULE);
1580 int system_del_iprule(struct iprule *rule)
1582 return system_iprule(rule, RTM_DELRULE);
1585 int system_flush_iprules(void)
1590 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1591 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1593 memset(&rule, 0, sizeof(rule));
1596 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1599 rule.lookup = RT_TABLE_LOCAL;
1600 rv |= system_iprule(&rule, RTM_NEWRULE);
1602 rule.priority = 32766;
1603 rule.lookup = RT_TABLE_MAIN;
1604 rv |= system_iprule(&rule, RTM_NEWRULE);
1606 rule.priority = 32767;
1607 rule.lookup = RT_TABLE_DEFAULT;
1608 rv |= system_iprule(&rule, RTM_NEWRULE);
1611 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1614 rule.lookup = RT_TABLE_LOCAL;
1615 rv |= system_iprule(&rule, RTM_NEWRULE);
1617 rule.priority = 32766;
1618 rule.lookup = RT_TABLE_MAIN;
1619 rv |= system_iprule(&rule, RTM_NEWRULE);
1624 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1626 return system_rtn_aton(action, id);
1629 time_t system_get_rtime(void)
1634 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1637 if (gettimeofday(&tv, NULL) == 0)
1644 #define IP_DF 0x4000
1647 static int tunnel_ioctl(const char *name, int cmd, void *p)
1651 memset(&ifr, 0, sizeof(ifr));
1652 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1653 ifr.ifr_ifru.ifru_data = p;
1654 return ioctl(sock_ioctl, cmd, &ifr);
1657 int system_del_ip_tunnel(const char *name)
1659 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
1662 int system_update_ipv6_mtu(struct device *dev, int mtu)
1666 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
1669 int fd = open(buf, O_RDWR);
1670 ssize_t len = read(fd, buf, sizeof(buf) - 1);
1677 if (!mtu || ret <= mtu)
1680 lseek(fd, 0, SEEK_SET);
1681 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) <= 0)
1689 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
1691 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
1692 struct blob_attr *cur;
1696 system_del_ip_tunnel(name);
1698 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
1699 blob_data(attr), blob_len(attr));
1701 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
1703 str = blobmsg_data(cur);
1705 if ((cur = tb[TUNNEL_ATTR_DF]))
1706 set_df = blobmsg_get_bool(cur);
1708 unsigned int ttl = 0;
1709 if ((cur = tb[TUNNEL_ATTR_TTL])) {
1710 ttl = blobmsg_get_u32(cur);
1711 if (ttl > 255 || (!set_df && ttl))
1715 unsigned int link = 0;
1716 if ((cur = tb[TUNNEL_ATTR_LINK])) {
1717 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
1721 if (iface->l3_dev.dev)
1722 link = iface->l3_dev.dev->ifindex;
1725 if (!strcmp(str, "sit")) {
1726 struct ip_tunnel_parm p = {
1731 .frag_off = set_df ? htons(IP_DF) : 0,
1732 .protocol = IPPROTO_IPV6,
1737 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
1738 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
1741 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
1742 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
1745 strncpy(p.name, name, sizeof(p.name));
1746 if (tunnel_ioctl("sit0", SIOCADDTUNNEL, &p) < 0)
1750 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
1752 struct ip_tunnel_6rd p6;
1754 memset(&p6, 0, sizeof(p6));
1756 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
1757 &p6.prefix, &mask) || mask > 128)
1759 p6.prefixlen = mask;
1761 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
1762 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
1763 &p6.relay_prefix, &mask) || mask > 32)
1765 p6.relay_prefixlen = mask;
1768 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
1769 system_del_ip_tunnel(name);
1774 } else if (!strcmp(str, "ipip6")) {
1775 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
1776 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
1777 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
1783 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
1784 nla_put_string(nlm, IFLA_IFNAME, name);
1787 nla_put_u32(nlm, IFLA_LINK, link);
1789 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
1794 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
1795 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
1802 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
1804 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
1805 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
1806 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
1808 struct in6_addr in6buf;
1809 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1810 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1814 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
1817 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
1818 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1822 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
1825 #ifdef IFLA_IPTUN_FMR_MAX
1826 if ((cur = tb[TUNNEL_ATTR_FMRS])) {
1827 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
1829 struct blob_attr *fmr;
1830 unsigned rem, fmrcnt = 0;
1831 blobmsg_for_each_attr(fmr, cur, rem) {
1832 if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
1835 unsigned ip4len, ip6len, ealen, offset = 6;
1839 if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
1840 ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) {
1845 struct in6_addr ip6prefix;
1846 struct in_addr ip4prefix;
1847 if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
1848 inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) {
1853 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
1855 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
1856 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
1857 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
1858 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
1859 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
1860 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
1862 nla_nest_end(nlm, rule);
1865 nla_nest_end(nlm, fmrs);
1869 nla_nest_end(nlm, infodata);
1870 nla_nest_end(nlm, linkinfo);
1872 return system_rtnl_call(nlm);