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),
1948 if (cmd == RTM_NEWNEIGH)
1949 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1951 msg = nlmsg_alloc_simple(cmd, flags);
1956 nlmsg_append(msg, &ndm, sizeof(ndm), 0);
1958 nla_put(msg, NDA_DST, alen, &neighbor->addr);
1959 if (neighbor->flags & DEVNEIGH_MAC)
1960 nla_put(msg, NDA_LLADDR, sizeof(neighbor->macaddr), &neighbor->macaddr);
1963 return system_rtnl_call(msg);
1966 int system_add_neighbor(struct device *dev, struct device_neighbor *neighbor)
1968 return system_neigh(dev, neighbor, RTM_NEWNEIGH);
1971 int system_del_neighbor(struct device *dev, struct device_neighbor *neighbor)
1973 return system_neigh(dev, neighbor, RTM_DELNEIGH);
1976 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1978 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1980 unsigned int flags = 0;
1983 have_gw = !!route->nexthop.in.s_addr;
1985 have_gw = route->nexthop.in6.s6_addr32[0] ||
1986 route->nexthop.in6.s6_addr32[1] ||
1987 route->nexthop.in6.s6_addr32[2] ||
1988 route->nexthop.in6.s6_addr32[3];
1990 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1991 ? route->table : RT_TABLE_MAIN;
1993 struct rtmsg rtm = {
1994 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1995 .rtm_dst_len = route->mask,
1996 .rtm_src_len = route->sourcemask,
1997 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1998 .rtm_protocol = (route->flags & DEVROUTE_PROTO) ? route->proto : RTPROT_STATIC,
1999 .rtm_scope = RT_SCOPE_NOWHERE,
2000 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
2001 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
2005 if (cmd == RTM_NEWROUTE) {
2006 flags |= NLM_F_CREATE | NLM_F_REPLACE;
2008 if (!dev) { /* Add null-route */
2009 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
2010 rtm.rtm_type = RTN_UNREACHABLE;
2013 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
2016 if (route->flags & DEVROUTE_TYPE) {
2017 rtm.rtm_type = route->type;
2018 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
2019 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
2020 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
2021 rtm.rtm_table = RT_TABLE_LOCAL;
2024 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT) {
2025 rtm.rtm_scope = RT_SCOPE_HOST;
2026 } else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
2027 rtm.rtm_type == RTN_ANYCAST) {
2028 rtm.rtm_scope = RT_SCOPE_LINK;
2029 } else if (rtm.rtm_type == RTN_BLACKHOLE || rtm.rtm_type == RTN_UNREACHABLE ||
2030 rtm.rtm_type == RTN_PROHIBIT || rtm.rtm_type == RTN_FAILED_POLICY ||
2031 rtm.rtm_type == RTN_THROW) {
2032 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
2037 msg = nlmsg_alloc_simple(cmd, flags);
2041 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
2044 nla_put(msg, RTA_DST, alen, &route->addr);
2046 if (route->sourcemask) {
2047 if (rtm.rtm_family == AF_INET)
2048 nla_put(msg, RTA_PREFSRC, alen, &route->source);
2050 nla_put(msg, RTA_SRC, alen, &route->source);
2053 if (route->metric > 0)
2054 nla_put_u32(msg, RTA_PRIORITY, route->metric);
2057 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
2060 nla_put_u32(msg, RTA_OIF, dev->ifindex);
2063 nla_put_u32(msg, RTA_TABLE, table);
2065 if (route->flags & DEVROUTE_MTU) {
2066 struct nlattr *metrics;
2068 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
2069 goto nla_put_failure;
2071 nla_put_u32(msg, RTAX_MTU, route->mtu);
2073 nla_nest_end(msg, metrics);
2076 return system_rtnl_call(msg);
2083 int system_add_route(struct device *dev, struct device_route *route)
2085 return system_rt(dev, route, RTM_NEWROUTE);
2088 int system_del_route(struct device *dev, struct device_route *route)
2090 return system_rt(dev, route, RTM_DELROUTE);
2093 int system_flush_routes(void)
2095 const char *names[] = {
2096 "/proc/sys/net/ipv4/route/flush",
2097 "/proc/sys/net/ipv6/route/flush"
2101 for (i = 0; i < ARRAY_SIZE(names); i++) {
2102 fd = open(names[i], O_WRONLY);
2106 if (write(fd, "-1", 2)) {}
2112 bool system_resolve_rt_type(const char *type, unsigned int *id)
2114 return system_rtn_aton(type, id);
2117 bool system_resolve_rt_proto(const char *type, unsigned int *id)
2121 unsigned int n, proto = 256;
2122 n = strtoul(type, &e, 0);
2123 if (!*e && e != type)
2125 else if (!strcmp(type, "unspec"))
2126 proto = RTPROT_UNSPEC;
2127 else if (!strcmp(type, "kernel"))
2128 proto = RTPROT_KERNEL;
2129 else if (!strcmp(type, "boot"))
2130 proto = RTPROT_BOOT;
2131 else if (!strcmp(type, "static"))
2132 proto = RTPROT_STATIC;
2133 else if ((f = fopen("/etc/iproute2/rt_protos", "r")) != NULL) {
2134 while (fgets(buf, sizeof(buf) - 1, f) != NULL) {
2135 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
2138 n = strtoul(e, NULL, 10);
2139 e = strtok(NULL, " \t\n");
2141 if (e && !strcmp(e, type)) {
2156 bool system_resolve_rt_table(const char *name, unsigned int *id)
2160 unsigned int n, table = RT_TABLE_UNSPEC;
2162 /* first try to parse table as number */
2163 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
2166 /* handle well known aliases */
2167 else if (!strcmp(name, "default"))
2168 table = RT_TABLE_DEFAULT;
2169 else if (!strcmp(name, "main"))
2170 table = RT_TABLE_MAIN;
2171 else if (!strcmp(name, "local"))
2172 table = RT_TABLE_LOCAL;
2174 /* try to look up name in /etc/iproute2/rt_tables */
2175 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
2177 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
2179 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
2182 n = strtoul(e, NULL, 10);
2183 e = strtok(NULL, " \t\n");
2185 if (e && !strcmp(e, name))
2195 if (table == RT_TABLE_UNSPEC)
2202 bool system_is_default_rt_table(unsigned int id)
2204 return (id == RT_TABLE_MAIN);
2207 bool system_resolve_rpfilter(const char *filter, unsigned int *id)
2212 if (!strcmp(filter, "strict"))
2214 else if (!strcmp(filter, "loose"))
2217 n = strtoul(filter, &e, 0);
2218 if (*e || e == filter || n > 2)
2226 static int system_iprule(struct iprule *rule, int cmd)
2228 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
2231 struct rtmsg rtm = {
2232 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
2233 .rtm_protocol = RTPROT_STATIC,
2234 .rtm_scope = RT_SCOPE_UNIVERSE,
2235 .rtm_table = RT_TABLE_UNSPEC,
2236 .rtm_type = RTN_UNSPEC,
2240 if (cmd == RTM_NEWRULE)
2241 rtm.rtm_type = RTN_UNICAST;
2244 rtm.rtm_flags |= FIB_RULE_INVERT;
2246 if (rule->flags & IPRULE_SRC)
2247 rtm.rtm_src_len = rule->src_mask;
2249 if (rule->flags & IPRULE_DEST)
2250 rtm.rtm_dst_len = rule->dest_mask;
2252 if (rule->flags & IPRULE_TOS)
2253 rtm.rtm_tos = rule->tos;
2255 if (rule->flags & IPRULE_LOOKUP) {
2256 if (rule->lookup < 256)
2257 rtm.rtm_table = rule->lookup;
2260 if (rule->flags & IPRULE_ACTION)
2261 rtm.rtm_type = rule->action;
2262 else if (rule->flags & IPRULE_GOTO)
2263 rtm.rtm_type = FR_ACT_GOTO;
2264 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
2265 rtm.rtm_type = FR_ACT_NOP;
2267 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
2272 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
2274 if (rule->flags & IPRULE_IN)
2275 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
2277 if (rule->flags & IPRULE_OUT)
2278 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
2280 if (rule->flags & IPRULE_SRC)
2281 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
2283 if (rule->flags & IPRULE_DEST)
2284 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
2286 if (rule->flags & IPRULE_PRIORITY)
2287 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
2288 else if (cmd == RTM_NEWRULE)
2289 nla_put_u32(msg, FRA_PRIORITY, rule->order);
2291 if (rule->flags & IPRULE_FWMARK)
2292 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
2294 if (rule->flags & IPRULE_FWMASK)
2295 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
2297 if (rule->flags & IPRULE_LOOKUP) {
2298 if (rule->lookup >= 256)
2299 nla_put_u32(msg, FRA_TABLE, rule->lookup);
2302 if (rule->flags & IPRULE_SUP_PREFIXLEN)
2303 nla_put_u32(msg, FRA_SUPPRESS_PREFIXLEN, rule->sup_prefixlen);
2305 if (rule->flags & IPRULE_GOTO)
2306 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
2308 return system_rtnl_call(msg);
2311 int system_add_iprule(struct iprule *rule)
2313 return system_iprule(rule, RTM_NEWRULE);
2316 int system_del_iprule(struct iprule *rule)
2318 return system_iprule(rule, RTM_DELRULE);
2321 int system_flush_iprules(void)
2326 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
2327 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
2329 memset(&rule, 0, sizeof(rule));
2332 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2335 rule.lookup = RT_TABLE_LOCAL;
2336 rv |= system_iprule(&rule, RTM_NEWRULE);
2338 rule.priority = 32766;
2339 rule.lookup = RT_TABLE_MAIN;
2340 rv |= system_iprule(&rule, RTM_NEWRULE);
2342 rule.priority = 32767;
2343 rule.lookup = RT_TABLE_DEFAULT;
2344 rv |= system_iprule(&rule, RTM_NEWRULE);
2347 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2350 rule.lookup = RT_TABLE_LOCAL;
2351 rv |= system_iprule(&rule, RTM_NEWRULE);
2353 rule.priority = 32766;
2354 rule.lookup = RT_TABLE_MAIN;
2355 rv |= system_iprule(&rule, RTM_NEWRULE);
2360 bool system_resolve_iprule_action(const char *action, unsigned int *id)
2362 return system_rtn_aton(action, id);
2365 time_t system_get_rtime(void)
2370 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
2373 if (gettimeofday(&tv, NULL) == 0)
2380 #define IP_DF 0x4000
2383 static int tunnel_ioctl(const char *name, int cmd, void *p)
2387 memset(&ifr, 0, sizeof(ifr));
2388 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name) - 1);
2389 ifr.ifr_ifru.ifru_data = p;
2390 return ioctl(sock_ioctl, cmd, &ifr);
2393 #ifdef IFLA_IPTUN_MAX
2394 static int system_add_ip6_tunnel(const char *name, const unsigned int link,
2395 struct blob_attr **tb)
2397 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2398 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2399 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2400 struct blob_attr *cur;
2401 int ret = 0, ttl = 0;
2406 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2407 nla_put_string(nlm, IFLA_IFNAME, name);
2410 nla_put_u32(nlm, IFLA_LINK, link);
2412 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2418 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2419 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2426 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2428 if ((cur = tb[TUNNEL_ATTR_TTL]))
2429 ttl = blobmsg_get_u32(cur);
2431 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2432 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2434 struct in6_addr in6buf;
2435 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2436 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2440 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2443 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2444 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2448 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2451 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2452 struct blob_attr *tb_data[__IPIP6_DATA_ATTR_MAX];
2453 uint32_t tun_flags = IP6_TNL_F_IGN_ENCAP_LIMIT;
2455 blobmsg_parse(ipip6_data_attr_list.params, __IPIP6_DATA_ATTR_MAX, tb_data,
2456 blobmsg_data(cur), blobmsg_len(cur));
2458 if ((cur = tb_data[IPIP6_DATA_ENCAPLIMIT])) {
2459 char *str = blobmsg_get_string(cur);
2461 if (strcmp(str, "ignore")) {
2463 unsigned encap_limit = strtoul(str, &e, 0);
2465 if (e == str || *e || encap_limit > 255) {
2470 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, encap_limit);
2471 tun_flags &= ~IP6_TNL_F_IGN_ENCAP_LIMIT;
2475 #ifdef IFLA_IPTUN_FMR_MAX
2476 if ((cur = tb_data[IPIP6_DATA_FMRS])) {
2477 struct blob_attr *rcur;
2478 unsigned rrem, fmrcnt = 0;
2479 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2486 blobmsg_for_each_attr(rcur, cur, rrem) {
2487 struct blob_attr *tb_fmr[__FMR_DATA_ATTR_MAX], *tb_cur;
2488 struct in6_addr ip6prefix;
2489 struct in_addr ip4prefix;
2490 unsigned ip4len, ip6len, ealen, offset;
2492 blobmsg_parse(fmr_data_attr_list.params, __FMR_DATA_ATTR_MAX, tb_fmr,
2493 blobmsg_data(rcur), blobmsg_len(rcur));
2495 if (!(tb_cur = tb_fmr[FMR_DATA_PREFIX6]) ||
2496 !parse_ip_and_netmask(AF_INET6,
2497 blobmsg_data(tb_cur), &ip6prefix,
2503 if (!(tb_cur = tb_fmr[FMR_DATA_PREFIX4]) ||
2504 !parse_ip_and_netmask(AF_INET,
2505 blobmsg_data(tb_cur), &ip4prefix,
2511 if (!(tb_cur = tb_fmr[FMR_DATA_EALEN])) {
2515 ealen = blobmsg_get_u32(tb_cur);
2517 if (!(tb_cur = tb_fmr[FMR_DATA_OFFSET])) {
2521 offset = blobmsg_get_u32(tb_cur);
2523 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2529 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2530 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2531 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2532 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2533 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2534 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2536 nla_nest_end(nlm, rule);
2539 nla_nest_end(nlm, fmrs);
2543 nla_put_u32(nlm, IFLA_IPTUN_FLAGS, tun_flags);
2546 nla_nest_end(nlm, infodata);
2547 nla_nest_end(nlm, linkinfo);
2549 return system_rtnl_call(nlm);
2557 #ifdef IFLA_IPTUN_MAX
2558 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
2559 static int system_add_gre_tunnel(const char *name, const char *kind,
2560 const unsigned int link, struct blob_attr **tb, bool v6)
2563 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2564 struct blob_attr *cur;
2565 uint32_t ikey = 0, okey = 0, flowinfo = 0, flags6 = IP6_TNL_F_IGN_ENCAP_LIMIT;
2566 uint16_t iflags = 0, oflags = 0;
2568 int ret = 0, ttl = 0;
2569 unsigned encap_limit = 0;
2571 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2575 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2576 nla_put_string(nlm, IFLA_IFNAME, name);
2578 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2584 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2585 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2592 nla_put_u32(nlm, IFLA_GRE_LINK, link);
2594 if ((cur = tb[TUNNEL_ATTR_TTL]))
2595 ttl = blobmsg_get_u32(cur);
2597 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2598 char *str = blobmsg_get_string(cur);
2599 if (strcmp(str, "inherit")) {
2602 if (!system_tos_aton(str, &uval)) {
2608 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
2613 flags6 |= IP6_TNL_F_USE_ORIG_TCLASS;
2619 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2620 struct blob_attr *tb_data[__GRE_DATA_ATTR_MAX];
2622 blobmsg_parse(gre_data_attr_list.params, __GRE_DATA_ATTR_MAX, tb_data,
2623 blobmsg_data(cur), blobmsg_len(cur));
2625 if ((cur = tb_data[GRE_DATA_IKEY])) {
2626 if ((ikey = blobmsg_get_u32(cur)))
2630 if ((cur = tb_data[GRE_DATA_OKEY])) {
2631 if ((okey = blobmsg_get_u32(cur)))
2635 if ((cur = tb_data[GRE_DATA_ICSUM])) {
2636 if (blobmsg_get_bool(cur))
2640 if ((cur = tb_data[GRE_DATA_OCSUM])) {
2641 if (blobmsg_get_bool(cur))
2645 if ((cur = tb_data[GRE_DATA_ISEQNO])) {
2646 if (blobmsg_get_bool(cur))
2650 if ((cur = tb_data[GRE_DATA_OSEQNO])) {
2651 if (blobmsg_get_bool(cur))
2655 if ((cur = tb_data[GRE_DATA_ENCAPLIMIT])) {
2656 char *str = blobmsg_get_string(cur);
2658 if (strcmp(str, "ignore")) {
2661 encap_limit = strtoul(str, &e, 0);
2663 if (e == str || *e || encap_limit > 255) {
2668 flags6 &= ~IP6_TNL_F_IGN_ENCAP_LIMIT;
2674 struct in6_addr in6buf;
2675 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2676 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2680 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
2683 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2684 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2688 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
2691 if (!(flags6 & IP6_TNL_F_IGN_ENCAP_LIMIT))
2692 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, encap_limit);
2695 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
2698 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags6);
2703 struct in_addr inbuf;
2706 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2707 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2711 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
2714 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2715 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2719 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
2721 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
2723 okey = inbuf.s_addr;
2728 ikey = inbuf.s_addr;
2734 if ((cur = tb[TUNNEL_ATTR_DF]))
2735 set_df = blobmsg_get_bool(cur);
2738 /* ttl != 0 and nopmtudisc are incompatible */
2746 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
2748 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
2752 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
2755 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
2758 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
2761 nla_put_u32(nlm, IFLA_GRE_OKEY, htonl(okey));
2764 nla_put_u32(nlm, IFLA_GRE_IKEY, htonl(ikey));
2766 nla_nest_end(nlm, infodata);
2767 nla_nest_end(nlm, linkinfo);
2769 return system_rtnl_call(nlm);
2778 static int system_add_vti_tunnel(const char *name, const char *kind,
2779 const unsigned int link, struct blob_attr **tb, bool v6)
2782 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2783 struct blob_attr *cur;
2786 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2790 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2791 nla_put_string(nlm, IFLA_IFNAME, name);
2793 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2799 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2800 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2807 nla_put_u32(nlm, IFLA_VTI_LINK, link);
2810 struct in6_addr in6buf;
2811 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2812 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2816 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(in6buf), &in6buf);
2819 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2820 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2824 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(in6buf), &in6buf);
2828 struct in_addr inbuf;
2830 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2831 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2835 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(inbuf), &inbuf);
2838 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2839 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2843 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(inbuf), &inbuf);
2848 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2849 struct blob_attr *tb_data[__VTI_DATA_ATTR_MAX];
2850 uint32_t ikey = 0, okey = 0;
2852 blobmsg_parse(vti_data_attr_list.params, __VTI_DATA_ATTR_MAX, tb_data,
2853 blobmsg_data(cur), blobmsg_len(cur));
2855 if ((cur = tb_data[VTI_DATA_IKEY])) {
2856 if ((ikey = blobmsg_get_u32(cur)))
2857 nla_put_u32(nlm, IFLA_VTI_IKEY, htonl(ikey));
2860 if ((cur = tb_data[VTI_DATA_OKEY])) {
2861 if ((okey = blobmsg_get_u32(cur)))
2862 nla_put_u32(nlm, IFLA_VTI_OKEY, htonl(okey));
2866 nla_nest_end(nlm, infodata);
2867 nla_nest_end(nlm, linkinfo);
2869 return system_rtnl_call(nlm);
2877 #ifdef IFLA_XFRM_MAX
2878 static int system_add_xfrm_tunnel(const char *name, const char *kind,
2879 const unsigned int link, struct blob_attr **tb)
2882 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2883 struct blob_attr *cur;
2886 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2890 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2891 nla_put_string(nlm, IFLA_IFNAME, name);
2893 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2899 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2900 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2907 nla_put_u32(nlm, IFLA_XFRM_LINK, link);
2909 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2910 struct blob_attr *tb_data[__XFRM_DATA_ATTR_MAX];
2913 blobmsg_parse(xfrm_data_attr_list.params, __XFRM_DATA_ATTR_MAX, tb_data,
2914 blobmsg_data(cur), blobmsg_len(cur));
2916 if ((cur = tb_data[XFRM_DATA_IF_ID])) {
2917 if ((if_id = blobmsg_get_u32(cur)))
2918 nla_put_u32(nlm, IFLA_XFRM_IF_ID, if_id);
2923 nla_nest_end(nlm, infodata);
2924 nla_nest_end(nlm, linkinfo);
2926 return system_rtnl_call(nlm);
2934 #ifdef IFLA_VXLAN_MAX
2935 static int system_add_vxlan(const char *name, const unsigned int link, struct blob_attr **tb, bool v6)
2937 struct blob_attr *tb_data[__VXLAN_DATA_ATTR_MAX];
2939 struct nlattr *linkinfo, *data;
2940 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
2941 struct blob_attr *cur;
2944 if ((cur = tb[TUNNEL_ATTR_DATA]))
2945 blobmsg_parse(vxlan_data_attr_list.params, __VXLAN_DATA_ATTR_MAX, tb_data,
2946 blobmsg_data(cur), blobmsg_len(cur));
2950 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
2955 nlmsg_append(msg, &iim, sizeof(iim), 0);
2957 nla_put_string(msg, IFLA_IFNAME, name);
2959 if ((cur = tb_data[VXLAN_DATA_ATTR_MACADDR])) {
2960 struct ether_addr *ea = ether_aton(blobmsg_get_string(cur));
2966 nla_put(msg, IFLA_ADDRESS, ETH_ALEN, ea);
2969 if ((cur = tb[TUNNEL_ATTR_MTU])) {
2970 uint32_t mtu = blobmsg_get_u32(cur);
2971 nla_put_u32(msg, IFLA_MTU, mtu);
2974 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO))) {
2979 nla_put_string(msg, IFLA_INFO_KIND, "vxlan");
2981 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) {
2987 nla_put_u32(msg, IFLA_VXLAN_LINK, link);
2989 if ((cur = tb_data[VXLAN_DATA_ATTR_ID])) {
2990 uint32_t id = blobmsg_get_u32(cur);
2991 if (id >= (1u << 24) - 1) {
2996 nla_put_u32(msg, IFLA_VXLAN_ID, id);
3000 struct in6_addr in6buf;
3001 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
3002 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
3006 nla_put(msg, IFLA_VXLAN_LOCAL6, sizeof(in6buf), &in6buf);
3009 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
3010 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
3014 nla_put(msg, IFLA_VXLAN_GROUP6, sizeof(in6buf), &in6buf);
3017 struct in_addr inbuf;
3019 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
3020 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
3024 nla_put(msg, IFLA_VXLAN_LOCAL, sizeof(inbuf), &inbuf);
3027 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
3028 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
3032 nla_put(msg, IFLA_VXLAN_GROUP, sizeof(inbuf), &inbuf);
3036 uint32_t port = 4789;
3037 if ((cur = tb_data[VXLAN_DATA_ATTR_PORT])) {
3038 port = blobmsg_get_u32(cur);
3039 if (port < 1 || port > 65535) {
3044 nla_put_u16(msg, IFLA_VXLAN_PORT, htons(port));
3046 if ((cur = tb_data[VXLAN_DATA_ATTR_RXCSUM])) {
3047 bool rxcsum = blobmsg_get_bool(cur);
3048 nla_put_u8(msg, IFLA_VXLAN_UDP_ZERO_CSUM6_RX, !rxcsum);
3051 if ((cur = tb_data[VXLAN_DATA_ATTR_TXCSUM])) {
3052 bool txcsum = blobmsg_get_bool(cur);
3053 nla_put_u8(msg, IFLA_VXLAN_UDP_CSUM, txcsum);
3054 nla_put_u8(msg, IFLA_VXLAN_UDP_ZERO_CSUM6_TX, !txcsum);
3057 if ((cur = tb[TUNNEL_ATTR_TOS])) {
3058 char *str = blobmsg_get_string(cur);
3061 if (strcmp(str, "inherit")) {
3062 if (!system_tos_aton(str, &tos)) {
3068 nla_put_u8(msg, IFLA_VXLAN_TOS, tos);
3071 if ((cur = tb[TUNNEL_ATTR_TTL])) {
3072 uint32_t ttl = blobmsg_get_u32(cur);
3073 if (ttl < 1 || ttl > 255) {
3078 nla_put_u8(msg, IFLA_VXLAN_TTL, ttl);
3081 nla_nest_end(msg, data);
3082 nla_nest_end(msg, linkinfo);
3084 ret = system_rtnl_call(msg);
3086 D(SYSTEM, "Error adding vxlan '%s': %d\n", name, ret);
3096 static int system_add_sit_tunnel(const char *name, const unsigned int link, struct blob_attr **tb)
3098 struct blob_attr *cur;
3101 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
3105 if ((cur = tb[TUNNEL_ATTR_DATA])) {
3106 struct blob_attr *tb_data[__SIXRD_DATA_ATTR_MAX];
3108 struct ip_tunnel_6rd p6;
3110 blobmsg_parse(sixrd_data_attr_list.params, __SIXRD_DATA_ATTR_MAX, tb_data,
3111 blobmsg_data(cur), blobmsg_len(cur));
3113 memset(&p6, 0, sizeof(p6));
3115 if ((cur = tb_data[SIXRD_DATA_PREFIX])) {
3116 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
3117 &p6.prefix, &mask) || mask > 128) {
3122 p6.prefixlen = mask;
3125 if ((cur = tb_data[SIXRD_DATA_RELAY_PREFIX])) {
3126 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
3127 &p6.relay_prefix, &mask) || mask > 32) {
3132 p6.relay_prefixlen = mask;
3135 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
3145 __system_del_ip_tunnel(name, tb);
3149 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
3151 struct blob_attr *cur;
3153 struct ip_tunnel_parm p = {
3162 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
3163 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
3166 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
3167 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
3170 if ((cur = tb[TUNNEL_ATTR_DF]))
3171 set_df = blobmsg_get_bool(cur);
3173 if ((cur = tb[TUNNEL_ATTR_TTL]))
3174 p.iph.ttl = blobmsg_get_u32(cur);
3176 if ((cur = tb[TUNNEL_ATTR_TOS])) {
3177 char *str = blobmsg_get_string(cur);
3178 if (strcmp(str, "inherit")) {
3181 if (!system_tos_aton(str, &uval))
3189 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
3190 /* ttl !=0 and nopmtudisc are incompatible */
3191 if (p.iph.ttl && p.iph.frag_off == 0)
3194 strncpy(p.name, name, sizeof(p.name) - 1);
3196 switch (p.iph.protocol) {
3198 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
3200 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
3207 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
3209 struct blob_attr *cur;
3212 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
3214 str = blobmsg_data(cur);
3216 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
3217 !strcmp(str, "greip6") || !strcmp(str, "gretapip6") ||
3218 !strcmp(str, "vtiip") || !strcmp(str, "vtiip6") ||
3219 !strcmp(str, "vxlan") || !strcmp(str, "vxlan6") ||
3220 !strcmp(str, "xfrm"))
3221 return system_link_del(name);
3223 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
3226 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
3228 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
3230 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
3231 blob_data(attr), blob_len(attr));
3233 return __system_del_ip_tunnel(name, tb);
3236 int system_update_ipv6_mtu(struct device *dev, int mtu)
3242 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
3245 fd = open(buf, O_RDWR);
3250 ssize_t len = read(fd, buf, sizeof(buf) - 1);
3257 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) > 0)
3266 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
3268 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
3269 struct blob_attr *cur;
3272 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
3273 blob_data(attr), blob_len(attr));
3275 __system_del_ip_tunnel(name, tb);
3277 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
3279 str = blobmsg_data(cur);
3281 unsigned int ttl = 0;
3282 if ((cur = tb[TUNNEL_ATTR_TTL])) {
3283 ttl = blobmsg_get_u32(cur);
3288 unsigned int link = 0;
3289 if ((cur = tb[TUNNEL_ATTR_LINK])) {
3290 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
3294 if (iface->l3_dev.dev)
3295 link = iface->l3_dev.dev->ifindex;
3298 if (!strcmp(str, "sit"))
3299 return system_add_sit_tunnel(name, link, tb);
3300 #ifdef IFLA_IPTUN_MAX
3301 else if (!strcmp(str, "ipip6")) {
3302 return system_add_ip6_tunnel(name, link, tb);
3303 } else if (!strcmp(str, "greip")) {
3304 return system_add_gre_tunnel(name, "gre", link, tb, false);
3305 } else if (!strcmp(str, "gretapip")) {
3306 return system_add_gre_tunnel(name, "gretap", link, tb, false);
3307 } else if (!strcmp(str, "greip6")) {
3308 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
3309 } else if (!strcmp(str, "gretapip6")) {
3310 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
3312 } else if (!strcmp(str, "vtiip")) {
3313 return system_add_vti_tunnel(name, "vti", link, tb, false);
3314 } else if (!strcmp(str, "vtiip6")) {
3315 return system_add_vti_tunnel(name, "vti6", link, tb, true);
3317 #ifdef IFLA_XFRM_MAX
3318 } else if (!strcmp(str, "xfrm")) {
3319 return system_add_xfrm_tunnel(name, "xfrm", link, tb);
3321 #ifdef IFLA_VXLAN_MAX
3322 } else if(!strcmp(str, "vxlan")) {
3323 return system_add_vxlan(name, link, tb, false);
3324 } else if(!strcmp(str, "vxlan6")) {
3325 return system_add_vxlan(name, link, tb, true);
3328 } else if (!strcmp(str, "ipip")) {
3329 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);