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>
30 #include <arpa/inet.h>
31 #include <netinet/ether.h>
32 #include <netinet/in.h>
34 #include <linux/rtnetlink.h>
35 #include <linux/neighbour.h>
36 #include <linux/sockios.h>
38 #include <linux/if_addr.h>
39 #include <linux/if_link.h>
40 #include <linux/if_vlan.h>
41 #include <linux/if_bridge.h>
42 #include <linux/if_tunnel.h>
43 #include <linux/ip6_tunnel.h>
44 #include <linux/ethtool.h>
45 #include <linux/fib_rules.h>
46 #include <linux/veth.h>
47 #include <linux/version.h>
51 #ifndef RTN_FAILED_POLICY
52 #define RTN_FAILED_POLICY 12
55 #ifndef IFA_F_NOPREFIXROUTE
56 #define IFA_F_NOPREFIXROUTE 0x200
60 #define IFA_FLAGS (IFA_MULTICAST + 1)
69 #include <netlink/msg.h>
70 #include <netlink/attr.h>
71 #include <netlink/socket.h>
72 #include <libubox/uloop.h>
80 struct uloop_fd uloop;
85 static int sock_ioctl = -1;
86 static struct nl_sock *sock_rtnl = NULL;
88 static int cb_rtnl_event(struct nl_msg *msg, void *arg);
89 static void handle_hotplug_event(struct uloop_fd *u, unsigned int events);
90 static int system_add_proto_tunnel(const char *name, const uint8_t proto,
91 const unsigned int link, struct blob_attr **tb);
92 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb);
94 static char dev_buf[256];
97 handler_nl_event(struct uloop_fd *u, unsigned int events)
99 struct event_socket *ev = container_of(u, struct event_socket, uloop);
101 socklen_t errlen = sizeof(err);
104 nl_recvmsgs_default(ev->sock);
108 if (getsockopt(u->fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen))
113 /* Increase rx buffer size on netlink socket */
115 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
118 /* Request full dump since some info got dropped */
119 struct rtgenmsg msg = { .rtgen_family = AF_UNSPEC };
120 nl_send_simple(ev->sock, RTM_GETLINK, NLM_F_DUMP, &msg, sizeof(msg));
130 uloop_fd_delete(&ev->uloop);
134 static struct nl_sock *
135 create_socket(int protocol, int groups)
137 struct nl_sock *sock;
139 sock = nl_socket_alloc();
144 nl_join_groups(sock, groups);
146 if (nl_connect(sock, protocol)) {
147 nl_socket_free(sock);
155 create_raw_event_socket(struct event_socket *ev, int protocol, int groups,
156 uloop_fd_handler cb, int flags)
158 ev->sock = create_socket(protocol, groups);
162 ev->uloop.fd = nl_socket_get_fd(ev->sock);
164 if (uloop_fd_add(&ev->uloop, ULOOP_READ|flags))
171 create_event_socket(struct event_socket *ev, int protocol,
172 int (*cb)(struct nl_msg *msg, void *arg))
174 if (!create_raw_event_socket(ev, protocol, 0, handler_nl_event, ULOOP_ERROR_CB))
177 /* Install the valid custom callback handler */
178 nl_socket_modify_cb(ev->sock, NL_CB_VALID, NL_CB_CUSTOM, cb, NULL);
180 /* Disable sequence number checking on event sockets */
181 nl_socket_disable_seq_check(ev->sock);
183 /* Increase rx buffer size to 65K on event sockets */
185 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
192 create_hotplug_event_socket(struct event_socket *ev, int protocol,
193 void (*cb)(struct uloop_fd *u, unsigned int events))
195 if (!create_raw_event_socket(ev, protocol, 1, cb, ULOOP_ERROR_CB))
198 /* Increase rx buffer size to 65K on event sockets */
200 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
207 system_rtn_aton(const char *src, unsigned int *dst)
212 if (!strcmp(src, "local"))
214 else if (!strcmp(src, "nat"))
216 else if (!strcmp(src, "broadcast"))
218 else if (!strcmp(src, "anycast"))
220 else if (!strcmp(src, "multicast"))
222 else if (!strcmp(src, "prohibit"))
224 else if (!strcmp(src, "unreachable"))
226 else if (!strcmp(src, "blackhole"))
228 else if (!strcmp(src, "xresolve"))
230 else if (!strcmp(src, "unicast"))
232 else if (!strcmp(src, "throw"))
234 else if (!strcmp(src, "failed_policy"))
235 n = RTN_FAILED_POLICY;
237 n = strtoul(src, &e, 0);
238 if (!e || *e || e == src || n > 255)
247 system_tos_aton(const char *src, unsigned *dst)
251 *dst = strtoul(src, &e, 16);
252 if (e == src || *e || *dst > 255)
258 int system_init(void)
260 static struct event_socket rtnl_event;
261 static struct event_socket hotplug_event;
263 sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0);
264 system_fd_set_cloexec(sock_ioctl);
266 /* Prepare socket for routing / address control */
267 sock_rtnl = create_socket(NETLINK_ROUTE, 0);
271 if (!create_event_socket(&rtnl_event, NETLINK_ROUTE, cb_rtnl_event))
274 if (!create_hotplug_event_socket(&hotplug_event, NETLINK_KOBJECT_UEVENT,
275 handle_hotplug_event))
278 /* Receive network link events form kernel */
279 nl_socket_add_membership(rtnl_event.sock, RTNLGRP_LINK);
284 static void system_set_sysctl(const char *path, const char *val)
288 fd = open(path, O_WRONLY);
292 if (write(fd, val, strlen(val))) {}
296 static void system_set_dev_sysctl(const char *path, const char *device, const char *val)
298 snprintf(dev_buf, sizeof(dev_buf), path, device);
299 system_set_sysctl(dev_buf, val);
302 static void system_set_disable_ipv6(struct device *dev, const char *val)
304 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val);
307 static void system_set_rpfilter(struct device *dev, const char *val)
309 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter", dev->ifname, val);
312 static void system_set_acceptlocal(struct device *dev, const char *val)
314 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local", dev->ifname, val);
317 static void system_set_igmpversion(struct device *dev, const char *val)
319 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version", dev->ifname, val);
322 static void system_set_mldversion(struct device *dev, const char *val)
324 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version", dev->ifname, val);
327 static void system_set_neigh4reachabletime(struct device *dev, const char *val)
329 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms", dev->ifname, val);
332 static void system_set_neigh6reachabletime(struct device *dev, const char *val)
334 system_set_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms", dev->ifname, val);
337 static void system_set_neigh4gcstaletime(struct device *dev, const char *val)
339 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/gc_stale_time", dev->ifname, val);
342 static void system_set_neigh6gcstaletime(struct device *dev, const char *val)
344 system_set_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/gc_stale_time", dev->ifname, val);
347 static void system_set_neigh4locktime(struct device *dev, const char *val)
349 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/locktime", dev->ifname, val);
352 static void system_set_dadtransmits(struct device *dev, const char *val)
354 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits", dev->ifname, val);
357 static void system_bridge_set_multicast_to_unicast(struct device *dev, const char *val)
359 system_set_dev_sysctl("/sys/class/net/%s/brport/multicast_to_unicast", dev->ifname, val);
362 static void system_bridge_set_multicast_fast_leave(struct device *dev, const char *val)
364 system_set_dev_sysctl("/sys/class/net/%s/brport/multicast_fast_leave", dev->ifname, val);
367 static void system_bridge_set_hairpin_mode(struct device *dev, const char *val)
369 system_set_dev_sysctl("/sys/class/net/%s/brport/hairpin_mode", dev->ifname, val);
372 static void system_bridge_set_isolated(struct device *dev, const char *val)
374 system_set_dev_sysctl("/sys/class/net/%s/brport/isolated", dev->ifname, val);
377 static void system_bridge_set_multicast_router(struct device *dev, const char *val, bool bridge)
379 system_set_dev_sysctl(bridge ? "/sys/class/net/%s/bridge/multicast_router" :
380 "/sys/class/net/%s/brport/multicast_router",
384 static void system_bridge_set_robustness(struct device *dev, const char *val)
386 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_startup_query_count",
388 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_last_member_count",
392 static void system_bridge_set_query_interval(struct device *dev, const char *val)
394 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_query_interval",
398 static void system_bridge_set_query_response_interval(struct device *dev, const char *val)
400 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_query_response_interval",
404 static void system_bridge_set_last_member_interval(struct device *dev, const char *val)
406 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_last_member_interval",
410 static void system_bridge_set_membership_interval(struct device *dev, const char *val)
412 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_membership_interval",
416 static void system_bridge_set_other_querier_timeout(struct device *dev, const char *val)
418 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier_interval",
422 static void system_bridge_set_startup_query_interval(struct device *dev, const char *val)
424 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_startup_query_interval",
428 static void system_bridge_set_stp_state(struct device *dev, const char *val)
430 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/stp_state", dev->ifname, val);
433 static void system_bridge_set_forward_delay(struct device *dev, const char *val)
435 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/forward_delay", dev->ifname, val);
438 static void system_bridge_set_priority(struct device *dev, const char *val)
440 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/priority", dev->ifname, val);
443 static void system_bridge_set_ageing_time(struct device *dev, const char *val)
445 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/ageing_time", dev->ifname, val);
448 static void system_bridge_set_hello_time(struct device *dev, const char *val)
450 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/hello_time", dev->ifname, val);
453 static void system_bridge_set_max_age(struct device *dev, const char *val)
455 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/max_age", dev->ifname, val);
458 static void system_bridge_set_learning(struct device *dev, const char *val)
460 system_set_dev_sysctl("/sys/class/net/%s/brport/learning", dev->ifname, val);
463 static void system_bridge_set_unicast_flood(struct device *dev, const char *val)
465 system_set_dev_sysctl("/sys/class/net/%s/brport/unicast_flood", dev->ifname, val);
468 static void system_set_sendredirects(struct device *dev, const char *val)
470 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/send_redirects", dev->ifname, val);
473 static int system_get_sysctl(const char *path, char *buf, const size_t buf_sz)
475 int fd = -1, ret = -1;
477 fd = open(path, O_RDONLY);
481 ssize_t len = read(fd, buf, buf_sz - 1);
495 system_get_dev_sysctl(const char *path, const char *device, char *buf, const size_t buf_sz)
497 snprintf(dev_buf, sizeof(dev_buf), path, device);
498 return system_get_sysctl(dev_buf, buf, buf_sz);
501 static int system_get_disable_ipv6(struct device *dev, char *buf, const size_t buf_sz)
503 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6",
504 dev->ifname, buf, buf_sz);
507 static int system_get_rpfilter(struct device *dev, char *buf, const size_t buf_sz)
509 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter",
510 dev->ifname, buf, buf_sz);
513 static int system_get_acceptlocal(struct device *dev, char *buf, const size_t buf_sz)
515 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local",
516 dev->ifname, buf, buf_sz);
519 static int system_get_igmpversion(struct device *dev, char *buf, const size_t buf_sz)
521 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version",
522 dev->ifname, buf, buf_sz);
525 static int system_get_mldversion(struct device *dev, char *buf, const size_t buf_sz)
527 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version",
528 dev->ifname, buf, buf_sz);
531 static int system_get_neigh4reachabletime(struct device *dev, char *buf, const size_t buf_sz)
533 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms",
534 dev->ifname, buf, buf_sz);
537 static int system_get_neigh6reachabletime(struct device *dev, char *buf, const size_t buf_sz)
539 return system_get_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms",
540 dev->ifname, buf, buf_sz);
543 static int system_get_neigh4gcstaletime(struct device *dev, char *buf, const size_t buf_sz)
545 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/gc_stale_time",
546 dev->ifname, buf, buf_sz);
549 static int system_get_neigh6gcstaletime(struct device *dev, char *buf, const size_t buf_sz)
551 return system_get_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/gc_stale_time",
552 dev->ifname, buf, buf_sz);
555 static int system_get_neigh4locktime(struct device *dev, char *buf, const size_t buf_sz)
557 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/locktime",
558 dev->ifname, buf, buf_sz);
561 static int system_get_dadtransmits(struct device *dev, char *buf, const size_t buf_sz)
563 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits",
564 dev->ifname, buf, buf_sz);
567 static int system_get_sendredirects(struct device *dev, char *buf, const size_t buf_sz)
569 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/send_redirects",
570 dev->ifname, buf, buf_sz);
573 /* Evaluate netlink messages */
574 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
576 struct nlmsghdr *nh = nlmsg_hdr(msg);
577 struct nlattr *nla[__IFLA_MAX];
581 if (nh->nlmsg_type != RTM_NEWLINK)
584 nlmsg_parse(nh, sizeof(struct ifinfomsg), nla, __IFLA_MAX - 1, NULL);
585 if (!nla[IFLA_IFNAME])
588 struct device *dev = device_find(nla_data(nla[IFLA_IFNAME]));
592 if (!system_get_dev_sysctl("/sys/class/net/%s/carrier", dev->ifname, buf, sizeof(buf)))
593 link_state = strtoul(buf, NULL, 0);
595 if (dev->type == &simple_device_type && !system_if_force_external(dev->ifname))
596 device_set_present(dev, true);
598 device_set_link(dev, link_state ? true : false);
605 handle_hotplug_msg(char *data, int size)
607 const char *subsystem = NULL, *interface = NULL, *interface_old = NULL;
608 char *cur, *end, *sep;
611 bool add, move = false;
613 if (!strncmp(data, "add@", 4))
615 else if (!strncmp(data, "remove@", 7))
617 else if (!strncmp(data, "move@", 5)) {
624 skip = strlen(data) + 1;
627 for (cur = data + skip; cur < end; cur += skip) {
628 skip = strlen(cur) + 1;
630 sep = strchr(cur, '=');
635 if (!strcmp(cur, "INTERFACE"))
637 else if (!strcmp(cur, "SUBSYSTEM")) {
639 if (strcmp(subsystem, "net") != 0)
641 } else if (!strcmp(cur, "DEVPATH_OLD")) {
642 interface_old = strrchr(sep + 1, '/');
648 if (subsystem && interface) {
649 if (move && interface_old)
658 dev = device_find(interface_old);
662 if (dev->type != &simple_device_type)
665 device_set_present(dev, false);
670 dev = device_find(interface);
674 if (dev->type != &simple_device_type)
677 if (add && system_if_force_external(dev->ifname))
680 device_set_present(dev, add);
684 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
686 struct event_socket *ev = container_of(u, struct event_socket, uloop);
687 struct sockaddr_nl nla;
688 unsigned char *buf = NULL;
691 socklen_t errlen = sizeof(err);
694 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
696 handle_hotplug_msg((char *) buf, size);
703 if (getsockopt(u->fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen))
708 /* Increase rx buffer size on netlink socket */
710 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
721 uloop_fd_delete(&ev->uloop);
725 static int system_rtnl_call(struct nl_msg *msg)
729 ret = nl_send_auto_complete(sock_rtnl, msg);
735 return nl_wait_for_ack(sock_rtnl);
738 int system_bridge_delbr(struct device *bridge)
740 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
743 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
747 memset(&ifr, 0, sizeof(ifr));
749 ifr.ifr_ifindex = dev->ifindex;
752 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name) - 1);
753 return ioctl(sock_ioctl, cmd, &ifr);
756 static bool system_is_bridge(const char *name, char *buf, int buflen)
760 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
761 if (stat(buf, &st) < 0)
767 static char *system_get_bridge(const char *name, char *buf, int buflen)
773 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
774 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
778 len = readlink(gl.gl_pathv[0], buf, buflen);
786 path = strrchr(buf, '/');
794 system_bridge_set_wireless(struct device *bridge, struct device *dev)
796 bool mcast_to_ucast = dev->wireless_ap;
799 if (bridge->settings.flags & DEV_OPT_MULTICAST_TO_UNICAST &&
800 !bridge->settings.multicast_to_unicast)
801 mcast_to_ucast = false;
803 if (!mcast_to_ucast || dev->wireless_isolate)
806 system_bridge_set_multicast_to_unicast(dev, mcast_to_ucast ? "1" : "0");
807 system_bridge_set_hairpin_mode(dev, hairpin ? "1" : "0");
810 int system_bridge_addif(struct device *bridge, struct device *dev)
816 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
817 if (!oldbr || strcmp(oldbr, bridge->ifname) != 0)
818 ret = system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
821 system_bridge_set_wireless(bridge, dev);
823 if (dev->settings.flags & DEV_OPT_MULTICAST_ROUTER) {
824 snprintf(buf, sizeof(buf), "%u", dev->settings.multicast_router);
825 system_bridge_set_multicast_router(dev, buf, false);
828 if (dev->settings.flags & DEV_OPT_MULTICAST_FAST_LEAVE &&
829 dev->settings.multicast_fast_leave)
830 system_bridge_set_multicast_fast_leave(dev, "1");
832 if (dev->settings.flags & DEV_OPT_LEARNING &&
833 !dev->settings.learning)
834 system_bridge_set_learning(dev, "0");
836 if (dev->settings.flags & DEV_OPT_UNICAST_FLOOD &&
837 !dev->settings.unicast_flood)
838 system_bridge_set_unicast_flood(dev, "0");
840 if (dev->settings.flags & DEV_OPT_ISOLATE &&
841 dev->settings.isolate)
842 system_bridge_set_isolated(dev, "1");
847 int system_bridge_delif(struct device *bridge, struct device *dev)
849 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
852 int system_if_resolve(struct device *dev)
855 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
856 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
857 return ifr.ifr_ifindex;
862 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
866 memset(&ifr, 0, sizeof(ifr));
867 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1);
868 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) < 0)
871 ifr.ifr_flags |= add;
872 ifr.ifr_flags &= ~rem;
873 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
885 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
887 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
889 return ifa->ifa_index == ifindex;
892 static bool check_route(struct nlmsghdr *hdr, int ifindex)
894 struct rtmsg *r = NLMSG_DATA(hdr);
895 struct nlattr *tb[__RTA_MAX];
897 if (r->rtm_protocol == RTPROT_KERNEL &&
898 r->rtm_family == AF_INET6)
901 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
905 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
908 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
913 static int cb_clear_event(struct nl_msg *msg, void *arg)
915 struct clear_data *clr = arg;
916 struct nlmsghdr *hdr = nlmsg_hdr(msg);
917 bool (*cb)(struct nlmsghdr *, int ifindex);
923 if (hdr->nlmsg_type != RTM_NEWADDR)
930 if (hdr->nlmsg_type != RTM_NEWROUTE)
937 if (hdr->nlmsg_type != RTM_NEWRULE)
946 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
949 if (type == RTM_DELRULE)
950 D(SYSTEM, "Remove a rule\n");
952 D(SYSTEM, "Remove %s from device %s\n",
953 type == RTM_DELADDR ? "an address" : "a route",
956 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
957 hdr = nlmsg_hdr(clr->msg);
958 hdr->nlmsg_type = type;
959 hdr->nlmsg_flags = NLM_F_REQUEST;
961 nl_socket_disable_auto_ack(sock_rtnl);
962 ret = nl_send_auto_complete(sock_rtnl, clr->msg);
964 if (type == RTM_DELRULE)
965 D(SYSTEM, "Error deleting a rule: %d\n", ret);
967 D(SYSTEM, "Error deleting %s from device '%s': %d\n",
968 type == RTM_DELADDR ? "an address" : "a route",
969 clr->dev->ifname, ret);
972 nl_socket_enable_auto_ack(sock_rtnl);
978 cb_finish_event(struct nl_msg *msg, void *arg)
986 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
989 *pending = err->error;
994 system_if_clear_entries(struct device *dev, int type, int af)
996 struct clear_data clr;
1000 .rtm_flags = RTM_F_CLONED,
1002 int flags = NLM_F_DUMP;
1011 clr.size = sizeof(struct rtgenmsg);
1014 clr.size = sizeof(struct rtmsg);
1020 cb = nl_cb_alloc(NL_CB_DEFAULT);
1024 clr.msg = nlmsg_alloc_simple(type, flags);
1028 nlmsg_append(clr.msg, &rtm, clr.size, 0);
1029 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
1030 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
1031 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
1033 if (nl_send_auto_complete(sock_rtnl, clr.msg) < 0)
1037 nl_recvmsgs(sock_rtnl, cb);
1040 nlmsg_free(clr.msg);
1046 * Clear bridge (membership) state and bring down device
1048 void system_if_clear_state(struct device *dev)
1050 static char buf[256];
1052 device_set_ifindex(dev, system_if_resolve(dev));
1054 if (dev->external || !dev->ifindex)
1057 system_if_flags(dev->ifname, 0, IFF_UP);
1059 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
1060 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
1061 system_bridge_delbr(dev);
1065 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
1067 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
1068 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
1071 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
1072 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
1073 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
1074 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
1075 system_if_clear_entries(dev, RTM_GETNEIGH, AF_INET);
1076 system_if_clear_entries(dev, RTM_GETNEIGH, AF_INET6);
1077 system_set_disable_ipv6(dev, "0");
1080 static inline unsigned long
1081 sec_to_jiffies(int val)
1083 return (unsigned long) val * 100;
1086 static void system_bridge_conf_multicast_deps(struct device *bridge,
1087 struct bridge_config *cfg,
1093 if (cfg->flags & BRIDGE_OPT_ROBUSTNESS ||
1094 cfg->flags & BRIDGE_OPT_QUERY_INTERVAL ||
1095 cfg->flags & BRIDGE_OPT_QUERY_RESPONSE_INTERVAL) {
1096 val = cfg->robustness * cfg->query_interval +
1097 cfg->query_response_interval;
1099 snprintf(buf, buf_len, "%i", val);
1100 system_bridge_set_membership_interval(bridge, buf);
1102 val = cfg->robustness * cfg->query_interval +
1103 cfg->query_response_interval / 2;
1105 snprintf(buf, buf_len, "%i", val);
1106 system_bridge_set_other_querier_timeout(bridge, buf);
1109 if (cfg->flags & BRIDGE_OPT_QUERY_INTERVAL) {
1110 val = cfg->query_interval / 4;
1112 snprintf(buf, buf_len, "%i", val);
1113 system_bridge_set_startup_query_interval(bridge, buf);
1117 static void system_bridge_conf_multicast(struct device *bridge,
1118 struct bridge_config *cfg,
1122 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
1123 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
1125 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier",
1126 bridge->ifname, cfg->multicast_querier ? "1" : "0");
1128 snprintf(buf, buf_len, "%i", cfg->hash_max);
1129 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/hash_max",
1130 bridge->ifname, buf);
1132 if (bridge->settings.flags & DEV_OPT_MULTICAST_ROUTER) {
1133 snprintf(buf, buf_len, "%u", bridge->settings.multicast_router);
1134 system_bridge_set_multicast_router(bridge, buf, true);
1137 if (cfg->flags & BRIDGE_OPT_ROBUSTNESS) {
1138 snprintf(buf, buf_len, "%i", cfg->robustness);
1139 system_bridge_set_robustness(bridge, buf);
1142 if (cfg->flags & BRIDGE_OPT_QUERY_INTERVAL) {
1143 snprintf(buf, buf_len, "%i", cfg->query_interval);
1144 system_bridge_set_query_interval(bridge, buf);
1147 if (cfg->flags & BRIDGE_OPT_QUERY_RESPONSE_INTERVAL) {
1148 snprintf(buf, buf_len, "%i", cfg->query_response_interval);
1149 system_bridge_set_query_response_interval(bridge, buf);
1152 if (cfg->flags & BRIDGE_OPT_LAST_MEMBER_INTERVAL) {
1153 snprintf(buf, buf_len, "%i", cfg->last_member_interval);
1154 system_bridge_set_last_member_interval(bridge, buf);
1157 system_bridge_conf_multicast_deps(bridge, cfg, buf, buf_len);
1160 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
1164 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
1167 system_bridge_set_stp_state(bridge, cfg->stp ? "1" : "0");
1169 snprintf(buf, sizeof(buf), "%lu", sec_to_jiffies(cfg->forward_delay));
1170 system_bridge_set_forward_delay(bridge, buf);
1172 system_bridge_conf_multicast(bridge, cfg, buf, sizeof(buf));
1174 snprintf(buf, sizeof(buf), "%d", cfg->priority);
1175 system_bridge_set_priority(bridge, buf);
1177 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
1178 snprintf(buf, sizeof(buf), "%lu", sec_to_jiffies(cfg->ageing_time));
1179 system_bridge_set_ageing_time(bridge, buf);
1182 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
1183 snprintf(buf, sizeof(buf), "%lu", sec_to_jiffies(cfg->hello_time));
1184 system_bridge_set_hello_time(bridge, buf);
1187 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
1188 snprintf(buf, sizeof(buf), "%lu", sec_to_jiffies(cfg->max_age));
1189 system_bridge_set_max_age(bridge, buf);
1195 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
1198 struct nlattr *linkinfo, *data;
1199 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
1201 static const struct {
1203 enum macvlan_mode val;
1205 { "private", MACVLAN_MODE_PRIVATE },
1206 { "vepa", MACVLAN_MODE_VEPA },
1207 { "bridge", MACVLAN_MODE_BRIDGE },
1208 { "passthru", MACVLAN_MODE_PASSTHRU },
1211 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1216 nlmsg_append(msg, &iim, sizeof(iim), 0);
1218 if (cfg->flags & MACVLAN_OPT_MACADDR)
1219 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
1220 nla_put_string(msg, IFLA_IFNAME, macvlan->ifname);
1221 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
1223 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1224 goto nla_put_failure;
1226 nla_put_string(msg, IFLA_INFO_KIND, "macvlan");
1228 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1229 goto nla_put_failure;
1232 for (i = 0; i < ARRAY_SIZE(modes); i++) {
1233 if (strcmp(cfg->mode, modes[i].name) != 0)
1236 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
1241 nla_nest_end(msg, data);
1242 nla_nest_end(msg, linkinfo);
1244 rv = system_rtnl_call(msg);
1246 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
1255 int system_link_netns_move(struct device *dev, int netns_fd, const char *target_ifname)
1258 struct ifinfomsg iim = {
1259 .ifi_family = AF_UNSPEC,
1265 iim.ifi_index = system_if_resolve(dev);
1266 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST);
1271 nlmsg_append(msg, &iim, sizeof(iim), 0);
1273 nla_put_string(msg, IFLA_IFNAME, target_ifname);
1275 nla_put_u32(msg, IFLA_NET_NS_FD, netns_fd);
1276 return system_rtnl_call(msg);
1279 static int system_link_del(const char *ifname)
1282 struct ifinfomsg iim = {
1283 .ifi_family = AF_UNSPEC,
1287 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
1292 nlmsg_append(msg, &iim, sizeof(iim), 0);
1293 nla_put_string(msg, IFLA_IFNAME, ifname);
1294 return system_rtnl_call(msg);
1297 int system_macvlan_del(struct device *macvlan)
1299 return system_link_del(macvlan->ifname);
1302 int system_netns_open(const pid_t target_ns)
1304 char pid_net_path[PATH_MAX];
1306 snprintf(pid_net_path, sizeof(pid_net_path), "/proc/%u/ns/net", target_ns);
1308 return open(pid_net_path, O_RDONLY);
1311 int system_netns_set(int netns_fd)
1313 return setns(netns_fd, CLONE_NEWNET);
1316 int system_veth_add(struct device *veth, struct veth_config *cfg)
1319 struct ifinfomsg empty_iim = {};
1320 struct nlattr *linkinfo, *data, *veth_info;
1323 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1328 nlmsg_append(msg, &empty_iim, sizeof(empty_iim), 0);
1330 if (cfg->flags & VETH_OPT_MACADDR)
1331 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
1332 nla_put_string(msg, IFLA_IFNAME, veth->ifname);
1334 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1335 goto nla_put_failure;
1337 nla_put_string(msg, IFLA_INFO_KIND, "veth");
1339 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1340 goto nla_put_failure;
1342 if (!(veth_info = nla_nest_start(msg, VETH_INFO_PEER)))
1343 goto nla_put_failure;
1345 nlmsg_append(msg, &empty_iim, sizeof(empty_iim), 0);
1347 if (cfg->flags & VETH_OPT_PEER_NAME)
1348 nla_put_string(msg, IFLA_IFNAME, cfg->peer_name);
1349 if (cfg->flags & VETH_OPT_PEER_MACADDR)
1350 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->peer_macaddr), cfg->peer_macaddr);
1352 nla_nest_end(msg, veth_info);
1353 nla_nest_end(msg, data);
1354 nla_nest_end(msg, linkinfo);
1356 rv = system_rtnl_call(msg);
1358 if (cfg->flags & VETH_OPT_PEER_NAME)
1359 D(SYSTEM, "Error adding veth '%s' with peer '%s': %d\n", veth->ifname, cfg->peer_name, rv);
1361 D(SYSTEM, "Error adding veth '%s': %d\n", veth->ifname, rv);
1371 int system_veth_del(struct device *veth)
1373 return system_link_del(veth->ifname);
1376 static int system_vlan(struct device *dev, int id)
1378 struct vlan_ioctl_args ifr = {
1379 .cmd = SET_VLAN_NAME_TYPE_CMD,
1380 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
1383 if (ioctl(sock_ioctl, SIOCSIFVLAN, &ifr) < 0)
1387 ifr.cmd = DEL_VLAN_CMD;
1390 ifr.cmd = ADD_VLAN_CMD;
1393 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
1394 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
1397 int system_vlan_add(struct device *dev, int id)
1399 return system_vlan(dev, id);
1402 int system_vlan_del(struct device *dev)
1404 return system_vlan(dev, -1);
1407 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
1410 struct nlattr *linkinfo, *data, *qos;
1411 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
1412 struct vlan_qos_mapping *elem;
1413 struct ifla_vlan_qos_mapping nl_qos_map;
1416 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1421 nlmsg_append(msg, &iim, sizeof(iim), 0);
1422 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
1423 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
1425 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1426 goto nla_put_failure;
1428 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
1430 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1431 goto nla_put_failure;
1433 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
1435 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
1436 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
1438 if(cfg->proto == VLAN_PROTO_8021AD)
1439 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);
1442 if (!(qos = nla_nest_start(msg, IFLA_VLAN_INGRESS_QOS)))
1443 goto nla_put_failure;
1445 vlist_simple_for_each_element(&cfg->ingress_qos_mapping_list, elem, node) {
1446 nl_qos_map.from = elem->from;
1447 nl_qos_map.to = elem->to;
1448 nla_put(msg, IFLA_VLAN_QOS_MAPPING, sizeof(nl_qos_map), &nl_qos_map);
1450 nla_nest_end(msg, qos);
1452 if (!(qos = nla_nest_start(msg, IFLA_VLAN_EGRESS_QOS)))
1453 goto nla_put_failure;
1455 vlist_simple_for_each_element(&cfg->egress_qos_mapping_list, elem, node) {
1456 nl_qos_map.from = elem->from;
1457 nl_qos_map.to = elem->to;
1458 nla_put(msg, IFLA_VLAN_QOS_MAPPING, sizeof(nl_qos_map), &nl_qos_map);
1460 nla_nest_end(msg, qos);
1462 nla_nest_end(msg, data);
1463 nla_nest_end(msg, linkinfo);
1465 rv = system_rtnl_call(msg);
1467 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
1476 int system_vlandev_del(struct device *vlandev)
1478 return system_link_del(vlandev->ifname);
1482 system_if_get_settings(struct device *dev, struct device_settings *s)
1487 memset(&ifr, 0, sizeof(ifr));
1488 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
1490 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
1491 s->mtu = ifr.ifr_mtu;
1492 s->flags |= DEV_OPT_MTU;
1495 s->mtu6 = system_update_ipv6_mtu(dev, 0);
1497 s->flags |= DEV_OPT_MTU6;
1499 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
1500 s->txqueuelen = ifr.ifr_qlen;
1501 s->flags |= DEV_OPT_TXQUEUELEN;
1504 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
1505 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
1506 s->flags |= DEV_OPT_MACADDR;
1509 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
1510 s->ipv6 = !strtoul(buf, NULL, 0);
1511 s->flags |= DEV_OPT_IPV6;
1514 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
1515 s->promisc = ifr.ifr_flags & IFF_PROMISC;
1516 s->flags |= DEV_OPT_PROMISC;
1518 s->multicast = ifr.ifr_flags & IFF_MULTICAST;
1519 s->flags |= DEV_OPT_MULTICAST;
1522 if (!system_get_rpfilter(dev, buf, sizeof(buf))) {
1523 s->rpfilter = strtoul(buf, NULL, 0);
1524 s->flags |= DEV_OPT_RPFILTER;
1527 if (!system_get_acceptlocal(dev, buf, sizeof(buf))) {
1528 s->acceptlocal = strtoul(buf, NULL, 0);
1529 s->flags |= DEV_OPT_ACCEPTLOCAL;
1532 if (!system_get_igmpversion(dev, buf, sizeof(buf))) {
1533 s->igmpversion = strtoul(buf, NULL, 0);
1534 s->flags |= DEV_OPT_IGMPVERSION;
1537 if (!system_get_mldversion(dev, buf, sizeof(buf))) {
1538 s->mldversion = strtoul(buf, NULL, 0);
1539 s->flags |= DEV_OPT_MLDVERSION;
1542 if (!system_get_neigh4reachabletime(dev, buf, sizeof(buf))) {
1543 s->neigh4reachabletime = strtoul(buf, NULL, 0);
1544 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1547 if (!system_get_neigh6reachabletime(dev, buf, sizeof(buf))) {
1548 s->neigh6reachabletime = strtoul(buf, NULL, 0);
1549 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1552 if (!system_get_neigh4locktime(dev, buf, sizeof(buf))) {
1553 s->neigh4locktime = strtol(buf, NULL, 0);
1554 s->flags |= DEV_OPT_NEIGHLOCKTIME;
1557 if (!system_get_neigh4gcstaletime(dev, buf, sizeof(buf))) {
1558 s->neigh4gcstaletime = strtoul(buf, NULL, 0);
1559 s->flags |= DEV_OPT_NEIGHGCSTALETIME;
1562 if (!system_get_neigh6gcstaletime(dev, buf, sizeof(buf))) {
1563 s->neigh6gcstaletime = strtoul(buf, NULL, 0);
1564 s->flags |= DEV_OPT_NEIGHGCSTALETIME;
1567 if (!system_get_dadtransmits(dev, buf, sizeof(buf))) {
1568 s->dadtransmits = strtoul(buf, NULL, 0);
1569 s->flags |= DEV_OPT_DADTRANSMITS;
1572 if (!system_get_sendredirects(dev, buf, sizeof(buf))) {
1573 s->sendredirects = strtoul(buf, NULL, 0);
1574 s->flags |= DEV_OPT_SENDREDIRECTS;
1579 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
1584 memset(&ifr, 0, sizeof(ifr));
1585 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
1586 if (s->flags & DEV_OPT_MTU & apply_mask) {
1587 ifr.ifr_mtu = s->mtu;
1588 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
1589 s->flags &= ~DEV_OPT_MTU;
1591 if (s->flags & DEV_OPT_MTU6 & apply_mask) {
1592 system_update_ipv6_mtu(dev, s->mtu6);
1594 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
1595 ifr.ifr_qlen = s->txqueuelen;
1596 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
1597 s->flags &= ~DEV_OPT_TXQUEUELEN;
1599 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
1600 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
1601 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
1602 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
1603 s->flags &= ~DEV_OPT_MACADDR;
1605 if (s->flags & DEV_OPT_IPV6 & apply_mask)
1606 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
1607 if (s->flags & DEV_OPT_PROMISC & apply_mask) {
1608 if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
1609 !s->promisc ? IFF_PROMISC : 0) < 0)
1610 s->flags &= ~DEV_OPT_PROMISC;
1612 if (s->flags & DEV_OPT_RPFILTER & apply_mask) {
1613 snprintf(buf, sizeof(buf), "%u", s->rpfilter);
1614 system_set_rpfilter(dev, buf);
1616 if (s->flags & DEV_OPT_ACCEPTLOCAL & apply_mask)
1617 system_set_acceptlocal(dev, s->acceptlocal ? "1" : "0");
1618 if (s->flags & DEV_OPT_IGMPVERSION & apply_mask) {
1619 snprintf(buf, sizeof(buf), "%u", s->igmpversion);
1620 system_set_igmpversion(dev, buf);
1622 if (s->flags & DEV_OPT_MLDVERSION & apply_mask) {
1623 snprintf(buf, sizeof(buf), "%u", s->mldversion);
1624 system_set_mldversion(dev, buf);
1626 if (s->flags & DEV_OPT_NEIGHREACHABLETIME & apply_mask) {
1627 snprintf(buf, sizeof(buf), "%u", s->neigh4reachabletime);
1628 system_set_neigh4reachabletime(dev, buf);
1629 snprintf(buf, sizeof(buf), "%u", s->neigh6reachabletime);
1630 system_set_neigh6reachabletime(dev, buf);
1632 if (s->flags & DEV_OPT_NEIGHLOCKTIME & apply_mask) {
1633 snprintf(buf, sizeof(buf), "%d", s->neigh4locktime);
1634 system_set_neigh4locktime(dev, buf);
1636 if (s->flags & DEV_OPT_NEIGHGCSTALETIME & apply_mask) {
1637 snprintf(buf, sizeof(buf), "%u", s->neigh4gcstaletime);
1638 system_set_neigh4gcstaletime(dev, buf);
1639 snprintf(buf, sizeof(buf), "%u", s->neigh6gcstaletime);
1640 system_set_neigh6gcstaletime(dev, buf);
1642 if (s->flags & DEV_OPT_DADTRANSMITS & apply_mask) {
1643 snprintf(buf, sizeof(buf), "%u", s->dadtransmits);
1644 system_set_dadtransmits(dev, buf);
1646 if (s->flags & DEV_OPT_MULTICAST & apply_mask) {
1647 if (system_if_flags(dev->ifname, s->multicast ? IFF_MULTICAST : 0,
1648 !s->multicast ? IFF_MULTICAST : 0) < 0)
1649 s->flags &= ~DEV_OPT_MULTICAST;
1651 if (s->flags & DEV_OPT_SENDREDIRECTS & apply_mask)
1652 system_set_sendredirects(dev, s->sendredirects ? "1" : "0");
1655 int system_if_up(struct device *dev)
1657 system_if_get_settings(dev, &dev->orig_settings);
1658 /* Only keep orig settings based on what needs to be set */
1659 dev->orig_settings.valid_flags = dev->orig_settings.flags;
1660 dev->orig_settings.flags &= dev->settings.flags;
1661 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
1662 return system_if_flags(dev->ifname, IFF_UP, 0);
1665 int system_if_down(struct device *dev)
1667 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
1668 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
1672 struct if_check_data {
1678 #ifndef IFF_LOWER_UP
1679 #define IFF_LOWER_UP 0x10000
1682 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1684 struct nlmsghdr *nh = nlmsg_hdr(msg);
1685 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1686 struct if_check_data *chk = (struct if_check_data *)arg;
1688 if (nh->nlmsg_type != RTM_NEWLINK)
1691 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1692 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1697 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1699 struct if_check_data *chk = (struct if_check_data *)arg;
1704 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1706 struct if_check_data *chk = (struct if_check_data *)arg;
1708 device_set_present(chk->dev, false);
1709 device_set_link(chk->dev, false);
1710 chk->pending = err->error;
1715 int system_if_check(struct device *dev)
1717 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1719 struct ifinfomsg ifi = {
1720 .ifi_family = AF_UNSPEC,
1723 struct if_check_data chk = {
1732 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1736 if (nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1737 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1740 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1741 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1742 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1744 ret = nl_send_auto_complete(sock_rtnl, msg);
1748 while (chk.pending > 0)
1749 nl_recvmsgs(sock_rtnl, cb);
1761 system_if_get_parent(struct device *dev)
1763 char buf[64], *devname;
1764 int ifindex, iflink, len;
1767 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1768 f = fopen(buf, "r");
1772 len = fread(buf, 1, sizeof(buf) - 1, f);
1779 iflink = strtoul(buf, NULL, 0);
1780 ifindex = system_if_resolve(dev);
1781 if (!iflink || iflink == ifindex)
1784 devname = if_indextoname(iflink, buf);
1788 return device_get(devname, true);
1792 read_string_file(int dir_fd, const char *file, char *buf, int len)
1798 fd = openat(dir_fd, file, O_RDONLY);
1803 len = read(fd, buf, len - 1);
1807 } else if (len > 0) {
1810 c = strchr(buf, '\n');
1823 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1828 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1830 *val = strtoull(buf, NULL, 0);
1835 /* Assume advertised flags == supported flags */
1836 static const struct {
1839 } ethtool_link_modes[] = {
1840 { ADVERTISED_10baseT_Half, "10baseT-H" },
1841 { ADVERTISED_10baseT_Full, "10baseT-F" },
1842 { ADVERTISED_100baseT_Half, "100baseT-H" },
1843 { ADVERTISED_100baseT_Full, "100baseT-F" },
1844 { ADVERTISED_1000baseT_Half, "1000baseT-H" },
1845 { ADVERTISED_1000baseT_Full, "1000baseT-F" },
1846 { ADVERTISED_1000baseKX_Full, "1000baseKX-F" },
1847 { ADVERTISED_2500baseX_Full, "2500baseX-F" },
1848 { ADVERTISED_10000baseT_Full, "10000baseT-F" },
1849 { ADVERTISED_10000baseKX4_Full, "10000baseKX4-F" },
1850 { ADVERTISED_10000baseKR_Full, "10000baseKR-F" },
1851 { ADVERTISED_20000baseMLD2_Full, "20000baseMLD2-F" },
1852 { ADVERTISED_20000baseKR2_Full, "20000baseKR2-F" },
1853 { ADVERTISED_40000baseKR4_Full, "40000baseKR4-F" },
1854 { ADVERTISED_40000baseCR4_Full, "40000baseCR4-F" },
1855 { ADVERTISED_40000baseSR4_Full, "40000baseSR4-F" },
1856 { ADVERTISED_40000baseLR4_Full, "40000baseLR4-F" },
1857 #ifdef ADVERTISED_56000baseKR4_Full
1858 { ADVERTISED_56000baseKR4_Full, "56000baseKR4-F" },
1859 { ADVERTISED_56000baseCR4_Full, "56000baseCR4-F" },
1860 { ADVERTISED_56000baseSR4_Full, "56000baseSR4-F" },
1861 { ADVERTISED_56000baseLR4_Full, "56000baseLR4-F" },
1865 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1868 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1869 if (mask & ethtool_link_modes[i].mask)
1870 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1875 system_if_force_external(const char *ifname)
1880 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1881 return stat(buf, &s) == 0;
1885 system_if_dump_info(struct device *dev, struct blob_buf *b)
1887 struct ethtool_cmd ecmd;
1892 memset(&ecmd, 0, sizeof(ecmd));
1893 memset(&ifr, 0, sizeof(ifr));
1894 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
1895 ifr.ifr_data = (caddr_t) &ecmd;
1896 ecmd.cmd = ETHTOOL_GSET;
1898 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1899 c = blobmsg_open_array(b, "link-advertising");
1900 system_add_link_modes(b, ecmd.advertising);
1901 blobmsg_close_array(b, c);
1903 c = blobmsg_open_array(b, "link-partner-advertising");
1904 system_add_link_modes(b, ecmd.lp_advertising);
1905 blobmsg_close_array(b, c);
1907 c = blobmsg_open_array(b, "link-supported");
1908 system_add_link_modes(b, ecmd.supported);
1909 blobmsg_close_array(b, c);
1911 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1912 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1913 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1914 blobmsg_add_string_buffer(b);
1916 blobmsg_add_u8(b, "autoneg", !!ecmd.autoneg);
1923 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1925 const char *const counters[] = {
1926 "collisions", "rx_frame_errors", "tx_compressed",
1927 "multicast", "rx_length_errors", "tx_dropped",
1928 "rx_bytes", "rx_missed_errors", "tx_errors",
1929 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1930 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1931 "rx_dropped", "tx_aborted_errors", "tx_packets",
1932 "rx_errors", "tx_bytes", "tx_window_errors",
1933 "rx_fifo_errors", "tx_carrier_errors",
1940 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1941 stats_dir = open(buf, O_DIRECTORY);
1945 for (i = 0; i < ARRAY_SIZE(counters); i++)
1946 if (read_uint64_file(stats_dir, counters[i], &val))
1947 blobmsg_add_u64(b, counters[i], val);
1953 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1955 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1956 int alen = v4 ? 4 : 16;
1957 unsigned int flags = 0;
1958 struct ifaddrmsg ifa = {
1959 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1960 .ifa_prefixlen = addr->mask,
1961 .ifa_index = dev->ifindex,
1965 if (cmd == RTM_NEWADDR)
1966 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1968 msg = nlmsg_alloc_simple(cmd, flags);
1972 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1973 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1975 if (addr->broadcast)
1976 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1977 if (addr->point_to_point)
1978 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1980 time_t now = system_get_rtime();
1981 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1983 if (addr->preferred_until) {
1984 int64_t preferred = addr->preferred_until - now;
1987 else if (preferred > UINT32_MAX)
1988 preferred = UINT32_MAX;
1990 cinfo.ifa_prefered = preferred;
1993 if (addr->valid_until) {
1994 int64_t valid = addr->valid_until - now;
1999 else if (valid > UINT32_MAX)
2002 cinfo.ifa_valid = valid;
2005 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
2007 if (cmd == RTM_NEWADDR && (addr->flags & DEVADDR_OFFLINK))
2008 nla_put_u32(msg, IFA_FLAGS, IFA_F_NOPREFIXROUTE);
2011 return system_rtnl_call(msg);
2014 int system_add_address(struct device *dev, struct device_addr *addr)
2016 return system_addr(dev, addr, RTM_NEWADDR);
2019 int system_del_address(struct device *dev, struct device_addr *addr)
2021 return system_addr(dev, addr, RTM_DELADDR);
2024 static int system_neigh(struct device *dev, struct device_neighbor *neighbor, int cmd)
2026 int alen = ((neighbor->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
2027 unsigned int flags = 0;
2028 struct ndmsg ndm = {
2029 .ndm_family = (alen == 4) ? AF_INET : AF_INET6,
2030 .ndm_ifindex = dev->ifindex,
2031 .ndm_state = NUD_PERMANENT,
2032 .ndm_flags = (neighbor->proxy ? NTF_PROXY : 0) | (neighbor->router ? NTF_ROUTER : 0),
2036 if (cmd == RTM_NEWNEIGH)
2037 flags |= NLM_F_CREATE | NLM_F_REPLACE;
2039 msg = nlmsg_alloc_simple(cmd, flags);
2044 nlmsg_append(msg, &ndm, sizeof(ndm), 0);
2046 nla_put(msg, NDA_DST, alen, &neighbor->addr);
2047 if (neighbor->flags & DEVNEIGH_MAC)
2048 nla_put(msg, NDA_LLADDR, sizeof(neighbor->macaddr), &neighbor->macaddr);
2051 return system_rtnl_call(msg);
2054 int system_add_neighbor(struct device *dev, struct device_neighbor *neighbor)
2056 return system_neigh(dev, neighbor, RTM_NEWNEIGH);
2059 int system_del_neighbor(struct device *dev, struct device_neighbor *neighbor)
2061 return system_neigh(dev, neighbor, RTM_DELNEIGH);
2064 static int system_rt(struct device *dev, struct device_route *route, int cmd)
2066 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
2068 unsigned int flags = 0;
2071 have_gw = !!route->nexthop.in.s_addr;
2073 have_gw = route->nexthop.in6.s6_addr32[0] ||
2074 route->nexthop.in6.s6_addr32[1] ||
2075 route->nexthop.in6.s6_addr32[2] ||
2076 route->nexthop.in6.s6_addr32[3];
2078 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
2079 ? route->table : RT_TABLE_MAIN;
2081 struct rtmsg rtm = {
2082 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
2083 .rtm_dst_len = route->mask,
2084 .rtm_src_len = route->sourcemask,
2085 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
2086 .rtm_protocol = (route->flags & DEVROUTE_PROTO) ? route->proto : RTPROT_STATIC,
2087 .rtm_scope = RT_SCOPE_NOWHERE,
2088 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
2089 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
2093 if (cmd == RTM_NEWROUTE) {
2094 flags |= NLM_F_CREATE | NLM_F_REPLACE;
2096 if (!dev) { /* Add null-route */
2097 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
2098 rtm.rtm_type = RTN_UNREACHABLE;
2101 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
2104 if (route->flags & DEVROUTE_TYPE) {
2105 rtm.rtm_type = route->type;
2106 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
2107 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
2108 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
2109 rtm.rtm_table = RT_TABLE_LOCAL;
2112 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT) {
2113 rtm.rtm_scope = RT_SCOPE_HOST;
2114 } else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
2115 rtm.rtm_type == RTN_ANYCAST) {
2116 rtm.rtm_scope = RT_SCOPE_LINK;
2117 } else if (rtm.rtm_type == RTN_BLACKHOLE || rtm.rtm_type == RTN_UNREACHABLE ||
2118 rtm.rtm_type == RTN_PROHIBIT || rtm.rtm_type == RTN_FAILED_POLICY ||
2119 rtm.rtm_type == RTN_THROW) {
2120 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
2125 msg = nlmsg_alloc_simple(cmd, flags);
2129 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
2132 nla_put(msg, RTA_DST, alen, &route->addr);
2134 if (route->sourcemask) {
2135 if (rtm.rtm_family == AF_INET)
2136 nla_put(msg, RTA_PREFSRC, alen, &route->source);
2138 nla_put(msg, RTA_SRC, alen, &route->source);
2141 if (route->metric > 0)
2142 nla_put_u32(msg, RTA_PRIORITY, route->metric);
2145 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
2148 nla_put_u32(msg, RTA_OIF, dev->ifindex);
2151 nla_put_u32(msg, RTA_TABLE, table);
2153 if (route->flags & DEVROUTE_MTU) {
2154 struct nlattr *metrics;
2156 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
2157 goto nla_put_failure;
2159 nla_put_u32(msg, RTAX_MTU, route->mtu);
2161 nla_nest_end(msg, metrics);
2164 return system_rtnl_call(msg);
2171 int system_add_route(struct device *dev, struct device_route *route)
2173 return system_rt(dev, route, RTM_NEWROUTE);
2176 int system_del_route(struct device *dev, struct device_route *route)
2178 return system_rt(dev, route, RTM_DELROUTE);
2181 int system_flush_routes(void)
2183 const char *names[] = {
2184 "/proc/sys/net/ipv4/route/flush",
2185 "/proc/sys/net/ipv6/route/flush"
2189 for (i = 0; i < ARRAY_SIZE(names); i++) {
2190 fd = open(names[i], O_WRONLY);
2194 if (write(fd, "-1", 2)) {}
2200 bool system_resolve_rt_type(const char *type, unsigned int *id)
2202 return system_rtn_aton(type, id);
2205 bool system_resolve_rt_proto(const char *type, unsigned int *id)
2209 unsigned int n, proto = 256;
2210 n = strtoul(type, &e, 0);
2211 if (!*e && e != type)
2213 else if (!strcmp(type, "unspec"))
2214 proto = RTPROT_UNSPEC;
2215 else if (!strcmp(type, "kernel"))
2216 proto = RTPROT_KERNEL;
2217 else if (!strcmp(type, "boot"))
2218 proto = RTPROT_BOOT;
2219 else if (!strcmp(type, "static"))
2220 proto = RTPROT_STATIC;
2221 else if ((f = fopen("/etc/iproute2/rt_protos", "r")) != NULL) {
2222 while (fgets(buf, sizeof(buf) - 1, f) != NULL) {
2223 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
2226 n = strtoul(e, NULL, 10);
2227 e = strtok(NULL, " \t\n");
2229 if (e && !strcmp(e, type)) {
2244 bool system_resolve_rt_table(const char *name, unsigned int *id)
2248 unsigned int n, table = RT_TABLE_UNSPEC;
2250 /* first try to parse table as number */
2251 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
2254 /* handle well known aliases */
2255 else if (!strcmp(name, "default"))
2256 table = RT_TABLE_DEFAULT;
2257 else if (!strcmp(name, "main"))
2258 table = RT_TABLE_MAIN;
2259 else if (!strcmp(name, "local"))
2260 table = RT_TABLE_LOCAL;
2262 /* try to look up name in /etc/iproute2/rt_tables */
2263 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
2265 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
2267 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
2270 n = strtoul(e, NULL, 10);
2271 e = strtok(NULL, " \t\n");
2273 if (e && !strcmp(e, name))
2283 if (table == RT_TABLE_UNSPEC)
2290 bool system_is_default_rt_table(unsigned int id)
2292 return (id == RT_TABLE_MAIN);
2295 bool system_resolve_rpfilter(const char *filter, unsigned int *id)
2300 if (!strcmp(filter, "strict"))
2302 else if (!strcmp(filter, "loose"))
2305 n = strtoul(filter, &e, 0);
2306 if (*e || e == filter || n > 2)
2314 static int system_iprule(struct iprule *rule, int cmd)
2316 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
2319 struct rtmsg rtm = {
2320 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
2321 .rtm_protocol = RTPROT_STATIC,
2322 .rtm_scope = RT_SCOPE_UNIVERSE,
2323 .rtm_table = RT_TABLE_UNSPEC,
2324 .rtm_type = RTN_UNSPEC,
2328 if (cmd == RTM_NEWRULE)
2329 rtm.rtm_type = RTN_UNICAST;
2332 rtm.rtm_flags |= FIB_RULE_INVERT;
2334 if (rule->flags & IPRULE_SRC)
2335 rtm.rtm_src_len = rule->src_mask;
2337 if (rule->flags & IPRULE_DEST)
2338 rtm.rtm_dst_len = rule->dest_mask;
2340 if (rule->flags & IPRULE_TOS)
2341 rtm.rtm_tos = rule->tos;
2343 if (rule->flags & IPRULE_LOOKUP) {
2344 if (rule->lookup < 256)
2345 rtm.rtm_table = rule->lookup;
2348 if (rule->flags & IPRULE_ACTION)
2349 rtm.rtm_type = rule->action;
2350 else if (rule->flags & IPRULE_GOTO)
2351 rtm.rtm_type = FR_ACT_GOTO;
2352 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
2353 rtm.rtm_type = FR_ACT_NOP;
2355 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
2360 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
2362 if (rule->flags & IPRULE_IN)
2363 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
2365 if (rule->flags & IPRULE_OUT)
2366 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
2368 if (rule->flags & IPRULE_SRC)
2369 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
2371 if (rule->flags & IPRULE_DEST)
2372 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
2374 if (rule->flags & IPRULE_PRIORITY)
2375 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
2376 else if (cmd == RTM_NEWRULE)
2377 nla_put_u32(msg, FRA_PRIORITY, rule->order);
2379 if (rule->flags & IPRULE_FWMARK)
2380 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
2382 if (rule->flags & IPRULE_FWMASK)
2383 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
2385 if (rule->flags & IPRULE_LOOKUP) {
2386 if (rule->lookup >= 256)
2387 nla_put_u32(msg, FRA_TABLE, rule->lookup);
2390 if (rule->flags & IPRULE_SUP_PREFIXLEN)
2391 nla_put_u32(msg, FRA_SUPPRESS_PREFIXLEN, rule->sup_prefixlen);
2393 if (rule->flags & IPRULE_GOTO)
2394 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
2396 return system_rtnl_call(msg);
2399 int system_add_iprule(struct iprule *rule)
2401 return system_iprule(rule, RTM_NEWRULE);
2404 int system_del_iprule(struct iprule *rule)
2406 return system_iprule(rule, RTM_DELRULE);
2409 int system_flush_iprules(void)
2414 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
2415 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
2417 memset(&rule, 0, sizeof(rule));
2420 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2423 rule.lookup = RT_TABLE_LOCAL;
2424 rv |= system_iprule(&rule, RTM_NEWRULE);
2426 rule.priority = 32766;
2427 rule.lookup = RT_TABLE_MAIN;
2428 rv |= system_iprule(&rule, RTM_NEWRULE);
2430 rule.priority = 32767;
2431 rule.lookup = RT_TABLE_DEFAULT;
2432 rv |= system_iprule(&rule, RTM_NEWRULE);
2435 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2438 rule.lookup = RT_TABLE_LOCAL;
2439 rv |= system_iprule(&rule, RTM_NEWRULE);
2441 rule.priority = 32766;
2442 rule.lookup = RT_TABLE_MAIN;
2443 rv |= system_iprule(&rule, RTM_NEWRULE);
2448 bool system_resolve_iprule_action(const char *action, unsigned int *id)
2450 return system_rtn_aton(action, id);
2453 time_t system_get_rtime(void)
2458 if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
2461 if (gettimeofday(&tv, NULL) == 0)
2468 #define IP_DF 0x4000
2471 static int tunnel_ioctl(const char *name, int cmd, void *p)
2475 memset(&ifr, 0, sizeof(ifr));
2476 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name) - 1);
2477 ifr.ifr_ifru.ifru_data = p;
2478 return ioctl(sock_ioctl, cmd, &ifr);
2481 #ifdef IFLA_IPTUN_MAX
2482 static int system_add_ip6_tunnel(const char *name, const unsigned int link,
2483 struct blob_attr **tb)
2485 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2486 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2487 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2488 struct blob_attr *cur;
2489 int ret = 0, ttl = 0;
2494 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2495 nla_put_string(nlm, IFLA_IFNAME, name);
2498 nla_put_u32(nlm, IFLA_LINK, link);
2500 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2506 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2507 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2514 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2516 if ((cur = tb[TUNNEL_ATTR_TTL]))
2517 ttl = blobmsg_get_u32(cur);
2519 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2520 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2522 struct in6_addr in6buf;
2523 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2524 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2528 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2531 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2532 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2536 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2539 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2540 struct blob_attr *tb_data[__IPIP6_DATA_ATTR_MAX];
2541 uint32_t tun_flags = IP6_TNL_F_IGN_ENCAP_LIMIT;
2543 blobmsg_parse(ipip6_data_attr_list.params, __IPIP6_DATA_ATTR_MAX, tb_data,
2544 blobmsg_data(cur), blobmsg_len(cur));
2546 if ((cur = tb_data[IPIP6_DATA_ENCAPLIMIT])) {
2547 char *str = blobmsg_get_string(cur);
2549 if (strcmp(str, "ignore")) {
2551 unsigned encap_limit = strtoul(str, &e, 0);
2553 if (e == str || *e || encap_limit > 255) {
2558 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, encap_limit);
2559 tun_flags &= ~IP6_TNL_F_IGN_ENCAP_LIMIT;
2563 #ifdef IFLA_IPTUN_FMR_MAX
2564 if ((cur = tb_data[IPIP6_DATA_FMRS])) {
2565 struct blob_attr *rcur;
2566 unsigned rrem, fmrcnt = 0;
2567 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2574 blobmsg_for_each_attr(rcur, cur, rrem) {
2575 struct blob_attr *tb_fmr[__FMR_DATA_ATTR_MAX], *tb_cur;
2576 struct in6_addr ip6prefix;
2577 struct in_addr ip4prefix;
2578 unsigned ip4len, ip6len, ealen, offset;
2580 blobmsg_parse(fmr_data_attr_list.params, __FMR_DATA_ATTR_MAX, tb_fmr,
2581 blobmsg_data(rcur), blobmsg_len(rcur));
2583 if (!(tb_cur = tb_fmr[FMR_DATA_PREFIX6]) ||
2584 !parse_ip_and_netmask(AF_INET6,
2585 blobmsg_data(tb_cur), &ip6prefix,
2591 if (!(tb_cur = tb_fmr[FMR_DATA_PREFIX4]) ||
2592 !parse_ip_and_netmask(AF_INET,
2593 blobmsg_data(tb_cur), &ip4prefix,
2599 if (!(tb_cur = tb_fmr[FMR_DATA_EALEN])) {
2603 ealen = blobmsg_get_u32(tb_cur);
2605 if (!(tb_cur = tb_fmr[FMR_DATA_OFFSET])) {
2609 offset = blobmsg_get_u32(tb_cur);
2611 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2617 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2618 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2619 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2620 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2621 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2622 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2624 nla_nest_end(nlm, rule);
2627 nla_nest_end(nlm, fmrs);
2631 nla_put_u32(nlm, IFLA_IPTUN_FLAGS, tun_flags);
2634 nla_nest_end(nlm, infodata);
2635 nla_nest_end(nlm, linkinfo);
2637 return system_rtnl_call(nlm);
2645 #ifdef IFLA_IPTUN_MAX
2646 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
2647 static int system_add_gre_tunnel(const char *name, const char *kind,
2648 const unsigned int link, struct blob_attr **tb, bool v6)
2651 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2652 struct blob_attr *cur;
2653 uint32_t ikey = 0, okey = 0, flowinfo = 0, flags6 = IP6_TNL_F_IGN_ENCAP_LIMIT;
2654 uint16_t iflags = 0, oflags = 0;
2656 int ret = 0, ttl = 0;
2657 unsigned encap_limit = 0;
2659 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2663 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2664 nla_put_string(nlm, IFLA_IFNAME, name);
2666 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2672 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2673 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2680 nla_put_u32(nlm, IFLA_GRE_LINK, link);
2682 if ((cur = tb[TUNNEL_ATTR_TTL]))
2683 ttl = blobmsg_get_u32(cur);
2685 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2686 char *str = blobmsg_get_string(cur);
2687 if (strcmp(str, "inherit")) {
2690 if (!system_tos_aton(str, &uval)) {
2696 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
2701 flags6 |= IP6_TNL_F_USE_ORIG_TCLASS;
2707 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2708 struct blob_attr *tb_data[__GRE_DATA_ATTR_MAX];
2710 blobmsg_parse(gre_data_attr_list.params, __GRE_DATA_ATTR_MAX, tb_data,
2711 blobmsg_data(cur), blobmsg_len(cur));
2713 if ((cur = tb_data[GRE_DATA_IKEY])) {
2714 if ((ikey = blobmsg_get_u32(cur)))
2718 if ((cur = tb_data[GRE_DATA_OKEY])) {
2719 if ((okey = blobmsg_get_u32(cur)))
2723 if ((cur = tb_data[GRE_DATA_ICSUM])) {
2724 if (blobmsg_get_bool(cur))
2728 if ((cur = tb_data[GRE_DATA_OCSUM])) {
2729 if (blobmsg_get_bool(cur))
2733 if ((cur = tb_data[GRE_DATA_ISEQNO])) {
2734 if (blobmsg_get_bool(cur))
2738 if ((cur = tb_data[GRE_DATA_OSEQNO])) {
2739 if (blobmsg_get_bool(cur))
2743 if ((cur = tb_data[GRE_DATA_ENCAPLIMIT])) {
2744 char *str = blobmsg_get_string(cur);
2746 if (strcmp(str, "ignore")) {
2749 encap_limit = strtoul(str, &e, 0);
2751 if (e == str || *e || encap_limit > 255) {
2756 flags6 &= ~IP6_TNL_F_IGN_ENCAP_LIMIT;
2762 struct in6_addr in6buf;
2763 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2764 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2768 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
2771 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2772 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2776 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
2779 if (!(flags6 & IP6_TNL_F_IGN_ENCAP_LIMIT))
2780 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, encap_limit);
2783 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
2786 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags6);
2791 struct in_addr inbuf;
2794 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2795 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2799 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
2802 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2803 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2807 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
2809 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
2811 okey = inbuf.s_addr;
2816 ikey = inbuf.s_addr;
2822 if ((cur = tb[TUNNEL_ATTR_DF]))
2823 set_df = blobmsg_get_bool(cur);
2826 /* ttl != 0 and nopmtudisc are incompatible */
2834 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
2836 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
2840 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
2843 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
2846 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
2849 nla_put_u32(nlm, IFLA_GRE_OKEY, htonl(okey));
2852 nla_put_u32(nlm, IFLA_GRE_IKEY, htonl(ikey));
2854 nla_nest_end(nlm, infodata);
2855 nla_nest_end(nlm, linkinfo);
2857 return system_rtnl_call(nlm);
2866 static int system_add_vti_tunnel(const char *name, const char *kind,
2867 const unsigned int link, struct blob_attr **tb, bool v6)
2870 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2871 struct blob_attr *cur;
2874 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2878 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2879 nla_put_string(nlm, IFLA_IFNAME, name);
2881 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2887 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2888 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2895 nla_put_u32(nlm, IFLA_VTI_LINK, link);
2898 struct in6_addr in6buf;
2899 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2900 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2904 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(in6buf), &in6buf);
2907 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2908 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2912 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(in6buf), &in6buf);
2916 struct in_addr inbuf;
2918 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2919 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2923 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(inbuf), &inbuf);
2926 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2927 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2931 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(inbuf), &inbuf);
2936 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2937 struct blob_attr *tb_data[__VTI_DATA_ATTR_MAX];
2938 uint32_t ikey = 0, okey = 0;
2940 blobmsg_parse(vti_data_attr_list.params, __VTI_DATA_ATTR_MAX, tb_data,
2941 blobmsg_data(cur), blobmsg_len(cur));
2943 if ((cur = tb_data[VTI_DATA_IKEY])) {
2944 if ((ikey = blobmsg_get_u32(cur)))
2945 nla_put_u32(nlm, IFLA_VTI_IKEY, htonl(ikey));
2948 if ((cur = tb_data[VTI_DATA_OKEY])) {
2949 if ((okey = blobmsg_get_u32(cur)))
2950 nla_put_u32(nlm, IFLA_VTI_OKEY, htonl(okey));
2954 nla_nest_end(nlm, infodata);
2955 nla_nest_end(nlm, linkinfo);
2957 return system_rtnl_call(nlm);
2965 #ifdef IFLA_XFRM_MAX
2966 static int system_add_xfrm_tunnel(const char *name, const char *kind,
2967 const unsigned int link, struct blob_attr **tb)
2970 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2971 struct blob_attr *cur;
2974 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2978 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2979 nla_put_string(nlm, IFLA_IFNAME, name);
2981 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2987 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2988 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2995 nla_put_u32(nlm, IFLA_XFRM_LINK, link);
2997 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2998 struct blob_attr *tb_data[__XFRM_DATA_ATTR_MAX];
3001 blobmsg_parse(xfrm_data_attr_list.params, __XFRM_DATA_ATTR_MAX, tb_data,
3002 blobmsg_data(cur), blobmsg_len(cur));
3004 if ((cur = tb_data[XFRM_DATA_IF_ID])) {
3005 if ((if_id = blobmsg_get_u32(cur)))
3006 nla_put_u32(nlm, IFLA_XFRM_IF_ID, if_id);
3011 nla_nest_end(nlm, infodata);
3012 nla_nest_end(nlm, linkinfo);
3014 return system_rtnl_call(nlm);
3022 #ifdef IFLA_VXLAN_MAX
3023 static int system_add_vxlan(const char *name, const unsigned int link, struct blob_attr **tb, bool v6)
3025 struct blob_attr *tb_data[__VXLAN_DATA_ATTR_MAX];
3027 struct nlattr *linkinfo, *data;
3028 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
3029 struct blob_attr *cur;
3032 if ((cur = tb[TUNNEL_ATTR_DATA]))
3033 blobmsg_parse(vxlan_data_attr_list.params, __VXLAN_DATA_ATTR_MAX, tb_data,
3034 blobmsg_data(cur), blobmsg_len(cur));
3038 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
3043 nlmsg_append(msg, &iim, sizeof(iim), 0);
3045 nla_put_string(msg, IFLA_IFNAME, name);
3047 if ((cur = tb_data[VXLAN_DATA_ATTR_MACADDR])) {
3048 struct ether_addr *ea = ether_aton(blobmsg_get_string(cur));
3054 nla_put(msg, IFLA_ADDRESS, ETH_ALEN, ea);
3057 if ((cur = tb[TUNNEL_ATTR_MTU])) {
3058 uint32_t mtu = blobmsg_get_u32(cur);
3059 nla_put_u32(msg, IFLA_MTU, mtu);
3062 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO))) {
3067 nla_put_string(msg, IFLA_INFO_KIND, "vxlan");
3069 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) {
3075 nla_put_u32(msg, IFLA_VXLAN_LINK, link);
3077 if ((cur = tb_data[VXLAN_DATA_ATTR_ID])) {
3078 uint32_t id = blobmsg_get_u32(cur);
3079 if (id >= (1u << 24) - 1) {
3084 nla_put_u32(msg, IFLA_VXLAN_ID, id);
3088 struct in6_addr in6buf;
3089 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
3090 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
3094 nla_put(msg, IFLA_VXLAN_LOCAL6, sizeof(in6buf), &in6buf);
3097 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
3098 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
3102 nla_put(msg, IFLA_VXLAN_GROUP6, sizeof(in6buf), &in6buf);
3105 struct in_addr inbuf;
3107 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
3108 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
3112 nla_put(msg, IFLA_VXLAN_LOCAL, sizeof(inbuf), &inbuf);
3115 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
3116 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
3120 nla_put(msg, IFLA_VXLAN_GROUP, sizeof(inbuf), &inbuf);
3124 uint32_t port = 4789;
3125 if ((cur = tb_data[VXLAN_DATA_ATTR_PORT])) {
3126 port = blobmsg_get_u32(cur);
3127 if (port < 1 || port > 65535) {
3132 nla_put_u16(msg, IFLA_VXLAN_PORT, htons(port));
3134 if ((cur = tb_data[VXLAN_DATA_ATTR_RXCSUM])) {
3135 bool rxcsum = blobmsg_get_bool(cur);
3136 nla_put_u8(msg, IFLA_VXLAN_UDP_ZERO_CSUM6_RX, !rxcsum);
3139 if ((cur = tb_data[VXLAN_DATA_ATTR_TXCSUM])) {
3140 bool txcsum = blobmsg_get_bool(cur);
3141 nla_put_u8(msg, IFLA_VXLAN_UDP_CSUM, txcsum);
3142 nla_put_u8(msg, IFLA_VXLAN_UDP_ZERO_CSUM6_TX, !txcsum);
3145 if ((cur = tb[TUNNEL_ATTR_TOS])) {
3146 char *str = blobmsg_get_string(cur);
3149 if (strcmp(str, "inherit")) {
3150 if (!system_tos_aton(str, &tos)) {
3156 nla_put_u8(msg, IFLA_VXLAN_TOS, tos);
3159 if ((cur = tb[TUNNEL_ATTR_TTL])) {
3160 uint32_t ttl = blobmsg_get_u32(cur);
3161 if (ttl < 1 || ttl > 255) {
3166 nla_put_u8(msg, IFLA_VXLAN_TTL, ttl);
3169 nla_nest_end(msg, data);
3170 nla_nest_end(msg, linkinfo);
3172 ret = system_rtnl_call(msg);
3174 D(SYSTEM, "Error adding vxlan '%s': %d\n", name, ret);
3184 static int system_add_sit_tunnel(const char *name, const unsigned int link, struct blob_attr **tb)
3186 struct blob_attr *cur;
3189 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
3193 if ((cur = tb[TUNNEL_ATTR_DATA])) {
3194 struct blob_attr *tb_data[__SIXRD_DATA_ATTR_MAX];
3196 struct ip_tunnel_6rd p6;
3198 blobmsg_parse(sixrd_data_attr_list.params, __SIXRD_DATA_ATTR_MAX, tb_data,
3199 blobmsg_data(cur), blobmsg_len(cur));
3201 memset(&p6, 0, sizeof(p6));
3203 if ((cur = tb_data[SIXRD_DATA_PREFIX])) {
3204 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
3205 &p6.prefix, &mask) || mask > 128) {
3210 p6.prefixlen = mask;
3213 if ((cur = tb_data[SIXRD_DATA_RELAY_PREFIX])) {
3214 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
3215 &p6.relay_prefix, &mask) || mask > 32) {
3220 p6.relay_prefixlen = mask;
3223 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
3233 __system_del_ip_tunnel(name, tb);
3237 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
3239 struct blob_attr *cur;
3241 struct ip_tunnel_parm p = {
3250 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
3251 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
3254 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
3255 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
3258 if ((cur = tb[TUNNEL_ATTR_DF]))
3259 set_df = blobmsg_get_bool(cur);
3261 if ((cur = tb[TUNNEL_ATTR_TTL]))
3262 p.iph.ttl = blobmsg_get_u32(cur);
3264 if ((cur = tb[TUNNEL_ATTR_TOS])) {
3265 char *str = blobmsg_get_string(cur);
3266 if (strcmp(str, "inherit")) {
3269 if (!system_tos_aton(str, &uval))
3277 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
3278 /* ttl !=0 and nopmtudisc are incompatible */
3279 if (p.iph.ttl && p.iph.frag_off == 0)
3282 strncpy(p.name, name, sizeof(p.name) - 1);
3284 switch (p.iph.protocol) {
3286 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
3288 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
3295 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
3297 struct blob_attr *cur;
3300 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
3302 str = blobmsg_data(cur);
3304 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
3305 !strcmp(str, "greip6") || !strcmp(str, "gretapip6") ||
3306 !strcmp(str, "vtiip") || !strcmp(str, "vtiip6") ||
3307 !strcmp(str, "vxlan") || !strcmp(str, "vxlan6") ||
3308 !strcmp(str, "xfrm"))
3309 return system_link_del(name);
3311 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
3314 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
3316 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
3318 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
3319 blob_data(attr), blob_len(attr));
3321 return __system_del_ip_tunnel(name, tb);
3324 int system_update_ipv6_mtu(struct device *dev, int mtu)
3330 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
3333 fd = open(buf, O_RDWR);
3338 ssize_t len = read(fd, buf, sizeof(buf) - 1);
3345 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) > 0)
3354 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
3356 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
3357 struct blob_attr *cur;
3360 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
3361 blob_data(attr), blob_len(attr));
3363 __system_del_ip_tunnel(name, tb);
3365 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
3367 str = blobmsg_data(cur);
3369 unsigned int ttl = 0;
3370 if ((cur = tb[TUNNEL_ATTR_TTL])) {
3371 ttl = blobmsg_get_u32(cur);
3376 unsigned int link = 0;
3377 if ((cur = tb[TUNNEL_ATTR_LINK])) {
3378 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
3382 if (iface->l3_dev.dev)
3383 link = iface->l3_dev.dev->ifindex;
3386 if (!strcmp(str, "sit"))
3387 return system_add_sit_tunnel(name, link, tb);
3388 #ifdef IFLA_IPTUN_MAX
3389 else if (!strcmp(str, "ipip6")) {
3390 return system_add_ip6_tunnel(name, link, tb);
3391 } else if (!strcmp(str, "greip")) {
3392 return system_add_gre_tunnel(name, "gre", link, tb, false);
3393 } else if (!strcmp(str, "gretapip")) {
3394 return system_add_gre_tunnel(name, "gretap", link, tb, false);
3395 } else if (!strcmp(str, "greip6")) {
3396 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
3397 } else if (!strcmp(str, "gretapip6")) {
3398 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
3400 } else if (!strcmp(str, "vtiip")) {
3401 return system_add_vti_tunnel(name, "vti", link, tb, false);
3402 } else if (!strcmp(str, "vtiip6")) {
3403 return system_add_vti_tunnel(name, "vti6", link, tb, true);
3405 #ifdef IFLA_XFRM_MAX
3406 } else if (!strcmp(str, "xfrm")) {
3407 return system_add_xfrm_tunnel(name, "xfrm", link, tb);
3409 #ifdef IFLA_VXLAN_MAX
3410 } else if(!strcmp(str, "vxlan")) {
3411 return system_add_vxlan(name, link, tb, false);
3412 } else if(!strcmp(str, "vxlan6")) {
3413 return system_add_vxlan(name, link, tb, true);
3416 } else if (!strcmp(str, "ipip")) {
3417 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);