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)
1467 /* do not consider main table special */
1468 if (table == RT_TABLE_MAIN)
1469 table = RT_TABLE_UNSPEC;
1475 static int system_iprule(struct iprule *rule, int cmd)
1477 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1480 struct rtmsg rtm = {
1481 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1482 .rtm_protocol = RTPROT_STATIC,
1483 .rtm_scope = RT_SCOPE_UNIVERSE,
1484 .rtm_table = RT_TABLE_UNSPEC,
1485 .rtm_type = RTN_UNSPEC,
1489 if (cmd == RTM_NEWRULE) {
1490 rtm.rtm_type = RTN_UNICAST;
1491 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1495 rtm.rtm_flags |= FIB_RULE_INVERT;
1497 if (rule->flags & IPRULE_SRC)
1498 rtm.rtm_src_len = rule->src_mask;
1500 if (rule->flags & IPRULE_DEST)
1501 rtm.rtm_dst_len = rule->dest_mask;
1503 if (rule->flags & IPRULE_TOS)
1504 rtm.rtm_tos = rule->tos;
1506 if (rule->flags & IPRULE_LOOKUP) {
1507 if (rule->lookup < 256)
1508 rtm.rtm_table = rule->lookup;
1511 if (rule->flags & IPRULE_ACTION)
1512 rtm.rtm_type = rule->action;
1513 else if (rule->flags & IPRULE_GOTO)
1514 rtm.rtm_type = FR_ACT_GOTO;
1515 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1516 rtm.rtm_type = FR_ACT_NOP;
1518 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1523 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1525 if (rule->flags & IPRULE_IN)
1526 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1528 if (rule->flags & IPRULE_OUT)
1529 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1531 if (rule->flags & IPRULE_SRC)
1532 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1534 if (rule->flags & IPRULE_DEST)
1535 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1537 if (rule->flags & IPRULE_PRIORITY)
1538 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1539 else if (cmd == RTM_NEWRULE)
1540 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1542 if (rule->flags & IPRULE_FWMARK)
1543 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1545 if (rule->flags & IPRULE_FWMASK)
1546 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1548 if (rule->flags & IPRULE_LOOKUP) {
1549 if (rule->lookup >= 256)
1550 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1553 if (rule->flags & IPRULE_GOTO)
1554 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1556 return system_rtnl_call(msg);
1559 int system_add_iprule(struct iprule *rule)
1561 return system_iprule(rule, RTM_NEWRULE);
1564 int system_del_iprule(struct iprule *rule)
1566 return system_iprule(rule, RTM_DELRULE);
1569 int system_flush_iprules(void)
1574 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1575 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1577 memset(&rule, 0, sizeof(rule));
1580 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1583 rule.lookup = RT_TABLE_LOCAL;
1584 rv |= system_iprule(&rule, RTM_NEWRULE);
1586 rule.priority = 32766;
1587 rule.lookup = RT_TABLE_MAIN;
1588 rv |= system_iprule(&rule, RTM_NEWRULE);
1590 rule.priority = 32767;
1591 rule.lookup = RT_TABLE_DEFAULT;
1592 rv |= system_iprule(&rule, RTM_NEWRULE);
1595 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1598 rule.lookup = RT_TABLE_LOCAL;
1599 rv |= system_iprule(&rule, RTM_NEWRULE);
1601 rule.priority = 32766;
1602 rule.lookup = RT_TABLE_MAIN;
1603 rv |= system_iprule(&rule, RTM_NEWRULE);
1608 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1610 return system_rtn_aton(action, id);
1613 time_t system_get_rtime(void)
1618 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1621 if (gettimeofday(&tv, NULL) == 0)
1628 #define IP_DF 0x4000
1631 static int tunnel_ioctl(const char *name, int cmd, void *p)
1635 memset(&ifr, 0, sizeof(ifr));
1636 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1637 ifr.ifr_ifru.ifru_data = p;
1638 return ioctl(sock_ioctl, cmd, &ifr);
1641 int system_del_ip_tunnel(const char *name)
1643 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
1646 int system_update_ipv6_mtu(struct device *dev, int mtu)
1650 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
1653 int fd = open(buf, O_RDWR);
1654 ssize_t len = read(fd, buf, sizeof(buf) - 1);
1661 if (!mtu || ret <= mtu)
1664 lseek(fd, 0, SEEK_SET);
1665 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) <= 0)
1673 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
1675 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
1676 struct blob_attr *cur;
1680 system_del_ip_tunnel(name);
1682 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
1683 blob_data(attr), blob_len(attr));
1685 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
1687 str = blobmsg_data(cur);
1689 if ((cur = tb[TUNNEL_ATTR_DF]))
1690 set_df = blobmsg_get_bool(cur);
1692 unsigned int ttl = 0;
1693 if ((cur = tb[TUNNEL_ATTR_TTL])) {
1694 ttl = blobmsg_get_u32(cur);
1695 if (ttl > 255 || (!set_df && ttl))
1699 unsigned int link = 0;
1700 if ((cur = tb[TUNNEL_ATTR_LINK])) {
1701 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
1705 if (iface->l3_dev.dev)
1706 link = iface->l3_dev.dev->ifindex;
1709 if (!strcmp(str, "sit")) {
1710 struct ip_tunnel_parm p = {
1715 .frag_off = set_df ? htons(IP_DF) : 0,
1716 .protocol = IPPROTO_IPV6,
1721 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
1722 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
1725 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
1726 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
1729 strncpy(p.name, name, sizeof(p.name));
1730 if (tunnel_ioctl("sit0", SIOCADDTUNNEL, &p) < 0)
1734 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
1736 struct ip_tunnel_6rd p6;
1738 memset(&p6, 0, sizeof(p6));
1740 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
1741 &p6.prefix, &mask) || mask > 128)
1743 p6.prefixlen = mask;
1745 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
1746 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
1747 &p6.relay_prefix, &mask) || mask > 32)
1749 p6.relay_prefixlen = mask;
1752 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
1753 system_del_ip_tunnel(name);
1758 } else if (!strcmp(str, "ipip6")) {
1759 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
1760 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
1761 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
1767 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
1768 nla_put_string(nlm, IFLA_IFNAME, name);
1771 nla_put_u32(nlm, IFLA_LINK, link);
1773 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
1778 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
1779 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
1786 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
1788 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
1789 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
1790 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
1792 struct in6_addr in6buf;
1793 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1794 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1798 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
1801 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
1802 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1806 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
1809 #ifdef IFLA_IPTUN_FMR_MAX
1810 if ((cur = tb[TUNNEL_ATTR_FMRS])) {
1811 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
1813 struct blob_attr *fmr;
1814 unsigned rem, fmrcnt = 0;
1815 blobmsg_for_each_attr(fmr, cur, rem) {
1816 if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
1819 unsigned ip4len, ip6len, ealen, offset = 6;
1823 if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
1824 ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) {
1829 struct in6_addr ip6prefix;
1830 struct in_addr ip4prefix;
1831 if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
1832 inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) {
1837 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
1839 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
1840 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
1841 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
1842 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
1843 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
1844 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
1846 nla_nest_end(nlm, rule);
1849 nla_nest_end(nlm, fmrs);
1853 nla_nest_end(nlm, infodata);
1854 nla_nest_end(nlm, linkinfo);
1856 return system_rtnl_call(nlm);