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_scope = RT_SCOPE_UNIVERSE;
1905 msg = nlmsg_alloc_simple(cmd, flags);
1909 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1912 nla_put(msg, RTA_DST, alen, &route->addr);
1914 if (route->sourcemask) {
1915 if (rtm.rtm_family == AF_INET)
1916 nla_put(msg, RTA_PREFSRC, alen, &route->source);
1918 nla_put(msg, RTA_SRC, alen, &route->source);
1921 if (route->metric > 0)
1922 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1925 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1928 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1931 nla_put_u32(msg, RTA_TABLE, table);
1933 if (route->flags & DEVROUTE_MTU) {
1934 struct nlattr *metrics;
1936 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1937 goto nla_put_failure;
1939 nla_put_u32(msg, RTAX_MTU, route->mtu);
1941 nla_nest_end(msg, metrics);
1944 return system_rtnl_call(msg);
1951 int system_add_route(struct device *dev, struct device_route *route)
1953 return system_rt(dev, route, RTM_NEWROUTE);
1956 int system_del_route(struct device *dev, struct device_route *route)
1958 return system_rt(dev, route, RTM_DELROUTE);
1961 int system_flush_routes(void)
1963 const char *names[] = {
1964 "/proc/sys/net/ipv4/route/flush",
1965 "/proc/sys/net/ipv6/route/flush"
1969 for (i = 0; i < ARRAY_SIZE(names); i++) {
1970 fd = open(names[i], O_WRONLY);
1974 if (write(fd, "-1", 2)) {}
1980 bool system_resolve_rt_type(const char *type, unsigned int *id)
1982 return system_rtn_aton(type, id);
1985 bool system_resolve_rt_proto(const char *type, unsigned int *id)
1989 unsigned int n, proto = 256;
1991 if ((n = strtoul(type, &e, 0)) >= 0 && !*e && e != type)
1993 else if (!strcmp(type, "unspec"))
1994 proto = RTPROT_UNSPEC;
1995 else if (!strcmp(type, "kernel"))
1996 proto = RTPROT_KERNEL;
1997 else if (!strcmp(type, "boot"))
1998 proto = RTPROT_BOOT;
1999 else if (!strcmp(type, "static"))
2000 proto = RTPROT_STATIC;
2001 else if ((f = fopen("/etc/iproute2/rt_protos", "r")) != NULL) {
2002 while (fgets(buf, sizeof(buf) - 1, f) != NULL) {
2003 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
2006 n = strtoul(e, NULL, 10);
2007 e = strtok(NULL, " \t\n");
2009 if (e && !strcmp(e, type)) {
2024 bool system_resolve_rt_table(const char *name, unsigned int *id)
2028 unsigned int n, table = RT_TABLE_UNSPEC;
2030 /* first try to parse table as number */
2031 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
2034 /* handle well known aliases */
2035 else if (!strcmp(name, "default"))
2036 table = RT_TABLE_DEFAULT;
2037 else if (!strcmp(name, "main"))
2038 table = RT_TABLE_MAIN;
2039 else if (!strcmp(name, "local"))
2040 table = RT_TABLE_LOCAL;
2042 /* try to look up name in /etc/iproute2/rt_tables */
2043 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
2045 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
2047 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
2050 n = strtoul(e, NULL, 10);
2051 e = strtok(NULL, " \t\n");
2053 if (e && !strcmp(e, name))
2063 if (table == RT_TABLE_UNSPEC)
2070 bool system_is_default_rt_table(unsigned int id)
2072 return (id == RT_TABLE_MAIN);
2075 bool system_resolve_rpfilter(const char *filter, unsigned int *id)
2080 if (!strcmp(filter, "strict"))
2082 else if (!strcmp(filter, "loose"))
2085 n = strtoul(filter, &e, 0);
2086 if (*e || e == filter || n > 2)
2094 static int system_iprule(struct iprule *rule, int cmd)
2096 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
2099 struct rtmsg rtm = {
2100 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
2101 .rtm_protocol = RTPROT_STATIC,
2102 .rtm_scope = RT_SCOPE_UNIVERSE,
2103 .rtm_table = RT_TABLE_UNSPEC,
2104 .rtm_type = RTN_UNSPEC,
2108 if (cmd == RTM_NEWRULE)
2109 rtm.rtm_type = RTN_UNICAST;
2112 rtm.rtm_flags |= FIB_RULE_INVERT;
2114 if (rule->flags & IPRULE_SRC)
2115 rtm.rtm_src_len = rule->src_mask;
2117 if (rule->flags & IPRULE_DEST)
2118 rtm.rtm_dst_len = rule->dest_mask;
2120 if (rule->flags & IPRULE_TOS)
2121 rtm.rtm_tos = rule->tos;
2123 if (rule->flags & IPRULE_LOOKUP) {
2124 if (rule->lookup < 256)
2125 rtm.rtm_table = rule->lookup;
2128 if (rule->flags & IPRULE_ACTION)
2129 rtm.rtm_type = rule->action;
2130 else if (rule->flags & IPRULE_GOTO)
2131 rtm.rtm_type = FR_ACT_GOTO;
2132 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
2133 rtm.rtm_type = FR_ACT_NOP;
2135 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
2140 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
2142 if (rule->flags & IPRULE_IN)
2143 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
2145 if (rule->flags & IPRULE_OUT)
2146 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
2148 if (rule->flags & IPRULE_SRC)
2149 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
2151 if (rule->flags & IPRULE_DEST)
2152 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
2154 if (rule->flags & IPRULE_PRIORITY)
2155 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
2156 else if (cmd == RTM_NEWRULE)
2157 nla_put_u32(msg, FRA_PRIORITY, rule->order);
2159 if (rule->flags & IPRULE_FWMARK)
2160 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
2162 if (rule->flags & IPRULE_FWMASK)
2163 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
2165 if (rule->flags & IPRULE_LOOKUP) {
2166 if (rule->lookup >= 256)
2167 nla_put_u32(msg, FRA_TABLE, rule->lookup);
2170 if (rule->flags & IPRULE_GOTO)
2171 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
2173 return system_rtnl_call(msg);
2176 int system_add_iprule(struct iprule *rule)
2178 return system_iprule(rule, RTM_NEWRULE);
2181 int system_del_iprule(struct iprule *rule)
2183 return system_iprule(rule, RTM_DELRULE);
2186 int system_flush_iprules(void)
2191 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
2192 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
2194 memset(&rule, 0, sizeof(rule));
2197 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2200 rule.lookup = RT_TABLE_LOCAL;
2201 rv |= system_iprule(&rule, RTM_NEWRULE);
2203 rule.priority = 32766;
2204 rule.lookup = RT_TABLE_MAIN;
2205 rv |= system_iprule(&rule, RTM_NEWRULE);
2207 rule.priority = 32767;
2208 rule.lookup = RT_TABLE_DEFAULT;
2209 rv |= system_iprule(&rule, RTM_NEWRULE);
2212 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2215 rule.lookup = RT_TABLE_LOCAL;
2216 rv |= system_iprule(&rule, RTM_NEWRULE);
2218 rule.priority = 32766;
2219 rule.lookup = RT_TABLE_MAIN;
2220 rv |= system_iprule(&rule, RTM_NEWRULE);
2225 bool system_resolve_iprule_action(const char *action, unsigned int *id)
2227 return system_rtn_aton(action, id);
2230 time_t system_get_rtime(void)
2235 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
2238 if (gettimeofday(&tv, NULL) == 0)
2245 #define IP_DF 0x4000
2248 static int tunnel_ioctl(const char *name, int cmd, void *p)
2252 memset(&ifr, 0, sizeof(ifr));
2253 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
2254 ifr.ifr_ifru.ifru_data = p;
2255 return ioctl(sock_ioctl, cmd, &ifr);
2258 #ifdef IFLA_IPTUN_MAX
2259 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
2260 static int system_add_gre_tunnel(const char *name, const char *kind,
2261 const unsigned int link, struct blob_attr **tb, bool v6)
2264 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2265 struct blob_attr *cur;
2266 uint32_t ikey = 0, okey = 0, flags = 0, flowinfo = 0;
2267 uint16_t iflags = 0, oflags = 0;
2269 int ret = 0, ttl = 0;
2271 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2275 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2276 nla_put_string(nlm, IFLA_IFNAME, name);
2278 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2284 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2285 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2292 nla_put_u32(nlm, IFLA_GRE_LINK, link);
2294 if ((cur = tb[TUNNEL_ATTR_TTL]))
2295 ttl = blobmsg_get_u32(cur);
2297 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2298 char *str = blobmsg_get_string(cur);
2299 if (strcmp(str, "inherit")) {
2302 if (!system_tos_aton(str, &uval)) {
2308 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
2313 flags |= IP6_TNL_F_USE_ORIG_TCLASS;
2319 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2320 struct blob_attr *tb_data[__GRE_DATA_ATTR_MAX];
2322 blobmsg_parse(gre_data_attr_list.params, __GRE_DATA_ATTR_MAX, tb_data,
2323 blobmsg_data(cur), blobmsg_len(cur));
2325 if ((cur = tb_data[GRE_DATA_IKEY])) {
2326 if ((ikey = blobmsg_get_u32(cur)))
2330 if ((cur = tb_data[GRE_DATA_OKEY])) {
2331 if ((okey = blobmsg_get_u32(cur)))
2335 if ((cur = tb_data[GRE_DATA_ICSUM])) {
2336 if (blobmsg_get_bool(cur))
2340 if ((cur = tb_data[GRE_DATA_OCSUM])) {
2341 if (blobmsg_get_bool(cur))
2345 if ((cur = tb_data[GRE_DATA_ISEQNO])) {
2346 if (blobmsg_get_bool(cur))
2350 if ((cur = tb[GRE_DATA_OSEQNO])) {
2351 if (blobmsg_get_bool(cur))
2357 struct in6_addr in6buf;
2358 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2359 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2363 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
2366 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2367 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2371 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
2373 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, 4);
2376 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
2379 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags);
2384 struct in_addr inbuf;
2387 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2388 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2392 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
2395 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2396 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2400 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
2402 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
2404 okey = inbuf.s_addr;
2409 ikey = inbuf.s_addr;
2415 if ((cur = tb[TUNNEL_ATTR_DF]))
2416 set_df = blobmsg_get_bool(cur);
2419 /* ttl != 0 and nopmtudisc are incompatible */
2427 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
2429 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
2433 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
2436 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
2439 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
2442 nla_put_u32(nlm, IFLA_GRE_OKEY, okey);
2445 nla_put_u32(nlm, IFLA_GRE_IKEY, ikey);
2447 nla_nest_end(nlm, infodata);
2448 nla_nest_end(nlm, linkinfo);
2450 return system_rtnl_call(nlm);
2459 static int system_add_vti_tunnel(const char *name, const char *kind,
2460 const unsigned int link, struct blob_attr **tb, bool v6)
2463 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2464 struct blob_attr *cur;
2467 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2471 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2472 nla_put_string(nlm, IFLA_IFNAME, name);
2474 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2480 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2481 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2488 nla_put_u32(nlm, IFLA_VTI_LINK, link);
2491 struct in6_addr in6buf;
2492 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2493 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2497 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(in6buf), &in6buf);
2500 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2501 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2505 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(in6buf), &in6buf);
2509 struct in_addr inbuf;
2511 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2512 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2516 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(inbuf), &inbuf);
2519 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2520 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2524 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(inbuf), &inbuf);
2529 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2530 struct blob_attr *tb_data[__VTI_DATA_ATTR_MAX];
2531 uint32_t ikey = 0, okey = 0;
2533 blobmsg_parse(vti_data_attr_list.params, __VTI_DATA_ATTR_MAX, tb_data,
2534 blobmsg_data(cur), blobmsg_len(cur));
2536 if ((cur = tb_data[VTI_DATA_IKEY])) {
2537 if ((ikey = blobmsg_get_u32(cur)))
2538 nla_put_u32(nlm, IFLA_VTI_IKEY, htonl(ikey));
2541 if ((cur = tb_data[VTI_DATA_OKEY])) {
2542 if ((okey = blobmsg_get_u32(cur)))
2543 nla_put_u32(nlm, IFLA_VTI_OKEY, htonl(okey));
2547 nla_nest_end(nlm, infodata);
2548 nla_nest_end(nlm, linkinfo);
2550 return system_rtnl_call(nlm);
2558 #ifdef IFLA_VXLAN_MAX
2559 static int system_add_vxlan(const char *name, const unsigned int link, struct blob_attr **tb, bool v6)
2561 struct blob_attr *tb_data[__VXLAN_DATA_ATTR_MAX];
2563 struct nlattr *linkinfo, *data;
2564 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
2565 struct blob_attr *cur;
2568 if ((cur = tb[TUNNEL_ATTR_DATA]))
2569 blobmsg_parse(vxlan_data_attr_list.params, __VXLAN_DATA_ATTR_MAX, tb_data,
2570 blobmsg_data(cur), blobmsg_len(cur));
2574 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
2579 nlmsg_append(msg, &iim, sizeof(iim), 0);
2581 nla_put_string(msg, IFLA_IFNAME, name);
2583 if ((cur = tb_data[VXLAN_DATA_ATTR_MACADDR])) {
2584 struct ether_addr *ea = ether_aton(blobmsg_get_string(cur));
2590 nla_put(msg, IFLA_ADDRESS, ETH_ALEN, ea);
2593 if ((cur = tb[TUNNEL_ATTR_MTU])) {
2594 uint32_t mtu = blobmsg_get_u32(cur);
2595 nla_put_u32(msg, IFLA_MTU, mtu);
2598 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO))) {
2603 nla_put_string(msg, IFLA_INFO_KIND, "vxlan");
2605 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) {
2611 nla_put_u32(msg, IFLA_VXLAN_LINK, link);
2613 if ((cur = tb_data[VXLAN_DATA_ATTR_ID])) {
2614 uint32_t id = blobmsg_get_u32(cur);
2615 if (id >= (1u << 24) - 1) {
2620 nla_put_u32(msg, IFLA_VXLAN_ID, id);
2624 struct in6_addr in6buf;
2625 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2626 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2630 nla_put(msg, IFLA_VXLAN_LOCAL6, sizeof(in6buf), &in6buf);
2633 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2634 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2638 nla_put(msg, IFLA_VXLAN_GROUP6, sizeof(in6buf), &in6buf);
2641 struct in_addr inbuf;
2643 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2644 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2648 nla_put(msg, IFLA_VXLAN_LOCAL, sizeof(inbuf), &inbuf);
2651 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2652 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2656 nla_put(msg, IFLA_VXLAN_GROUP, sizeof(inbuf), &inbuf);
2660 uint32_t port = 4789;
2661 if ((cur = tb_data[VXLAN_DATA_ATTR_PORT])) {
2662 port = blobmsg_get_u32(cur);
2663 if (port < 1 || port > 65535) {
2668 nla_put_u16(msg, IFLA_VXLAN_PORT, htons(port));
2670 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2671 char *str = blobmsg_get_string(cur);
2674 if (strcmp(str, "inherit")) {
2675 if (!system_tos_aton(str, &tos))
2679 nla_put_u8(msg, IFLA_VXLAN_TOS, tos);
2682 if ((cur = tb[TUNNEL_ATTR_TTL])) {
2683 uint32_t ttl = blobmsg_get_u32(cur);
2684 if (ttl < 1 || ttl > 255) {
2689 nla_put_u8(msg, IFLA_VXLAN_TTL, ttl);
2692 nla_nest_end(msg, data);
2693 nla_nest_end(msg, linkinfo);
2695 ret = system_rtnl_call(msg);
2697 D(SYSTEM, "Error adding vxlan '%s': %d\n", name, ret);
2707 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
2709 struct blob_attr *cur;
2711 struct ip_tunnel_parm p = {
2720 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
2721 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
2724 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
2725 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
2728 if ((cur = tb[TUNNEL_ATTR_DF]))
2729 set_df = blobmsg_get_bool(cur);
2731 if ((cur = tb[TUNNEL_ATTR_TTL]))
2732 p.iph.ttl = blobmsg_get_u32(cur);
2734 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2735 char *str = blobmsg_get_string(cur);
2736 if (strcmp(str, "inherit")) {
2739 if (!system_tos_aton(str, &uval))
2747 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
2748 /* ttl !=0 and nopmtudisc are incompatible */
2749 if (p.iph.ttl && p.iph.frag_off == 0)
2752 strncpy(p.name, name, sizeof(p.name));
2754 switch (p.iph.protocol) {
2756 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
2758 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
2765 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
2767 struct blob_attr *cur;
2770 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2772 str = blobmsg_data(cur);
2774 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
2775 !strcmp(str, "greip6") || !strcmp(str, "gretapip6") ||
2776 !strcmp(str, "vtiip") || !strcmp(str, "vtiip6") ||
2777 !strcmp(str, "vxlan") || !strcmp(str, "vxlan6"))
2778 return system_link_del(name);
2780 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
2783 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
2785 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2787 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2788 blob_data(attr), blob_len(attr));
2790 return __system_del_ip_tunnel(name, tb);
2793 int system_update_ipv6_mtu(struct device *dev, int mtu)
2799 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
2802 fd = open(buf, O_RDWR);
2807 ssize_t len = read(fd, buf, sizeof(buf) - 1);
2814 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) > 0)
2823 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
2825 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2826 struct blob_attr *cur;
2829 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2830 blob_data(attr), blob_len(attr));
2832 __system_del_ip_tunnel(name, tb);
2834 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2836 str = blobmsg_data(cur);
2838 unsigned int ttl = 0;
2839 if ((cur = tb[TUNNEL_ATTR_TTL])) {
2840 ttl = blobmsg_get_u32(cur);
2845 unsigned int link = 0;
2846 if ((cur = tb[TUNNEL_ATTR_LINK])) {
2847 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
2851 if (iface->l3_dev.dev)
2852 link = iface->l3_dev.dev->ifindex;
2855 if (!strcmp(str, "sit")) {
2856 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
2860 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
2862 struct ip_tunnel_6rd p6;
2864 memset(&p6, 0, sizeof(p6));
2866 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
2867 &p6.prefix, &mask) || mask > 128)
2869 p6.prefixlen = mask;
2871 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
2872 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
2873 &p6.relay_prefix, &mask) || mask > 32)
2875 p6.relay_prefixlen = mask;
2878 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
2879 __system_del_ip_tunnel(name, tb);
2884 #ifdef IFLA_IPTUN_MAX
2885 } else if (!strcmp(str, "ipip6")) {
2886 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2887 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2888 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2894 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2895 nla_put_string(nlm, IFLA_IFNAME, name);
2898 nla_put_u32(nlm, IFLA_LINK, link);
2900 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2905 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2906 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2913 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2915 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2916 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2917 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
2919 struct in6_addr in6buf;
2920 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2921 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2925 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2928 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2929 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2933 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2936 #ifdef IFLA_IPTUN_FMR_MAX
2937 if ((cur = tb[TUNNEL_ATTR_FMRS])) {
2938 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2940 struct blob_attr *fmr;
2941 unsigned rem, fmrcnt = 0;
2942 blobmsg_for_each_attr(fmr, cur, rem) {
2943 if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
2946 unsigned ip4len, ip6len, ealen, offset = 6;
2950 if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
2951 ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) {
2956 struct in6_addr ip6prefix;
2957 struct in_addr ip4prefix;
2958 if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
2959 inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) {
2964 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2966 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2967 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2968 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2969 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2970 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2971 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2973 nla_nest_end(nlm, rule);
2976 nla_nest_end(nlm, fmrs);
2980 nla_nest_end(nlm, infodata);
2981 nla_nest_end(nlm, linkinfo);
2983 return system_rtnl_call(nlm);
2987 } else if (!strcmp(str, "greip")) {
2988 return system_add_gre_tunnel(name, "gre", link, tb, false);
2989 } else if (!strcmp(str, "gretapip")) {
2990 return system_add_gre_tunnel(name, "gretap", link, tb, false);
2991 } else if (!strcmp(str, "greip6")) {
2992 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
2993 } else if (!strcmp(str, "gretapip6")) {
2994 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
2996 } else if (!strcmp(str, "vtiip")) {
2997 return system_add_vti_tunnel(name, "vti", link, tb, false);
2998 } else if (!strcmp(str, "vtiip6")) {
2999 return system_add_vti_tunnel(name, "vti6", link, tb, true);
3001 #ifdef IFLA_VXLAN_MAX
3002 } else if(!strcmp(str, "vxlan")) {
3003 return system_add_vxlan(name, link, tb, false);
3004 } else if(!strcmp(str, "vxlan6")) {
3005 return system_add_vxlan(name, link, tb, true);
3008 } else if (!strcmp(str, "ipip")) {
3009 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);