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];
2347 uint32_t tun_flags = IP6_TNL_F_IGN_ENCAP_LIMIT;
2349 blobmsg_parse(ipip6_data_attr_list.params, __IPIP6_DATA_ATTR_MAX, tb_data,
2350 blobmsg_data(cur), blobmsg_len(cur));
2352 if ((cur = tb_data[IPIP6_DATA_ENCAPLIMIT])) {
2353 char *str = blobmsg_get_string(cur);
2355 if (strcmp(str, "ignore")) {
2357 unsigned encap_limit = strtoul(str, &e, 0);
2359 if (e == str || *e || encap_limit > 255) {
2364 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, encap_limit);
2365 tun_flags &= ~IP6_TNL_F_IGN_ENCAP_LIMIT;
2369 #ifdef IFLA_IPTUN_FMR_MAX
2370 if ((cur = tb_data[IPIP6_DATA_FMRS])) {
2371 struct blob_attr *rcur;
2372 unsigned rrem, fmrcnt = 0;
2373 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2380 blobmsg_for_each_attr(rcur, cur, rrem) {
2381 struct blob_attr *tb_fmr[__FMR_DATA_ATTR_MAX], *tb_cur;
2382 struct in6_addr ip6prefix;
2383 struct in_addr ip4prefix;
2384 unsigned ip4len, ip6len, ealen, offset;
2386 blobmsg_parse(fmr_data_attr_list.params, __FMR_DATA_ATTR_MAX, tb_fmr,
2387 blobmsg_data(rcur), blobmsg_len(rcur));
2389 if (!(tb_cur = tb_fmr[FMR_DATA_PREFIX6]) ||
2390 !parse_ip_and_netmask(AF_INET6,
2391 blobmsg_data(tb_cur), &ip6prefix,
2397 if (!(tb_cur = tb_fmr[FMR_DATA_PREFIX4]) ||
2398 !parse_ip_and_netmask(AF_INET,
2399 blobmsg_data(tb_cur), &ip4prefix,
2405 if (!(tb_cur = tb_fmr[FMR_DATA_EALEN])) {
2409 ealen = blobmsg_get_u32(tb_cur);
2411 if (!(tb_cur = tb_fmr[FMR_DATA_OFFSET])) {
2415 offset = blobmsg_get_u32(tb_cur);
2417 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2423 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2424 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2425 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2426 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2427 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2428 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2430 nla_nest_end(nlm, rule);
2433 nla_nest_end(nlm, fmrs);
2437 nla_put_u32(nlm, IFLA_IPTUN_FLAGS, tun_flags);
2440 nla_nest_end(nlm, infodata);
2441 nla_nest_end(nlm, linkinfo);
2443 return system_rtnl_call(nlm);
2451 #ifdef IFLA_IPTUN_MAX
2452 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
2453 static int system_add_gre_tunnel(const char *name, const char *kind,
2454 const unsigned int link, struct blob_attr **tb, bool v6)
2457 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2458 struct blob_attr *cur;
2459 uint32_t ikey = 0, okey = 0, flags = 0, flowinfo = 0;
2460 uint16_t iflags = 0, oflags = 0;
2462 int ret = 0, ttl = 0;
2464 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2468 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2469 nla_put_string(nlm, IFLA_IFNAME, name);
2471 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2477 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2478 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2485 nla_put_u32(nlm, IFLA_GRE_LINK, link);
2487 if ((cur = tb[TUNNEL_ATTR_TTL]))
2488 ttl = blobmsg_get_u32(cur);
2490 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2491 char *str = blobmsg_get_string(cur);
2492 if (strcmp(str, "inherit")) {
2495 if (!system_tos_aton(str, &uval)) {
2501 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
2506 flags |= IP6_TNL_F_USE_ORIG_TCLASS;
2512 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2513 struct blob_attr *tb_data[__GRE_DATA_ATTR_MAX];
2515 blobmsg_parse(gre_data_attr_list.params, __GRE_DATA_ATTR_MAX, tb_data,
2516 blobmsg_data(cur), blobmsg_len(cur));
2518 if ((cur = tb_data[GRE_DATA_IKEY])) {
2519 if ((ikey = blobmsg_get_u32(cur)))
2523 if ((cur = tb_data[GRE_DATA_OKEY])) {
2524 if ((okey = blobmsg_get_u32(cur)))
2528 if ((cur = tb_data[GRE_DATA_ICSUM])) {
2529 if (blobmsg_get_bool(cur))
2533 if ((cur = tb_data[GRE_DATA_OCSUM])) {
2534 if (blobmsg_get_bool(cur))
2538 if ((cur = tb_data[GRE_DATA_ISEQNO])) {
2539 if (blobmsg_get_bool(cur))
2543 if ((cur = tb[GRE_DATA_OSEQNO])) {
2544 if (blobmsg_get_bool(cur))
2550 struct in6_addr in6buf;
2551 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2552 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2556 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
2559 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2560 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2564 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
2566 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, 4);
2569 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
2572 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags);
2577 struct in_addr inbuf;
2580 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2581 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2585 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
2588 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2589 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2593 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
2595 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
2597 okey = inbuf.s_addr;
2602 ikey = inbuf.s_addr;
2608 if ((cur = tb[TUNNEL_ATTR_DF]))
2609 set_df = blobmsg_get_bool(cur);
2612 /* ttl != 0 and nopmtudisc are incompatible */
2620 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
2622 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
2626 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
2629 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
2632 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
2635 nla_put_u32(nlm, IFLA_GRE_OKEY, htonl(okey));
2638 nla_put_u32(nlm, IFLA_GRE_IKEY, htonl(ikey));
2640 nla_nest_end(nlm, infodata);
2641 nla_nest_end(nlm, linkinfo);
2643 return system_rtnl_call(nlm);
2652 static int system_add_vti_tunnel(const char *name, const char *kind,
2653 const unsigned int link, struct blob_attr **tb, bool v6)
2656 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2657 struct blob_attr *cur;
2660 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2664 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2665 nla_put_string(nlm, IFLA_IFNAME, name);
2667 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2673 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2674 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2681 nla_put_u32(nlm, IFLA_VTI_LINK, link);
2684 struct in6_addr in6buf;
2685 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2686 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2690 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(in6buf), &in6buf);
2693 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2694 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2698 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(in6buf), &in6buf);
2702 struct in_addr inbuf;
2704 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2705 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2709 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(inbuf), &inbuf);
2712 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2713 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2717 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(inbuf), &inbuf);
2722 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2723 struct blob_attr *tb_data[__VTI_DATA_ATTR_MAX];
2724 uint32_t ikey = 0, okey = 0;
2726 blobmsg_parse(vti_data_attr_list.params, __VTI_DATA_ATTR_MAX, tb_data,
2727 blobmsg_data(cur), blobmsg_len(cur));
2729 if ((cur = tb_data[VTI_DATA_IKEY])) {
2730 if ((ikey = blobmsg_get_u32(cur)))
2731 nla_put_u32(nlm, IFLA_VTI_IKEY, htonl(ikey));
2734 if ((cur = tb_data[VTI_DATA_OKEY])) {
2735 if ((okey = blobmsg_get_u32(cur)))
2736 nla_put_u32(nlm, IFLA_VTI_OKEY, htonl(okey));
2740 nla_nest_end(nlm, infodata);
2741 nla_nest_end(nlm, linkinfo);
2743 return system_rtnl_call(nlm);
2751 #ifdef IFLA_VXLAN_MAX
2752 static int system_add_vxlan(const char *name, const unsigned int link, struct blob_attr **tb, bool v6)
2754 struct blob_attr *tb_data[__VXLAN_DATA_ATTR_MAX];
2756 struct nlattr *linkinfo, *data;
2757 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
2758 struct blob_attr *cur;
2761 if ((cur = tb[TUNNEL_ATTR_DATA]))
2762 blobmsg_parse(vxlan_data_attr_list.params, __VXLAN_DATA_ATTR_MAX, tb_data,
2763 blobmsg_data(cur), blobmsg_len(cur));
2767 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
2772 nlmsg_append(msg, &iim, sizeof(iim), 0);
2774 nla_put_string(msg, IFLA_IFNAME, name);
2776 if ((cur = tb_data[VXLAN_DATA_ATTR_MACADDR])) {
2777 struct ether_addr *ea = ether_aton(blobmsg_get_string(cur));
2783 nla_put(msg, IFLA_ADDRESS, ETH_ALEN, ea);
2786 if ((cur = tb[TUNNEL_ATTR_MTU])) {
2787 uint32_t mtu = blobmsg_get_u32(cur);
2788 nla_put_u32(msg, IFLA_MTU, mtu);
2791 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO))) {
2796 nla_put_string(msg, IFLA_INFO_KIND, "vxlan");
2798 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) {
2804 nla_put_u32(msg, IFLA_VXLAN_LINK, link);
2806 if ((cur = tb_data[VXLAN_DATA_ATTR_ID])) {
2807 uint32_t id = blobmsg_get_u32(cur);
2808 if (id >= (1u << 24) - 1) {
2813 nla_put_u32(msg, IFLA_VXLAN_ID, id);
2817 struct in6_addr in6buf;
2818 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2819 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2823 nla_put(msg, IFLA_VXLAN_LOCAL6, sizeof(in6buf), &in6buf);
2826 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2827 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2831 nla_put(msg, IFLA_VXLAN_GROUP6, sizeof(in6buf), &in6buf);
2834 struct in_addr inbuf;
2836 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2837 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2841 nla_put(msg, IFLA_VXLAN_LOCAL, sizeof(inbuf), &inbuf);
2844 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2845 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2849 nla_put(msg, IFLA_VXLAN_GROUP, sizeof(inbuf), &inbuf);
2853 uint32_t port = 4789;
2854 if ((cur = tb_data[VXLAN_DATA_ATTR_PORT])) {
2855 port = blobmsg_get_u32(cur);
2856 if (port < 1 || port > 65535) {
2861 nla_put_u16(msg, IFLA_VXLAN_PORT, htons(port));
2863 if ((cur = tb_data[VXLAN_DATA_ATTR_RXCSUM])) {
2864 bool rxcsum = blobmsg_get_bool(cur);
2865 nla_put_u8(msg, IFLA_VXLAN_UDP_ZERO_CSUM6_RX, !rxcsum);
2868 if ((cur = tb_data[VXLAN_DATA_ATTR_TXCSUM])) {
2869 bool txcsum = blobmsg_get_bool(cur);
2870 nla_put_u8(msg, IFLA_VXLAN_UDP_CSUM, txcsum);
2871 nla_put_u8(msg, IFLA_VXLAN_UDP_ZERO_CSUM6_TX, !txcsum);
2874 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2875 char *str = blobmsg_get_string(cur);
2878 if (strcmp(str, "inherit")) {
2879 if (!system_tos_aton(str, &tos)) {
2885 nla_put_u8(msg, IFLA_VXLAN_TOS, tos);
2888 if ((cur = tb[TUNNEL_ATTR_TTL])) {
2889 uint32_t ttl = blobmsg_get_u32(cur);
2890 if (ttl < 1 || ttl > 255) {
2895 nla_put_u8(msg, IFLA_VXLAN_TTL, ttl);
2898 nla_nest_end(msg, data);
2899 nla_nest_end(msg, linkinfo);
2901 ret = system_rtnl_call(msg);
2903 D(SYSTEM, "Error adding vxlan '%s': %d\n", name, ret);
2913 static int system_add_sit_tunnel(const char *name, const unsigned int link, struct blob_attr **tb)
2915 struct blob_attr *cur;
2918 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
2922 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2923 struct blob_attr *tb_data[__SIXRD_DATA_ATTR_MAX];
2925 struct ip_tunnel_6rd p6;
2927 blobmsg_parse(sixrd_data_attr_list.params, __SIXRD_DATA_ATTR_MAX, tb_data,
2928 blobmsg_data(cur), blobmsg_len(cur));
2930 memset(&p6, 0, sizeof(p6));
2932 if ((cur = tb_data[SIXRD_DATA_PREFIX])) {
2933 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
2934 &p6.prefix, &mask) || mask > 128) {
2939 p6.prefixlen = mask;
2942 if ((cur = tb_data[SIXRD_DATA_RELAY_PREFIX])) {
2943 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
2944 &p6.relay_prefix, &mask) || mask > 32) {
2949 p6.relay_prefixlen = mask;
2952 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
2962 __system_del_ip_tunnel(name, tb);
2966 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
2968 struct blob_attr *cur;
2970 struct ip_tunnel_parm p = {
2979 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
2980 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
2983 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
2984 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
2987 if ((cur = tb[TUNNEL_ATTR_DF]))
2988 set_df = blobmsg_get_bool(cur);
2990 if ((cur = tb[TUNNEL_ATTR_TTL]))
2991 p.iph.ttl = blobmsg_get_u32(cur);
2993 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2994 char *str = blobmsg_get_string(cur);
2995 if (strcmp(str, "inherit")) {
2998 if (!system_tos_aton(str, &uval))
3006 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
3007 /* ttl !=0 and nopmtudisc are incompatible */
3008 if (p.iph.ttl && p.iph.frag_off == 0)
3011 strncpy(p.name, name, sizeof(p.name) - 1);
3013 switch (p.iph.protocol) {
3015 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
3017 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
3024 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
3026 struct blob_attr *cur;
3029 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
3031 str = blobmsg_data(cur);
3033 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
3034 !strcmp(str, "greip6") || !strcmp(str, "gretapip6") ||
3035 !strcmp(str, "vtiip") || !strcmp(str, "vtiip6") ||
3036 !strcmp(str, "vxlan") || !strcmp(str, "vxlan6"))
3037 return system_link_del(name);
3039 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
3042 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
3044 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
3046 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
3047 blob_data(attr), blob_len(attr));
3049 return __system_del_ip_tunnel(name, tb);
3052 int system_update_ipv6_mtu(struct device *dev, int mtu)
3058 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
3061 fd = open(buf, O_RDWR);
3066 ssize_t len = read(fd, buf, sizeof(buf) - 1);
3073 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) > 0)
3082 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
3084 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
3085 struct blob_attr *cur;
3088 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
3089 blob_data(attr), blob_len(attr));
3091 __system_del_ip_tunnel(name, tb);
3093 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
3095 str = blobmsg_data(cur);
3097 unsigned int ttl = 0;
3098 if ((cur = tb[TUNNEL_ATTR_TTL])) {
3099 ttl = blobmsg_get_u32(cur);
3104 unsigned int link = 0;
3105 if ((cur = tb[TUNNEL_ATTR_LINK])) {
3106 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
3110 if (iface->l3_dev.dev)
3111 link = iface->l3_dev.dev->ifindex;
3114 if (!strcmp(str, "sit"))
3115 return system_add_sit_tunnel(name, link, tb);
3116 #ifdef IFLA_IPTUN_MAX
3117 else if (!strcmp(str, "ipip6")) {
3118 return system_add_ip6_tunnel(name, link, tb);
3119 } else if (!strcmp(str, "greip")) {
3120 return system_add_gre_tunnel(name, "gre", link, tb, false);
3121 } else if (!strcmp(str, "gretapip")) {
3122 return system_add_gre_tunnel(name, "gretap", link, tb, false);
3123 } else if (!strcmp(str, "greip6")) {
3124 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
3125 } else if (!strcmp(str, "gretapip6")) {
3126 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
3128 } else if (!strcmp(str, "vtiip")) {
3129 return system_add_vti_tunnel(name, "vti", link, tb, false);
3130 } else if (!strcmp(str, "vtiip6")) {
3131 return system_add_vti_tunnel(name, "vti6", link, tb, true);
3133 #ifdef IFLA_VXLAN_MAX
3134 } else if(!strcmp(str, "vxlan")) {
3135 return system_add_vxlan(name, link, tb, false);
3136 } else if(!strcmp(str, "vxlan6")) {
3137 return system_add_vxlan(name, link, tb, true);
3140 } else if (!strcmp(str, "ipip")) {
3141 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);