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>
7 * Copyright (C) 2017 Matthias Schiffer <mschiffer@universe-factory.net>
8 * Copyright (C) 2018 Hans Dedecker <dedeckeh@gmail.com>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
21 #include <sys/socket.h>
22 #include <sys/ioctl.h>
24 #include <sys/syscall.h>
27 #include <net/if_arp.h>
29 #include <arpa/inet.h>
30 #include <netinet/ether.h>
31 #include <netinet/in.h>
33 #include <linux/rtnetlink.h>
34 #include <linux/neighbour.h>
35 #include <linux/sockios.h>
37 #include <linux/if_addr.h>
38 #include <linux/if_link.h>
39 #include <linux/if_vlan.h>
40 #include <linux/if_bridge.h>
41 #include <linux/if_tunnel.h>
42 #include <linux/ip6_tunnel.h>
43 #include <linux/ethtool.h>
44 #include <linux/fib_rules.h>
45 #include <linux/veth.h>
46 #include <linux/version.h>
48 #ifndef RTN_FAILED_POLICY
49 #define RTN_FAILED_POLICY 12
52 #ifndef IFA_F_NOPREFIXROUTE
53 #define IFA_F_NOPREFIXROUTE 0x200
57 #define IFA_FLAGS (IFA_MULTICAST + 1)
66 #include <netlink/msg.h>
67 #include <netlink/attr.h>
68 #include <netlink/socket.h>
69 #include <libubox/uloop.h>
76 struct uloop_fd uloop;
81 static int sock_ioctl = -1;
82 static struct nl_sock *sock_rtnl = NULL;
84 static int cb_rtnl_event(struct nl_msg *msg, void *arg);
85 static void handle_hotplug_event(struct uloop_fd *u, unsigned int events);
86 static int system_add_proto_tunnel(const char *name, const uint8_t proto,
87 const unsigned int link, struct blob_attr **tb);
88 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb);
90 static char dev_buf[256];
93 handler_nl_event(struct uloop_fd *u, unsigned int events)
95 struct event_socket *ev = container_of(u, struct event_socket, uloop);
97 socklen_t errlen = sizeof(err);
100 nl_recvmsgs_default(ev->sock);
104 if (getsockopt(u->fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen))
109 /* Increase rx buffer size on netlink socket */
111 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
114 /* Request full dump since some info got dropped */
115 struct rtgenmsg msg = { .rtgen_family = AF_UNSPEC };
116 nl_send_simple(ev->sock, RTM_GETLINK, NLM_F_DUMP, &msg, sizeof(msg));
126 uloop_fd_delete(&ev->uloop);
130 static struct nl_sock *
131 create_socket(int protocol, int groups)
133 struct nl_sock *sock;
135 sock = nl_socket_alloc();
140 nl_join_groups(sock, groups);
142 if (nl_connect(sock, protocol)) {
143 nl_socket_free(sock);
151 create_raw_event_socket(struct event_socket *ev, int protocol, int groups,
152 uloop_fd_handler cb, int flags)
154 ev->sock = create_socket(protocol, groups);
158 ev->uloop.fd = nl_socket_get_fd(ev->sock);
160 if (uloop_fd_add(&ev->uloop, ULOOP_READ|flags))
167 create_event_socket(struct event_socket *ev, int protocol,
168 int (*cb)(struct nl_msg *msg, void *arg))
170 if (!create_raw_event_socket(ev, protocol, 0, handler_nl_event, ULOOP_ERROR_CB))
173 /* Install the valid custom callback handler */
174 nl_socket_modify_cb(ev->sock, NL_CB_VALID, NL_CB_CUSTOM, cb, NULL);
176 /* Disable sequence number checking on event sockets */
177 nl_socket_disable_seq_check(ev->sock);
179 /* Increase rx buffer size to 65K on event sockets */
181 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
188 create_hotplug_event_socket(struct event_socket *ev, int protocol,
189 void (*cb)(struct uloop_fd *u, unsigned int events))
191 if (!create_raw_event_socket(ev, protocol, 1, cb, ULOOP_ERROR_CB))
194 /* Increase rx buffer size to 65K on event sockets */
196 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
203 system_rtn_aton(const char *src, unsigned int *dst)
208 if (!strcmp(src, "local"))
210 else if (!strcmp(src, "nat"))
212 else if (!strcmp(src, "broadcast"))
214 else if (!strcmp(src, "anycast"))
216 else if (!strcmp(src, "multicast"))
218 else if (!strcmp(src, "prohibit"))
220 else if (!strcmp(src, "unreachable"))
222 else if (!strcmp(src, "blackhole"))
224 else if (!strcmp(src, "xresolve"))
226 else if (!strcmp(src, "unicast"))
228 else if (!strcmp(src, "throw"))
230 else if (!strcmp(src, "failed_policy"))
231 n = RTN_FAILED_POLICY;
233 n = strtoul(src, &e, 0);
234 if (!e || *e || e == src || n > 255)
243 system_tos_aton(const char *src, unsigned *dst)
247 *dst = strtoul(src, &e, 16);
248 if (e == src || *e || *dst > 255)
254 int system_init(void)
256 static struct event_socket rtnl_event;
257 static struct event_socket hotplug_event;
259 sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0);
260 system_fd_set_cloexec(sock_ioctl);
262 /* Prepare socket for routing / address control */
263 sock_rtnl = create_socket(NETLINK_ROUTE, 0);
267 if (!create_event_socket(&rtnl_event, NETLINK_ROUTE, cb_rtnl_event))
270 if (!create_hotplug_event_socket(&hotplug_event, NETLINK_KOBJECT_UEVENT,
271 handle_hotplug_event))
274 /* Receive network link events form kernel */
275 nl_socket_add_membership(rtnl_event.sock, RTNLGRP_LINK);
280 static void system_set_sysctl(const char *path, const char *val)
284 fd = open(path, O_WRONLY);
288 if (write(fd, val, strlen(val))) {}
292 static void system_set_dev_sysctl(const char *path, const char *device, const char *val)
294 snprintf(dev_buf, sizeof(dev_buf), path, device);
295 system_set_sysctl(dev_buf, val);
298 static void system_set_disable_ipv6(struct device *dev, const char *val)
300 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val);
303 static void system_set_rpfilter(struct device *dev, const char *val)
305 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter", dev->ifname, val);
308 static void system_set_acceptlocal(struct device *dev, const char *val)
310 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local", dev->ifname, val);
313 static void system_set_igmpversion(struct device *dev, const char *val)
315 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version", dev->ifname, val);
318 static void system_set_mldversion(struct device *dev, const char *val)
320 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version", dev->ifname, val);
323 static void system_set_neigh4reachabletime(struct device *dev, const char *val)
325 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms", dev->ifname, val);
328 static void system_set_neigh6reachabletime(struct device *dev, const char *val)
330 system_set_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms", dev->ifname, val);
333 static void system_set_neigh4gcstaletime(struct device *dev, const char *val)
335 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/gc_stale_time", dev->ifname, val);
338 static void system_set_neigh6gcstaletime(struct device *dev, const char *val)
340 system_set_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/gc_stale_time", dev->ifname, val);
343 static void system_set_neigh4locktime(struct device *dev, const char *val)
345 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/locktime", dev->ifname, val);
348 static void system_set_dadtransmits(struct device *dev, const char *val)
350 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits", dev->ifname, val);
353 static void system_bridge_set_multicast_to_unicast(struct device *dev, const char *val)
355 system_set_dev_sysctl("/sys/class/net/%s/brport/multicast_to_unicast", dev->ifname, val);
358 static void system_bridge_set_multicast_fast_leave(struct device *dev, const char *val)
360 system_set_dev_sysctl("/sys/class/net/%s/brport/multicast_fast_leave", dev->ifname, val);
363 static void system_bridge_set_hairpin_mode(struct device *dev, const char *val)
365 system_set_dev_sysctl("/sys/class/net/%s/brport/hairpin_mode", dev->ifname, val);
368 static void system_bridge_set_isolated(struct device *dev, const char *val)
370 system_set_dev_sysctl("/sys/class/net/%s/brport/isolated", dev->ifname, val);
373 static void system_bridge_set_multicast_router(struct device *dev, const char *val, bool bridge)
375 system_set_dev_sysctl(bridge ? "/sys/class/net/%s/bridge/multicast_router" :
376 "/sys/class/net/%s/brport/multicast_router",
380 static void system_bridge_set_robustness(struct device *dev, const char *val)
382 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_startup_query_count",
384 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_last_member_count",
388 static void system_bridge_set_query_interval(struct device *dev, const char *val)
390 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_query_interval",
394 static void system_bridge_set_query_response_interval(struct device *dev, const char *val)
396 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_query_response_interval",
400 static void system_bridge_set_last_member_interval(struct device *dev, const char *val)
402 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_last_member_interval",
406 static void system_bridge_set_membership_interval(struct device *dev, const char *val)
408 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_membership_interval",
412 static void system_bridge_set_other_querier_timeout(struct device *dev, const char *val)
414 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier_interval",
418 static void system_bridge_set_startup_query_interval(struct device *dev, const char *val)
420 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_startup_query_interval",
424 static void system_bridge_set_stp_state(struct device *dev, const char *val)
426 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/stp_state", dev->ifname, val);
429 static void system_bridge_set_forward_delay(struct device *dev, const char *val)
431 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/forward_delay", dev->ifname, val);
434 static void system_bridge_set_priority(struct device *dev, const char *val)
436 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/priority", dev->ifname, val);
439 static void system_bridge_set_ageing_time(struct device *dev, const char *val)
441 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/ageing_time", dev->ifname, val);
444 static void system_bridge_set_hello_time(struct device *dev, const char *val)
446 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/hello_time", dev->ifname, val);
449 static void system_bridge_set_max_age(struct device *dev, const char *val)
451 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/max_age", dev->ifname, val);
454 static void system_bridge_set_learning(struct device *dev, const char *val)
456 system_set_dev_sysctl("/sys/class/net/%s/brport/learning", dev->ifname, val);
459 static void system_bridge_set_unicast_flood(struct device *dev, const char *val)
461 system_set_dev_sysctl("/sys/class/net/%s/brport/unicast_flood", dev->ifname, val);
464 static void system_set_sendredirects(struct device *dev, const char *val)
466 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/send_redirects", dev->ifname, val);
469 static int system_get_sysctl(const char *path, char *buf, const size_t buf_sz)
471 int fd = -1, ret = -1;
473 fd = open(path, O_RDONLY);
477 ssize_t len = read(fd, buf, buf_sz - 1);
491 system_get_dev_sysctl(const char *path, const char *device, char *buf, const size_t buf_sz)
493 snprintf(dev_buf, sizeof(dev_buf), path, device);
494 return system_get_sysctl(dev_buf, buf, buf_sz);
497 static int system_get_disable_ipv6(struct device *dev, char *buf, const size_t buf_sz)
499 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6",
500 dev->ifname, buf, buf_sz);
503 static int system_get_rpfilter(struct device *dev, char *buf, const size_t buf_sz)
505 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter",
506 dev->ifname, buf, buf_sz);
509 static int system_get_acceptlocal(struct device *dev, char *buf, const size_t buf_sz)
511 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local",
512 dev->ifname, buf, buf_sz);
515 static int system_get_igmpversion(struct device *dev, char *buf, const size_t buf_sz)
517 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version",
518 dev->ifname, buf, buf_sz);
521 static int system_get_mldversion(struct device *dev, char *buf, const size_t buf_sz)
523 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version",
524 dev->ifname, buf, buf_sz);
527 static int system_get_neigh4reachabletime(struct device *dev, char *buf, const size_t buf_sz)
529 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms",
530 dev->ifname, buf, buf_sz);
533 static int system_get_neigh6reachabletime(struct device *dev, char *buf, const size_t buf_sz)
535 return system_get_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms",
536 dev->ifname, buf, buf_sz);
539 static int system_get_neigh4gcstaletime(struct device *dev, char *buf, const size_t buf_sz)
541 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/gc_stale_time",
542 dev->ifname, buf, buf_sz);
545 static int system_get_neigh6gcstaletime(struct device *dev, char *buf, const size_t buf_sz)
547 return system_get_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/gc_stale_time",
548 dev->ifname, buf, buf_sz);
551 static int system_get_neigh4locktime(struct device *dev, char *buf, const size_t buf_sz)
553 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/locktime",
554 dev->ifname, buf, buf_sz);
557 static int system_get_dadtransmits(struct device *dev, char *buf, const size_t buf_sz)
559 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits",
560 dev->ifname, buf, buf_sz);
563 static int system_get_sendredirects(struct device *dev, char *buf, const size_t buf_sz)
565 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/send_redirects",
566 dev->ifname, buf, buf_sz);
569 /* Evaluate netlink messages */
570 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
572 struct nlmsghdr *nh = nlmsg_hdr(msg);
573 struct nlattr *nla[__IFLA_MAX];
577 if (nh->nlmsg_type != RTM_NEWLINK)
580 nlmsg_parse(nh, sizeof(struct ifinfomsg), nla, __IFLA_MAX - 1, NULL);
581 if (!nla[IFLA_IFNAME])
584 struct device *dev = device_find(nla_data(nla[IFLA_IFNAME]));
588 if (!system_get_dev_sysctl("/sys/class/net/%s/carrier", dev->ifname, buf, sizeof(buf)))
589 link_state = strtoul(buf, NULL, 0);
591 device_set_link(dev, link_state ? true : false);
598 handle_hotplug_msg(char *data, int size)
600 const char *subsystem = NULL, *interface = NULL, *interface_old = NULL;
601 char *cur, *end, *sep;
604 bool add, move = false;
606 if (!strncmp(data, "add@", 4))
608 else if (!strncmp(data, "remove@", 7))
610 else if (!strncmp(data, "move@", 5)) {
617 skip = strlen(data) + 1;
620 for (cur = data + skip; cur < end; cur += skip) {
621 skip = strlen(cur) + 1;
623 sep = strchr(cur, '=');
628 if (!strcmp(cur, "INTERFACE"))
630 else if (!strcmp(cur, "SUBSYSTEM")) {
632 if (strcmp(subsystem, "net") != 0)
634 } else if (!strcmp(cur, "DEVPATH_OLD")) {
635 interface_old = strrchr(sep + 1, '/');
641 if (subsystem && interface) {
642 if (move && interface_old)
651 dev = device_find(interface_old);
655 if (dev->type != &simple_device_type)
658 device_set_present(dev, false);
661 dev = device_find(interface);
665 if (dev->type != &simple_device_type)
668 if (add && system_if_force_external(dev->ifname))
671 device_set_present(dev, add);
675 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
677 struct event_socket *ev = container_of(u, struct event_socket, uloop);
678 struct sockaddr_nl nla;
679 unsigned char *buf = NULL;
682 socklen_t errlen = sizeof(err);
685 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
687 handle_hotplug_msg((char *) buf, size);
694 if (getsockopt(u->fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen))
699 /* Increase rx buffer size on netlink socket */
701 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
712 uloop_fd_delete(&ev->uloop);
716 static int system_rtnl_call(struct nl_msg *msg)
720 ret = nl_send_auto_complete(sock_rtnl, msg);
726 return nl_wait_for_ack(sock_rtnl);
729 int system_bridge_delbr(struct device *bridge)
731 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
734 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
738 memset(&ifr, 0, sizeof(ifr));
740 ifr.ifr_ifindex = dev->ifindex;
743 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name) - 1);
744 return ioctl(sock_ioctl, cmd, &ifr);
747 static bool system_is_bridge(const char *name, char *buf, int buflen)
751 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
752 if (stat(buf, &st) < 0)
758 static char *system_get_bridge(const char *name, char *buf, int buflen)
764 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
765 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
769 len = readlink(gl.gl_pathv[0], buf, buflen);
777 path = strrchr(buf, '/');
785 system_bridge_set_wireless(struct device *bridge, struct device *dev)
787 bool mcast_to_ucast = dev->wireless_ap;
790 if (bridge->settings.flags & DEV_OPT_MULTICAST_TO_UNICAST &&
791 !bridge->settings.multicast_to_unicast)
792 mcast_to_ucast = false;
794 if (!mcast_to_ucast || dev->wireless_isolate)
797 system_bridge_set_multicast_to_unicast(dev, mcast_to_ucast ? "1" : "0");
798 system_bridge_set_hairpin_mode(dev, hairpin ? "1" : "0");
801 int system_bridge_addif(struct device *bridge, struct device *dev)
807 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
808 if (!oldbr || strcmp(oldbr, bridge->ifname) != 0)
809 ret = system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
812 system_bridge_set_wireless(bridge, dev);
814 if (dev->settings.flags & DEV_OPT_MULTICAST_ROUTER) {
815 snprintf(buf, sizeof(buf), "%u", dev->settings.multicast_router);
816 system_bridge_set_multicast_router(dev, buf, false);
819 if (dev->settings.flags & DEV_OPT_MULTICAST_FAST_LEAVE &&
820 dev->settings.multicast_fast_leave)
821 system_bridge_set_multicast_fast_leave(dev, "1");
823 if (dev->settings.flags & DEV_OPT_LEARNING &&
824 !dev->settings.learning)
825 system_bridge_set_learning(dev, "0");
827 if (dev->settings.flags & DEV_OPT_UNICAST_FLOOD &&
828 !dev->settings.unicast_flood)
829 system_bridge_set_unicast_flood(dev, "0");
831 if (dev->settings.flags & DEV_OPT_ISOLATE &&
832 dev->settings.isolate)
833 system_bridge_set_isolated(dev, "1");
838 int system_bridge_delif(struct device *bridge, struct device *dev)
840 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
843 int system_if_resolve(struct device *dev)
846 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
847 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
848 return ifr.ifr_ifindex;
853 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
857 memset(&ifr, 0, sizeof(ifr));
858 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1);
859 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) < 0)
862 ifr.ifr_flags |= add;
863 ifr.ifr_flags &= ~rem;
864 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
876 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
878 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
880 return ifa->ifa_index == ifindex;
883 static bool check_route(struct nlmsghdr *hdr, int ifindex)
885 struct rtmsg *r = NLMSG_DATA(hdr);
886 struct nlattr *tb[__RTA_MAX];
888 if (r->rtm_protocol == RTPROT_KERNEL &&
889 r->rtm_family == AF_INET6)
892 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
896 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
899 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
904 static int cb_clear_event(struct nl_msg *msg, void *arg)
906 struct clear_data *clr = arg;
907 struct nlmsghdr *hdr = nlmsg_hdr(msg);
908 bool (*cb)(struct nlmsghdr *, int ifindex);
914 if (hdr->nlmsg_type != RTM_NEWADDR)
921 if (hdr->nlmsg_type != RTM_NEWROUTE)
928 if (hdr->nlmsg_type != RTM_NEWRULE)
937 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
940 if (type == RTM_DELRULE)
941 D(SYSTEM, "Remove a rule\n");
943 D(SYSTEM, "Remove %s from device %s\n",
944 type == RTM_DELADDR ? "an address" : "a route",
947 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
948 hdr = nlmsg_hdr(clr->msg);
949 hdr->nlmsg_type = type;
950 hdr->nlmsg_flags = NLM_F_REQUEST;
952 nl_socket_disable_auto_ack(sock_rtnl);
953 ret = nl_send_auto_complete(sock_rtnl, clr->msg);
955 if (type == RTM_DELRULE)
956 D(SYSTEM, "Error deleting a rule: %d\n", ret);
958 D(SYSTEM, "Error deleting %s from device '%s': %d\n",
959 type == RTM_DELADDR ? "an address" : "a route",
960 clr->dev->ifname, ret);
963 nl_socket_enable_auto_ack(sock_rtnl);
969 cb_finish_event(struct nl_msg *msg, void *arg)
977 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
980 *pending = err->error;
985 system_if_clear_entries(struct device *dev, int type, int af)
987 struct clear_data clr;
991 .rtm_flags = RTM_F_CLONED,
993 int flags = NLM_F_DUMP;
1002 clr.size = sizeof(struct rtgenmsg);
1005 clr.size = sizeof(struct rtmsg);
1011 cb = nl_cb_alloc(NL_CB_DEFAULT);
1015 clr.msg = nlmsg_alloc_simple(type, flags);
1019 nlmsg_append(clr.msg, &rtm, clr.size, 0);
1020 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
1021 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
1022 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
1024 if (nl_send_auto_complete(sock_rtnl, clr.msg) < 0)
1028 nl_recvmsgs(sock_rtnl, cb);
1031 nlmsg_free(clr.msg);
1037 * Clear bridge (membership) state and bring down device
1039 void system_if_clear_state(struct device *dev)
1041 static char buf[256];
1043 device_set_ifindex(dev, system_if_resolve(dev));
1045 if (dev->external || !dev->ifindex)
1048 system_if_flags(dev->ifname, 0, IFF_UP);
1050 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
1051 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
1052 system_bridge_delbr(dev);
1056 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
1058 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
1059 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
1062 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
1063 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
1064 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
1065 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
1066 system_if_clear_entries(dev, RTM_GETNEIGH, AF_INET);
1067 system_if_clear_entries(dev, RTM_GETNEIGH, AF_INET6);
1068 system_set_disable_ipv6(dev, "0");
1071 static inline unsigned long
1072 sec_to_jiffies(int val)
1074 return (unsigned long) val * 100;
1077 static void system_bridge_conf_multicast_deps(struct device *bridge,
1078 struct bridge_config *cfg,
1084 if (cfg->flags & BRIDGE_OPT_ROBUSTNESS ||
1085 cfg->flags & BRIDGE_OPT_QUERY_INTERVAL ||
1086 cfg->flags & BRIDGE_OPT_QUERY_RESPONSE_INTERVAL) {
1087 val = cfg->robustness * cfg->query_interval +
1088 cfg->query_response_interval;
1090 snprintf(buf, buf_len, "%i", val);
1091 system_bridge_set_membership_interval(bridge, buf);
1093 val = cfg->robustness * cfg->query_interval +
1094 cfg->query_response_interval / 2;
1096 snprintf(buf, buf_len, "%i", val);
1097 system_bridge_set_other_querier_timeout(bridge, buf);
1100 if (cfg->flags & BRIDGE_OPT_QUERY_INTERVAL) {
1101 val = cfg->query_interval / 4;
1103 snprintf(buf, buf_len, "%i", val);
1104 system_bridge_set_startup_query_interval(bridge, buf);
1108 static void system_bridge_conf_multicast(struct device *bridge,
1109 struct bridge_config *cfg,
1113 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
1114 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
1116 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier",
1117 bridge->ifname, cfg->multicast_querier ? "1" : "0");
1119 snprintf(buf, buf_len, "%i", cfg->hash_max);
1120 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/hash_max",
1121 bridge->ifname, buf);
1123 if (bridge->settings.flags & DEV_OPT_MULTICAST_ROUTER) {
1124 snprintf(buf, buf_len, "%u", bridge->settings.multicast_router);
1125 system_bridge_set_multicast_router(bridge, buf, true);
1128 if (cfg->flags & BRIDGE_OPT_ROBUSTNESS) {
1129 snprintf(buf, buf_len, "%i", cfg->robustness);
1130 system_bridge_set_robustness(bridge, buf);
1133 if (cfg->flags & BRIDGE_OPT_QUERY_INTERVAL) {
1134 snprintf(buf, buf_len, "%i", cfg->query_interval);
1135 system_bridge_set_query_interval(bridge, buf);
1138 if (cfg->flags & BRIDGE_OPT_QUERY_RESPONSE_INTERVAL) {
1139 snprintf(buf, buf_len, "%i", cfg->query_response_interval);
1140 system_bridge_set_query_response_interval(bridge, buf);
1143 if (cfg->flags & BRIDGE_OPT_LAST_MEMBER_INTERVAL) {
1144 snprintf(buf, buf_len, "%i", cfg->last_member_interval);
1145 system_bridge_set_last_member_interval(bridge, buf);
1148 system_bridge_conf_multicast_deps(bridge, cfg, buf, buf_len);
1151 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
1155 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
1158 system_bridge_set_stp_state(bridge, cfg->stp ? "1" : "0");
1160 snprintf(buf, sizeof(buf), "%lu", sec_to_jiffies(cfg->forward_delay));
1161 system_bridge_set_forward_delay(bridge, buf);
1163 system_bridge_conf_multicast(bridge, cfg, buf, sizeof(buf));
1165 snprintf(buf, sizeof(buf), "%d", cfg->priority);
1166 system_bridge_set_priority(bridge, buf);
1168 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
1169 snprintf(buf, sizeof(buf), "%lu", sec_to_jiffies(cfg->ageing_time));
1170 system_bridge_set_ageing_time(bridge, buf);
1173 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
1174 snprintf(buf, sizeof(buf), "%lu", sec_to_jiffies(cfg->hello_time));
1175 system_bridge_set_hello_time(bridge, buf);
1178 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
1179 snprintf(buf, sizeof(buf), "%lu", sec_to_jiffies(cfg->max_age));
1180 system_bridge_set_max_age(bridge, buf);
1186 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
1189 struct nlattr *linkinfo, *data;
1190 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
1192 static const struct {
1194 enum macvlan_mode val;
1196 { "private", MACVLAN_MODE_PRIVATE },
1197 { "vepa", MACVLAN_MODE_VEPA },
1198 { "bridge", MACVLAN_MODE_BRIDGE },
1199 { "passthru", MACVLAN_MODE_PASSTHRU },
1202 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1207 nlmsg_append(msg, &iim, sizeof(iim), 0);
1209 if (cfg->flags & MACVLAN_OPT_MACADDR)
1210 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
1211 nla_put_string(msg, IFLA_IFNAME, macvlan->ifname);
1212 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
1214 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1215 goto nla_put_failure;
1217 nla_put_string(msg, IFLA_INFO_KIND, "macvlan");
1219 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1220 goto nla_put_failure;
1223 for (i = 0; i < ARRAY_SIZE(modes); i++) {
1224 if (strcmp(cfg->mode, modes[i].name) != 0)
1227 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
1232 nla_nest_end(msg, data);
1233 nla_nest_end(msg, linkinfo);
1235 rv = system_rtnl_call(msg);
1237 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
1246 static int system_link_del(const char *ifname)
1249 struct ifinfomsg iim = {
1250 .ifi_family = AF_UNSPEC,
1254 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
1259 nlmsg_append(msg, &iim, sizeof(iim), 0);
1260 nla_put_string(msg, IFLA_IFNAME, ifname);
1261 return system_rtnl_call(msg);
1264 int system_macvlan_del(struct device *macvlan)
1266 return system_link_del(macvlan->ifname);
1269 int system_veth_add(struct device *veth, struct veth_config *cfg)
1272 struct ifinfomsg empty_iim = {};
1273 struct nlattr *linkinfo, *data, *veth_info;
1276 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1281 nlmsg_append(msg, &empty_iim, sizeof(empty_iim), 0);
1283 if (cfg->flags & VETH_OPT_MACADDR)
1284 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
1285 nla_put_string(msg, IFLA_IFNAME, veth->ifname);
1287 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1288 goto nla_put_failure;
1290 nla_put_string(msg, IFLA_INFO_KIND, "veth");
1292 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1293 goto nla_put_failure;
1295 if (!(veth_info = nla_nest_start(msg, VETH_INFO_PEER)))
1296 goto nla_put_failure;
1298 nlmsg_append(msg, &empty_iim, sizeof(empty_iim), 0);
1300 if (cfg->flags & VETH_OPT_PEER_NAME)
1301 nla_put_string(msg, IFLA_IFNAME, cfg->peer_name);
1302 if (cfg->flags & VETH_OPT_PEER_MACADDR)
1303 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->peer_macaddr), cfg->peer_macaddr);
1305 nla_nest_end(msg, veth_info);
1306 nla_nest_end(msg, data);
1307 nla_nest_end(msg, linkinfo);
1309 rv = system_rtnl_call(msg);
1311 if (cfg->flags & VETH_OPT_PEER_NAME)
1312 D(SYSTEM, "Error adding veth '%s' with peer '%s': %d\n", veth->ifname, cfg->peer_name, rv);
1314 D(SYSTEM, "Error adding veth '%s': %d\n", veth->ifname, rv);
1324 int system_veth_del(struct device *veth)
1326 return system_link_del(veth->ifname);
1329 static int system_vlan(struct device *dev, int id)
1331 struct vlan_ioctl_args ifr = {
1332 .cmd = SET_VLAN_NAME_TYPE_CMD,
1333 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
1336 if (ioctl(sock_ioctl, SIOCSIFVLAN, &ifr) < 0)
1340 ifr.cmd = DEL_VLAN_CMD;
1343 ifr.cmd = ADD_VLAN_CMD;
1346 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
1347 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
1350 int system_vlan_add(struct device *dev, int id)
1352 return system_vlan(dev, id);
1355 int system_vlan_del(struct device *dev)
1357 return system_vlan(dev, -1);
1360 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
1363 struct nlattr *linkinfo, *data;
1364 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
1367 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1372 nlmsg_append(msg, &iim, sizeof(iim), 0);
1373 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
1374 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
1376 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1377 goto nla_put_failure;
1379 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
1381 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1382 goto nla_put_failure;
1384 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
1386 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
1387 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
1389 if(cfg->proto == VLAN_PROTO_8021AD)
1390 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);
1393 nla_nest_end(msg, data);
1394 nla_nest_end(msg, linkinfo);
1396 rv = system_rtnl_call(msg);
1398 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
1407 int system_vlandev_del(struct device *vlandev)
1409 return system_link_del(vlandev->ifname);
1413 system_if_get_settings(struct device *dev, struct device_settings *s)
1418 memset(&ifr, 0, sizeof(ifr));
1419 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
1421 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
1422 s->mtu = ifr.ifr_mtu;
1423 s->flags |= DEV_OPT_MTU;
1426 s->mtu6 = system_update_ipv6_mtu(dev, 0);
1428 s->flags |= DEV_OPT_MTU6;
1430 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
1431 s->txqueuelen = ifr.ifr_qlen;
1432 s->flags |= DEV_OPT_TXQUEUELEN;
1435 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
1436 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
1437 s->flags |= DEV_OPT_MACADDR;
1440 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
1441 s->ipv6 = !strtoul(buf, NULL, 0);
1442 s->flags |= DEV_OPT_IPV6;
1445 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
1446 s->promisc = ifr.ifr_flags & IFF_PROMISC;
1447 s->flags |= DEV_OPT_PROMISC;
1449 s->multicast = ifr.ifr_flags & IFF_MULTICAST;
1450 s->flags |= DEV_OPT_MULTICAST;
1453 if (!system_get_rpfilter(dev, buf, sizeof(buf))) {
1454 s->rpfilter = strtoul(buf, NULL, 0);
1455 s->flags |= DEV_OPT_RPFILTER;
1458 if (!system_get_acceptlocal(dev, buf, sizeof(buf))) {
1459 s->acceptlocal = strtoul(buf, NULL, 0);
1460 s->flags |= DEV_OPT_ACCEPTLOCAL;
1463 if (!system_get_igmpversion(dev, buf, sizeof(buf))) {
1464 s->igmpversion = strtoul(buf, NULL, 0);
1465 s->flags |= DEV_OPT_IGMPVERSION;
1468 if (!system_get_mldversion(dev, buf, sizeof(buf))) {
1469 s->mldversion = strtoul(buf, NULL, 0);
1470 s->flags |= DEV_OPT_MLDVERSION;
1473 if (!system_get_neigh4reachabletime(dev, buf, sizeof(buf))) {
1474 s->neigh4reachabletime = strtoul(buf, NULL, 0);
1475 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1478 if (!system_get_neigh6reachabletime(dev, buf, sizeof(buf))) {
1479 s->neigh6reachabletime = strtoul(buf, NULL, 0);
1480 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1483 if (!system_get_neigh4locktime(dev, buf, sizeof(buf))) {
1484 s->neigh4locktime = strtol(buf, NULL, 0);
1485 s->flags |= DEV_OPT_NEIGHLOCKTIME;
1488 if (!system_get_neigh4gcstaletime(dev, buf, sizeof(buf))) {
1489 s->neigh4gcstaletime = strtoul(buf, NULL, 0);
1490 s->flags |= DEV_OPT_NEIGHGCSTALETIME;
1493 if (!system_get_neigh6gcstaletime(dev, buf, sizeof(buf))) {
1494 s->neigh6gcstaletime = strtoul(buf, NULL, 0);
1495 s->flags |= DEV_OPT_NEIGHGCSTALETIME;
1498 if (!system_get_dadtransmits(dev, buf, sizeof(buf))) {
1499 s->dadtransmits = strtoul(buf, NULL, 0);
1500 s->flags |= DEV_OPT_DADTRANSMITS;
1503 if (!system_get_sendredirects(dev, buf, sizeof(buf))) {
1504 s->sendredirects = strtoul(buf, NULL, 0);
1505 s->flags |= DEV_OPT_SENDREDIRECTS;
1510 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
1515 memset(&ifr, 0, sizeof(ifr));
1516 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
1517 if (s->flags & DEV_OPT_MTU & apply_mask) {
1518 ifr.ifr_mtu = s->mtu;
1519 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
1520 s->flags &= ~DEV_OPT_MTU;
1522 if (s->flags & DEV_OPT_MTU6 & apply_mask) {
1523 system_update_ipv6_mtu(dev, s->mtu6);
1525 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
1526 ifr.ifr_qlen = s->txqueuelen;
1527 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
1528 s->flags &= ~DEV_OPT_TXQUEUELEN;
1530 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
1531 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
1532 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
1533 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
1534 s->flags &= ~DEV_OPT_MACADDR;
1536 if (s->flags & DEV_OPT_IPV6 & apply_mask)
1537 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
1538 if (s->flags & DEV_OPT_PROMISC & apply_mask) {
1539 if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
1540 !s->promisc ? IFF_PROMISC : 0) < 0)
1541 s->flags &= ~DEV_OPT_PROMISC;
1543 if (s->flags & DEV_OPT_RPFILTER & apply_mask) {
1544 snprintf(buf, sizeof(buf), "%u", s->rpfilter);
1545 system_set_rpfilter(dev, buf);
1547 if (s->flags & DEV_OPT_ACCEPTLOCAL & apply_mask)
1548 system_set_acceptlocal(dev, s->acceptlocal ? "1" : "0");
1549 if (s->flags & DEV_OPT_IGMPVERSION & apply_mask) {
1550 snprintf(buf, sizeof(buf), "%u", s->igmpversion);
1551 system_set_igmpversion(dev, buf);
1553 if (s->flags & DEV_OPT_MLDVERSION & apply_mask) {
1554 snprintf(buf, sizeof(buf), "%u", s->mldversion);
1555 system_set_mldversion(dev, buf);
1557 if (s->flags & DEV_OPT_NEIGHREACHABLETIME & apply_mask) {
1558 snprintf(buf, sizeof(buf), "%u", s->neigh4reachabletime);
1559 system_set_neigh4reachabletime(dev, buf);
1560 snprintf(buf, sizeof(buf), "%u", s->neigh6reachabletime);
1561 system_set_neigh6reachabletime(dev, buf);
1563 if (s->flags & DEV_OPT_NEIGHLOCKTIME & apply_mask) {
1564 snprintf(buf, sizeof(buf), "%d", s->neigh4locktime);
1565 system_set_neigh4locktime(dev, buf);
1567 if (s->flags & DEV_OPT_NEIGHGCSTALETIME & apply_mask) {
1568 snprintf(buf, sizeof(buf), "%u", s->neigh4gcstaletime);
1569 system_set_neigh4gcstaletime(dev, buf);
1570 snprintf(buf, sizeof(buf), "%u", s->neigh6gcstaletime);
1571 system_set_neigh6gcstaletime(dev, buf);
1573 if (s->flags & DEV_OPT_DADTRANSMITS & apply_mask) {
1574 snprintf(buf, sizeof(buf), "%u", s->dadtransmits);
1575 system_set_dadtransmits(dev, buf);
1577 if (s->flags & DEV_OPT_MULTICAST & apply_mask) {
1578 if (system_if_flags(dev->ifname, s->multicast ? IFF_MULTICAST : 0,
1579 !s->multicast ? IFF_MULTICAST : 0) < 0)
1580 s->flags &= ~DEV_OPT_MULTICAST;
1582 if (s->flags & DEV_OPT_SENDREDIRECTS & apply_mask)
1583 system_set_sendredirects(dev, s->sendredirects ? "1" : "0");
1586 int system_if_up(struct device *dev)
1588 system_if_get_settings(dev, &dev->orig_settings);
1589 /* Only keep orig settings based on what needs to be set */
1590 dev->orig_settings.valid_flags = dev->orig_settings.flags;
1591 dev->orig_settings.flags &= dev->settings.flags;
1592 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
1593 return system_if_flags(dev->ifname, IFF_UP, 0);
1596 int system_if_down(struct device *dev)
1598 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
1599 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
1603 struct if_check_data {
1609 #ifndef IFF_LOWER_UP
1610 #define IFF_LOWER_UP 0x10000
1613 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1615 struct nlmsghdr *nh = nlmsg_hdr(msg);
1616 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1617 struct if_check_data *chk = (struct if_check_data *)arg;
1619 if (nh->nlmsg_type != RTM_NEWLINK)
1622 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1623 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1628 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1630 struct if_check_data *chk = (struct if_check_data *)arg;
1635 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1637 struct if_check_data *chk = (struct if_check_data *)arg;
1639 device_set_present(chk->dev, false);
1640 device_set_link(chk->dev, false);
1641 chk->pending = err->error;
1646 int system_if_check(struct device *dev)
1648 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1650 struct ifinfomsg ifi = {
1651 .ifi_family = AF_UNSPEC,
1654 struct if_check_data chk = {
1663 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1667 if (nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1668 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1671 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1672 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1673 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1675 ret = nl_send_auto_complete(sock_rtnl, msg);
1679 while (chk.pending > 0)
1680 nl_recvmsgs(sock_rtnl, cb);
1692 system_if_get_parent(struct device *dev)
1694 char buf[64], *devname;
1695 int ifindex, iflink, len;
1698 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1699 f = fopen(buf, "r");
1703 len = fread(buf, 1, sizeof(buf) - 1, f);
1710 iflink = strtoul(buf, NULL, 0);
1711 ifindex = system_if_resolve(dev);
1712 if (!iflink || iflink == ifindex)
1715 devname = if_indextoname(iflink, buf);
1719 return device_get(devname, true);
1723 read_string_file(int dir_fd, const char *file, char *buf, int len)
1729 fd = openat(dir_fd, file, O_RDONLY);
1734 len = read(fd, buf, len - 1);
1738 } else if (len > 0) {
1741 c = strchr(buf, '\n');
1754 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1759 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1761 *val = strtoull(buf, NULL, 0);
1766 /* Assume advertised flags == supported flags */
1767 static const struct {
1770 } ethtool_link_modes[] = {
1771 { ADVERTISED_10baseT_Half, "10baseT-H" },
1772 { ADVERTISED_10baseT_Full, "10baseT-F" },
1773 { ADVERTISED_100baseT_Half, "100baseT-H" },
1774 { ADVERTISED_100baseT_Full, "100baseT-F" },
1775 { ADVERTISED_1000baseT_Half, "1000baseT-H" },
1776 { ADVERTISED_1000baseT_Full, "1000baseT-F" },
1777 { ADVERTISED_1000baseKX_Full, "1000baseKX-F" },
1778 { ADVERTISED_2500baseX_Full, "2500baseX-F" },
1779 { ADVERTISED_10000baseT_Full, "10000baseT-F" },
1780 { ADVERTISED_10000baseKX4_Full, "10000baseKX4-F" },
1781 { ADVERTISED_10000baseKR_Full, "10000baseKR-F" },
1782 { ADVERTISED_20000baseMLD2_Full, "20000baseMLD2-F" },
1783 { ADVERTISED_20000baseKR2_Full, "20000baseKR2-F" },
1784 { ADVERTISED_40000baseKR4_Full, "40000baseKR4-F" },
1785 { ADVERTISED_40000baseCR4_Full, "40000baseCR4-F" },
1786 { ADVERTISED_40000baseSR4_Full, "40000baseSR4-F" },
1787 { ADVERTISED_40000baseLR4_Full, "40000baseLR4-F" },
1788 #ifdef ADVERTISED_56000baseKR4_Full
1789 { ADVERTISED_56000baseKR4_Full, "56000baseKR4-F" },
1790 { ADVERTISED_56000baseCR4_Full, "56000baseCR4-F" },
1791 { ADVERTISED_56000baseSR4_Full, "56000baseSR4-F" },
1792 { ADVERTISED_56000baseLR4_Full, "56000baseLR4-F" },
1796 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1799 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1800 if (mask & ethtool_link_modes[i].mask)
1801 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1806 system_if_force_external(const char *ifname)
1811 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1812 return stat(buf, &s) == 0;
1816 system_if_dump_info(struct device *dev, struct blob_buf *b)
1818 struct ethtool_cmd ecmd;
1823 memset(&ecmd, 0, sizeof(ecmd));
1824 memset(&ifr, 0, sizeof(ifr));
1825 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
1826 ifr.ifr_data = (caddr_t) &ecmd;
1827 ecmd.cmd = ETHTOOL_GSET;
1829 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1830 c = blobmsg_open_array(b, "link-advertising");
1831 system_add_link_modes(b, ecmd.advertising);
1832 blobmsg_close_array(b, c);
1834 c = blobmsg_open_array(b, "link-partner-advertising");
1835 system_add_link_modes(b, ecmd.lp_advertising);
1836 blobmsg_close_array(b, c);
1838 c = blobmsg_open_array(b, "link-supported");
1839 system_add_link_modes(b, ecmd.supported);
1840 blobmsg_close_array(b, c);
1842 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1843 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1844 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1845 blobmsg_add_string_buffer(b);
1847 blobmsg_add_u8(b, "autoneg", !!ecmd.autoneg);
1854 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1856 const char *const counters[] = {
1857 "collisions", "rx_frame_errors", "tx_compressed",
1858 "multicast", "rx_length_errors", "tx_dropped",
1859 "rx_bytes", "rx_missed_errors", "tx_errors",
1860 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1861 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1862 "rx_dropped", "tx_aborted_errors", "tx_packets",
1863 "rx_errors", "tx_bytes", "tx_window_errors",
1864 "rx_fifo_errors", "tx_carrier_errors",
1871 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1872 stats_dir = open(buf, O_DIRECTORY);
1876 for (i = 0; i < ARRAY_SIZE(counters); i++)
1877 if (read_uint64_file(stats_dir, counters[i], &val))
1878 blobmsg_add_u64(b, counters[i], val);
1884 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1886 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1887 int alen = v4 ? 4 : 16;
1888 unsigned int flags = 0;
1889 struct ifaddrmsg ifa = {
1890 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1891 .ifa_prefixlen = addr->mask,
1892 .ifa_index = dev->ifindex,
1896 if (cmd == RTM_NEWADDR)
1897 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1899 msg = nlmsg_alloc_simple(cmd, flags);
1903 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1904 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1906 if (addr->broadcast)
1907 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1908 if (addr->point_to_point)
1909 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1911 time_t now = system_get_rtime();
1912 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1914 if (addr->preferred_until) {
1915 int64_t preferred = addr->preferred_until - now;
1918 else if (preferred > UINT32_MAX)
1919 preferred = UINT32_MAX;
1921 cinfo.ifa_prefered = preferred;
1924 if (addr->valid_until) {
1925 int64_t valid = addr->valid_until - now;
1930 else if (valid > UINT32_MAX)
1933 cinfo.ifa_valid = valid;
1936 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1938 if (cmd == RTM_NEWADDR && (addr->flags & DEVADDR_OFFLINK))
1939 nla_put_u32(msg, IFA_FLAGS, IFA_F_NOPREFIXROUTE);
1942 return system_rtnl_call(msg);
1945 int system_add_address(struct device *dev, struct device_addr *addr)
1947 return system_addr(dev, addr, RTM_NEWADDR);
1950 int system_del_address(struct device *dev, struct device_addr *addr)
1952 return system_addr(dev, addr, RTM_DELADDR);
1955 static int system_neigh(struct device *dev, struct device_neighbor *neighbor, int cmd)
1957 int alen = ((neighbor->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1958 unsigned int flags = 0;
1959 struct ndmsg ndm = {
1960 .ndm_family = (alen == 4) ? AF_INET : AF_INET6,
1961 .ndm_ifindex = dev->ifindex,
1962 .ndm_state = NUD_PERMANENT,
1963 .ndm_flags = (neighbor->proxy ? NTF_PROXY : 0) | (neighbor->router ? NTF_ROUTER : 0),
1967 if (cmd == RTM_NEWNEIGH)
1968 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1970 msg = nlmsg_alloc_simple(cmd, flags);
1975 nlmsg_append(msg, &ndm, sizeof(ndm), 0);
1977 nla_put(msg, NDA_DST, alen, &neighbor->addr);
1978 if (neighbor->flags & DEVNEIGH_MAC)
1979 nla_put(msg, NDA_LLADDR, sizeof(neighbor->macaddr), &neighbor->macaddr);
1982 return system_rtnl_call(msg);
1985 int system_add_neighbor(struct device *dev, struct device_neighbor *neighbor)
1987 return system_neigh(dev, neighbor, RTM_NEWNEIGH);
1990 int system_del_neighbor(struct device *dev, struct device_neighbor *neighbor)
1992 return system_neigh(dev, neighbor, RTM_DELNEIGH);
1995 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1997 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1999 unsigned int flags = 0;
2002 have_gw = !!route->nexthop.in.s_addr;
2004 have_gw = route->nexthop.in6.s6_addr32[0] ||
2005 route->nexthop.in6.s6_addr32[1] ||
2006 route->nexthop.in6.s6_addr32[2] ||
2007 route->nexthop.in6.s6_addr32[3];
2009 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
2010 ? route->table : RT_TABLE_MAIN;
2012 struct rtmsg rtm = {
2013 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
2014 .rtm_dst_len = route->mask,
2015 .rtm_src_len = route->sourcemask,
2016 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
2017 .rtm_protocol = (route->flags & DEVROUTE_PROTO) ? route->proto : RTPROT_STATIC,
2018 .rtm_scope = RT_SCOPE_NOWHERE,
2019 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
2020 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
2024 if (cmd == RTM_NEWROUTE) {
2025 flags |= NLM_F_CREATE | NLM_F_REPLACE;
2027 if (!dev) { /* Add null-route */
2028 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
2029 rtm.rtm_type = RTN_UNREACHABLE;
2032 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
2035 if (route->flags & DEVROUTE_TYPE) {
2036 rtm.rtm_type = route->type;
2037 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
2038 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
2039 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
2040 rtm.rtm_table = RT_TABLE_LOCAL;
2043 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT) {
2044 rtm.rtm_scope = RT_SCOPE_HOST;
2045 } else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
2046 rtm.rtm_type == RTN_ANYCAST) {
2047 rtm.rtm_scope = RT_SCOPE_LINK;
2048 } else if (rtm.rtm_type == RTN_BLACKHOLE || rtm.rtm_type == RTN_UNREACHABLE ||
2049 rtm.rtm_type == RTN_PROHIBIT || rtm.rtm_type == RTN_FAILED_POLICY ||
2050 rtm.rtm_type == RTN_THROW) {
2051 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
2056 msg = nlmsg_alloc_simple(cmd, flags);
2060 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
2063 nla_put(msg, RTA_DST, alen, &route->addr);
2065 if (route->sourcemask) {
2066 if (rtm.rtm_family == AF_INET)
2067 nla_put(msg, RTA_PREFSRC, alen, &route->source);
2069 nla_put(msg, RTA_SRC, alen, &route->source);
2072 if (route->metric > 0)
2073 nla_put_u32(msg, RTA_PRIORITY, route->metric);
2076 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
2079 nla_put_u32(msg, RTA_OIF, dev->ifindex);
2082 nla_put_u32(msg, RTA_TABLE, table);
2084 if (route->flags & DEVROUTE_MTU) {
2085 struct nlattr *metrics;
2087 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
2088 goto nla_put_failure;
2090 nla_put_u32(msg, RTAX_MTU, route->mtu);
2092 nla_nest_end(msg, metrics);
2095 return system_rtnl_call(msg);
2102 int system_add_route(struct device *dev, struct device_route *route)
2104 return system_rt(dev, route, RTM_NEWROUTE);
2107 int system_del_route(struct device *dev, struct device_route *route)
2109 return system_rt(dev, route, RTM_DELROUTE);
2112 int system_flush_routes(void)
2114 const char *names[] = {
2115 "/proc/sys/net/ipv4/route/flush",
2116 "/proc/sys/net/ipv6/route/flush"
2120 for (i = 0; i < ARRAY_SIZE(names); i++) {
2121 fd = open(names[i], O_WRONLY);
2125 if (write(fd, "-1", 2)) {}
2131 bool system_resolve_rt_type(const char *type, unsigned int *id)
2133 return system_rtn_aton(type, id);
2136 bool system_resolve_rt_proto(const char *type, unsigned int *id)
2140 unsigned int n, proto = 256;
2141 n = strtoul(type, &e, 0);
2142 if (!*e && e != type)
2144 else if (!strcmp(type, "unspec"))
2145 proto = RTPROT_UNSPEC;
2146 else if (!strcmp(type, "kernel"))
2147 proto = RTPROT_KERNEL;
2148 else if (!strcmp(type, "boot"))
2149 proto = RTPROT_BOOT;
2150 else if (!strcmp(type, "static"))
2151 proto = RTPROT_STATIC;
2152 else if ((f = fopen("/etc/iproute2/rt_protos", "r")) != NULL) {
2153 while (fgets(buf, sizeof(buf) - 1, f) != NULL) {
2154 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
2157 n = strtoul(e, NULL, 10);
2158 e = strtok(NULL, " \t\n");
2160 if (e && !strcmp(e, type)) {
2175 bool system_resolve_rt_table(const char *name, unsigned int *id)
2179 unsigned int n, table = RT_TABLE_UNSPEC;
2181 /* first try to parse table as number */
2182 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
2185 /* handle well known aliases */
2186 else if (!strcmp(name, "default"))
2187 table = RT_TABLE_DEFAULT;
2188 else if (!strcmp(name, "main"))
2189 table = RT_TABLE_MAIN;
2190 else if (!strcmp(name, "local"))
2191 table = RT_TABLE_LOCAL;
2193 /* try to look up name in /etc/iproute2/rt_tables */
2194 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
2196 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
2198 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
2201 n = strtoul(e, NULL, 10);
2202 e = strtok(NULL, " \t\n");
2204 if (e && !strcmp(e, name))
2214 if (table == RT_TABLE_UNSPEC)
2221 bool system_is_default_rt_table(unsigned int id)
2223 return (id == RT_TABLE_MAIN);
2226 bool system_resolve_rpfilter(const char *filter, unsigned int *id)
2231 if (!strcmp(filter, "strict"))
2233 else if (!strcmp(filter, "loose"))
2236 n = strtoul(filter, &e, 0);
2237 if (*e || e == filter || n > 2)
2245 static int system_iprule(struct iprule *rule, int cmd)
2247 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
2250 struct rtmsg rtm = {
2251 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
2252 .rtm_protocol = RTPROT_STATIC,
2253 .rtm_scope = RT_SCOPE_UNIVERSE,
2254 .rtm_table = RT_TABLE_UNSPEC,
2255 .rtm_type = RTN_UNSPEC,
2259 if (cmd == RTM_NEWRULE)
2260 rtm.rtm_type = RTN_UNICAST;
2263 rtm.rtm_flags |= FIB_RULE_INVERT;
2265 if (rule->flags & IPRULE_SRC)
2266 rtm.rtm_src_len = rule->src_mask;
2268 if (rule->flags & IPRULE_DEST)
2269 rtm.rtm_dst_len = rule->dest_mask;
2271 if (rule->flags & IPRULE_TOS)
2272 rtm.rtm_tos = rule->tos;
2274 if (rule->flags & IPRULE_LOOKUP) {
2275 if (rule->lookup < 256)
2276 rtm.rtm_table = rule->lookup;
2279 if (rule->flags & IPRULE_ACTION)
2280 rtm.rtm_type = rule->action;
2281 else if (rule->flags & IPRULE_GOTO)
2282 rtm.rtm_type = FR_ACT_GOTO;
2283 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
2284 rtm.rtm_type = FR_ACT_NOP;
2286 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
2291 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
2293 if (rule->flags & IPRULE_IN)
2294 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
2296 if (rule->flags & IPRULE_OUT)
2297 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
2299 if (rule->flags & IPRULE_SRC)
2300 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
2302 if (rule->flags & IPRULE_DEST)
2303 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
2305 if (rule->flags & IPRULE_PRIORITY)
2306 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
2307 else if (cmd == RTM_NEWRULE)
2308 nla_put_u32(msg, FRA_PRIORITY, rule->order);
2310 if (rule->flags & IPRULE_FWMARK)
2311 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
2313 if (rule->flags & IPRULE_FWMASK)
2314 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
2316 if (rule->flags & IPRULE_LOOKUP) {
2317 if (rule->lookup >= 256)
2318 nla_put_u32(msg, FRA_TABLE, rule->lookup);
2321 if (rule->flags & IPRULE_SUP_PREFIXLEN)
2322 nla_put_u32(msg, FRA_SUPPRESS_PREFIXLEN, rule->sup_prefixlen);
2324 if (rule->flags & IPRULE_GOTO)
2325 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
2327 return system_rtnl_call(msg);
2330 int system_add_iprule(struct iprule *rule)
2332 return system_iprule(rule, RTM_NEWRULE);
2335 int system_del_iprule(struct iprule *rule)
2337 return system_iprule(rule, RTM_DELRULE);
2340 int system_flush_iprules(void)
2345 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
2346 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
2348 memset(&rule, 0, sizeof(rule));
2351 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2354 rule.lookup = RT_TABLE_LOCAL;
2355 rv |= system_iprule(&rule, RTM_NEWRULE);
2357 rule.priority = 32766;
2358 rule.lookup = RT_TABLE_MAIN;
2359 rv |= system_iprule(&rule, RTM_NEWRULE);
2361 rule.priority = 32767;
2362 rule.lookup = RT_TABLE_DEFAULT;
2363 rv |= system_iprule(&rule, RTM_NEWRULE);
2366 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2369 rule.lookup = RT_TABLE_LOCAL;
2370 rv |= system_iprule(&rule, RTM_NEWRULE);
2372 rule.priority = 32766;
2373 rule.lookup = RT_TABLE_MAIN;
2374 rv |= system_iprule(&rule, RTM_NEWRULE);
2379 bool system_resolve_iprule_action(const char *action, unsigned int *id)
2381 return system_rtn_aton(action, id);
2384 time_t system_get_rtime(void)
2389 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
2392 if (gettimeofday(&tv, NULL) == 0)
2399 #define IP_DF 0x4000
2402 static int tunnel_ioctl(const char *name, int cmd, void *p)
2406 memset(&ifr, 0, sizeof(ifr));
2407 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name) - 1);
2408 ifr.ifr_ifru.ifru_data = p;
2409 return ioctl(sock_ioctl, cmd, &ifr);
2412 #ifdef IFLA_IPTUN_MAX
2413 static int system_add_ip6_tunnel(const char *name, const unsigned int link,
2414 struct blob_attr **tb)
2416 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2417 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2418 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2419 struct blob_attr *cur;
2420 int ret = 0, ttl = 0;
2425 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2426 nla_put_string(nlm, IFLA_IFNAME, name);
2429 nla_put_u32(nlm, IFLA_LINK, link);
2431 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2437 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2438 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2445 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2447 if ((cur = tb[TUNNEL_ATTR_TTL]))
2448 ttl = blobmsg_get_u32(cur);
2450 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2451 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2453 struct in6_addr in6buf;
2454 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2455 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2459 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2462 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2463 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2467 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2470 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2471 struct blob_attr *tb_data[__IPIP6_DATA_ATTR_MAX];
2472 uint32_t tun_flags = IP6_TNL_F_IGN_ENCAP_LIMIT;
2474 blobmsg_parse(ipip6_data_attr_list.params, __IPIP6_DATA_ATTR_MAX, tb_data,
2475 blobmsg_data(cur), blobmsg_len(cur));
2477 if ((cur = tb_data[IPIP6_DATA_ENCAPLIMIT])) {
2478 char *str = blobmsg_get_string(cur);
2480 if (strcmp(str, "ignore")) {
2482 unsigned encap_limit = strtoul(str, &e, 0);
2484 if (e == str || *e || encap_limit > 255) {
2489 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, encap_limit);
2490 tun_flags &= ~IP6_TNL_F_IGN_ENCAP_LIMIT;
2494 #ifdef IFLA_IPTUN_FMR_MAX
2495 if ((cur = tb_data[IPIP6_DATA_FMRS])) {
2496 struct blob_attr *rcur;
2497 unsigned rrem, fmrcnt = 0;
2498 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2505 blobmsg_for_each_attr(rcur, cur, rrem) {
2506 struct blob_attr *tb_fmr[__FMR_DATA_ATTR_MAX], *tb_cur;
2507 struct in6_addr ip6prefix;
2508 struct in_addr ip4prefix;
2509 unsigned ip4len, ip6len, ealen, offset;
2511 blobmsg_parse(fmr_data_attr_list.params, __FMR_DATA_ATTR_MAX, tb_fmr,
2512 blobmsg_data(rcur), blobmsg_len(rcur));
2514 if (!(tb_cur = tb_fmr[FMR_DATA_PREFIX6]) ||
2515 !parse_ip_and_netmask(AF_INET6,
2516 blobmsg_data(tb_cur), &ip6prefix,
2522 if (!(tb_cur = tb_fmr[FMR_DATA_PREFIX4]) ||
2523 !parse_ip_and_netmask(AF_INET,
2524 blobmsg_data(tb_cur), &ip4prefix,
2530 if (!(tb_cur = tb_fmr[FMR_DATA_EALEN])) {
2534 ealen = blobmsg_get_u32(tb_cur);
2536 if (!(tb_cur = tb_fmr[FMR_DATA_OFFSET])) {
2540 offset = blobmsg_get_u32(tb_cur);
2542 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2548 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2549 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2550 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2551 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2552 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2553 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2555 nla_nest_end(nlm, rule);
2558 nla_nest_end(nlm, fmrs);
2562 nla_put_u32(nlm, IFLA_IPTUN_FLAGS, tun_flags);
2565 nla_nest_end(nlm, infodata);
2566 nla_nest_end(nlm, linkinfo);
2568 return system_rtnl_call(nlm);
2576 #ifdef IFLA_IPTUN_MAX
2577 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
2578 static int system_add_gre_tunnel(const char *name, const char *kind,
2579 const unsigned int link, struct blob_attr **tb, bool v6)
2582 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2583 struct blob_attr *cur;
2584 uint32_t ikey = 0, okey = 0, flowinfo = 0, flags6 = IP6_TNL_F_IGN_ENCAP_LIMIT;
2585 uint16_t iflags = 0, oflags = 0;
2587 int ret = 0, ttl = 0;
2588 unsigned encap_limit = 0;
2590 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2594 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2595 nla_put_string(nlm, IFLA_IFNAME, name);
2597 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2603 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2604 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2611 nla_put_u32(nlm, IFLA_GRE_LINK, link);
2613 if ((cur = tb[TUNNEL_ATTR_TTL]))
2614 ttl = blobmsg_get_u32(cur);
2616 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2617 char *str = blobmsg_get_string(cur);
2618 if (strcmp(str, "inherit")) {
2621 if (!system_tos_aton(str, &uval)) {
2627 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
2632 flags6 |= IP6_TNL_F_USE_ORIG_TCLASS;
2638 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2639 struct blob_attr *tb_data[__GRE_DATA_ATTR_MAX];
2641 blobmsg_parse(gre_data_attr_list.params, __GRE_DATA_ATTR_MAX, tb_data,
2642 blobmsg_data(cur), blobmsg_len(cur));
2644 if ((cur = tb_data[GRE_DATA_IKEY])) {
2645 if ((ikey = blobmsg_get_u32(cur)))
2649 if ((cur = tb_data[GRE_DATA_OKEY])) {
2650 if ((okey = blobmsg_get_u32(cur)))
2654 if ((cur = tb_data[GRE_DATA_ICSUM])) {
2655 if (blobmsg_get_bool(cur))
2659 if ((cur = tb_data[GRE_DATA_OCSUM])) {
2660 if (blobmsg_get_bool(cur))
2664 if ((cur = tb_data[GRE_DATA_ISEQNO])) {
2665 if (blobmsg_get_bool(cur))
2669 if ((cur = tb_data[GRE_DATA_OSEQNO])) {
2670 if (blobmsg_get_bool(cur))
2674 if ((cur = tb_data[GRE_DATA_ENCAPLIMIT])) {
2675 char *str = blobmsg_get_string(cur);
2677 if (strcmp(str, "ignore")) {
2680 encap_limit = strtoul(str, &e, 0);
2682 if (e == str || *e || encap_limit > 255) {
2687 flags6 &= ~IP6_TNL_F_IGN_ENCAP_LIMIT;
2693 struct in6_addr in6buf;
2694 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2695 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2699 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
2702 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2703 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2707 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
2710 if (!(flags6 & IP6_TNL_F_IGN_ENCAP_LIMIT))
2711 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, encap_limit);
2714 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
2717 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags6);
2722 struct in_addr inbuf;
2725 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2726 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2730 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
2733 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2734 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2738 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
2740 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
2742 okey = inbuf.s_addr;
2747 ikey = inbuf.s_addr;
2753 if ((cur = tb[TUNNEL_ATTR_DF]))
2754 set_df = blobmsg_get_bool(cur);
2757 /* ttl != 0 and nopmtudisc are incompatible */
2765 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
2767 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
2771 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
2774 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
2777 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
2780 nla_put_u32(nlm, IFLA_GRE_OKEY, htonl(okey));
2783 nla_put_u32(nlm, IFLA_GRE_IKEY, htonl(ikey));
2785 nla_nest_end(nlm, infodata);
2786 nla_nest_end(nlm, linkinfo);
2788 return system_rtnl_call(nlm);
2797 static int system_add_vti_tunnel(const char *name, const char *kind,
2798 const unsigned int link, struct blob_attr **tb, bool v6)
2801 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2802 struct blob_attr *cur;
2805 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2809 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2810 nla_put_string(nlm, IFLA_IFNAME, name);
2812 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2818 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2819 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2826 nla_put_u32(nlm, IFLA_VTI_LINK, link);
2829 struct in6_addr in6buf;
2830 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2831 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2835 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(in6buf), &in6buf);
2838 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2839 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2843 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(in6buf), &in6buf);
2847 struct in_addr inbuf;
2849 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2850 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2854 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(inbuf), &inbuf);
2857 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2858 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2862 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(inbuf), &inbuf);
2867 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2868 struct blob_attr *tb_data[__VTI_DATA_ATTR_MAX];
2869 uint32_t ikey = 0, okey = 0;
2871 blobmsg_parse(vti_data_attr_list.params, __VTI_DATA_ATTR_MAX, tb_data,
2872 blobmsg_data(cur), blobmsg_len(cur));
2874 if ((cur = tb_data[VTI_DATA_IKEY])) {
2875 if ((ikey = blobmsg_get_u32(cur)))
2876 nla_put_u32(nlm, IFLA_VTI_IKEY, htonl(ikey));
2879 if ((cur = tb_data[VTI_DATA_OKEY])) {
2880 if ((okey = blobmsg_get_u32(cur)))
2881 nla_put_u32(nlm, IFLA_VTI_OKEY, htonl(okey));
2885 nla_nest_end(nlm, infodata);
2886 nla_nest_end(nlm, linkinfo);
2888 return system_rtnl_call(nlm);
2896 #ifdef IFLA_XFRM_MAX
2897 static int system_add_xfrm_tunnel(const char *name, const char *kind,
2898 const unsigned int link, struct blob_attr **tb)
2901 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2902 struct blob_attr *cur;
2905 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2909 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2910 nla_put_string(nlm, IFLA_IFNAME, name);
2912 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2918 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2919 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2926 nla_put_u32(nlm, IFLA_XFRM_LINK, link);
2928 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2929 struct blob_attr *tb_data[__XFRM_DATA_ATTR_MAX];
2932 blobmsg_parse(xfrm_data_attr_list.params, __XFRM_DATA_ATTR_MAX, tb_data,
2933 blobmsg_data(cur), blobmsg_len(cur));
2935 if ((cur = tb_data[XFRM_DATA_IF_ID])) {
2936 if ((if_id = blobmsg_get_u32(cur)))
2937 nla_put_u32(nlm, IFLA_XFRM_IF_ID, if_id);
2942 nla_nest_end(nlm, infodata);
2943 nla_nest_end(nlm, linkinfo);
2945 return system_rtnl_call(nlm);
2953 #ifdef IFLA_VXLAN_MAX
2954 static int system_add_vxlan(const char *name, const unsigned int link, struct blob_attr **tb, bool v6)
2956 struct blob_attr *tb_data[__VXLAN_DATA_ATTR_MAX];
2958 struct nlattr *linkinfo, *data;
2959 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
2960 struct blob_attr *cur;
2963 if ((cur = tb[TUNNEL_ATTR_DATA]))
2964 blobmsg_parse(vxlan_data_attr_list.params, __VXLAN_DATA_ATTR_MAX, tb_data,
2965 blobmsg_data(cur), blobmsg_len(cur));
2969 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
2974 nlmsg_append(msg, &iim, sizeof(iim), 0);
2976 nla_put_string(msg, IFLA_IFNAME, name);
2978 if ((cur = tb_data[VXLAN_DATA_ATTR_MACADDR])) {
2979 struct ether_addr *ea = ether_aton(blobmsg_get_string(cur));
2985 nla_put(msg, IFLA_ADDRESS, ETH_ALEN, ea);
2988 if ((cur = tb[TUNNEL_ATTR_MTU])) {
2989 uint32_t mtu = blobmsg_get_u32(cur);
2990 nla_put_u32(msg, IFLA_MTU, mtu);
2993 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO))) {
2998 nla_put_string(msg, IFLA_INFO_KIND, "vxlan");
3000 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) {
3006 nla_put_u32(msg, IFLA_VXLAN_LINK, link);
3008 if ((cur = tb_data[VXLAN_DATA_ATTR_ID])) {
3009 uint32_t id = blobmsg_get_u32(cur);
3010 if (id >= (1u << 24) - 1) {
3015 nla_put_u32(msg, IFLA_VXLAN_ID, id);
3019 struct in6_addr in6buf;
3020 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
3021 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
3025 nla_put(msg, IFLA_VXLAN_LOCAL6, sizeof(in6buf), &in6buf);
3028 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
3029 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
3033 nla_put(msg, IFLA_VXLAN_GROUP6, sizeof(in6buf), &in6buf);
3036 struct in_addr inbuf;
3038 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
3039 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
3043 nla_put(msg, IFLA_VXLAN_LOCAL, sizeof(inbuf), &inbuf);
3046 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
3047 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
3051 nla_put(msg, IFLA_VXLAN_GROUP, sizeof(inbuf), &inbuf);
3055 uint32_t port = 4789;
3056 if ((cur = tb_data[VXLAN_DATA_ATTR_PORT])) {
3057 port = blobmsg_get_u32(cur);
3058 if (port < 1 || port > 65535) {
3063 nla_put_u16(msg, IFLA_VXLAN_PORT, htons(port));
3065 if ((cur = tb_data[VXLAN_DATA_ATTR_RXCSUM])) {
3066 bool rxcsum = blobmsg_get_bool(cur);
3067 nla_put_u8(msg, IFLA_VXLAN_UDP_ZERO_CSUM6_RX, !rxcsum);
3070 if ((cur = tb_data[VXLAN_DATA_ATTR_TXCSUM])) {
3071 bool txcsum = blobmsg_get_bool(cur);
3072 nla_put_u8(msg, IFLA_VXLAN_UDP_CSUM, txcsum);
3073 nla_put_u8(msg, IFLA_VXLAN_UDP_ZERO_CSUM6_TX, !txcsum);
3076 if ((cur = tb[TUNNEL_ATTR_TOS])) {
3077 char *str = blobmsg_get_string(cur);
3080 if (strcmp(str, "inherit")) {
3081 if (!system_tos_aton(str, &tos)) {
3087 nla_put_u8(msg, IFLA_VXLAN_TOS, tos);
3090 if ((cur = tb[TUNNEL_ATTR_TTL])) {
3091 uint32_t ttl = blobmsg_get_u32(cur);
3092 if (ttl < 1 || ttl > 255) {
3097 nla_put_u8(msg, IFLA_VXLAN_TTL, ttl);
3100 nla_nest_end(msg, data);
3101 nla_nest_end(msg, linkinfo);
3103 ret = system_rtnl_call(msg);
3105 D(SYSTEM, "Error adding vxlan '%s': %d\n", name, ret);
3115 static int system_add_sit_tunnel(const char *name, const unsigned int link, struct blob_attr **tb)
3117 struct blob_attr *cur;
3120 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
3124 if ((cur = tb[TUNNEL_ATTR_DATA])) {
3125 struct blob_attr *tb_data[__SIXRD_DATA_ATTR_MAX];
3127 struct ip_tunnel_6rd p6;
3129 blobmsg_parse(sixrd_data_attr_list.params, __SIXRD_DATA_ATTR_MAX, tb_data,
3130 blobmsg_data(cur), blobmsg_len(cur));
3132 memset(&p6, 0, sizeof(p6));
3134 if ((cur = tb_data[SIXRD_DATA_PREFIX])) {
3135 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
3136 &p6.prefix, &mask) || mask > 128) {
3141 p6.prefixlen = mask;
3144 if ((cur = tb_data[SIXRD_DATA_RELAY_PREFIX])) {
3145 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
3146 &p6.relay_prefix, &mask) || mask > 32) {
3151 p6.relay_prefixlen = mask;
3154 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
3164 __system_del_ip_tunnel(name, tb);
3168 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
3170 struct blob_attr *cur;
3172 struct ip_tunnel_parm p = {
3181 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
3182 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
3185 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
3186 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
3189 if ((cur = tb[TUNNEL_ATTR_DF]))
3190 set_df = blobmsg_get_bool(cur);
3192 if ((cur = tb[TUNNEL_ATTR_TTL]))
3193 p.iph.ttl = blobmsg_get_u32(cur);
3195 if ((cur = tb[TUNNEL_ATTR_TOS])) {
3196 char *str = blobmsg_get_string(cur);
3197 if (strcmp(str, "inherit")) {
3200 if (!system_tos_aton(str, &uval))
3208 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
3209 /* ttl !=0 and nopmtudisc are incompatible */
3210 if (p.iph.ttl && p.iph.frag_off == 0)
3213 strncpy(p.name, name, sizeof(p.name) - 1);
3215 switch (p.iph.protocol) {
3217 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
3219 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
3226 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
3228 struct blob_attr *cur;
3231 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
3233 str = blobmsg_data(cur);
3235 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
3236 !strcmp(str, "greip6") || !strcmp(str, "gretapip6") ||
3237 !strcmp(str, "vtiip") || !strcmp(str, "vtiip6") ||
3238 !strcmp(str, "vxlan") || !strcmp(str, "vxlan6") ||
3239 !strcmp(str, "xfrm"))
3240 return system_link_del(name);
3242 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
3245 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
3247 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
3249 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
3250 blob_data(attr), blob_len(attr));
3252 return __system_del_ip_tunnel(name, tb);
3255 int system_update_ipv6_mtu(struct device *dev, int mtu)
3261 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
3264 fd = open(buf, O_RDWR);
3269 ssize_t len = read(fd, buf, sizeof(buf) - 1);
3276 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) > 0)
3285 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
3287 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
3288 struct blob_attr *cur;
3291 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
3292 blob_data(attr), blob_len(attr));
3294 __system_del_ip_tunnel(name, tb);
3296 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
3298 str = blobmsg_data(cur);
3300 unsigned int ttl = 0;
3301 if ((cur = tb[TUNNEL_ATTR_TTL])) {
3302 ttl = blobmsg_get_u32(cur);
3307 unsigned int link = 0;
3308 if ((cur = tb[TUNNEL_ATTR_LINK])) {
3309 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
3313 if (iface->l3_dev.dev)
3314 link = iface->l3_dev.dev->ifindex;
3317 if (!strcmp(str, "sit"))
3318 return system_add_sit_tunnel(name, link, tb);
3319 #ifdef IFLA_IPTUN_MAX
3320 else if (!strcmp(str, "ipip6")) {
3321 return system_add_ip6_tunnel(name, link, tb);
3322 } else if (!strcmp(str, "greip")) {
3323 return system_add_gre_tunnel(name, "gre", link, tb, false);
3324 } else if (!strcmp(str, "gretapip")) {
3325 return system_add_gre_tunnel(name, "gretap", link, tb, false);
3326 } else if (!strcmp(str, "greip6")) {
3327 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
3328 } else if (!strcmp(str, "gretapip6")) {
3329 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
3331 } else if (!strcmp(str, "vtiip")) {
3332 return system_add_vti_tunnel(name, "vti", link, tb, false);
3333 } else if (!strcmp(str, "vtiip6")) {
3334 return system_add_vti_tunnel(name, "vti6", link, tb, true);
3336 #ifdef IFLA_XFRM_MAX
3337 } else if (!strcmp(str, "xfrm")) {
3338 return system_add_xfrm_tunnel(name, "xfrm", link, tb);
3340 #ifdef IFLA_VXLAN_MAX
3341 } else if(!strcmp(str, "vxlan")) {
3342 return system_add_vxlan(name, link, tb, false);
3343 } else if(!strcmp(str, "vxlan6")) {
3344 return system_add_vxlan(name, link, tb, true);
3347 } else if (!strcmp(str, "ipip")) {
3348 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);