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;
988 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
991 .rtm_flags = RTM_F_CLONED,
993 int flags = NLM_F_DUMP;
1005 clr.size = sizeof(struct rtgenmsg);
1008 clr.size = sizeof(struct rtmsg);
1014 clr.msg = nlmsg_alloc_simple(type, flags);
1018 nlmsg_append(clr.msg, &rtm, clr.size, 0);
1019 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
1020 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
1021 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
1023 if (nl_send_auto_complete(sock_rtnl, clr.msg) < 0)
1027 nl_recvmsgs(sock_rtnl, cb);
1030 nlmsg_free(clr.msg);
1036 * Clear bridge (membership) state and bring down device
1038 void system_if_clear_state(struct device *dev)
1040 static char buf[256];
1042 device_set_ifindex(dev, system_if_resolve(dev));
1044 if (dev->external || !dev->ifindex)
1047 system_if_flags(dev->ifname, 0, IFF_UP);
1049 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
1050 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
1051 system_bridge_delbr(dev);
1055 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
1057 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
1058 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
1061 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
1062 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
1063 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
1064 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
1065 system_if_clear_entries(dev, RTM_GETNEIGH, AF_INET);
1066 system_if_clear_entries(dev, RTM_GETNEIGH, AF_INET6);
1067 system_set_disable_ipv6(dev, "0");
1070 static inline unsigned long
1071 sec_to_jiffies(int val)
1073 return (unsigned long) val * 100;
1076 static void system_bridge_conf_multicast_deps(struct device *bridge,
1077 struct bridge_config *cfg,
1083 if (cfg->flags & BRIDGE_OPT_ROBUSTNESS ||
1084 cfg->flags & BRIDGE_OPT_QUERY_INTERVAL ||
1085 cfg->flags & BRIDGE_OPT_QUERY_RESPONSE_INTERVAL) {
1086 val = cfg->robustness * cfg->query_interval +
1087 cfg->query_response_interval;
1089 snprintf(buf, buf_len, "%i", val);
1090 system_bridge_set_membership_interval(bridge, buf);
1092 val = cfg->robustness * cfg->query_interval +
1093 cfg->query_response_interval / 2;
1095 snprintf(buf, buf_len, "%i", val);
1096 system_bridge_set_other_querier_timeout(bridge, buf);
1099 if (cfg->flags & BRIDGE_OPT_QUERY_INTERVAL) {
1100 val = cfg->query_interval / 4;
1102 snprintf(buf, buf_len, "%i", val);
1103 system_bridge_set_startup_query_interval(bridge, buf);
1107 static void system_bridge_conf_multicast(struct device *bridge,
1108 struct bridge_config *cfg,
1112 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
1113 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
1115 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier",
1116 bridge->ifname, cfg->multicast_querier ? "1" : "0");
1118 snprintf(buf, buf_len, "%i", cfg->hash_max);
1119 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/hash_max",
1120 bridge->ifname, buf);
1122 if (bridge->settings.flags & DEV_OPT_MULTICAST_ROUTER) {
1123 snprintf(buf, buf_len, "%u", bridge->settings.multicast_router);
1124 system_bridge_set_multicast_router(bridge, buf, true);
1127 if (cfg->flags & BRIDGE_OPT_ROBUSTNESS) {
1128 snprintf(buf, buf_len, "%i", cfg->robustness);
1129 system_bridge_set_robustness(bridge, buf);
1132 if (cfg->flags & BRIDGE_OPT_QUERY_INTERVAL) {
1133 snprintf(buf, buf_len, "%i", cfg->query_interval);
1134 system_bridge_set_query_interval(bridge, buf);
1137 if (cfg->flags & BRIDGE_OPT_QUERY_RESPONSE_INTERVAL) {
1138 snprintf(buf, buf_len, "%i", cfg->query_response_interval);
1139 system_bridge_set_query_response_interval(bridge, buf);
1142 if (cfg->flags & BRIDGE_OPT_LAST_MEMBER_INTERVAL) {
1143 snprintf(buf, buf_len, "%i", cfg->last_member_interval);
1144 system_bridge_set_last_member_interval(bridge, buf);
1147 system_bridge_conf_multicast_deps(bridge, cfg, buf, buf_len);
1150 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
1154 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
1157 system_bridge_set_stp_state(bridge, cfg->stp ? "1" : "0");
1159 snprintf(buf, sizeof(buf), "%lu", sec_to_jiffies(cfg->forward_delay));
1160 system_bridge_set_forward_delay(bridge, buf);
1162 system_bridge_conf_multicast(bridge, cfg, buf, sizeof(buf));
1164 snprintf(buf, sizeof(buf), "%d", cfg->priority);
1165 system_bridge_set_priority(bridge, buf);
1167 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
1168 snprintf(buf, sizeof(buf), "%lu", sec_to_jiffies(cfg->ageing_time));
1169 system_bridge_set_ageing_time(bridge, buf);
1172 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
1173 snprintf(buf, sizeof(buf), "%lu", sec_to_jiffies(cfg->hello_time));
1174 system_bridge_set_hello_time(bridge, buf);
1177 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
1178 snprintf(buf, sizeof(buf), "%lu", sec_to_jiffies(cfg->max_age));
1179 system_bridge_set_max_age(bridge, buf);
1185 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
1188 struct nlattr *linkinfo, *data;
1189 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
1191 static const struct {
1193 enum macvlan_mode val;
1195 { "private", MACVLAN_MODE_PRIVATE },
1196 { "vepa", MACVLAN_MODE_VEPA },
1197 { "bridge", MACVLAN_MODE_BRIDGE },
1198 { "passthru", MACVLAN_MODE_PASSTHRU },
1201 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1206 nlmsg_append(msg, &iim, sizeof(iim), 0);
1208 if (cfg->flags & MACVLAN_OPT_MACADDR)
1209 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
1210 nla_put_string(msg, IFLA_IFNAME, macvlan->ifname);
1211 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
1213 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1214 goto nla_put_failure;
1216 nla_put_string(msg, IFLA_INFO_KIND, "macvlan");
1218 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1219 goto nla_put_failure;
1222 for (i = 0; i < ARRAY_SIZE(modes); i++) {
1223 if (strcmp(cfg->mode, modes[i].name) != 0)
1226 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
1231 nla_nest_end(msg, data);
1232 nla_nest_end(msg, linkinfo);
1234 rv = system_rtnl_call(msg);
1236 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
1245 static int system_link_del(const char *ifname)
1248 struct ifinfomsg iim = {
1249 .ifi_family = AF_UNSPEC,
1253 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
1258 nlmsg_append(msg, &iim, sizeof(iim), 0);
1259 nla_put_string(msg, IFLA_IFNAME, ifname);
1260 return system_rtnl_call(msg);
1263 int system_macvlan_del(struct device *macvlan)
1265 return system_link_del(macvlan->ifname);
1268 int system_veth_add(struct device *veth, struct veth_config *cfg)
1271 struct ifinfomsg empty_iim = {};
1272 struct nlattr *linkinfo, *data, *veth_info;
1275 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1280 nlmsg_append(msg, &empty_iim, sizeof(empty_iim), 0);
1282 if (cfg->flags & VETH_OPT_MACADDR)
1283 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
1284 nla_put_string(msg, IFLA_IFNAME, veth->ifname);
1286 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1287 goto nla_put_failure;
1289 nla_put_string(msg, IFLA_INFO_KIND, "veth");
1291 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1292 goto nla_put_failure;
1294 if (!(veth_info = nla_nest_start(msg, VETH_INFO_PEER)))
1295 goto nla_put_failure;
1297 nlmsg_append(msg, &empty_iim, sizeof(empty_iim), 0);
1299 if (cfg->flags & VETH_OPT_PEER_NAME)
1300 nla_put_string(msg, IFLA_IFNAME, cfg->peer_name);
1301 if (cfg->flags & VETH_OPT_PEER_MACADDR)
1302 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->peer_macaddr), cfg->peer_macaddr);
1304 nla_nest_end(msg, veth_info);
1305 nla_nest_end(msg, data);
1306 nla_nest_end(msg, linkinfo);
1308 rv = system_rtnl_call(msg);
1310 if (cfg->flags & VETH_OPT_PEER_NAME)
1311 D(SYSTEM, "Error adding veth '%s' with peer '%s': %d\n", veth->ifname, cfg->peer_name, rv);
1313 D(SYSTEM, "Error adding veth '%s': %d\n", veth->ifname, rv);
1323 int system_veth_del(struct device *veth)
1325 return system_link_del(veth->ifname);
1328 static int system_vlan(struct device *dev, int id)
1330 struct vlan_ioctl_args ifr = {
1331 .cmd = SET_VLAN_NAME_TYPE_CMD,
1332 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
1335 if (ioctl(sock_ioctl, SIOCSIFVLAN, &ifr) < 0)
1339 ifr.cmd = DEL_VLAN_CMD;
1342 ifr.cmd = ADD_VLAN_CMD;
1345 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
1346 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
1349 int system_vlan_add(struct device *dev, int id)
1351 return system_vlan(dev, id);
1354 int system_vlan_del(struct device *dev)
1356 return system_vlan(dev, -1);
1359 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
1362 struct nlattr *linkinfo, *data;
1363 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
1366 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1371 nlmsg_append(msg, &iim, sizeof(iim), 0);
1372 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
1373 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
1375 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1376 goto nla_put_failure;
1378 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
1380 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1381 goto nla_put_failure;
1383 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
1385 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
1386 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
1388 if(cfg->proto == VLAN_PROTO_8021AD)
1389 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);
1392 nla_nest_end(msg, data);
1393 nla_nest_end(msg, linkinfo);
1395 rv = system_rtnl_call(msg);
1397 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
1406 int system_vlandev_del(struct device *vlandev)
1408 return system_link_del(vlandev->ifname);
1412 system_if_get_settings(struct device *dev, struct device_settings *s)
1417 memset(&ifr, 0, sizeof(ifr));
1418 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
1420 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
1421 s->mtu = ifr.ifr_mtu;
1422 s->flags |= DEV_OPT_MTU;
1425 s->mtu6 = system_update_ipv6_mtu(dev, 0);
1427 s->flags |= DEV_OPT_MTU6;
1429 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
1430 s->txqueuelen = ifr.ifr_qlen;
1431 s->flags |= DEV_OPT_TXQUEUELEN;
1434 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
1435 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
1436 s->flags |= DEV_OPT_MACADDR;
1439 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
1440 s->ipv6 = !strtoul(buf, NULL, 0);
1441 s->flags |= DEV_OPT_IPV6;
1444 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
1445 s->promisc = ifr.ifr_flags & IFF_PROMISC;
1446 s->flags |= DEV_OPT_PROMISC;
1448 s->multicast = ifr.ifr_flags & IFF_MULTICAST;
1449 s->flags |= DEV_OPT_MULTICAST;
1452 if (!system_get_rpfilter(dev, buf, sizeof(buf))) {
1453 s->rpfilter = strtoul(buf, NULL, 0);
1454 s->flags |= DEV_OPT_RPFILTER;
1457 if (!system_get_acceptlocal(dev, buf, sizeof(buf))) {
1458 s->acceptlocal = strtoul(buf, NULL, 0);
1459 s->flags |= DEV_OPT_ACCEPTLOCAL;
1462 if (!system_get_igmpversion(dev, buf, sizeof(buf))) {
1463 s->igmpversion = strtoul(buf, NULL, 0);
1464 s->flags |= DEV_OPT_IGMPVERSION;
1467 if (!system_get_mldversion(dev, buf, sizeof(buf))) {
1468 s->mldversion = strtoul(buf, NULL, 0);
1469 s->flags |= DEV_OPT_MLDVERSION;
1472 if (!system_get_neigh4reachabletime(dev, buf, sizeof(buf))) {
1473 s->neigh4reachabletime = strtoul(buf, NULL, 0);
1474 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1477 if (!system_get_neigh6reachabletime(dev, buf, sizeof(buf))) {
1478 s->neigh6reachabletime = strtoul(buf, NULL, 0);
1479 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1482 if (!system_get_neigh4locktime(dev, buf, sizeof(buf))) {
1483 s->neigh4locktime = strtol(buf, NULL, 0);
1484 s->flags |= DEV_OPT_NEIGHLOCKTIME;
1487 if (!system_get_neigh4gcstaletime(dev, buf, sizeof(buf))) {
1488 s->neigh4gcstaletime = strtoul(buf, NULL, 0);
1489 s->flags |= DEV_OPT_NEIGHGCSTALETIME;
1492 if (!system_get_neigh6gcstaletime(dev, buf, sizeof(buf))) {
1493 s->neigh6gcstaletime = strtoul(buf, NULL, 0);
1494 s->flags |= DEV_OPT_NEIGHGCSTALETIME;
1497 if (!system_get_dadtransmits(dev, buf, sizeof(buf))) {
1498 s->dadtransmits = strtoul(buf, NULL, 0);
1499 s->flags |= DEV_OPT_DADTRANSMITS;
1502 if (!system_get_sendredirects(dev, buf, sizeof(buf))) {
1503 s->sendredirects = strtoul(buf, NULL, 0);
1504 s->flags |= DEV_OPT_SENDREDIRECTS;
1509 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
1514 memset(&ifr, 0, sizeof(ifr));
1515 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
1516 if (s->flags & DEV_OPT_MTU & apply_mask) {
1517 ifr.ifr_mtu = s->mtu;
1518 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
1519 s->flags &= ~DEV_OPT_MTU;
1521 if (s->flags & DEV_OPT_MTU6 & apply_mask) {
1522 system_update_ipv6_mtu(dev, s->mtu6);
1524 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
1525 ifr.ifr_qlen = s->txqueuelen;
1526 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
1527 s->flags &= ~DEV_OPT_TXQUEUELEN;
1529 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
1530 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
1531 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
1532 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
1533 s->flags &= ~DEV_OPT_MACADDR;
1535 if (s->flags & DEV_OPT_IPV6 & apply_mask)
1536 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
1537 if (s->flags & DEV_OPT_PROMISC & apply_mask) {
1538 if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
1539 !s->promisc ? IFF_PROMISC : 0) < 0)
1540 s->flags &= ~DEV_OPT_PROMISC;
1542 if (s->flags & DEV_OPT_RPFILTER & apply_mask) {
1543 snprintf(buf, sizeof(buf), "%u", s->rpfilter);
1544 system_set_rpfilter(dev, buf);
1546 if (s->flags & DEV_OPT_ACCEPTLOCAL & apply_mask)
1547 system_set_acceptlocal(dev, s->acceptlocal ? "1" : "0");
1548 if (s->flags & DEV_OPT_IGMPVERSION & apply_mask) {
1549 snprintf(buf, sizeof(buf), "%u", s->igmpversion);
1550 system_set_igmpversion(dev, buf);
1552 if (s->flags & DEV_OPT_MLDVERSION & apply_mask) {
1553 snprintf(buf, sizeof(buf), "%u", s->mldversion);
1554 system_set_mldversion(dev, buf);
1556 if (s->flags & DEV_OPT_NEIGHREACHABLETIME & apply_mask) {
1557 snprintf(buf, sizeof(buf), "%u", s->neigh4reachabletime);
1558 system_set_neigh4reachabletime(dev, buf);
1559 snprintf(buf, sizeof(buf), "%u", s->neigh6reachabletime);
1560 system_set_neigh6reachabletime(dev, buf);
1562 if (s->flags & DEV_OPT_NEIGHLOCKTIME & apply_mask) {
1563 snprintf(buf, sizeof(buf), "%d", s->neigh4locktime);
1564 system_set_neigh4locktime(dev, buf);
1566 if (s->flags & DEV_OPT_NEIGHGCSTALETIME & apply_mask) {
1567 snprintf(buf, sizeof(buf), "%u", s->neigh4gcstaletime);
1568 system_set_neigh4gcstaletime(dev, buf);
1569 snprintf(buf, sizeof(buf), "%u", s->neigh6gcstaletime);
1570 system_set_neigh6gcstaletime(dev, buf);
1572 if (s->flags & DEV_OPT_DADTRANSMITS & apply_mask) {
1573 snprintf(buf, sizeof(buf), "%u", s->dadtransmits);
1574 system_set_dadtransmits(dev, buf);
1576 if (s->flags & DEV_OPT_MULTICAST & apply_mask) {
1577 if (system_if_flags(dev->ifname, s->multicast ? IFF_MULTICAST : 0,
1578 !s->multicast ? IFF_MULTICAST : 0) < 0)
1579 s->flags &= ~DEV_OPT_MULTICAST;
1581 if (s->flags & DEV_OPT_SENDREDIRECTS & apply_mask)
1582 system_set_sendredirects(dev, s->sendredirects ? "1" : "0");
1585 int system_if_up(struct device *dev)
1587 system_if_get_settings(dev, &dev->orig_settings);
1588 /* Only keep orig settings based on what needs to be set */
1589 dev->orig_settings.valid_flags = dev->orig_settings.flags;
1590 dev->orig_settings.flags &= dev->settings.flags;
1591 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
1592 return system_if_flags(dev->ifname, IFF_UP, 0);
1595 int system_if_down(struct device *dev)
1597 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
1598 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
1602 struct if_check_data {
1608 #ifndef IFF_LOWER_UP
1609 #define IFF_LOWER_UP 0x10000
1612 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1614 struct nlmsghdr *nh = nlmsg_hdr(msg);
1615 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1616 struct if_check_data *chk = (struct if_check_data *)arg;
1618 if (nh->nlmsg_type != RTM_NEWLINK)
1621 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1622 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1627 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1629 struct if_check_data *chk = (struct if_check_data *)arg;
1634 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1636 struct if_check_data *chk = (struct if_check_data *)arg;
1638 device_set_present(chk->dev, false);
1639 device_set_link(chk->dev, false);
1640 chk->pending = err->error;
1645 int system_if_check(struct device *dev)
1647 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1649 struct ifinfomsg ifi = {
1650 .ifi_family = AF_UNSPEC,
1653 struct if_check_data chk = {
1662 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1666 if (nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1667 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1670 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1671 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1672 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1674 ret = nl_send_auto_complete(sock_rtnl, msg);
1678 while (chk.pending > 0)
1679 nl_recvmsgs(sock_rtnl, cb);
1691 system_if_get_parent(struct device *dev)
1693 char buf[64], *devname;
1694 int ifindex, iflink, len;
1697 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1698 f = fopen(buf, "r");
1702 len = fread(buf, 1, sizeof(buf) - 1, f);
1709 iflink = strtoul(buf, NULL, 0);
1710 ifindex = system_if_resolve(dev);
1711 if (!iflink || iflink == ifindex)
1714 devname = if_indextoname(iflink, buf);
1718 return device_get(devname, true);
1722 read_string_file(int dir_fd, const char *file, char *buf, int len)
1728 fd = openat(dir_fd, file, O_RDONLY);
1733 len = read(fd, buf, len - 1);
1737 } else if (len > 0) {
1740 c = strchr(buf, '\n');
1753 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1758 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1760 *val = strtoull(buf, NULL, 0);
1765 /* Assume advertised flags == supported flags */
1766 static const struct {
1769 } ethtool_link_modes[] = {
1770 { ADVERTISED_10baseT_Half, "10baseT-H" },
1771 { ADVERTISED_10baseT_Full, "10baseT-F" },
1772 { ADVERTISED_100baseT_Half, "100baseT-H" },
1773 { ADVERTISED_100baseT_Full, "100baseT-F" },
1774 { ADVERTISED_1000baseT_Half, "1000baseT-H" },
1775 { ADVERTISED_1000baseT_Full, "1000baseT-F" },
1776 { ADVERTISED_1000baseKX_Full, "1000baseKX-F" },
1777 { ADVERTISED_2500baseX_Full, "2500baseX-F" },
1778 { ADVERTISED_10000baseT_Full, "10000baseT-F" },
1779 { ADVERTISED_10000baseKX4_Full, "10000baseKX4-F" },
1780 { ADVERTISED_10000baseKR_Full, "10000baseKR-F" },
1781 { ADVERTISED_20000baseMLD2_Full, "20000baseMLD2-F" },
1782 { ADVERTISED_20000baseKR2_Full, "20000baseKR2-F" },
1783 { ADVERTISED_40000baseKR4_Full, "40000baseKR4-F" },
1784 { ADVERTISED_40000baseCR4_Full, "40000baseCR4-F" },
1785 { ADVERTISED_40000baseSR4_Full, "40000baseSR4-F" },
1786 { ADVERTISED_40000baseLR4_Full, "40000baseLR4-F" },
1787 #ifdef ADVERTISED_56000baseKR4_Full
1788 { ADVERTISED_56000baseKR4_Full, "56000baseKR4-F" },
1789 { ADVERTISED_56000baseCR4_Full, "56000baseCR4-F" },
1790 { ADVERTISED_56000baseSR4_Full, "56000baseSR4-F" },
1791 { ADVERTISED_56000baseLR4_Full, "56000baseLR4-F" },
1795 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1798 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1799 if (mask & ethtool_link_modes[i].mask)
1800 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1805 system_if_force_external(const char *ifname)
1810 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1811 return stat(buf, &s) == 0;
1815 system_if_dump_info(struct device *dev, struct blob_buf *b)
1817 struct ethtool_cmd ecmd;
1822 memset(&ecmd, 0, sizeof(ecmd));
1823 memset(&ifr, 0, sizeof(ifr));
1824 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
1825 ifr.ifr_data = (caddr_t) &ecmd;
1826 ecmd.cmd = ETHTOOL_GSET;
1828 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1829 c = blobmsg_open_array(b, "link-advertising");
1830 system_add_link_modes(b, ecmd.advertising);
1831 blobmsg_close_array(b, c);
1833 c = blobmsg_open_array(b, "link-partner-advertising");
1834 system_add_link_modes(b, ecmd.lp_advertising);
1835 blobmsg_close_array(b, c);
1837 c = blobmsg_open_array(b, "link-supported");
1838 system_add_link_modes(b, ecmd.supported);
1839 blobmsg_close_array(b, c);
1841 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1842 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1843 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1844 blobmsg_add_string_buffer(b);
1846 blobmsg_add_u8(b, "autoneg", !!ecmd.autoneg);
1853 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1855 const char *const counters[] = {
1856 "collisions", "rx_frame_errors", "tx_compressed",
1857 "multicast", "rx_length_errors", "tx_dropped",
1858 "rx_bytes", "rx_missed_errors", "tx_errors",
1859 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1860 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1861 "rx_dropped", "tx_aborted_errors", "tx_packets",
1862 "rx_errors", "tx_bytes", "tx_window_errors",
1863 "rx_fifo_errors", "tx_carrier_errors",
1870 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1871 stats_dir = open(buf, O_DIRECTORY);
1875 for (i = 0; i < ARRAY_SIZE(counters); i++)
1876 if (read_uint64_file(stats_dir, counters[i], &val))
1877 blobmsg_add_u64(b, counters[i], val);
1883 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1885 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1886 int alen = v4 ? 4 : 16;
1887 unsigned int flags = 0;
1888 struct ifaddrmsg ifa = {
1889 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1890 .ifa_prefixlen = addr->mask,
1891 .ifa_index = dev->ifindex,
1895 if (cmd == RTM_NEWADDR)
1896 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1898 msg = nlmsg_alloc_simple(cmd, flags);
1902 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1903 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1905 if (addr->broadcast)
1906 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1907 if (addr->point_to_point)
1908 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1910 time_t now = system_get_rtime();
1911 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1913 if (addr->preferred_until) {
1914 int64_t preferred = addr->preferred_until - now;
1917 else if (preferred > UINT32_MAX)
1918 preferred = UINT32_MAX;
1920 cinfo.ifa_prefered = preferred;
1923 if (addr->valid_until) {
1924 int64_t valid = addr->valid_until - now;
1929 else if (valid > UINT32_MAX)
1932 cinfo.ifa_valid = valid;
1935 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1937 if (cmd == RTM_NEWADDR && (addr->flags & DEVADDR_OFFLINK))
1938 nla_put_u32(msg, IFA_FLAGS, IFA_F_NOPREFIXROUTE);
1941 return system_rtnl_call(msg);
1944 int system_add_address(struct device *dev, struct device_addr *addr)
1946 return system_addr(dev, addr, RTM_NEWADDR);
1949 int system_del_address(struct device *dev, struct device_addr *addr)
1951 return system_addr(dev, addr, RTM_DELADDR);
1954 static int system_neigh(struct device *dev, struct device_neighbor *neighbor, int cmd)
1956 int alen = ((neighbor->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1957 unsigned int flags = 0;
1958 struct ndmsg ndm = {
1959 .ndm_family = (alen == 4) ? AF_INET : AF_INET6,
1960 .ndm_ifindex = dev->ifindex,
1961 .ndm_state = NUD_PERMANENT,
1962 .ndm_flags = (neighbor->proxy ? NTF_PROXY : 0) | (neighbor->router ? NTF_ROUTER : 0),
1966 if (cmd == RTM_NEWNEIGH)
1967 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1969 msg = nlmsg_alloc_simple(cmd, flags);
1974 nlmsg_append(msg, &ndm, sizeof(ndm), 0);
1976 nla_put(msg, NDA_DST, alen, &neighbor->addr);
1977 if (neighbor->flags & DEVNEIGH_MAC)
1978 nla_put(msg, NDA_LLADDR, sizeof(neighbor->macaddr), &neighbor->macaddr);
1981 return system_rtnl_call(msg);
1984 int system_add_neighbor(struct device *dev, struct device_neighbor *neighbor)
1986 return system_neigh(dev, neighbor, RTM_NEWNEIGH);
1989 int system_del_neighbor(struct device *dev, struct device_neighbor *neighbor)
1991 return system_neigh(dev, neighbor, RTM_DELNEIGH);
1994 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1996 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1998 unsigned int flags = 0;
2001 have_gw = !!route->nexthop.in.s_addr;
2003 have_gw = route->nexthop.in6.s6_addr32[0] ||
2004 route->nexthop.in6.s6_addr32[1] ||
2005 route->nexthop.in6.s6_addr32[2] ||
2006 route->nexthop.in6.s6_addr32[3];
2008 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
2009 ? route->table : RT_TABLE_MAIN;
2011 struct rtmsg rtm = {
2012 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
2013 .rtm_dst_len = route->mask,
2014 .rtm_src_len = route->sourcemask,
2015 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
2016 .rtm_protocol = (route->flags & DEVROUTE_PROTO) ? route->proto : RTPROT_STATIC,
2017 .rtm_scope = RT_SCOPE_NOWHERE,
2018 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
2019 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
2023 if (cmd == RTM_NEWROUTE) {
2024 flags |= NLM_F_CREATE | NLM_F_REPLACE;
2026 if (!dev) { /* Add null-route */
2027 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
2028 rtm.rtm_type = RTN_UNREACHABLE;
2031 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
2034 if (route->flags & DEVROUTE_TYPE) {
2035 rtm.rtm_type = route->type;
2036 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
2037 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
2038 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
2039 rtm.rtm_table = RT_TABLE_LOCAL;
2042 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT) {
2043 rtm.rtm_scope = RT_SCOPE_HOST;
2044 } else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
2045 rtm.rtm_type == RTN_ANYCAST) {
2046 rtm.rtm_scope = RT_SCOPE_LINK;
2047 } else if (rtm.rtm_type == RTN_BLACKHOLE || rtm.rtm_type == RTN_UNREACHABLE ||
2048 rtm.rtm_type == RTN_PROHIBIT || rtm.rtm_type == RTN_FAILED_POLICY ||
2049 rtm.rtm_type == RTN_THROW) {
2050 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
2055 msg = nlmsg_alloc_simple(cmd, flags);
2059 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
2062 nla_put(msg, RTA_DST, alen, &route->addr);
2064 if (route->sourcemask) {
2065 if (rtm.rtm_family == AF_INET)
2066 nla_put(msg, RTA_PREFSRC, alen, &route->source);
2068 nla_put(msg, RTA_SRC, alen, &route->source);
2071 if (route->metric > 0)
2072 nla_put_u32(msg, RTA_PRIORITY, route->metric);
2075 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
2078 nla_put_u32(msg, RTA_OIF, dev->ifindex);
2081 nla_put_u32(msg, RTA_TABLE, table);
2083 if (route->flags & DEVROUTE_MTU) {
2084 struct nlattr *metrics;
2086 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
2087 goto nla_put_failure;
2089 nla_put_u32(msg, RTAX_MTU, route->mtu);
2091 nla_nest_end(msg, metrics);
2094 return system_rtnl_call(msg);
2101 int system_add_route(struct device *dev, struct device_route *route)
2103 return system_rt(dev, route, RTM_NEWROUTE);
2106 int system_del_route(struct device *dev, struct device_route *route)
2108 return system_rt(dev, route, RTM_DELROUTE);
2111 int system_flush_routes(void)
2113 const char *names[] = {
2114 "/proc/sys/net/ipv4/route/flush",
2115 "/proc/sys/net/ipv6/route/flush"
2119 for (i = 0; i < ARRAY_SIZE(names); i++) {
2120 fd = open(names[i], O_WRONLY);
2124 if (write(fd, "-1", 2)) {}
2130 bool system_resolve_rt_type(const char *type, unsigned int *id)
2132 return system_rtn_aton(type, id);
2135 bool system_resolve_rt_proto(const char *type, unsigned int *id)
2139 unsigned int n, proto = 256;
2140 n = strtoul(type, &e, 0);
2141 if (!*e && e != type)
2143 else if (!strcmp(type, "unspec"))
2144 proto = RTPROT_UNSPEC;
2145 else if (!strcmp(type, "kernel"))
2146 proto = RTPROT_KERNEL;
2147 else if (!strcmp(type, "boot"))
2148 proto = RTPROT_BOOT;
2149 else if (!strcmp(type, "static"))
2150 proto = RTPROT_STATIC;
2151 else if ((f = fopen("/etc/iproute2/rt_protos", "r")) != NULL) {
2152 while (fgets(buf, sizeof(buf) - 1, f) != NULL) {
2153 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
2156 n = strtoul(e, NULL, 10);
2157 e = strtok(NULL, " \t\n");
2159 if (e && !strcmp(e, type)) {
2174 bool system_resolve_rt_table(const char *name, unsigned int *id)
2178 unsigned int n, table = RT_TABLE_UNSPEC;
2180 /* first try to parse table as number */
2181 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
2184 /* handle well known aliases */
2185 else if (!strcmp(name, "default"))
2186 table = RT_TABLE_DEFAULT;
2187 else if (!strcmp(name, "main"))
2188 table = RT_TABLE_MAIN;
2189 else if (!strcmp(name, "local"))
2190 table = RT_TABLE_LOCAL;
2192 /* try to look up name in /etc/iproute2/rt_tables */
2193 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
2195 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
2197 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
2200 n = strtoul(e, NULL, 10);
2201 e = strtok(NULL, " \t\n");
2203 if (e && !strcmp(e, name))
2213 if (table == RT_TABLE_UNSPEC)
2220 bool system_is_default_rt_table(unsigned int id)
2222 return (id == RT_TABLE_MAIN);
2225 bool system_resolve_rpfilter(const char *filter, unsigned int *id)
2230 if (!strcmp(filter, "strict"))
2232 else if (!strcmp(filter, "loose"))
2235 n = strtoul(filter, &e, 0);
2236 if (*e || e == filter || n > 2)
2244 static int system_iprule(struct iprule *rule, int cmd)
2246 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
2249 struct rtmsg rtm = {
2250 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
2251 .rtm_protocol = RTPROT_STATIC,
2252 .rtm_scope = RT_SCOPE_UNIVERSE,
2253 .rtm_table = RT_TABLE_UNSPEC,
2254 .rtm_type = RTN_UNSPEC,
2258 if (cmd == RTM_NEWRULE)
2259 rtm.rtm_type = RTN_UNICAST;
2262 rtm.rtm_flags |= FIB_RULE_INVERT;
2264 if (rule->flags & IPRULE_SRC)
2265 rtm.rtm_src_len = rule->src_mask;
2267 if (rule->flags & IPRULE_DEST)
2268 rtm.rtm_dst_len = rule->dest_mask;
2270 if (rule->flags & IPRULE_TOS)
2271 rtm.rtm_tos = rule->tos;
2273 if (rule->flags & IPRULE_LOOKUP) {
2274 if (rule->lookup < 256)
2275 rtm.rtm_table = rule->lookup;
2278 if (rule->flags & IPRULE_ACTION)
2279 rtm.rtm_type = rule->action;
2280 else if (rule->flags & IPRULE_GOTO)
2281 rtm.rtm_type = FR_ACT_GOTO;
2282 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
2283 rtm.rtm_type = FR_ACT_NOP;
2285 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
2290 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
2292 if (rule->flags & IPRULE_IN)
2293 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
2295 if (rule->flags & IPRULE_OUT)
2296 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
2298 if (rule->flags & IPRULE_SRC)
2299 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
2301 if (rule->flags & IPRULE_DEST)
2302 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
2304 if (rule->flags & IPRULE_PRIORITY)
2305 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
2306 else if (cmd == RTM_NEWRULE)
2307 nla_put_u32(msg, FRA_PRIORITY, rule->order);
2309 if (rule->flags & IPRULE_FWMARK)
2310 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
2312 if (rule->flags & IPRULE_FWMASK)
2313 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
2315 if (rule->flags & IPRULE_LOOKUP) {
2316 if (rule->lookup >= 256)
2317 nla_put_u32(msg, FRA_TABLE, rule->lookup);
2320 if (rule->flags & IPRULE_SUP_PREFIXLEN)
2321 nla_put_u32(msg, FRA_SUPPRESS_PREFIXLEN, rule->sup_prefixlen);
2323 if (rule->flags & IPRULE_GOTO)
2324 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
2326 return system_rtnl_call(msg);
2329 int system_add_iprule(struct iprule *rule)
2331 return system_iprule(rule, RTM_NEWRULE);
2334 int system_del_iprule(struct iprule *rule)
2336 return system_iprule(rule, RTM_DELRULE);
2339 int system_flush_iprules(void)
2344 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
2345 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
2347 memset(&rule, 0, sizeof(rule));
2350 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2353 rule.lookup = RT_TABLE_LOCAL;
2354 rv |= system_iprule(&rule, RTM_NEWRULE);
2356 rule.priority = 32766;
2357 rule.lookup = RT_TABLE_MAIN;
2358 rv |= system_iprule(&rule, RTM_NEWRULE);
2360 rule.priority = 32767;
2361 rule.lookup = RT_TABLE_DEFAULT;
2362 rv |= system_iprule(&rule, RTM_NEWRULE);
2365 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2368 rule.lookup = RT_TABLE_LOCAL;
2369 rv |= system_iprule(&rule, RTM_NEWRULE);
2371 rule.priority = 32766;
2372 rule.lookup = RT_TABLE_MAIN;
2373 rv |= system_iprule(&rule, RTM_NEWRULE);
2378 bool system_resolve_iprule_action(const char *action, unsigned int *id)
2380 return system_rtn_aton(action, id);
2383 time_t system_get_rtime(void)
2388 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
2391 if (gettimeofday(&tv, NULL) == 0)
2398 #define IP_DF 0x4000
2401 static int tunnel_ioctl(const char *name, int cmd, void *p)
2405 memset(&ifr, 0, sizeof(ifr));
2406 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name) - 1);
2407 ifr.ifr_ifru.ifru_data = p;
2408 return ioctl(sock_ioctl, cmd, &ifr);
2411 #ifdef IFLA_IPTUN_MAX
2412 static int system_add_ip6_tunnel(const char *name, const unsigned int link,
2413 struct blob_attr **tb)
2415 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2416 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2417 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2418 struct blob_attr *cur;
2419 int ret = 0, ttl = 0;
2424 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2425 nla_put_string(nlm, IFLA_IFNAME, name);
2428 nla_put_u32(nlm, IFLA_LINK, link);
2430 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2436 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2437 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2444 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2446 if ((cur = tb[TUNNEL_ATTR_TTL]))
2447 ttl = blobmsg_get_u32(cur);
2449 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2450 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2452 struct in6_addr in6buf;
2453 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2454 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2458 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2461 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2462 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2466 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2469 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2470 struct blob_attr *tb_data[__IPIP6_DATA_ATTR_MAX];
2471 uint32_t tun_flags = IP6_TNL_F_IGN_ENCAP_LIMIT;
2473 blobmsg_parse(ipip6_data_attr_list.params, __IPIP6_DATA_ATTR_MAX, tb_data,
2474 blobmsg_data(cur), blobmsg_len(cur));
2476 if ((cur = tb_data[IPIP6_DATA_ENCAPLIMIT])) {
2477 char *str = blobmsg_get_string(cur);
2479 if (strcmp(str, "ignore")) {
2481 unsigned encap_limit = strtoul(str, &e, 0);
2483 if (e == str || *e || encap_limit > 255) {
2488 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, encap_limit);
2489 tun_flags &= ~IP6_TNL_F_IGN_ENCAP_LIMIT;
2493 #ifdef IFLA_IPTUN_FMR_MAX
2494 if ((cur = tb_data[IPIP6_DATA_FMRS])) {
2495 struct blob_attr *rcur;
2496 unsigned rrem, fmrcnt = 0;
2497 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2504 blobmsg_for_each_attr(rcur, cur, rrem) {
2505 struct blob_attr *tb_fmr[__FMR_DATA_ATTR_MAX], *tb_cur;
2506 struct in6_addr ip6prefix;
2507 struct in_addr ip4prefix;
2508 unsigned ip4len, ip6len, ealen, offset;
2510 blobmsg_parse(fmr_data_attr_list.params, __FMR_DATA_ATTR_MAX, tb_fmr,
2511 blobmsg_data(rcur), blobmsg_len(rcur));
2513 if (!(tb_cur = tb_fmr[FMR_DATA_PREFIX6]) ||
2514 !parse_ip_and_netmask(AF_INET6,
2515 blobmsg_data(tb_cur), &ip6prefix,
2521 if (!(tb_cur = tb_fmr[FMR_DATA_PREFIX4]) ||
2522 !parse_ip_and_netmask(AF_INET,
2523 blobmsg_data(tb_cur), &ip4prefix,
2529 if (!(tb_cur = tb_fmr[FMR_DATA_EALEN])) {
2533 ealen = blobmsg_get_u32(tb_cur);
2535 if (!(tb_cur = tb_fmr[FMR_DATA_OFFSET])) {
2539 offset = blobmsg_get_u32(tb_cur);
2541 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2547 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2548 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2549 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2550 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2551 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2552 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2554 nla_nest_end(nlm, rule);
2557 nla_nest_end(nlm, fmrs);
2561 nla_put_u32(nlm, IFLA_IPTUN_FLAGS, tun_flags);
2564 nla_nest_end(nlm, infodata);
2565 nla_nest_end(nlm, linkinfo);
2567 return system_rtnl_call(nlm);
2575 #ifdef IFLA_IPTUN_MAX
2576 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
2577 static int system_add_gre_tunnel(const char *name, const char *kind,
2578 const unsigned int link, struct blob_attr **tb, bool v6)
2581 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2582 struct blob_attr *cur;
2583 uint32_t ikey = 0, okey = 0, flowinfo = 0, flags6 = IP6_TNL_F_IGN_ENCAP_LIMIT;
2584 uint16_t iflags = 0, oflags = 0;
2586 int ret = 0, ttl = 0;
2587 unsigned encap_limit = 0;
2589 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2593 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2594 nla_put_string(nlm, IFLA_IFNAME, name);
2596 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2602 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2603 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2610 nla_put_u32(nlm, IFLA_GRE_LINK, link);
2612 if ((cur = tb[TUNNEL_ATTR_TTL]))
2613 ttl = blobmsg_get_u32(cur);
2615 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2616 char *str = blobmsg_get_string(cur);
2617 if (strcmp(str, "inherit")) {
2620 if (!system_tos_aton(str, &uval)) {
2626 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
2631 flags6 |= IP6_TNL_F_USE_ORIG_TCLASS;
2637 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2638 struct blob_attr *tb_data[__GRE_DATA_ATTR_MAX];
2640 blobmsg_parse(gre_data_attr_list.params, __GRE_DATA_ATTR_MAX, tb_data,
2641 blobmsg_data(cur), blobmsg_len(cur));
2643 if ((cur = tb_data[GRE_DATA_IKEY])) {
2644 if ((ikey = blobmsg_get_u32(cur)))
2648 if ((cur = tb_data[GRE_DATA_OKEY])) {
2649 if ((okey = blobmsg_get_u32(cur)))
2653 if ((cur = tb_data[GRE_DATA_ICSUM])) {
2654 if (blobmsg_get_bool(cur))
2658 if ((cur = tb_data[GRE_DATA_OCSUM])) {
2659 if (blobmsg_get_bool(cur))
2663 if ((cur = tb_data[GRE_DATA_ISEQNO])) {
2664 if (blobmsg_get_bool(cur))
2668 if ((cur = tb_data[GRE_DATA_OSEQNO])) {
2669 if (blobmsg_get_bool(cur))
2673 if ((cur = tb_data[GRE_DATA_ENCAPLIMIT])) {
2674 char *str = blobmsg_get_string(cur);
2676 if (strcmp(str, "ignore")) {
2679 encap_limit = strtoul(str, &e, 0);
2681 if (e == str || *e || encap_limit > 255) {
2686 flags6 &= ~IP6_TNL_F_IGN_ENCAP_LIMIT;
2692 struct in6_addr in6buf;
2693 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2694 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2698 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
2701 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2702 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2706 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
2709 if (!(flags6 & IP6_TNL_F_IGN_ENCAP_LIMIT))
2710 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, encap_limit);
2713 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
2716 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags6);
2721 struct in_addr inbuf;
2724 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2725 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2729 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
2732 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2733 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2737 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
2739 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
2741 okey = inbuf.s_addr;
2746 ikey = inbuf.s_addr;
2752 if ((cur = tb[TUNNEL_ATTR_DF]))
2753 set_df = blobmsg_get_bool(cur);
2756 /* ttl != 0 and nopmtudisc are incompatible */
2764 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
2766 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
2770 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
2773 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
2776 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
2779 nla_put_u32(nlm, IFLA_GRE_OKEY, htonl(okey));
2782 nla_put_u32(nlm, IFLA_GRE_IKEY, htonl(ikey));
2784 nla_nest_end(nlm, infodata);
2785 nla_nest_end(nlm, linkinfo);
2787 return system_rtnl_call(nlm);
2796 static int system_add_vti_tunnel(const char *name, const char *kind,
2797 const unsigned int link, struct blob_attr **tb, bool v6)
2800 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2801 struct blob_attr *cur;
2804 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2808 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2809 nla_put_string(nlm, IFLA_IFNAME, name);
2811 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2817 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2818 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2825 nla_put_u32(nlm, IFLA_VTI_LINK, link);
2828 struct in6_addr in6buf;
2829 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2830 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2834 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(in6buf), &in6buf);
2837 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2838 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2842 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(in6buf), &in6buf);
2846 struct in_addr inbuf;
2848 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2849 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2853 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(inbuf), &inbuf);
2856 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2857 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2861 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(inbuf), &inbuf);
2866 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2867 struct blob_attr *tb_data[__VTI_DATA_ATTR_MAX];
2868 uint32_t ikey = 0, okey = 0;
2870 blobmsg_parse(vti_data_attr_list.params, __VTI_DATA_ATTR_MAX, tb_data,
2871 blobmsg_data(cur), blobmsg_len(cur));
2873 if ((cur = tb_data[VTI_DATA_IKEY])) {
2874 if ((ikey = blobmsg_get_u32(cur)))
2875 nla_put_u32(nlm, IFLA_VTI_IKEY, htonl(ikey));
2878 if ((cur = tb_data[VTI_DATA_OKEY])) {
2879 if ((okey = blobmsg_get_u32(cur)))
2880 nla_put_u32(nlm, IFLA_VTI_OKEY, htonl(okey));
2884 nla_nest_end(nlm, infodata);
2885 nla_nest_end(nlm, linkinfo);
2887 return system_rtnl_call(nlm);
2895 #ifdef IFLA_XFRM_MAX
2896 static int system_add_xfrm_tunnel(const char *name, const char *kind,
2897 const unsigned int link, struct blob_attr **tb)
2900 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2901 struct blob_attr *cur;
2904 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2908 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2909 nla_put_string(nlm, IFLA_IFNAME, name);
2911 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2917 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2918 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2925 nla_put_u32(nlm, IFLA_XFRM_LINK, link);
2927 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2928 struct blob_attr *tb_data[__XFRM_DATA_ATTR_MAX];
2931 blobmsg_parse(xfrm_data_attr_list.params, __XFRM_DATA_ATTR_MAX, tb_data,
2932 blobmsg_data(cur), blobmsg_len(cur));
2934 if ((cur = tb_data[XFRM_DATA_IF_ID])) {
2935 if ((if_id = blobmsg_get_u32(cur)))
2936 nla_put_u32(nlm, IFLA_XFRM_IF_ID, if_id);
2941 nla_nest_end(nlm, infodata);
2942 nla_nest_end(nlm, linkinfo);
2944 return system_rtnl_call(nlm);
2952 #ifdef IFLA_VXLAN_MAX
2953 static int system_add_vxlan(const char *name, const unsigned int link, struct blob_attr **tb, bool v6)
2955 struct blob_attr *tb_data[__VXLAN_DATA_ATTR_MAX];
2957 struct nlattr *linkinfo, *data;
2958 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
2959 struct blob_attr *cur;
2962 if ((cur = tb[TUNNEL_ATTR_DATA]))
2963 blobmsg_parse(vxlan_data_attr_list.params, __VXLAN_DATA_ATTR_MAX, tb_data,
2964 blobmsg_data(cur), blobmsg_len(cur));
2968 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
2973 nlmsg_append(msg, &iim, sizeof(iim), 0);
2975 nla_put_string(msg, IFLA_IFNAME, name);
2977 if ((cur = tb_data[VXLAN_DATA_ATTR_MACADDR])) {
2978 struct ether_addr *ea = ether_aton(blobmsg_get_string(cur));
2984 nla_put(msg, IFLA_ADDRESS, ETH_ALEN, ea);
2987 if ((cur = tb[TUNNEL_ATTR_MTU])) {
2988 uint32_t mtu = blobmsg_get_u32(cur);
2989 nla_put_u32(msg, IFLA_MTU, mtu);
2992 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO))) {
2997 nla_put_string(msg, IFLA_INFO_KIND, "vxlan");
2999 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) {
3005 nla_put_u32(msg, IFLA_VXLAN_LINK, link);
3007 if ((cur = tb_data[VXLAN_DATA_ATTR_ID])) {
3008 uint32_t id = blobmsg_get_u32(cur);
3009 if (id >= (1u << 24) - 1) {
3014 nla_put_u32(msg, IFLA_VXLAN_ID, id);
3018 struct in6_addr in6buf;
3019 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
3020 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
3024 nla_put(msg, IFLA_VXLAN_LOCAL6, sizeof(in6buf), &in6buf);
3027 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
3028 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
3032 nla_put(msg, IFLA_VXLAN_GROUP6, sizeof(in6buf), &in6buf);
3035 struct in_addr inbuf;
3037 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
3038 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
3042 nla_put(msg, IFLA_VXLAN_LOCAL, sizeof(inbuf), &inbuf);
3045 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
3046 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
3050 nla_put(msg, IFLA_VXLAN_GROUP, sizeof(inbuf), &inbuf);
3054 uint32_t port = 4789;
3055 if ((cur = tb_data[VXLAN_DATA_ATTR_PORT])) {
3056 port = blobmsg_get_u32(cur);
3057 if (port < 1 || port > 65535) {
3062 nla_put_u16(msg, IFLA_VXLAN_PORT, htons(port));
3064 if ((cur = tb_data[VXLAN_DATA_ATTR_RXCSUM])) {
3065 bool rxcsum = blobmsg_get_bool(cur);
3066 nla_put_u8(msg, IFLA_VXLAN_UDP_ZERO_CSUM6_RX, !rxcsum);
3069 if ((cur = tb_data[VXLAN_DATA_ATTR_TXCSUM])) {
3070 bool txcsum = blobmsg_get_bool(cur);
3071 nla_put_u8(msg, IFLA_VXLAN_UDP_CSUM, txcsum);
3072 nla_put_u8(msg, IFLA_VXLAN_UDP_ZERO_CSUM6_TX, !txcsum);
3075 if ((cur = tb[TUNNEL_ATTR_TOS])) {
3076 char *str = blobmsg_get_string(cur);
3079 if (strcmp(str, "inherit")) {
3080 if (!system_tos_aton(str, &tos)) {
3086 nla_put_u8(msg, IFLA_VXLAN_TOS, tos);
3089 if ((cur = tb[TUNNEL_ATTR_TTL])) {
3090 uint32_t ttl = blobmsg_get_u32(cur);
3091 if (ttl < 1 || ttl > 255) {
3096 nla_put_u8(msg, IFLA_VXLAN_TTL, ttl);
3099 nla_nest_end(msg, data);
3100 nla_nest_end(msg, linkinfo);
3102 ret = system_rtnl_call(msg);
3104 D(SYSTEM, "Error adding vxlan '%s': %d\n", name, ret);
3114 static int system_add_sit_tunnel(const char *name, const unsigned int link, struct blob_attr **tb)
3116 struct blob_attr *cur;
3119 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
3123 if ((cur = tb[TUNNEL_ATTR_DATA])) {
3124 struct blob_attr *tb_data[__SIXRD_DATA_ATTR_MAX];
3126 struct ip_tunnel_6rd p6;
3128 blobmsg_parse(sixrd_data_attr_list.params, __SIXRD_DATA_ATTR_MAX, tb_data,
3129 blobmsg_data(cur), blobmsg_len(cur));
3131 memset(&p6, 0, sizeof(p6));
3133 if ((cur = tb_data[SIXRD_DATA_PREFIX])) {
3134 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
3135 &p6.prefix, &mask) || mask > 128) {
3140 p6.prefixlen = mask;
3143 if ((cur = tb_data[SIXRD_DATA_RELAY_PREFIX])) {
3144 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
3145 &p6.relay_prefix, &mask) || mask > 32) {
3150 p6.relay_prefixlen = mask;
3153 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
3163 __system_del_ip_tunnel(name, tb);
3167 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
3169 struct blob_attr *cur;
3171 struct ip_tunnel_parm p = {
3180 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
3181 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
3184 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
3185 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
3188 if ((cur = tb[TUNNEL_ATTR_DF]))
3189 set_df = blobmsg_get_bool(cur);
3191 if ((cur = tb[TUNNEL_ATTR_TTL]))
3192 p.iph.ttl = blobmsg_get_u32(cur);
3194 if ((cur = tb[TUNNEL_ATTR_TOS])) {
3195 char *str = blobmsg_get_string(cur);
3196 if (strcmp(str, "inherit")) {
3199 if (!system_tos_aton(str, &uval))
3207 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
3208 /* ttl !=0 and nopmtudisc are incompatible */
3209 if (p.iph.ttl && p.iph.frag_off == 0)
3212 strncpy(p.name, name, sizeof(p.name) - 1);
3214 switch (p.iph.protocol) {
3216 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
3218 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
3225 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
3227 struct blob_attr *cur;
3230 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
3232 str = blobmsg_data(cur);
3234 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
3235 !strcmp(str, "greip6") || !strcmp(str, "gretapip6") ||
3236 !strcmp(str, "vtiip") || !strcmp(str, "vtiip6") ||
3237 !strcmp(str, "vxlan") || !strcmp(str, "vxlan6") ||
3238 !strcmp(str, "xfrm"))
3239 return system_link_del(name);
3241 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
3244 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
3246 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
3248 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
3249 blob_data(attr), blob_len(attr));
3251 return __system_del_ip_tunnel(name, tb);
3254 int system_update_ipv6_mtu(struct device *dev, int mtu)
3260 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
3263 fd = open(buf, O_RDWR);
3268 ssize_t len = read(fd, buf, sizeof(buf) - 1);
3275 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) > 0)
3284 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
3286 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
3287 struct blob_attr *cur;
3290 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
3291 blob_data(attr), blob_len(attr));
3293 __system_del_ip_tunnel(name, tb);
3295 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
3297 str = blobmsg_data(cur);
3299 unsigned int ttl = 0;
3300 if ((cur = tb[TUNNEL_ATTR_TTL])) {
3301 ttl = blobmsg_get_u32(cur);
3306 unsigned int link = 0;
3307 if ((cur = tb[TUNNEL_ATTR_LINK])) {
3308 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
3312 if (iface->l3_dev.dev)
3313 link = iface->l3_dev.dev->ifindex;
3316 if (!strcmp(str, "sit"))
3317 return system_add_sit_tunnel(name, link, tb);
3318 #ifdef IFLA_IPTUN_MAX
3319 else if (!strcmp(str, "ipip6")) {
3320 return system_add_ip6_tunnel(name, link, tb);
3321 } else if (!strcmp(str, "greip")) {
3322 return system_add_gre_tunnel(name, "gre", link, tb, false);
3323 } else if (!strcmp(str, "gretapip")) {
3324 return system_add_gre_tunnel(name, "gretap", link, tb, false);
3325 } else if (!strcmp(str, "greip6")) {
3326 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
3327 } else if (!strcmp(str, "gretapip6")) {
3328 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
3330 } else if (!strcmp(str, "vtiip")) {
3331 return system_add_vti_tunnel(name, "vti", link, tb, false);
3332 } else if (!strcmp(str, "vtiip6")) {
3333 return system_add_vti_tunnel(name, "vti6", link, tb, true);
3335 #ifdef IFLA_XFRM_MAX
3336 } else if (!strcmp(str, "xfrm")) {
3337 return system_add_xfrm_tunnel(name, "xfrm", link, tb);
3339 #ifdef IFLA_VXLAN_MAX
3340 } else if(!strcmp(str, "vxlan")) {
3341 return system_add_vxlan(name, link, tb, false);
3342 } else if(!strcmp(str, "vxlan6")) {
3343 return system_add_vxlan(name, link, tb, true);
3346 } else if (!strcmp(str, "ipip")) {
3347 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);