2 * netifd - network interface daemon
3 * Copyright (C) 2012 Felix Fietkau <nbd@openwrt.org>
4 * Copyright (C) 2013 Jo-Philipp Wich <jow@openwrt.org>
5 * Copyright (C) 2013 Steven Barth <steven@midlink.org>
6 * Copyright (C) 2014 Gioacchino Mazzurco <gio@eigenlab.org>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2
10 * as published by the Free Software Foundation
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
19 #include <sys/socket.h>
20 #include <sys/ioctl.h>
22 #include <sys/syscall.h>
25 #include <net/if_arp.h>
27 #include <arpa/inet.h>
28 #include <netinet/in.h>
30 #include <linux/rtnetlink.h>
31 #include <linux/sockios.h>
33 #include <linux/if_link.h>
34 #include <linux/if_vlan.h>
35 #include <linux/if_bridge.h>
36 #include <linux/if_tunnel.h>
37 #include <linux/ip6_tunnel.h>
38 #include <linux/ethtool.h>
39 #include <linux/fib_rules.h>
40 #include <linux/version.h>
42 #ifndef RTN_FAILED_POLICY
43 #define RTN_FAILED_POLICY 12
51 #include <netlink/msg.h>
52 #include <netlink/attr.h>
53 #include <netlink/socket.h>
54 #include <libubox/uloop.h>
61 struct uloop_fd uloop;
66 static int sock_ioctl = -1;
67 static struct nl_sock *sock_rtnl = NULL;
69 static int cb_rtnl_event(struct nl_msg *msg, void *arg);
70 static void handle_hotplug_event(struct uloop_fd *u, unsigned int events);
72 static char dev_buf[256];
75 handler_nl_event(struct uloop_fd *u, unsigned int events)
77 struct event_socket *ev = container_of(u, struct event_socket, uloop);
79 socklen_t errlen = sizeof(err);
82 nl_recvmsgs_default(ev->sock);
86 if (getsockopt(u->fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen))
91 // Increase rx buffer size on netlink socket
93 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
96 // Request full dump since some info got dropped
97 struct rtgenmsg msg = { .rtgen_family = AF_UNSPEC };
98 nl_send_simple(ev->sock, RTM_GETLINK, NLM_F_DUMP, &msg, sizeof(msg));
108 uloop_fd_delete(&ev->uloop);
112 static struct nl_sock *
113 create_socket(int protocol, int groups)
115 struct nl_sock *sock;
117 sock = nl_socket_alloc();
122 nl_join_groups(sock, groups);
124 if (nl_connect(sock, protocol))
131 create_raw_event_socket(struct event_socket *ev, int protocol, int groups,
132 uloop_fd_handler cb, int flags)
134 ev->sock = create_socket(protocol, groups);
138 ev->uloop.fd = nl_socket_get_fd(ev->sock);
140 if (uloop_fd_add(&ev->uloop, ULOOP_READ|flags))
147 create_event_socket(struct event_socket *ev, int protocol,
148 int (*cb)(struct nl_msg *msg, void *arg))
150 if (!create_raw_event_socket(ev, protocol, 0, handler_nl_event, ULOOP_ERROR_CB))
153 // Install the valid custom callback handler
154 nl_socket_modify_cb(ev->sock, NL_CB_VALID, NL_CB_CUSTOM, cb, NULL);
156 // Disable sequence number checking on event sockets
157 nl_socket_disable_seq_check(ev->sock);
159 // Increase rx buffer size to 65K on event sockets
161 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
168 system_rtn_aton(const char *src, unsigned int *dst)
173 if (!strcmp(src, "local"))
175 else if (!strcmp(src, "nat"))
177 else if (!strcmp(src, "broadcast"))
179 else if (!strcmp(src, "anycast"))
181 else if (!strcmp(src, "multicast"))
183 else if (!strcmp(src, "prohibit"))
185 else if (!strcmp(src, "unreachable"))
187 else if (!strcmp(src, "blackhole"))
189 else if (!strcmp(src, "xresolve"))
191 else if (!strcmp(src, "unicast"))
193 else if (!strcmp(src, "throw"))
195 else if (!strcmp(src, "failed_policy"))
196 n = RTN_FAILED_POLICY;
198 n = strtoul(src, &e, 0);
199 if (!e || *e || e == src || n > 255)
207 int system_init(void)
209 static struct event_socket rtnl_event;
210 static struct event_socket hotplug_event;
212 sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0);
213 system_fd_set_cloexec(sock_ioctl);
215 // Prepare socket for routing / address control
216 sock_rtnl = create_socket(NETLINK_ROUTE, 0);
220 if (!create_event_socket(&rtnl_event, NETLINK_ROUTE, cb_rtnl_event))
223 if (!create_raw_event_socket(&hotplug_event, NETLINK_KOBJECT_UEVENT, 1,
224 handle_hotplug_event, 0))
227 // Receive network link events form kernel
228 nl_socket_add_membership(rtnl_event.sock, RTNLGRP_LINK);
233 static void system_set_sysctl(const char *path, const char *val)
237 fd = open(path, O_WRONLY);
241 if (write(fd, val, strlen(val))) {}
245 static void system_set_dev_sysctl(const char *path, const char *device, const char *val)
247 snprintf(dev_buf, sizeof(dev_buf), path, device);
248 system_set_sysctl(dev_buf, val);
251 static void system_set_disable_ipv6(struct device *dev, const char *val)
253 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val);
256 static int system_get_sysctl(const char *path, char *buf, const size_t buf_sz)
258 int fd = -1, ret = -1;
260 fd = open(path, O_RDONLY);
264 ssize_t len = read(fd, buf, buf_sz - 1);
278 system_get_dev_sysctl(const char *path, const char *device, char *buf, const size_t buf_sz)
280 snprintf(dev_buf, sizeof(dev_buf), path, device);
281 return system_get_sysctl(dev_buf, buf, buf_sz);
284 static int system_get_disable_ipv6(struct device *dev, char *buf, const size_t buf_sz)
286 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6",
287 dev->ifname, buf, buf_sz);
291 #define IFF_LOWER_UP 0x10000
294 // Evaluate netlink messages
295 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
297 struct nlmsghdr *nh = nlmsg_hdr(msg);
298 struct ifinfomsg *ifi = NLMSG_DATA(nh);
299 struct nlattr *nla[__IFLA_MAX];
301 if (nh->nlmsg_type != RTM_NEWLINK)
304 nlmsg_parse(nh, sizeof(*ifi), nla, __IFLA_MAX - 1, NULL);
305 if (!nla[IFLA_IFNAME])
308 struct device *dev = device_get(nla_data(nla[IFLA_IFNAME]), false);
312 device_set_ifindex(dev, ifi->ifi_index);
313 device_set_link(dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
320 handle_hotplug_msg(char *data, int size)
322 const char *subsystem = NULL, *interface = NULL;
323 char *cur, *end, *sep;
328 if (!strncmp(data, "add@", 4))
330 else if (!strncmp(data, "remove@", 7))
335 skip = strlen(data) + 1;
338 for (cur = data + skip; cur < end; cur += skip) {
339 skip = strlen(cur) + 1;
341 sep = strchr(cur, '=');
346 if (!strcmp(cur, "INTERFACE"))
348 else if (!strcmp(cur, "SUBSYSTEM")) {
350 if (strcmp(subsystem, "net") != 0)
353 if (subsystem && interface)
359 dev = device_get(interface, false);
363 if (dev->type != &simple_device_type)
366 if (add && system_if_force_external(dev->ifname))
369 device_set_present(dev, add);
373 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
375 struct event_socket *ev = container_of(u, struct event_socket, uloop);
376 struct sockaddr_nl nla;
377 unsigned char *buf = NULL;
380 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
382 handle_hotplug_msg((char *) buf, size);
388 static int system_rtnl_call(struct nl_msg *msg)
392 ret = nl_send_auto_complete(sock_rtnl, msg);
398 return nl_wait_for_ack(sock_rtnl);
401 int system_bridge_delbr(struct device *bridge)
403 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
406 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
410 memset(&ifr, 0, sizeof(ifr));
412 ifr.ifr_ifindex = dev->ifindex;
415 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
416 return ioctl(sock_ioctl, cmd, &ifr);
419 static bool system_is_bridge(const char *name, char *buf, int buflen)
423 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
424 if (stat(buf, &st) < 0)
430 static char *system_get_bridge(const char *name, char *buf, int buflen)
436 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
437 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
440 if (gl.gl_pathc == 0)
443 len = readlink(gl.gl_pathv[0], buf, buflen);
448 path = strrchr(buf, '/');
455 int system_bridge_addif(struct device *bridge, struct device *dev)
459 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
460 if (oldbr && !strcmp(oldbr, bridge->ifname))
463 return system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
466 int system_bridge_delif(struct device *bridge, struct device *dev)
468 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
471 static int system_if_resolve(struct device *dev)
474 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
475 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
476 return ifr.ifr_ifindex;
481 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
485 memset(&ifr, 0, sizeof(ifr));
486 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
487 ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
488 ifr.ifr_flags |= add;
489 ifr.ifr_flags &= ~rem;
490 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
502 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
504 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
506 return ifa->ifa_index == ifindex;
509 static bool check_route(struct nlmsghdr *hdr, int ifindex)
511 struct rtmsg *r = NLMSG_DATA(hdr);
512 struct nlattr *tb[__RTA_MAX];
514 if (r->rtm_protocol == RTPROT_KERNEL &&
515 r->rtm_family == AF_INET6)
518 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
522 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
525 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
530 static int cb_clear_event(struct nl_msg *msg, void *arg)
532 struct clear_data *clr = arg;
533 struct nlmsghdr *hdr = nlmsg_hdr(msg);
534 bool (*cb)(struct nlmsghdr *, int ifindex);
540 if (hdr->nlmsg_type != RTM_NEWADDR)
547 if (hdr->nlmsg_type != RTM_NEWROUTE)
554 if (hdr->nlmsg_type != RTM_NEWRULE)
563 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
566 if (type == RTM_DELRULE)
567 D(SYSTEM, "Remove a rule\n");
569 D(SYSTEM, "Remove %s from device %s\n",
570 type == RTM_DELADDR ? "an address" : "a route",
572 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
573 hdr = nlmsg_hdr(clr->msg);
574 hdr->nlmsg_type = type;
575 hdr->nlmsg_flags = NLM_F_REQUEST;
577 nl_socket_disable_auto_ack(sock_rtnl);
578 nl_send_auto_complete(sock_rtnl, clr->msg);
579 nl_socket_enable_auto_ack(sock_rtnl);
585 cb_finish_event(struct nl_msg *msg, void *arg)
593 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
596 *pending = err->error;
601 system_if_clear_entries(struct device *dev, int type, int af)
603 struct clear_data clr;
604 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
607 .rtm_flags = RTM_F_CLONED,
609 int flags = NLM_F_DUMP;
618 clr.size = sizeof(struct rtgenmsg);
621 clr.size = sizeof(struct rtmsg);
630 clr.msg = nlmsg_alloc_simple(type, flags);
634 nlmsg_append(clr.msg, &rtm, clr.size, 0);
635 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
636 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
637 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
639 nl_send_auto_complete(sock_rtnl, clr.msg);
641 nl_recvmsgs(sock_rtnl, cb);
649 * Clear bridge (membership) state and bring down device
651 void system_if_clear_state(struct device *dev)
653 static char buf[256];
656 device_set_ifindex(dev, system_if_resolve(dev));
657 if (dev->external || !dev->ifindex)
660 system_if_flags(dev->ifname, 0, IFF_UP);
662 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
663 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
664 system_bridge_delbr(dev);
668 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
670 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
671 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
674 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
675 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
676 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
677 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
678 system_set_disable_ipv6(dev, "0");
681 static inline unsigned long
682 sec_to_jiffies(int val)
684 return (unsigned long) val * 100;
687 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
689 unsigned long args[4] = {};
691 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
694 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
695 args[1] = !!cfg->stp;
696 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
698 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
699 args[1] = sec_to_jiffies(cfg->forward_delay);
700 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
702 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
703 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
705 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
706 args[1] = cfg->priority;
707 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
709 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
710 args[0] = BRCTL_SET_AGEING_TIME;
711 args[1] = sec_to_jiffies(cfg->ageing_time);
712 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
715 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
716 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
717 args[1] = sec_to_jiffies(cfg->hello_time);
718 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
721 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
722 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
723 args[1] = sec_to_jiffies(cfg->max_age);
724 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
730 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
733 struct nlattr *linkinfo, *data;
734 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
735 int ifindex = system_if_resolve(dev);
737 static const struct {
739 enum macvlan_mode val;
741 { "private", MACVLAN_MODE_PRIVATE },
742 { "vepa", MACVLAN_MODE_VEPA },
743 { "bridge", MACVLAN_MODE_BRIDGE },
744 { "passthru", MACVLAN_MODE_PASSTHRU },
750 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
755 nlmsg_append(msg, &iim, sizeof(iim), 0);
757 if (cfg->flags & MACVLAN_OPT_MACADDR)
758 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
759 nla_put_string(msg, IFLA_IFNAME, macvlan->ifname);
760 nla_put_u32(msg, IFLA_LINK, ifindex);
762 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
763 goto nla_put_failure;
765 nla_put_string(msg, IFLA_INFO_KIND, "macvlan");
767 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
768 goto nla_put_failure;
771 for (i = 0; i < ARRAY_SIZE(modes); i++) {
772 if (strcmp(cfg->mode, modes[i].name) != 0)
775 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
780 nla_nest_end(msg, data);
781 nla_nest_end(msg, linkinfo);
783 rv = system_rtnl_call(msg);
785 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
794 static int system_link_del(struct device *dev)
797 struct ifinfomsg iim = {
798 .ifi_family = AF_UNSPEC,
802 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
807 nlmsg_append(msg, &iim, sizeof(iim), 0);
808 nla_put_string(msg, IFLA_IFNAME, dev->ifname);
809 return system_rtnl_call(msg);
812 int system_macvlan_del(struct device *macvlan)
814 return system_link_del(macvlan);
817 static int system_vlan(struct device *dev, int id)
819 struct vlan_ioctl_args ifr = {
820 .cmd = SET_VLAN_NAME_TYPE_CMD,
821 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
824 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
827 ifr.cmd = DEL_VLAN_CMD;
830 ifr.cmd = ADD_VLAN_CMD;
833 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
834 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
837 int system_vlan_add(struct device *dev, int id)
839 return system_vlan(dev, id);
842 int system_vlan_del(struct device *dev)
844 return system_vlan(dev, -1);
847 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
850 struct nlattr *linkinfo, *data;
851 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
852 int ifindex = system_if_resolve(dev);
858 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
863 nlmsg_append(msg, &iim, sizeof(iim), 0);
864 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
865 nla_put_u32(msg, IFLA_LINK, ifindex);
867 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
868 goto nla_put_failure;
870 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
872 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
873 goto nla_put_failure;
875 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
877 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
878 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
880 if(cfg->proto == VLAN_PROTO_8021AD)
881 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);
884 nla_nest_end(msg, data);
885 nla_nest_end(msg, linkinfo);
887 rv = system_rtnl_call(msg);
889 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
898 int system_vlandev_del(struct device *vlandev)
900 return system_link_del(vlandev);
904 system_if_get_settings(struct device *dev, struct device_settings *s)
909 memset(&ifr, 0, sizeof(ifr));
910 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
912 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
913 s->mtu = ifr.ifr_mtu;
914 s->flags |= DEV_OPT_MTU;
917 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
918 s->txqueuelen = ifr.ifr_qlen;
919 s->flags |= DEV_OPT_TXQUEUELEN;
922 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
923 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
924 s->flags |= DEV_OPT_MACADDR;
927 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
928 s->ipv6 = !strtoul(buf, NULL, 0);
929 s->flags |= DEV_OPT_IPV6;
934 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
941 memset(&ifr, 0, sizeof(ifr));
942 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
943 if (s->flags & DEV_OPT_MTU & apply_mask) {
944 ifr.ifr_mtu = s->mtu;
945 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
946 s->flags &= ~DEV_OPT_MTU;
948 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
949 ifr.ifr_qlen = s->txqueuelen;
950 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
951 s->flags &= ~DEV_OPT_TXQUEUELEN;
953 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
954 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
955 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
956 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
957 s->flags &= ~DEV_OPT_MACADDR;
959 if (s->flags & DEV_OPT_IPV6 & apply_mask)
960 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
963 int system_if_up(struct device *dev)
965 system_if_get_settings(dev, &dev->orig_settings);
966 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
967 device_set_ifindex(dev, system_if_resolve(dev));
968 return system_if_flags(dev->ifname, IFF_UP, 0);
971 int system_if_down(struct device *dev)
973 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
974 dev->orig_settings.flags &= dev->settings.flags;
975 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
979 struct if_check_data {
985 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
987 struct nlmsghdr *nh = nlmsg_hdr(msg);
988 struct ifinfomsg *ifi = NLMSG_DATA(nh);
989 struct if_check_data *chk = (struct if_check_data *)arg;
991 if (nh->nlmsg_type != RTM_NEWLINK)
994 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
995 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1000 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1002 struct if_check_data *chk = (struct if_check_data *)arg;
1007 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1009 struct if_check_data *chk = (struct if_check_data *)arg;
1011 device_set_present(chk->dev, false);
1012 device_set_link(chk->dev, false);
1013 chk->pending = err->error;
1018 int system_if_check(struct device *dev)
1020 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1022 struct ifinfomsg ifi = {
1023 .ifi_family = AF_UNSPEC,
1026 struct if_check_data chk = {
1032 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1033 if (!msg || nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1034 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1037 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1038 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1039 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1041 nl_send_auto_complete(sock_rtnl, msg);
1042 while (chk.pending > 0)
1043 nl_recvmsgs(sock_rtnl, cb);
1054 system_if_get_parent(struct device *dev)
1056 char buf[64], *devname;
1057 int ifindex, iflink, len;
1060 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1061 f = fopen(buf, "r");
1065 len = fread(buf, 1, sizeof(buf) - 1, f);
1072 iflink = strtoul(buf, NULL, 0);
1073 ifindex = system_if_resolve(dev);
1074 if (!iflink || iflink == ifindex)
1077 devname = if_indextoname(iflink, buf);
1081 return device_get(devname, true);
1085 read_string_file(int dir_fd, const char *file, char *buf, int len)
1091 fd = openat(dir_fd, file, O_RDONLY);
1096 len = read(fd, buf, len - 1);
1100 } else if (len > 0) {
1103 c = strchr(buf, '\n');
1116 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1121 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1123 *val = strtoull(buf, NULL, 0);
1128 /* Assume advertised flags == supported flags */
1129 static const struct {
1132 } ethtool_link_modes[] = {
1133 { ADVERTISED_10baseT_Half, "10H" },
1134 { ADVERTISED_10baseT_Full, "10F" },
1135 { ADVERTISED_100baseT_Half, "100H" },
1136 { ADVERTISED_100baseT_Full, "100F" },
1137 { ADVERTISED_1000baseT_Half, "1000H" },
1138 { ADVERTISED_1000baseT_Full, "1000F" },
1141 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1144 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1145 if (mask & ethtool_link_modes[i].mask)
1146 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1151 system_if_force_external(const char *ifname)
1156 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1157 return stat(buf, &s) == 0;
1161 system_if_dump_info(struct device *dev, struct blob_buf *b)
1163 struct ethtool_cmd ecmd;
1169 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
1170 dir_fd = open(buf, O_DIRECTORY);
1172 memset(&ecmd, 0, sizeof(ecmd));
1173 memset(&ifr, 0, sizeof(ifr));
1174 strcpy(ifr.ifr_name, dev->ifname);
1175 ifr.ifr_data = (caddr_t) &ecmd;
1176 ecmd.cmd = ETHTOOL_GSET;
1178 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1179 c = blobmsg_open_array(b, "link-advertising");
1180 system_add_link_modes(b, ecmd.advertising);
1181 blobmsg_close_array(b, c);
1183 c = blobmsg_open_array(b, "link-supported");
1184 system_add_link_modes(b, ecmd.supported);
1185 blobmsg_close_array(b, c);
1187 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1188 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1189 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1190 blobmsg_add_string_buffer(b);
1198 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1200 const char *const counters[] = {
1201 "collisions", "rx_frame_errors", "tx_compressed",
1202 "multicast", "rx_length_errors", "tx_dropped",
1203 "rx_bytes", "rx_missed_errors", "tx_errors",
1204 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1205 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1206 "rx_dropped", "tx_aborted_errors", "tx_packets",
1207 "rx_errors", "tx_bytes", "tx_window_errors",
1208 "rx_fifo_errors", "tx_carrier_errors",
1215 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1216 stats_dir = open(buf, O_DIRECTORY);
1220 for (i = 0; i < ARRAY_SIZE(counters); i++)
1221 if (read_uint64_file(stats_dir, counters[i], &val))
1222 blobmsg_add_u64(b, counters[i], val);
1228 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1230 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1231 int alen = v4 ? 4 : 16;
1232 unsigned int flags = 0;
1233 struct ifaddrmsg ifa = {
1234 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1235 .ifa_prefixlen = addr->mask,
1236 .ifa_index = dev->ifindex,
1240 if (cmd == RTM_NEWADDR)
1241 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1243 msg = nlmsg_alloc_simple(cmd, flags);
1247 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1248 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1250 if (addr->broadcast)
1251 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1252 if (addr->point_to_point)
1253 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1255 time_t now = system_get_rtime();
1256 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1258 if (addr->preferred_until) {
1259 int64_t preferred = addr->preferred_until - now;
1262 else if (preferred > UINT32_MAX)
1263 preferred = UINT32_MAX;
1265 cinfo.ifa_prefered = preferred;
1268 if (addr->valid_until) {
1269 int64_t valid = addr->valid_until - now;
1272 else if (valid > UINT32_MAX)
1275 cinfo.ifa_valid = valid;
1278 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1281 return system_rtnl_call(msg);
1284 int system_add_address(struct device *dev, struct device_addr *addr)
1286 return system_addr(dev, addr, RTM_NEWADDR);
1289 int system_del_address(struct device *dev, struct device_addr *addr)
1291 return system_addr(dev, addr, RTM_DELADDR);
1294 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1296 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1298 unsigned int flags = 0;
1301 have_gw = !!route->nexthop.in.s_addr;
1303 have_gw = route->nexthop.in6.s6_addr32[0] ||
1304 route->nexthop.in6.s6_addr32[1] ||
1305 route->nexthop.in6.s6_addr32[2] ||
1306 route->nexthop.in6.s6_addr32[3];
1308 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1309 ? route->table : RT_TABLE_MAIN;
1311 struct rtmsg rtm = {
1312 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1313 .rtm_dst_len = route->mask,
1314 .rtm_src_len = route->sourcemask,
1315 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1316 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
1317 .rtm_scope = RT_SCOPE_NOWHERE,
1318 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1319 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1323 if (cmd == RTM_NEWROUTE) {
1324 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1326 if (!dev) { // Add null-route
1327 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1328 rtm.rtm_type = RTN_UNREACHABLE;
1331 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1334 if (route->flags & DEVROUTE_TYPE) {
1335 rtm.rtm_type = route->type;
1336 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
1337 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
1338 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
1339 rtm.rtm_table = RT_TABLE_LOCAL;
1342 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT)
1343 rtm.rtm_scope = RT_SCOPE_HOST;
1344 else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
1345 rtm.rtm_type == RTN_ANYCAST)
1346 rtm.rtm_scope = RT_SCOPE_LINK;
1349 msg = nlmsg_alloc_simple(cmd, flags);
1353 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1356 nla_put(msg, RTA_DST, alen, &route->addr);
1358 if (route->sourcemask)
1359 nla_put(msg, RTA_SRC, alen, &route->source);
1361 if (route->metric > 0)
1362 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1365 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1368 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1371 nla_put_u32(msg, RTA_TABLE, table);
1373 if (route->flags & DEVROUTE_MTU) {
1374 struct nlattr *metrics;
1376 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1377 goto nla_put_failure;
1379 nla_put_u32(msg, RTAX_MTU, route->mtu);
1381 nla_nest_end(msg, metrics);
1384 return system_rtnl_call(msg);
1391 int system_add_route(struct device *dev, struct device_route *route)
1393 return system_rt(dev, route, RTM_NEWROUTE);
1396 int system_del_route(struct device *dev, struct device_route *route)
1398 return system_rt(dev, route, RTM_DELROUTE);
1401 int system_flush_routes(void)
1403 const char *names[] = {
1404 "/proc/sys/net/ipv4/route/flush",
1405 "/proc/sys/net/ipv6/route/flush"
1409 for (i = 0; i < ARRAY_SIZE(names); i++) {
1410 fd = open(names[i], O_WRONLY);
1414 if (write(fd, "-1", 2)) {}
1420 bool system_resolve_rt_type(const char *type, unsigned int *id)
1422 return system_rtn_aton(type, id);
1425 bool system_resolve_rt_table(const char *name, unsigned int *id)
1429 unsigned int n, table = RT_TABLE_UNSPEC;
1431 /* first try to parse table as number */
1432 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1435 /* handle well known aliases */
1436 else if (!strcmp(name, "default"))
1437 table = RT_TABLE_DEFAULT;
1438 else if (!strcmp(name, "main"))
1439 table = RT_TABLE_MAIN;
1440 else if (!strcmp(name, "local"))
1441 table = RT_TABLE_LOCAL;
1443 /* try to look up name in /etc/iproute2/rt_tables */
1444 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1446 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1448 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1451 n = strtoul(e, NULL, 10);
1452 e = strtok(NULL, " \t\n");
1454 if (e && !strcmp(e, name))
1464 if (table == RT_TABLE_UNSPEC)
1471 bool system_is_default_rt_table(unsigned int id)
1473 return (id == RT_TABLE_MAIN);
1476 static int system_iprule(struct iprule *rule, int cmd)
1478 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1481 struct rtmsg rtm = {
1482 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1483 .rtm_protocol = RTPROT_STATIC,
1484 .rtm_scope = RT_SCOPE_UNIVERSE,
1485 .rtm_table = RT_TABLE_UNSPEC,
1486 .rtm_type = RTN_UNSPEC,
1490 if (cmd == RTM_NEWRULE) {
1491 rtm.rtm_type = RTN_UNICAST;
1492 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1496 rtm.rtm_flags |= FIB_RULE_INVERT;
1498 if (rule->flags & IPRULE_SRC)
1499 rtm.rtm_src_len = rule->src_mask;
1501 if (rule->flags & IPRULE_DEST)
1502 rtm.rtm_dst_len = rule->dest_mask;
1504 if (rule->flags & IPRULE_TOS)
1505 rtm.rtm_tos = rule->tos;
1507 if (rule->flags & IPRULE_LOOKUP) {
1508 if (rule->lookup < 256)
1509 rtm.rtm_table = rule->lookup;
1512 if (rule->flags & IPRULE_ACTION)
1513 rtm.rtm_type = rule->action;
1514 else if (rule->flags & IPRULE_GOTO)
1515 rtm.rtm_type = FR_ACT_GOTO;
1516 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1517 rtm.rtm_type = FR_ACT_NOP;
1519 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1524 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1526 if (rule->flags & IPRULE_IN)
1527 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1529 if (rule->flags & IPRULE_OUT)
1530 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1532 if (rule->flags & IPRULE_SRC)
1533 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1535 if (rule->flags & IPRULE_DEST)
1536 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1538 if (rule->flags & IPRULE_PRIORITY)
1539 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1540 else if (cmd == RTM_NEWRULE)
1541 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1543 if (rule->flags & IPRULE_FWMARK)
1544 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1546 if (rule->flags & IPRULE_FWMASK)
1547 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1549 if (rule->flags & IPRULE_LOOKUP) {
1550 if (rule->lookup >= 256)
1551 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1554 if (rule->flags & IPRULE_GOTO)
1555 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1557 return system_rtnl_call(msg);
1560 int system_add_iprule(struct iprule *rule)
1562 return system_iprule(rule, RTM_NEWRULE);
1565 int system_del_iprule(struct iprule *rule)
1567 return system_iprule(rule, RTM_DELRULE);
1570 int system_flush_iprules(void)
1575 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1576 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1578 memset(&rule, 0, sizeof(rule));
1581 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1584 rule.lookup = RT_TABLE_LOCAL;
1585 rv |= system_iprule(&rule, RTM_NEWRULE);
1587 rule.priority = 32766;
1588 rule.lookup = RT_TABLE_MAIN;
1589 rv |= system_iprule(&rule, RTM_NEWRULE);
1591 rule.priority = 32767;
1592 rule.lookup = RT_TABLE_DEFAULT;
1593 rv |= system_iprule(&rule, RTM_NEWRULE);
1596 rule.flags = IPRULE_INET6 | 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);
1609 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1611 return system_rtn_aton(action, id);
1614 time_t system_get_rtime(void)
1619 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1622 if (gettimeofday(&tv, NULL) == 0)
1629 #define IP_DF 0x4000
1632 static int tunnel_ioctl(const char *name, int cmd, void *p)
1636 memset(&ifr, 0, sizeof(ifr));
1637 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1638 ifr.ifr_ifru.ifru_data = p;
1639 return ioctl(sock_ioctl, cmd, &ifr);
1642 int system_del_ip_tunnel(const char *name)
1644 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
1647 int system_update_ipv6_mtu(struct device *dev, int mtu)
1651 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
1654 int fd = open(buf, O_RDWR);
1655 ssize_t len = read(fd, buf, sizeof(buf) - 1);
1662 if (!mtu || ret <= mtu)
1665 lseek(fd, 0, SEEK_SET);
1666 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) <= 0)
1674 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
1676 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
1677 struct blob_attr *cur;
1681 system_del_ip_tunnel(name);
1683 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
1684 blob_data(attr), blob_len(attr));
1686 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
1688 str = blobmsg_data(cur);
1690 if ((cur = tb[TUNNEL_ATTR_DF]))
1691 set_df = blobmsg_get_bool(cur);
1693 unsigned int ttl = 0;
1694 if ((cur = tb[TUNNEL_ATTR_TTL])) {
1695 ttl = blobmsg_get_u32(cur);
1696 if (ttl > 255 || (!set_df && ttl))
1700 unsigned int link = 0;
1701 if ((cur = tb[TUNNEL_ATTR_LINK])) {
1702 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
1706 if (iface->l3_dev.dev)
1707 link = iface->l3_dev.dev->ifindex;
1710 if (!strcmp(str, "sit")) {
1711 struct ip_tunnel_parm p = {
1716 .frag_off = set_df ? htons(IP_DF) : 0,
1717 .protocol = IPPROTO_IPV6,
1722 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
1723 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
1726 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
1727 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
1730 strncpy(p.name, name, sizeof(p.name));
1731 if (tunnel_ioctl("sit0", SIOCADDTUNNEL, &p) < 0)
1735 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
1737 struct ip_tunnel_6rd p6;
1739 memset(&p6, 0, sizeof(p6));
1741 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
1742 &p6.prefix, &mask) || mask > 128)
1744 p6.prefixlen = mask;
1746 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
1747 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
1748 &p6.relay_prefix, &mask) || mask > 32)
1750 p6.relay_prefixlen = mask;
1753 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
1754 system_del_ip_tunnel(name);
1759 } else if (!strcmp(str, "ipip6")) {
1760 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
1761 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
1762 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
1768 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
1769 nla_put_string(nlm, IFLA_IFNAME, name);
1772 nla_put_u32(nlm, IFLA_LINK, link);
1774 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
1779 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
1780 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
1787 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
1789 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
1790 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
1791 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
1793 struct in6_addr in6buf;
1794 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1795 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1799 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
1802 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
1803 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1807 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
1810 #ifdef IFLA_IPTUN_FMR_MAX
1811 if ((cur = tb[TUNNEL_ATTR_FMRS])) {
1812 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
1814 struct blob_attr *fmr;
1815 unsigned rem, fmrcnt = 0;
1816 blobmsg_for_each_attr(fmr, cur, rem) {
1817 if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
1820 unsigned ip4len, ip6len, ealen, offset = 6;
1824 if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
1825 ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) {
1830 struct in6_addr ip6prefix;
1831 struct in_addr ip4prefix;
1832 if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
1833 inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) {
1838 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
1840 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
1841 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
1842 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
1843 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
1844 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
1845 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
1847 nla_nest_end(nlm, rule);
1850 nla_nest_end(nlm, fmrs);
1854 nla_nest_end(nlm, infodata);
1855 nla_nest_end(nlm, linkinfo);
1857 return system_rtnl_call(nlm);