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>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2
11 * as published by the Free Software Foundation
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
20 #include <sys/socket.h>
21 #include <sys/ioctl.h>
23 #include <sys/syscall.h>
26 #include <net/if_arp.h>
28 #include <arpa/inet.h>
29 #include <netinet/ether.h>
30 #include <netinet/in.h>
32 #include <linux/rtnetlink.h>
33 #include <linux/sockios.h>
35 #include <linux/if_addr.h>
36 #include <linux/if_link.h>
37 #include <linux/if_vlan.h>
38 #include <linux/if_bridge.h>
39 #include <linux/if_tunnel.h>
40 #include <linux/ip6_tunnel.h>
41 #include <linux/ethtool.h>
42 #include <linux/fib_rules.h>
43 #include <linux/veth.h>
44 #include <linux/version.h>
46 #ifndef RTN_FAILED_POLICY
47 #define RTN_FAILED_POLICY 12
50 #ifndef IFA_F_NOPREFIXROUTE
51 #define IFA_F_NOPREFIXROUTE 0x200
55 #define IFA_FLAGS (IFA_MULTICAST + 1)
64 #include <netlink/msg.h>
65 #include <netlink/attr.h>
66 #include <netlink/socket.h>
67 #include <libubox/uloop.h>
74 struct uloop_fd uloop;
79 static int sock_ioctl = -1;
80 static struct nl_sock *sock_rtnl = NULL;
82 static int cb_rtnl_event(struct nl_msg *msg, void *arg);
83 static void handle_hotplug_event(struct uloop_fd *u, unsigned int events);
85 static char dev_buf[256];
88 handler_nl_event(struct uloop_fd *u, unsigned int events)
90 struct event_socket *ev = container_of(u, struct event_socket, uloop);
92 socklen_t errlen = sizeof(err);
95 nl_recvmsgs_default(ev->sock);
99 if (getsockopt(u->fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen))
104 // Increase rx buffer size on netlink socket
106 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
109 // Request full dump since some info got dropped
110 struct rtgenmsg msg = { .rtgen_family = AF_UNSPEC };
111 nl_send_simple(ev->sock, RTM_GETLINK, NLM_F_DUMP, &msg, sizeof(msg));
121 uloop_fd_delete(&ev->uloop);
125 static struct nl_sock *
126 create_socket(int protocol, int groups)
128 struct nl_sock *sock;
130 sock = nl_socket_alloc();
135 nl_join_groups(sock, groups);
137 if (nl_connect(sock, protocol))
144 create_raw_event_socket(struct event_socket *ev, int protocol, int groups,
145 uloop_fd_handler cb, int flags)
147 ev->sock = create_socket(protocol, groups);
151 ev->uloop.fd = nl_socket_get_fd(ev->sock);
153 if (uloop_fd_add(&ev->uloop, ULOOP_READ|flags))
160 create_event_socket(struct event_socket *ev, int protocol,
161 int (*cb)(struct nl_msg *msg, void *arg))
163 if (!create_raw_event_socket(ev, protocol, 0, handler_nl_event, ULOOP_ERROR_CB))
166 // Install the valid custom callback handler
167 nl_socket_modify_cb(ev->sock, NL_CB_VALID, NL_CB_CUSTOM, cb, NULL);
169 // Disable sequence number checking on event sockets
170 nl_socket_disable_seq_check(ev->sock);
172 // Increase rx buffer size to 65K on event sockets
174 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
181 system_rtn_aton(const char *src, unsigned int *dst)
186 if (!strcmp(src, "local"))
188 else if (!strcmp(src, "nat"))
190 else if (!strcmp(src, "broadcast"))
192 else if (!strcmp(src, "anycast"))
194 else if (!strcmp(src, "multicast"))
196 else if (!strcmp(src, "prohibit"))
198 else if (!strcmp(src, "unreachable"))
200 else if (!strcmp(src, "blackhole"))
202 else if (!strcmp(src, "xresolve"))
204 else if (!strcmp(src, "unicast"))
206 else if (!strcmp(src, "throw"))
208 else if (!strcmp(src, "failed_policy"))
209 n = RTN_FAILED_POLICY;
211 n = strtoul(src, &e, 0);
212 if (!e || *e || e == src || n > 255)
221 system_tos_aton(const char *src, unsigned *dst)
225 *dst = strtoul(src, &e, 16);
226 if (e == src || *e || *dst > 255)
232 int system_init(void)
234 static struct event_socket rtnl_event;
235 static struct event_socket hotplug_event;
237 sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0);
238 system_fd_set_cloexec(sock_ioctl);
240 // Prepare socket for routing / address control
241 sock_rtnl = create_socket(NETLINK_ROUTE, 0);
245 if (!create_event_socket(&rtnl_event, NETLINK_ROUTE, cb_rtnl_event))
248 if (!create_raw_event_socket(&hotplug_event, NETLINK_KOBJECT_UEVENT, 1,
249 handle_hotplug_event, 0))
252 // Receive network link events form kernel
253 nl_socket_add_membership(rtnl_event.sock, RTNLGRP_LINK);
258 static void system_set_sysctl(const char *path, const char *val)
262 fd = open(path, O_WRONLY);
266 if (write(fd, val, strlen(val))) {}
270 static void system_set_dev_sysctl(const char *path, const char *device, const char *val)
272 snprintf(dev_buf, sizeof(dev_buf), path, device);
273 system_set_sysctl(dev_buf, val);
276 static void system_set_disable_ipv6(struct device *dev, const char *val)
278 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val);
281 static void system_set_rpfilter(struct device *dev, const char *val)
283 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter", dev->ifname, val);
286 static void system_set_acceptlocal(struct device *dev, const char *val)
288 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local", dev->ifname, val);
291 static void system_set_igmpversion(struct device *dev, const char *val)
293 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version", dev->ifname, val);
296 static void system_set_mldversion(struct device *dev, const char *val)
298 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version", dev->ifname, val);
301 static void system_set_neigh4reachabletime(struct device *dev, const char *val)
303 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms", dev->ifname, val);
306 static void system_set_neigh6reachabletime(struct device *dev, const char *val)
308 system_set_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms", dev->ifname, val);
311 static void system_set_neigh4gcstaletime(struct device *dev, const char *val)
313 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/gc_stale_time", dev->ifname, val);
316 static void system_set_neigh6gcstaletime(struct device *dev, const char *val)
318 system_set_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/gc_stale_time", dev->ifname, val);
321 static void system_set_neigh4locktime(struct device *dev, const char *val)
323 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/locktime", dev->ifname, val);
326 static void system_set_dadtransmits(struct device *dev, const char *val)
328 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits", dev->ifname, val);
331 static void system_bridge_set_multicast_to_unicast(struct device *dev, const char *val)
333 system_set_dev_sysctl("/sys/class/net/%s/brport/multicast_to_unicast", dev->ifname, val);
336 static void system_bridge_set_multicast_fast_leave(struct device *dev, const char *val)
338 system_set_dev_sysctl("/sys/class/net/%s/brport/multicast_fast_leave", dev->ifname, val);
341 static void system_bridge_set_hairpin_mode(struct device *dev, const char *val)
343 system_set_dev_sysctl("/sys/class/net/%s/brport/hairpin_mode", dev->ifname, val);
346 static void system_bridge_set_multicast_router(struct device *dev, const char *val, bool bridge)
348 system_set_dev_sysctl(bridge ? "/sys/class/net/%s/bridge/multicast_router" :
349 "/sys/class/net/%s/brport/multicast_router",
353 static void system_bridge_set_robustness(struct device *dev, const char *val)
355 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_startup_query_count",
357 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_last_member_count",
361 static void system_bridge_set_query_interval(struct device *dev, const char *val)
363 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_query_interval",
367 static void system_bridge_set_query_response_interval(struct device *dev, const char *val)
369 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_query_response_interval",
373 static void system_bridge_set_last_member_interval(struct device *dev, const char *val)
375 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_last_member_interval",
379 static void system_bridge_set_membership_interval(struct device *dev, const char *val)
381 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_membership_interval",
385 static void system_bridge_set_other_querier_timeout(struct device *dev, const char *val)
387 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier_interval",
391 static void system_bridge_set_startup_query_interval(struct device *dev, const char *val)
393 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_startup_query_interval",
397 static void system_bridge_set_learning(struct device *dev, const char *val)
399 system_set_dev_sysctl("/sys/class/net/%s/brport/learning", dev->ifname, val);
402 static void system_bridge_set_unicast_flood(struct device *dev, const char *val)
404 system_set_dev_sysctl("/sys/class/net/%s/brport/unicast_flood", dev->ifname, val);
407 static void system_set_sendredirects(struct device *dev, const char *val)
409 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/send_redirects", dev->ifname, val);
412 static int system_get_sysctl(const char *path, char *buf, const size_t buf_sz)
414 int fd = -1, ret = -1;
416 fd = open(path, O_RDONLY);
420 ssize_t len = read(fd, buf, buf_sz - 1);
434 system_get_dev_sysctl(const char *path, const char *device, char *buf, const size_t buf_sz)
436 snprintf(dev_buf, sizeof(dev_buf), path, device);
437 return system_get_sysctl(dev_buf, buf, buf_sz);
440 static int system_get_disable_ipv6(struct device *dev, char *buf, const size_t buf_sz)
442 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6",
443 dev->ifname, buf, buf_sz);
446 static int system_get_rpfilter(struct device *dev, char *buf, const size_t buf_sz)
448 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter",
449 dev->ifname, buf, buf_sz);
452 static int system_get_acceptlocal(struct device *dev, char *buf, const size_t buf_sz)
454 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local",
455 dev->ifname, buf, buf_sz);
458 static int system_get_igmpversion(struct device *dev, char *buf, const size_t buf_sz)
460 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version",
461 dev->ifname, buf, buf_sz);
464 static int system_get_mldversion(struct device *dev, char *buf, const size_t buf_sz)
466 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version",
467 dev->ifname, buf, buf_sz);
470 static int system_get_neigh4reachabletime(struct device *dev, char *buf, const size_t buf_sz)
472 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms",
473 dev->ifname, buf, buf_sz);
476 static int system_get_neigh6reachabletime(struct device *dev, char *buf, const size_t buf_sz)
478 return system_get_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms",
479 dev->ifname, buf, buf_sz);
482 static int system_get_neigh4gcstaletime(struct device *dev, char *buf, const size_t buf_sz)
484 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/gc_stale_time",
485 dev->ifname, buf, buf_sz);
488 static int system_get_neigh6gcstaletime(struct device *dev, char *buf, const size_t buf_sz)
490 return system_get_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/gc_stale_time",
491 dev->ifname, buf, buf_sz);
494 static int system_get_neigh4locktime(struct device *dev, char *buf, const size_t buf_sz)
496 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/locktime",
497 dev->ifname, buf, buf_sz);
500 static int system_get_dadtransmits(struct device *dev, char *buf, const size_t buf_sz)
502 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits",
503 dev->ifname, buf, buf_sz);
506 static int system_get_sendredirects(struct device *dev, char *buf, const size_t buf_sz)
508 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/send_redirects",
509 dev->ifname, buf, buf_sz);
512 // Evaluate netlink messages
513 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
515 struct nlmsghdr *nh = nlmsg_hdr(msg);
516 struct nlattr *nla[__IFLA_MAX];
520 if (nh->nlmsg_type != RTM_NEWLINK)
523 nlmsg_parse(nh, sizeof(struct ifinfomsg), nla, __IFLA_MAX - 1, NULL);
524 if (!nla[IFLA_IFNAME])
527 struct device *dev = device_find(nla_data(nla[IFLA_IFNAME]));
531 if (!system_get_dev_sysctl("/sys/class/net/%s/carrier", dev->ifname, buf, sizeof(buf)))
532 link_state = strtoul(buf, NULL, 0);
534 device_set_link(dev, link_state ? true : false);
541 handle_hotplug_msg(char *data, int size)
543 const char *subsystem = NULL, *interface = NULL;
544 char *cur, *end, *sep;
549 if (!strncmp(data, "add@", 4))
551 else if (!strncmp(data, "remove@", 7))
556 skip = strlen(data) + 1;
559 for (cur = data + skip; cur < end; cur += skip) {
560 skip = strlen(cur) + 1;
562 sep = strchr(cur, '=');
567 if (!strcmp(cur, "INTERFACE"))
569 else if (!strcmp(cur, "SUBSYSTEM")) {
571 if (strcmp(subsystem, "net") != 0)
574 if (subsystem && interface)
580 dev = device_find(interface);
584 if (dev->type != &simple_device_type)
587 if (add && system_if_force_external(dev->ifname))
590 device_set_present(dev, add);
594 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
596 struct event_socket *ev = container_of(u, struct event_socket, uloop);
597 struct sockaddr_nl nla;
598 unsigned char *buf = NULL;
601 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
603 handle_hotplug_msg((char *) buf, size);
609 static int system_rtnl_call(struct nl_msg *msg)
613 ret = nl_send_auto_complete(sock_rtnl, msg);
619 return nl_wait_for_ack(sock_rtnl);
622 int system_bridge_delbr(struct device *bridge)
624 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
627 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
631 memset(&ifr, 0, sizeof(ifr));
633 ifr.ifr_ifindex = dev->ifindex;
636 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
637 return ioctl(sock_ioctl, cmd, &ifr);
640 static bool system_is_bridge(const char *name, char *buf, int buflen)
644 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
645 if (stat(buf, &st) < 0)
651 static char *system_get_bridge(const char *name, char *buf, int buflen)
657 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
658 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
662 len = readlink(gl.gl_pathv[0], buf, buflen);
670 path = strrchr(buf, '/');
678 system_bridge_set_wireless(struct device *bridge, struct device *dev)
680 bool mcast_to_ucast = dev->wireless_ap;
683 if (bridge->settings.flags & DEV_OPT_MULTICAST_TO_UNICAST &&
684 !bridge->settings.multicast_to_unicast)
685 mcast_to_ucast = false;
687 if (!mcast_to_ucast || dev->wireless_isolate)
690 system_bridge_set_multicast_to_unicast(dev, mcast_to_ucast ? "1" : "0");
691 system_bridge_set_hairpin_mode(dev, hairpin ? "1" : "0");
694 int system_bridge_addif(struct device *bridge, struct device *dev)
700 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
701 if (!oldbr || strcmp(oldbr, bridge->ifname) != 0)
702 ret = system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
705 system_bridge_set_wireless(bridge, dev);
707 if (dev->settings.flags & DEV_OPT_MULTICAST_ROUTER) {
708 snprintf(buf, sizeof(buf), "%i", dev->settings.multicast_router);
709 system_bridge_set_multicast_router(dev, buf, false);
712 if (dev->settings.flags & DEV_OPT_MULTICAST_FAST_LEAVE &&
713 dev->settings.multicast_fast_leave)
714 system_bridge_set_multicast_fast_leave(dev, "1");
716 if (dev->settings.flags & DEV_OPT_LEARNING &&
717 !dev->settings.learning)
718 system_bridge_set_learning(dev, "0");
720 if (dev->settings.flags & DEV_OPT_UNICAST_FLOOD &&
721 !dev->settings.unicast_flood)
722 system_bridge_set_unicast_flood(dev, "0");
727 int system_bridge_delif(struct device *bridge, struct device *dev)
729 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
732 int system_if_resolve(struct device *dev)
735 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
736 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
737 return ifr.ifr_ifindex;
742 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
746 memset(&ifr, 0, sizeof(ifr));
747 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
748 ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
749 ifr.ifr_flags |= add;
750 ifr.ifr_flags &= ~rem;
751 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
763 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
765 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
767 return ifa->ifa_index == ifindex;
770 static bool check_route(struct nlmsghdr *hdr, int ifindex)
772 struct rtmsg *r = NLMSG_DATA(hdr);
773 struct nlattr *tb[__RTA_MAX];
775 if (r->rtm_protocol == RTPROT_KERNEL &&
776 r->rtm_family == AF_INET6)
779 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
783 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
786 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
791 static int cb_clear_event(struct nl_msg *msg, void *arg)
793 struct clear_data *clr = arg;
794 struct nlmsghdr *hdr = nlmsg_hdr(msg);
795 bool (*cb)(struct nlmsghdr *, int ifindex);
801 if (hdr->nlmsg_type != RTM_NEWADDR)
808 if (hdr->nlmsg_type != RTM_NEWROUTE)
815 if (hdr->nlmsg_type != RTM_NEWRULE)
824 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
827 if (type == RTM_DELRULE)
828 D(SYSTEM, "Remove a rule\n");
830 D(SYSTEM, "Remove %s from device %s\n",
831 type == RTM_DELADDR ? "an address" : "a route",
833 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
834 hdr = nlmsg_hdr(clr->msg);
835 hdr->nlmsg_type = type;
836 hdr->nlmsg_flags = NLM_F_REQUEST;
838 nl_socket_disable_auto_ack(sock_rtnl);
839 nl_send_auto_complete(sock_rtnl, clr->msg);
840 nl_socket_enable_auto_ack(sock_rtnl);
846 cb_finish_event(struct nl_msg *msg, void *arg)
854 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
857 *pending = err->error;
862 system_if_clear_entries(struct device *dev, int type, int af)
864 struct clear_data clr;
865 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
868 .rtm_flags = RTM_F_CLONED,
870 int flags = NLM_F_DUMP;
879 clr.size = sizeof(struct rtgenmsg);
882 clr.size = sizeof(struct rtmsg);
891 clr.msg = nlmsg_alloc_simple(type, flags);
895 nlmsg_append(clr.msg, &rtm, clr.size, 0);
896 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
897 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
898 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
900 nl_send_auto_complete(sock_rtnl, clr.msg);
902 nl_recvmsgs(sock_rtnl, cb);
910 * Clear bridge (membership) state and bring down device
912 void system_if_clear_state(struct device *dev)
914 static char buf[256];
917 device_set_ifindex(dev, system_if_resolve(dev));
918 if (dev->external || !dev->ifindex)
921 system_if_flags(dev->ifname, 0, IFF_UP);
923 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
924 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
925 system_bridge_delbr(dev);
929 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
931 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
932 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
935 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
936 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
937 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
938 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
939 system_set_disable_ipv6(dev, "0");
942 static inline unsigned long
943 sec_to_jiffies(int val)
945 return (unsigned long) val * 100;
948 static void system_bridge_conf_multicast_deps(struct device *bridge,
949 struct bridge_config *cfg,
955 if (cfg->flags & BRIDGE_OPT_ROBUSTNESS ||
956 cfg->flags & BRIDGE_OPT_QUERY_INTERVAL ||
957 cfg->flags & BRIDGE_OPT_QUERY_RESPONSE_INTERVAL) {
958 val = cfg->robustness * cfg->query_interval +
959 cfg->query_response_interval;
961 snprintf(buf, buf_len, "%i", val);
962 system_bridge_set_membership_interval(bridge, buf);
964 val = cfg->robustness * cfg->query_interval +
965 cfg->query_response_interval / 2;
967 snprintf(buf, buf_len, "%i", val);
968 system_bridge_set_other_querier_timeout(bridge, buf);
971 if (cfg->flags & BRIDGE_OPT_QUERY_INTERVAL) {
972 val = cfg->query_interval / 4;
974 snprintf(buf, buf_len, "%i", val);
975 system_bridge_set_startup_query_interval(bridge, buf);
979 static void system_bridge_conf_multicast(struct device *bridge,
980 struct bridge_config *cfg,
984 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
985 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
987 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier",
988 bridge->ifname, cfg->multicast_querier ? "1" : "0");
990 snprintf(buf, buf_len, "%i", cfg->hash_max);
991 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/hash_max",
992 bridge->ifname, buf);
994 if (bridge->settings.flags & DEV_OPT_MULTICAST_ROUTER) {
995 snprintf(buf, buf_len, "%i", bridge->settings.multicast_router);
996 system_bridge_set_multicast_router(bridge, buf, true);
999 if (cfg->flags & BRIDGE_OPT_ROBUSTNESS) {
1000 snprintf(buf, buf_len, "%i", cfg->robustness);
1001 system_bridge_set_robustness(bridge, buf);
1004 if (cfg->flags & BRIDGE_OPT_QUERY_INTERVAL) {
1005 snprintf(buf, buf_len, "%i", cfg->query_interval);
1006 system_bridge_set_query_interval(bridge, buf);
1009 if (cfg->flags & BRIDGE_OPT_QUERY_RESPONSE_INTERVAL) {
1010 snprintf(buf, buf_len, "%i", cfg->query_response_interval);
1011 system_bridge_set_query_response_interval(bridge, buf);
1014 if (cfg->flags & BRIDGE_OPT_LAST_MEMBER_INTERVAL) {
1015 snprintf(buf, buf_len, "%i", cfg->last_member_interval);
1016 system_bridge_set_last_member_interval(bridge, buf);
1019 system_bridge_conf_multicast_deps(bridge, cfg, buf, buf_len);
1022 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
1025 unsigned long args[4] = {};
1027 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
1030 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
1031 args[1] = !!cfg->stp;
1032 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1034 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
1035 args[1] = sec_to_jiffies(cfg->forward_delay);
1036 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1038 system_bridge_conf_multicast(bridge, cfg, buf, sizeof(buf));
1040 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
1041 args[1] = cfg->priority;
1042 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1044 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
1045 args[0] = BRCTL_SET_AGEING_TIME;
1046 args[1] = sec_to_jiffies(cfg->ageing_time);
1047 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1050 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
1051 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
1052 args[1] = sec_to_jiffies(cfg->hello_time);
1053 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1056 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
1057 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
1058 args[1] = sec_to_jiffies(cfg->max_age);
1059 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1065 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
1068 struct nlattr *linkinfo, *data;
1069 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
1071 static const struct {
1073 enum macvlan_mode val;
1075 { "private", MACVLAN_MODE_PRIVATE },
1076 { "vepa", MACVLAN_MODE_VEPA },
1077 { "bridge", MACVLAN_MODE_BRIDGE },
1078 { "passthru", MACVLAN_MODE_PASSTHRU },
1081 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1086 nlmsg_append(msg, &iim, sizeof(iim), 0);
1088 if (cfg->flags & MACVLAN_OPT_MACADDR)
1089 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
1090 nla_put_string(msg, IFLA_IFNAME, macvlan->ifname);
1091 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
1093 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1094 goto nla_put_failure;
1096 nla_put_string(msg, IFLA_INFO_KIND, "macvlan");
1098 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1099 goto nla_put_failure;
1102 for (i = 0; i < ARRAY_SIZE(modes); i++) {
1103 if (strcmp(cfg->mode, modes[i].name) != 0)
1106 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
1111 nla_nest_end(msg, data);
1112 nla_nest_end(msg, linkinfo);
1114 rv = system_rtnl_call(msg);
1116 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
1125 static int system_link_del(const char *ifname)
1128 struct ifinfomsg iim = {
1129 .ifi_family = AF_UNSPEC,
1133 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
1138 nlmsg_append(msg, &iim, sizeof(iim), 0);
1139 nla_put_string(msg, IFLA_IFNAME, ifname);
1140 return system_rtnl_call(msg);
1143 int system_macvlan_del(struct device *macvlan)
1145 return system_link_del(macvlan->ifname);
1148 int system_veth_add(struct device *veth, struct veth_config *cfg)
1151 struct ifinfomsg empty_iim = {};
1152 struct nlattr *linkinfo, *data, *veth_info;
1155 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1160 nlmsg_append(msg, &empty_iim, sizeof(empty_iim), 0);
1162 if (cfg->flags & VETH_OPT_MACADDR)
1163 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
1164 nla_put_string(msg, IFLA_IFNAME, veth->ifname);
1166 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1167 goto nla_put_failure;
1169 nla_put_string(msg, IFLA_INFO_KIND, "veth");
1171 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1172 goto nla_put_failure;
1174 if (!(veth_info = nla_nest_start(msg, VETH_INFO_PEER)))
1175 goto nla_put_failure;
1177 nlmsg_append(msg, &empty_iim, sizeof(empty_iim), 0);
1179 if (cfg->flags & VETH_OPT_PEER_NAME)
1180 nla_put_string(msg, IFLA_IFNAME, cfg->peer_name);
1181 if (cfg->flags & VETH_OPT_PEER_MACADDR)
1182 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->peer_macaddr), cfg->peer_macaddr);
1184 nla_nest_end(msg, veth_info);
1185 nla_nest_end(msg, data);
1186 nla_nest_end(msg, linkinfo);
1188 rv = system_rtnl_call(msg);
1190 if (cfg->flags & VETH_OPT_PEER_NAME)
1191 D(SYSTEM, "Error adding veth '%s' with peer '%s': %d\n", veth->ifname, cfg->peer_name, rv);
1193 D(SYSTEM, "Error adding veth '%s': %d\n", veth->ifname, rv);
1203 int system_veth_del(struct device *veth)
1205 return system_link_del(veth->ifname);
1208 static int system_vlan(struct device *dev, int id)
1210 struct vlan_ioctl_args ifr = {
1211 .cmd = SET_VLAN_NAME_TYPE_CMD,
1212 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
1215 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
1218 ifr.cmd = DEL_VLAN_CMD;
1221 ifr.cmd = ADD_VLAN_CMD;
1224 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
1225 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
1228 int system_vlan_add(struct device *dev, int id)
1230 return system_vlan(dev, id);
1233 int system_vlan_del(struct device *dev)
1235 return system_vlan(dev, -1);
1238 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
1241 struct nlattr *linkinfo, *data;
1242 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
1245 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1250 nlmsg_append(msg, &iim, sizeof(iim), 0);
1251 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
1252 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
1254 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1255 goto nla_put_failure;
1257 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
1259 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1260 goto nla_put_failure;
1262 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
1264 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
1265 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
1267 if(cfg->proto == VLAN_PROTO_8021AD)
1268 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);
1271 nla_nest_end(msg, data);
1272 nla_nest_end(msg, linkinfo);
1274 rv = system_rtnl_call(msg);
1276 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
1285 int system_vlandev_del(struct device *vlandev)
1287 return system_link_del(vlandev->ifname);
1291 system_if_get_settings(struct device *dev, struct device_settings *s)
1296 memset(&ifr, 0, sizeof(ifr));
1297 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1299 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
1300 s->mtu = ifr.ifr_mtu;
1301 s->flags |= DEV_OPT_MTU;
1304 s->mtu6 = system_update_ipv6_mtu(dev, 0);
1306 s->flags |= DEV_OPT_MTU6;
1308 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
1309 s->txqueuelen = ifr.ifr_qlen;
1310 s->flags |= DEV_OPT_TXQUEUELEN;
1313 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
1314 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
1315 s->flags |= DEV_OPT_MACADDR;
1318 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
1319 s->ipv6 = !strtoul(buf, NULL, 0);
1320 s->flags |= DEV_OPT_IPV6;
1323 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
1324 s->promisc = ifr.ifr_flags & IFF_PROMISC;
1325 s->flags |= DEV_OPT_PROMISC;
1327 s->multicast = ifr.ifr_flags & IFF_MULTICAST;
1328 s->flags |= DEV_OPT_MULTICAST;
1331 if (!system_get_rpfilter(dev, buf, sizeof(buf))) {
1332 s->rpfilter = strtoul(buf, NULL, 0);
1333 s->flags |= DEV_OPT_RPFILTER;
1336 if (!system_get_acceptlocal(dev, buf, sizeof(buf))) {
1337 s->acceptlocal = strtoul(buf, NULL, 0);
1338 s->flags |= DEV_OPT_ACCEPTLOCAL;
1341 if (!system_get_igmpversion(dev, buf, sizeof(buf))) {
1342 s->igmpversion = strtoul(buf, NULL, 0);
1343 s->flags |= DEV_OPT_IGMPVERSION;
1346 if (!system_get_mldversion(dev, buf, sizeof(buf))) {
1347 s->mldversion = strtoul(buf, NULL, 0);
1348 s->flags |= DEV_OPT_MLDVERSION;
1351 if (!system_get_neigh4reachabletime(dev, buf, sizeof(buf))) {
1352 s->neigh4reachabletime = strtoul(buf, NULL, 0);
1353 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1356 if (!system_get_neigh6reachabletime(dev, buf, sizeof(buf))) {
1357 s->neigh6reachabletime = strtoul(buf, NULL, 0);
1358 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1361 if (!system_get_neigh4locktime(dev, buf, sizeof(buf))) {
1362 s->neigh4locktime = strtoul(buf, NULL, 0);
1363 s->flags |= DEV_OPT_NEIGHLOCKTIME;
1366 if (!system_get_neigh4gcstaletime(dev, buf, sizeof(buf))) {
1367 s->neigh4gcstaletime = strtoul(buf, NULL, 0);
1368 s->flags |= DEV_OPT_NEIGHGCSTALETIME;
1371 if (!system_get_neigh6gcstaletime(dev, buf, sizeof(buf))) {
1372 s->neigh6gcstaletime = strtoul(buf, NULL, 0);
1373 s->flags |= DEV_OPT_NEIGHGCSTALETIME;
1376 if (!system_get_dadtransmits(dev, buf, sizeof(buf))) {
1377 s->dadtransmits = strtoul(buf, NULL, 0);
1378 s->flags |= DEV_OPT_DADTRANSMITS;
1381 if (!system_get_sendredirects(dev, buf, sizeof(buf))) {
1382 s->sendredirects = strtoul(buf, NULL, 0);
1383 s->flags |= DEV_OPT_SENDREDIRECTS;
1388 system_if_set_rps_xps_val(const char *path, int val)
1394 if (glob(path, 0, NULL, &gl))
1397 snprintf(val_buf, sizeof(val_buf), "%x", val);
1398 for (i = 0; i < gl.gl_pathc; i++)
1399 system_set_sysctl(gl.gl_pathv[i], val_buf);
1405 system_if_apply_rps_xps(struct device *dev, struct device_settings *s)
1407 long n_cpus = sysconf(_SC_NPROCESSORS_ONLN);
1413 val = (1 << n_cpus) - 1;
1414 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/rps_cpus", dev->ifname);
1415 system_if_set_rps_xps_val(dev_buf, s->rps ? val : 0);
1417 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/xps_cpus", dev->ifname);
1418 system_if_set_rps_xps_val(dev_buf, s->xps ? val : 0);
1422 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
1427 memset(&ifr, 0, sizeof(ifr));
1428 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1429 if (s->flags & DEV_OPT_MTU & apply_mask) {
1430 ifr.ifr_mtu = s->mtu;
1431 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
1432 s->flags &= ~DEV_OPT_MTU;
1434 if (s->flags & DEV_OPT_MTU6 & apply_mask) {
1435 system_update_ipv6_mtu(dev, s->mtu6);
1437 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
1438 ifr.ifr_qlen = s->txqueuelen;
1439 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
1440 s->flags &= ~DEV_OPT_TXQUEUELEN;
1442 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
1443 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
1444 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
1445 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
1446 s->flags &= ~DEV_OPT_MACADDR;
1448 if (s->flags & DEV_OPT_IPV6 & apply_mask)
1449 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
1450 if (s->flags & DEV_OPT_PROMISC & apply_mask) {
1451 if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
1452 !s->promisc ? IFF_PROMISC : 0) < 0)
1453 s->flags &= ~DEV_OPT_PROMISC;
1455 if (s->flags & DEV_OPT_RPFILTER & apply_mask) {
1456 snprintf(buf, sizeof(buf), "%d", s->rpfilter);
1457 system_set_rpfilter(dev, buf);
1459 if (s->flags & DEV_OPT_ACCEPTLOCAL & apply_mask)
1460 system_set_acceptlocal(dev, s->acceptlocal ? "1" : "0");
1461 if (s->flags & DEV_OPT_IGMPVERSION & apply_mask) {
1462 snprintf(buf, sizeof(buf), "%d", s->igmpversion);
1463 system_set_igmpversion(dev, buf);
1465 if (s->flags & DEV_OPT_MLDVERSION & apply_mask) {
1466 snprintf(buf, sizeof(buf), "%d", s->mldversion);
1467 system_set_mldversion(dev, buf);
1469 if (s->flags & DEV_OPT_NEIGHREACHABLETIME & apply_mask) {
1470 snprintf(buf, sizeof(buf), "%d", s->neigh4reachabletime);
1471 system_set_neigh4reachabletime(dev, buf);
1472 snprintf(buf, sizeof(buf), "%d", s->neigh6reachabletime);
1473 system_set_neigh6reachabletime(dev, buf);
1475 if (s->flags & DEV_OPT_NEIGHLOCKTIME & apply_mask) {
1476 snprintf(buf, sizeof(buf), "%d", s->neigh4locktime);
1477 system_set_neigh4locktime(dev, buf);
1479 if (s->flags & DEV_OPT_NEIGHGCSTALETIME & apply_mask) {
1480 snprintf(buf, sizeof(buf), "%d", s->neigh4gcstaletime);
1481 system_set_neigh4gcstaletime(dev, buf);
1482 snprintf(buf, sizeof(buf), "%d", s->neigh6gcstaletime);
1483 system_set_neigh6gcstaletime(dev, buf);
1485 if (s->flags & DEV_OPT_DADTRANSMITS & apply_mask) {
1486 snprintf(buf, sizeof(buf), "%d", s->dadtransmits);
1487 system_set_dadtransmits(dev, buf);
1489 if (s->flags & DEV_OPT_MULTICAST & apply_mask) {
1490 if (system_if_flags(dev->ifname, s->multicast ? IFF_MULTICAST : 0,
1491 !s->multicast ? IFF_MULTICAST : 0) < 0)
1492 s->flags &= ~DEV_OPT_MULTICAST;
1494 if (s->flags & DEV_OPT_SENDREDIRECTS & apply_mask)
1495 system_set_sendredirects(dev, s->sendredirects ? "1" : "0");
1497 system_if_apply_rps_xps(dev, s);
1500 int system_if_up(struct device *dev)
1502 system_if_get_settings(dev, &dev->orig_settings);
1503 /* Only keep orig settings based on what needs to be set */
1504 dev->orig_settings.valid_flags = dev->orig_settings.flags;
1505 dev->orig_settings.flags &= dev->settings.flags;
1506 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
1507 return system_if_flags(dev->ifname, IFF_UP, 0);
1510 int system_if_down(struct device *dev)
1512 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
1513 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
1517 struct if_check_data {
1523 #ifndef IFF_LOWER_UP
1524 #define IFF_LOWER_UP 0x10000
1527 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1529 struct nlmsghdr *nh = nlmsg_hdr(msg);
1530 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1531 struct if_check_data *chk = (struct if_check_data *)arg;
1533 if (nh->nlmsg_type != RTM_NEWLINK)
1536 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1537 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1542 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1544 struct if_check_data *chk = (struct if_check_data *)arg;
1549 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1551 struct if_check_data *chk = (struct if_check_data *)arg;
1553 device_set_present(chk->dev, false);
1554 device_set_link(chk->dev, false);
1555 chk->pending = err->error;
1560 int system_if_check(struct device *dev)
1562 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1564 struct ifinfomsg ifi = {
1565 .ifi_family = AF_UNSPEC,
1568 struct if_check_data chk = {
1574 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1578 if (nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1579 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1582 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1583 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1584 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1586 nl_send_auto_complete(sock_rtnl, msg);
1587 while (chk.pending > 0)
1588 nl_recvmsgs(sock_rtnl, cb);
1600 system_if_get_parent(struct device *dev)
1602 char buf[64], *devname;
1603 int ifindex, iflink, len;
1606 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1607 f = fopen(buf, "r");
1611 len = fread(buf, 1, sizeof(buf) - 1, f);
1618 iflink = strtoul(buf, NULL, 0);
1619 ifindex = system_if_resolve(dev);
1620 if (!iflink || iflink == ifindex)
1623 devname = if_indextoname(iflink, buf);
1627 return device_get(devname, true);
1631 read_string_file(int dir_fd, const char *file, char *buf, int len)
1637 fd = openat(dir_fd, file, O_RDONLY);
1642 len = read(fd, buf, len - 1);
1646 } else if (len > 0) {
1649 c = strchr(buf, '\n');
1662 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1667 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1669 *val = strtoull(buf, NULL, 0);
1674 /* Assume advertised flags == supported flags */
1675 static const struct {
1678 } ethtool_link_modes[] = {
1679 { ADVERTISED_10baseT_Half, "10H" },
1680 { ADVERTISED_10baseT_Full, "10F" },
1681 { ADVERTISED_100baseT_Half, "100H" },
1682 { ADVERTISED_100baseT_Full, "100F" },
1683 { ADVERTISED_1000baseT_Half, "1000H" },
1684 { ADVERTISED_1000baseT_Full, "1000F" },
1687 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1690 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1691 if (mask & ethtool_link_modes[i].mask)
1692 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1697 system_if_force_external(const char *ifname)
1702 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1703 return stat(buf, &s) == 0;
1707 system_if_dump_info(struct device *dev, struct blob_buf *b)
1709 struct ethtool_cmd ecmd;
1715 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
1716 dir_fd = open(buf, O_DIRECTORY);
1718 memset(&ecmd, 0, sizeof(ecmd));
1719 memset(&ifr, 0, sizeof(ifr));
1720 strcpy(ifr.ifr_name, dev->ifname);
1721 ifr.ifr_data = (caddr_t) &ecmd;
1722 ecmd.cmd = ETHTOOL_GSET;
1724 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1725 c = blobmsg_open_array(b, "link-advertising");
1726 system_add_link_modes(b, ecmd.advertising);
1727 blobmsg_close_array(b, c);
1729 c = blobmsg_open_array(b, "link-supported");
1730 system_add_link_modes(b, ecmd.supported);
1731 blobmsg_close_array(b, c);
1733 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1734 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1735 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1736 blobmsg_add_string_buffer(b);
1744 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1746 const char *const counters[] = {
1747 "collisions", "rx_frame_errors", "tx_compressed",
1748 "multicast", "rx_length_errors", "tx_dropped",
1749 "rx_bytes", "rx_missed_errors", "tx_errors",
1750 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1751 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1752 "rx_dropped", "tx_aborted_errors", "tx_packets",
1753 "rx_errors", "tx_bytes", "tx_window_errors",
1754 "rx_fifo_errors", "tx_carrier_errors",
1761 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1762 stats_dir = open(buf, O_DIRECTORY);
1766 for (i = 0; i < ARRAY_SIZE(counters); i++)
1767 if (read_uint64_file(stats_dir, counters[i], &val))
1768 blobmsg_add_u64(b, counters[i], val);
1774 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1776 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1777 int alen = v4 ? 4 : 16;
1778 unsigned int flags = 0;
1779 struct ifaddrmsg ifa = {
1780 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1781 .ifa_prefixlen = addr->mask,
1782 .ifa_index = dev->ifindex,
1786 if (cmd == RTM_NEWADDR)
1787 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1789 msg = nlmsg_alloc_simple(cmd, flags);
1793 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1794 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1796 if (addr->broadcast)
1797 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1798 if (addr->point_to_point)
1799 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1801 time_t now = system_get_rtime();
1802 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1804 if (addr->preferred_until) {
1805 int64_t preferred = addr->preferred_until - now;
1808 else if (preferred > UINT32_MAX)
1809 preferred = UINT32_MAX;
1811 cinfo.ifa_prefered = preferred;
1814 if (addr->valid_until) {
1815 int64_t valid = addr->valid_until - now;
1820 else if (valid > UINT32_MAX)
1823 cinfo.ifa_valid = valid;
1826 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1828 if (cmd == RTM_NEWADDR && (addr->flags & DEVADDR_OFFLINK))
1829 nla_put_u32(msg, IFA_FLAGS, IFA_F_NOPREFIXROUTE);
1832 return system_rtnl_call(msg);
1835 int system_add_address(struct device *dev, struct device_addr *addr)
1837 return system_addr(dev, addr, RTM_NEWADDR);
1840 int system_del_address(struct device *dev, struct device_addr *addr)
1842 return system_addr(dev, addr, RTM_DELADDR);
1845 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1847 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1849 unsigned int flags = 0;
1852 have_gw = !!route->nexthop.in.s_addr;
1854 have_gw = route->nexthop.in6.s6_addr32[0] ||
1855 route->nexthop.in6.s6_addr32[1] ||
1856 route->nexthop.in6.s6_addr32[2] ||
1857 route->nexthop.in6.s6_addr32[3];
1859 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1860 ? route->table : RT_TABLE_MAIN;
1862 struct rtmsg rtm = {
1863 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1864 .rtm_dst_len = route->mask,
1865 .rtm_src_len = route->sourcemask,
1866 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1867 .rtm_protocol = (route->flags & DEVROUTE_PROTO) ? route->proto : RTPROT_STATIC,
1868 .rtm_scope = RT_SCOPE_NOWHERE,
1869 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1870 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1874 if (cmd == RTM_NEWROUTE) {
1875 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1877 if (!dev) { // Add null-route
1878 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1879 rtm.rtm_type = RTN_UNREACHABLE;
1882 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1885 if (route->flags & DEVROUTE_TYPE) {
1886 rtm.rtm_type = route->type;
1887 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
1888 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
1889 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
1890 rtm.rtm_table = RT_TABLE_LOCAL;
1893 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT) {
1894 rtm.rtm_scope = RT_SCOPE_HOST;
1895 } else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
1896 rtm.rtm_type == RTN_ANYCAST) {
1897 rtm.rtm_scope = RT_SCOPE_LINK;
1898 } else if (rtm.rtm_type == RTN_BLACKHOLE || rtm.rtm_type == RTN_UNREACHABLE ||
1899 rtm.rtm_type == RTN_PROHIBIT || rtm.rtm_type == RTN_FAILED_POLICY ||
1900 rtm.rtm_type == RTN_THROW) {
1901 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1906 msg = nlmsg_alloc_simple(cmd, flags);
1910 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1913 nla_put(msg, RTA_DST, alen, &route->addr);
1915 if (route->sourcemask) {
1916 if (rtm.rtm_family == AF_INET)
1917 nla_put(msg, RTA_PREFSRC, alen, &route->source);
1919 nla_put(msg, RTA_SRC, alen, &route->source);
1922 if (route->metric > 0)
1923 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1926 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1929 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1932 nla_put_u32(msg, RTA_TABLE, table);
1934 if (route->flags & DEVROUTE_MTU) {
1935 struct nlattr *metrics;
1937 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1938 goto nla_put_failure;
1940 nla_put_u32(msg, RTAX_MTU, route->mtu);
1942 nla_nest_end(msg, metrics);
1945 return system_rtnl_call(msg);
1952 int system_add_route(struct device *dev, struct device_route *route)
1954 return system_rt(dev, route, RTM_NEWROUTE);
1957 int system_del_route(struct device *dev, struct device_route *route)
1959 return system_rt(dev, route, RTM_DELROUTE);
1962 int system_flush_routes(void)
1964 const char *names[] = {
1965 "/proc/sys/net/ipv4/route/flush",
1966 "/proc/sys/net/ipv6/route/flush"
1970 for (i = 0; i < ARRAY_SIZE(names); i++) {
1971 fd = open(names[i], O_WRONLY);
1975 if (write(fd, "-1", 2)) {}
1981 bool system_resolve_rt_type(const char *type, unsigned int *id)
1983 return system_rtn_aton(type, id);
1986 bool system_resolve_rt_proto(const char *type, unsigned int *id)
1990 unsigned int n, proto = 256;
1991 n = strtoul(type, &e, 0);
1992 if (!*e && e != type)
1994 else if (!strcmp(type, "unspec"))
1995 proto = RTPROT_UNSPEC;
1996 else if (!strcmp(type, "kernel"))
1997 proto = RTPROT_KERNEL;
1998 else if (!strcmp(type, "boot"))
1999 proto = RTPROT_BOOT;
2000 else if (!strcmp(type, "static"))
2001 proto = RTPROT_STATIC;
2002 else if ((f = fopen("/etc/iproute2/rt_protos", "r")) != NULL) {
2003 while (fgets(buf, sizeof(buf) - 1, f) != NULL) {
2004 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
2007 n = strtoul(e, NULL, 10);
2008 e = strtok(NULL, " \t\n");
2010 if (e && !strcmp(e, type)) {
2025 bool system_resolve_rt_table(const char *name, unsigned int *id)
2029 unsigned int n, table = RT_TABLE_UNSPEC;
2031 /* first try to parse table as number */
2032 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
2035 /* handle well known aliases */
2036 else if (!strcmp(name, "default"))
2037 table = RT_TABLE_DEFAULT;
2038 else if (!strcmp(name, "main"))
2039 table = RT_TABLE_MAIN;
2040 else if (!strcmp(name, "local"))
2041 table = RT_TABLE_LOCAL;
2043 /* try to look up name in /etc/iproute2/rt_tables */
2044 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
2046 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
2048 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
2051 n = strtoul(e, NULL, 10);
2052 e = strtok(NULL, " \t\n");
2054 if (e && !strcmp(e, name))
2064 if (table == RT_TABLE_UNSPEC)
2071 bool system_is_default_rt_table(unsigned int id)
2073 return (id == RT_TABLE_MAIN);
2076 bool system_resolve_rpfilter(const char *filter, unsigned int *id)
2081 if (!strcmp(filter, "strict"))
2083 else if (!strcmp(filter, "loose"))
2086 n = strtoul(filter, &e, 0);
2087 if (*e || e == filter || n > 2)
2095 static int system_iprule(struct iprule *rule, int cmd)
2097 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
2100 struct rtmsg rtm = {
2101 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
2102 .rtm_protocol = RTPROT_STATIC,
2103 .rtm_scope = RT_SCOPE_UNIVERSE,
2104 .rtm_table = RT_TABLE_UNSPEC,
2105 .rtm_type = RTN_UNSPEC,
2109 if (cmd == RTM_NEWRULE)
2110 rtm.rtm_type = RTN_UNICAST;
2113 rtm.rtm_flags |= FIB_RULE_INVERT;
2115 if (rule->flags & IPRULE_SRC)
2116 rtm.rtm_src_len = rule->src_mask;
2118 if (rule->flags & IPRULE_DEST)
2119 rtm.rtm_dst_len = rule->dest_mask;
2121 if (rule->flags & IPRULE_TOS)
2122 rtm.rtm_tos = rule->tos;
2124 if (rule->flags & IPRULE_LOOKUP) {
2125 if (rule->lookup < 256)
2126 rtm.rtm_table = rule->lookup;
2129 if (rule->flags & IPRULE_ACTION)
2130 rtm.rtm_type = rule->action;
2131 else if (rule->flags & IPRULE_GOTO)
2132 rtm.rtm_type = FR_ACT_GOTO;
2133 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
2134 rtm.rtm_type = FR_ACT_NOP;
2136 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
2141 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
2143 if (rule->flags & IPRULE_IN)
2144 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
2146 if (rule->flags & IPRULE_OUT)
2147 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
2149 if (rule->flags & IPRULE_SRC)
2150 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
2152 if (rule->flags & IPRULE_DEST)
2153 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
2155 if (rule->flags & IPRULE_PRIORITY)
2156 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
2157 else if (cmd == RTM_NEWRULE)
2158 nla_put_u32(msg, FRA_PRIORITY, rule->order);
2160 if (rule->flags & IPRULE_FWMARK)
2161 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
2163 if (rule->flags & IPRULE_FWMASK)
2164 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
2166 if (rule->flags & IPRULE_LOOKUP) {
2167 if (rule->lookup >= 256)
2168 nla_put_u32(msg, FRA_TABLE, rule->lookup);
2171 if (rule->flags & IPRULE_GOTO)
2172 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
2174 return system_rtnl_call(msg);
2177 int system_add_iprule(struct iprule *rule)
2179 return system_iprule(rule, RTM_NEWRULE);
2182 int system_del_iprule(struct iprule *rule)
2184 return system_iprule(rule, RTM_DELRULE);
2187 int system_flush_iprules(void)
2192 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
2193 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
2195 memset(&rule, 0, sizeof(rule));
2198 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2201 rule.lookup = RT_TABLE_LOCAL;
2202 rv |= system_iprule(&rule, RTM_NEWRULE);
2204 rule.priority = 32766;
2205 rule.lookup = RT_TABLE_MAIN;
2206 rv |= system_iprule(&rule, RTM_NEWRULE);
2208 rule.priority = 32767;
2209 rule.lookup = RT_TABLE_DEFAULT;
2210 rv |= system_iprule(&rule, RTM_NEWRULE);
2213 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2216 rule.lookup = RT_TABLE_LOCAL;
2217 rv |= system_iprule(&rule, RTM_NEWRULE);
2219 rule.priority = 32766;
2220 rule.lookup = RT_TABLE_MAIN;
2221 rv |= system_iprule(&rule, RTM_NEWRULE);
2226 bool system_resolve_iprule_action(const char *action, unsigned int *id)
2228 return system_rtn_aton(action, id);
2231 time_t system_get_rtime(void)
2236 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
2239 if (gettimeofday(&tv, NULL) == 0)
2246 #define IP_DF 0x4000
2249 static int tunnel_ioctl(const char *name, int cmd, void *p)
2253 memset(&ifr, 0, sizeof(ifr));
2254 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
2255 ifr.ifr_ifru.ifru_data = p;
2256 return ioctl(sock_ioctl, cmd, &ifr);
2259 #ifdef IFLA_IPTUN_MAX
2260 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
2261 static int system_add_gre_tunnel(const char *name, const char *kind,
2262 const unsigned int link, struct blob_attr **tb, bool v6)
2265 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2266 struct blob_attr *cur;
2267 uint32_t ikey = 0, okey = 0, flags = 0, flowinfo = 0;
2268 uint16_t iflags = 0, oflags = 0;
2270 int ret = 0, ttl = 0;
2272 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2276 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2277 nla_put_string(nlm, IFLA_IFNAME, name);
2279 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2285 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2286 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2293 nla_put_u32(nlm, IFLA_GRE_LINK, link);
2295 if ((cur = tb[TUNNEL_ATTR_TTL]))
2296 ttl = blobmsg_get_u32(cur);
2298 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2299 char *str = blobmsg_get_string(cur);
2300 if (strcmp(str, "inherit")) {
2303 if (!system_tos_aton(str, &uval)) {
2309 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
2314 flags |= IP6_TNL_F_USE_ORIG_TCLASS;
2320 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2321 struct blob_attr *tb_data[__GRE_DATA_ATTR_MAX];
2323 blobmsg_parse(gre_data_attr_list.params, __GRE_DATA_ATTR_MAX, tb_data,
2324 blobmsg_data(cur), blobmsg_len(cur));
2326 if ((cur = tb_data[GRE_DATA_IKEY])) {
2327 if ((ikey = blobmsg_get_u32(cur)))
2331 if ((cur = tb_data[GRE_DATA_OKEY])) {
2332 if ((okey = blobmsg_get_u32(cur)))
2336 if ((cur = tb_data[GRE_DATA_ICSUM])) {
2337 if (blobmsg_get_bool(cur))
2341 if ((cur = tb_data[GRE_DATA_OCSUM])) {
2342 if (blobmsg_get_bool(cur))
2346 if ((cur = tb_data[GRE_DATA_ISEQNO])) {
2347 if (blobmsg_get_bool(cur))
2351 if ((cur = tb[GRE_DATA_OSEQNO])) {
2352 if (blobmsg_get_bool(cur))
2358 struct in6_addr in6buf;
2359 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2360 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2364 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
2367 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2368 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2372 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
2374 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, 4);
2377 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
2380 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags);
2385 struct in_addr inbuf;
2388 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2389 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2393 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
2396 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2397 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2401 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
2403 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
2405 okey = inbuf.s_addr;
2410 ikey = inbuf.s_addr;
2416 if ((cur = tb[TUNNEL_ATTR_DF]))
2417 set_df = blobmsg_get_bool(cur);
2420 /* ttl != 0 and nopmtudisc are incompatible */
2428 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
2430 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
2434 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
2437 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
2440 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
2443 nla_put_u32(nlm, IFLA_GRE_OKEY, okey);
2446 nla_put_u32(nlm, IFLA_GRE_IKEY, ikey);
2448 nla_nest_end(nlm, infodata);
2449 nla_nest_end(nlm, linkinfo);
2451 return system_rtnl_call(nlm);
2460 static int system_add_vti_tunnel(const char *name, const char *kind,
2461 const unsigned int link, struct blob_attr **tb, bool v6)
2464 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2465 struct blob_attr *cur;
2468 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2472 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2473 nla_put_string(nlm, IFLA_IFNAME, name);
2475 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2481 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2482 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2489 nla_put_u32(nlm, IFLA_VTI_LINK, link);
2492 struct in6_addr in6buf;
2493 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2494 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2498 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(in6buf), &in6buf);
2501 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2502 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2506 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(in6buf), &in6buf);
2510 struct in_addr inbuf;
2512 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2513 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2517 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(inbuf), &inbuf);
2520 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2521 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2525 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(inbuf), &inbuf);
2530 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2531 struct blob_attr *tb_data[__VTI_DATA_ATTR_MAX];
2532 uint32_t ikey = 0, okey = 0;
2534 blobmsg_parse(vti_data_attr_list.params, __VTI_DATA_ATTR_MAX, tb_data,
2535 blobmsg_data(cur), blobmsg_len(cur));
2537 if ((cur = tb_data[VTI_DATA_IKEY])) {
2538 if ((ikey = blobmsg_get_u32(cur)))
2539 nla_put_u32(nlm, IFLA_VTI_IKEY, htonl(ikey));
2542 if ((cur = tb_data[VTI_DATA_OKEY])) {
2543 if ((okey = blobmsg_get_u32(cur)))
2544 nla_put_u32(nlm, IFLA_VTI_OKEY, htonl(okey));
2548 nla_nest_end(nlm, infodata);
2549 nla_nest_end(nlm, linkinfo);
2551 return system_rtnl_call(nlm);
2559 #ifdef IFLA_VXLAN_MAX
2560 static int system_add_vxlan(const char *name, const unsigned int link, struct blob_attr **tb, bool v6)
2562 struct blob_attr *tb_data[__VXLAN_DATA_ATTR_MAX];
2564 struct nlattr *linkinfo, *data;
2565 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
2566 struct blob_attr *cur;
2569 if ((cur = tb[TUNNEL_ATTR_DATA]))
2570 blobmsg_parse(vxlan_data_attr_list.params, __VXLAN_DATA_ATTR_MAX, tb_data,
2571 blobmsg_data(cur), blobmsg_len(cur));
2575 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
2580 nlmsg_append(msg, &iim, sizeof(iim), 0);
2582 nla_put_string(msg, IFLA_IFNAME, name);
2584 if ((cur = tb_data[VXLAN_DATA_ATTR_MACADDR])) {
2585 struct ether_addr *ea = ether_aton(blobmsg_get_string(cur));
2591 nla_put(msg, IFLA_ADDRESS, ETH_ALEN, ea);
2594 if ((cur = tb[TUNNEL_ATTR_MTU])) {
2595 uint32_t mtu = blobmsg_get_u32(cur);
2596 nla_put_u32(msg, IFLA_MTU, mtu);
2599 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO))) {
2604 nla_put_string(msg, IFLA_INFO_KIND, "vxlan");
2606 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) {
2612 nla_put_u32(msg, IFLA_VXLAN_LINK, link);
2614 if ((cur = tb_data[VXLAN_DATA_ATTR_ID])) {
2615 uint32_t id = blobmsg_get_u32(cur);
2616 if (id >= (1u << 24) - 1) {
2621 nla_put_u32(msg, IFLA_VXLAN_ID, id);
2625 struct in6_addr in6buf;
2626 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2627 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2631 nla_put(msg, IFLA_VXLAN_LOCAL6, sizeof(in6buf), &in6buf);
2634 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2635 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2639 nla_put(msg, IFLA_VXLAN_GROUP6, sizeof(in6buf), &in6buf);
2642 struct in_addr inbuf;
2644 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2645 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2649 nla_put(msg, IFLA_VXLAN_LOCAL, sizeof(inbuf), &inbuf);
2652 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2653 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2657 nla_put(msg, IFLA_VXLAN_GROUP, sizeof(inbuf), &inbuf);
2661 uint32_t port = 4789;
2662 if ((cur = tb_data[VXLAN_DATA_ATTR_PORT])) {
2663 port = blobmsg_get_u32(cur);
2664 if (port < 1 || port > 65535) {
2669 nla_put_u16(msg, IFLA_VXLAN_PORT, htons(port));
2671 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2672 char *str = blobmsg_get_string(cur);
2675 if (strcmp(str, "inherit")) {
2676 if (!system_tos_aton(str, &tos))
2680 nla_put_u8(msg, IFLA_VXLAN_TOS, tos);
2683 if ((cur = tb[TUNNEL_ATTR_TTL])) {
2684 uint32_t ttl = blobmsg_get_u32(cur);
2685 if (ttl < 1 || ttl > 255) {
2690 nla_put_u8(msg, IFLA_VXLAN_TTL, ttl);
2693 nla_nest_end(msg, data);
2694 nla_nest_end(msg, linkinfo);
2696 ret = system_rtnl_call(msg);
2698 D(SYSTEM, "Error adding vxlan '%s': %d\n", name, ret);
2708 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
2710 struct blob_attr *cur;
2712 struct ip_tunnel_parm p = {
2721 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
2722 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
2725 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
2726 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
2729 if ((cur = tb[TUNNEL_ATTR_DF]))
2730 set_df = blobmsg_get_bool(cur);
2732 if ((cur = tb[TUNNEL_ATTR_TTL]))
2733 p.iph.ttl = blobmsg_get_u32(cur);
2735 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2736 char *str = blobmsg_get_string(cur);
2737 if (strcmp(str, "inherit")) {
2740 if (!system_tos_aton(str, &uval))
2748 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
2749 /* ttl !=0 and nopmtudisc are incompatible */
2750 if (p.iph.ttl && p.iph.frag_off == 0)
2753 strncpy(p.name, name, sizeof(p.name));
2755 switch (p.iph.protocol) {
2757 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
2759 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
2766 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
2768 struct blob_attr *cur;
2771 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2773 str = blobmsg_data(cur);
2775 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
2776 !strcmp(str, "greip6") || !strcmp(str, "gretapip6") ||
2777 !strcmp(str, "vtiip") || !strcmp(str, "vtiip6") ||
2778 !strcmp(str, "vxlan") || !strcmp(str, "vxlan6"))
2779 return system_link_del(name);
2781 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
2784 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
2786 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2788 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2789 blob_data(attr), blob_len(attr));
2791 return __system_del_ip_tunnel(name, tb);
2794 int system_update_ipv6_mtu(struct device *dev, int mtu)
2800 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
2803 fd = open(buf, O_RDWR);
2808 ssize_t len = read(fd, buf, sizeof(buf) - 1);
2815 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) > 0)
2824 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
2826 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2827 struct blob_attr *cur;
2830 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2831 blob_data(attr), blob_len(attr));
2833 __system_del_ip_tunnel(name, tb);
2835 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2837 str = blobmsg_data(cur);
2839 unsigned int ttl = 0;
2840 if ((cur = tb[TUNNEL_ATTR_TTL])) {
2841 ttl = blobmsg_get_u32(cur);
2846 unsigned int link = 0;
2847 if ((cur = tb[TUNNEL_ATTR_LINK])) {
2848 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
2852 if (iface->l3_dev.dev)
2853 link = iface->l3_dev.dev->ifindex;
2856 if (!strcmp(str, "sit")) {
2857 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
2861 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
2863 struct ip_tunnel_6rd p6;
2865 memset(&p6, 0, sizeof(p6));
2867 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
2868 &p6.prefix, &mask) || mask > 128)
2870 p6.prefixlen = mask;
2872 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
2873 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
2874 &p6.relay_prefix, &mask) || mask > 32)
2876 p6.relay_prefixlen = mask;
2879 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
2880 __system_del_ip_tunnel(name, tb);
2885 #ifdef IFLA_IPTUN_MAX
2886 } else if (!strcmp(str, "ipip6")) {
2887 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2888 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2889 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2895 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2896 nla_put_string(nlm, IFLA_IFNAME, name);
2899 nla_put_u32(nlm, IFLA_LINK, link);
2901 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2906 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2907 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2914 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2916 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2917 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2918 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
2920 struct in6_addr in6buf;
2921 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2922 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2926 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2929 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2930 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2934 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2937 #ifdef IFLA_IPTUN_FMR_MAX
2938 if ((cur = tb[TUNNEL_ATTR_FMRS])) {
2939 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2941 struct blob_attr *fmr;
2942 unsigned rem, fmrcnt = 0;
2943 blobmsg_for_each_attr(fmr, cur, rem) {
2944 if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
2947 unsigned ip4len, ip6len, ealen, offset = 6;
2951 if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
2952 ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) {
2957 struct in6_addr ip6prefix;
2958 struct in_addr ip4prefix;
2959 if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
2960 inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) {
2965 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2967 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2968 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2969 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2970 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2971 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2972 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2974 nla_nest_end(nlm, rule);
2977 nla_nest_end(nlm, fmrs);
2981 nla_nest_end(nlm, infodata);
2982 nla_nest_end(nlm, linkinfo);
2984 return system_rtnl_call(nlm);
2988 } else if (!strcmp(str, "greip")) {
2989 return system_add_gre_tunnel(name, "gre", link, tb, false);
2990 } else if (!strcmp(str, "gretapip")) {
2991 return system_add_gre_tunnel(name, "gretap", link, tb, false);
2992 } else if (!strcmp(str, "greip6")) {
2993 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
2994 } else if (!strcmp(str, "gretapip6")) {
2995 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
2997 } else if (!strcmp(str, "vtiip")) {
2998 return system_add_vti_tunnel(name, "vti", link, tb, false);
2999 } else if (!strcmp(str, "vtiip6")) {
3000 return system_add_vti_tunnel(name, "vti6", link, tb, true);
3002 #ifdef IFLA_VXLAN_MAX
3003 } else if(!strcmp(str, "vxlan")) {
3004 return system_add_vxlan(name, link, tb, false);
3005 } else if(!strcmp(str, "vxlan6")) {
3006 return system_add_vxlan(name, link, tb, true);
3009 } else if (!strcmp(str, "ipip")) {
3010 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);