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_isolate_mode(struct device *dev, const char *val)
352 system_set_dev_sysctl("/sys/class/net/%s/brport/isolate_mode", 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_isolate_mode(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 { ADVERTISED_56000baseKR4_Full, "56000baseKR4-F" },
1704 { ADVERTISED_56000baseCR4_Full, "56000baseCR4-F" },
1705 { ADVERTISED_56000baseSR4_Full, "56000baseSR4-F" },
1706 { ADVERTISED_56000baseLR4_Full, "56000baseLR4-F" },
1709 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1712 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1713 if (mask & ethtool_link_modes[i].mask)
1714 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1719 system_if_force_external(const char *ifname)
1724 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1725 return stat(buf, &s) == 0;
1729 system_if_dump_info(struct device *dev, struct blob_buf *b)
1731 struct ethtool_cmd ecmd;
1736 memset(&ecmd, 0, sizeof(ecmd));
1737 memset(&ifr, 0, sizeof(ifr));
1738 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
1739 ifr.ifr_data = (caddr_t) &ecmd;
1740 ecmd.cmd = ETHTOOL_GSET;
1742 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1743 c = blobmsg_open_array(b, "link-advertising");
1744 system_add_link_modes(b, ecmd.advertising);
1745 blobmsg_close_array(b, c);
1747 c = blobmsg_open_array(b, "link-partner-advertising");
1748 system_add_link_modes(b, ecmd.lp_advertising);
1749 blobmsg_close_array(b, c);
1751 c = blobmsg_open_array(b, "link-supported");
1752 system_add_link_modes(b, ecmd.supported);
1753 blobmsg_close_array(b, c);
1755 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1756 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1757 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1758 blobmsg_add_string_buffer(b);
1760 blobmsg_add_u8(b, "autoneg", !!ecmd.autoneg);
1767 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1769 const char *const counters[] = {
1770 "collisions", "rx_frame_errors", "tx_compressed",
1771 "multicast", "rx_length_errors", "tx_dropped",
1772 "rx_bytes", "rx_missed_errors", "tx_errors",
1773 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1774 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1775 "rx_dropped", "tx_aborted_errors", "tx_packets",
1776 "rx_errors", "tx_bytes", "tx_window_errors",
1777 "rx_fifo_errors", "tx_carrier_errors",
1784 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1785 stats_dir = open(buf, O_DIRECTORY);
1789 for (i = 0; i < ARRAY_SIZE(counters); i++)
1790 if (read_uint64_file(stats_dir, counters[i], &val))
1791 blobmsg_add_u64(b, counters[i], val);
1797 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1799 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1800 int alen = v4 ? 4 : 16;
1801 unsigned int flags = 0;
1802 struct ifaddrmsg ifa = {
1803 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1804 .ifa_prefixlen = addr->mask,
1805 .ifa_index = dev->ifindex,
1809 if (cmd == RTM_NEWADDR)
1810 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1812 msg = nlmsg_alloc_simple(cmd, flags);
1816 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1817 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1819 if (addr->broadcast)
1820 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1821 if (addr->point_to_point)
1822 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1824 time_t now = system_get_rtime();
1825 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1827 if (addr->preferred_until) {
1828 int64_t preferred = addr->preferred_until - now;
1831 else if (preferred > UINT32_MAX)
1832 preferred = UINT32_MAX;
1834 cinfo.ifa_prefered = preferred;
1837 if (addr->valid_until) {
1838 int64_t valid = addr->valid_until - now;
1843 else if (valid > UINT32_MAX)
1846 cinfo.ifa_valid = valid;
1849 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1851 if (cmd == RTM_NEWADDR && (addr->flags & DEVADDR_OFFLINK))
1852 nla_put_u32(msg, IFA_FLAGS, IFA_F_NOPREFIXROUTE);
1855 return system_rtnl_call(msg);
1858 int system_add_address(struct device *dev, struct device_addr *addr)
1860 return system_addr(dev, addr, RTM_NEWADDR);
1863 int system_del_address(struct device *dev, struct device_addr *addr)
1865 return system_addr(dev, addr, RTM_DELADDR);
1868 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1870 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1872 unsigned int flags = 0;
1875 have_gw = !!route->nexthop.in.s_addr;
1877 have_gw = route->nexthop.in6.s6_addr32[0] ||
1878 route->nexthop.in6.s6_addr32[1] ||
1879 route->nexthop.in6.s6_addr32[2] ||
1880 route->nexthop.in6.s6_addr32[3];
1882 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1883 ? route->table : RT_TABLE_MAIN;
1885 struct rtmsg rtm = {
1886 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1887 .rtm_dst_len = route->mask,
1888 .rtm_src_len = route->sourcemask,
1889 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1890 .rtm_protocol = (route->flags & DEVROUTE_PROTO) ? route->proto : RTPROT_STATIC,
1891 .rtm_scope = RT_SCOPE_NOWHERE,
1892 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1893 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1897 if (cmd == RTM_NEWROUTE) {
1898 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1900 if (!dev) { // Add null-route
1901 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1902 rtm.rtm_type = RTN_UNREACHABLE;
1905 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1908 if (route->flags & DEVROUTE_TYPE) {
1909 rtm.rtm_type = route->type;
1910 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
1911 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
1912 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
1913 rtm.rtm_table = RT_TABLE_LOCAL;
1916 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT) {
1917 rtm.rtm_scope = RT_SCOPE_HOST;
1918 } else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
1919 rtm.rtm_type == RTN_ANYCAST) {
1920 rtm.rtm_scope = RT_SCOPE_LINK;
1921 } else if (rtm.rtm_type == RTN_BLACKHOLE || rtm.rtm_type == RTN_UNREACHABLE ||
1922 rtm.rtm_type == RTN_PROHIBIT || rtm.rtm_type == RTN_FAILED_POLICY ||
1923 rtm.rtm_type == RTN_THROW) {
1924 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1929 msg = nlmsg_alloc_simple(cmd, flags);
1933 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1936 nla_put(msg, RTA_DST, alen, &route->addr);
1938 if (route->sourcemask) {
1939 if (rtm.rtm_family == AF_INET)
1940 nla_put(msg, RTA_PREFSRC, alen, &route->source);
1942 nla_put(msg, RTA_SRC, alen, &route->source);
1945 if (route->metric > 0)
1946 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1949 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1952 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1955 nla_put_u32(msg, RTA_TABLE, table);
1957 if (route->flags & DEVROUTE_MTU) {
1958 struct nlattr *metrics;
1960 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1961 goto nla_put_failure;
1963 nla_put_u32(msg, RTAX_MTU, route->mtu);
1965 nla_nest_end(msg, metrics);
1968 return system_rtnl_call(msg);
1975 int system_add_route(struct device *dev, struct device_route *route)
1977 return system_rt(dev, route, RTM_NEWROUTE);
1980 int system_del_route(struct device *dev, struct device_route *route)
1982 return system_rt(dev, route, RTM_DELROUTE);
1985 int system_flush_routes(void)
1987 const char *names[] = {
1988 "/proc/sys/net/ipv4/route/flush",
1989 "/proc/sys/net/ipv6/route/flush"
1993 for (i = 0; i < ARRAY_SIZE(names); i++) {
1994 fd = open(names[i], O_WRONLY);
1998 if (write(fd, "-1", 2)) {}
2004 bool system_resolve_rt_type(const char *type, unsigned int *id)
2006 return system_rtn_aton(type, id);
2009 bool system_resolve_rt_proto(const char *type, unsigned int *id)
2013 unsigned int n, proto = 256;
2014 n = strtoul(type, &e, 0);
2015 if (!*e && e != type)
2017 else if (!strcmp(type, "unspec"))
2018 proto = RTPROT_UNSPEC;
2019 else if (!strcmp(type, "kernel"))
2020 proto = RTPROT_KERNEL;
2021 else if (!strcmp(type, "boot"))
2022 proto = RTPROT_BOOT;
2023 else if (!strcmp(type, "static"))
2024 proto = RTPROT_STATIC;
2025 else if ((f = fopen("/etc/iproute2/rt_protos", "r")) != NULL) {
2026 while (fgets(buf, sizeof(buf) - 1, f) != NULL) {
2027 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
2030 n = strtoul(e, NULL, 10);
2031 e = strtok(NULL, " \t\n");
2033 if (e && !strcmp(e, type)) {
2048 bool system_resolve_rt_table(const char *name, unsigned int *id)
2052 unsigned int n, table = RT_TABLE_UNSPEC;
2054 /* first try to parse table as number */
2055 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
2058 /* handle well known aliases */
2059 else if (!strcmp(name, "default"))
2060 table = RT_TABLE_DEFAULT;
2061 else if (!strcmp(name, "main"))
2062 table = RT_TABLE_MAIN;
2063 else if (!strcmp(name, "local"))
2064 table = RT_TABLE_LOCAL;
2066 /* try to look up name in /etc/iproute2/rt_tables */
2067 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
2069 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
2071 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
2074 n = strtoul(e, NULL, 10);
2075 e = strtok(NULL, " \t\n");
2077 if (e && !strcmp(e, name))
2087 if (table == RT_TABLE_UNSPEC)
2094 bool system_is_default_rt_table(unsigned int id)
2096 return (id == RT_TABLE_MAIN);
2099 bool system_resolve_rpfilter(const char *filter, unsigned int *id)
2104 if (!strcmp(filter, "strict"))
2106 else if (!strcmp(filter, "loose"))
2109 n = strtoul(filter, &e, 0);
2110 if (*e || e == filter || n > 2)
2118 static int system_iprule(struct iprule *rule, int cmd)
2120 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
2123 struct rtmsg rtm = {
2124 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
2125 .rtm_protocol = RTPROT_STATIC,
2126 .rtm_scope = RT_SCOPE_UNIVERSE,
2127 .rtm_table = RT_TABLE_UNSPEC,
2128 .rtm_type = RTN_UNSPEC,
2132 if (cmd == RTM_NEWRULE)
2133 rtm.rtm_type = RTN_UNICAST;
2136 rtm.rtm_flags |= FIB_RULE_INVERT;
2138 if (rule->flags & IPRULE_SRC)
2139 rtm.rtm_src_len = rule->src_mask;
2141 if (rule->flags & IPRULE_DEST)
2142 rtm.rtm_dst_len = rule->dest_mask;
2144 if (rule->flags & IPRULE_TOS)
2145 rtm.rtm_tos = rule->tos;
2147 if (rule->flags & IPRULE_LOOKUP) {
2148 if (rule->lookup < 256)
2149 rtm.rtm_table = rule->lookup;
2152 if (rule->flags & IPRULE_ACTION)
2153 rtm.rtm_type = rule->action;
2154 else if (rule->flags & IPRULE_GOTO)
2155 rtm.rtm_type = FR_ACT_GOTO;
2156 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
2157 rtm.rtm_type = FR_ACT_NOP;
2159 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
2164 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
2166 if (rule->flags & IPRULE_IN)
2167 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
2169 if (rule->flags & IPRULE_OUT)
2170 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
2172 if (rule->flags & IPRULE_SRC)
2173 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
2175 if (rule->flags & IPRULE_DEST)
2176 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
2178 if (rule->flags & IPRULE_PRIORITY)
2179 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
2180 else if (cmd == RTM_NEWRULE)
2181 nla_put_u32(msg, FRA_PRIORITY, rule->order);
2183 if (rule->flags & IPRULE_FWMARK)
2184 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
2186 if (rule->flags & IPRULE_FWMASK)
2187 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
2189 if (rule->flags & IPRULE_LOOKUP) {
2190 if (rule->lookup >= 256)
2191 nla_put_u32(msg, FRA_TABLE, rule->lookup);
2194 if (rule->flags & IPRULE_SUP_PREFIXLEN)
2195 nla_put_u32(msg, FRA_SUPPRESS_PREFIXLEN, rule->sup_prefixlen);
2197 if (rule->flags & IPRULE_GOTO)
2198 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
2200 return system_rtnl_call(msg);
2203 int system_add_iprule(struct iprule *rule)
2205 return system_iprule(rule, RTM_NEWRULE);
2208 int system_del_iprule(struct iprule *rule)
2210 return system_iprule(rule, RTM_DELRULE);
2213 int system_flush_iprules(void)
2218 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
2219 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
2221 memset(&rule, 0, sizeof(rule));
2224 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2227 rule.lookup = RT_TABLE_LOCAL;
2228 rv |= system_iprule(&rule, RTM_NEWRULE);
2230 rule.priority = 32766;
2231 rule.lookup = RT_TABLE_MAIN;
2232 rv |= system_iprule(&rule, RTM_NEWRULE);
2234 rule.priority = 32767;
2235 rule.lookup = RT_TABLE_DEFAULT;
2236 rv |= system_iprule(&rule, RTM_NEWRULE);
2239 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2242 rule.lookup = RT_TABLE_LOCAL;
2243 rv |= system_iprule(&rule, RTM_NEWRULE);
2245 rule.priority = 32766;
2246 rule.lookup = RT_TABLE_MAIN;
2247 rv |= system_iprule(&rule, RTM_NEWRULE);
2252 bool system_resolve_iprule_action(const char *action, unsigned int *id)
2254 return system_rtn_aton(action, id);
2257 time_t system_get_rtime(void)
2262 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
2265 if (gettimeofday(&tv, NULL) == 0)
2272 #define IP_DF 0x4000
2275 static int tunnel_ioctl(const char *name, int cmd, void *p)
2279 memset(&ifr, 0, sizeof(ifr));
2280 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name) - 1);
2281 ifr.ifr_ifru.ifru_data = p;
2282 return ioctl(sock_ioctl, cmd, &ifr);
2285 #ifdef IFLA_IPTUN_MAX
2286 static int system_add_ip6_tunnel(const char *name, const unsigned int link,
2287 struct blob_attr **tb)
2289 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2290 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2291 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2292 struct blob_attr *cur;
2293 int ret = 0, ttl = 0;
2298 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2299 nla_put_string(nlm, IFLA_IFNAME, name);
2302 nla_put_u32(nlm, IFLA_LINK, link);
2304 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2310 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2311 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2318 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2320 if ((cur = tb[TUNNEL_ATTR_TTL]))
2321 ttl = blobmsg_get_u32(cur);
2323 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2324 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2326 struct in6_addr in6buf;
2327 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2328 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2332 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2335 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2336 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2340 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2343 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2344 struct blob_attr *tb_data[__IPIP6_DATA_ATTR_MAX];
2346 blobmsg_parse(ipip6_data_attr_list.params, __IPIP6_DATA_ATTR_MAX, tb_data,
2347 blobmsg_data(cur), blobmsg_len(cur));
2349 if ((cur = tb_data[IPIP6_DATA_ENCAPLIMIT])) {
2350 char *str = blobmsg_get_string(cur);
2352 if (strcmp(str, "ignore")) {
2354 unsigned encap_limit = strtoul(str, &e, 0);
2356 if (e == str || *e || encap_limit > 255) {
2361 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, encap_limit);
2363 nla_put_u32(nlm, IFLA_IPTUN_FLAGS, IP6_TNL_F_IGN_ENCAP_LIMIT);
2366 #ifdef IFLA_IPTUN_FMR_MAX
2367 if ((cur = tb_data[IPIP6_DATA_FMRS])) {
2368 struct blob_attr *rcur;
2369 unsigned rrem, fmrcnt = 0;
2370 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2377 blobmsg_for_each_attr(rcur, cur, rrem) {
2378 struct blob_attr *tb_fmr[__FMR_DATA_ATTR_MAX], *tb_cur;
2379 struct in6_addr ip6prefix;
2380 struct in_addr ip4prefix;
2381 unsigned ip4len, ip6len, ealen, offset;
2383 blobmsg_parse(fmr_data_attr_list.params, __FMR_DATA_ATTR_MAX, tb_fmr,
2384 blobmsg_data(rcur), blobmsg_len(rcur));
2386 if (!(tb_cur = tb_fmr[FMR_DATA_PREFIX6]) ||
2387 !parse_ip_and_netmask(AF_INET6,
2388 blobmsg_data(tb_cur), &ip6prefix,
2394 if (!(tb_cur = tb_fmr[FMR_DATA_PREFIX4]) ||
2395 !parse_ip_and_netmask(AF_INET,
2396 blobmsg_data(tb_cur), &ip4prefix,
2402 if (!(tb_cur = tb_fmr[FMR_DATA_EALEN])) {
2406 ealen = blobmsg_get_u32(tb_cur);
2408 if (!(tb_cur = tb_fmr[FMR_DATA_OFFSET])) {
2412 offset = blobmsg_get_u32(tb_cur);
2414 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2420 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2421 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2422 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2423 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2424 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2425 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2427 nla_nest_end(nlm, rule);
2430 nla_nest_end(nlm, fmrs);
2435 nla_nest_end(nlm, infodata);
2436 nla_nest_end(nlm, linkinfo);
2438 return system_rtnl_call(nlm);
2446 #ifdef IFLA_IPTUN_MAX
2447 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
2448 static int system_add_gre_tunnel(const char *name, const char *kind,
2449 const unsigned int link, struct blob_attr **tb, bool v6)
2452 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2453 struct blob_attr *cur;
2454 uint32_t ikey = 0, okey = 0, flags = 0, flowinfo = 0;
2455 uint16_t iflags = 0, oflags = 0;
2457 int ret = 0, ttl = 0;
2459 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2463 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2464 nla_put_string(nlm, IFLA_IFNAME, name);
2466 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2472 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2473 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2480 nla_put_u32(nlm, IFLA_GRE_LINK, link);
2482 if ((cur = tb[TUNNEL_ATTR_TTL]))
2483 ttl = blobmsg_get_u32(cur);
2485 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2486 char *str = blobmsg_get_string(cur);
2487 if (strcmp(str, "inherit")) {
2490 if (!system_tos_aton(str, &uval)) {
2496 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
2501 flags |= IP6_TNL_F_USE_ORIG_TCLASS;
2507 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2508 struct blob_attr *tb_data[__GRE_DATA_ATTR_MAX];
2510 blobmsg_parse(gre_data_attr_list.params, __GRE_DATA_ATTR_MAX, tb_data,
2511 blobmsg_data(cur), blobmsg_len(cur));
2513 if ((cur = tb_data[GRE_DATA_IKEY])) {
2514 if ((ikey = blobmsg_get_u32(cur)))
2518 if ((cur = tb_data[GRE_DATA_OKEY])) {
2519 if ((okey = blobmsg_get_u32(cur)))
2523 if ((cur = tb_data[GRE_DATA_ICSUM])) {
2524 if (blobmsg_get_bool(cur))
2528 if ((cur = tb_data[GRE_DATA_OCSUM])) {
2529 if (blobmsg_get_bool(cur))
2533 if ((cur = tb_data[GRE_DATA_ISEQNO])) {
2534 if (blobmsg_get_bool(cur))
2538 if ((cur = tb[GRE_DATA_OSEQNO])) {
2539 if (blobmsg_get_bool(cur))
2545 struct in6_addr in6buf;
2546 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2547 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2551 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
2554 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2555 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2559 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
2561 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, 4);
2564 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
2567 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags);
2572 struct in_addr inbuf;
2575 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2576 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2580 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
2583 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2584 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2588 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
2590 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
2592 okey = inbuf.s_addr;
2597 ikey = inbuf.s_addr;
2603 if ((cur = tb[TUNNEL_ATTR_DF]))
2604 set_df = blobmsg_get_bool(cur);
2607 /* ttl != 0 and nopmtudisc are incompatible */
2615 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
2617 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
2621 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
2624 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
2627 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
2630 nla_put_u32(nlm, IFLA_GRE_OKEY, htonl(okey));
2633 nla_put_u32(nlm, IFLA_GRE_IKEY, htonl(ikey));
2635 nla_nest_end(nlm, infodata);
2636 nla_nest_end(nlm, linkinfo);
2638 return system_rtnl_call(nlm);
2647 static int system_add_vti_tunnel(const char *name, const char *kind,
2648 const unsigned int link, struct blob_attr **tb, bool v6)
2651 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2652 struct blob_attr *cur;
2655 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2659 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2660 nla_put_string(nlm, IFLA_IFNAME, name);
2662 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2668 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2669 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2676 nla_put_u32(nlm, IFLA_VTI_LINK, link);
2679 struct in6_addr in6buf;
2680 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2681 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2685 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(in6buf), &in6buf);
2688 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2689 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2693 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(in6buf), &in6buf);
2697 struct in_addr inbuf;
2699 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2700 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2704 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(inbuf), &inbuf);
2707 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2708 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2712 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(inbuf), &inbuf);
2717 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2718 struct blob_attr *tb_data[__VTI_DATA_ATTR_MAX];
2719 uint32_t ikey = 0, okey = 0;
2721 blobmsg_parse(vti_data_attr_list.params, __VTI_DATA_ATTR_MAX, tb_data,
2722 blobmsg_data(cur), blobmsg_len(cur));
2724 if ((cur = tb_data[VTI_DATA_IKEY])) {
2725 if ((ikey = blobmsg_get_u32(cur)))
2726 nla_put_u32(nlm, IFLA_VTI_IKEY, htonl(ikey));
2729 if ((cur = tb_data[VTI_DATA_OKEY])) {
2730 if ((okey = blobmsg_get_u32(cur)))
2731 nla_put_u32(nlm, IFLA_VTI_OKEY, htonl(okey));
2735 nla_nest_end(nlm, infodata);
2736 nla_nest_end(nlm, linkinfo);
2738 return system_rtnl_call(nlm);
2746 #ifdef IFLA_VXLAN_MAX
2747 static int system_add_vxlan(const char *name, const unsigned int link, struct blob_attr **tb, bool v6)
2749 struct blob_attr *tb_data[__VXLAN_DATA_ATTR_MAX];
2751 struct nlattr *linkinfo, *data;
2752 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
2753 struct blob_attr *cur;
2756 if ((cur = tb[TUNNEL_ATTR_DATA]))
2757 blobmsg_parse(vxlan_data_attr_list.params, __VXLAN_DATA_ATTR_MAX, tb_data,
2758 blobmsg_data(cur), blobmsg_len(cur));
2762 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
2767 nlmsg_append(msg, &iim, sizeof(iim), 0);
2769 nla_put_string(msg, IFLA_IFNAME, name);
2771 if ((cur = tb_data[VXLAN_DATA_ATTR_MACADDR])) {
2772 struct ether_addr *ea = ether_aton(blobmsg_get_string(cur));
2778 nla_put(msg, IFLA_ADDRESS, ETH_ALEN, ea);
2781 if ((cur = tb[TUNNEL_ATTR_MTU])) {
2782 uint32_t mtu = blobmsg_get_u32(cur);
2783 nla_put_u32(msg, IFLA_MTU, mtu);
2786 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO))) {
2791 nla_put_string(msg, IFLA_INFO_KIND, "vxlan");
2793 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) {
2799 nla_put_u32(msg, IFLA_VXLAN_LINK, link);
2801 if ((cur = tb_data[VXLAN_DATA_ATTR_ID])) {
2802 uint32_t id = blobmsg_get_u32(cur);
2803 if (id >= (1u << 24) - 1) {
2808 nla_put_u32(msg, IFLA_VXLAN_ID, id);
2812 struct in6_addr in6buf;
2813 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2814 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2818 nla_put(msg, IFLA_VXLAN_LOCAL6, sizeof(in6buf), &in6buf);
2821 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2822 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2826 nla_put(msg, IFLA_VXLAN_GROUP6, sizeof(in6buf), &in6buf);
2829 struct in_addr inbuf;
2831 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2832 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2836 nla_put(msg, IFLA_VXLAN_LOCAL, sizeof(inbuf), &inbuf);
2839 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2840 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2844 nla_put(msg, IFLA_VXLAN_GROUP, sizeof(inbuf), &inbuf);
2848 uint32_t port = 4789;
2849 if ((cur = tb_data[VXLAN_DATA_ATTR_PORT])) {
2850 port = blobmsg_get_u32(cur);
2851 if (port < 1 || port > 65535) {
2856 nla_put_u16(msg, IFLA_VXLAN_PORT, htons(port));
2858 if ((cur = tb_data[VXLAN_DATA_ATTR_RXCSUM])) {
2859 bool rxcsum = blobmsg_get_bool(cur);
2860 nla_put_u8(msg, IFLA_VXLAN_UDP_ZERO_CSUM6_RX, !rxcsum);
2863 if ((cur = tb_data[VXLAN_DATA_ATTR_TXCSUM])) {
2864 bool txcsum = blobmsg_get_bool(cur);
2865 nla_put_u8(msg, IFLA_VXLAN_UDP_CSUM, txcsum);
2866 nla_put_u8(msg, IFLA_VXLAN_UDP_ZERO_CSUM6_TX, !txcsum);
2869 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2870 char *str = blobmsg_get_string(cur);
2873 if (strcmp(str, "inherit")) {
2874 if (!system_tos_aton(str, &tos)) {
2880 nla_put_u8(msg, IFLA_VXLAN_TOS, tos);
2883 if ((cur = tb[TUNNEL_ATTR_TTL])) {
2884 uint32_t ttl = blobmsg_get_u32(cur);
2885 if (ttl < 1 || ttl > 255) {
2890 nla_put_u8(msg, IFLA_VXLAN_TTL, ttl);
2893 nla_nest_end(msg, data);
2894 nla_nest_end(msg, linkinfo);
2896 ret = system_rtnl_call(msg);
2898 D(SYSTEM, "Error adding vxlan '%s': %d\n", name, ret);
2908 static int system_add_sit_tunnel(const char *name, const unsigned int link, struct blob_attr **tb)
2910 struct blob_attr *cur;
2913 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
2917 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2918 struct blob_attr *tb_data[__SIXRD_DATA_ATTR_MAX];
2920 struct ip_tunnel_6rd p6;
2922 blobmsg_parse(sixrd_data_attr_list.params, __SIXRD_DATA_ATTR_MAX, tb_data,
2923 blobmsg_data(cur), blobmsg_len(cur));
2925 memset(&p6, 0, sizeof(p6));
2927 if ((cur = tb_data[SIXRD_DATA_PREFIX])) {
2928 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
2929 &p6.prefix, &mask) || mask > 128) {
2934 p6.prefixlen = mask;
2937 if ((cur = tb_data[SIXRD_DATA_RELAY_PREFIX])) {
2938 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
2939 &p6.relay_prefix, &mask) || mask > 32) {
2944 p6.relay_prefixlen = mask;
2947 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
2957 __system_del_ip_tunnel(name, tb);
2961 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
2963 struct blob_attr *cur;
2965 struct ip_tunnel_parm p = {
2974 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
2975 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
2978 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
2979 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
2982 if ((cur = tb[TUNNEL_ATTR_DF]))
2983 set_df = blobmsg_get_bool(cur);
2985 if ((cur = tb[TUNNEL_ATTR_TTL]))
2986 p.iph.ttl = blobmsg_get_u32(cur);
2988 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2989 char *str = blobmsg_get_string(cur);
2990 if (strcmp(str, "inherit")) {
2993 if (!system_tos_aton(str, &uval))
3001 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
3002 /* ttl !=0 and nopmtudisc are incompatible */
3003 if (p.iph.ttl && p.iph.frag_off == 0)
3006 strncpy(p.name, name, sizeof(p.name) - 1);
3008 switch (p.iph.protocol) {
3010 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
3012 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
3019 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
3021 struct blob_attr *cur;
3024 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
3026 str = blobmsg_data(cur);
3028 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
3029 !strcmp(str, "greip6") || !strcmp(str, "gretapip6") ||
3030 !strcmp(str, "vtiip") || !strcmp(str, "vtiip6") ||
3031 !strcmp(str, "vxlan") || !strcmp(str, "vxlan6"))
3032 return system_link_del(name);
3034 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
3037 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
3039 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
3041 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
3042 blob_data(attr), blob_len(attr));
3044 return __system_del_ip_tunnel(name, tb);
3047 int system_update_ipv6_mtu(struct device *dev, int mtu)
3053 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
3056 fd = open(buf, O_RDWR);
3061 ssize_t len = read(fd, buf, sizeof(buf) - 1);
3068 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) > 0)
3077 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
3079 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
3080 struct blob_attr *cur;
3083 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
3084 blob_data(attr), blob_len(attr));
3086 __system_del_ip_tunnel(name, tb);
3088 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
3090 str = blobmsg_data(cur);
3092 unsigned int ttl = 0;
3093 if ((cur = tb[TUNNEL_ATTR_TTL])) {
3094 ttl = blobmsg_get_u32(cur);
3099 unsigned int link = 0;
3100 if ((cur = tb[TUNNEL_ATTR_LINK])) {
3101 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
3105 if (iface->l3_dev.dev)
3106 link = iface->l3_dev.dev->ifindex;
3109 if (!strcmp(str, "sit"))
3110 return system_add_sit_tunnel(name, link, tb);
3111 #ifdef IFLA_IPTUN_MAX
3112 else if (!strcmp(str, "ipip6")) {
3113 return system_add_ip6_tunnel(name, link, tb);
3114 } else if (!strcmp(str, "greip")) {
3115 return system_add_gre_tunnel(name, "gre", link, tb, false);
3116 } else if (!strcmp(str, "gretapip")) {
3117 return system_add_gre_tunnel(name, "gretap", link, tb, false);
3118 } else if (!strcmp(str, "greip6")) {
3119 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
3120 } else if (!strcmp(str, "gretapip6")) {
3121 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
3123 } else if (!strcmp(str, "vtiip")) {
3124 return system_add_vti_tunnel(name, "vti", link, tb, false);
3125 } else if (!strcmp(str, "vtiip6")) {
3126 return system_add_vti_tunnel(name, "vti6", link, tb, true);
3128 #ifdef IFLA_VXLAN_MAX
3129 } else if(!strcmp(str, "vxlan")) {
3130 return system_add_vxlan(name, link, tb, false);
3131 } else if(!strcmp(str, "vxlan6")) {
3132 return system_add_vxlan(name, link, tb, true);
3135 } else if (!strcmp(str, "ipip")) {
3136 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);