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_addr.h>
34 #include <linux/if_link.h>
35 #include <linux/if_vlan.h>
36 #include <linux/if_bridge.h>
37 #include <linux/if_tunnel.h>
38 #include <linux/ip6_tunnel.h>
39 #include <linux/ethtool.h>
40 #include <linux/fib_rules.h>
41 #include <linux/version.h>
43 #ifndef RTN_FAILED_POLICY
44 #define RTN_FAILED_POLICY 12
47 #ifndef IFA_F_NOPREFIXROUTE
48 #define IFA_F_NOPREFIXROUTE 0x200
52 #define IFA_FLAGS (IFA_MULTICAST + 1)
62 #include <netlink/msg.h>
63 #include <netlink/attr.h>
64 #include <netlink/socket.h>
65 #include <libubox/uloop.h>
72 struct uloop_fd uloop;
77 static int sock_ioctl = -1;
78 static struct nl_sock *sock_rtnl = NULL;
80 static int cb_rtnl_event(struct nl_msg *msg, void *arg);
81 static void handle_hotplug_event(struct uloop_fd *u, unsigned int events);
83 static char dev_buf[256];
86 handler_nl_event(struct uloop_fd *u, unsigned int events)
88 struct event_socket *ev = container_of(u, struct event_socket, uloop);
90 socklen_t errlen = sizeof(err);
93 nl_recvmsgs_default(ev->sock);
97 if (getsockopt(u->fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen))
102 // Increase rx buffer size on netlink socket
104 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
107 // Request full dump since some info got dropped
108 struct rtgenmsg msg = { .rtgen_family = AF_UNSPEC };
109 nl_send_simple(ev->sock, RTM_GETLINK, NLM_F_DUMP, &msg, sizeof(msg));
119 uloop_fd_delete(&ev->uloop);
123 static struct nl_sock *
124 create_socket(int protocol, int groups)
126 struct nl_sock *sock;
128 sock = nl_socket_alloc();
133 nl_join_groups(sock, groups);
135 if (nl_connect(sock, protocol))
142 create_raw_event_socket(struct event_socket *ev, int protocol, int groups,
143 uloop_fd_handler cb, int flags)
145 ev->sock = create_socket(protocol, groups);
149 ev->uloop.fd = nl_socket_get_fd(ev->sock);
151 if (uloop_fd_add(&ev->uloop, ULOOP_READ|flags))
158 create_event_socket(struct event_socket *ev, int protocol,
159 int (*cb)(struct nl_msg *msg, void *arg))
161 if (!create_raw_event_socket(ev, protocol, 0, handler_nl_event, ULOOP_ERROR_CB))
164 // Install the valid custom callback handler
165 nl_socket_modify_cb(ev->sock, NL_CB_VALID, NL_CB_CUSTOM, cb, NULL);
167 // Disable sequence number checking on event sockets
168 nl_socket_disable_seq_check(ev->sock);
170 // Increase rx buffer size to 65K on event sockets
172 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
179 system_rtn_aton(const char *src, unsigned int *dst)
184 if (!strcmp(src, "local"))
186 else if (!strcmp(src, "nat"))
188 else if (!strcmp(src, "broadcast"))
190 else if (!strcmp(src, "anycast"))
192 else if (!strcmp(src, "multicast"))
194 else if (!strcmp(src, "prohibit"))
196 else if (!strcmp(src, "unreachable"))
198 else if (!strcmp(src, "blackhole"))
200 else if (!strcmp(src, "xresolve"))
202 else if (!strcmp(src, "unicast"))
204 else if (!strcmp(src, "throw"))
206 else if (!strcmp(src, "failed_policy"))
207 n = RTN_FAILED_POLICY;
209 n = strtoul(src, &e, 0);
210 if (!e || *e || e == src || n > 255)
219 system_tos_aton(const char *src, unsigned *dst)
223 *dst = strtoul(src, &e, 16);
224 if (e == src || *e || *dst > 255)
230 int system_init(void)
232 static struct event_socket rtnl_event;
233 static struct event_socket hotplug_event;
235 sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0);
236 system_fd_set_cloexec(sock_ioctl);
238 // Prepare socket for routing / address control
239 sock_rtnl = create_socket(NETLINK_ROUTE, 0);
243 if (!create_event_socket(&rtnl_event, NETLINK_ROUTE, cb_rtnl_event))
246 if (!create_raw_event_socket(&hotplug_event, NETLINK_KOBJECT_UEVENT, 1,
247 handle_hotplug_event, 0))
250 // Receive network link events form kernel
251 nl_socket_add_membership(rtnl_event.sock, RTNLGRP_LINK);
256 static void system_set_sysctl(const char *path, const char *val)
260 fd = open(path, O_WRONLY);
264 if (write(fd, val, strlen(val))) {}
268 static void system_set_dev_sysctl(const char *path, const char *device, const char *val)
270 snprintf(dev_buf, sizeof(dev_buf), path, device);
271 system_set_sysctl(dev_buf, val);
274 static void system_set_disable_ipv6(struct device *dev, const char *val)
276 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val);
279 static void system_set_rpfilter(struct device *dev, const char *val)
281 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter", dev->ifname, val);
284 static void system_set_acceptlocal(struct device *dev, const char *val)
286 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local", dev->ifname, val);
289 static void system_set_igmpversion(struct device *dev, const char *val)
291 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version", dev->ifname, val);
294 static void system_set_mldversion(struct device *dev, const char *val)
296 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version", dev->ifname, val);
299 static void system_set_neigh4reachabletime(struct device *dev, const char *val)
301 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms", dev->ifname, val);
304 static void system_set_neigh6reachabletime(struct device *dev, const char *val)
306 system_set_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms", dev->ifname, val);
309 static void system_set_dadtransmits(struct device *dev, const char *val)
311 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits", dev->ifname, val);
314 static void system_bridge_set_multicast_to_unicast(struct device *dev, const char *val)
316 system_set_dev_sysctl("/sys/class/net/%s/brport/multicast_to_unicast", dev->ifname, val);
319 static void system_bridge_set_hairpin_mode(struct device *dev, const char *val)
321 system_set_dev_sysctl("/sys/class/net/%s/brport/hairpin_mode", dev->ifname, val);
324 static void system_bridge_set_multicast_router(struct device *dev, const char *val, bool bridge)
326 system_set_dev_sysctl(bridge ? "/sys/class/net/%s/bridge/multicast_router" :
327 "/sys/class/net/%s/brport/multicast_router",
331 static void system_bridge_set_robustness(struct device *dev, const char *val)
333 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_startup_query_count",
335 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_last_member_count",
339 static void system_bridge_set_query_interval(struct device *dev, const char *val)
341 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_query_interval",
345 static void system_bridge_set_query_response_interval(struct device *dev, const char *val)
347 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_query_response_interval",
351 static void system_bridge_set_last_member_interval(struct device *dev, const char *val)
353 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_last_member_interval",
357 static void system_bridge_set_membership_interval(struct device *dev, const char *val)
359 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_membership_interval",
363 static void system_bridge_set_other_querier_timeout(struct device *dev, const char *val)
365 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier_interval",
369 static void system_bridge_set_startup_query_interval(struct device *dev, const char *val)
371 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_startup_query_interval",
375 static int system_get_sysctl(const char *path, char *buf, const size_t buf_sz)
377 int fd = -1, ret = -1;
379 fd = open(path, O_RDONLY);
383 ssize_t len = read(fd, buf, buf_sz - 1);
397 system_get_dev_sysctl(const char *path, const char *device, char *buf, const size_t buf_sz)
399 snprintf(dev_buf, sizeof(dev_buf), path, device);
400 return system_get_sysctl(dev_buf, buf, buf_sz);
403 static int system_get_disable_ipv6(struct device *dev, char *buf, const size_t buf_sz)
405 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6",
406 dev->ifname, buf, buf_sz);
409 static int system_get_rpfilter(struct device *dev, char *buf, const size_t buf_sz)
411 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter",
412 dev->ifname, buf, buf_sz);
415 static int system_get_acceptlocal(struct device *dev, char *buf, const size_t buf_sz)
417 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local",
418 dev->ifname, buf, buf_sz);
421 static int system_get_igmpversion(struct device *dev, char *buf, const size_t buf_sz)
423 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version",
424 dev->ifname, buf, buf_sz);
427 static int system_get_mldversion(struct device *dev, char *buf, const size_t buf_sz)
429 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version",
430 dev->ifname, buf, buf_sz);
433 static int system_get_neigh4reachabletime(struct device *dev, char *buf, const size_t buf_sz)
435 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms",
436 dev->ifname, buf, buf_sz);
439 static int system_get_neigh6reachabletime(struct device *dev, char *buf, const size_t buf_sz)
441 return system_get_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms",
442 dev->ifname, buf, buf_sz);
445 static int system_get_dadtransmits(struct device *dev, char *buf, const size_t buf_sz)
447 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits",
448 dev->ifname, buf, buf_sz);
451 // Evaluate netlink messages
452 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
454 struct nlmsghdr *nh = nlmsg_hdr(msg);
455 struct nlattr *nla[__IFLA_MAX];
459 if (nh->nlmsg_type != RTM_NEWLINK)
462 nlmsg_parse(nh, sizeof(struct ifinfomsg), nla, __IFLA_MAX - 1, NULL);
463 if (!nla[IFLA_IFNAME])
466 struct device *dev = device_get(nla_data(nla[IFLA_IFNAME]), false);
470 if (!system_get_dev_sysctl("/sys/class/net/%s/carrier", dev->ifname, buf, sizeof(buf)))
471 link_state = strtoul(buf, NULL, 0);
473 device_set_link(dev, link_state ? true : false);
480 handle_hotplug_msg(char *data, int size)
482 const char *subsystem = NULL, *interface = NULL;
483 char *cur, *end, *sep;
488 if (!strncmp(data, "add@", 4))
490 else if (!strncmp(data, "remove@", 7))
495 skip = strlen(data) + 1;
498 for (cur = data + skip; cur < end; cur += skip) {
499 skip = strlen(cur) + 1;
501 sep = strchr(cur, '=');
506 if (!strcmp(cur, "INTERFACE"))
508 else if (!strcmp(cur, "SUBSYSTEM")) {
510 if (strcmp(subsystem, "net") != 0)
513 if (subsystem && interface)
519 dev = device_get(interface, false);
523 if (dev->type != &simple_device_type)
526 if (add && system_if_force_external(dev->ifname))
529 device_set_present(dev, add);
533 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
535 struct event_socket *ev = container_of(u, struct event_socket, uloop);
536 struct sockaddr_nl nla;
537 unsigned char *buf = NULL;
540 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
542 handle_hotplug_msg((char *) buf, size);
548 static int system_rtnl_call(struct nl_msg *msg)
552 ret = nl_send_auto_complete(sock_rtnl, msg);
558 return nl_wait_for_ack(sock_rtnl);
561 int system_bridge_delbr(struct device *bridge)
563 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
566 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
570 memset(&ifr, 0, sizeof(ifr));
572 ifr.ifr_ifindex = dev->ifindex;
575 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
576 return ioctl(sock_ioctl, cmd, &ifr);
579 static bool system_is_bridge(const char *name, char *buf, int buflen)
583 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
584 if (stat(buf, &st) < 0)
590 static char *system_get_bridge(const char *name, char *buf, int buflen)
596 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
597 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
601 len = readlink(gl.gl_pathv[0], buf, buflen);
609 path = strrchr(buf, '/');
617 system_bridge_set_wireless(struct device *bridge, struct device *dev)
619 bool mcast_to_ucast = dev->wireless_ap;
622 if (bridge->settings.flags & DEV_OPT_MULTICAST_TO_UNICAST &&
623 !bridge->settings.multicast_to_unicast)
624 mcast_to_ucast = false;
626 if (!mcast_to_ucast || dev->wireless_isolate)
629 system_bridge_set_multicast_to_unicast(dev, mcast_to_ucast ? "1" : "0");
630 system_bridge_set_hairpin_mode(dev, hairpin ? "1" : "0");
633 int system_bridge_addif(struct device *bridge, struct device *dev)
639 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
640 if (!oldbr || strcmp(oldbr, bridge->ifname) != 0)
641 ret = system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
644 system_bridge_set_wireless(bridge, dev);
646 if (dev->settings.flags & DEV_OPT_MULTICAST_ROUTER) {
647 snprintf(buf, sizeof(buf), "%i", dev->settings.multicast_router);
648 system_bridge_set_multicast_router(dev, buf, false);
654 int system_bridge_delif(struct device *bridge, struct device *dev)
656 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
659 int system_if_resolve(struct device *dev)
662 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
663 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
664 return ifr.ifr_ifindex;
669 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
673 memset(&ifr, 0, sizeof(ifr));
674 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
675 ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
676 ifr.ifr_flags |= add;
677 ifr.ifr_flags &= ~rem;
678 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
690 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
692 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
694 return ifa->ifa_index == ifindex;
697 static bool check_route(struct nlmsghdr *hdr, int ifindex)
699 struct rtmsg *r = NLMSG_DATA(hdr);
700 struct nlattr *tb[__RTA_MAX];
702 if (r->rtm_protocol == RTPROT_KERNEL &&
703 r->rtm_family == AF_INET6)
706 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
710 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
713 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
718 static int cb_clear_event(struct nl_msg *msg, void *arg)
720 struct clear_data *clr = arg;
721 struct nlmsghdr *hdr = nlmsg_hdr(msg);
722 bool (*cb)(struct nlmsghdr *, int ifindex);
728 if (hdr->nlmsg_type != RTM_NEWADDR)
735 if (hdr->nlmsg_type != RTM_NEWROUTE)
742 if (hdr->nlmsg_type != RTM_NEWRULE)
751 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
754 if (type == RTM_DELRULE)
755 D(SYSTEM, "Remove a rule\n");
757 D(SYSTEM, "Remove %s from device %s\n",
758 type == RTM_DELADDR ? "an address" : "a route",
760 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
761 hdr = nlmsg_hdr(clr->msg);
762 hdr->nlmsg_type = type;
763 hdr->nlmsg_flags = NLM_F_REQUEST;
765 nl_socket_disable_auto_ack(sock_rtnl);
766 nl_send_auto_complete(sock_rtnl, clr->msg);
767 nl_socket_enable_auto_ack(sock_rtnl);
773 cb_finish_event(struct nl_msg *msg, void *arg)
781 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
784 *pending = err->error;
789 system_if_clear_entries(struct device *dev, int type, int af)
791 struct clear_data clr;
792 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
795 .rtm_flags = RTM_F_CLONED,
797 int flags = NLM_F_DUMP;
806 clr.size = sizeof(struct rtgenmsg);
809 clr.size = sizeof(struct rtmsg);
818 clr.msg = nlmsg_alloc_simple(type, flags);
822 nlmsg_append(clr.msg, &rtm, clr.size, 0);
823 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
824 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
825 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
827 nl_send_auto_complete(sock_rtnl, clr.msg);
829 nl_recvmsgs(sock_rtnl, cb);
837 * Clear bridge (membership) state and bring down device
839 void system_if_clear_state(struct device *dev)
841 static char buf[256];
844 device_set_ifindex(dev, system_if_resolve(dev));
845 if (dev->external || !dev->ifindex)
848 system_if_flags(dev->ifname, 0, IFF_UP);
850 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
851 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
852 system_bridge_delbr(dev);
856 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
858 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
859 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
862 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
863 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
864 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
865 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
866 system_set_disable_ipv6(dev, "0");
869 static inline unsigned long
870 sec_to_jiffies(int val)
872 return (unsigned long) val * 100;
875 static void system_bridge_conf_multicast_deps(struct device *bridge,
876 struct bridge_config *cfg,
882 if (cfg->flags & BRIDGE_OPT_ROBUSTNESS ||
883 cfg->flags & BRIDGE_OPT_QUERY_INTERVAL ||
884 cfg->flags & BRIDGE_OPT_QUERY_RESPONSE_INTERVAL) {
885 val = cfg->robustness * cfg->query_interval +
886 cfg->query_response_interval;
888 snprintf(buf, buf_len, "%i", val);
889 system_bridge_set_membership_interval(bridge, buf);
891 val = cfg->robustness * cfg->query_interval +
892 cfg->query_response_interval / 2;
894 snprintf(buf, buf_len, "%i", val);
895 system_bridge_set_other_querier_timeout(bridge, buf);
898 if (cfg->flags & BRIDGE_OPT_QUERY_INTERVAL) {
899 val = cfg->query_interval / 4;
901 snprintf(buf, buf_len, "%i", val);
902 system_bridge_set_startup_query_interval(bridge, buf);
906 static void system_bridge_conf_multicast(struct device *bridge,
907 struct bridge_config *cfg,
911 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
912 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
914 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier",
915 bridge->ifname, cfg->multicast_querier ? "1" : "0");
917 snprintf(buf, buf_len, "%i", cfg->hash_max);
918 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/hash_max",
919 bridge->ifname, buf);
921 if (bridge->settings.flags & DEV_OPT_MULTICAST_ROUTER) {
922 snprintf(buf, buf_len, "%i", bridge->settings.multicast_router);
923 system_bridge_set_multicast_router(bridge, buf, true);
926 if (cfg->flags & BRIDGE_OPT_ROBUSTNESS) {
927 snprintf(buf, buf_len, "%i", cfg->robustness);
928 system_bridge_set_robustness(bridge, buf);
931 if (cfg->flags & BRIDGE_OPT_QUERY_INTERVAL) {
932 snprintf(buf, buf_len, "%i", cfg->query_interval);
933 system_bridge_set_query_interval(bridge, buf);
936 if (cfg->flags & BRIDGE_OPT_QUERY_RESPONSE_INTERVAL) {
937 snprintf(buf, buf_len, "%i", cfg->query_response_interval);
938 system_bridge_set_query_response_interval(bridge, buf);
941 if (cfg->flags & BRIDGE_OPT_LAST_MEMBER_INTERVAL) {
942 snprintf(buf, buf_len, "%i", cfg->last_member_interval);
943 system_bridge_set_last_member_interval(bridge, buf);
946 system_bridge_conf_multicast_deps(bridge, cfg, buf, buf_len);
949 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
952 unsigned long args[4] = {};
954 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
957 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
958 args[1] = !!cfg->stp;
959 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
961 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
962 args[1] = sec_to_jiffies(cfg->forward_delay);
963 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
965 system_bridge_conf_multicast(bridge, cfg, buf, sizeof(buf));
967 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
968 args[1] = cfg->priority;
969 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
971 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
972 args[0] = BRCTL_SET_AGEING_TIME;
973 args[1] = sec_to_jiffies(cfg->ageing_time);
974 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
977 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
978 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
979 args[1] = sec_to_jiffies(cfg->hello_time);
980 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
983 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
984 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
985 args[1] = sec_to_jiffies(cfg->max_age);
986 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
992 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
995 struct nlattr *linkinfo, *data;
996 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
998 static const struct {
1000 enum macvlan_mode val;
1002 { "private", MACVLAN_MODE_PRIVATE },
1003 { "vepa", MACVLAN_MODE_VEPA },
1004 { "bridge", MACVLAN_MODE_BRIDGE },
1005 { "passthru", MACVLAN_MODE_PASSTHRU },
1008 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1013 nlmsg_append(msg, &iim, sizeof(iim), 0);
1015 if (cfg->flags & MACVLAN_OPT_MACADDR)
1016 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
1017 nla_put_string(msg, IFLA_IFNAME, macvlan->ifname);
1018 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
1020 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1021 goto nla_put_failure;
1023 nla_put_string(msg, IFLA_INFO_KIND, "macvlan");
1025 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1026 goto nla_put_failure;
1029 for (i = 0; i < ARRAY_SIZE(modes); i++) {
1030 if (strcmp(cfg->mode, modes[i].name) != 0)
1033 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
1038 nla_nest_end(msg, data);
1039 nla_nest_end(msg, linkinfo);
1041 rv = system_rtnl_call(msg);
1043 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
1052 static int system_link_del(const char *ifname)
1055 struct ifinfomsg iim = {
1056 .ifi_family = AF_UNSPEC,
1060 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
1065 nlmsg_append(msg, &iim, sizeof(iim), 0);
1066 nla_put_string(msg, IFLA_IFNAME, ifname);
1067 return system_rtnl_call(msg);
1070 int system_macvlan_del(struct device *macvlan)
1072 return system_link_del(macvlan->ifname);
1075 static int system_vlan(struct device *dev, int id)
1077 struct vlan_ioctl_args ifr = {
1078 .cmd = SET_VLAN_NAME_TYPE_CMD,
1079 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
1082 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
1085 ifr.cmd = DEL_VLAN_CMD;
1088 ifr.cmd = ADD_VLAN_CMD;
1091 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
1092 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
1095 int system_vlan_add(struct device *dev, int id)
1097 return system_vlan(dev, id);
1100 int system_vlan_del(struct device *dev)
1102 return system_vlan(dev, -1);
1105 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
1108 struct nlattr *linkinfo, *data;
1109 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
1112 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1117 nlmsg_append(msg, &iim, sizeof(iim), 0);
1118 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
1119 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
1121 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1122 goto nla_put_failure;
1124 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
1126 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1127 goto nla_put_failure;
1129 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
1131 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
1132 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
1134 if(cfg->proto == VLAN_PROTO_8021AD)
1135 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);
1138 nla_nest_end(msg, data);
1139 nla_nest_end(msg, linkinfo);
1141 rv = system_rtnl_call(msg);
1143 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
1152 int system_vlandev_del(struct device *vlandev)
1154 return system_link_del(vlandev->ifname);
1158 system_if_get_settings(struct device *dev, struct device_settings *s)
1163 memset(&ifr, 0, sizeof(ifr));
1164 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1166 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
1167 s->mtu = ifr.ifr_mtu;
1168 s->flags |= DEV_OPT_MTU;
1171 s->mtu6 = system_update_ipv6_mtu(dev, 0);
1173 s->flags |= DEV_OPT_MTU6;
1175 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
1176 s->txqueuelen = ifr.ifr_qlen;
1177 s->flags |= DEV_OPT_TXQUEUELEN;
1180 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
1181 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
1182 s->flags |= DEV_OPT_MACADDR;
1185 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
1186 s->ipv6 = !strtoul(buf, NULL, 0);
1187 s->flags |= DEV_OPT_IPV6;
1190 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
1191 s->promisc = ifr.ifr_flags & IFF_PROMISC;
1192 s->flags |= DEV_OPT_PROMISC;
1194 s->multicast = ifr.ifr_flags & IFF_MULTICAST;
1195 s->flags |= DEV_OPT_MULTICAST;
1198 if (!system_get_rpfilter(dev, buf, sizeof(buf))) {
1199 s->rpfilter = strtoul(buf, NULL, 0);
1200 s->flags |= DEV_OPT_RPFILTER;
1203 if (!system_get_acceptlocal(dev, buf, sizeof(buf))) {
1204 s->acceptlocal = strtoul(buf, NULL, 0);
1205 s->flags |= DEV_OPT_ACCEPTLOCAL;
1208 if (!system_get_igmpversion(dev, buf, sizeof(buf))) {
1209 s->igmpversion = strtoul(buf, NULL, 0);
1210 s->flags |= DEV_OPT_IGMPVERSION;
1213 if (!system_get_mldversion(dev, buf, sizeof(buf))) {
1214 s->mldversion = strtoul(buf, NULL, 0);
1215 s->flags |= DEV_OPT_MLDVERSION;
1218 if (!system_get_neigh4reachabletime(dev, buf, sizeof(buf))) {
1219 s->neigh4reachabletime = strtoul(buf, NULL, 0);
1220 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1223 if (!system_get_neigh6reachabletime(dev, buf, sizeof(buf))) {
1224 s->neigh6reachabletime = strtoul(buf, NULL, 0);
1225 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1228 if (!system_get_dadtransmits(dev, buf, sizeof(buf))) {
1229 s->dadtransmits = strtoul(buf, NULL, 0);
1230 s->flags |= DEV_OPT_DADTRANSMITS;
1235 system_if_set_rps_xps_val(const char *path, int val)
1241 if (glob(path, 0, NULL, &gl))
1244 snprintf(val_buf, sizeof(val_buf), "%x", val);
1245 for (i = 0; i < gl.gl_pathc; i++)
1246 system_set_sysctl(gl.gl_pathv[i], val_buf);
1252 system_if_apply_rps_xps(struct device *dev, struct device_settings *s)
1254 long n_cpus = sysconf(_SC_NPROCESSORS_ONLN);
1260 val = (1 << n_cpus) - 1;
1261 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/rps_cpus", dev->ifname);
1262 system_if_set_rps_xps_val(dev_buf, s->rps ? val : 0);
1264 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/xps_cpus", dev->ifname);
1265 system_if_set_rps_xps_val(dev_buf, s->xps ? val : 0);
1269 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
1274 memset(&ifr, 0, sizeof(ifr));
1275 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1276 if (s->flags & DEV_OPT_MTU & apply_mask) {
1277 ifr.ifr_mtu = s->mtu;
1278 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
1279 s->flags &= ~DEV_OPT_MTU;
1281 if (s->flags & DEV_OPT_MTU6 & apply_mask) {
1282 system_update_ipv6_mtu(dev, s->mtu6);
1284 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
1285 ifr.ifr_qlen = s->txqueuelen;
1286 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
1287 s->flags &= ~DEV_OPT_TXQUEUELEN;
1289 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
1290 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
1291 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
1292 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
1293 s->flags &= ~DEV_OPT_MACADDR;
1295 if (s->flags & DEV_OPT_IPV6 & apply_mask)
1296 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
1297 if (s->flags & DEV_OPT_PROMISC & apply_mask) {
1298 if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
1299 !s->promisc ? IFF_PROMISC : 0) < 0)
1300 s->flags &= ~DEV_OPT_PROMISC;
1302 if (s->flags & DEV_OPT_RPFILTER & apply_mask) {
1303 snprintf(buf, sizeof(buf), "%d", s->rpfilter);
1304 system_set_rpfilter(dev, buf);
1306 if (s->flags & DEV_OPT_ACCEPTLOCAL & apply_mask)
1307 system_set_acceptlocal(dev, s->acceptlocal ? "1" : "0");
1308 if (s->flags & DEV_OPT_IGMPVERSION & apply_mask) {
1309 snprintf(buf, sizeof(buf), "%d", s->igmpversion);
1310 system_set_igmpversion(dev, buf);
1312 if (s->flags & DEV_OPT_MLDVERSION & apply_mask) {
1313 snprintf(buf, sizeof(buf), "%d", s->mldversion);
1314 system_set_mldversion(dev, buf);
1316 if (s->flags & DEV_OPT_NEIGHREACHABLETIME & apply_mask) {
1317 snprintf(buf, sizeof(buf), "%d", s->neigh4reachabletime);
1318 system_set_neigh4reachabletime(dev, buf);
1319 snprintf(buf, sizeof(buf), "%d", s->neigh6reachabletime);
1320 system_set_neigh6reachabletime(dev, buf);
1322 if (s->flags & DEV_OPT_DADTRANSMITS & apply_mask) {
1323 snprintf(buf, sizeof(buf), "%d", s->dadtransmits);
1324 system_set_dadtransmits(dev, buf);
1326 if (s->flags & DEV_OPT_MULTICAST & apply_mask) {
1327 if (system_if_flags(dev->ifname, s->multicast ? IFF_MULTICAST : 0,
1328 !s->multicast ? IFF_MULTICAST : 0) < 0)
1329 s->flags &= ~DEV_OPT_MULTICAST;
1332 system_if_apply_rps_xps(dev, s);
1335 int system_if_up(struct device *dev)
1337 system_if_get_settings(dev, &dev->orig_settings);
1338 /* Only keep orig settings based on what needs to be set */
1339 dev->orig_settings.valid_flags = dev->orig_settings.flags;
1340 dev->orig_settings.flags &= dev->settings.flags;
1341 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
1342 return system_if_flags(dev->ifname, IFF_UP, 0);
1345 int system_if_down(struct device *dev)
1347 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
1348 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
1352 struct if_check_data {
1358 #ifndef IFF_LOWER_UP
1359 #define IFF_LOWER_UP 0x10000
1362 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1364 struct nlmsghdr *nh = nlmsg_hdr(msg);
1365 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1366 struct if_check_data *chk = (struct if_check_data *)arg;
1368 if (nh->nlmsg_type != RTM_NEWLINK)
1371 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1372 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1377 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1379 struct if_check_data *chk = (struct if_check_data *)arg;
1384 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1386 struct if_check_data *chk = (struct if_check_data *)arg;
1388 device_set_present(chk->dev, false);
1389 device_set_link(chk->dev, false);
1390 chk->pending = err->error;
1395 int system_if_check(struct device *dev)
1397 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1399 struct ifinfomsg ifi = {
1400 .ifi_family = AF_UNSPEC,
1403 struct if_check_data chk = {
1409 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1413 if (nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1414 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1417 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1418 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1419 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1421 nl_send_auto_complete(sock_rtnl, msg);
1422 while (chk.pending > 0)
1423 nl_recvmsgs(sock_rtnl, cb);
1435 system_if_get_parent(struct device *dev)
1437 char buf[64], *devname;
1438 int ifindex, iflink, len;
1441 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1442 f = fopen(buf, "r");
1446 len = fread(buf, 1, sizeof(buf) - 1, f);
1453 iflink = strtoul(buf, NULL, 0);
1454 ifindex = system_if_resolve(dev);
1455 if (!iflink || iflink == ifindex)
1458 devname = if_indextoname(iflink, buf);
1462 return device_get(devname, true);
1466 read_string_file(int dir_fd, const char *file, char *buf, int len)
1472 fd = openat(dir_fd, file, O_RDONLY);
1477 len = read(fd, buf, len - 1);
1481 } else if (len > 0) {
1484 c = strchr(buf, '\n');
1497 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1502 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1504 *val = strtoull(buf, NULL, 0);
1509 /* Assume advertised flags == supported flags */
1510 static const struct {
1513 } ethtool_link_modes[] = {
1514 { ADVERTISED_10baseT_Half, "10H" },
1515 { ADVERTISED_10baseT_Full, "10F" },
1516 { ADVERTISED_100baseT_Half, "100H" },
1517 { ADVERTISED_100baseT_Full, "100F" },
1518 { ADVERTISED_1000baseT_Half, "1000H" },
1519 { ADVERTISED_1000baseT_Full, "1000F" },
1522 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1525 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1526 if (mask & ethtool_link_modes[i].mask)
1527 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1532 system_if_force_external(const char *ifname)
1537 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1538 return stat(buf, &s) == 0;
1542 system_if_dump_info(struct device *dev, struct blob_buf *b)
1544 struct ethtool_cmd ecmd;
1550 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
1551 dir_fd = open(buf, O_DIRECTORY);
1553 memset(&ecmd, 0, sizeof(ecmd));
1554 memset(&ifr, 0, sizeof(ifr));
1555 strcpy(ifr.ifr_name, dev->ifname);
1556 ifr.ifr_data = (caddr_t) &ecmd;
1557 ecmd.cmd = ETHTOOL_GSET;
1559 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1560 c = blobmsg_open_array(b, "link-advertising");
1561 system_add_link_modes(b, ecmd.advertising);
1562 blobmsg_close_array(b, c);
1564 c = blobmsg_open_array(b, "link-supported");
1565 system_add_link_modes(b, ecmd.supported);
1566 blobmsg_close_array(b, c);
1568 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1569 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1570 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1571 blobmsg_add_string_buffer(b);
1579 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1581 const char *const counters[] = {
1582 "collisions", "rx_frame_errors", "tx_compressed",
1583 "multicast", "rx_length_errors", "tx_dropped",
1584 "rx_bytes", "rx_missed_errors", "tx_errors",
1585 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1586 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1587 "rx_dropped", "tx_aborted_errors", "tx_packets",
1588 "rx_errors", "tx_bytes", "tx_window_errors",
1589 "rx_fifo_errors", "tx_carrier_errors",
1596 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1597 stats_dir = open(buf, O_DIRECTORY);
1601 for (i = 0; i < ARRAY_SIZE(counters); i++)
1602 if (read_uint64_file(stats_dir, counters[i], &val))
1603 blobmsg_add_u64(b, counters[i], val);
1609 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1611 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1612 int alen = v4 ? 4 : 16;
1613 unsigned int flags = 0;
1614 struct ifaddrmsg ifa = {
1615 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1616 .ifa_prefixlen = addr->mask,
1617 .ifa_index = dev->ifindex,
1621 if (cmd == RTM_NEWADDR)
1622 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1624 msg = nlmsg_alloc_simple(cmd, flags);
1628 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1629 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1631 if (addr->broadcast)
1632 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1633 if (addr->point_to_point)
1634 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1636 time_t now = system_get_rtime();
1637 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1639 if (addr->preferred_until) {
1640 int64_t preferred = addr->preferred_until - now;
1643 else if (preferred > UINT32_MAX)
1644 preferred = UINT32_MAX;
1646 cinfo.ifa_prefered = preferred;
1649 if (addr->valid_until) {
1650 int64_t valid = addr->valid_until - now;
1655 else if (valid > UINT32_MAX)
1658 cinfo.ifa_valid = valid;
1661 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1663 if (cmd == RTM_NEWADDR && (addr->flags & DEVADDR_OFFLINK))
1664 nla_put_u32(msg, IFA_FLAGS, IFA_F_NOPREFIXROUTE);
1667 return system_rtnl_call(msg);
1670 int system_add_address(struct device *dev, struct device_addr *addr)
1672 return system_addr(dev, addr, RTM_NEWADDR);
1675 int system_del_address(struct device *dev, struct device_addr *addr)
1677 return system_addr(dev, addr, RTM_DELADDR);
1680 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1682 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1684 unsigned int flags = 0;
1687 have_gw = !!route->nexthop.in.s_addr;
1689 have_gw = route->nexthop.in6.s6_addr32[0] ||
1690 route->nexthop.in6.s6_addr32[1] ||
1691 route->nexthop.in6.s6_addr32[2] ||
1692 route->nexthop.in6.s6_addr32[3];
1694 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1695 ? route->table : RT_TABLE_MAIN;
1697 struct rtmsg rtm = {
1698 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1699 .rtm_dst_len = route->mask,
1700 .rtm_src_len = route->sourcemask,
1701 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1702 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
1703 .rtm_scope = RT_SCOPE_NOWHERE,
1704 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1705 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1709 if (cmd == RTM_NEWROUTE) {
1710 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1712 if (!dev) { // Add null-route
1713 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1714 rtm.rtm_type = RTN_UNREACHABLE;
1717 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1720 if (route->flags & DEVROUTE_TYPE) {
1721 rtm.rtm_type = route->type;
1722 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
1723 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
1724 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
1725 rtm.rtm_table = RT_TABLE_LOCAL;
1728 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT) {
1729 rtm.rtm_scope = RT_SCOPE_HOST;
1730 } else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
1731 rtm.rtm_type == RTN_ANYCAST) {
1732 rtm.rtm_scope = RT_SCOPE_LINK;
1733 } else if (rtm.rtm_type == RTN_BLACKHOLE || rtm.rtm_type == RTN_UNREACHABLE ||
1734 rtm.rtm_type == RTN_PROHIBIT || rtm.rtm_type == RTN_FAILED_POLICY) {
1735 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1740 msg = nlmsg_alloc_simple(cmd, flags);
1744 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1747 nla_put(msg, RTA_DST, alen, &route->addr);
1749 if (route->sourcemask) {
1750 if (rtm.rtm_family == AF_INET)
1751 nla_put(msg, RTA_PREFSRC, alen, &route->source);
1753 nla_put(msg, RTA_SRC, alen, &route->source);
1756 if (route->metric > 0)
1757 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1760 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1763 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1766 nla_put_u32(msg, RTA_TABLE, table);
1768 if (route->flags & DEVROUTE_MTU) {
1769 struct nlattr *metrics;
1771 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1772 goto nla_put_failure;
1774 nla_put_u32(msg, RTAX_MTU, route->mtu);
1776 nla_nest_end(msg, metrics);
1779 return system_rtnl_call(msg);
1786 int system_add_route(struct device *dev, struct device_route *route)
1788 return system_rt(dev, route, RTM_NEWROUTE);
1791 int system_del_route(struct device *dev, struct device_route *route)
1793 return system_rt(dev, route, RTM_DELROUTE);
1796 int system_flush_routes(void)
1798 const char *names[] = {
1799 "/proc/sys/net/ipv4/route/flush",
1800 "/proc/sys/net/ipv6/route/flush"
1804 for (i = 0; i < ARRAY_SIZE(names); i++) {
1805 fd = open(names[i], O_WRONLY);
1809 if (write(fd, "-1", 2)) {}
1815 bool system_resolve_rt_type(const char *type, unsigned int *id)
1817 return system_rtn_aton(type, id);
1820 bool system_resolve_rt_table(const char *name, unsigned int *id)
1824 unsigned int n, table = RT_TABLE_UNSPEC;
1826 /* first try to parse table as number */
1827 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1830 /* handle well known aliases */
1831 else if (!strcmp(name, "default"))
1832 table = RT_TABLE_DEFAULT;
1833 else if (!strcmp(name, "main"))
1834 table = RT_TABLE_MAIN;
1835 else if (!strcmp(name, "local"))
1836 table = RT_TABLE_LOCAL;
1838 /* try to look up name in /etc/iproute2/rt_tables */
1839 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1841 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1843 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1846 n = strtoul(e, NULL, 10);
1847 e = strtok(NULL, " \t\n");
1849 if (e && !strcmp(e, name))
1859 if (table == RT_TABLE_UNSPEC)
1866 bool system_is_default_rt_table(unsigned int id)
1868 return (id == RT_TABLE_MAIN);
1871 bool system_resolve_rpfilter(const char *filter, unsigned int *id)
1876 if (!strcmp(filter, "strict"))
1878 else if (!strcmp(filter, "loose"))
1881 n = strtoul(filter, &e, 0);
1882 if (*e || e == filter || n > 2)
1890 static int system_iprule(struct iprule *rule, int cmd)
1892 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1895 struct rtmsg rtm = {
1896 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1897 .rtm_protocol = RTPROT_STATIC,
1898 .rtm_scope = RT_SCOPE_UNIVERSE,
1899 .rtm_table = RT_TABLE_UNSPEC,
1900 .rtm_type = RTN_UNSPEC,
1904 if (cmd == RTM_NEWRULE)
1905 rtm.rtm_type = RTN_UNICAST;
1908 rtm.rtm_flags |= FIB_RULE_INVERT;
1910 if (rule->flags & IPRULE_SRC)
1911 rtm.rtm_src_len = rule->src_mask;
1913 if (rule->flags & IPRULE_DEST)
1914 rtm.rtm_dst_len = rule->dest_mask;
1916 if (rule->flags & IPRULE_TOS)
1917 rtm.rtm_tos = rule->tos;
1919 if (rule->flags & IPRULE_LOOKUP) {
1920 if (rule->lookup < 256)
1921 rtm.rtm_table = rule->lookup;
1924 if (rule->flags & IPRULE_ACTION)
1925 rtm.rtm_type = rule->action;
1926 else if (rule->flags & IPRULE_GOTO)
1927 rtm.rtm_type = FR_ACT_GOTO;
1928 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1929 rtm.rtm_type = FR_ACT_NOP;
1931 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1936 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1938 if (rule->flags & IPRULE_IN)
1939 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1941 if (rule->flags & IPRULE_OUT)
1942 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1944 if (rule->flags & IPRULE_SRC)
1945 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1947 if (rule->flags & IPRULE_DEST)
1948 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1950 if (rule->flags & IPRULE_PRIORITY)
1951 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1952 else if (cmd == RTM_NEWRULE)
1953 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1955 if (rule->flags & IPRULE_FWMARK)
1956 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1958 if (rule->flags & IPRULE_FWMASK)
1959 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1961 if (rule->flags & IPRULE_LOOKUP) {
1962 if (rule->lookup >= 256)
1963 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1966 if (rule->flags & IPRULE_GOTO)
1967 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1969 return system_rtnl_call(msg);
1972 int system_add_iprule(struct iprule *rule)
1974 return system_iprule(rule, RTM_NEWRULE);
1977 int system_del_iprule(struct iprule *rule)
1979 return system_iprule(rule, RTM_DELRULE);
1982 int system_flush_iprules(void)
1987 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1988 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1990 memset(&rule, 0, sizeof(rule));
1993 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1996 rule.lookup = RT_TABLE_LOCAL;
1997 rv |= system_iprule(&rule, RTM_NEWRULE);
1999 rule.priority = 32766;
2000 rule.lookup = RT_TABLE_MAIN;
2001 rv |= system_iprule(&rule, RTM_NEWRULE);
2003 rule.priority = 32767;
2004 rule.lookup = RT_TABLE_DEFAULT;
2005 rv |= system_iprule(&rule, RTM_NEWRULE);
2008 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2011 rule.lookup = RT_TABLE_LOCAL;
2012 rv |= system_iprule(&rule, RTM_NEWRULE);
2014 rule.priority = 32766;
2015 rule.lookup = RT_TABLE_MAIN;
2016 rv |= system_iprule(&rule, RTM_NEWRULE);
2021 bool system_resolve_iprule_action(const char *action, unsigned int *id)
2023 return system_rtn_aton(action, id);
2026 time_t system_get_rtime(void)
2031 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
2034 if (gettimeofday(&tv, NULL) == 0)
2041 #define IP_DF 0x4000
2044 static int tunnel_ioctl(const char *name, int cmd, void *p)
2048 memset(&ifr, 0, sizeof(ifr));
2049 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
2050 ifr.ifr_ifru.ifru_data = p;
2051 return ioctl(sock_ioctl, cmd, &ifr);
2054 #ifdef IFLA_IPTUN_MAX
2055 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
2056 static int system_add_gre_tunnel(const char *name, const char *kind,
2057 const unsigned int link, struct blob_attr **tb, bool v6)
2060 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2061 struct blob_attr *cur;
2062 uint32_t ikey = 0, okey = 0, flags = 0, flowinfo = 0;
2063 uint16_t iflags = 0, oflags = 0;
2065 int ret = 0, ttl = 64;
2067 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2071 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2072 nla_put_string(nlm, IFLA_IFNAME, name);
2074 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2080 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2081 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2088 nla_put_u32(nlm, IFLA_GRE_LINK, link);
2090 if ((cur = tb[TUNNEL_ATTR_TTL]))
2091 ttl = blobmsg_get_u32(cur);
2093 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
2095 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2096 char *str = blobmsg_get_string(cur);
2097 if (strcmp(str, "inherit")) {
2100 if (!system_tos_aton(str, &uval)) {
2106 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
2111 flags |= IP6_TNL_F_USE_ORIG_TCLASS;
2117 if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) {
2118 uint8_t icsum, ocsum, iseqno, oseqno;
2119 if (sscanf(blobmsg_get_string(cur), "%u,%u,%hhu,%hhu,%hhu,%hhu",
2120 &ikey, &okey, &icsum, &ocsum, &iseqno, &oseqno) < 6) {
2145 struct in6_addr in6buf;
2146 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2147 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2151 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
2154 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2155 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2159 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
2161 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, 4);
2164 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
2167 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags);
2169 struct in_addr inbuf;
2172 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2173 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2177 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
2180 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2181 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2185 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
2187 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
2189 okey = inbuf.s_addr;
2194 ikey = inbuf.s_addr;
2200 if ((cur = tb[TUNNEL_ATTR_DF]))
2201 set_df = blobmsg_get_bool(cur);
2203 /* ttl !=0 and nopmtudisc are incompatible */
2204 if (ttl && !set_df) {
2209 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
2211 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
2215 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
2218 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
2221 nla_put_u32(nlm, IFLA_GRE_OKEY, okey);
2224 nla_put_u32(nlm, IFLA_GRE_IKEY, ikey);
2226 nla_nest_end(nlm, infodata);
2227 nla_nest_end(nlm, linkinfo);
2229 return system_rtnl_call(nlm);
2238 static int system_add_vti_tunnel(const char *name, const char *kind,
2239 const unsigned int link, struct blob_attr **tb, bool v6)
2242 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2243 struct blob_attr *cur;
2244 uint32_t ikey = 0, okey = 0;
2247 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2251 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2252 nla_put_string(nlm, IFLA_IFNAME, name);
2254 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2260 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2261 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2268 nla_put_u32(nlm, IFLA_VTI_LINK, link);
2270 if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) {
2271 if (sscanf(blobmsg_get_string(cur), "%u,%u",
2272 &ikey, &okey) < 2) {
2279 struct in6_addr in6buf;
2280 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2281 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2285 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(in6buf), &in6buf);
2288 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2289 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2293 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(in6buf), &in6buf);
2297 struct in_addr inbuf;
2299 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2300 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2304 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(inbuf), &inbuf);
2307 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2308 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2312 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(inbuf), &inbuf);
2318 nla_put_u32(nlm, IFLA_VTI_OKEY, htonl(okey));
2321 nla_put_u32(nlm, IFLA_VTI_IKEY, htonl(ikey));
2323 nla_nest_end(nlm, infodata);
2324 nla_nest_end(nlm, linkinfo);
2326 return system_rtnl_call(nlm);
2334 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
2336 struct blob_attr *cur;
2338 struct ip_tunnel_parm p = {
2347 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
2348 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
2351 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
2352 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
2355 if ((cur = tb[TUNNEL_ATTR_DF]))
2356 set_df = blobmsg_get_bool(cur);
2358 if ((cur = tb[TUNNEL_ATTR_TTL]))
2359 p.iph.ttl = blobmsg_get_u32(cur);
2361 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2362 char *str = blobmsg_get_string(cur);
2363 if (strcmp(str, "inherit")) {
2366 if (!system_tos_aton(str, &uval))
2374 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
2375 /* ttl !=0 and nopmtudisc are incompatible */
2376 if (p.iph.ttl && p.iph.frag_off == 0)
2379 strncpy(p.name, name, sizeof(p.name));
2381 switch (p.iph.protocol) {
2383 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
2385 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
2392 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
2394 struct blob_attr *cur;
2397 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2399 str = blobmsg_data(cur);
2401 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
2402 !strcmp(str, "greip6") || !strcmp(str, "gretapip6") ||
2403 !strcmp(str, "vtiip") || !strcmp(str, "vtiip6"))
2404 return system_link_del(name);
2406 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
2409 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
2411 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2413 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2414 blob_data(attr), blob_len(attr));
2416 return __system_del_ip_tunnel(name, tb);
2419 int system_update_ipv6_mtu(struct device *dev, int mtu)
2423 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
2426 int fd = open(buf, O_RDWR);
2429 ssize_t len = read(fd, buf, sizeof(buf) - 1);
2436 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) > 0)
2445 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
2447 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2448 struct blob_attr *cur;
2451 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2452 blob_data(attr), blob_len(attr));
2454 __system_del_ip_tunnel(name, tb);
2456 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2458 str = blobmsg_data(cur);
2460 unsigned int ttl = 0;
2461 if ((cur = tb[TUNNEL_ATTR_TTL])) {
2462 ttl = blobmsg_get_u32(cur);
2467 unsigned int link = 0;
2468 if ((cur = tb[TUNNEL_ATTR_LINK])) {
2469 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
2473 if (iface->l3_dev.dev)
2474 link = iface->l3_dev.dev->ifindex;
2477 if (!strcmp(str, "sit")) {
2478 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
2482 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
2484 struct ip_tunnel_6rd p6;
2486 memset(&p6, 0, sizeof(p6));
2488 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
2489 &p6.prefix, &mask) || mask > 128)
2491 p6.prefixlen = mask;
2493 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
2494 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
2495 &p6.relay_prefix, &mask) || mask > 32)
2497 p6.relay_prefixlen = mask;
2500 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
2501 __system_del_ip_tunnel(name, tb);
2506 #ifdef IFLA_IPTUN_MAX
2507 } else if (!strcmp(str, "ipip6")) {
2508 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2509 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2510 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2516 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2517 nla_put_string(nlm, IFLA_IFNAME, name);
2520 nla_put_u32(nlm, IFLA_LINK, link);
2522 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2527 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2528 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2535 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2537 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2538 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2539 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
2541 struct in6_addr in6buf;
2542 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2543 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2547 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2550 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2551 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2555 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2558 #ifdef IFLA_IPTUN_FMR_MAX
2559 if ((cur = tb[TUNNEL_ATTR_FMRS])) {
2560 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2562 struct blob_attr *fmr;
2563 unsigned rem, fmrcnt = 0;
2564 blobmsg_for_each_attr(fmr, cur, rem) {
2565 if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
2568 unsigned ip4len, ip6len, ealen, offset = 6;
2572 if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
2573 ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) {
2578 struct in6_addr ip6prefix;
2579 struct in_addr ip4prefix;
2580 if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
2581 inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) {
2586 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2588 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2589 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2590 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2591 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2592 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2593 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2595 nla_nest_end(nlm, rule);
2598 nla_nest_end(nlm, fmrs);
2602 nla_nest_end(nlm, infodata);
2603 nla_nest_end(nlm, linkinfo);
2605 return system_rtnl_call(nlm);
2609 } else if (!strcmp(str, "greip")) {
2610 return system_add_gre_tunnel(name, "gre", link, tb, false);
2611 } else if (!strcmp(str, "gretapip")) {
2612 return system_add_gre_tunnel(name, "gretap", link, tb, false);
2613 } else if (!strcmp(str, "greip6")) {
2614 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
2615 } else if (!strcmp(str, "gretapip6")) {
2616 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
2618 } else if (!strcmp(str, "vtiip")) {
2619 return system_add_vti_tunnel(name, "vti", link, tb, false);
2620 } else if (!strcmp(str, "vtiip6")) {
2621 return system_add_vti_tunnel(name, "vti6", link, tb, true);
2624 } else if (!strcmp(str, "ipip")) {
2625 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);