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>
79 struct uloop_fd uloop;
84 static int sock_ioctl = -1;
85 static struct nl_sock *sock_rtnl = NULL;
87 static int cb_rtnl_event(struct nl_msg *msg, void *arg);
88 static void handle_hotplug_event(struct uloop_fd *u, unsigned int events);
89 static int system_add_proto_tunnel(const char *name, const uint8_t proto,
90 const unsigned int link, struct blob_attr **tb);
91 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb);
93 static char dev_buf[256];
96 handler_nl_event(struct uloop_fd *u, unsigned int events)
98 struct event_socket *ev = container_of(u, struct event_socket, uloop);
100 socklen_t errlen = sizeof(err);
103 nl_recvmsgs_default(ev->sock);
107 if (getsockopt(u->fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen))
112 /* Increase rx buffer size on netlink socket */
114 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
117 /* Request full dump since some info got dropped */
118 struct rtgenmsg msg = { .rtgen_family = AF_UNSPEC };
119 nl_send_simple(ev->sock, RTM_GETLINK, NLM_F_DUMP, &msg, sizeof(msg));
129 uloop_fd_delete(&ev->uloop);
133 static struct nl_sock *
134 create_socket(int protocol, int groups)
136 struct nl_sock *sock;
138 sock = nl_socket_alloc();
143 nl_join_groups(sock, groups);
145 if (nl_connect(sock, protocol)) {
146 nl_socket_free(sock);
154 create_raw_event_socket(struct event_socket *ev, int protocol, int groups,
155 uloop_fd_handler cb, int flags)
157 ev->sock = create_socket(protocol, groups);
161 ev->uloop.fd = nl_socket_get_fd(ev->sock);
163 if (uloop_fd_add(&ev->uloop, ULOOP_READ|flags))
170 create_event_socket(struct event_socket *ev, int protocol,
171 int (*cb)(struct nl_msg *msg, void *arg))
173 if (!create_raw_event_socket(ev, protocol, 0, handler_nl_event, ULOOP_ERROR_CB))
176 /* Install the valid custom callback handler */
177 nl_socket_modify_cb(ev->sock, NL_CB_VALID, NL_CB_CUSTOM, cb, NULL);
179 /* Disable sequence number checking on event sockets */
180 nl_socket_disable_seq_check(ev->sock);
182 /* Increase rx buffer size to 65K on event sockets */
184 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
191 create_hotplug_event_socket(struct event_socket *ev, int protocol,
192 void (*cb)(struct uloop_fd *u, unsigned int events))
194 if (!create_raw_event_socket(ev, protocol, 1, cb, ULOOP_ERROR_CB))
197 /* Increase rx buffer size to 65K on event sockets */
199 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
206 system_rtn_aton(const char *src, unsigned int *dst)
211 if (!strcmp(src, "local"))
213 else if (!strcmp(src, "nat"))
215 else if (!strcmp(src, "broadcast"))
217 else if (!strcmp(src, "anycast"))
219 else if (!strcmp(src, "multicast"))
221 else if (!strcmp(src, "prohibit"))
223 else if (!strcmp(src, "unreachable"))
225 else if (!strcmp(src, "blackhole"))
227 else if (!strcmp(src, "xresolve"))
229 else if (!strcmp(src, "unicast"))
231 else if (!strcmp(src, "throw"))
233 else if (!strcmp(src, "failed_policy"))
234 n = RTN_FAILED_POLICY;
236 n = strtoul(src, &e, 0);
237 if (!e || *e || e == src || n > 255)
246 system_tos_aton(const char *src, unsigned *dst)
250 *dst = strtoul(src, &e, 16);
251 if (e == src || *e || *dst > 255)
257 int system_init(void)
259 static struct event_socket rtnl_event;
260 static struct event_socket hotplug_event;
262 sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0);
263 system_fd_set_cloexec(sock_ioctl);
265 /* Prepare socket for routing / address control */
266 sock_rtnl = create_socket(NETLINK_ROUTE, 0);
270 if (!create_event_socket(&rtnl_event, NETLINK_ROUTE, cb_rtnl_event))
273 if (!create_hotplug_event_socket(&hotplug_event, NETLINK_KOBJECT_UEVENT,
274 handle_hotplug_event))
277 /* Receive network link events form kernel */
278 nl_socket_add_membership(rtnl_event.sock, RTNLGRP_LINK);
283 static void system_set_sysctl(const char *path, const char *val)
287 fd = open(path, O_WRONLY);
291 if (write(fd, val, strlen(val))) {}
295 static void system_set_dev_sysctl(const char *path, const char *device, const char *val)
297 snprintf(dev_buf, sizeof(dev_buf), path, device);
298 system_set_sysctl(dev_buf, val);
301 static void system_set_disable_ipv6(struct device *dev, const char *val)
303 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val);
306 static void system_set_rpfilter(struct device *dev, const char *val)
308 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter", dev->ifname, val);
311 static void system_set_acceptlocal(struct device *dev, const char *val)
313 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local", dev->ifname, val);
316 static void system_set_igmpversion(struct device *dev, const char *val)
318 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version", dev->ifname, val);
321 static void system_set_mldversion(struct device *dev, const char *val)
323 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version", dev->ifname, val);
326 static void system_set_neigh4reachabletime(struct device *dev, const char *val)
328 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms", dev->ifname, val);
331 static void system_set_neigh6reachabletime(struct device *dev, const char *val)
333 system_set_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms", dev->ifname, val);
336 static void system_set_neigh4gcstaletime(struct device *dev, const char *val)
338 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/gc_stale_time", dev->ifname, val);
341 static void system_set_neigh6gcstaletime(struct device *dev, const char *val)
343 system_set_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/gc_stale_time", dev->ifname, val);
346 static void system_set_neigh4locktime(struct device *dev, const char *val)
348 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/locktime", dev->ifname, val);
351 static void system_set_dadtransmits(struct device *dev, const char *val)
353 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits", dev->ifname, val);
356 static void system_bridge_set_multicast_to_unicast(struct device *dev, const char *val)
358 system_set_dev_sysctl("/sys/class/net/%s/brport/multicast_to_unicast", dev->ifname, val);
361 static void system_bridge_set_multicast_fast_leave(struct device *dev, const char *val)
363 system_set_dev_sysctl("/sys/class/net/%s/brport/multicast_fast_leave", dev->ifname, val);
366 static void system_bridge_set_hairpin_mode(struct device *dev, const char *val)
368 system_set_dev_sysctl("/sys/class/net/%s/brport/hairpin_mode", dev->ifname, val);
371 static void system_bridge_set_isolated(struct device *dev, const char *val)
373 system_set_dev_sysctl("/sys/class/net/%s/brport/isolated", dev->ifname, val);
376 static void system_bridge_set_multicast_router(struct device *dev, const char *val, bool bridge)
378 system_set_dev_sysctl(bridge ? "/sys/class/net/%s/bridge/multicast_router" :
379 "/sys/class/net/%s/brport/multicast_router",
383 static void system_bridge_set_robustness(struct device *dev, const char *val)
385 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_startup_query_count",
387 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_last_member_count",
391 static void system_bridge_set_query_interval(struct device *dev, const char *val)
393 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_query_interval",
397 static void system_bridge_set_query_response_interval(struct device *dev, const char *val)
399 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_query_response_interval",
403 static void system_bridge_set_last_member_interval(struct device *dev, const char *val)
405 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_last_member_interval",
409 static void system_bridge_set_membership_interval(struct device *dev, const char *val)
411 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_membership_interval",
415 static void system_bridge_set_other_querier_timeout(struct device *dev, const char *val)
417 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier_interval",
421 static void system_bridge_set_startup_query_interval(struct device *dev, const char *val)
423 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_startup_query_interval",
427 static void system_bridge_set_stp_state(struct device *dev, const char *val)
429 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/stp_state", dev->ifname, val);
432 static void system_bridge_set_forward_delay(struct device *dev, const char *val)
434 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/forward_delay", dev->ifname, val);
437 static void system_bridge_set_priority(struct device *dev, const char *val)
439 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/priority", dev->ifname, val);
442 static void system_bridge_set_ageing_time(struct device *dev, const char *val)
444 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/ageing_time", dev->ifname, val);
447 static void system_bridge_set_hello_time(struct device *dev, const char *val)
449 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/hello_time", dev->ifname, val);
452 static void system_bridge_set_max_age(struct device *dev, const char *val)
454 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/max_age", dev->ifname, val);
457 static void system_bridge_set_learning(struct device *dev, const char *val)
459 system_set_dev_sysctl("/sys/class/net/%s/brport/learning", dev->ifname, val);
462 static void system_bridge_set_unicast_flood(struct device *dev, const char *val)
464 system_set_dev_sysctl("/sys/class/net/%s/brport/unicast_flood", dev->ifname, val);
467 static void system_set_sendredirects(struct device *dev, const char *val)
469 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/send_redirects", dev->ifname, val);
472 static int system_get_sysctl(const char *path, char *buf, const size_t buf_sz)
474 int fd = -1, ret = -1;
476 fd = open(path, O_RDONLY);
480 ssize_t len = read(fd, buf, buf_sz - 1);
494 system_get_dev_sysctl(const char *path, const char *device, char *buf, const size_t buf_sz)
496 snprintf(dev_buf, sizeof(dev_buf), path, device);
497 return system_get_sysctl(dev_buf, buf, buf_sz);
500 static int system_get_disable_ipv6(struct device *dev, char *buf, const size_t buf_sz)
502 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6",
503 dev->ifname, buf, buf_sz);
506 static int system_get_rpfilter(struct device *dev, char *buf, const size_t buf_sz)
508 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter",
509 dev->ifname, buf, buf_sz);
512 static int system_get_acceptlocal(struct device *dev, char *buf, const size_t buf_sz)
514 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local",
515 dev->ifname, buf, buf_sz);
518 static int system_get_igmpversion(struct device *dev, char *buf, const size_t buf_sz)
520 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version",
521 dev->ifname, buf, buf_sz);
524 static int system_get_mldversion(struct device *dev, char *buf, const size_t buf_sz)
526 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version",
527 dev->ifname, buf, buf_sz);
530 static int system_get_neigh4reachabletime(struct device *dev, char *buf, const size_t buf_sz)
532 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms",
533 dev->ifname, buf, buf_sz);
536 static int system_get_neigh6reachabletime(struct device *dev, char *buf, const size_t buf_sz)
538 return system_get_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms",
539 dev->ifname, buf, buf_sz);
542 static int system_get_neigh4gcstaletime(struct device *dev, char *buf, const size_t buf_sz)
544 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/gc_stale_time",
545 dev->ifname, buf, buf_sz);
548 static int system_get_neigh6gcstaletime(struct device *dev, char *buf, const size_t buf_sz)
550 return system_get_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/gc_stale_time",
551 dev->ifname, buf, buf_sz);
554 static int system_get_neigh4locktime(struct device *dev, char *buf, const size_t buf_sz)
556 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/locktime",
557 dev->ifname, buf, buf_sz);
560 static int system_get_dadtransmits(struct device *dev, char *buf, const size_t buf_sz)
562 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits",
563 dev->ifname, buf, buf_sz);
566 static int system_get_sendredirects(struct device *dev, char *buf, const size_t buf_sz)
568 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/send_redirects",
569 dev->ifname, buf, buf_sz);
572 /* Evaluate netlink messages */
573 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
575 struct nlmsghdr *nh = nlmsg_hdr(msg);
576 struct nlattr *nla[__IFLA_MAX];
580 if (nh->nlmsg_type != RTM_NEWLINK)
583 nlmsg_parse(nh, sizeof(struct ifinfomsg), nla, __IFLA_MAX - 1, NULL);
584 if (!nla[IFLA_IFNAME])
587 struct device *dev = device_find(nla_data(nla[IFLA_IFNAME]));
591 if (!system_get_dev_sysctl("/sys/class/net/%s/carrier", dev->ifname, buf, sizeof(buf)))
592 link_state = strtoul(buf, NULL, 0);
594 device_set_link(dev, link_state ? true : false);
601 handle_hotplug_msg(char *data, int size)
603 const char *subsystem = NULL, *interface = NULL, *interface_old = NULL;
604 char *cur, *end, *sep;
607 bool add, move = false;
609 if (!strncmp(data, "add@", 4))
611 else if (!strncmp(data, "remove@", 7))
613 else if (!strncmp(data, "move@", 5)) {
620 skip = strlen(data) + 1;
623 for (cur = data + skip; cur < end; cur += skip) {
624 skip = strlen(cur) + 1;
626 sep = strchr(cur, '=');
631 if (!strcmp(cur, "INTERFACE"))
633 else if (!strcmp(cur, "SUBSYSTEM")) {
635 if (strcmp(subsystem, "net") != 0)
637 } else if (!strcmp(cur, "DEVPATH_OLD")) {
638 interface_old = strrchr(sep + 1, '/');
644 if (subsystem && interface) {
645 if (move && interface_old)
654 dev = device_find(interface_old);
658 if (dev->type != &simple_device_type)
661 device_set_present(dev, false);
664 dev = device_find(interface);
668 if (dev->type != &simple_device_type)
671 if (add && system_if_force_external(dev->ifname))
674 device_set_present(dev, add);
678 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
680 struct event_socket *ev = container_of(u, struct event_socket, uloop);
681 struct sockaddr_nl nla;
682 unsigned char *buf = NULL;
685 socklen_t errlen = sizeof(err);
688 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
690 handle_hotplug_msg((char *) buf, size);
697 if (getsockopt(u->fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen))
702 /* Increase rx buffer size on netlink socket */
704 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
715 uloop_fd_delete(&ev->uloop);
719 static int system_rtnl_call(struct nl_msg *msg)
723 ret = nl_send_auto_complete(sock_rtnl, msg);
729 return nl_wait_for_ack(sock_rtnl);
732 int system_bridge_delbr(struct device *bridge)
734 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
737 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
741 memset(&ifr, 0, sizeof(ifr));
743 ifr.ifr_ifindex = dev->ifindex;
746 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name) - 1);
747 return ioctl(sock_ioctl, cmd, &ifr);
750 static bool system_is_bridge(const char *name, char *buf, int buflen)
754 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
755 if (stat(buf, &st) < 0)
761 static char *system_get_bridge(const char *name, char *buf, int buflen)
767 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
768 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
772 len = readlink(gl.gl_pathv[0], buf, buflen);
780 path = strrchr(buf, '/');
788 system_bridge_set_wireless(struct device *bridge, struct device *dev)
790 bool mcast_to_ucast = dev->wireless_ap;
793 if (bridge->settings.flags & DEV_OPT_MULTICAST_TO_UNICAST &&
794 !bridge->settings.multicast_to_unicast)
795 mcast_to_ucast = false;
797 if (!mcast_to_ucast || dev->wireless_isolate)
800 system_bridge_set_multicast_to_unicast(dev, mcast_to_ucast ? "1" : "0");
801 system_bridge_set_hairpin_mode(dev, hairpin ? "1" : "0");
804 int system_bridge_addif(struct device *bridge, struct device *dev)
810 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
811 if (!oldbr || strcmp(oldbr, bridge->ifname) != 0)
812 ret = system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
815 system_bridge_set_wireless(bridge, dev);
817 if (dev->settings.flags & DEV_OPT_MULTICAST_ROUTER) {
818 snprintf(buf, sizeof(buf), "%u", dev->settings.multicast_router);
819 system_bridge_set_multicast_router(dev, buf, false);
822 if (dev->settings.flags & DEV_OPT_MULTICAST_FAST_LEAVE &&
823 dev->settings.multicast_fast_leave)
824 system_bridge_set_multicast_fast_leave(dev, "1");
826 if (dev->settings.flags & DEV_OPT_LEARNING &&
827 !dev->settings.learning)
828 system_bridge_set_learning(dev, "0");
830 if (dev->settings.flags & DEV_OPT_UNICAST_FLOOD &&
831 !dev->settings.unicast_flood)
832 system_bridge_set_unicast_flood(dev, "0");
834 if (dev->settings.flags & DEV_OPT_ISOLATE &&
835 dev->settings.isolate)
836 system_bridge_set_isolated(dev, "1");
841 int system_bridge_delif(struct device *bridge, struct device *dev)
843 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
846 int system_if_resolve(struct device *dev)
849 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
850 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
851 return ifr.ifr_ifindex;
856 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
860 memset(&ifr, 0, sizeof(ifr));
861 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1);
862 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) < 0)
865 ifr.ifr_flags |= add;
866 ifr.ifr_flags &= ~rem;
867 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
879 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
881 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
883 return ifa->ifa_index == ifindex;
886 static bool check_route(struct nlmsghdr *hdr, int ifindex)
888 struct rtmsg *r = NLMSG_DATA(hdr);
889 struct nlattr *tb[__RTA_MAX];
891 if (r->rtm_protocol == RTPROT_KERNEL &&
892 r->rtm_family == AF_INET6)
895 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
899 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
902 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
907 static int cb_clear_event(struct nl_msg *msg, void *arg)
909 struct clear_data *clr = arg;
910 struct nlmsghdr *hdr = nlmsg_hdr(msg);
911 bool (*cb)(struct nlmsghdr *, int ifindex);
917 if (hdr->nlmsg_type != RTM_NEWADDR)
924 if (hdr->nlmsg_type != RTM_NEWROUTE)
931 if (hdr->nlmsg_type != RTM_NEWRULE)
940 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
943 if (type == RTM_DELRULE)
944 D(SYSTEM, "Remove a rule\n");
946 D(SYSTEM, "Remove %s from device %s\n",
947 type == RTM_DELADDR ? "an address" : "a route",
950 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
951 hdr = nlmsg_hdr(clr->msg);
952 hdr->nlmsg_type = type;
953 hdr->nlmsg_flags = NLM_F_REQUEST;
955 nl_socket_disable_auto_ack(sock_rtnl);
956 ret = nl_send_auto_complete(sock_rtnl, clr->msg);
958 if (type == RTM_DELRULE)
959 D(SYSTEM, "Error deleting a rule: %d\n", ret);
961 D(SYSTEM, "Error deleting %s from device '%s': %d\n",
962 type == RTM_DELADDR ? "an address" : "a route",
963 clr->dev->ifname, ret);
966 nl_socket_enable_auto_ack(sock_rtnl);
972 cb_finish_event(struct nl_msg *msg, void *arg)
980 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
983 *pending = err->error;
988 system_if_clear_entries(struct device *dev, int type, int af)
990 struct clear_data clr;
994 .rtm_flags = RTM_F_CLONED,
996 int flags = NLM_F_DUMP;
1005 clr.size = sizeof(struct rtgenmsg);
1008 clr.size = sizeof(struct rtmsg);
1014 cb = nl_cb_alloc(NL_CB_DEFAULT);
1018 clr.msg = nlmsg_alloc_simple(type, flags);
1022 nlmsg_append(clr.msg, &rtm, clr.size, 0);
1023 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
1024 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
1025 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
1027 if (nl_send_auto_complete(sock_rtnl, clr.msg) < 0)
1031 nl_recvmsgs(sock_rtnl, cb);
1034 nlmsg_free(clr.msg);
1040 * Clear bridge (membership) state and bring down device
1042 void system_if_clear_state(struct device *dev)
1044 static char buf[256];
1046 device_set_ifindex(dev, system_if_resolve(dev));
1048 if (dev->external || !dev->ifindex)
1051 system_if_flags(dev->ifname, 0, IFF_UP);
1053 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
1054 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
1055 system_bridge_delbr(dev);
1059 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
1061 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
1062 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
1065 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
1066 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
1067 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
1068 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
1069 system_if_clear_entries(dev, RTM_GETNEIGH, AF_INET);
1070 system_if_clear_entries(dev, RTM_GETNEIGH, AF_INET6);
1071 system_set_disable_ipv6(dev, "0");
1074 static inline unsigned long
1075 sec_to_jiffies(int val)
1077 return (unsigned long) val * 100;
1080 static void system_bridge_conf_multicast_deps(struct device *bridge,
1081 struct bridge_config *cfg,
1087 if (cfg->flags & BRIDGE_OPT_ROBUSTNESS ||
1088 cfg->flags & BRIDGE_OPT_QUERY_INTERVAL ||
1089 cfg->flags & BRIDGE_OPT_QUERY_RESPONSE_INTERVAL) {
1090 val = cfg->robustness * cfg->query_interval +
1091 cfg->query_response_interval;
1093 snprintf(buf, buf_len, "%i", val);
1094 system_bridge_set_membership_interval(bridge, buf);
1096 val = cfg->robustness * cfg->query_interval +
1097 cfg->query_response_interval / 2;
1099 snprintf(buf, buf_len, "%i", val);
1100 system_bridge_set_other_querier_timeout(bridge, buf);
1103 if (cfg->flags & BRIDGE_OPT_QUERY_INTERVAL) {
1104 val = cfg->query_interval / 4;
1106 snprintf(buf, buf_len, "%i", val);
1107 system_bridge_set_startup_query_interval(bridge, buf);
1111 static void system_bridge_conf_multicast(struct device *bridge,
1112 struct bridge_config *cfg,
1116 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
1117 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
1119 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier",
1120 bridge->ifname, cfg->multicast_querier ? "1" : "0");
1122 snprintf(buf, buf_len, "%i", cfg->hash_max);
1123 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/hash_max",
1124 bridge->ifname, buf);
1126 if (bridge->settings.flags & DEV_OPT_MULTICAST_ROUTER) {
1127 snprintf(buf, buf_len, "%u", bridge->settings.multicast_router);
1128 system_bridge_set_multicast_router(bridge, buf, true);
1131 if (cfg->flags & BRIDGE_OPT_ROBUSTNESS) {
1132 snprintf(buf, buf_len, "%i", cfg->robustness);
1133 system_bridge_set_robustness(bridge, buf);
1136 if (cfg->flags & BRIDGE_OPT_QUERY_INTERVAL) {
1137 snprintf(buf, buf_len, "%i", cfg->query_interval);
1138 system_bridge_set_query_interval(bridge, buf);
1141 if (cfg->flags & BRIDGE_OPT_QUERY_RESPONSE_INTERVAL) {
1142 snprintf(buf, buf_len, "%i", cfg->query_response_interval);
1143 system_bridge_set_query_response_interval(bridge, buf);
1146 if (cfg->flags & BRIDGE_OPT_LAST_MEMBER_INTERVAL) {
1147 snprintf(buf, buf_len, "%i", cfg->last_member_interval);
1148 system_bridge_set_last_member_interval(bridge, buf);
1151 system_bridge_conf_multicast_deps(bridge, cfg, buf, buf_len);
1154 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
1158 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
1161 system_bridge_set_stp_state(bridge, cfg->stp ? "1" : "0");
1163 snprintf(buf, sizeof(buf), "%lu", sec_to_jiffies(cfg->forward_delay));
1164 system_bridge_set_forward_delay(bridge, buf);
1166 system_bridge_conf_multicast(bridge, cfg, buf, sizeof(buf));
1168 snprintf(buf, sizeof(buf), "%d", cfg->priority);
1169 system_bridge_set_priority(bridge, buf);
1171 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
1172 snprintf(buf, sizeof(buf), "%lu", sec_to_jiffies(cfg->ageing_time));
1173 system_bridge_set_ageing_time(bridge, buf);
1176 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
1177 snprintf(buf, sizeof(buf), "%lu", sec_to_jiffies(cfg->hello_time));
1178 system_bridge_set_hello_time(bridge, buf);
1181 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
1182 snprintf(buf, sizeof(buf), "%lu", sec_to_jiffies(cfg->max_age));
1183 system_bridge_set_max_age(bridge, buf);
1189 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
1192 struct nlattr *linkinfo, *data;
1193 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
1195 static const struct {
1197 enum macvlan_mode val;
1199 { "private", MACVLAN_MODE_PRIVATE },
1200 { "vepa", MACVLAN_MODE_VEPA },
1201 { "bridge", MACVLAN_MODE_BRIDGE },
1202 { "passthru", MACVLAN_MODE_PASSTHRU },
1205 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1210 nlmsg_append(msg, &iim, sizeof(iim), 0);
1212 if (cfg->flags & MACVLAN_OPT_MACADDR)
1213 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
1214 nla_put_string(msg, IFLA_IFNAME, macvlan->ifname);
1215 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
1217 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1218 goto nla_put_failure;
1220 nla_put_string(msg, IFLA_INFO_KIND, "macvlan");
1222 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1223 goto nla_put_failure;
1226 for (i = 0; i < ARRAY_SIZE(modes); i++) {
1227 if (strcmp(cfg->mode, modes[i].name) != 0)
1230 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
1235 nla_nest_end(msg, data);
1236 nla_nest_end(msg, linkinfo);
1238 rv = system_rtnl_call(msg);
1240 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
1249 int system_link_netns_move(const char *ifname, int netns_fd)
1252 struct ifinfomsg iim = {
1253 .ifi_family = AF_UNSPEC,
1257 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST);
1262 nlmsg_append(msg, &iim, sizeof(iim), 0);
1263 nla_put_string(msg, IFLA_IFNAME, ifname);
1264 nla_put_u32(msg, IFLA_NET_NS_FD, netns_fd);
1265 return system_rtnl_call(msg);
1268 static int system_link_del(const char *ifname)
1271 struct ifinfomsg iim = {
1272 .ifi_family = AF_UNSPEC,
1276 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
1281 nlmsg_append(msg, &iim, sizeof(iim), 0);
1282 nla_put_string(msg, IFLA_IFNAME, ifname);
1283 return system_rtnl_call(msg);
1286 int system_macvlan_del(struct device *macvlan)
1288 return system_link_del(macvlan->ifname);
1291 int system_netns_open(const pid_t target_ns)
1293 char pid_net_path[PATH_MAX];
1295 snprintf(pid_net_path, sizeof(pid_net_path), "/proc/%u/ns/net", target_ns);
1297 return open(pid_net_path, O_RDONLY);
1300 int system_netns_set(int netns_fd)
1302 return setns(netns_fd, CLONE_NEWNET);
1305 int system_veth_add(struct device *veth, struct veth_config *cfg)
1308 struct ifinfomsg empty_iim = {};
1309 struct nlattr *linkinfo, *data, *veth_info;
1312 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1317 nlmsg_append(msg, &empty_iim, sizeof(empty_iim), 0);
1319 if (cfg->flags & VETH_OPT_MACADDR)
1320 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
1321 nla_put_string(msg, IFLA_IFNAME, veth->ifname);
1323 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1324 goto nla_put_failure;
1326 nla_put_string(msg, IFLA_INFO_KIND, "veth");
1328 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1329 goto nla_put_failure;
1331 if (!(veth_info = nla_nest_start(msg, VETH_INFO_PEER)))
1332 goto nla_put_failure;
1334 nlmsg_append(msg, &empty_iim, sizeof(empty_iim), 0);
1336 if (cfg->flags & VETH_OPT_PEER_NAME)
1337 nla_put_string(msg, IFLA_IFNAME, cfg->peer_name);
1338 if (cfg->flags & VETH_OPT_PEER_MACADDR)
1339 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->peer_macaddr), cfg->peer_macaddr);
1341 nla_nest_end(msg, veth_info);
1342 nla_nest_end(msg, data);
1343 nla_nest_end(msg, linkinfo);
1345 rv = system_rtnl_call(msg);
1347 if (cfg->flags & VETH_OPT_PEER_NAME)
1348 D(SYSTEM, "Error adding veth '%s' with peer '%s': %d\n", veth->ifname, cfg->peer_name, rv);
1350 D(SYSTEM, "Error adding veth '%s': %d\n", veth->ifname, rv);
1360 int system_veth_del(struct device *veth)
1362 return system_link_del(veth->ifname);
1365 static int system_vlan(struct device *dev, int id)
1367 struct vlan_ioctl_args ifr = {
1368 .cmd = SET_VLAN_NAME_TYPE_CMD,
1369 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
1372 if (ioctl(sock_ioctl, SIOCSIFVLAN, &ifr) < 0)
1376 ifr.cmd = DEL_VLAN_CMD;
1379 ifr.cmd = ADD_VLAN_CMD;
1382 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
1383 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
1386 int system_vlan_add(struct device *dev, int id)
1388 return system_vlan(dev, id);
1391 int system_vlan_del(struct device *dev)
1393 return system_vlan(dev, -1);
1396 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
1399 struct nlattr *linkinfo, *data;
1400 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
1403 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1408 nlmsg_append(msg, &iim, sizeof(iim), 0);
1409 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
1410 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
1412 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1413 goto nla_put_failure;
1415 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
1417 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1418 goto nla_put_failure;
1420 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
1422 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
1423 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
1425 if(cfg->proto == VLAN_PROTO_8021AD)
1426 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);
1429 nla_nest_end(msg, data);
1430 nla_nest_end(msg, linkinfo);
1432 rv = system_rtnl_call(msg);
1434 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
1443 int system_vlandev_del(struct device *vlandev)
1445 return system_link_del(vlandev->ifname);
1449 system_if_get_settings(struct device *dev, struct device_settings *s)
1454 memset(&ifr, 0, sizeof(ifr));
1455 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
1457 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
1458 s->mtu = ifr.ifr_mtu;
1459 s->flags |= DEV_OPT_MTU;
1462 s->mtu6 = system_update_ipv6_mtu(dev, 0);
1464 s->flags |= DEV_OPT_MTU6;
1466 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
1467 s->txqueuelen = ifr.ifr_qlen;
1468 s->flags |= DEV_OPT_TXQUEUELEN;
1471 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
1472 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
1473 s->flags |= DEV_OPT_MACADDR;
1476 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
1477 s->ipv6 = !strtoul(buf, NULL, 0);
1478 s->flags |= DEV_OPT_IPV6;
1481 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
1482 s->promisc = ifr.ifr_flags & IFF_PROMISC;
1483 s->flags |= DEV_OPT_PROMISC;
1485 s->multicast = ifr.ifr_flags & IFF_MULTICAST;
1486 s->flags |= DEV_OPT_MULTICAST;
1489 if (!system_get_rpfilter(dev, buf, sizeof(buf))) {
1490 s->rpfilter = strtoul(buf, NULL, 0);
1491 s->flags |= DEV_OPT_RPFILTER;
1494 if (!system_get_acceptlocal(dev, buf, sizeof(buf))) {
1495 s->acceptlocal = strtoul(buf, NULL, 0);
1496 s->flags |= DEV_OPT_ACCEPTLOCAL;
1499 if (!system_get_igmpversion(dev, buf, sizeof(buf))) {
1500 s->igmpversion = strtoul(buf, NULL, 0);
1501 s->flags |= DEV_OPT_IGMPVERSION;
1504 if (!system_get_mldversion(dev, buf, sizeof(buf))) {
1505 s->mldversion = strtoul(buf, NULL, 0);
1506 s->flags |= DEV_OPT_MLDVERSION;
1509 if (!system_get_neigh4reachabletime(dev, buf, sizeof(buf))) {
1510 s->neigh4reachabletime = strtoul(buf, NULL, 0);
1511 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1514 if (!system_get_neigh6reachabletime(dev, buf, sizeof(buf))) {
1515 s->neigh6reachabletime = strtoul(buf, NULL, 0);
1516 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1519 if (!system_get_neigh4locktime(dev, buf, sizeof(buf))) {
1520 s->neigh4locktime = strtol(buf, NULL, 0);
1521 s->flags |= DEV_OPT_NEIGHLOCKTIME;
1524 if (!system_get_neigh4gcstaletime(dev, buf, sizeof(buf))) {
1525 s->neigh4gcstaletime = strtoul(buf, NULL, 0);
1526 s->flags |= DEV_OPT_NEIGHGCSTALETIME;
1529 if (!system_get_neigh6gcstaletime(dev, buf, sizeof(buf))) {
1530 s->neigh6gcstaletime = strtoul(buf, NULL, 0);
1531 s->flags |= DEV_OPT_NEIGHGCSTALETIME;
1534 if (!system_get_dadtransmits(dev, buf, sizeof(buf))) {
1535 s->dadtransmits = strtoul(buf, NULL, 0);
1536 s->flags |= DEV_OPT_DADTRANSMITS;
1539 if (!system_get_sendredirects(dev, buf, sizeof(buf))) {
1540 s->sendredirects = strtoul(buf, NULL, 0);
1541 s->flags |= DEV_OPT_SENDREDIRECTS;
1546 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
1551 memset(&ifr, 0, sizeof(ifr));
1552 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
1553 if (s->flags & DEV_OPT_MTU & apply_mask) {
1554 ifr.ifr_mtu = s->mtu;
1555 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
1556 s->flags &= ~DEV_OPT_MTU;
1558 if (s->flags & DEV_OPT_MTU6 & apply_mask) {
1559 system_update_ipv6_mtu(dev, s->mtu6);
1561 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
1562 ifr.ifr_qlen = s->txqueuelen;
1563 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
1564 s->flags &= ~DEV_OPT_TXQUEUELEN;
1566 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
1567 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
1568 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
1569 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
1570 s->flags &= ~DEV_OPT_MACADDR;
1572 if (s->flags & DEV_OPT_IPV6 & apply_mask)
1573 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
1574 if (s->flags & DEV_OPT_PROMISC & apply_mask) {
1575 if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
1576 !s->promisc ? IFF_PROMISC : 0) < 0)
1577 s->flags &= ~DEV_OPT_PROMISC;
1579 if (s->flags & DEV_OPT_RPFILTER & apply_mask) {
1580 snprintf(buf, sizeof(buf), "%u", s->rpfilter);
1581 system_set_rpfilter(dev, buf);
1583 if (s->flags & DEV_OPT_ACCEPTLOCAL & apply_mask)
1584 system_set_acceptlocal(dev, s->acceptlocal ? "1" : "0");
1585 if (s->flags & DEV_OPT_IGMPVERSION & apply_mask) {
1586 snprintf(buf, sizeof(buf), "%u", s->igmpversion);
1587 system_set_igmpversion(dev, buf);
1589 if (s->flags & DEV_OPT_MLDVERSION & apply_mask) {
1590 snprintf(buf, sizeof(buf), "%u", s->mldversion);
1591 system_set_mldversion(dev, buf);
1593 if (s->flags & DEV_OPT_NEIGHREACHABLETIME & apply_mask) {
1594 snprintf(buf, sizeof(buf), "%u", s->neigh4reachabletime);
1595 system_set_neigh4reachabletime(dev, buf);
1596 snprintf(buf, sizeof(buf), "%u", s->neigh6reachabletime);
1597 system_set_neigh6reachabletime(dev, buf);
1599 if (s->flags & DEV_OPT_NEIGHLOCKTIME & apply_mask) {
1600 snprintf(buf, sizeof(buf), "%d", s->neigh4locktime);
1601 system_set_neigh4locktime(dev, buf);
1603 if (s->flags & DEV_OPT_NEIGHGCSTALETIME & apply_mask) {
1604 snprintf(buf, sizeof(buf), "%u", s->neigh4gcstaletime);
1605 system_set_neigh4gcstaletime(dev, buf);
1606 snprintf(buf, sizeof(buf), "%u", s->neigh6gcstaletime);
1607 system_set_neigh6gcstaletime(dev, buf);
1609 if (s->flags & DEV_OPT_DADTRANSMITS & apply_mask) {
1610 snprintf(buf, sizeof(buf), "%u", s->dadtransmits);
1611 system_set_dadtransmits(dev, buf);
1613 if (s->flags & DEV_OPT_MULTICAST & apply_mask) {
1614 if (system_if_flags(dev->ifname, s->multicast ? IFF_MULTICAST : 0,
1615 !s->multicast ? IFF_MULTICAST : 0) < 0)
1616 s->flags &= ~DEV_OPT_MULTICAST;
1618 if (s->flags & DEV_OPT_SENDREDIRECTS & apply_mask)
1619 system_set_sendredirects(dev, s->sendredirects ? "1" : "0");
1622 int system_if_up(struct device *dev)
1624 system_if_get_settings(dev, &dev->orig_settings);
1625 /* Only keep orig settings based on what needs to be set */
1626 dev->orig_settings.valid_flags = dev->orig_settings.flags;
1627 dev->orig_settings.flags &= dev->settings.flags;
1628 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
1629 return system_if_flags(dev->ifname, IFF_UP, 0);
1632 int system_if_down(struct device *dev)
1634 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
1635 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
1639 struct if_check_data {
1645 #ifndef IFF_LOWER_UP
1646 #define IFF_LOWER_UP 0x10000
1649 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1651 struct nlmsghdr *nh = nlmsg_hdr(msg);
1652 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1653 struct if_check_data *chk = (struct if_check_data *)arg;
1655 if (nh->nlmsg_type != RTM_NEWLINK)
1658 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1659 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1664 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1666 struct if_check_data *chk = (struct if_check_data *)arg;
1671 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1673 struct if_check_data *chk = (struct if_check_data *)arg;
1675 device_set_present(chk->dev, false);
1676 device_set_link(chk->dev, false);
1677 chk->pending = err->error;
1682 int system_if_check(struct device *dev)
1684 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1686 struct ifinfomsg ifi = {
1687 .ifi_family = AF_UNSPEC,
1690 struct if_check_data chk = {
1699 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1703 if (nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1704 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1707 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1708 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1709 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1711 ret = nl_send_auto_complete(sock_rtnl, msg);
1715 while (chk.pending > 0)
1716 nl_recvmsgs(sock_rtnl, cb);
1728 system_if_get_parent(struct device *dev)
1730 char buf[64], *devname;
1731 int ifindex, iflink, len;
1734 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1735 f = fopen(buf, "r");
1739 len = fread(buf, 1, sizeof(buf) - 1, f);
1746 iflink = strtoul(buf, NULL, 0);
1747 ifindex = system_if_resolve(dev);
1748 if (!iflink || iflink == ifindex)
1751 devname = if_indextoname(iflink, buf);
1755 return device_get(devname, true);
1759 read_string_file(int dir_fd, const char *file, char *buf, int len)
1765 fd = openat(dir_fd, file, O_RDONLY);
1770 len = read(fd, buf, len - 1);
1774 } else if (len > 0) {
1777 c = strchr(buf, '\n');
1790 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1795 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1797 *val = strtoull(buf, NULL, 0);
1802 /* Assume advertised flags == supported flags */
1803 static const struct {
1806 } ethtool_link_modes[] = {
1807 { ADVERTISED_10baseT_Half, "10baseT-H" },
1808 { ADVERTISED_10baseT_Full, "10baseT-F" },
1809 { ADVERTISED_100baseT_Half, "100baseT-H" },
1810 { ADVERTISED_100baseT_Full, "100baseT-F" },
1811 { ADVERTISED_1000baseT_Half, "1000baseT-H" },
1812 { ADVERTISED_1000baseT_Full, "1000baseT-F" },
1813 { ADVERTISED_1000baseKX_Full, "1000baseKX-F" },
1814 { ADVERTISED_2500baseX_Full, "2500baseX-F" },
1815 { ADVERTISED_10000baseT_Full, "10000baseT-F" },
1816 { ADVERTISED_10000baseKX4_Full, "10000baseKX4-F" },
1817 { ADVERTISED_10000baseKR_Full, "10000baseKR-F" },
1818 { ADVERTISED_20000baseMLD2_Full, "20000baseMLD2-F" },
1819 { ADVERTISED_20000baseKR2_Full, "20000baseKR2-F" },
1820 { ADVERTISED_40000baseKR4_Full, "40000baseKR4-F" },
1821 { ADVERTISED_40000baseCR4_Full, "40000baseCR4-F" },
1822 { ADVERTISED_40000baseSR4_Full, "40000baseSR4-F" },
1823 { ADVERTISED_40000baseLR4_Full, "40000baseLR4-F" },
1824 #ifdef ADVERTISED_56000baseKR4_Full
1825 { ADVERTISED_56000baseKR4_Full, "56000baseKR4-F" },
1826 { ADVERTISED_56000baseCR4_Full, "56000baseCR4-F" },
1827 { ADVERTISED_56000baseSR4_Full, "56000baseSR4-F" },
1828 { ADVERTISED_56000baseLR4_Full, "56000baseLR4-F" },
1832 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1835 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1836 if (mask & ethtool_link_modes[i].mask)
1837 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1842 system_if_force_external(const char *ifname)
1847 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1848 return stat(buf, &s) == 0;
1852 system_if_dump_info(struct device *dev, struct blob_buf *b)
1854 struct ethtool_cmd ecmd;
1859 memset(&ecmd, 0, sizeof(ecmd));
1860 memset(&ifr, 0, sizeof(ifr));
1861 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
1862 ifr.ifr_data = (caddr_t) &ecmd;
1863 ecmd.cmd = ETHTOOL_GSET;
1865 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1866 c = blobmsg_open_array(b, "link-advertising");
1867 system_add_link_modes(b, ecmd.advertising);
1868 blobmsg_close_array(b, c);
1870 c = blobmsg_open_array(b, "link-partner-advertising");
1871 system_add_link_modes(b, ecmd.lp_advertising);
1872 blobmsg_close_array(b, c);
1874 c = blobmsg_open_array(b, "link-supported");
1875 system_add_link_modes(b, ecmd.supported);
1876 blobmsg_close_array(b, c);
1878 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1879 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1880 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1881 blobmsg_add_string_buffer(b);
1883 blobmsg_add_u8(b, "autoneg", !!ecmd.autoneg);
1890 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1892 const char *const counters[] = {
1893 "collisions", "rx_frame_errors", "tx_compressed",
1894 "multicast", "rx_length_errors", "tx_dropped",
1895 "rx_bytes", "rx_missed_errors", "tx_errors",
1896 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1897 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1898 "rx_dropped", "tx_aborted_errors", "tx_packets",
1899 "rx_errors", "tx_bytes", "tx_window_errors",
1900 "rx_fifo_errors", "tx_carrier_errors",
1907 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1908 stats_dir = open(buf, O_DIRECTORY);
1912 for (i = 0; i < ARRAY_SIZE(counters); i++)
1913 if (read_uint64_file(stats_dir, counters[i], &val))
1914 blobmsg_add_u64(b, counters[i], val);
1920 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1922 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1923 int alen = v4 ? 4 : 16;
1924 unsigned int flags = 0;
1925 struct ifaddrmsg ifa = {
1926 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1927 .ifa_prefixlen = addr->mask,
1928 .ifa_index = dev->ifindex,
1932 if (cmd == RTM_NEWADDR)
1933 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1935 msg = nlmsg_alloc_simple(cmd, flags);
1939 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1940 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1942 if (addr->broadcast)
1943 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1944 if (addr->point_to_point)
1945 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1947 time_t now = system_get_rtime();
1948 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1950 if (addr->preferred_until) {
1951 int64_t preferred = addr->preferred_until - now;
1954 else if (preferred > UINT32_MAX)
1955 preferred = UINT32_MAX;
1957 cinfo.ifa_prefered = preferred;
1960 if (addr->valid_until) {
1961 int64_t valid = addr->valid_until - now;
1966 else if (valid > UINT32_MAX)
1969 cinfo.ifa_valid = valid;
1972 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1974 if (cmd == RTM_NEWADDR && (addr->flags & DEVADDR_OFFLINK))
1975 nla_put_u32(msg, IFA_FLAGS, IFA_F_NOPREFIXROUTE);
1978 return system_rtnl_call(msg);
1981 int system_add_address(struct device *dev, struct device_addr *addr)
1983 return system_addr(dev, addr, RTM_NEWADDR);
1986 int system_del_address(struct device *dev, struct device_addr *addr)
1988 return system_addr(dev, addr, RTM_DELADDR);
1991 static int system_neigh(struct device *dev, struct device_neighbor *neighbor, int cmd)
1993 int alen = ((neighbor->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1994 unsigned int flags = 0;
1995 struct ndmsg ndm = {
1996 .ndm_family = (alen == 4) ? AF_INET : AF_INET6,
1997 .ndm_ifindex = dev->ifindex,
1998 .ndm_state = NUD_PERMANENT,
1999 .ndm_flags = (neighbor->proxy ? NTF_PROXY : 0) | (neighbor->router ? NTF_ROUTER : 0),
2003 if (cmd == RTM_NEWNEIGH)
2004 flags |= NLM_F_CREATE | NLM_F_REPLACE;
2006 msg = nlmsg_alloc_simple(cmd, flags);
2011 nlmsg_append(msg, &ndm, sizeof(ndm), 0);
2013 nla_put(msg, NDA_DST, alen, &neighbor->addr);
2014 if (neighbor->flags & DEVNEIGH_MAC)
2015 nla_put(msg, NDA_LLADDR, sizeof(neighbor->macaddr), &neighbor->macaddr);
2018 return system_rtnl_call(msg);
2021 int system_add_neighbor(struct device *dev, struct device_neighbor *neighbor)
2023 return system_neigh(dev, neighbor, RTM_NEWNEIGH);
2026 int system_del_neighbor(struct device *dev, struct device_neighbor *neighbor)
2028 return system_neigh(dev, neighbor, RTM_DELNEIGH);
2031 static int system_rt(struct device *dev, struct device_route *route, int cmd)
2033 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
2035 unsigned int flags = 0;
2038 have_gw = !!route->nexthop.in.s_addr;
2040 have_gw = route->nexthop.in6.s6_addr32[0] ||
2041 route->nexthop.in6.s6_addr32[1] ||
2042 route->nexthop.in6.s6_addr32[2] ||
2043 route->nexthop.in6.s6_addr32[3];
2045 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
2046 ? route->table : RT_TABLE_MAIN;
2048 struct rtmsg rtm = {
2049 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
2050 .rtm_dst_len = route->mask,
2051 .rtm_src_len = route->sourcemask,
2052 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
2053 .rtm_protocol = (route->flags & DEVROUTE_PROTO) ? route->proto : RTPROT_STATIC,
2054 .rtm_scope = RT_SCOPE_NOWHERE,
2055 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
2056 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
2060 if (cmd == RTM_NEWROUTE) {
2061 flags |= NLM_F_CREATE | NLM_F_REPLACE;
2063 if (!dev) { /* Add null-route */
2064 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
2065 rtm.rtm_type = RTN_UNREACHABLE;
2068 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
2071 if (route->flags & DEVROUTE_TYPE) {
2072 rtm.rtm_type = route->type;
2073 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
2074 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
2075 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
2076 rtm.rtm_table = RT_TABLE_LOCAL;
2079 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT) {
2080 rtm.rtm_scope = RT_SCOPE_HOST;
2081 } else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
2082 rtm.rtm_type == RTN_ANYCAST) {
2083 rtm.rtm_scope = RT_SCOPE_LINK;
2084 } else if (rtm.rtm_type == RTN_BLACKHOLE || rtm.rtm_type == RTN_UNREACHABLE ||
2085 rtm.rtm_type == RTN_PROHIBIT || rtm.rtm_type == RTN_FAILED_POLICY ||
2086 rtm.rtm_type == RTN_THROW) {
2087 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
2092 msg = nlmsg_alloc_simple(cmd, flags);
2096 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
2099 nla_put(msg, RTA_DST, alen, &route->addr);
2101 if (route->sourcemask) {
2102 if (rtm.rtm_family == AF_INET)
2103 nla_put(msg, RTA_PREFSRC, alen, &route->source);
2105 nla_put(msg, RTA_SRC, alen, &route->source);
2108 if (route->metric > 0)
2109 nla_put_u32(msg, RTA_PRIORITY, route->metric);
2112 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
2115 nla_put_u32(msg, RTA_OIF, dev->ifindex);
2118 nla_put_u32(msg, RTA_TABLE, table);
2120 if (route->flags & DEVROUTE_MTU) {
2121 struct nlattr *metrics;
2123 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
2124 goto nla_put_failure;
2126 nla_put_u32(msg, RTAX_MTU, route->mtu);
2128 nla_nest_end(msg, metrics);
2131 return system_rtnl_call(msg);
2138 int system_add_route(struct device *dev, struct device_route *route)
2140 return system_rt(dev, route, RTM_NEWROUTE);
2143 int system_del_route(struct device *dev, struct device_route *route)
2145 return system_rt(dev, route, RTM_DELROUTE);
2148 int system_flush_routes(void)
2150 const char *names[] = {
2151 "/proc/sys/net/ipv4/route/flush",
2152 "/proc/sys/net/ipv6/route/flush"
2156 for (i = 0; i < ARRAY_SIZE(names); i++) {
2157 fd = open(names[i], O_WRONLY);
2161 if (write(fd, "-1", 2)) {}
2167 bool system_resolve_rt_type(const char *type, unsigned int *id)
2169 return system_rtn_aton(type, id);
2172 bool system_resolve_rt_proto(const char *type, unsigned int *id)
2176 unsigned int n, proto = 256;
2177 n = strtoul(type, &e, 0);
2178 if (!*e && e != type)
2180 else if (!strcmp(type, "unspec"))
2181 proto = RTPROT_UNSPEC;
2182 else if (!strcmp(type, "kernel"))
2183 proto = RTPROT_KERNEL;
2184 else if (!strcmp(type, "boot"))
2185 proto = RTPROT_BOOT;
2186 else if (!strcmp(type, "static"))
2187 proto = RTPROT_STATIC;
2188 else if ((f = fopen("/etc/iproute2/rt_protos", "r")) != NULL) {
2189 while (fgets(buf, sizeof(buf) - 1, f) != NULL) {
2190 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
2193 n = strtoul(e, NULL, 10);
2194 e = strtok(NULL, " \t\n");
2196 if (e && !strcmp(e, type)) {
2211 bool system_resolve_rt_table(const char *name, unsigned int *id)
2215 unsigned int n, table = RT_TABLE_UNSPEC;
2217 /* first try to parse table as number */
2218 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
2221 /* handle well known aliases */
2222 else if (!strcmp(name, "default"))
2223 table = RT_TABLE_DEFAULT;
2224 else if (!strcmp(name, "main"))
2225 table = RT_TABLE_MAIN;
2226 else if (!strcmp(name, "local"))
2227 table = RT_TABLE_LOCAL;
2229 /* try to look up name in /etc/iproute2/rt_tables */
2230 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
2232 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
2234 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
2237 n = strtoul(e, NULL, 10);
2238 e = strtok(NULL, " \t\n");
2240 if (e && !strcmp(e, name))
2250 if (table == RT_TABLE_UNSPEC)
2257 bool system_is_default_rt_table(unsigned int id)
2259 return (id == RT_TABLE_MAIN);
2262 bool system_resolve_rpfilter(const char *filter, unsigned int *id)
2267 if (!strcmp(filter, "strict"))
2269 else if (!strcmp(filter, "loose"))
2272 n = strtoul(filter, &e, 0);
2273 if (*e || e == filter || n > 2)
2281 static int system_iprule(struct iprule *rule, int cmd)
2283 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
2286 struct rtmsg rtm = {
2287 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
2288 .rtm_protocol = RTPROT_STATIC,
2289 .rtm_scope = RT_SCOPE_UNIVERSE,
2290 .rtm_table = RT_TABLE_UNSPEC,
2291 .rtm_type = RTN_UNSPEC,
2295 if (cmd == RTM_NEWRULE)
2296 rtm.rtm_type = RTN_UNICAST;
2299 rtm.rtm_flags |= FIB_RULE_INVERT;
2301 if (rule->flags & IPRULE_SRC)
2302 rtm.rtm_src_len = rule->src_mask;
2304 if (rule->flags & IPRULE_DEST)
2305 rtm.rtm_dst_len = rule->dest_mask;
2307 if (rule->flags & IPRULE_TOS)
2308 rtm.rtm_tos = rule->tos;
2310 if (rule->flags & IPRULE_LOOKUP) {
2311 if (rule->lookup < 256)
2312 rtm.rtm_table = rule->lookup;
2315 if (rule->flags & IPRULE_ACTION)
2316 rtm.rtm_type = rule->action;
2317 else if (rule->flags & IPRULE_GOTO)
2318 rtm.rtm_type = FR_ACT_GOTO;
2319 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
2320 rtm.rtm_type = FR_ACT_NOP;
2322 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
2327 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
2329 if (rule->flags & IPRULE_IN)
2330 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
2332 if (rule->flags & IPRULE_OUT)
2333 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
2335 if (rule->flags & IPRULE_SRC)
2336 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
2338 if (rule->flags & IPRULE_DEST)
2339 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
2341 if (rule->flags & IPRULE_PRIORITY)
2342 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
2343 else if (cmd == RTM_NEWRULE)
2344 nla_put_u32(msg, FRA_PRIORITY, rule->order);
2346 if (rule->flags & IPRULE_FWMARK)
2347 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
2349 if (rule->flags & IPRULE_FWMASK)
2350 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
2352 if (rule->flags & IPRULE_LOOKUP) {
2353 if (rule->lookup >= 256)
2354 nla_put_u32(msg, FRA_TABLE, rule->lookup);
2357 if (rule->flags & IPRULE_SUP_PREFIXLEN)
2358 nla_put_u32(msg, FRA_SUPPRESS_PREFIXLEN, rule->sup_prefixlen);
2360 if (rule->flags & IPRULE_GOTO)
2361 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
2363 return system_rtnl_call(msg);
2366 int system_add_iprule(struct iprule *rule)
2368 return system_iprule(rule, RTM_NEWRULE);
2371 int system_del_iprule(struct iprule *rule)
2373 return system_iprule(rule, RTM_DELRULE);
2376 int system_flush_iprules(void)
2381 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
2382 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
2384 memset(&rule, 0, sizeof(rule));
2387 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2390 rule.lookup = RT_TABLE_LOCAL;
2391 rv |= system_iprule(&rule, RTM_NEWRULE);
2393 rule.priority = 32766;
2394 rule.lookup = RT_TABLE_MAIN;
2395 rv |= system_iprule(&rule, RTM_NEWRULE);
2397 rule.priority = 32767;
2398 rule.lookup = RT_TABLE_DEFAULT;
2399 rv |= system_iprule(&rule, RTM_NEWRULE);
2402 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2405 rule.lookup = RT_TABLE_LOCAL;
2406 rv |= system_iprule(&rule, RTM_NEWRULE);
2408 rule.priority = 32766;
2409 rule.lookup = RT_TABLE_MAIN;
2410 rv |= system_iprule(&rule, RTM_NEWRULE);
2415 bool system_resolve_iprule_action(const char *action, unsigned int *id)
2417 return system_rtn_aton(action, id);
2420 time_t system_get_rtime(void)
2425 if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
2428 if (gettimeofday(&tv, NULL) == 0)
2435 #define IP_DF 0x4000
2438 static int tunnel_ioctl(const char *name, int cmd, void *p)
2442 memset(&ifr, 0, sizeof(ifr));
2443 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name) - 1);
2444 ifr.ifr_ifru.ifru_data = p;
2445 return ioctl(sock_ioctl, cmd, &ifr);
2448 #ifdef IFLA_IPTUN_MAX
2449 static int system_add_ip6_tunnel(const char *name, const unsigned int link,
2450 struct blob_attr **tb)
2452 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2453 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2454 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2455 struct blob_attr *cur;
2456 int ret = 0, ttl = 0;
2461 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2462 nla_put_string(nlm, IFLA_IFNAME, name);
2465 nla_put_u32(nlm, IFLA_LINK, link);
2467 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2473 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2474 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2481 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2483 if ((cur = tb[TUNNEL_ATTR_TTL]))
2484 ttl = blobmsg_get_u32(cur);
2486 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2487 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2489 struct in6_addr in6buf;
2490 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2491 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2495 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2498 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2499 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2503 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2506 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2507 struct blob_attr *tb_data[__IPIP6_DATA_ATTR_MAX];
2508 uint32_t tun_flags = IP6_TNL_F_IGN_ENCAP_LIMIT;
2510 blobmsg_parse(ipip6_data_attr_list.params, __IPIP6_DATA_ATTR_MAX, tb_data,
2511 blobmsg_data(cur), blobmsg_len(cur));
2513 if ((cur = tb_data[IPIP6_DATA_ENCAPLIMIT])) {
2514 char *str = blobmsg_get_string(cur);
2516 if (strcmp(str, "ignore")) {
2518 unsigned encap_limit = strtoul(str, &e, 0);
2520 if (e == str || *e || encap_limit > 255) {
2525 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, encap_limit);
2526 tun_flags &= ~IP6_TNL_F_IGN_ENCAP_LIMIT;
2530 #ifdef IFLA_IPTUN_FMR_MAX
2531 if ((cur = tb_data[IPIP6_DATA_FMRS])) {
2532 struct blob_attr *rcur;
2533 unsigned rrem, fmrcnt = 0;
2534 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2541 blobmsg_for_each_attr(rcur, cur, rrem) {
2542 struct blob_attr *tb_fmr[__FMR_DATA_ATTR_MAX], *tb_cur;
2543 struct in6_addr ip6prefix;
2544 struct in_addr ip4prefix;
2545 unsigned ip4len, ip6len, ealen, offset;
2547 blobmsg_parse(fmr_data_attr_list.params, __FMR_DATA_ATTR_MAX, tb_fmr,
2548 blobmsg_data(rcur), blobmsg_len(rcur));
2550 if (!(tb_cur = tb_fmr[FMR_DATA_PREFIX6]) ||
2551 !parse_ip_and_netmask(AF_INET6,
2552 blobmsg_data(tb_cur), &ip6prefix,
2558 if (!(tb_cur = tb_fmr[FMR_DATA_PREFIX4]) ||
2559 !parse_ip_and_netmask(AF_INET,
2560 blobmsg_data(tb_cur), &ip4prefix,
2566 if (!(tb_cur = tb_fmr[FMR_DATA_EALEN])) {
2570 ealen = blobmsg_get_u32(tb_cur);
2572 if (!(tb_cur = tb_fmr[FMR_DATA_OFFSET])) {
2576 offset = blobmsg_get_u32(tb_cur);
2578 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2584 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2585 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2586 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2587 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2588 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2589 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2591 nla_nest_end(nlm, rule);
2594 nla_nest_end(nlm, fmrs);
2598 nla_put_u32(nlm, IFLA_IPTUN_FLAGS, tun_flags);
2601 nla_nest_end(nlm, infodata);
2602 nla_nest_end(nlm, linkinfo);
2604 return system_rtnl_call(nlm);
2612 #ifdef IFLA_IPTUN_MAX
2613 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
2614 static int system_add_gre_tunnel(const char *name, const char *kind,
2615 const unsigned int link, struct blob_attr **tb, bool v6)
2618 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2619 struct blob_attr *cur;
2620 uint32_t ikey = 0, okey = 0, flowinfo = 0, flags6 = IP6_TNL_F_IGN_ENCAP_LIMIT;
2621 uint16_t iflags = 0, oflags = 0;
2623 int ret = 0, ttl = 0;
2624 unsigned encap_limit = 0;
2626 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2630 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2631 nla_put_string(nlm, IFLA_IFNAME, name);
2633 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2639 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2640 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2647 nla_put_u32(nlm, IFLA_GRE_LINK, link);
2649 if ((cur = tb[TUNNEL_ATTR_TTL]))
2650 ttl = blobmsg_get_u32(cur);
2652 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2653 char *str = blobmsg_get_string(cur);
2654 if (strcmp(str, "inherit")) {
2657 if (!system_tos_aton(str, &uval)) {
2663 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
2668 flags6 |= IP6_TNL_F_USE_ORIG_TCLASS;
2674 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2675 struct blob_attr *tb_data[__GRE_DATA_ATTR_MAX];
2677 blobmsg_parse(gre_data_attr_list.params, __GRE_DATA_ATTR_MAX, tb_data,
2678 blobmsg_data(cur), blobmsg_len(cur));
2680 if ((cur = tb_data[GRE_DATA_IKEY])) {
2681 if ((ikey = blobmsg_get_u32(cur)))
2685 if ((cur = tb_data[GRE_DATA_OKEY])) {
2686 if ((okey = blobmsg_get_u32(cur)))
2690 if ((cur = tb_data[GRE_DATA_ICSUM])) {
2691 if (blobmsg_get_bool(cur))
2695 if ((cur = tb_data[GRE_DATA_OCSUM])) {
2696 if (blobmsg_get_bool(cur))
2700 if ((cur = tb_data[GRE_DATA_ISEQNO])) {
2701 if (blobmsg_get_bool(cur))
2705 if ((cur = tb_data[GRE_DATA_OSEQNO])) {
2706 if (blobmsg_get_bool(cur))
2710 if ((cur = tb_data[GRE_DATA_ENCAPLIMIT])) {
2711 char *str = blobmsg_get_string(cur);
2713 if (strcmp(str, "ignore")) {
2716 encap_limit = strtoul(str, &e, 0);
2718 if (e == str || *e || encap_limit > 255) {
2723 flags6 &= ~IP6_TNL_F_IGN_ENCAP_LIMIT;
2729 struct in6_addr in6buf;
2730 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2731 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2735 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
2738 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2739 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2743 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
2746 if (!(flags6 & IP6_TNL_F_IGN_ENCAP_LIMIT))
2747 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, encap_limit);
2750 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
2753 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags6);
2758 struct in_addr inbuf;
2761 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2762 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2766 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
2769 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2770 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2774 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
2776 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
2778 okey = inbuf.s_addr;
2783 ikey = inbuf.s_addr;
2789 if ((cur = tb[TUNNEL_ATTR_DF]))
2790 set_df = blobmsg_get_bool(cur);
2793 /* ttl != 0 and nopmtudisc are incompatible */
2801 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
2803 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
2807 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
2810 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
2813 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
2816 nla_put_u32(nlm, IFLA_GRE_OKEY, htonl(okey));
2819 nla_put_u32(nlm, IFLA_GRE_IKEY, htonl(ikey));
2821 nla_nest_end(nlm, infodata);
2822 nla_nest_end(nlm, linkinfo);
2824 return system_rtnl_call(nlm);
2833 static int system_add_vti_tunnel(const char *name, const char *kind,
2834 const unsigned int link, struct blob_attr **tb, bool v6)
2837 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2838 struct blob_attr *cur;
2841 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2845 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2846 nla_put_string(nlm, IFLA_IFNAME, name);
2848 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2854 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2855 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2862 nla_put_u32(nlm, IFLA_VTI_LINK, link);
2865 struct in6_addr in6buf;
2866 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2867 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2871 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(in6buf), &in6buf);
2874 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2875 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2879 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(in6buf), &in6buf);
2883 struct in_addr inbuf;
2885 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2886 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2890 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(inbuf), &inbuf);
2893 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2894 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2898 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(inbuf), &inbuf);
2903 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2904 struct blob_attr *tb_data[__VTI_DATA_ATTR_MAX];
2905 uint32_t ikey = 0, okey = 0;
2907 blobmsg_parse(vti_data_attr_list.params, __VTI_DATA_ATTR_MAX, tb_data,
2908 blobmsg_data(cur), blobmsg_len(cur));
2910 if ((cur = tb_data[VTI_DATA_IKEY])) {
2911 if ((ikey = blobmsg_get_u32(cur)))
2912 nla_put_u32(nlm, IFLA_VTI_IKEY, htonl(ikey));
2915 if ((cur = tb_data[VTI_DATA_OKEY])) {
2916 if ((okey = blobmsg_get_u32(cur)))
2917 nla_put_u32(nlm, IFLA_VTI_OKEY, htonl(okey));
2921 nla_nest_end(nlm, infodata);
2922 nla_nest_end(nlm, linkinfo);
2924 return system_rtnl_call(nlm);
2932 #ifdef IFLA_XFRM_MAX
2933 static int system_add_xfrm_tunnel(const char *name, const char *kind,
2934 const unsigned int link, struct blob_attr **tb)
2937 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2938 struct blob_attr *cur;
2941 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2945 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2946 nla_put_string(nlm, IFLA_IFNAME, name);
2948 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2954 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2955 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2962 nla_put_u32(nlm, IFLA_XFRM_LINK, link);
2964 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2965 struct blob_attr *tb_data[__XFRM_DATA_ATTR_MAX];
2968 blobmsg_parse(xfrm_data_attr_list.params, __XFRM_DATA_ATTR_MAX, tb_data,
2969 blobmsg_data(cur), blobmsg_len(cur));
2971 if ((cur = tb_data[XFRM_DATA_IF_ID])) {
2972 if ((if_id = blobmsg_get_u32(cur)))
2973 nla_put_u32(nlm, IFLA_XFRM_IF_ID, if_id);
2978 nla_nest_end(nlm, infodata);
2979 nla_nest_end(nlm, linkinfo);
2981 return system_rtnl_call(nlm);
2989 #ifdef IFLA_VXLAN_MAX
2990 static int system_add_vxlan(const char *name, const unsigned int link, struct blob_attr **tb, bool v6)
2992 struct blob_attr *tb_data[__VXLAN_DATA_ATTR_MAX];
2994 struct nlattr *linkinfo, *data;
2995 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
2996 struct blob_attr *cur;
2999 if ((cur = tb[TUNNEL_ATTR_DATA]))
3000 blobmsg_parse(vxlan_data_attr_list.params, __VXLAN_DATA_ATTR_MAX, tb_data,
3001 blobmsg_data(cur), blobmsg_len(cur));
3005 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
3010 nlmsg_append(msg, &iim, sizeof(iim), 0);
3012 nla_put_string(msg, IFLA_IFNAME, name);
3014 if ((cur = tb_data[VXLAN_DATA_ATTR_MACADDR])) {
3015 struct ether_addr *ea = ether_aton(blobmsg_get_string(cur));
3021 nla_put(msg, IFLA_ADDRESS, ETH_ALEN, ea);
3024 if ((cur = tb[TUNNEL_ATTR_MTU])) {
3025 uint32_t mtu = blobmsg_get_u32(cur);
3026 nla_put_u32(msg, IFLA_MTU, mtu);
3029 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO))) {
3034 nla_put_string(msg, IFLA_INFO_KIND, "vxlan");
3036 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) {
3042 nla_put_u32(msg, IFLA_VXLAN_LINK, link);
3044 if ((cur = tb_data[VXLAN_DATA_ATTR_ID])) {
3045 uint32_t id = blobmsg_get_u32(cur);
3046 if (id >= (1u << 24) - 1) {
3051 nla_put_u32(msg, IFLA_VXLAN_ID, id);
3055 struct in6_addr in6buf;
3056 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
3057 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
3061 nla_put(msg, IFLA_VXLAN_LOCAL6, sizeof(in6buf), &in6buf);
3064 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
3065 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
3069 nla_put(msg, IFLA_VXLAN_GROUP6, sizeof(in6buf), &in6buf);
3072 struct in_addr inbuf;
3074 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
3075 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
3079 nla_put(msg, IFLA_VXLAN_LOCAL, sizeof(inbuf), &inbuf);
3082 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
3083 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
3087 nla_put(msg, IFLA_VXLAN_GROUP, sizeof(inbuf), &inbuf);
3091 uint32_t port = 4789;
3092 if ((cur = tb_data[VXLAN_DATA_ATTR_PORT])) {
3093 port = blobmsg_get_u32(cur);
3094 if (port < 1 || port > 65535) {
3099 nla_put_u16(msg, IFLA_VXLAN_PORT, htons(port));
3101 if ((cur = tb_data[VXLAN_DATA_ATTR_RXCSUM])) {
3102 bool rxcsum = blobmsg_get_bool(cur);
3103 nla_put_u8(msg, IFLA_VXLAN_UDP_ZERO_CSUM6_RX, !rxcsum);
3106 if ((cur = tb_data[VXLAN_DATA_ATTR_TXCSUM])) {
3107 bool txcsum = blobmsg_get_bool(cur);
3108 nla_put_u8(msg, IFLA_VXLAN_UDP_CSUM, txcsum);
3109 nla_put_u8(msg, IFLA_VXLAN_UDP_ZERO_CSUM6_TX, !txcsum);
3112 if ((cur = tb[TUNNEL_ATTR_TOS])) {
3113 char *str = blobmsg_get_string(cur);
3116 if (strcmp(str, "inherit")) {
3117 if (!system_tos_aton(str, &tos)) {
3123 nla_put_u8(msg, IFLA_VXLAN_TOS, tos);
3126 if ((cur = tb[TUNNEL_ATTR_TTL])) {
3127 uint32_t ttl = blobmsg_get_u32(cur);
3128 if (ttl < 1 || ttl > 255) {
3133 nla_put_u8(msg, IFLA_VXLAN_TTL, ttl);
3136 nla_nest_end(msg, data);
3137 nla_nest_end(msg, linkinfo);
3139 ret = system_rtnl_call(msg);
3141 D(SYSTEM, "Error adding vxlan '%s': %d\n", name, ret);
3151 static int system_add_sit_tunnel(const char *name, const unsigned int link, struct blob_attr **tb)
3153 struct blob_attr *cur;
3156 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
3160 if ((cur = tb[TUNNEL_ATTR_DATA])) {
3161 struct blob_attr *tb_data[__SIXRD_DATA_ATTR_MAX];
3163 struct ip_tunnel_6rd p6;
3165 blobmsg_parse(sixrd_data_attr_list.params, __SIXRD_DATA_ATTR_MAX, tb_data,
3166 blobmsg_data(cur), blobmsg_len(cur));
3168 memset(&p6, 0, sizeof(p6));
3170 if ((cur = tb_data[SIXRD_DATA_PREFIX])) {
3171 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
3172 &p6.prefix, &mask) || mask > 128) {
3177 p6.prefixlen = mask;
3180 if ((cur = tb_data[SIXRD_DATA_RELAY_PREFIX])) {
3181 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
3182 &p6.relay_prefix, &mask) || mask > 32) {
3187 p6.relay_prefixlen = mask;
3190 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
3200 __system_del_ip_tunnel(name, tb);
3204 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
3206 struct blob_attr *cur;
3208 struct ip_tunnel_parm p = {
3217 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
3218 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
3221 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
3222 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
3225 if ((cur = tb[TUNNEL_ATTR_DF]))
3226 set_df = blobmsg_get_bool(cur);
3228 if ((cur = tb[TUNNEL_ATTR_TTL]))
3229 p.iph.ttl = blobmsg_get_u32(cur);
3231 if ((cur = tb[TUNNEL_ATTR_TOS])) {
3232 char *str = blobmsg_get_string(cur);
3233 if (strcmp(str, "inherit")) {
3236 if (!system_tos_aton(str, &uval))
3244 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
3245 /* ttl !=0 and nopmtudisc are incompatible */
3246 if (p.iph.ttl && p.iph.frag_off == 0)
3249 strncpy(p.name, name, sizeof(p.name) - 1);
3251 switch (p.iph.protocol) {
3253 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
3255 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
3262 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
3264 struct blob_attr *cur;
3267 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
3269 str = blobmsg_data(cur);
3271 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
3272 !strcmp(str, "greip6") || !strcmp(str, "gretapip6") ||
3273 !strcmp(str, "vtiip") || !strcmp(str, "vtiip6") ||
3274 !strcmp(str, "vxlan") || !strcmp(str, "vxlan6") ||
3275 !strcmp(str, "xfrm"))
3276 return system_link_del(name);
3278 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
3281 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
3283 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
3285 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
3286 blob_data(attr), blob_len(attr));
3288 return __system_del_ip_tunnel(name, tb);
3291 int system_update_ipv6_mtu(struct device *dev, int mtu)
3297 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
3300 fd = open(buf, O_RDWR);
3305 ssize_t len = read(fd, buf, sizeof(buf) - 1);
3312 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) > 0)
3321 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
3323 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
3324 struct blob_attr *cur;
3327 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
3328 blob_data(attr), blob_len(attr));
3330 __system_del_ip_tunnel(name, tb);
3332 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
3334 str = blobmsg_data(cur);
3336 unsigned int ttl = 0;
3337 if ((cur = tb[TUNNEL_ATTR_TTL])) {
3338 ttl = blobmsg_get_u32(cur);
3343 unsigned int link = 0;
3344 if ((cur = tb[TUNNEL_ATTR_LINK])) {
3345 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
3349 if (iface->l3_dev.dev)
3350 link = iface->l3_dev.dev->ifindex;
3353 if (!strcmp(str, "sit"))
3354 return system_add_sit_tunnel(name, link, tb);
3355 #ifdef IFLA_IPTUN_MAX
3356 else if (!strcmp(str, "ipip6")) {
3357 return system_add_ip6_tunnel(name, link, tb);
3358 } else if (!strcmp(str, "greip")) {
3359 return system_add_gre_tunnel(name, "gre", link, tb, false);
3360 } else if (!strcmp(str, "gretapip")) {
3361 return system_add_gre_tunnel(name, "gretap", link, tb, false);
3362 } else if (!strcmp(str, "greip6")) {
3363 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
3364 } else if (!strcmp(str, "gretapip6")) {
3365 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
3367 } else if (!strcmp(str, "vtiip")) {
3368 return system_add_vti_tunnel(name, "vti", link, tb, false);
3369 } else if (!strcmp(str, "vtiip6")) {
3370 return system_add_vti_tunnel(name, "vti6", link, tb, true);
3372 #ifdef IFLA_XFRM_MAX
3373 } else if (!strcmp(str, "xfrm")) {
3374 return system_add_xfrm_tunnel(name, "xfrm", link, tb);
3376 #ifdef IFLA_VXLAN_MAX
3377 } else if(!strcmp(str, "vxlan")) {
3378 return system_add_vxlan(name, link, tb, false);
3379 } else if(!strcmp(str, "vxlan6")) {
3380 return system_add_vxlan(name, link, tb, true);
3383 } else if (!strcmp(str, "ipip")) {
3384 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);