2 * netifd - network interface daemon
3 * Copyright (C) 2012 Felix Fietkau <nbd@openwrt.org>
4 * Copyright (C) 2013 Jo-Philipp Wich <jow@openwrt.org>
5 * Copyright (C) 2013 Steven Barth <steven@midlink.org>
6 * Copyright (C) 2014 Gioacchino Mazzurco <gio@eigenlab.org>
7 * Copyright (C) 2017 Matthias Schiffer <mschiffer@universe-factory.net>
8 * Copyright (C) 2018 Hans Dedecker <dedeckeh@gmail.com>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
21 #include <sys/socket.h>
22 #include <sys/ioctl.h>
24 #include <sys/syscall.h>
27 #include <net/if_arp.h>
29 #include <arpa/inet.h>
30 #include <netinet/ether.h>
31 #include <netinet/in.h>
33 #include <linux/rtnetlink.h>
34 #include <linux/sockios.h>
36 #include <linux/if_addr.h>
37 #include <linux/if_link.h>
38 #include <linux/if_vlan.h>
39 #include <linux/if_bridge.h>
40 #include <linux/if_tunnel.h>
41 #include <linux/ip6_tunnel.h>
42 #include <linux/ethtool.h>
43 #include <linux/fib_rules.h>
44 #include <linux/veth.h>
45 #include <linux/version.h>
47 #ifndef RTN_FAILED_POLICY
48 #define RTN_FAILED_POLICY 12
51 #ifndef IFA_F_NOPREFIXROUTE
52 #define IFA_F_NOPREFIXROUTE 0x200
56 #define IFA_FLAGS (IFA_MULTICAST + 1)
65 #include <netlink/msg.h>
66 #include <netlink/attr.h>
67 #include <netlink/socket.h>
68 #include <libubox/uloop.h>
75 struct uloop_fd uloop;
80 static int sock_ioctl = -1;
81 static struct nl_sock *sock_rtnl = NULL;
83 static int cb_rtnl_event(struct nl_msg *msg, void *arg);
84 static void handle_hotplug_event(struct uloop_fd *u, unsigned int events);
85 static int system_add_proto_tunnel(const char *name, const uint8_t proto,
86 const unsigned int link, struct blob_attr **tb);
87 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb);
89 static char dev_buf[256];
92 handler_nl_event(struct uloop_fd *u, unsigned int events)
94 struct event_socket *ev = container_of(u, struct event_socket, uloop);
96 socklen_t errlen = sizeof(err);
99 nl_recvmsgs_default(ev->sock);
103 if (getsockopt(u->fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen))
108 // Increase rx buffer size on netlink socket
110 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
113 // Request full dump since some info got dropped
114 struct rtgenmsg msg = { .rtgen_family = AF_UNSPEC };
115 nl_send_simple(ev->sock, RTM_GETLINK, NLM_F_DUMP, &msg, sizeof(msg));
125 uloop_fd_delete(&ev->uloop);
129 static struct nl_sock *
130 create_socket(int protocol, int groups)
132 struct nl_sock *sock;
134 sock = nl_socket_alloc();
139 nl_join_groups(sock, groups);
141 if (nl_connect(sock, protocol))
148 create_raw_event_socket(struct event_socket *ev, int protocol, int groups,
149 uloop_fd_handler cb, int flags)
151 ev->sock = create_socket(protocol, groups);
155 ev->uloop.fd = nl_socket_get_fd(ev->sock);
157 if (uloop_fd_add(&ev->uloop, ULOOP_READ|flags))
164 create_event_socket(struct event_socket *ev, int protocol,
165 int (*cb)(struct nl_msg *msg, void *arg))
167 if (!create_raw_event_socket(ev, protocol, 0, handler_nl_event, ULOOP_ERROR_CB))
170 // Install the valid custom callback handler
171 nl_socket_modify_cb(ev->sock, NL_CB_VALID, NL_CB_CUSTOM, cb, NULL);
173 // Disable sequence number checking on event sockets
174 nl_socket_disable_seq_check(ev->sock);
176 // Increase rx buffer size to 65K on event sockets
178 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
185 system_rtn_aton(const char *src, unsigned int *dst)
190 if (!strcmp(src, "local"))
192 else if (!strcmp(src, "nat"))
194 else if (!strcmp(src, "broadcast"))
196 else if (!strcmp(src, "anycast"))
198 else if (!strcmp(src, "multicast"))
200 else if (!strcmp(src, "prohibit"))
202 else if (!strcmp(src, "unreachable"))
204 else if (!strcmp(src, "blackhole"))
206 else if (!strcmp(src, "xresolve"))
208 else if (!strcmp(src, "unicast"))
210 else if (!strcmp(src, "throw"))
212 else if (!strcmp(src, "failed_policy"))
213 n = RTN_FAILED_POLICY;
215 n = strtoul(src, &e, 0);
216 if (!e || *e || e == src || n > 255)
225 system_tos_aton(const char *src, unsigned *dst)
229 *dst = strtoul(src, &e, 16);
230 if (e == src || *e || *dst > 255)
236 int system_init(void)
238 static struct event_socket rtnl_event;
239 static struct event_socket hotplug_event;
241 sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0);
242 system_fd_set_cloexec(sock_ioctl);
244 // Prepare socket for routing / address control
245 sock_rtnl = create_socket(NETLINK_ROUTE, 0);
249 if (!create_event_socket(&rtnl_event, NETLINK_ROUTE, cb_rtnl_event))
252 if (!create_raw_event_socket(&hotplug_event, NETLINK_KOBJECT_UEVENT, 1,
253 handle_hotplug_event, 0))
256 // Receive network link events form kernel
257 nl_socket_add_membership(rtnl_event.sock, RTNLGRP_LINK);
262 static void system_set_sysctl(const char *path, const char *val)
266 fd = open(path, O_WRONLY);
270 if (write(fd, val, strlen(val))) {}
274 static void system_set_dev_sysctl(const char *path, const char *device, const char *val)
276 snprintf(dev_buf, sizeof(dev_buf), path, device);
277 system_set_sysctl(dev_buf, val);
280 static void system_set_disable_ipv6(struct device *dev, const char *val)
282 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val);
285 static void system_set_rpfilter(struct device *dev, const char *val)
287 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter", dev->ifname, val);
290 static void system_set_acceptlocal(struct device *dev, const char *val)
292 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local", dev->ifname, val);
295 static void system_set_igmpversion(struct device *dev, const char *val)
297 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version", dev->ifname, val);
300 static void system_set_mldversion(struct device *dev, const char *val)
302 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version", dev->ifname, val);
305 static void system_set_neigh4reachabletime(struct device *dev, const char *val)
307 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms", dev->ifname, val);
310 static void system_set_neigh6reachabletime(struct device *dev, const char *val)
312 system_set_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms", dev->ifname, val);
315 static void system_set_neigh4gcstaletime(struct device *dev, const char *val)
317 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/gc_stale_time", dev->ifname, val);
320 static void system_set_neigh6gcstaletime(struct device *dev, const char *val)
322 system_set_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/gc_stale_time", dev->ifname, val);
325 static void system_set_neigh4locktime(struct device *dev, const char *val)
327 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/locktime", dev->ifname, val);
330 static void system_set_dadtransmits(struct device *dev, const char *val)
332 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits", dev->ifname, val);
335 static void system_bridge_set_multicast_to_unicast(struct device *dev, const char *val)
337 system_set_dev_sysctl("/sys/class/net/%s/brport/multicast_to_unicast", dev->ifname, val);
340 static void system_bridge_set_multicast_fast_leave(struct device *dev, const char *val)
342 system_set_dev_sysctl("/sys/class/net/%s/brport/multicast_fast_leave", dev->ifname, val);
345 static void system_bridge_set_hairpin_mode(struct device *dev, const char *val)
347 system_set_dev_sysctl("/sys/class/net/%s/brport/hairpin_mode", dev->ifname, val);
350 static void system_bridge_set_isolated(struct device *dev, const char *val)
352 system_set_dev_sysctl("/sys/class/net/%s/brport/isolated", dev->ifname, val);
355 static void system_bridge_set_multicast_router(struct device *dev, const char *val, bool bridge)
357 system_set_dev_sysctl(bridge ? "/sys/class/net/%s/bridge/multicast_router" :
358 "/sys/class/net/%s/brport/multicast_router",
362 static void system_bridge_set_robustness(struct device *dev, const char *val)
364 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_startup_query_count",
366 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_last_member_count",
370 static void system_bridge_set_query_interval(struct device *dev, const char *val)
372 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_query_interval",
376 static void system_bridge_set_query_response_interval(struct device *dev, const char *val)
378 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_query_response_interval",
382 static void system_bridge_set_last_member_interval(struct device *dev, const char *val)
384 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_last_member_interval",
388 static void system_bridge_set_membership_interval(struct device *dev, const char *val)
390 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_membership_interval",
394 static void system_bridge_set_other_querier_timeout(struct device *dev, const char *val)
396 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier_interval",
400 static void system_bridge_set_startup_query_interval(struct device *dev, const char *val)
402 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_startup_query_interval",
406 static void system_bridge_set_learning(struct device *dev, const char *val)
408 system_set_dev_sysctl("/sys/class/net/%s/brport/learning", dev->ifname, val);
411 static void system_bridge_set_unicast_flood(struct device *dev, const char *val)
413 system_set_dev_sysctl("/sys/class/net/%s/brport/unicast_flood", dev->ifname, val);
416 static void system_set_sendredirects(struct device *dev, const char *val)
418 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/send_redirects", dev->ifname, val);
421 static int system_get_sysctl(const char *path, char *buf, const size_t buf_sz)
423 int fd = -1, ret = -1;
425 fd = open(path, O_RDONLY);
429 ssize_t len = read(fd, buf, buf_sz - 1);
443 system_get_dev_sysctl(const char *path, const char *device, char *buf, const size_t buf_sz)
445 snprintf(dev_buf, sizeof(dev_buf), path, device);
446 return system_get_sysctl(dev_buf, buf, buf_sz);
449 static int system_get_disable_ipv6(struct device *dev, char *buf, const size_t buf_sz)
451 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6",
452 dev->ifname, buf, buf_sz);
455 static int system_get_rpfilter(struct device *dev, char *buf, const size_t buf_sz)
457 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter",
458 dev->ifname, buf, buf_sz);
461 static int system_get_acceptlocal(struct device *dev, char *buf, const size_t buf_sz)
463 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local",
464 dev->ifname, buf, buf_sz);
467 static int system_get_igmpversion(struct device *dev, char *buf, const size_t buf_sz)
469 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version",
470 dev->ifname, buf, buf_sz);
473 static int system_get_mldversion(struct device *dev, char *buf, const size_t buf_sz)
475 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version",
476 dev->ifname, buf, buf_sz);
479 static int system_get_neigh4reachabletime(struct device *dev, char *buf, const size_t buf_sz)
481 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms",
482 dev->ifname, buf, buf_sz);
485 static int system_get_neigh6reachabletime(struct device *dev, char *buf, const size_t buf_sz)
487 return system_get_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms",
488 dev->ifname, buf, buf_sz);
491 static int system_get_neigh4gcstaletime(struct device *dev, char *buf, const size_t buf_sz)
493 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/gc_stale_time",
494 dev->ifname, buf, buf_sz);
497 static int system_get_neigh6gcstaletime(struct device *dev, char *buf, const size_t buf_sz)
499 return system_get_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/gc_stale_time",
500 dev->ifname, buf, buf_sz);
503 static int system_get_neigh4locktime(struct device *dev, char *buf, const size_t buf_sz)
505 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/locktime",
506 dev->ifname, buf, buf_sz);
509 static int system_get_dadtransmits(struct device *dev, char *buf, const size_t buf_sz)
511 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits",
512 dev->ifname, buf, buf_sz);
515 static int system_get_sendredirects(struct device *dev, char *buf, const size_t buf_sz)
517 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/send_redirects",
518 dev->ifname, buf, buf_sz);
521 // Evaluate netlink messages
522 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
524 struct nlmsghdr *nh = nlmsg_hdr(msg);
525 struct nlattr *nla[__IFLA_MAX];
529 if (nh->nlmsg_type != RTM_NEWLINK)
532 nlmsg_parse(nh, sizeof(struct ifinfomsg), nla, __IFLA_MAX - 1, NULL);
533 if (!nla[IFLA_IFNAME])
536 struct device *dev = device_find(nla_data(nla[IFLA_IFNAME]));
540 if (!system_get_dev_sysctl("/sys/class/net/%s/carrier", dev->ifname, buf, sizeof(buf)))
541 link_state = strtoul(buf, NULL, 0);
543 device_set_link(dev, link_state ? true : false);
550 handle_hotplug_msg(char *data, int size)
552 const char *subsystem = NULL, *interface = NULL, *interface_old = NULL;
553 char *cur, *end, *sep;
556 bool add, move = false;
558 if (!strncmp(data, "add@", 4))
560 else if (!strncmp(data, "remove@", 7))
562 else if (!strncmp(data, "move@", 5)) {
569 skip = strlen(data) + 1;
572 for (cur = data + skip; cur < end; cur += skip) {
573 skip = strlen(cur) + 1;
575 sep = strchr(cur, '=');
580 if (!strcmp(cur, "INTERFACE"))
582 else if (!strcmp(cur, "SUBSYSTEM")) {
584 if (strcmp(subsystem, "net") != 0)
586 } else if (!strcmp(cur, "DEVPATH_OLD")) {
587 interface_old = strrchr(sep + 1, '/');
593 if (subsystem && interface) {
594 if (move && interface_old)
603 dev = device_find(interface_old);
607 if (dev->type != &simple_device_type)
610 device_set_present(dev, false);
613 dev = device_find(interface);
617 if (dev->type != &simple_device_type)
620 if (add && system_if_force_external(dev->ifname))
623 device_set_present(dev, add);
627 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
629 struct event_socket *ev = container_of(u, struct event_socket, uloop);
630 struct sockaddr_nl nla;
631 unsigned char *buf = NULL;
634 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
636 handle_hotplug_msg((char *) buf, size);
642 static int system_rtnl_call(struct nl_msg *msg)
646 ret = nl_send_auto_complete(sock_rtnl, msg);
652 return nl_wait_for_ack(sock_rtnl);
655 int system_bridge_delbr(struct device *bridge)
657 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
660 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
664 memset(&ifr, 0, sizeof(ifr));
666 ifr.ifr_ifindex = dev->ifindex;
669 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name) - 1);
670 return ioctl(sock_ioctl, cmd, &ifr);
673 static bool system_is_bridge(const char *name, char *buf, int buflen)
677 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
678 if (stat(buf, &st) < 0)
684 static char *system_get_bridge(const char *name, char *buf, int buflen)
690 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
691 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
695 len = readlink(gl.gl_pathv[0], buf, buflen);
703 path = strrchr(buf, '/');
711 system_bridge_set_wireless(struct device *bridge, struct device *dev)
713 bool mcast_to_ucast = dev->wireless_ap;
716 if (bridge->settings.flags & DEV_OPT_MULTICAST_TO_UNICAST &&
717 !bridge->settings.multicast_to_unicast)
718 mcast_to_ucast = false;
720 if (!mcast_to_ucast || dev->wireless_isolate)
723 system_bridge_set_multicast_to_unicast(dev, mcast_to_ucast ? "1" : "0");
724 system_bridge_set_hairpin_mode(dev, hairpin ? "1" : "0");
727 int system_bridge_addif(struct device *bridge, struct device *dev)
733 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
734 if (!oldbr || strcmp(oldbr, bridge->ifname) != 0)
735 ret = system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
738 system_bridge_set_wireless(bridge, dev);
740 if (dev->settings.flags & DEV_OPT_MULTICAST_ROUTER) {
741 snprintf(buf, sizeof(buf), "%u", dev->settings.multicast_router);
742 system_bridge_set_multicast_router(dev, buf, false);
745 if (dev->settings.flags & DEV_OPT_MULTICAST_FAST_LEAVE &&
746 dev->settings.multicast_fast_leave)
747 system_bridge_set_multicast_fast_leave(dev, "1");
749 if (dev->settings.flags & DEV_OPT_LEARNING &&
750 !dev->settings.learning)
751 system_bridge_set_learning(dev, "0");
753 if (dev->settings.flags & DEV_OPT_UNICAST_FLOOD &&
754 !dev->settings.unicast_flood)
755 system_bridge_set_unicast_flood(dev, "0");
757 if (dev->settings.flags & DEV_OPT_ISOLATE &&
758 dev->settings.isolate)
759 system_bridge_set_isolated(dev, "1");
764 int system_bridge_delif(struct device *bridge, struct device *dev)
766 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
769 int system_if_resolve(struct device *dev)
772 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
773 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
774 return ifr.ifr_ifindex;
779 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
783 memset(&ifr, 0, sizeof(ifr));
784 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1);
785 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) < 0)
788 ifr.ifr_flags |= add;
789 ifr.ifr_flags &= ~rem;
790 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
802 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
804 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
806 return ifa->ifa_index == ifindex;
809 static bool check_route(struct nlmsghdr *hdr, int ifindex)
811 struct rtmsg *r = NLMSG_DATA(hdr);
812 struct nlattr *tb[__RTA_MAX];
814 if (r->rtm_protocol == RTPROT_KERNEL &&
815 r->rtm_family == AF_INET6)
818 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
822 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
825 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
830 static int cb_clear_event(struct nl_msg *msg, void *arg)
832 struct clear_data *clr = arg;
833 struct nlmsghdr *hdr = nlmsg_hdr(msg);
834 bool (*cb)(struct nlmsghdr *, int ifindex);
840 if (hdr->nlmsg_type != RTM_NEWADDR)
847 if (hdr->nlmsg_type != RTM_NEWROUTE)
854 if (hdr->nlmsg_type != RTM_NEWRULE)
863 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
866 if (type == RTM_DELRULE)
867 D(SYSTEM, "Remove a rule\n");
869 D(SYSTEM, "Remove %s from device %s\n",
870 type == RTM_DELADDR ? "an address" : "a route",
872 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
873 hdr = nlmsg_hdr(clr->msg);
874 hdr->nlmsg_type = type;
875 hdr->nlmsg_flags = NLM_F_REQUEST;
877 nl_socket_disable_auto_ack(sock_rtnl);
878 nl_send_auto_complete(sock_rtnl, clr->msg);
879 nl_socket_enable_auto_ack(sock_rtnl);
885 cb_finish_event(struct nl_msg *msg, void *arg)
893 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
896 *pending = err->error;
901 system_if_clear_entries(struct device *dev, int type, int af)
903 struct clear_data clr;
904 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
907 .rtm_flags = RTM_F_CLONED,
909 int flags = NLM_F_DUMP;
918 clr.size = sizeof(struct rtgenmsg);
921 clr.size = sizeof(struct rtmsg);
930 clr.msg = nlmsg_alloc_simple(type, flags);
934 nlmsg_append(clr.msg, &rtm, clr.size, 0);
935 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
936 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
937 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
939 nl_send_auto_complete(sock_rtnl, clr.msg);
941 nl_recvmsgs(sock_rtnl, cb);
949 * Clear bridge (membership) state and bring down device
951 void system_if_clear_state(struct device *dev)
953 static char buf[256];
956 device_set_ifindex(dev, system_if_resolve(dev));
957 if (dev->external || !dev->ifindex)
960 system_if_flags(dev->ifname, 0, IFF_UP);
962 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
963 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
964 system_bridge_delbr(dev);
968 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
970 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
971 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
974 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
975 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
976 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
977 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
978 system_set_disable_ipv6(dev, "0");
981 static inline unsigned long
982 sec_to_jiffies(int val)
984 return (unsigned long) val * 100;
987 static void system_bridge_conf_multicast_deps(struct device *bridge,
988 struct bridge_config *cfg,
994 if (cfg->flags & BRIDGE_OPT_ROBUSTNESS ||
995 cfg->flags & BRIDGE_OPT_QUERY_INTERVAL ||
996 cfg->flags & BRIDGE_OPT_QUERY_RESPONSE_INTERVAL) {
997 val = cfg->robustness * cfg->query_interval +
998 cfg->query_response_interval;
1000 snprintf(buf, buf_len, "%i", val);
1001 system_bridge_set_membership_interval(bridge, buf);
1003 val = cfg->robustness * cfg->query_interval +
1004 cfg->query_response_interval / 2;
1006 snprintf(buf, buf_len, "%i", val);
1007 system_bridge_set_other_querier_timeout(bridge, buf);
1010 if (cfg->flags & BRIDGE_OPT_QUERY_INTERVAL) {
1011 val = cfg->query_interval / 4;
1013 snprintf(buf, buf_len, "%i", val);
1014 system_bridge_set_startup_query_interval(bridge, buf);
1018 static void system_bridge_conf_multicast(struct device *bridge,
1019 struct bridge_config *cfg,
1023 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
1024 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
1026 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier",
1027 bridge->ifname, cfg->multicast_querier ? "1" : "0");
1029 snprintf(buf, buf_len, "%i", cfg->hash_max);
1030 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/hash_max",
1031 bridge->ifname, buf);
1033 if (bridge->settings.flags & DEV_OPT_MULTICAST_ROUTER) {
1034 snprintf(buf, buf_len, "%u", bridge->settings.multicast_router);
1035 system_bridge_set_multicast_router(bridge, buf, true);
1038 if (cfg->flags & BRIDGE_OPT_ROBUSTNESS) {
1039 snprintf(buf, buf_len, "%i", cfg->robustness);
1040 system_bridge_set_robustness(bridge, buf);
1043 if (cfg->flags & BRIDGE_OPT_QUERY_INTERVAL) {
1044 snprintf(buf, buf_len, "%i", cfg->query_interval);
1045 system_bridge_set_query_interval(bridge, buf);
1048 if (cfg->flags & BRIDGE_OPT_QUERY_RESPONSE_INTERVAL) {
1049 snprintf(buf, buf_len, "%i", cfg->query_response_interval);
1050 system_bridge_set_query_response_interval(bridge, buf);
1053 if (cfg->flags & BRIDGE_OPT_LAST_MEMBER_INTERVAL) {
1054 snprintf(buf, buf_len, "%i", cfg->last_member_interval);
1055 system_bridge_set_last_member_interval(bridge, buf);
1058 system_bridge_conf_multicast_deps(bridge, cfg, buf, buf_len);
1061 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
1064 unsigned long args[4] = {};
1066 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
1069 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
1070 args[1] = !!cfg->stp;
1071 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1073 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
1074 args[1] = sec_to_jiffies(cfg->forward_delay);
1075 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1077 system_bridge_conf_multicast(bridge, cfg, buf, sizeof(buf));
1079 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
1080 args[1] = cfg->priority;
1081 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1083 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
1084 args[0] = BRCTL_SET_AGEING_TIME;
1085 args[1] = sec_to_jiffies(cfg->ageing_time);
1086 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1089 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
1090 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
1091 args[1] = sec_to_jiffies(cfg->hello_time);
1092 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1095 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
1096 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
1097 args[1] = sec_to_jiffies(cfg->max_age);
1098 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1104 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
1107 struct nlattr *linkinfo, *data;
1108 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
1110 static const struct {
1112 enum macvlan_mode val;
1114 { "private", MACVLAN_MODE_PRIVATE },
1115 { "vepa", MACVLAN_MODE_VEPA },
1116 { "bridge", MACVLAN_MODE_BRIDGE },
1117 { "passthru", MACVLAN_MODE_PASSTHRU },
1120 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1125 nlmsg_append(msg, &iim, sizeof(iim), 0);
1127 if (cfg->flags & MACVLAN_OPT_MACADDR)
1128 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
1129 nla_put_string(msg, IFLA_IFNAME, macvlan->ifname);
1130 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
1132 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1133 goto nla_put_failure;
1135 nla_put_string(msg, IFLA_INFO_KIND, "macvlan");
1137 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1138 goto nla_put_failure;
1141 for (i = 0; i < ARRAY_SIZE(modes); i++) {
1142 if (strcmp(cfg->mode, modes[i].name) != 0)
1145 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
1150 nla_nest_end(msg, data);
1151 nla_nest_end(msg, linkinfo);
1153 rv = system_rtnl_call(msg);
1155 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
1164 static int system_link_del(const char *ifname)
1167 struct ifinfomsg iim = {
1168 .ifi_family = AF_UNSPEC,
1172 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
1177 nlmsg_append(msg, &iim, sizeof(iim), 0);
1178 nla_put_string(msg, IFLA_IFNAME, ifname);
1179 return system_rtnl_call(msg);
1182 int system_macvlan_del(struct device *macvlan)
1184 return system_link_del(macvlan->ifname);
1187 int system_veth_add(struct device *veth, struct veth_config *cfg)
1190 struct ifinfomsg empty_iim = {};
1191 struct nlattr *linkinfo, *data, *veth_info;
1194 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1199 nlmsg_append(msg, &empty_iim, sizeof(empty_iim), 0);
1201 if (cfg->flags & VETH_OPT_MACADDR)
1202 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
1203 nla_put_string(msg, IFLA_IFNAME, veth->ifname);
1205 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1206 goto nla_put_failure;
1208 nla_put_string(msg, IFLA_INFO_KIND, "veth");
1210 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1211 goto nla_put_failure;
1213 if (!(veth_info = nla_nest_start(msg, VETH_INFO_PEER)))
1214 goto nla_put_failure;
1216 nlmsg_append(msg, &empty_iim, sizeof(empty_iim), 0);
1218 if (cfg->flags & VETH_OPT_PEER_NAME)
1219 nla_put_string(msg, IFLA_IFNAME, cfg->peer_name);
1220 if (cfg->flags & VETH_OPT_PEER_MACADDR)
1221 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->peer_macaddr), cfg->peer_macaddr);
1223 nla_nest_end(msg, veth_info);
1224 nla_nest_end(msg, data);
1225 nla_nest_end(msg, linkinfo);
1227 rv = system_rtnl_call(msg);
1229 if (cfg->flags & VETH_OPT_PEER_NAME)
1230 D(SYSTEM, "Error adding veth '%s' with peer '%s': %d\n", veth->ifname, cfg->peer_name, rv);
1232 D(SYSTEM, "Error adding veth '%s': %d\n", veth->ifname, rv);
1242 int system_veth_del(struct device *veth)
1244 return system_link_del(veth->ifname);
1247 static int system_vlan(struct device *dev, int id)
1249 struct vlan_ioctl_args ifr = {
1250 .cmd = SET_VLAN_NAME_TYPE_CMD,
1251 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
1254 if (ioctl(sock_ioctl, SIOCSIFVLAN, &ifr) < 0)
1258 ifr.cmd = DEL_VLAN_CMD;
1261 ifr.cmd = ADD_VLAN_CMD;
1264 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
1265 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
1268 int system_vlan_add(struct device *dev, int id)
1270 return system_vlan(dev, id);
1273 int system_vlan_del(struct device *dev)
1275 return system_vlan(dev, -1);
1278 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
1281 struct nlattr *linkinfo, *data;
1282 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
1285 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1290 nlmsg_append(msg, &iim, sizeof(iim), 0);
1291 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
1292 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
1294 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1295 goto nla_put_failure;
1297 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
1299 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1300 goto nla_put_failure;
1302 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
1304 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
1305 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
1307 if(cfg->proto == VLAN_PROTO_8021AD)
1308 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);
1311 nla_nest_end(msg, data);
1312 nla_nest_end(msg, linkinfo);
1314 rv = system_rtnl_call(msg);
1316 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
1325 int system_vlandev_del(struct device *vlandev)
1327 return system_link_del(vlandev->ifname);
1331 system_if_get_settings(struct device *dev, struct device_settings *s)
1336 memset(&ifr, 0, sizeof(ifr));
1337 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
1339 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
1340 s->mtu = ifr.ifr_mtu;
1341 s->flags |= DEV_OPT_MTU;
1344 s->mtu6 = system_update_ipv6_mtu(dev, 0);
1346 s->flags |= DEV_OPT_MTU6;
1348 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
1349 s->txqueuelen = ifr.ifr_qlen;
1350 s->flags |= DEV_OPT_TXQUEUELEN;
1353 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
1354 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
1355 s->flags |= DEV_OPT_MACADDR;
1358 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
1359 s->ipv6 = !strtoul(buf, NULL, 0);
1360 s->flags |= DEV_OPT_IPV6;
1363 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
1364 s->promisc = ifr.ifr_flags & IFF_PROMISC;
1365 s->flags |= DEV_OPT_PROMISC;
1367 s->multicast = ifr.ifr_flags & IFF_MULTICAST;
1368 s->flags |= DEV_OPT_MULTICAST;
1371 if (!system_get_rpfilter(dev, buf, sizeof(buf))) {
1372 s->rpfilter = strtoul(buf, NULL, 0);
1373 s->flags |= DEV_OPT_RPFILTER;
1376 if (!system_get_acceptlocal(dev, buf, sizeof(buf))) {
1377 s->acceptlocal = strtoul(buf, NULL, 0);
1378 s->flags |= DEV_OPT_ACCEPTLOCAL;
1381 if (!system_get_igmpversion(dev, buf, sizeof(buf))) {
1382 s->igmpversion = strtoul(buf, NULL, 0);
1383 s->flags |= DEV_OPT_IGMPVERSION;
1386 if (!system_get_mldversion(dev, buf, sizeof(buf))) {
1387 s->mldversion = strtoul(buf, NULL, 0);
1388 s->flags |= DEV_OPT_MLDVERSION;
1391 if (!system_get_neigh4reachabletime(dev, buf, sizeof(buf))) {
1392 s->neigh4reachabletime = strtoul(buf, NULL, 0);
1393 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1396 if (!system_get_neigh6reachabletime(dev, buf, sizeof(buf))) {
1397 s->neigh6reachabletime = strtoul(buf, NULL, 0);
1398 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1401 if (!system_get_neigh4locktime(dev, buf, sizeof(buf))) {
1402 s->neigh4locktime = strtol(buf, NULL, 0);
1403 s->flags |= DEV_OPT_NEIGHLOCKTIME;
1406 if (!system_get_neigh4gcstaletime(dev, buf, sizeof(buf))) {
1407 s->neigh4gcstaletime = strtoul(buf, NULL, 0);
1408 s->flags |= DEV_OPT_NEIGHGCSTALETIME;
1411 if (!system_get_neigh6gcstaletime(dev, buf, sizeof(buf))) {
1412 s->neigh6gcstaletime = strtoul(buf, NULL, 0);
1413 s->flags |= DEV_OPT_NEIGHGCSTALETIME;
1416 if (!system_get_dadtransmits(dev, buf, sizeof(buf))) {
1417 s->dadtransmits = strtoul(buf, NULL, 0);
1418 s->flags |= DEV_OPT_DADTRANSMITS;
1421 if (!system_get_sendredirects(dev, buf, sizeof(buf))) {
1422 s->sendredirects = strtoul(buf, NULL, 0);
1423 s->flags |= DEV_OPT_SENDREDIRECTS;
1428 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
1433 memset(&ifr, 0, sizeof(ifr));
1434 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
1435 if (s->flags & DEV_OPT_MTU & apply_mask) {
1436 ifr.ifr_mtu = s->mtu;
1437 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
1438 s->flags &= ~DEV_OPT_MTU;
1440 if (s->flags & DEV_OPT_MTU6 & apply_mask) {
1441 system_update_ipv6_mtu(dev, s->mtu6);
1443 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
1444 ifr.ifr_qlen = s->txqueuelen;
1445 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
1446 s->flags &= ~DEV_OPT_TXQUEUELEN;
1448 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
1449 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
1450 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
1451 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
1452 s->flags &= ~DEV_OPT_MACADDR;
1454 if (s->flags & DEV_OPT_IPV6 & apply_mask)
1455 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
1456 if (s->flags & DEV_OPT_PROMISC & apply_mask) {
1457 if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
1458 !s->promisc ? IFF_PROMISC : 0) < 0)
1459 s->flags &= ~DEV_OPT_PROMISC;
1461 if (s->flags & DEV_OPT_RPFILTER & apply_mask) {
1462 snprintf(buf, sizeof(buf), "%u", s->rpfilter);
1463 system_set_rpfilter(dev, buf);
1465 if (s->flags & DEV_OPT_ACCEPTLOCAL & apply_mask)
1466 system_set_acceptlocal(dev, s->acceptlocal ? "1" : "0");
1467 if (s->flags & DEV_OPT_IGMPVERSION & apply_mask) {
1468 snprintf(buf, sizeof(buf), "%u", s->igmpversion);
1469 system_set_igmpversion(dev, buf);
1471 if (s->flags & DEV_OPT_MLDVERSION & apply_mask) {
1472 snprintf(buf, sizeof(buf), "%u", s->mldversion);
1473 system_set_mldversion(dev, buf);
1475 if (s->flags & DEV_OPT_NEIGHREACHABLETIME & apply_mask) {
1476 snprintf(buf, sizeof(buf), "%u", s->neigh4reachabletime);
1477 system_set_neigh4reachabletime(dev, buf);
1478 snprintf(buf, sizeof(buf), "%u", s->neigh6reachabletime);
1479 system_set_neigh6reachabletime(dev, buf);
1481 if (s->flags & DEV_OPT_NEIGHLOCKTIME & apply_mask) {
1482 snprintf(buf, sizeof(buf), "%d", s->neigh4locktime);
1483 system_set_neigh4locktime(dev, buf);
1485 if (s->flags & DEV_OPT_NEIGHGCSTALETIME & apply_mask) {
1486 snprintf(buf, sizeof(buf), "%u", s->neigh4gcstaletime);
1487 system_set_neigh4gcstaletime(dev, buf);
1488 snprintf(buf, sizeof(buf), "%u", s->neigh6gcstaletime);
1489 system_set_neigh6gcstaletime(dev, buf);
1491 if (s->flags & DEV_OPT_DADTRANSMITS & apply_mask) {
1492 snprintf(buf, sizeof(buf), "%u", s->dadtransmits);
1493 system_set_dadtransmits(dev, buf);
1495 if (s->flags & DEV_OPT_MULTICAST & apply_mask) {
1496 if (system_if_flags(dev->ifname, s->multicast ? IFF_MULTICAST : 0,
1497 !s->multicast ? IFF_MULTICAST : 0) < 0)
1498 s->flags &= ~DEV_OPT_MULTICAST;
1500 if (s->flags & DEV_OPT_SENDREDIRECTS & apply_mask)
1501 system_set_sendredirects(dev, s->sendredirects ? "1" : "0");
1504 int system_if_up(struct device *dev)
1506 system_if_get_settings(dev, &dev->orig_settings);
1507 /* Only keep orig settings based on what needs to be set */
1508 dev->orig_settings.valid_flags = dev->orig_settings.flags;
1509 dev->orig_settings.flags &= dev->settings.flags;
1510 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
1511 return system_if_flags(dev->ifname, IFF_UP, 0);
1514 int system_if_down(struct device *dev)
1516 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
1517 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
1521 struct if_check_data {
1527 #ifndef IFF_LOWER_UP
1528 #define IFF_LOWER_UP 0x10000
1531 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1533 struct nlmsghdr *nh = nlmsg_hdr(msg);
1534 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1535 struct if_check_data *chk = (struct if_check_data *)arg;
1537 if (nh->nlmsg_type != RTM_NEWLINK)
1540 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1541 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1546 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1548 struct if_check_data *chk = (struct if_check_data *)arg;
1553 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1555 struct if_check_data *chk = (struct if_check_data *)arg;
1557 device_set_present(chk->dev, false);
1558 device_set_link(chk->dev, false);
1559 chk->pending = err->error;
1564 int system_if_check(struct device *dev)
1566 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1568 struct ifinfomsg ifi = {
1569 .ifi_family = AF_UNSPEC,
1572 struct if_check_data chk = {
1581 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1585 if (nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1586 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1589 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1590 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1591 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1593 nl_send_auto_complete(sock_rtnl, msg);
1594 while (chk.pending > 0)
1595 nl_recvmsgs(sock_rtnl, cb);
1607 system_if_get_parent(struct device *dev)
1609 char buf[64], *devname;
1610 int ifindex, iflink, len;
1613 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1614 f = fopen(buf, "r");
1618 len = fread(buf, 1, sizeof(buf) - 1, f);
1625 iflink = strtoul(buf, NULL, 0);
1626 ifindex = system_if_resolve(dev);
1627 if (!iflink || iflink == ifindex)
1630 devname = if_indextoname(iflink, buf);
1634 return device_get(devname, true);
1638 read_string_file(int dir_fd, const char *file, char *buf, int len)
1644 fd = openat(dir_fd, file, O_RDONLY);
1649 len = read(fd, buf, len - 1);
1653 } else if (len > 0) {
1656 c = strchr(buf, '\n');
1669 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1674 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1676 *val = strtoull(buf, NULL, 0);
1681 /* Assume advertised flags == supported flags */
1682 static const struct {
1685 } ethtool_link_modes[] = {
1686 { ADVERTISED_10baseT_Half, "10baseT-H" },
1687 { ADVERTISED_10baseT_Full, "10baseT-F" },
1688 { ADVERTISED_100baseT_Half, "100baseT-H" },
1689 { ADVERTISED_100baseT_Full, "100baseT-F" },
1690 { ADVERTISED_1000baseT_Half, "1000baseT-H" },
1691 { ADVERTISED_1000baseT_Full, "1000baseT-F" },
1692 { ADVERTISED_1000baseKX_Full, "1000baseKX-F" },
1693 { ADVERTISED_2500baseX_Full, "2500baseX-F" },
1694 { ADVERTISED_10000baseT_Full, "10000baseT-F" },
1695 { ADVERTISED_10000baseKX4_Full, "10000baseKX4-F" },
1696 { ADVERTISED_10000baseKR_Full, "10000baseKR-F" },
1697 { ADVERTISED_20000baseMLD2_Full, "20000baseMLD2-F" },
1698 { ADVERTISED_20000baseKR2_Full, "20000baseKR2-F" },
1699 { ADVERTISED_40000baseKR4_Full, "40000baseKR4-F" },
1700 { ADVERTISED_40000baseCR4_Full, "40000baseCR4-F" },
1701 { ADVERTISED_40000baseSR4_Full, "40000baseSR4-F" },
1702 { ADVERTISED_40000baseLR4_Full, "40000baseLR4-F" },
1703 #ifdef ADVERTISED_56000baseKR4_Full
1704 { ADVERTISED_56000baseKR4_Full, "56000baseKR4-F" },
1705 { ADVERTISED_56000baseCR4_Full, "56000baseCR4-F" },
1706 { ADVERTISED_56000baseSR4_Full, "56000baseSR4-F" },
1707 { ADVERTISED_56000baseLR4_Full, "56000baseLR4-F" },
1711 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1714 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1715 if (mask & ethtool_link_modes[i].mask)
1716 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1721 system_if_force_external(const char *ifname)
1726 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1727 return stat(buf, &s) == 0;
1731 system_if_dump_info(struct device *dev, struct blob_buf *b)
1733 struct ethtool_cmd ecmd;
1738 memset(&ecmd, 0, sizeof(ecmd));
1739 memset(&ifr, 0, sizeof(ifr));
1740 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
1741 ifr.ifr_data = (caddr_t) &ecmd;
1742 ecmd.cmd = ETHTOOL_GSET;
1744 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1745 c = blobmsg_open_array(b, "link-advertising");
1746 system_add_link_modes(b, ecmd.advertising);
1747 blobmsg_close_array(b, c);
1749 c = blobmsg_open_array(b, "link-partner-advertising");
1750 system_add_link_modes(b, ecmd.lp_advertising);
1751 blobmsg_close_array(b, c);
1753 c = blobmsg_open_array(b, "link-supported");
1754 system_add_link_modes(b, ecmd.supported);
1755 blobmsg_close_array(b, c);
1757 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1758 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1759 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1760 blobmsg_add_string_buffer(b);
1762 blobmsg_add_u8(b, "autoneg", !!ecmd.autoneg);
1769 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1771 const char *const counters[] = {
1772 "collisions", "rx_frame_errors", "tx_compressed",
1773 "multicast", "rx_length_errors", "tx_dropped",
1774 "rx_bytes", "rx_missed_errors", "tx_errors",
1775 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1776 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1777 "rx_dropped", "tx_aborted_errors", "tx_packets",
1778 "rx_errors", "tx_bytes", "tx_window_errors",
1779 "rx_fifo_errors", "tx_carrier_errors",
1786 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1787 stats_dir = open(buf, O_DIRECTORY);
1791 for (i = 0; i < ARRAY_SIZE(counters); i++)
1792 if (read_uint64_file(stats_dir, counters[i], &val))
1793 blobmsg_add_u64(b, counters[i], val);
1799 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1801 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1802 int alen = v4 ? 4 : 16;
1803 unsigned int flags = 0;
1804 struct ifaddrmsg ifa = {
1805 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1806 .ifa_prefixlen = addr->mask,
1807 .ifa_index = dev->ifindex,
1811 if (cmd == RTM_NEWADDR)
1812 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1814 msg = nlmsg_alloc_simple(cmd, flags);
1818 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1819 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1821 if (addr->broadcast)
1822 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1823 if (addr->point_to_point)
1824 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1826 time_t now = system_get_rtime();
1827 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1829 if (addr->preferred_until) {
1830 int64_t preferred = addr->preferred_until - now;
1833 else if (preferred > UINT32_MAX)
1834 preferred = UINT32_MAX;
1836 cinfo.ifa_prefered = preferred;
1839 if (addr->valid_until) {
1840 int64_t valid = addr->valid_until - now;
1845 else if (valid > UINT32_MAX)
1848 cinfo.ifa_valid = valid;
1851 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1853 if (cmd == RTM_NEWADDR && (addr->flags & DEVADDR_OFFLINK))
1854 nla_put_u32(msg, IFA_FLAGS, IFA_F_NOPREFIXROUTE);
1857 return system_rtnl_call(msg);
1860 int system_add_address(struct device *dev, struct device_addr *addr)
1862 return system_addr(dev, addr, RTM_NEWADDR);
1865 int system_del_address(struct device *dev, struct device_addr *addr)
1867 return system_addr(dev, addr, RTM_DELADDR);
1870 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1872 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1874 unsigned int flags = 0;
1877 have_gw = !!route->nexthop.in.s_addr;
1879 have_gw = route->nexthop.in6.s6_addr32[0] ||
1880 route->nexthop.in6.s6_addr32[1] ||
1881 route->nexthop.in6.s6_addr32[2] ||
1882 route->nexthop.in6.s6_addr32[3];
1884 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1885 ? route->table : RT_TABLE_MAIN;
1887 struct rtmsg rtm = {
1888 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1889 .rtm_dst_len = route->mask,
1890 .rtm_src_len = route->sourcemask,
1891 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1892 .rtm_protocol = (route->flags & DEVROUTE_PROTO) ? route->proto : RTPROT_STATIC,
1893 .rtm_scope = RT_SCOPE_NOWHERE,
1894 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1895 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1899 if (cmd == RTM_NEWROUTE) {
1900 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1902 if (!dev) { // Add null-route
1903 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1904 rtm.rtm_type = RTN_UNREACHABLE;
1907 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1910 if (route->flags & DEVROUTE_TYPE) {
1911 rtm.rtm_type = route->type;
1912 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
1913 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
1914 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
1915 rtm.rtm_table = RT_TABLE_LOCAL;
1918 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT) {
1919 rtm.rtm_scope = RT_SCOPE_HOST;
1920 } else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
1921 rtm.rtm_type == RTN_ANYCAST) {
1922 rtm.rtm_scope = RT_SCOPE_LINK;
1923 } else if (rtm.rtm_type == RTN_BLACKHOLE || rtm.rtm_type == RTN_UNREACHABLE ||
1924 rtm.rtm_type == RTN_PROHIBIT || rtm.rtm_type == RTN_FAILED_POLICY ||
1925 rtm.rtm_type == RTN_THROW) {
1926 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1931 msg = nlmsg_alloc_simple(cmd, flags);
1935 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1938 nla_put(msg, RTA_DST, alen, &route->addr);
1940 if (route->sourcemask) {
1941 if (rtm.rtm_family == AF_INET)
1942 nla_put(msg, RTA_PREFSRC, alen, &route->source);
1944 nla_put(msg, RTA_SRC, alen, &route->source);
1947 if (route->metric > 0)
1948 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1951 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1954 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1957 nla_put_u32(msg, RTA_TABLE, table);
1959 if (route->flags & DEVROUTE_MTU) {
1960 struct nlattr *metrics;
1962 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1963 goto nla_put_failure;
1965 nla_put_u32(msg, RTAX_MTU, route->mtu);
1967 nla_nest_end(msg, metrics);
1970 return system_rtnl_call(msg);
1977 int system_add_route(struct device *dev, struct device_route *route)
1979 return system_rt(dev, route, RTM_NEWROUTE);
1982 int system_del_route(struct device *dev, struct device_route *route)
1984 return system_rt(dev, route, RTM_DELROUTE);
1987 int system_flush_routes(void)
1989 const char *names[] = {
1990 "/proc/sys/net/ipv4/route/flush",
1991 "/proc/sys/net/ipv6/route/flush"
1995 for (i = 0; i < ARRAY_SIZE(names); i++) {
1996 fd = open(names[i], O_WRONLY);
2000 if (write(fd, "-1", 2)) {}
2006 bool system_resolve_rt_type(const char *type, unsigned int *id)
2008 return system_rtn_aton(type, id);
2011 bool system_resolve_rt_proto(const char *type, unsigned int *id)
2015 unsigned int n, proto = 256;
2016 n = strtoul(type, &e, 0);
2017 if (!*e && e != type)
2019 else if (!strcmp(type, "unspec"))
2020 proto = RTPROT_UNSPEC;
2021 else if (!strcmp(type, "kernel"))
2022 proto = RTPROT_KERNEL;
2023 else if (!strcmp(type, "boot"))
2024 proto = RTPROT_BOOT;
2025 else if (!strcmp(type, "static"))
2026 proto = RTPROT_STATIC;
2027 else if ((f = fopen("/etc/iproute2/rt_protos", "r")) != NULL) {
2028 while (fgets(buf, sizeof(buf) - 1, f) != NULL) {
2029 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
2032 n = strtoul(e, NULL, 10);
2033 e = strtok(NULL, " \t\n");
2035 if (e && !strcmp(e, type)) {
2050 bool system_resolve_rt_table(const char *name, unsigned int *id)
2054 unsigned int n, table = RT_TABLE_UNSPEC;
2056 /* first try to parse table as number */
2057 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
2060 /* handle well known aliases */
2061 else if (!strcmp(name, "default"))
2062 table = RT_TABLE_DEFAULT;
2063 else if (!strcmp(name, "main"))
2064 table = RT_TABLE_MAIN;
2065 else if (!strcmp(name, "local"))
2066 table = RT_TABLE_LOCAL;
2068 /* try to look up name in /etc/iproute2/rt_tables */
2069 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
2071 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
2073 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
2076 n = strtoul(e, NULL, 10);
2077 e = strtok(NULL, " \t\n");
2079 if (e && !strcmp(e, name))
2089 if (table == RT_TABLE_UNSPEC)
2096 bool system_is_default_rt_table(unsigned int id)
2098 return (id == RT_TABLE_MAIN);
2101 bool system_resolve_rpfilter(const char *filter, unsigned int *id)
2106 if (!strcmp(filter, "strict"))
2108 else if (!strcmp(filter, "loose"))
2111 n = strtoul(filter, &e, 0);
2112 if (*e || e == filter || n > 2)
2120 static int system_iprule(struct iprule *rule, int cmd)
2122 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
2125 struct rtmsg rtm = {
2126 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
2127 .rtm_protocol = RTPROT_STATIC,
2128 .rtm_scope = RT_SCOPE_UNIVERSE,
2129 .rtm_table = RT_TABLE_UNSPEC,
2130 .rtm_type = RTN_UNSPEC,
2134 if (cmd == RTM_NEWRULE)
2135 rtm.rtm_type = RTN_UNICAST;
2138 rtm.rtm_flags |= FIB_RULE_INVERT;
2140 if (rule->flags & IPRULE_SRC)
2141 rtm.rtm_src_len = rule->src_mask;
2143 if (rule->flags & IPRULE_DEST)
2144 rtm.rtm_dst_len = rule->dest_mask;
2146 if (rule->flags & IPRULE_TOS)
2147 rtm.rtm_tos = rule->tos;
2149 if (rule->flags & IPRULE_LOOKUP) {
2150 if (rule->lookup < 256)
2151 rtm.rtm_table = rule->lookup;
2154 if (rule->flags & IPRULE_ACTION)
2155 rtm.rtm_type = rule->action;
2156 else if (rule->flags & IPRULE_GOTO)
2157 rtm.rtm_type = FR_ACT_GOTO;
2158 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
2159 rtm.rtm_type = FR_ACT_NOP;
2161 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
2166 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
2168 if (rule->flags & IPRULE_IN)
2169 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
2171 if (rule->flags & IPRULE_OUT)
2172 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
2174 if (rule->flags & IPRULE_SRC)
2175 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
2177 if (rule->flags & IPRULE_DEST)
2178 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
2180 if (rule->flags & IPRULE_PRIORITY)
2181 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
2182 else if (cmd == RTM_NEWRULE)
2183 nla_put_u32(msg, FRA_PRIORITY, rule->order);
2185 if (rule->flags & IPRULE_FWMARK)
2186 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
2188 if (rule->flags & IPRULE_FWMASK)
2189 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
2191 if (rule->flags & IPRULE_LOOKUP) {
2192 if (rule->lookup >= 256)
2193 nla_put_u32(msg, FRA_TABLE, rule->lookup);
2196 if (rule->flags & IPRULE_SUP_PREFIXLEN)
2197 nla_put_u32(msg, FRA_SUPPRESS_PREFIXLEN, rule->sup_prefixlen);
2199 if (rule->flags & IPRULE_GOTO)
2200 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
2202 return system_rtnl_call(msg);
2205 int system_add_iprule(struct iprule *rule)
2207 return system_iprule(rule, RTM_NEWRULE);
2210 int system_del_iprule(struct iprule *rule)
2212 return system_iprule(rule, RTM_DELRULE);
2215 int system_flush_iprules(void)
2220 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
2221 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
2223 memset(&rule, 0, sizeof(rule));
2226 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2229 rule.lookup = RT_TABLE_LOCAL;
2230 rv |= system_iprule(&rule, RTM_NEWRULE);
2232 rule.priority = 32766;
2233 rule.lookup = RT_TABLE_MAIN;
2234 rv |= system_iprule(&rule, RTM_NEWRULE);
2236 rule.priority = 32767;
2237 rule.lookup = RT_TABLE_DEFAULT;
2238 rv |= system_iprule(&rule, RTM_NEWRULE);
2241 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2244 rule.lookup = RT_TABLE_LOCAL;
2245 rv |= system_iprule(&rule, RTM_NEWRULE);
2247 rule.priority = 32766;
2248 rule.lookup = RT_TABLE_MAIN;
2249 rv |= system_iprule(&rule, RTM_NEWRULE);
2254 bool system_resolve_iprule_action(const char *action, unsigned int *id)
2256 return system_rtn_aton(action, id);
2259 time_t system_get_rtime(void)
2264 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
2267 if (gettimeofday(&tv, NULL) == 0)
2274 #define IP_DF 0x4000
2277 static int tunnel_ioctl(const char *name, int cmd, void *p)
2281 memset(&ifr, 0, sizeof(ifr));
2282 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name) - 1);
2283 ifr.ifr_ifru.ifru_data = p;
2284 return ioctl(sock_ioctl, cmd, &ifr);
2287 #ifdef IFLA_IPTUN_MAX
2288 static int system_add_ip6_tunnel(const char *name, const unsigned int link,
2289 struct blob_attr **tb)
2291 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2292 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2293 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2294 struct blob_attr *cur;
2295 int ret = 0, ttl = 0;
2300 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2301 nla_put_string(nlm, IFLA_IFNAME, name);
2304 nla_put_u32(nlm, IFLA_LINK, link);
2306 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2312 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2313 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2320 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2322 if ((cur = tb[TUNNEL_ATTR_TTL]))
2323 ttl = blobmsg_get_u32(cur);
2325 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2326 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2328 struct in6_addr in6buf;
2329 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2330 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2334 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2337 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2338 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2342 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2345 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2346 struct blob_attr *tb_data[__IPIP6_DATA_ATTR_MAX];
2348 blobmsg_parse(ipip6_data_attr_list.params, __IPIP6_DATA_ATTR_MAX, tb_data,
2349 blobmsg_data(cur), blobmsg_len(cur));
2351 if ((cur = tb_data[IPIP6_DATA_ENCAPLIMIT])) {
2352 char *str = blobmsg_get_string(cur);
2354 if (strcmp(str, "ignore")) {
2356 unsigned encap_limit = strtoul(str, &e, 0);
2358 if (e == str || *e || encap_limit > 255) {
2363 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, encap_limit);
2365 nla_put_u32(nlm, IFLA_IPTUN_FLAGS, IP6_TNL_F_IGN_ENCAP_LIMIT);
2368 #ifdef IFLA_IPTUN_FMR_MAX
2369 if ((cur = tb_data[IPIP6_DATA_FMRS])) {
2370 struct blob_attr *rcur;
2371 unsigned rrem, fmrcnt = 0;
2372 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2379 blobmsg_for_each_attr(rcur, cur, rrem) {
2380 struct blob_attr *tb_fmr[__FMR_DATA_ATTR_MAX], *tb_cur;
2381 struct in6_addr ip6prefix;
2382 struct in_addr ip4prefix;
2383 unsigned ip4len, ip6len, ealen, offset;
2385 blobmsg_parse(fmr_data_attr_list.params, __FMR_DATA_ATTR_MAX, tb_fmr,
2386 blobmsg_data(rcur), blobmsg_len(rcur));
2388 if (!(tb_cur = tb_fmr[FMR_DATA_PREFIX6]) ||
2389 !parse_ip_and_netmask(AF_INET6,
2390 blobmsg_data(tb_cur), &ip6prefix,
2396 if (!(tb_cur = tb_fmr[FMR_DATA_PREFIX4]) ||
2397 !parse_ip_and_netmask(AF_INET,
2398 blobmsg_data(tb_cur), &ip4prefix,
2404 if (!(tb_cur = tb_fmr[FMR_DATA_EALEN])) {
2408 ealen = blobmsg_get_u32(tb_cur);
2410 if (!(tb_cur = tb_fmr[FMR_DATA_OFFSET])) {
2414 offset = blobmsg_get_u32(tb_cur);
2416 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2422 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2423 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2424 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2425 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2426 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2427 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2429 nla_nest_end(nlm, rule);
2432 nla_nest_end(nlm, fmrs);
2437 nla_nest_end(nlm, infodata);
2438 nla_nest_end(nlm, linkinfo);
2440 return system_rtnl_call(nlm);
2448 #ifdef IFLA_IPTUN_MAX
2449 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
2450 static int system_add_gre_tunnel(const char *name, const char *kind,
2451 const unsigned int link, struct blob_attr **tb, bool v6)
2454 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2455 struct blob_attr *cur;
2456 uint32_t ikey = 0, okey = 0, flags = 0, flowinfo = 0;
2457 uint16_t iflags = 0, oflags = 0;
2459 int ret = 0, ttl = 0;
2461 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2465 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2466 nla_put_string(nlm, IFLA_IFNAME, name);
2468 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2474 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2475 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2482 nla_put_u32(nlm, IFLA_GRE_LINK, link);
2484 if ((cur = tb[TUNNEL_ATTR_TTL]))
2485 ttl = blobmsg_get_u32(cur);
2487 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2488 char *str = blobmsg_get_string(cur);
2489 if (strcmp(str, "inherit")) {
2492 if (!system_tos_aton(str, &uval)) {
2498 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
2503 flags |= IP6_TNL_F_USE_ORIG_TCLASS;
2509 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2510 struct blob_attr *tb_data[__GRE_DATA_ATTR_MAX];
2512 blobmsg_parse(gre_data_attr_list.params, __GRE_DATA_ATTR_MAX, tb_data,
2513 blobmsg_data(cur), blobmsg_len(cur));
2515 if ((cur = tb_data[GRE_DATA_IKEY])) {
2516 if ((ikey = blobmsg_get_u32(cur)))
2520 if ((cur = tb_data[GRE_DATA_OKEY])) {
2521 if ((okey = blobmsg_get_u32(cur)))
2525 if ((cur = tb_data[GRE_DATA_ICSUM])) {
2526 if (blobmsg_get_bool(cur))
2530 if ((cur = tb_data[GRE_DATA_OCSUM])) {
2531 if (blobmsg_get_bool(cur))
2535 if ((cur = tb_data[GRE_DATA_ISEQNO])) {
2536 if (blobmsg_get_bool(cur))
2540 if ((cur = tb[GRE_DATA_OSEQNO])) {
2541 if (blobmsg_get_bool(cur))
2547 struct in6_addr in6buf;
2548 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2549 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2553 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
2556 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2557 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2561 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
2563 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, 4);
2566 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
2569 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags);
2574 struct in_addr inbuf;
2577 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2578 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2582 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
2585 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2586 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2590 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
2592 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
2594 okey = inbuf.s_addr;
2599 ikey = inbuf.s_addr;
2605 if ((cur = tb[TUNNEL_ATTR_DF]))
2606 set_df = blobmsg_get_bool(cur);
2609 /* ttl != 0 and nopmtudisc are incompatible */
2617 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
2619 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
2623 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
2626 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
2629 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
2632 nla_put_u32(nlm, IFLA_GRE_OKEY, htonl(okey));
2635 nla_put_u32(nlm, IFLA_GRE_IKEY, htonl(ikey));
2637 nla_nest_end(nlm, infodata);
2638 nla_nest_end(nlm, linkinfo);
2640 return system_rtnl_call(nlm);
2649 static int system_add_vti_tunnel(const char *name, const char *kind,
2650 const unsigned int link, struct blob_attr **tb, bool v6)
2653 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2654 struct blob_attr *cur;
2657 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2661 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2662 nla_put_string(nlm, IFLA_IFNAME, name);
2664 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2670 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2671 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2678 nla_put_u32(nlm, IFLA_VTI_LINK, link);
2681 struct in6_addr in6buf;
2682 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2683 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2687 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(in6buf), &in6buf);
2690 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2691 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2695 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(in6buf), &in6buf);
2699 struct in_addr inbuf;
2701 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2702 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2706 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(inbuf), &inbuf);
2709 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2710 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2714 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(inbuf), &inbuf);
2719 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2720 struct blob_attr *tb_data[__VTI_DATA_ATTR_MAX];
2721 uint32_t ikey = 0, okey = 0;
2723 blobmsg_parse(vti_data_attr_list.params, __VTI_DATA_ATTR_MAX, tb_data,
2724 blobmsg_data(cur), blobmsg_len(cur));
2726 if ((cur = tb_data[VTI_DATA_IKEY])) {
2727 if ((ikey = blobmsg_get_u32(cur)))
2728 nla_put_u32(nlm, IFLA_VTI_IKEY, htonl(ikey));
2731 if ((cur = tb_data[VTI_DATA_OKEY])) {
2732 if ((okey = blobmsg_get_u32(cur)))
2733 nla_put_u32(nlm, IFLA_VTI_OKEY, htonl(okey));
2737 nla_nest_end(nlm, infodata);
2738 nla_nest_end(nlm, linkinfo);
2740 return system_rtnl_call(nlm);
2748 #ifdef IFLA_VXLAN_MAX
2749 static int system_add_vxlan(const char *name, const unsigned int link, struct blob_attr **tb, bool v6)
2751 struct blob_attr *tb_data[__VXLAN_DATA_ATTR_MAX];
2753 struct nlattr *linkinfo, *data;
2754 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
2755 struct blob_attr *cur;
2758 if ((cur = tb[TUNNEL_ATTR_DATA]))
2759 blobmsg_parse(vxlan_data_attr_list.params, __VXLAN_DATA_ATTR_MAX, tb_data,
2760 blobmsg_data(cur), blobmsg_len(cur));
2764 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
2769 nlmsg_append(msg, &iim, sizeof(iim), 0);
2771 nla_put_string(msg, IFLA_IFNAME, name);
2773 if ((cur = tb_data[VXLAN_DATA_ATTR_MACADDR])) {
2774 struct ether_addr *ea = ether_aton(blobmsg_get_string(cur));
2780 nla_put(msg, IFLA_ADDRESS, ETH_ALEN, ea);
2783 if ((cur = tb[TUNNEL_ATTR_MTU])) {
2784 uint32_t mtu = blobmsg_get_u32(cur);
2785 nla_put_u32(msg, IFLA_MTU, mtu);
2788 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO))) {
2793 nla_put_string(msg, IFLA_INFO_KIND, "vxlan");
2795 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) {
2801 nla_put_u32(msg, IFLA_VXLAN_LINK, link);
2803 if ((cur = tb_data[VXLAN_DATA_ATTR_ID])) {
2804 uint32_t id = blobmsg_get_u32(cur);
2805 if (id >= (1u << 24) - 1) {
2810 nla_put_u32(msg, IFLA_VXLAN_ID, id);
2814 struct in6_addr in6buf;
2815 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2816 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2820 nla_put(msg, IFLA_VXLAN_LOCAL6, sizeof(in6buf), &in6buf);
2823 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2824 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2828 nla_put(msg, IFLA_VXLAN_GROUP6, sizeof(in6buf), &in6buf);
2831 struct in_addr inbuf;
2833 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2834 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2838 nla_put(msg, IFLA_VXLAN_LOCAL, sizeof(inbuf), &inbuf);
2841 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2842 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2846 nla_put(msg, IFLA_VXLAN_GROUP, sizeof(inbuf), &inbuf);
2850 uint32_t port = 4789;
2851 if ((cur = tb_data[VXLAN_DATA_ATTR_PORT])) {
2852 port = blobmsg_get_u32(cur);
2853 if (port < 1 || port > 65535) {
2858 nla_put_u16(msg, IFLA_VXLAN_PORT, htons(port));
2860 if ((cur = tb_data[VXLAN_DATA_ATTR_RXCSUM])) {
2861 bool rxcsum = blobmsg_get_bool(cur);
2862 nla_put_u8(msg, IFLA_VXLAN_UDP_ZERO_CSUM6_RX, !rxcsum);
2865 if ((cur = tb_data[VXLAN_DATA_ATTR_TXCSUM])) {
2866 bool txcsum = blobmsg_get_bool(cur);
2867 nla_put_u8(msg, IFLA_VXLAN_UDP_CSUM, txcsum);
2868 nla_put_u8(msg, IFLA_VXLAN_UDP_ZERO_CSUM6_TX, !txcsum);
2871 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2872 char *str = blobmsg_get_string(cur);
2875 if (strcmp(str, "inherit")) {
2876 if (!system_tos_aton(str, &tos)) {
2882 nla_put_u8(msg, IFLA_VXLAN_TOS, tos);
2885 if ((cur = tb[TUNNEL_ATTR_TTL])) {
2886 uint32_t ttl = blobmsg_get_u32(cur);
2887 if (ttl < 1 || ttl > 255) {
2892 nla_put_u8(msg, IFLA_VXLAN_TTL, ttl);
2895 nla_nest_end(msg, data);
2896 nla_nest_end(msg, linkinfo);
2898 ret = system_rtnl_call(msg);
2900 D(SYSTEM, "Error adding vxlan '%s': %d\n", name, ret);
2910 static int system_add_sit_tunnel(const char *name, const unsigned int link, struct blob_attr **tb)
2912 struct blob_attr *cur;
2915 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
2919 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2920 struct blob_attr *tb_data[__SIXRD_DATA_ATTR_MAX];
2922 struct ip_tunnel_6rd p6;
2924 blobmsg_parse(sixrd_data_attr_list.params, __SIXRD_DATA_ATTR_MAX, tb_data,
2925 blobmsg_data(cur), blobmsg_len(cur));
2927 memset(&p6, 0, sizeof(p6));
2929 if ((cur = tb_data[SIXRD_DATA_PREFIX])) {
2930 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
2931 &p6.prefix, &mask) || mask > 128) {
2936 p6.prefixlen = mask;
2939 if ((cur = tb_data[SIXRD_DATA_RELAY_PREFIX])) {
2940 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
2941 &p6.relay_prefix, &mask) || mask > 32) {
2946 p6.relay_prefixlen = mask;
2949 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
2959 __system_del_ip_tunnel(name, tb);
2963 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
2965 struct blob_attr *cur;
2967 struct ip_tunnel_parm p = {
2976 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
2977 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
2980 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
2981 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
2984 if ((cur = tb[TUNNEL_ATTR_DF]))
2985 set_df = blobmsg_get_bool(cur);
2987 if ((cur = tb[TUNNEL_ATTR_TTL]))
2988 p.iph.ttl = blobmsg_get_u32(cur);
2990 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2991 char *str = blobmsg_get_string(cur);
2992 if (strcmp(str, "inherit")) {
2995 if (!system_tos_aton(str, &uval))
3003 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
3004 /* ttl !=0 and nopmtudisc are incompatible */
3005 if (p.iph.ttl && p.iph.frag_off == 0)
3008 strncpy(p.name, name, sizeof(p.name) - 1);
3010 switch (p.iph.protocol) {
3012 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
3014 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
3021 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
3023 struct blob_attr *cur;
3026 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
3028 str = blobmsg_data(cur);
3030 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
3031 !strcmp(str, "greip6") || !strcmp(str, "gretapip6") ||
3032 !strcmp(str, "vtiip") || !strcmp(str, "vtiip6") ||
3033 !strcmp(str, "vxlan") || !strcmp(str, "vxlan6"))
3034 return system_link_del(name);
3036 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
3039 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
3041 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
3043 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
3044 blob_data(attr), blob_len(attr));
3046 return __system_del_ip_tunnel(name, tb);
3049 int system_update_ipv6_mtu(struct device *dev, int mtu)
3055 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
3058 fd = open(buf, O_RDWR);
3063 ssize_t len = read(fd, buf, sizeof(buf) - 1);
3070 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) > 0)
3079 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
3081 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
3082 struct blob_attr *cur;
3085 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
3086 blob_data(attr), blob_len(attr));
3088 __system_del_ip_tunnel(name, tb);
3090 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
3092 str = blobmsg_data(cur);
3094 unsigned int ttl = 0;
3095 if ((cur = tb[TUNNEL_ATTR_TTL])) {
3096 ttl = blobmsg_get_u32(cur);
3101 unsigned int link = 0;
3102 if ((cur = tb[TUNNEL_ATTR_LINK])) {
3103 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
3107 if (iface->l3_dev.dev)
3108 link = iface->l3_dev.dev->ifindex;
3111 if (!strcmp(str, "sit"))
3112 return system_add_sit_tunnel(name, link, tb);
3113 #ifdef IFLA_IPTUN_MAX
3114 else if (!strcmp(str, "ipip6")) {
3115 return system_add_ip6_tunnel(name, link, tb);
3116 } else if (!strcmp(str, "greip")) {
3117 return system_add_gre_tunnel(name, "gre", link, tb, false);
3118 } else if (!strcmp(str, "gretapip")) {
3119 return system_add_gre_tunnel(name, "gretap", link, tb, false);
3120 } else if (!strcmp(str, "greip6")) {
3121 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
3122 } else if (!strcmp(str, "gretapip6")) {
3123 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
3125 } else if (!strcmp(str, "vtiip")) {
3126 return system_add_vti_tunnel(name, "vti", link, tb, false);
3127 } else if (!strcmp(str, "vtiip6")) {
3128 return system_add_vti_tunnel(name, "vti6", link, tb, true);
3130 #ifdef IFLA_VXLAN_MAX
3131 } else if(!strcmp(str, "vxlan")) {
3132 return system_add_vxlan(name, link, tb, false);
3133 } else if(!strcmp(str, "vxlan6")) {
3134 return system_add_vxlan(name, link, tb, true);
3137 } else if (!strcmp(str, "ipip")) {
3138 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);