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))
149 create_raw_event_socket(struct event_socket *ev, int protocol, int groups,
150 uloop_fd_handler cb, int flags)
152 ev->sock = create_socket(protocol, groups);
156 ev->uloop.fd = nl_socket_get_fd(ev->sock);
158 if (uloop_fd_add(&ev->uloop, ULOOP_READ|flags))
165 create_event_socket(struct event_socket *ev, int protocol,
166 int (*cb)(struct nl_msg *msg, void *arg))
168 if (!create_raw_event_socket(ev, protocol, 0, handler_nl_event, ULOOP_ERROR_CB))
171 /* Install the valid custom callback handler */
172 nl_socket_modify_cb(ev->sock, NL_CB_VALID, NL_CB_CUSTOM, cb, NULL);
174 /* Disable sequence number checking on event sockets */
175 nl_socket_disable_seq_check(ev->sock);
177 /* Increase rx buffer size to 65K on event sockets */
179 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
186 create_hotplug_event_socket(struct event_socket *ev, int protocol,
187 void (*cb)(struct uloop_fd *u, unsigned int events))
189 if (!create_raw_event_socket(ev, protocol, 1, cb, ULOOP_ERROR_CB))
192 /* Increase rx buffer size to 65K on event sockets */
194 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
201 system_rtn_aton(const char *src, unsigned int *dst)
206 if (!strcmp(src, "local"))
208 else if (!strcmp(src, "nat"))
210 else if (!strcmp(src, "broadcast"))
212 else if (!strcmp(src, "anycast"))
214 else if (!strcmp(src, "multicast"))
216 else if (!strcmp(src, "prohibit"))
218 else if (!strcmp(src, "unreachable"))
220 else if (!strcmp(src, "blackhole"))
222 else if (!strcmp(src, "xresolve"))
224 else if (!strcmp(src, "unicast"))
226 else if (!strcmp(src, "throw"))
228 else if (!strcmp(src, "failed_policy"))
229 n = RTN_FAILED_POLICY;
231 n = strtoul(src, &e, 0);
232 if (!e || *e || e == src || n > 255)
241 system_tos_aton(const char *src, unsigned *dst)
245 *dst = strtoul(src, &e, 16);
246 if (e == src || *e || *dst > 255)
252 int system_init(void)
254 static struct event_socket rtnl_event;
255 static struct event_socket hotplug_event;
257 sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0);
258 system_fd_set_cloexec(sock_ioctl);
260 /* Prepare socket for routing / address control */
261 sock_rtnl = create_socket(NETLINK_ROUTE, 0);
265 if (!create_event_socket(&rtnl_event, NETLINK_ROUTE, cb_rtnl_event))
268 if (!create_hotplug_event_socket(&hotplug_event, NETLINK_KOBJECT_UEVENT,
269 handle_hotplug_event))
272 /* Receive network link events form kernel */
273 nl_socket_add_membership(rtnl_event.sock, RTNLGRP_LINK);
278 static void system_set_sysctl(const char *path, const char *val)
282 fd = open(path, O_WRONLY);
286 if (write(fd, val, strlen(val))) {}
290 static void system_set_dev_sysctl(const char *path, const char *device, const char *val)
292 snprintf(dev_buf, sizeof(dev_buf), path, device);
293 system_set_sysctl(dev_buf, val);
296 static void system_set_disable_ipv6(struct device *dev, const char *val)
298 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val);
301 static void system_set_rpfilter(struct device *dev, const char *val)
303 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter", dev->ifname, val);
306 static void system_set_acceptlocal(struct device *dev, const char *val)
308 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local", dev->ifname, val);
311 static void system_set_igmpversion(struct device *dev, const char *val)
313 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version", dev->ifname, val);
316 static void system_set_mldversion(struct device *dev, const char *val)
318 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version", dev->ifname, val);
321 static void system_set_neigh4reachabletime(struct device *dev, const char *val)
323 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms", dev->ifname, val);
326 static void system_set_neigh6reachabletime(struct device *dev, const char *val)
328 system_set_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms", dev->ifname, val);
331 static void system_set_neigh4gcstaletime(struct device *dev, const char *val)
333 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/gc_stale_time", dev->ifname, val);
336 static void system_set_neigh6gcstaletime(struct device *dev, const char *val)
338 system_set_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/gc_stale_time", dev->ifname, val);
341 static void system_set_neigh4locktime(struct device *dev, const char *val)
343 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/locktime", dev->ifname, val);
346 static void system_set_dadtransmits(struct device *dev, const char *val)
348 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits", dev->ifname, val);
351 static void system_bridge_set_multicast_to_unicast(struct device *dev, const char *val)
353 system_set_dev_sysctl("/sys/class/net/%s/brport/multicast_to_unicast", dev->ifname, val);
356 static void system_bridge_set_multicast_fast_leave(struct device *dev, const char *val)
358 system_set_dev_sysctl("/sys/class/net/%s/brport/multicast_fast_leave", dev->ifname, val);
361 static void system_bridge_set_hairpin_mode(struct device *dev, const char *val)
363 system_set_dev_sysctl("/sys/class/net/%s/brport/hairpin_mode", dev->ifname, val);
366 static void system_bridge_set_isolated(struct device *dev, const char *val)
368 system_set_dev_sysctl("/sys/class/net/%s/brport/isolated", dev->ifname, val);
371 static void system_bridge_set_multicast_router(struct device *dev, const char *val, bool bridge)
373 system_set_dev_sysctl(bridge ? "/sys/class/net/%s/bridge/multicast_router" :
374 "/sys/class/net/%s/brport/multicast_router",
378 static void system_bridge_set_robustness(struct device *dev, const char *val)
380 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_startup_query_count",
382 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_last_member_count",
386 static void system_bridge_set_query_interval(struct device *dev, const char *val)
388 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_query_interval",
392 static void system_bridge_set_query_response_interval(struct device *dev, const char *val)
394 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_query_response_interval",
398 static void system_bridge_set_last_member_interval(struct device *dev, const char *val)
400 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_last_member_interval",
404 static void system_bridge_set_membership_interval(struct device *dev, const char *val)
406 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_membership_interval",
410 static void system_bridge_set_other_querier_timeout(struct device *dev, const char *val)
412 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier_interval",
416 static void system_bridge_set_startup_query_interval(struct device *dev, const char *val)
418 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_startup_query_interval",
422 static void system_bridge_set_stp_state(struct device *dev, const char *val)
424 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/stp_state", dev->ifname, val);
427 static void system_bridge_set_forward_delay(struct device *dev, const char *val)
429 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/forward_delay", dev->ifname, val);
432 static void system_bridge_set_priority(struct device *dev, const char *val)
434 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/priority", dev->ifname, val);
437 static void system_bridge_set_ageing_time(struct device *dev, const char *val)
439 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/ageing_time", dev->ifname, val);
442 static void system_bridge_set_hello_time(struct device *dev, const char *val)
444 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/hello_time", dev->ifname, val);
447 static void system_bridge_set_max_age(struct device *dev, const char *val)
449 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/max_age", dev->ifname, val);
452 static void system_bridge_set_learning(struct device *dev, const char *val)
454 system_set_dev_sysctl("/sys/class/net/%s/brport/learning", dev->ifname, val);
457 static void system_bridge_set_unicast_flood(struct device *dev, const char *val)
459 system_set_dev_sysctl("/sys/class/net/%s/brport/unicast_flood", dev->ifname, val);
462 static void system_set_sendredirects(struct device *dev, const char *val)
464 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/send_redirects", dev->ifname, val);
467 static int system_get_sysctl(const char *path, char *buf, const size_t buf_sz)
469 int fd = -1, ret = -1;
471 fd = open(path, O_RDONLY);
475 ssize_t len = read(fd, buf, buf_sz - 1);
489 system_get_dev_sysctl(const char *path, const char *device, char *buf, const size_t buf_sz)
491 snprintf(dev_buf, sizeof(dev_buf), path, device);
492 return system_get_sysctl(dev_buf, buf, buf_sz);
495 static int system_get_disable_ipv6(struct device *dev, char *buf, const size_t buf_sz)
497 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6",
498 dev->ifname, buf, buf_sz);
501 static int system_get_rpfilter(struct device *dev, char *buf, const size_t buf_sz)
503 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter",
504 dev->ifname, buf, buf_sz);
507 static int system_get_acceptlocal(struct device *dev, char *buf, const size_t buf_sz)
509 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local",
510 dev->ifname, buf, buf_sz);
513 static int system_get_igmpversion(struct device *dev, char *buf, const size_t buf_sz)
515 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version",
516 dev->ifname, buf, buf_sz);
519 static int system_get_mldversion(struct device *dev, char *buf, const size_t buf_sz)
521 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version",
522 dev->ifname, buf, buf_sz);
525 static int system_get_neigh4reachabletime(struct device *dev, char *buf, const size_t buf_sz)
527 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms",
528 dev->ifname, buf, buf_sz);
531 static int system_get_neigh6reachabletime(struct device *dev, char *buf, const size_t buf_sz)
533 return system_get_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms",
534 dev->ifname, buf, buf_sz);
537 static int system_get_neigh4gcstaletime(struct device *dev, char *buf, const size_t buf_sz)
539 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/gc_stale_time",
540 dev->ifname, buf, buf_sz);
543 static int system_get_neigh6gcstaletime(struct device *dev, char *buf, const size_t buf_sz)
545 return system_get_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/gc_stale_time",
546 dev->ifname, buf, buf_sz);
549 static int system_get_neigh4locktime(struct device *dev, char *buf, const size_t buf_sz)
551 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/locktime",
552 dev->ifname, buf, buf_sz);
555 static int system_get_dadtransmits(struct device *dev, char *buf, const size_t buf_sz)
557 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits",
558 dev->ifname, buf, buf_sz);
561 static int system_get_sendredirects(struct device *dev, char *buf, const size_t buf_sz)
563 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/send_redirects",
564 dev->ifname, buf, buf_sz);
567 /* Evaluate netlink messages */
568 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
570 struct nlmsghdr *nh = nlmsg_hdr(msg);
571 struct nlattr *nla[__IFLA_MAX];
575 if (nh->nlmsg_type != RTM_NEWLINK)
578 nlmsg_parse(nh, sizeof(struct ifinfomsg), nla, __IFLA_MAX - 1, NULL);
579 if (!nla[IFLA_IFNAME])
582 struct device *dev = device_find(nla_data(nla[IFLA_IFNAME]));
586 if (!system_get_dev_sysctl("/sys/class/net/%s/carrier", dev->ifname, buf, sizeof(buf)))
587 link_state = strtoul(buf, NULL, 0);
589 device_set_link(dev, link_state ? true : false);
596 handle_hotplug_msg(char *data, int size)
598 const char *subsystem = NULL, *interface = NULL, *interface_old = NULL;
599 char *cur, *end, *sep;
602 bool add, move = false;
604 if (!strncmp(data, "add@", 4))
606 else if (!strncmp(data, "remove@", 7))
608 else if (!strncmp(data, "move@", 5)) {
615 skip = strlen(data) + 1;
618 for (cur = data + skip; cur < end; cur += skip) {
619 skip = strlen(cur) + 1;
621 sep = strchr(cur, '=');
626 if (!strcmp(cur, "INTERFACE"))
628 else if (!strcmp(cur, "SUBSYSTEM")) {
630 if (strcmp(subsystem, "net") != 0)
632 } else if (!strcmp(cur, "DEVPATH_OLD")) {
633 interface_old = strrchr(sep + 1, '/');
639 if (subsystem && interface) {
640 if (move && interface_old)
649 dev = device_find(interface_old);
653 if (dev->type != &simple_device_type)
656 device_set_present(dev, false);
659 dev = device_find(interface);
663 if (dev->type != &simple_device_type)
666 if (add && system_if_force_external(dev->ifname))
669 device_set_present(dev, add);
673 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
675 struct event_socket *ev = container_of(u, struct event_socket, uloop);
676 struct sockaddr_nl nla;
677 unsigned char *buf = NULL;
680 socklen_t errlen = sizeof(err);
683 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
685 handle_hotplug_msg((char *) buf, size);
692 if (getsockopt(u->fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen))
697 /* Increase rx buffer size on netlink socket */
699 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
710 uloop_fd_delete(&ev->uloop);
714 static int system_rtnl_call(struct nl_msg *msg)
718 ret = nl_send_auto_complete(sock_rtnl, msg);
724 return nl_wait_for_ack(sock_rtnl);
727 int system_bridge_delbr(struct device *bridge)
729 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
732 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
736 memset(&ifr, 0, sizeof(ifr));
738 ifr.ifr_ifindex = dev->ifindex;
741 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name) - 1);
742 return ioctl(sock_ioctl, cmd, &ifr);
745 static bool system_is_bridge(const char *name, char *buf, int buflen)
749 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
750 if (stat(buf, &st) < 0)
756 static char *system_get_bridge(const char *name, char *buf, int buflen)
762 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
763 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
767 len = readlink(gl.gl_pathv[0], buf, buflen);
775 path = strrchr(buf, '/');
783 system_bridge_set_wireless(struct device *bridge, struct device *dev)
785 bool mcast_to_ucast = dev->wireless_ap;
788 if (bridge->settings.flags & DEV_OPT_MULTICAST_TO_UNICAST &&
789 !bridge->settings.multicast_to_unicast)
790 mcast_to_ucast = false;
792 if (!mcast_to_ucast || dev->wireless_isolate)
795 system_bridge_set_multicast_to_unicast(dev, mcast_to_ucast ? "1" : "0");
796 system_bridge_set_hairpin_mode(dev, hairpin ? "1" : "0");
799 int system_bridge_addif(struct device *bridge, struct device *dev)
805 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
806 if (!oldbr || strcmp(oldbr, bridge->ifname) != 0)
807 ret = system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
810 system_bridge_set_wireless(bridge, dev);
812 if (dev->settings.flags & DEV_OPT_MULTICAST_ROUTER) {
813 snprintf(buf, sizeof(buf), "%u", dev->settings.multicast_router);
814 system_bridge_set_multicast_router(dev, buf, false);
817 if (dev->settings.flags & DEV_OPT_MULTICAST_FAST_LEAVE &&
818 dev->settings.multicast_fast_leave)
819 system_bridge_set_multicast_fast_leave(dev, "1");
821 if (dev->settings.flags & DEV_OPT_LEARNING &&
822 !dev->settings.learning)
823 system_bridge_set_learning(dev, "0");
825 if (dev->settings.flags & DEV_OPT_UNICAST_FLOOD &&
826 !dev->settings.unicast_flood)
827 system_bridge_set_unicast_flood(dev, "0");
829 if (dev->settings.flags & DEV_OPT_ISOLATE &&
830 dev->settings.isolate)
831 system_bridge_set_isolated(dev, "1");
836 int system_bridge_delif(struct device *bridge, struct device *dev)
838 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
841 int system_if_resolve(struct device *dev)
844 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
845 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
846 return ifr.ifr_ifindex;
851 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
855 memset(&ifr, 0, sizeof(ifr));
856 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1);
857 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) < 0)
860 ifr.ifr_flags |= add;
861 ifr.ifr_flags &= ~rem;
862 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
874 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
876 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
878 return ifa->ifa_index == ifindex;
881 static bool check_route(struct nlmsghdr *hdr, int ifindex)
883 struct rtmsg *r = NLMSG_DATA(hdr);
884 struct nlattr *tb[__RTA_MAX];
886 if (r->rtm_protocol == RTPROT_KERNEL &&
887 r->rtm_family == AF_INET6)
890 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
894 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
897 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
902 static int cb_clear_event(struct nl_msg *msg, void *arg)
904 struct clear_data *clr = arg;
905 struct nlmsghdr *hdr = nlmsg_hdr(msg);
906 bool (*cb)(struct nlmsghdr *, int ifindex);
912 if (hdr->nlmsg_type != RTM_NEWADDR)
919 if (hdr->nlmsg_type != RTM_NEWROUTE)
926 if (hdr->nlmsg_type != RTM_NEWRULE)
935 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
938 if (type == RTM_DELRULE)
939 D(SYSTEM, "Remove a rule\n");
941 D(SYSTEM, "Remove %s from device %s\n",
942 type == RTM_DELADDR ? "an address" : "a route",
944 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
945 hdr = nlmsg_hdr(clr->msg);
946 hdr->nlmsg_type = type;
947 hdr->nlmsg_flags = NLM_F_REQUEST;
949 nl_socket_disable_auto_ack(sock_rtnl);
950 nl_send_auto_complete(sock_rtnl, clr->msg);
951 nl_socket_enable_auto_ack(sock_rtnl);
957 cb_finish_event(struct nl_msg *msg, void *arg)
965 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
968 *pending = err->error;
973 system_if_clear_entries(struct device *dev, int type, int af)
975 struct clear_data clr;
976 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
979 .rtm_flags = RTM_F_CLONED,
981 int flags = NLM_F_DUMP;
990 clr.size = sizeof(struct rtgenmsg);
993 clr.size = sizeof(struct rtmsg);
1002 clr.msg = nlmsg_alloc_simple(type, flags);
1006 nlmsg_append(clr.msg, &rtm, clr.size, 0);
1007 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
1008 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
1009 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
1011 nl_send_auto_complete(sock_rtnl, clr.msg);
1013 nl_recvmsgs(sock_rtnl, cb);
1015 nlmsg_free(clr.msg);
1021 * Clear bridge (membership) state and bring down device
1023 void system_if_clear_state(struct device *dev)
1025 static char buf[256];
1027 device_set_ifindex(dev, system_if_resolve(dev));
1029 if (dev->external || !dev->ifindex)
1032 system_if_flags(dev->ifname, 0, IFF_UP);
1034 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
1035 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
1036 system_bridge_delbr(dev);
1040 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
1042 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
1043 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
1046 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
1047 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
1048 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
1049 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
1050 system_if_clear_entries(dev, RTM_GETNEIGH, AF_INET);
1051 system_if_clear_entries(dev, RTM_GETNEIGH, AF_INET6);
1052 system_set_disable_ipv6(dev, "0");
1055 static inline unsigned long
1056 sec_to_jiffies(int val)
1058 return (unsigned long) val * 100;
1061 static void system_bridge_conf_multicast_deps(struct device *bridge,
1062 struct bridge_config *cfg,
1068 if (cfg->flags & BRIDGE_OPT_ROBUSTNESS ||
1069 cfg->flags & BRIDGE_OPT_QUERY_INTERVAL ||
1070 cfg->flags & BRIDGE_OPT_QUERY_RESPONSE_INTERVAL) {
1071 val = cfg->robustness * cfg->query_interval +
1072 cfg->query_response_interval;
1074 snprintf(buf, buf_len, "%i", val);
1075 system_bridge_set_membership_interval(bridge, buf);
1077 val = cfg->robustness * cfg->query_interval +
1078 cfg->query_response_interval / 2;
1080 snprintf(buf, buf_len, "%i", val);
1081 system_bridge_set_other_querier_timeout(bridge, buf);
1084 if (cfg->flags & BRIDGE_OPT_QUERY_INTERVAL) {
1085 val = cfg->query_interval / 4;
1087 snprintf(buf, buf_len, "%i", val);
1088 system_bridge_set_startup_query_interval(bridge, buf);
1092 static void system_bridge_conf_multicast(struct device *bridge,
1093 struct bridge_config *cfg,
1097 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
1098 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
1100 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier",
1101 bridge->ifname, cfg->multicast_querier ? "1" : "0");
1103 snprintf(buf, buf_len, "%i", cfg->hash_max);
1104 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/hash_max",
1105 bridge->ifname, buf);
1107 if (bridge->settings.flags & DEV_OPT_MULTICAST_ROUTER) {
1108 snprintf(buf, buf_len, "%u", bridge->settings.multicast_router);
1109 system_bridge_set_multicast_router(bridge, buf, true);
1112 if (cfg->flags & BRIDGE_OPT_ROBUSTNESS) {
1113 snprintf(buf, buf_len, "%i", cfg->robustness);
1114 system_bridge_set_robustness(bridge, buf);
1117 if (cfg->flags & BRIDGE_OPT_QUERY_INTERVAL) {
1118 snprintf(buf, buf_len, "%i", cfg->query_interval);
1119 system_bridge_set_query_interval(bridge, buf);
1122 if (cfg->flags & BRIDGE_OPT_QUERY_RESPONSE_INTERVAL) {
1123 snprintf(buf, buf_len, "%i", cfg->query_response_interval);
1124 system_bridge_set_query_response_interval(bridge, buf);
1127 if (cfg->flags & BRIDGE_OPT_LAST_MEMBER_INTERVAL) {
1128 snprintf(buf, buf_len, "%i", cfg->last_member_interval);
1129 system_bridge_set_last_member_interval(bridge, buf);
1132 system_bridge_conf_multicast_deps(bridge, cfg, buf, buf_len);
1135 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
1139 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
1142 system_bridge_set_stp_state(bridge, cfg->stp ? "1" : "0");
1144 snprintf(buf, sizeof(buf), "%lu", sec_to_jiffies(cfg->forward_delay));
1145 system_bridge_set_forward_delay(bridge, buf);
1147 system_bridge_conf_multicast(bridge, cfg, buf, sizeof(buf));
1149 snprintf(buf, sizeof(buf), "%d", cfg->priority);
1150 system_bridge_set_priority(bridge, buf);
1152 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
1153 snprintf(buf, sizeof(buf), "%lu", sec_to_jiffies(cfg->ageing_time));
1154 system_bridge_set_ageing_time(bridge, buf);
1157 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
1158 snprintf(buf, sizeof(buf), "%lu", sec_to_jiffies(cfg->hello_time));
1159 system_bridge_set_hello_time(bridge, buf);
1162 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
1163 snprintf(buf, sizeof(buf), "%lu", sec_to_jiffies(cfg->max_age));
1164 system_bridge_set_max_age(bridge, buf);
1170 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
1173 struct nlattr *linkinfo, *data;
1174 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
1176 static const struct {
1178 enum macvlan_mode val;
1180 { "private", MACVLAN_MODE_PRIVATE },
1181 { "vepa", MACVLAN_MODE_VEPA },
1182 { "bridge", MACVLAN_MODE_BRIDGE },
1183 { "passthru", MACVLAN_MODE_PASSTHRU },
1186 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1191 nlmsg_append(msg, &iim, sizeof(iim), 0);
1193 if (cfg->flags & MACVLAN_OPT_MACADDR)
1194 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
1195 nla_put_string(msg, IFLA_IFNAME, macvlan->ifname);
1196 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
1198 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1199 goto nla_put_failure;
1201 nla_put_string(msg, IFLA_INFO_KIND, "macvlan");
1203 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1204 goto nla_put_failure;
1207 for (i = 0; i < ARRAY_SIZE(modes); i++) {
1208 if (strcmp(cfg->mode, modes[i].name) != 0)
1211 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
1216 nla_nest_end(msg, data);
1217 nla_nest_end(msg, linkinfo);
1219 rv = system_rtnl_call(msg);
1221 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
1230 static int system_link_del(const char *ifname)
1233 struct ifinfomsg iim = {
1234 .ifi_family = AF_UNSPEC,
1238 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
1243 nlmsg_append(msg, &iim, sizeof(iim), 0);
1244 nla_put_string(msg, IFLA_IFNAME, ifname);
1245 return system_rtnl_call(msg);
1248 int system_macvlan_del(struct device *macvlan)
1250 return system_link_del(macvlan->ifname);
1253 int system_veth_add(struct device *veth, struct veth_config *cfg)
1256 struct ifinfomsg empty_iim = {};
1257 struct nlattr *linkinfo, *data, *veth_info;
1260 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1265 nlmsg_append(msg, &empty_iim, sizeof(empty_iim), 0);
1267 if (cfg->flags & VETH_OPT_MACADDR)
1268 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
1269 nla_put_string(msg, IFLA_IFNAME, veth->ifname);
1271 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1272 goto nla_put_failure;
1274 nla_put_string(msg, IFLA_INFO_KIND, "veth");
1276 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1277 goto nla_put_failure;
1279 if (!(veth_info = nla_nest_start(msg, VETH_INFO_PEER)))
1280 goto nla_put_failure;
1282 nlmsg_append(msg, &empty_iim, sizeof(empty_iim), 0);
1284 if (cfg->flags & VETH_OPT_PEER_NAME)
1285 nla_put_string(msg, IFLA_IFNAME, cfg->peer_name);
1286 if (cfg->flags & VETH_OPT_PEER_MACADDR)
1287 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->peer_macaddr), cfg->peer_macaddr);
1289 nla_nest_end(msg, veth_info);
1290 nla_nest_end(msg, data);
1291 nla_nest_end(msg, linkinfo);
1293 rv = system_rtnl_call(msg);
1295 if (cfg->flags & VETH_OPT_PEER_NAME)
1296 D(SYSTEM, "Error adding veth '%s' with peer '%s': %d\n", veth->ifname, cfg->peer_name, rv);
1298 D(SYSTEM, "Error adding veth '%s': %d\n", veth->ifname, rv);
1308 int system_veth_del(struct device *veth)
1310 return system_link_del(veth->ifname);
1313 static int system_vlan(struct device *dev, int id)
1315 struct vlan_ioctl_args ifr = {
1316 .cmd = SET_VLAN_NAME_TYPE_CMD,
1317 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
1320 if (ioctl(sock_ioctl, SIOCSIFVLAN, &ifr) < 0)
1324 ifr.cmd = DEL_VLAN_CMD;
1327 ifr.cmd = ADD_VLAN_CMD;
1330 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
1331 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
1334 int system_vlan_add(struct device *dev, int id)
1336 return system_vlan(dev, id);
1339 int system_vlan_del(struct device *dev)
1341 return system_vlan(dev, -1);
1344 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
1347 struct nlattr *linkinfo, *data;
1348 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
1351 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1356 nlmsg_append(msg, &iim, sizeof(iim), 0);
1357 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
1358 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
1360 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1361 goto nla_put_failure;
1363 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
1365 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1366 goto nla_put_failure;
1368 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
1370 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
1371 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
1373 if(cfg->proto == VLAN_PROTO_8021AD)
1374 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);
1377 nla_nest_end(msg, data);
1378 nla_nest_end(msg, linkinfo);
1380 rv = system_rtnl_call(msg);
1382 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
1391 int system_vlandev_del(struct device *vlandev)
1393 return system_link_del(vlandev->ifname);
1397 system_if_get_settings(struct device *dev, struct device_settings *s)
1402 memset(&ifr, 0, sizeof(ifr));
1403 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
1405 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
1406 s->mtu = ifr.ifr_mtu;
1407 s->flags |= DEV_OPT_MTU;
1410 s->mtu6 = system_update_ipv6_mtu(dev, 0);
1412 s->flags |= DEV_OPT_MTU6;
1414 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
1415 s->txqueuelen = ifr.ifr_qlen;
1416 s->flags |= DEV_OPT_TXQUEUELEN;
1419 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
1420 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
1421 s->flags |= DEV_OPT_MACADDR;
1424 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
1425 s->ipv6 = !strtoul(buf, NULL, 0);
1426 s->flags |= DEV_OPT_IPV6;
1429 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
1430 s->promisc = ifr.ifr_flags & IFF_PROMISC;
1431 s->flags |= DEV_OPT_PROMISC;
1433 s->multicast = ifr.ifr_flags & IFF_MULTICAST;
1434 s->flags |= DEV_OPT_MULTICAST;
1437 if (!system_get_rpfilter(dev, buf, sizeof(buf))) {
1438 s->rpfilter = strtoul(buf, NULL, 0);
1439 s->flags |= DEV_OPT_RPFILTER;
1442 if (!system_get_acceptlocal(dev, buf, sizeof(buf))) {
1443 s->acceptlocal = strtoul(buf, NULL, 0);
1444 s->flags |= DEV_OPT_ACCEPTLOCAL;
1447 if (!system_get_igmpversion(dev, buf, sizeof(buf))) {
1448 s->igmpversion = strtoul(buf, NULL, 0);
1449 s->flags |= DEV_OPT_IGMPVERSION;
1452 if (!system_get_mldversion(dev, buf, sizeof(buf))) {
1453 s->mldversion = strtoul(buf, NULL, 0);
1454 s->flags |= DEV_OPT_MLDVERSION;
1457 if (!system_get_neigh4reachabletime(dev, buf, sizeof(buf))) {
1458 s->neigh4reachabletime = strtoul(buf, NULL, 0);
1459 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1462 if (!system_get_neigh6reachabletime(dev, buf, sizeof(buf))) {
1463 s->neigh6reachabletime = strtoul(buf, NULL, 0);
1464 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1467 if (!system_get_neigh4locktime(dev, buf, sizeof(buf))) {
1468 s->neigh4locktime = strtol(buf, NULL, 0);
1469 s->flags |= DEV_OPT_NEIGHLOCKTIME;
1472 if (!system_get_neigh4gcstaletime(dev, buf, sizeof(buf))) {
1473 s->neigh4gcstaletime = strtoul(buf, NULL, 0);
1474 s->flags |= DEV_OPT_NEIGHGCSTALETIME;
1477 if (!system_get_neigh6gcstaletime(dev, buf, sizeof(buf))) {
1478 s->neigh6gcstaletime = strtoul(buf, NULL, 0);
1479 s->flags |= DEV_OPT_NEIGHGCSTALETIME;
1482 if (!system_get_dadtransmits(dev, buf, sizeof(buf))) {
1483 s->dadtransmits = strtoul(buf, NULL, 0);
1484 s->flags |= DEV_OPT_DADTRANSMITS;
1487 if (!system_get_sendredirects(dev, buf, sizeof(buf))) {
1488 s->sendredirects = strtoul(buf, NULL, 0);
1489 s->flags |= DEV_OPT_SENDREDIRECTS;
1494 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
1499 memset(&ifr, 0, sizeof(ifr));
1500 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
1501 if (s->flags & DEV_OPT_MTU & apply_mask) {
1502 ifr.ifr_mtu = s->mtu;
1503 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
1504 s->flags &= ~DEV_OPT_MTU;
1506 if (s->flags & DEV_OPT_MTU6 & apply_mask) {
1507 system_update_ipv6_mtu(dev, s->mtu6);
1509 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
1510 ifr.ifr_qlen = s->txqueuelen;
1511 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
1512 s->flags &= ~DEV_OPT_TXQUEUELEN;
1514 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
1515 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
1516 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
1517 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
1518 s->flags &= ~DEV_OPT_MACADDR;
1520 if (s->flags & DEV_OPT_IPV6 & apply_mask)
1521 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
1522 if (s->flags & DEV_OPT_PROMISC & apply_mask) {
1523 if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
1524 !s->promisc ? IFF_PROMISC : 0) < 0)
1525 s->flags &= ~DEV_OPT_PROMISC;
1527 if (s->flags & DEV_OPT_RPFILTER & apply_mask) {
1528 snprintf(buf, sizeof(buf), "%u", s->rpfilter);
1529 system_set_rpfilter(dev, buf);
1531 if (s->flags & DEV_OPT_ACCEPTLOCAL & apply_mask)
1532 system_set_acceptlocal(dev, s->acceptlocal ? "1" : "0");
1533 if (s->flags & DEV_OPT_IGMPVERSION & apply_mask) {
1534 snprintf(buf, sizeof(buf), "%u", s->igmpversion);
1535 system_set_igmpversion(dev, buf);
1537 if (s->flags & DEV_OPT_MLDVERSION & apply_mask) {
1538 snprintf(buf, sizeof(buf), "%u", s->mldversion);
1539 system_set_mldversion(dev, buf);
1541 if (s->flags & DEV_OPT_NEIGHREACHABLETIME & apply_mask) {
1542 snprintf(buf, sizeof(buf), "%u", s->neigh4reachabletime);
1543 system_set_neigh4reachabletime(dev, buf);
1544 snprintf(buf, sizeof(buf), "%u", s->neigh6reachabletime);
1545 system_set_neigh6reachabletime(dev, buf);
1547 if (s->flags & DEV_OPT_NEIGHLOCKTIME & apply_mask) {
1548 snprintf(buf, sizeof(buf), "%d", s->neigh4locktime);
1549 system_set_neigh4locktime(dev, buf);
1551 if (s->flags & DEV_OPT_NEIGHGCSTALETIME & apply_mask) {
1552 snprintf(buf, sizeof(buf), "%u", s->neigh4gcstaletime);
1553 system_set_neigh4gcstaletime(dev, buf);
1554 snprintf(buf, sizeof(buf), "%u", s->neigh6gcstaletime);
1555 system_set_neigh6gcstaletime(dev, buf);
1557 if (s->flags & DEV_OPT_DADTRANSMITS & apply_mask) {
1558 snprintf(buf, sizeof(buf), "%u", s->dadtransmits);
1559 system_set_dadtransmits(dev, buf);
1561 if (s->flags & DEV_OPT_MULTICAST & apply_mask) {
1562 if (system_if_flags(dev->ifname, s->multicast ? IFF_MULTICAST : 0,
1563 !s->multicast ? IFF_MULTICAST : 0) < 0)
1564 s->flags &= ~DEV_OPT_MULTICAST;
1566 if (s->flags & DEV_OPT_SENDREDIRECTS & apply_mask)
1567 system_set_sendredirects(dev, s->sendredirects ? "1" : "0");
1570 int system_if_up(struct device *dev)
1572 system_if_get_settings(dev, &dev->orig_settings);
1573 /* Only keep orig settings based on what needs to be set */
1574 dev->orig_settings.valid_flags = dev->orig_settings.flags;
1575 dev->orig_settings.flags &= dev->settings.flags;
1576 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
1577 return system_if_flags(dev->ifname, IFF_UP, 0);
1580 int system_if_down(struct device *dev)
1582 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
1583 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
1587 struct if_check_data {
1593 #ifndef IFF_LOWER_UP
1594 #define IFF_LOWER_UP 0x10000
1597 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1599 struct nlmsghdr *nh = nlmsg_hdr(msg);
1600 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1601 struct if_check_data *chk = (struct if_check_data *)arg;
1603 if (nh->nlmsg_type != RTM_NEWLINK)
1606 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1607 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1612 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1614 struct if_check_data *chk = (struct if_check_data *)arg;
1619 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1621 struct if_check_data *chk = (struct if_check_data *)arg;
1623 device_set_present(chk->dev, false);
1624 device_set_link(chk->dev, false);
1625 chk->pending = err->error;
1630 int system_if_check(struct device *dev)
1632 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1634 struct ifinfomsg ifi = {
1635 .ifi_family = AF_UNSPEC,
1638 struct if_check_data chk = {
1647 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1651 if (nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1652 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1655 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1656 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1657 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1659 nl_send_auto_complete(sock_rtnl, msg);
1660 while (chk.pending > 0)
1661 nl_recvmsgs(sock_rtnl, cb);
1673 system_if_get_parent(struct device *dev)
1675 char buf[64], *devname;
1676 int ifindex, iflink, len;
1679 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1680 f = fopen(buf, "r");
1684 len = fread(buf, 1, sizeof(buf) - 1, f);
1691 iflink = strtoul(buf, NULL, 0);
1692 ifindex = system_if_resolve(dev);
1693 if (!iflink || iflink == ifindex)
1696 devname = if_indextoname(iflink, buf);
1700 return device_get(devname, true);
1704 read_string_file(int dir_fd, const char *file, char *buf, int len)
1710 fd = openat(dir_fd, file, O_RDONLY);
1715 len = read(fd, buf, len - 1);
1719 } else if (len > 0) {
1722 c = strchr(buf, '\n');
1735 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1740 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1742 *val = strtoull(buf, NULL, 0);
1747 /* Assume advertised flags == supported flags */
1748 static const struct {
1751 } ethtool_link_modes[] = {
1752 { ADVERTISED_10baseT_Half, "10baseT-H" },
1753 { ADVERTISED_10baseT_Full, "10baseT-F" },
1754 { ADVERTISED_100baseT_Half, "100baseT-H" },
1755 { ADVERTISED_100baseT_Full, "100baseT-F" },
1756 { ADVERTISED_1000baseT_Half, "1000baseT-H" },
1757 { ADVERTISED_1000baseT_Full, "1000baseT-F" },
1758 { ADVERTISED_1000baseKX_Full, "1000baseKX-F" },
1759 { ADVERTISED_2500baseX_Full, "2500baseX-F" },
1760 { ADVERTISED_10000baseT_Full, "10000baseT-F" },
1761 { ADVERTISED_10000baseKX4_Full, "10000baseKX4-F" },
1762 { ADVERTISED_10000baseKR_Full, "10000baseKR-F" },
1763 { ADVERTISED_20000baseMLD2_Full, "20000baseMLD2-F" },
1764 { ADVERTISED_20000baseKR2_Full, "20000baseKR2-F" },
1765 { ADVERTISED_40000baseKR4_Full, "40000baseKR4-F" },
1766 { ADVERTISED_40000baseCR4_Full, "40000baseCR4-F" },
1767 { ADVERTISED_40000baseSR4_Full, "40000baseSR4-F" },
1768 { ADVERTISED_40000baseLR4_Full, "40000baseLR4-F" },
1769 #ifdef ADVERTISED_56000baseKR4_Full
1770 { ADVERTISED_56000baseKR4_Full, "56000baseKR4-F" },
1771 { ADVERTISED_56000baseCR4_Full, "56000baseCR4-F" },
1772 { ADVERTISED_56000baseSR4_Full, "56000baseSR4-F" },
1773 { ADVERTISED_56000baseLR4_Full, "56000baseLR4-F" },
1777 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1780 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1781 if (mask & ethtool_link_modes[i].mask)
1782 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1787 system_if_force_external(const char *ifname)
1792 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1793 return stat(buf, &s) == 0;
1797 system_if_dump_info(struct device *dev, struct blob_buf *b)
1799 struct ethtool_cmd ecmd;
1804 memset(&ecmd, 0, sizeof(ecmd));
1805 memset(&ifr, 0, sizeof(ifr));
1806 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
1807 ifr.ifr_data = (caddr_t) &ecmd;
1808 ecmd.cmd = ETHTOOL_GSET;
1810 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1811 c = blobmsg_open_array(b, "link-advertising");
1812 system_add_link_modes(b, ecmd.advertising);
1813 blobmsg_close_array(b, c);
1815 c = blobmsg_open_array(b, "link-partner-advertising");
1816 system_add_link_modes(b, ecmd.lp_advertising);
1817 blobmsg_close_array(b, c);
1819 c = blobmsg_open_array(b, "link-supported");
1820 system_add_link_modes(b, ecmd.supported);
1821 blobmsg_close_array(b, c);
1823 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1824 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1825 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1826 blobmsg_add_string_buffer(b);
1828 blobmsg_add_u8(b, "autoneg", !!ecmd.autoneg);
1835 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1837 const char *const counters[] = {
1838 "collisions", "rx_frame_errors", "tx_compressed",
1839 "multicast", "rx_length_errors", "tx_dropped",
1840 "rx_bytes", "rx_missed_errors", "tx_errors",
1841 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1842 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1843 "rx_dropped", "tx_aborted_errors", "tx_packets",
1844 "rx_errors", "tx_bytes", "tx_window_errors",
1845 "rx_fifo_errors", "tx_carrier_errors",
1852 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1853 stats_dir = open(buf, O_DIRECTORY);
1857 for (i = 0; i < ARRAY_SIZE(counters); i++)
1858 if (read_uint64_file(stats_dir, counters[i], &val))
1859 blobmsg_add_u64(b, counters[i], val);
1865 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1867 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1868 int alen = v4 ? 4 : 16;
1869 unsigned int flags = 0;
1870 struct ifaddrmsg ifa = {
1871 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1872 .ifa_prefixlen = addr->mask,
1873 .ifa_index = dev->ifindex,
1877 if (cmd == RTM_NEWADDR)
1878 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1880 msg = nlmsg_alloc_simple(cmd, flags);
1884 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1885 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1887 if (addr->broadcast)
1888 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1889 if (addr->point_to_point)
1890 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1892 time_t now = system_get_rtime();
1893 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1895 if (addr->preferred_until) {
1896 int64_t preferred = addr->preferred_until - now;
1899 else if (preferred > UINT32_MAX)
1900 preferred = UINT32_MAX;
1902 cinfo.ifa_prefered = preferred;
1905 if (addr->valid_until) {
1906 int64_t valid = addr->valid_until - now;
1911 else if (valid > UINT32_MAX)
1914 cinfo.ifa_valid = valid;
1917 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1919 if (cmd == RTM_NEWADDR && (addr->flags & DEVADDR_OFFLINK))
1920 nla_put_u32(msg, IFA_FLAGS, IFA_F_NOPREFIXROUTE);
1923 return system_rtnl_call(msg);
1926 int system_add_address(struct device *dev, struct device_addr *addr)
1928 return system_addr(dev, addr, RTM_NEWADDR);
1931 int system_del_address(struct device *dev, struct device_addr *addr)
1933 return system_addr(dev, addr, RTM_DELADDR);
1936 static int system_neigh(struct device *dev, struct device_neighbor *neighbor, int cmd)
1938 int alen = ((neighbor->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1939 unsigned int flags = 0;
1940 struct ndmsg ndm = {
1941 .ndm_family = (alen == 4) ? AF_INET : AF_INET6,
1942 .ndm_ifindex = dev->ifindex,
1943 .ndm_state = NUD_PERMANENT,
1944 .ndm_flags = (neighbor->proxy ? NTF_PROXY : 0) | (neighbor->router ? NTF_ROUTER : 0),
1951 if (cmd == RTM_NEWNEIGH)
1952 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1954 msg = nlmsg_alloc_simple(cmd, flags);
1959 nlmsg_append(msg, &ndm, sizeof(ndm), 0);
1961 nla_put(msg, NDA_DST, alen, &neighbor->addr);
1962 if (neighbor->flags & DEVNEIGH_MAC)
1963 nla_put(msg, NDA_LLADDR, sizeof(neighbor->macaddr), &neighbor->macaddr);
1966 return system_rtnl_call(msg);
1969 int system_add_neighbor(struct device *dev, struct device_neighbor *neighbor)
1971 return system_neigh(dev, neighbor, RTM_NEWNEIGH);
1974 int system_del_neighbor(struct device *dev, struct device_neighbor *neighbor)
1976 return system_neigh(dev, neighbor, RTM_DELNEIGH);
1979 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1981 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1983 unsigned int flags = 0;
1986 have_gw = !!route->nexthop.in.s_addr;
1988 have_gw = route->nexthop.in6.s6_addr32[0] ||
1989 route->nexthop.in6.s6_addr32[1] ||
1990 route->nexthop.in6.s6_addr32[2] ||
1991 route->nexthop.in6.s6_addr32[3];
1993 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1994 ? route->table : RT_TABLE_MAIN;
1996 struct rtmsg rtm = {
1997 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1998 .rtm_dst_len = route->mask,
1999 .rtm_src_len = route->sourcemask,
2000 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
2001 .rtm_protocol = (route->flags & DEVROUTE_PROTO) ? route->proto : RTPROT_STATIC,
2002 .rtm_scope = RT_SCOPE_NOWHERE,
2003 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
2004 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
2008 if (cmd == RTM_NEWROUTE) {
2009 flags |= NLM_F_CREATE | NLM_F_REPLACE;
2011 if (!dev) { /* Add null-route */
2012 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
2013 rtm.rtm_type = RTN_UNREACHABLE;
2016 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
2019 if (route->flags & DEVROUTE_TYPE) {
2020 rtm.rtm_type = route->type;
2021 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
2022 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
2023 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
2024 rtm.rtm_table = RT_TABLE_LOCAL;
2027 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT) {
2028 rtm.rtm_scope = RT_SCOPE_HOST;
2029 } else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
2030 rtm.rtm_type == RTN_ANYCAST) {
2031 rtm.rtm_scope = RT_SCOPE_LINK;
2032 } else if (rtm.rtm_type == RTN_BLACKHOLE || rtm.rtm_type == RTN_UNREACHABLE ||
2033 rtm.rtm_type == RTN_PROHIBIT || rtm.rtm_type == RTN_FAILED_POLICY ||
2034 rtm.rtm_type == RTN_THROW) {
2035 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
2040 msg = nlmsg_alloc_simple(cmd, flags);
2044 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
2047 nla_put(msg, RTA_DST, alen, &route->addr);
2049 if (route->sourcemask) {
2050 if (rtm.rtm_family == AF_INET)
2051 nla_put(msg, RTA_PREFSRC, alen, &route->source);
2053 nla_put(msg, RTA_SRC, alen, &route->source);
2056 if (route->metric > 0)
2057 nla_put_u32(msg, RTA_PRIORITY, route->metric);
2060 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
2063 nla_put_u32(msg, RTA_OIF, dev->ifindex);
2066 nla_put_u32(msg, RTA_TABLE, table);
2068 if (route->flags & DEVROUTE_MTU) {
2069 struct nlattr *metrics;
2071 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
2072 goto nla_put_failure;
2074 nla_put_u32(msg, RTAX_MTU, route->mtu);
2076 nla_nest_end(msg, metrics);
2079 return system_rtnl_call(msg);
2086 int system_add_route(struct device *dev, struct device_route *route)
2088 return system_rt(dev, route, RTM_NEWROUTE);
2091 int system_del_route(struct device *dev, struct device_route *route)
2093 return system_rt(dev, route, RTM_DELROUTE);
2096 int system_flush_routes(void)
2098 const char *names[] = {
2099 "/proc/sys/net/ipv4/route/flush",
2100 "/proc/sys/net/ipv6/route/flush"
2104 for (i = 0; i < ARRAY_SIZE(names); i++) {
2105 fd = open(names[i], O_WRONLY);
2109 if (write(fd, "-1", 2)) {}
2115 bool system_resolve_rt_type(const char *type, unsigned int *id)
2117 return system_rtn_aton(type, id);
2120 bool system_resolve_rt_proto(const char *type, unsigned int *id)
2124 unsigned int n, proto = 256;
2125 n = strtoul(type, &e, 0);
2126 if (!*e && e != type)
2128 else if (!strcmp(type, "unspec"))
2129 proto = RTPROT_UNSPEC;
2130 else if (!strcmp(type, "kernel"))
2131 proto = RTPROT_KERNEL;
2132 else if (!strcmp(type, "boot"))
2133 proto = RTPROT_BOOT;
2134 else if (!strcmp(type, "static"))
2135 proto = RTPROT_STATIC;
2136 else if ((f = fopen("/etc/iproute2/rt_protos", "r")) != NULL) {
2137 while (fgets(buf, sizeof(buf) - 1, f) != NULL) {
2138 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
2141 n = strtoul(e, NULL, 10);
2142 e = strtok(NULL, " \t\n");
2144 if (e && !strcmp(e, type)) {
2159 bool system_resolve_rt_table(const char *name, unsigned int *id)
2163 unsigned int n, table = RT_TABLE_UNSPEC;
2165 /* first try to parse table as number */
2166 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
2169 /* handle well known aliases */
2170 else if (!strcmp(name, "default"))
2171 table = RT_TABLE_DEFAULT;
2172 else if (!strcmp(name, "main"))
2173 table = RT_TABLE_MAIN;
2174 else if (!strcmp(name, "local"))
2175 table = RT_TABLE_LOCAL;
2177 /* try to look up name in /etc/iproute2/rt_tables */
2178 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
2180 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
2182 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
2185 n = strtoul(e, NULL, 10);
2186 e = strtok(NULL, " \t\n");
2188 if (e && !strcmp(e, name))
2198 if (table == RT_TABLE_UNSPEC)
2205 bool system_is_default_rt_table(unsigned int id)
2207 return (id == RT_TABLE_MAIN);
2210 bool system_resolve_rpfilter(const char *filter, unsigned int *id)
2215 if (!strcmp(filter, "strict"))
2217 else if (!strcmp(filter, "loose"))
2220 n = strtoul(filter, &e, 0);
2221 if (*e || e == filter || n > 2)
2229 static int system_iprule(struct iprule *rule, int cmd)
2231 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
2234 struct rtmsg rtm = {
2235 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
2236 .rtm_protocol = RTPROT_STATIC,
2237 .rtm_scope = RT_SCOPE_UNIVERSE,
2238 .rtm_table = RT_TABLE_UNSPEC,
2239 .rtm_type = RTN_UNSPEC,
2243 if (cmd == RTM_NEWRULE)
2244 rtm.rtm_type = RTN_UNICAST;
2247 rtm.rtm_flags |= FIB_RULE_INVERT;
2249 if (rule->flags & IPRULE_SRC)
2250 rtm.rtm_src_len = rule->src_mask;
2252 if (rule->flags & IPRULE_DEST)
2253 rtm.rtm_dst_len = rule->dest_mask;
2255 if (rule->flags & IPRULE_TOS)
2256 rtm.rtm_tos = rule->tos;
2258 if (rule->flags & IPRULE_LOOKUP) {
2259 if (rule->lookup < 256)
2260 rtm.rtm_table = rule->lookup;
2263 if (rule->flags & IPRULE_ACTION)
2264 rtm.rtm_type = rule->action;
2265 else if (rule->flags & IPRULE_GOTO)
2266 rtm.rtm_type = FR_ACT_GOTO;
2267 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
2268 rtm.rtm_type = FR_ACT_NOP;
2270 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
2275 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
2277 if (rule->flags & IPRULE_IN)
2278 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
2280 if (rule->flags & IPRULE_OUT)
2281 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
2283 if (rule->flags & IPRULE_SRC)
2284 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
2286 if (rule->flags & IPRULE_DEST)
2287 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
2289 if (rule->flags & IPRULE_PRIORITY)
2290 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
2291 else if (cmd == RTM_NEWRULE)
2292 nla_put_u32(msg, FRA_PRIORITY, rule->order);
2294 if (rule->flags & IPRULE_FWMARK)
2295 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
2297 if (rule->flags & IPRULE_FWMASK)
2298 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
2300 if (rule->flags & IPRULE_LOOKUP) {
2301 if (rule->lookup >= 256)
2302 nla_put_u32(msg, FRA_TABLE, rule->lookup);
2305 if (rule->flags & IPRULE_SUP_PREFIXLEN)
2306 nla_put_u32(msg, FRA_SUPPRESS_PREFIXLEN, rule->sup_prefixlen);
2308 if (rule->flags & IPRULE_GOTO)
2309 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
2311 return system_rtnl_call(msg);
2314 int system_add_iprule(struct iprule *rule)
2316 return system_iprule(rule, RTM_NEWRULE);
2319 int system_del_iprule(struct iprule *rule)
2321 return system_iprule(rule, RTM_DELRULE);
2324 int system_flush_iprules(void)
2329 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
2330 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
2332 memset(&rule, 0, sizeof(rule));
2335 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2338 rule.lookup = RT_TABLE_LOCAL;
2339 rv |= system_iprule(&rule, RTM_NEWRULE);
2341 rule.priority = 32766;
2342 rule.lookup = RT_TABLE_MAIN;
2343 rv |= system_iprule(&rule, RTM_NEWRULE);
2345 rule.priority = 32767;
2346 rule.lookup = RT_TABLE_DEFAULT;
2347 rv |= system_iprule(&rule, RTM_NEWRULE);
2350 rule.flags = IPRULE_INET6 | 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);
2363 bool system_resolve_iprule_action(const char *action, unsigned int *id)
2365 return system_rtn_aton(action, id);
2368 time_t system_get_rtime(void)
2373 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
2376 if (gettimeofday(&tv, NULL) == 0)
2383 #define IP_DF 0x4000
2386 static int tunnel_ioctl(const char *name, int cmd, void *p)
2390 memset(&ifr, 0, sizeof(ifr));
2391 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name) - 1);
2392 ifr.ifr_ifru.ifru_data = p;
2393 return ioctl(sock_ioctl, cmd, &ifr);
2396 #ifdef IFLA_IPTUN_MAX
2397 static int system_add_ip6_tunnel(const char *name, const unsigned int link,
2398 struct blob_attr **tb)
2400 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2401 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2402 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2403 struct blob_attr *cur;
2404 int ret = 0, ttl = 0;
2409 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2410 nla_put_string(nlm, IFLA_IFNAME, name);
2413 nla_put_u32(nlm, IFLA_LINK, link);
2415 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2421 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2422 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2429 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2431 if ((cur = tb[TUNNEL_ATTR_TTL]))
2432 ttl = blobmsg_get_u32(cur);
2434 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2435 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2437 struct in6_addr in6buf;
2438 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2439 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2443 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2446 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2447 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2451 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2454 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2455 struct blob_attr *tb_data[__IPIP6_DATA_ATTR_MAX];
2456 uint32_t tun_flags = IP6_TNL_F_IGN_ENCAP_LIMIT;
2458 blobmsg_parse(ipip6_data_attr_list.params, __IPIP6_DATA_ATTR_MAX, tb_data,
2459 blobmsg_data(cur), blobmsg_len(cur));
2461 if ((cur = tb_data[IPIP6_DATA_ENCAPLIMIT])) {
2462 char *str = blobmsg_get_string(cur);
2464 if (strcmp(str, "ignore")) {
2466 unsigned encap_limit = strtoul(str, &e, 0);
2468 if (e == str || *e || encap_limit > 255) {
2473 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, encap_limit);
2474 tun_flags &= ~IP6_TNL_F_IGN_ENCAP_LIMIT;
2478 #ifdef IFLA_IPTUN_FMR_MAX
2479 if ((cur = tb_data[IPIP6_DATA_FMRS])) {
2480 struct blob_attr *rcur;
2481 unsigned rrem, fmrcnt = 0;
2482 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2489 blobmsg_for_each_attr(rcur, cur, rrem) {
2490 struct blob_attr *tb_fmr[__FMR_DATA_ATTR_MAX], *tb_cur;
2491 struct in6_addr ip6prefix;
2492 struct in_addr ip4prefix;
2493 unsigned ip4len, ip6len, ealen, offset;
2495 blobmsg_parse(fmr_data_attr_list.params, __FMR_DATA_ATTR_MAX, tb_fmr,
2496 blobmsg_data(rcur), blobmsg_len(rcur));
2498 if (!(tb_cur = tb_fmr[FMR_DATA_PREFIX6]) ||
2499 !parse_ip_and_netmask(AF_INET6,
2500 blobmsg_data(tb_cur), &ip6prefix,
2506 if (!(tb_cur = tb_fmr[FMR_DATA_PREFIX4]) ||
2507 !parse_ip_and_netmask(AF_INET,
2508 blobmsg_data(tb_cur), &ip4prefix,
2514 if (!(tb_cur = tb_fmr[FMR_DATA_EALEN])) {
2518 ealen = blobmsg_get_u32(tb_cur);
2520 if (!(tb_cur = tb_fmr[FMR_DATA_OFFSET])) {
2524 offset = blobmsg_get_u32(tb_cur);
2526 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2532 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2533 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2534 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2535 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2536 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2537 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2539 nla_nest_end(nlm, rule);
2542 nla_nest_end(nlm, fmrs);
2546 nla_put_u32(nlm, IFLA_IPTUN_FLAGS, tun_flags);
2549 nla_nest_end(nlm, infodata);
2550 nla_nest_end(nlm, linkinfo);
2552 return system_rtnl_call(nlm);
2560 #ifdef IFLA_IPTUN_MAX
2561 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
2562 static int system_add_gre_tunnel(const char *name, const char *kind,
2563 const unsigned int link, struct blob_attr **tb, bool v6)
2566 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2567 struct blob_attr *cur;
2568 uint32_t ikey = 0, okey = 0, flowinfo = 0, flags6 = IP6_TNL_F_IGN_ENCAP_LIMIT;
2569 uint16_t iflags = 0, oflags = 0;
2571 int ret = 0, ttl = 0;
2572 unsigned encap_limit = 0;
2574 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2578 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2579 nla_put_string(nlm, IFLA_IFNAME, name);
2581 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2587 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2588 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2595 nla_put_u32(nlm, IFLA_GRE_LINK, link);
2597 if ((cur = tb[TUNNEL_ATTR_TTL]))
2598 ttl = blobmsg_get_u32(cur);
2600 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2601 char *str = blobmsg_get_string(cur);
2602 if (strcmp(str, "inherit")) {
2605 if (!system_tos_aton(str, &uval)) {
2611 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
2616 flags6 |= IP6_TNL_F_USE_ORIG_TCLASS;
2622 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2623 struct blob_attr *tb_data[__GRE_DATA_ATTR_MAX];
2625 blobmsg_parse(gre_data_attr_list.params, __GRE_DATA_ATTR_MAX, tb_data,
2626 blobmsg_data(cur), blobmsg_len(cur));
2628 if ((cur = tb_data[GRE_DATA_IKEY])) {
2629 if ((ikey = blobmsg_get_u32(cur)))
2633 if ((cur = tb_data[GRE_DATA_OKEY])) {
2634 if ((okey = blobmsg_get_u32(cur)))
2638 if ((cur = tb_data[GRE_DATA_ICSUM])) {
2639 if (blobmsg_get_bool(cur))
2643 if ((cur = tb_data[GRE_DATA_OCSUM])) {
2644 if (blobmsg_get_bool(cur))
2648 if ((cur = tb_data[GRE_DATA_ISEQNO])) {
2649 if (blobmsg_get_bool(cur))
2653 if ((cur = tb_data[GRE_DATA_OSEQNO])) {
2654 if (blobmsg_get_bool(cur))
2658 if ((cur = tb_data[GRE_DATA_ENCAPLIMIT])) {
2659 char *str = blobmsg_get_string(cur);
2661 if (strcmp(str, "ignore")) {
2664 encap_limit = strtoul(str, &e, 0);
2666 if (e == str || *e || encap_limit > 255) {
2671 flags6 &= ~IP6_TNL_F_IGN_ENCAP_LIMIT;
2677 struct in6_addr in6buf;
2678 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2679 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2683 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
2686 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2687 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2691 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
2694 if (!(flags6 & IP6_TNL_F_IGN_ENCAP_LIMIT))
2695 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, encap_limit);
2698 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
2701 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags6);
2706 struct in_addr inbuf;
2709 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2710 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2714 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
2717 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2718 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2722 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
2724 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
2726 okey = inbuf.s_addr;
2731 ikey = inbuf.s_addr;
2737 if ((cur = tb[TUNNEL_ATTR_DF]))
2738 set_df = blobmsg_get_bool(cur);
2741 /* ttl != 0 and nopmtudisc are incompatible */
2749 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
2751 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
2755 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
2758 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
2761 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
2764 nla_put_u32(nlm, IFLA_GRE_OKEY, htonl(okey));
2767 nla_put_u32(nlm, IFLA_GRE_IKEY, htonl(ikey));
2769 nla_nest_end(nlm, infodata);
2770 nla_nest_end(nlm, linkinfo);
2772 return system_rtnl_call(nlm);
2781 static int system_add_vti_tunnel(const char *name, const char *kind,
2782 const unsigned int link, struct blob_attr **tb, bool v6)
2785 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2786 struct blob_attr *cur;
2789 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2793 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2794 nla_put_string(nlm, IFLA_IFNAME, name);
2796 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2802 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2803 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2810 nla_put_u32(nlm, IFLA_VTI_LINK, link);
2813 struct in6_addr in6buf;
2814 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2815 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2819 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(in6buf), &in6buf);
2822 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2823 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2827 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(in6buf), &in6buf);
2831 struct in_addr inbuf;
2833 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2834 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2838 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(inbuf), &inbuf);
2841 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2842 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2846 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(inbuf), &inbuf);
2851 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2852 struct blob_attr *tb_data[__VTI_DATA_ATTR_MAX];
2853 uint32_t ikey = 0, okey = 0;
2855 blobmsg_parse(vti_data_attr_list.params, __VTI_DATA_ATTR_MAX, tb_data,
2856 blobmsg_data(cur), blobmsg_len(cur));
2858 if ((cur = tb_data[VTI_DATA_IKEY])) {
2859 if ((ikey = blobmsg_get_u32(cur)))
2860 nla_put_u32(nlm, IFLA_VTI_IKEY, htonl(ikey));
2863 if ((cur = tb_data[VTI_DATA_OKEY])) {
2864 if ((okey = blobmsg_get_u32(cur)))
2865 nla_put_u32(nlm, IFLA_VTI_OKEY, htonl(okey));
2869 nla_nest_end(nlm, infodata);
2870 nla_nest_end(nlm, linkinfo);
2872 return system_rtnl_call(nlm);
2880 #ifdef IFLA_XFRM_MAX
2881 static int system_add_xfrm_tunnel(const char *name, const char *kind,
2882 const unsigned int link, struct blob_attr **tb)
2885 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2886 struct blob_attr *cur;
2889 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL);
2893 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2894 nla_put_string(nlm, IFLA_IFNAME, name);
2896 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2902 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2903 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2910 nla_put_u32(nlm, IFLA_XFRM_LINK, link);
2912 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2913 struct blob_attr *tb_data[__XFRM_DATA_ATTR_MAX];
2916 blobmsg_parse(xfrm_data_attr_list.params, __XFRM_DATA_ATTR_MAX, tb_data,
2917 blobmsg_data(cur), blobmsg_len(cur));
2919 if ((cur = tb_data[XFRM_DATA_IF_ID])) {
2920 if ((if_id = blobmsg_get_u32(cur)))
2921 nla_put_u32(nlm, IFLA_XFRM_IF_ID, if_id);
2926 nla_nest_end(nlm, infodata);
2927 nla_nest_end(nlm, linkinfo);
2929 return system_rtnl_call(nlm);
2937 #ifdef IFLA_VXLAN_MAX
2938 static int system_add_vxlan(const char *name, const unsigned int link, struct blob_attr **tb, bool v6)
2940 struct blob_attr *tb_data[__VXLAN_DATA_ATTR_MAX];
2942 struct nlattr *linkinfo, *data;
2943 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
2944 struct blob_attr *cur;
2947 if ((cur = tb[TUNNEL_ATTR_DATA]))
2948 blobmsg_parse(vxlan_data_attr_list.params, __VXLAN_DATA_ATTR_MAX, tb_data,
2949 blobmsg_data(cur), blobmsg_len(cur));
2953 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
2958 nlmsg_append(msg, &iim, sizeof(iim), 0);
2960 nla_put_string(msg, IFLA_IFNAME, name);
2962 if ((cur = tb_data[VXLAN_DATA_ATTR_MACADDR])) {
2963 struct ether_addr *ea = ether_aton(blobmsg_get_string(cur));
2969 nla_put(msg, IFLA_ADDRESS, ETH_ALEN, ea);
2972 if ((cur = tb[TUNNEL_ATTR_MTU])) {
2973 uint32_t mtu = blobmsg_get_u32(cur);
2974 nla_put_u32(msg, IFLA_MTU, mtu);
2977 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO))) {
2982 nla_put_string(msg, IFLA_INFO_KIND, "vxlan");
2984 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) {
2990 nla_put_u32(msg, IFLA_VXLAN_LINK, link);
2992 if ((cur = tb_data[VXLAN_DATA_ATTR_ID])) {
2993 uint32_t id = blobmsg_get_u32(cur);
2994 if (id >= (1u << 24) - 1) {
2999 nla_put_u32(msg, IFLA_VXLAN_ID, id);
3003 struct in6_addr in6buf;
3004 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
3005 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
3009 nla_put(msg, IFLA_VXLAN_LOCAL6, sizeof(in6buf), &in6buf);
3012 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
3013 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
3017 nla_put(msg, IFLA_VXLAN_GROUP6, sizeof(in6buf), &in6buf);
3020 struct in_addr inbuf;
3022 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
3023 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
3027 nla_put(msg, IFLA_VXLAN_LOCAL, sizeof(inbuf), &inbuf);
3030 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
3031 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
3035 nla_put(msg, IFLA_VXLAN_GROUP, sizeof(inbuf), &inbuf);
3039 uint32_t port = 4789;
3040 if ((cur = tb_data[VXLAN_DATA_ATTR_PORT])) {
3041 port = blobmsg_get_u32(cur);
3042 if (port < 1 || port > 65535) {
3047 nla_put_u16(msg, IFLA_VXLAN_PORT, htons(port));
3049 if ((cur = tb_data[VXLAN_DATA_ATTR_RXCSUM])) {
3050 bool rxcsum = blobmsg_get_bool(cur);
3051 nla_put_u8(msg, IFLA_VXLAN_UDP_ZERO_CSUM6_RX, !rxcsum);
3054 if ((cur = tb_data[VXLAN_DATA_ATTR_TXCSUM])) {
3055 bool txcsum = blobmsg_get_bool(cur);
3056 nla_put_u8(msg, IFLA_VXLAN_UDP_CSUM, txcsum);
3057 nla_put_u8(msg, IFLA_VXLAN_UDP_ZERO_CSUM6_TX, !txcsum);
3060 if ((cur = tb[TUNNEL_ATTR_TOS])) {
3061 char *str = blobmsg_get_string(cur);
3064 if (strcmp(str, "inherit")) {
3065 if (!system_tos_aton(str, &tos)) {
3071 nla_put_u8(msg, IFLA_VXLAN_TOS, tos);
3074 if ((cur = tb[TUNNEL_ATTR_TTL])) {
3075 uint32_t ttl = blobmsg_get_u32(cur);
3076 if (ttl < 1 || ttl > 255) {
3081 nla_put_u8(msg, IFLA_VXLAN_TTL, ttl);
3084 nla_nest_end(msg, data);
3085 nla_nest_end(msg, linkinfo);
3087 ret = system_rtnl_call(msg);
3089 D(SYSTEM, "Error adding vxlan '%s': %d\n", name, ret);
3099 static int system_add_sit_tunnel(const char *name, const unsigned int link, struct blob_attr **tb)
3101 struct blob_attr *cur;
3104 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
3108 if ((cur = tb[TUNNEL_ATTR_DATA])) {
3109 struct blob_attr *tb_data[__SIXRD_DATA_ATTR_MAX];
3111 struct ip_tunnel_6rd p6;
3113 blobmsg_parse(sixrd_data_attr_list.params, __SIXRD_DATA_ATTR_MAX, tb_data,
3114 blobmsg_data(cur), blobmsg_len(cur));
3116 memset(&p6, 0, sizeof(p6));
3118 if ((cur = tb_data[SIXRD_DATA_PREFIX])) {
3119 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
3120 &p6.prefix, &mask) || mask > 128) {
3125 p6.prefixlen = mask;
3128 if ((cur = tb_data[SIXRD_DATA_RELAY_PREFIX])) {
3129 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
3130 &p6.relay_prefix, &mask) || mask > 32) {
3135 p6.relay_prefixlen = mask;
3138 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
3148 __system_del_ip_tunnel(name, tb);
3152 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
3154 struct blob_attr *cur;
3156 struct ip_tunnel_parm p = {
3165 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
3166 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
3169 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
3170 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
3173 if ((cur = tb[TUNNEL_ATTR_DF]))
3174 set_df = blobmsg_get_bool(cur);
3176 if ((cur = tb[TUNNEL_ATTR_TTL]))
3177 p.iph.ttl = blobmsg_get_u32(cur);
3179 if ((cur = tb[TUNNEL_ATTR_TOS])) {
3180 char *str = blobmsg_get_string(cur);
3181 if (strcmp(str, "inherit")) {
3184 if (!system_tos_aton(str, &uval))
3192 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
3193 /* ttl !=0 and nopmtudisc are incompatible */
3194 if (p.iph.ttl && p.iph.frag_off == 0)
3197 strncpy(p.name, name, sizeof(p.name) - 1);
3199 switch (p.iph.protocol) {
3201 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
3203 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
3210 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
3212 struct blob_attr *cur;
3215 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
3217 str = blobmsg_data(cur);
3219 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
3220 !strcmp(str, "greip6") || !strcmp(str, "gretapip6") ||
3221 !strcmp(str, "vtiip") || !strcmp(str, "vtiip6") ||
3222 !strcmp(str, "vxlan") || !strcmp(str, "vxlan6"))
3223 return system_link_del(name);
3225 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
3228 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
3230 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
3232 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
3233 blob_data(attr), blob_len(attr));
3235 return __system_del_ip_tunnel(name, tb);
3238 int system_update_ipv6_mtu(struct device *dev, int mtu)
3244 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
3247 fd = open(buf, O_RDWR);
3252 ssize_t len = read(fd, buf, sizeof(buf) - 1);
3259 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) > 0)
3268 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
3270 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
3271 struct blob_attr *cur;
3274 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
3275 blob_data(attr), blob_len(attr));
3277 __system_del_ip_tunnel(name, tb);
3279 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
3281 str = blobmsg_data(cur);
3283 unsigned int ttl = 0;
3284 if ((cur = tb[TUNNEL_ATTR_TTL])) {
3285 ttl = blobmsg_get_u32(cur);
3290 unsigned int link = 0;
3291 if ((cur = tb[TUNNEL_ATTR_LINK])) {
3292 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
3296 if (iface->l3_dev.dev)
3297 link = iface->l3_dev.dev->ifindex;
3300 if (!strcmp(str, "sit"))
3301 return system_add_sit_tunnel(name, link, tb);
3302 #ifdef IFLA_IPTUN_MAX
3303 else if (!strcmp(str, "ipip6")) {
3304 return system_add_ip6_tunnel(name, link, tb);
3305 } else if (!strcmp(str, "greip")) {
3306 return system_add_gre_tunnel(name, "gre", link, tb, false);
3307 } else if (!strcmp(str, "gretapip")) {
3308 return system_add_gre_tunnel(name, "gretap", link, tb, false);
3309 } else if (!strcmp(str, "greip6")) {
3310 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
3311 } else if (!strcmp(str, "gretapip6")) {
3312 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
3314 } else if (!strcmp(str, "vtiip")) {
3315 return system_add_vti_tunnel(name, "vti", link, tb, false);
3316 } else if (!strcmp(str, "vtiip6")) {
3317 return system_add_vti_tunnel(name, "vti6", link, tb, true);
3319 #ifdef IFLA_XFRM_MAX
3320 } else if (!strcmp(str, "xfrm")) {
3321 return system_add_xfrm_tunnel(name, "xfrm", link, tb);
3323 #ifdef IFLA_VXLAN_MAX
3324 } else if(!strcmp(str, "vxlan")) {
3325 return system_add_vxlan(name, link, tb, false);
3326 } else if(!strcmp(str, "vxlan6")) {
3327 return system_add_vxlan(name, link, tb, true);
3330 } else if (!strcmp(str, "ipip")) {
3331 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);