2 * netifd - network interface daemon
3 * Copyright (C) 2012 Felix Fietkau <nbd@openwrt.org>
4 * Copyright (C) 2013 Jo-Philipp Wich <jow@openwrt.org>
5 * Copyright (C) 2013 Steven Barth <steven@midlink.org>
6 * Copyright (C) 2014 Gioacchino Mazzurco <gio@eigenlab.org>
7 * Copyright (C) 2017 Matthias Schiffer <mschiffer@universe-factory.net>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2
11 * as published by the Free Software Foundation
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
20 #include <sys/socket.h>
21 #include <sys/ioctl.h>
23 #include <sys/syscall.h>
26 #include <net/if_arp.h>
28 #include <arpa/inet.h>
29 #include <netinet/ether.h>
30 #include <netinet/in.h>
32 #include <linux/rtnetlink.h>
33 #include <linux/sockios.h>
35 #include <linux/if_addr.h>
36 #include <linux/if_link.h>
37 #include <linux/if_vlan.h>
38 #include <linux/if_bridge.h>
39 #include <linux/if_tunnel.h>
40 #include <linux/ip6_tunnel.h>
41 #include <linux/ethtool.h>
42 #include <linux/fib_rules.h>
43 #include <linux/veth.h>
44 #include <linux/version.h>
46 #ifndef RTN_FAILED_POLICY
47 #define RTN_FAILED_POLICY 12
50 #ifndef IFA_F_NOPREFIXROUTE
51 #define IFA_F_NOPREFIXROUTE 0x200
55 #define IFA_FLAGS (IFA_MULTICAST + 1)
64 #include <netlink/msg.h>
65 #include <netlink/attr.h>
66 #include <netlink/socket.h>
67 #include <libubox/uloop.h>
74 struct uloop_fd uloop;
79 static int sock_ioctl = -1;
80 static struct nl_sock *sock_rtnl = NULL;
82 static int cb_rtnl_event(struct nl_msg *msg, void *arg);
83 static void handle_hotplug_event(struct uloop_fd *u, unsigned int events);
84 static int system_add_proto_tunnel(const char *name, const uint8_t proto,
85 const unsigned int link, struct blob_attr **tb);
86 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb);
88 static char dev_buf[256];
91 handler_nl_event(struct uloop_fd *u, unsigned int events)
93 struct event_socket *ev = container_of(u, struct event_socket, uloop);
95 socklen_t errlen = sizeof(err);
98 nl_recvmsgs_default(ev->sock);
102 if (getsockopt(u->fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen))
107 // Increase rx buffer size on netlink socket
109 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
112 // Request full dump since some info got dropped
113 struct rtgenmsg msg = { .rtgen_family = AF_UNSPEC };
114 nl_send_simple(ev->sock, RTM_GETLINK, NLM_F_DUMP, &msg, sizeof(msg));
124 uloop_fd_delete(&ev->uloop);
128 static struct nl_sock *
129 create_socket(int protocol, int groups)
131 struct nl_sock *sock;
133 sock = nl_socket_alloc();
138 nl_join_groups(sock, groups);
140 if (nl_connect(sock, protocol))
147 create_raw_event_socket(struct event_socket *ev, int protocol, int groups,
148 uloop_fd_handler cb, int flags)
150 ev->sock = create_socket(protocol, groups);
154 ev->uloop.fd = nl_socket_get_fd(ev->sock);
156 if (uloop_fd_add(&ev->uloop, ULOOP_READ|flags))
163 create_event_socket(struct event_socket *ev, int protocol,
164 int (*cb)(struct nl_msg *msg, void *arg))
166 if (!create_raw_event_socket(ev, protocol, 0, handler_nl_event, ULOOP_ERROR_CB))
169 // Install the valid custom callback handler
170 nl_socket_modify_cb(ev->sock, NL_CB_VALID, NL_CB_CUSTOM, cb, NULL);
172 // Disable sequence number checking on event sockets
173 nl_socket_disable_seq_check(ev->sock);
175 // Increase rx buffer size to 65K on event sockets
177 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
184 system_rtn_aton(const char *src, unsigned int *dst)
189 if (!strcmp(src, "local"))
191 else if (!strcmp(src, "nat"))
193 else if (!strcmp(src, "broadcast"))
195 else if (!strcmp(src, "anycast"))
197 else if (!strcmp(src, "multicast"))
199 else if (!strcmp(src, "prohibit"))
201 else if (!strcmp(src, "unreachable"))
203 else if (!strcmp(src, "blackhole"))
205 else if (!strcmp(src, "xresolve"))
207 else if (!strcmp(src, "unicast"))
209 else if (!strcmp(src, "throw"))
211 else if (!strcmp(src, "failed_policy"))
212 n = RTN_FAILED_POLICY;
214 n = strtoul(src, &e, 0);
215 if (!e || *e || e == src || n > 255)
224 system_tos_aton(const char *src, unsigned *dst)
228 *dst = strtoul(src, &e, 16);
229 if (e == src || *e || *dst > 255)
235 int system_init(void)
237 static struct event_socket rtnl_event;
238 static struct event_socket hotplug_event;
240 sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0);
241 system_fd_set_cloexec(sock_ioctl);
243 // Prepare socket for routing / address control
244 sock_rtnl = create_socket(NETLINK_ROUTE, 0);
248 if (!create_event_socket(&rtnl_event, NETLINK_ROUTE, cb_rtnl_event))
251 if (!create_raw_event_socket(&hotplug_event, NETLINK_KOBJECT_UEVENT, 1,
252 handle_hotplug_event, 0))
255 // Receive network link events form kernel
256 nl_socket_add_membership(rtnl_event.sock, RTNLGRP_LINK);
261 static void system_set_sysctl(const char *path, const char *val)
265 fd = open(path, O_WRONLY);
269 if (write(fd, val, strlen(val))) {}
273 static void system_set_dev_sysctl(const char *path, const char *device, const char *val)
275 snprintf(dev_buf, sizeof(dev_buf), path, device);
276 system_set_sysctl(dev_buf, val);
279 static void system_set_disable_ipv6(struct device *dev, const char *val)
281 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val);
284 static void system_set_rpfilter(struct device *dev, const char *val)
286 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter", dev->ifname, val);
289 static void system_set_acceptlocal(struct device *dev, const char *val)
291 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local", dev->ifname, val);
294 static void system_set_igmpversion(struct device *dev, const char *val)
296 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version", dev->ifname, val);
299 static void system_set_mldversion(struct device *dev, const char *val)
301 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version", dev->ifname, val);
304 static void system_set_neigh4reachabletime(struct device *dev, const char *val)
306 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms", dev->ifname, val);
309 static void system_set_neigh6reachabletime(struct device *dev, const char *val)
311 system_set_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms", dev->ifname, val);
314 static void system_set_neigh4gcstaletime(struct device *dev, const char *val)
316 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/gc_stale_time", dev->ifname, val);
319 static void system_set_neigh6gcstaletime(struct device *dev, const char *val)
321 system_set_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/gc_stale_time", dev->ifname, val);
324 static void system_set_neigh4locktime(struct device *dev, const char *val)
326 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/locktime", dev->ifname, val);
329 static void system_set_dadtransmits(struct device *dev, const char *val)
331 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits", dev->ifname, val);
334 static void system_bridge_set_multicast_to_unicast(struct device *dev, const char *val)
336 system_set_dev_sysctl("/sys/class/net/%s/brport/multicast_to_unicast", dev->ifname, val);
339 static void system_bridge_set_multicast_fast_leave(struct device *dev, const char *val)
341 system_set_dev_sysctl("/sys/class/net/%s/brport/multicast_fast_leave", dev->ifname, val);
344 static void system_bridge_set_hairpin_mode(struct device *dev, const char *val)
346 system_set_dev_sysctl("/sys/class/net/%s/brport/hairpin_mode", dev->ifname, val);
349 static void system_bridge_set_multicast_router(struct device *dev, const char *val, bool bridge)
351 system_set_dev_sysctl(bridge ? "/sys/class/net/%s/bridge/multicast_router" :
352 "/sys/class/net/%s/brport/multicast_router",
356 static void system_bridge_set_robustness(struct device *dev, const char *val)
358 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_startup_query_count",
360 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_last_member_count",
364 static void system_bridge_set_query_interval(struct device *dev, const char *val)
366 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_query_interval",
370 static void system_bridge_set_query_response_interval(struct device *dev, const char *val)
372 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_query_response_interval",
376 static void system_bridge_set_last_member_interval(struct device *dev, const char *val)
378 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_last_member_interval",
382 static void system_bridge_set_membership_interval(struct device *dev, const char *val)
384 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_membership_interval",
388 static void system_bridge_set_other_querier_timeout(struct device *dev, const char *val)
390 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier_interval",
394 static void system_bridge_set_startup_query_interval(struct device *dev, const char *val)
396 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_startup_query_interval",
400 static void system_bridge_set_learning(struct device *dev, const char *val)
402 system_set_dev_sysctl("/sys/class/net/%s/brport/learning", dev->ifname, val);
405 static void system_bridge_set_unicast_flood(struct device *dev, const char *val)
407 system_set_dev_sysctl("/sys/class/net/%s/brport/unicast_flood", dev->ifname, val);
410 static void system_set_sendredirects(struct device *dev, const char *val)
412 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/send_redirects", dev->ifname, val);
415 static int system_get_sysctl(const char *path, char *buf, const size_t buf_sz)
417 int fd = -1, ret = -1;
419 fd = open(path, O_RDONLY);
423 ssize_t len = read(fd, buf, buf_sz - 1);
437 system_get_dev_sysctl(const char *path, const char *device, char *buf, const size_t buf_sz)
439 snprintf(dev_buf, sizeof(dev_buf), path, device);
440 return system_get_sysctl(dev_buf, buf, buf_sz);
443 static int system_get_disable_ipv6(struct device *dev, char *buf, const size_t buf_sz)
445 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6",
446 dev->ifname, buf, buf_sz);
449 static int system_get_rpfilter(struct device *dev, char *buf, const size_t buf_sz)
451 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter",
452 dev->ifname, buf, buf_sz);
455 static int system_get_acceptlocal(struct device *dev, char *buf, const size_t buf_sz)
457 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local",
458 dev->ifname, buf, buf_sz);
461 static int system_get_igmpversion(struct device *dev, char *buf, const size_t buf_sz)
463 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version",
464 dev->ifname, buf, buf_sz);
467 static int system_get_mldversion(struct device *dev, char *buf, const size_t buf_sz)
469 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version",
470 dev->ifname, buf, buf_sz);
473 static int system_get_neigh4reachabletime(struct device *dev, char *buf, const size_t buf_sz)
475 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms",
476 dev->ifname, buf, buf_sz);
479 static int system_get_neigh6reachabletime(struct device *dev, char *buf, const size_t buf_sz)
481 return system_get_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms",
482 dev->ifname, buf, buf_sz);
485 static int system_get_neigh4gcstaletime(struct device *dev, char *buf, const size_t buf_sz)
487 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/gc_stale_time",
488 dev->ifname, buf, buf_sz);
491 static int system_get_neigh6gcstaletime(struct device *dev, char *buf, const size_t buf_sz)
493 return system_get_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/gc_stale_time",
494 dev->ifname, buf, buf_sz);
497 static int system_get_neigh4locktime(struct device *dev, char *buf, const size_t buf_sz)
499 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/locktime",
500 dev->ifname, buf, buf_sz);
503 static int system_get_dadtransmits(struct device *dev, char *buf, const size_t buf_sz)
505 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits",
506 dev->ifname, buf, buf_sz);
509 static int system_get_sendredirects(struct device *dev, char *buf, const size_t buf_sz)
511 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/send_redirects",
512 dev->ifname, buf, buf_sz);
515 // Evaluate netlink messages
516 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
518 struct nlmsghdr *nh = nlmsg_hdr(msg);
519 struct nlattr *nla[__IFLA_MAX];
523 if (nh->nlmsg_type != RTM_NEWLINK)
526 nlmsg_parse(nh, sizeof(struct ifinfomsg), nla, __IFLA_MAX - 1, NULL);
527 if (!nla[IFLA_IFNAME])
530 struct device *dev = device_find(nla_data(nla[IFLA_IFNAME]));
534 if (!system_get_dev_sysctl("/sys/class/net/%s/carrier", dev->ifname, buf, sizeof(buf)))
535 link_state = strtoul(buf, NULL, 0);
537 device_set_link(dev, link_state ? true : false);
544 handle_hotplug_msg(char *data, int size)
546 const char *subsystem = NULL, *interface = NULL, *interface_old = NULL;
547 char *cur, *end, *sep;
550 bool add, move = false;
552 if (!strncmp(data, "add@", 4))
554 else if (!strncmp(data, "remove@", 7))
556 else if (!strncmp(data, "move@", 5)) {
563 skip = strlen(data) + 1;
566 for (cur = data + skip; cur < end; cur += skip) {
567 skip = strlen(cur) + 1;
569 sep = strchr(cur, '=');
574 if (!strcmp(cur, "INTERFACE"))
576 else if (!strcmp(cur, "SUBSYSTEM")) {
578 if (strcmp(subsystem, "net") != 0)
580 } else if (!strcmp(cur, "DEVPATH_OLD")) {
581 interface_old = strrchr(sep + 1, '/');
587 if (subsystem && interface) {
588 if (move && interface_old)
597 dev = device_find(interface_old);
601 if (dev->type != &simple_device_type)
604 device_set_present(dev, false);
607 dev = device_find(interface);
611 if (dev->type != &simple_device_type)
614 if (add && system_if_force_external(dev->ifname))
617 device_set_present(dev, add);
621 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
623 struct event_socket *ev = container_of(u, struct event_socket, uloop);
624 struct sockaddr_nl nla;
625 unsigned char *buf = NULL;
628 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
630 handle_hotplug_msg((char *) buf, size);
636 static int system_rtnl_call(struct nl_msg *msg)
640 ret = nl_send_auto_complete(sock_rtnl, msg);
646 return nl_wait_for_ack(sock_rtnl);
649 int system_bridge_delbr(struct device *bridge)
651 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
654 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
658 memset(&ifr, 0, sizeof(ifr));
660 ifr.ifr_ifindex = dev->ifindex;
663 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
664 return ioctl(sock_ioctl, cmd, &ifr);
667 static bool system_is_bridge(const char *name, char *buf, int buflen)
671 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
672 if (stat(buf, &st) < 0)
678 static char *system_get_bridge(const char *name, char *buf, int buflen)
684 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
685 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
689 len = readlink(gl.gl_pathv[0], buf, buflen);
697 path = strrchr(buf, '/');
705 system_bridge_set_wireless(struct device *bridge, struct device *dev)
707 bool mcast_to_ucast = dev->wireless_ap;
710 if (bridge->settings.flags & DEV_OPT_MULTICAST_TO_UNICAST &&
711 !bridge->settings.multicast_to_unicast)
712 mcast_to_ucast = false;
714 if (!mcast_to_ucast || dev->wireless_isolate)
717 system_bridge_set_multicast_to_unicast(dev, mcast_to_ucast ? "1" : "0");
718 system_bridge_set_hairpin_mode(dev, hairpin ? "1" : "0");
721 int system_bridge_addif(struct device *bridge, struct device *dev)
727 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
728 if (!oldbr || strcmp(oldbr, bridge->ifname) != 0)
729 ret = system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
732 system_bridge_set_wireless(bridge, dev);
734 if (dev->settings.flags & DEV_OPT_MULTICAST_ROUTER) {
735 snprintf(buf, sizeof(buf), "%u", dev->settings.multicast_router);
736 system_bridge_set_multicast_router(dev, buf, false);
739 if (dev->settings.flags & DEV_OPT_MULTICAST_FAST_LEAVE &&
740 dev->settings.multicast_fast_leave)
741 system_bridge_set_multicast_fast_leave(dev, "1");
743 if (dev->settings.flags & DEV_OPT_LEARNING &&
744 !dev->settings.learning)
745 system_bridge_set_learning(dev, "0");
747 if (dev->settings.flags & DEV_OPT_UNICAST_FLOOD &&
748 !dev->settings.unicast_flood)
749 system_bridge_set_unicast_flood(dev, "0");
754 int system_bridge_delif(struct device *bridge, struct device *dev)
756 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
759 int system_if_resolve(struct device *dev)
762 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
763 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
764 return ifr.ifr_ifindex;
769 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
773 memset(&ifr, 0, sizeof(ifr));
774 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
775 ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
776 ifr.ifr_flags |= add;
777 ifr.ifr_flags &= ~rem;
778 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
790 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
792 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
794 return ifa->ifa_index == ifindex;
797 static bool check_route(struct nlmsghdr *hdr, int ifindex)
799 struct rtmsg *r = NLMSG_DATA(hdr);
800 struct nlattr *tb[__RTA_MAX];
802 if (r->rtm_protocol == RTPROT_KERNEL &&
803 r->rtm_family == AF_INET6)
806 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
810 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
813 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
818 static int cb_clear_event(struct nl_msg *msg, void *arg)
820 struct clear_data *clr = arg;
821 struct nlmsghdr *hdr = nlmsg_hdr(msg);
822 bool (*cb)(struct nlmsghdr *, int ifindex);
828 if (hdr->nlmsg_type != RTM_NEWADDR)
835 if (hdr->nlmsg_type != RTM_NEWROUTE)
842 if (hdr->nlmsg_type != RTM_NEWRULE)
851 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
854 if (type == RTM_DELRULE)
855 D(SYSTEM, "Remove a rule\n");
857 D(SYSTEM, "Remove %s from device %s\n",
858 type == RTM_DELADDR ? "an address" : "a route",
860 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
861 hdr = nlmsg_hdr(clr->msg);
862 hdr->nlmsg_type = type;
863 hdr->nlmsg_flags = NLM_F_REQUEST;
865 nl_socket_disable_auto_ack(sock_rtnl);
866 nl_send_auto_complete(sock_rtnl, clr->msg);
867 nl_socket_enable_auto_ack(sock_rtnl);
873 cb_finish_event(struct nl_msg *msg, void *arg)
881 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
884 *pending = err->error;
889 system_if_clear_entries(struct device *dev, int type, int af)
891 struct clear_data clr;
892 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
895 .rtm_flags = RTM_F_CLONED,
897 int flags = NLM_F_DUMP;
906 clr.size = sizeof(struct rtgenmsg);
909 clr.size = sizeof(struct rtmsg);
918 clr.msg = nlmsg_alloc_simple(type, flags);
922 nlmsg_append(clr.msg, &rtm, clr.size, 0);
923 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
924 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
925 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
927 nl_send_auto_complete(sock_rtnl, clr.msg);
929 nl_recvmsgs(sock_rtnl, cb);
937 * Clear bridge (membership) state and bring down device
939 void system_if_clear_state(struct device *dev)
941 static char buf[256];
944 device_set_ifindex(dev, system_if_resolve(dev));
945 if (dev->external || !dev->ifindex)
948 system_if_flags(dev->ifname, 0, IFF_UP);
950 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
951 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
952 system_bridge_delbr(dev);
956 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
958 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
959 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
962 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
963 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
964 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
965 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
966 system_set_disable_ipv6(dev, "0");
969 static inline unsigned long
970 sec_to_jiffies(int val)
972 return (unsigned long) val * 100;
975 static void system_bridge_conf_multicast_deps(struct device *bridge,
976 struct bridge_config *cfg,
982 if (cfg->flags & BRIDGE_OPT_ROBUSTNESS ||
983 cfg->flags & BRIDGE_OPT_QUERY_INTERVAL ||
984 cfg->flags & BRIDGE_OPT_QUERY_RESPONSE_INTERVAL) {
985 val = cfg->robustness * cfg->query_interval +
986 cfg->query_response_interval;
988 snprintf(buf, buf_len, "%i", val);
989 system_bridge_set_membership_interval(bridge, buf);
991 val = cfg->robustness * cfg->query_interval +
992 cfg->query_response_interval / 2;
994 snprintf(buf, buf_len, "%i", val);
995 system_bridge_set_other_querier_timeout(bridge, buf);
998 if (cfg->flags & BRIDGE_OPT_QUERY_INTERVAL) {
999 val = cfg->query_interval / 4;
1001 snprintf(buf, buf_len, "%i", val);
1002 system_bridge_set_startup_query_interval(bridge, buf);
1006 static void system_bridge_conf_multicast(struct device *bridge,
1007 struct bridge_config *cfg,
1011 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
1012 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
1014 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier",
1015 bridge->ifname, cfg->multicast_querier ? "1" : "0");
1017 snprintf(buf, buf_len, "%i", cfg->hash_max);
1018 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/hash_max",
1019 bridge->ifname, buf);
1021 if (bridge->settings.flags & DEV_OPT_MULTICAST_ROUTER) {
1022 snprintf(buf, buf_len, "%u", bridge->settings.multicast_router);
1023 system_bridge_set_multicast_router(bridge, buf, true);
1026 if (cfg->flags & BRIDGE_OPT_ROBUSTNESS) {
1027 snprintf(buf, buf_len, "%i", cfg->robustness);
1028 system_bridge_set_robustness(bridge, buf);
1031 if (cfg->flags & BRIDGE_OPT_QUERY_INTERVAL) {
1032 snprintf(buf, buf_len, "%i", cfg->query_interval);
1033 system_bridge_set_query_interval(bridge, buf);
1036 if (cfg->flags & BRIDGE_OPT_QUERY_RESPONSE_INTERVAL) {
1037 snprintf(buf, buf_len, "%i", cfg->query_response_interval);
1038 system_bridge_set_query_response_interval(bridge, buf);
1041 if (cfg->flags & BRIDGE_OPT_LAST_MEMBER_INTERVAL) {
1042 snprintf(buf, buf_len, "%i", cfg->last_member_interval);
1043 system_bridge_set_last_member_interval(bridge, buf);
1046 system_bridge_conf_multicast_deps(bridge, cfg, buf, buf_len);
1049 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
1052 unsigned long args[4] = {};
1054 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
1057 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
1058 args[1] = !!cfg->stp;
1059 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1061 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
1062 args[1] = sec_to_jiffies(cfg->forward_delay);
1063 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1065 system_bridge_conf_multicast(bridge, cfg, buf, sizeof(buf));
1067 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
1068 args[1] = cfg->priority;
1069 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1071 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
1072 args[0] = BRCTL_SET_AGEING_TIME;
1073 args[1] = sec_to_jiffies(cfg->ageing_time);
1074 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1077 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
1078 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
1079 args[1] = sec_to_jiffies(cfg->hello_time);
1080 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1083 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
1084 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
1085 args[1] = sec_to_jiffies(cfg->max_age);
1086 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1092 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
1095 struct nlattr *linkinfo, *data;
1096 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
1098 static const struct {
1100 enum macvlan_mode val;
1102 { "private", MACVLAN_MODE_PRIVATE },
1103 { "vepa", MACVLAN_MODE_VEPA },
1104 { "bridge", MACVLAN_MODE_BRIDGE },
1105 { "passthru", MACVLAN_MODE_PASSTHRU },
1108 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1113 nlmsg_append(msg, &iim, sizeof(iim), 0);
1115 if (cfg->flags & MACVLAN_OPT_MACADDR)
1116 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
1117 nla_put_string(msg, IFLA_IFNAME, macvlan->ifname);
1118 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
1120 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1121 goto nla_put_failure;
1123 nla_put_string(msg, IFLA_INFO_KIND, "macvlan");
1125 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1126 goto nla_put_failure;
1129 for (i = 0; i < ARRAY_SIZE(modes); i++) {
1130 if (strcmp(cfg->mode, modes[i].name) != 0)
1133 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
1138 nla_nest_end(msg, data);
1139 nla_nest_end(msg, linkinfo);
1141 rv = system_rtnl_call(msg);
1143 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
1152 static int system_link_del(const char *ifname)
1155 struct ifinfomsg iim = {
1156 .ifi_family = AF_UNSPEC,
1160 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
1165 nlmsg_append(msg, &iim, sizeof(iim), 0);
1166 nla_put_string(msg, IFLA_IFNAME, ifname);
1167 return system_rtnl_call(msg);
1170 int system_macvlan_del(struct device *macvlan)
1172 return system_link_del(macvlan->ifname);
1175 int system_veth_add(struct device *veth, struct veth_config *cfg)
1178 struct ifinfomsg empty_iim = {};
1179 struct nlattr *linkinfo, *data, *veth_info;
1182 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1187 nlmsg_append(msg, &empty_iim, sizeof(empty_iim), 0);
1189 if (cfg->flags & VETH_OPT_MACADDR)
1190 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
1191 nla_put_string(msg, IFLA_IFNAME, veth->ifname);
1193 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1194 goto nla_put_failure;
1196 nla_put_string(msg, IFLA_INFO_KIND, "veth");
1198 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1199 goto nla_put_failure;
1201 if (!(veth_info = nla_nest_start(msg, VETH_INFO_PEER)))
1202 goto nla_put_failure;
1204 nlmsg_append(msg, &empty_iim, sizeof(empty_iim), 0);
1206 if (cfg->flags & VETH_OPT_PEER_NAME)
1207 nla_put_string(msg, IFLA_IFNAME, cfg->peer_name);
1208 if (cfg->flags & VETH_OPT_PEER_MACADDR)
1209 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->peer_macaddr), cfg->peer_macaddr);
1211 nla_nest_end(msg, veth_info);
1212 nla_nest_end(msg, data);
1213 nla_nest_end(msg, linkinfo);
1215 rv = system_rtnl_call(msg);
1217 if (cfg->flags & VETH_OPT_PEER_NAME)
1218 D(SYSTEM, "Error adding veth '%s' with peer '%s': %d\n", veth->ifname, cfg->peer_name, rv);
1220 D(SYSTEM, "Error adding veth '%s': %d\n", veth->ifname, rv);
1230 int system_veth_del(struct device *veth)
1232 return system_link_del(veth->ifname);
1235 static int system_vlan(struct device *dev, int id)
1237 struct vlan_ioctl_args ifr = {
1238 .cmd = SET_VLAN_NAME_TYPE_CMD,
1239 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
1242 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
1245 ifr.cmd = DEL_VLAN_CMD;
1248 ifr.cmd = ADD_VLAN_CMD;
1251 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
1252 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
1255 int system_vlan_add(struct device *dev, int id)
1257 return system_vlan(dev, id);
1260 int system_vlan_del(struct device *dev)
1262 return system_vlan(dev, -1);
1265 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
1268 struct nlattr *linkinfo, *data;
1269 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
1272 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1277 nlmsg_append(msg, &iim, sizeof(iim), 0);
1278 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
1279 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
1281 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1282 goto nla_put_failure;
1284 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
1286 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1287 goto nla_put_failure;
1289 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
1291 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
1292 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
1294 if(cfg->proto == VLAN_PROTO_8021AD)
1295 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);
1298 nla_nest_end(msg, data);
1299 nla_nest_end(msg, linkinfo);
1301 rv = system_rtnl_call(msg);
1303 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
1312 int system_vlandev_del(struct device *vlandev)
1314 return system_link_del(vlandev->ifname);
1318 system_if_get_settings(struct device *dev, struct device_settings *s)
1323 memset(&ifr, 0, sizeof(ifr));
1324 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1326 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
1327 s->mtu = ifr.ifr_mtu;
1328 s->flags |= DEV_OPT_MTU;
1331 s->mtu6 = system_update_ipv6_mtu(dev, 0);
1333 s->flags |= DEV_OPT_MTU6;
1335 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
1336 s->txqueuelen = ifr.ifr_qlen;
1337 s->flags |= DEV_OPT_TXQUEUELEN;
1340 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
1341 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
1342 s->flags |= DEV_OPT_MACADDR;
1345 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
1346 s->ipv6 = !strtoul(buf, NULL, 0);
1347 s->flags |= DEV_OPT_IPV6;
1350 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
1351 s->promisc = ifr.ifr_flags & IFF_PROMISC;
1352 s->flags |= DEV_OPT_PROMISC;
1354 s->multicast = ifr.ifr_flags & IFF_MULTICAST;
1355 s->flags |= DEV_OPT_MULTICAST;
1358 if (!system_get_rpfilter(dev, buf, sizeof(buf))) {
1359 s->rpfilter = strtoul(buf, NULL, 0);
1360 s->flags |= DEV_OPT_RPFILTER;
1363 if (!system_get_acceptlocal(dev, buf, sizeof(buf))) {
1364 s->acceptlocal = strtoul(buf, NULL, 0);
1365 s->flags |= DEV_OPT_ACCEPTLOCAL;
1368 if (!system_get_igmpversion(dev, buf, sizeof(buf))) {
1369 s->igmpversion = strtoul(buf, NULL, 0);
1370 s->flags |= DEV_OPT_IGMPVERSION;
1373 if (!system_get_mldversion(dev, buf, sizeof(buf))) {
1374 s->mldversion = strtoul(buf, NULL, 0);
1375 s->flags |= DEV_OPT_MLDVERSION;
1378 if (!system_get_neigh4reachabletime(dev, buf, sizeof(buf))) {
1379 s->neigh4reachabletime = strtoul(buf, NULL, 0);
1380 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1383 if (!system_get_neigh6reachabletime(dev, buf, sizeof(buf))) {
1384 s->neigh6reachabletime = strtoul(buf, NULL, 0);
1385 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1388 if (!system_get_neigh4locktime(dev, buf, sizeof(buf))) {
1389 s->neigh4locktime = strtol(buf, NULL, 0);
1390 s->flags |= DEV_OPT_NEIGHLOCKTIME;
1393 if (!system_get_neigh4gcstaletime(dev, buf, sizeof(buf))) {
1394 s->neigh4gcstaletime = strtoul(buf, NULL, 0);
1395 s->flags |= DEV_OPT_NEIGHGCSTALETIME;
1398 if (!system_get_neigh6gcstaletime(dev, buf, sizeof(buf))) {
1399 s->neigh6gcstaletime = strtoul(buf, NULL, 0);
1400 s->flags |= DEV_OPT_NEIGHGCSTALETIME;
1403 if (!system_get_dadtransmits(dev, buf, sizeof(buf))) {
1404 s->dadtransmits = strtoul(buf, NULL, 0);
1405 s->flags |= DEV_OPT_DADTRANSMITS;
1408 if (!system_get_sendredirects(dev, buf, sizeof(buf))) {
1409 s->sendredirects = strtoul(buf, NULL, 0);
1410 s->flags |= DEV_OPT_SENDREDIRECTS;
1415 system_if_set_rps_xps_val(const char *path, char *fmt, int val)
1421 if (glob(path, 0, NULL, &gl))
1424 snprintf(val_buf, sizeof(val_buf), fmt, val);
1425 for (i = 0; i < gl.gl_pathc; i++)
1426 system_set_sysctl(gl.gl_pathv[i], val_buf);
1432 system_if_apply_rps_xps(struct device *dev, struct device_settings *s)
1434 long n_cpus = sysconf(_SC_NPROCESSORS_ONLN);
1435 int val, rps_val, rps_flow_cnt, xps_val;
1440 val = (1 << n_cpus) - 1;
1441 rps_val = s->rps_val ? s->rps_val : val;
1442 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/rps_cpus", dev->ifname);
1443 system_if_set_rps_xps_val(dev_buf, "%x", s->rps ? rps_val : 0);
1445 rps_flow_cnt = s->rps_flow_cnt ? s->rps_flow_cnt : 0;
1446 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/rps_flow_cnt", dev->ifname);
1447 system_if_set_rps_xps_val(dev_buf, "%d", s->rps ? rps_flow_cnt : 0);
1449 xps_val = s->xps_val ? s->xps_val : val;
1450 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/xps_cpus", dev->ifname);
1451 system_if_set_rps_xps_val(dev_buf, "%x", s->xps ? xps_val : 0);
1455 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
1460 memset(&ifr, 0, sizeof(ifr));
1461 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1462 if (s->flags & DEV_OPT_MTU & apply_mask) {
1463 ifr.ifr_mtu = s->mtu;
1464 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
1465 s->flags &= ~DEV_OPT_MTU;
1467 if (s->flags & DEV_OPT_MTU6 & apply_mask) {
1468 system_update_ipv6_mtu(dev, s->mtu6);
1470 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
1471 ifr.ifr_qlen = s->txqueuelen;
1472 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
1473 s->flags &= ~DEV_OPT_TXQUEUELEN;
1475 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
1476 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
1477 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
1478 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
1479 s->flags &= ~DEV_OPT_MACADDR;
1481 if (s->flags & DEV_OPT_IPV6 & apply_mask)
1482 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
1483 if (s->flags & DEV_OPT_PROMISC & apply_mask) {
1484 if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
1485 !s->promisc ? IFF_PROMISC : 0) < 0)
1486 s->flags &= ~DEV_OPT_PROMISC;
1488 if (s->flags & DEV_OPT_RPFILTER & apply_mask) {
1489 snprintf(buf, sizeof(buf), "%u", s->rpfilter);
1490 system_set_rpfilter(dev, buf);
1492 if (s->flags & DEV_OPT_ACCEPTLOCAL & apply_mask)
1493 system_set_acceptlocal(dev, s->acceptlocal ? "1" : "0");
1494 if (s->flags & DEV_OPT_IGMPVERSION & apply_mask) {
1495 snprintf(buf, sizeof(buf), "%u", s->igmpversion);
1496 system_set_igmpversion(dev, buf);
1498 if (s->flags & DEV_OPT_MLDVERSION & apply_mask) {
1499 snprintf(buf, sizeof(buf), "%u", s->mldversion);
1500 system_set_mldversion(dev, buf);
1502 if (s->flags & DEV_OPT_NEIGHREACHABLETIME & apply_mask) {
1503 snprintf(buf, sizeof(buf), "%u", s->neigh4reachabletime);
1504 system_set_neigh4reachabletime(dev, buf);
1505 snprintf(buf, sizeof(buf), "%u", s->neigh6reachabletime);
1506 system_set_neigh6reachabletime(dev, buf);
1508 if (s->flags & DEV_OPT_NEIGHLOCKTIME & apply_mask) {
1509 snprintf(buf, sizeof(buf), "%d", s->neigh4locktime);
1510 system_set_neigh4locktime(dev, buf);
1512 if (s->flags & DEV_OPT_NEIGHGCSTALETIME & apply_mask) {
1513 snprintf(buf, sizeof(buf), "%u", s->neigh4gcstaletime);
1514 system_set_neigh4gcstaletime(dev, buf);
1515 snprintf(buf, sizeof(buf), "%u", s->neigh6gcstaletime);
1516 system_set_neigh6gcstaletime(dev, buf);
1518 if (s->flags & DEV_OPT_DADTRANSMITS & apply_mask) {
1519 snprintf(buf, sizeof(buf), "%u", s->dadtransmits);
1520 system_set_dadtransmits(dev, buf);
1522 if (s->flags & DEV_OPT_MULTICAST & apply_mask) {
1523 if (system_if_flags(dev->ifname, s->multicast ? IFF_MULTICAST : 0,
1524 !s->multicast ? IFF_MULTICAST : 0) < 0)
1525 s->flags &= ~DEV_OPT_MULTICAST;
1527 if (s->flags & DEV_OPT_SENDREDIRECTS & apply_mask)
1528 system_set_sendredirects(dev, s->sendredirects ? "1" : "0");
1530 system_if_apply_rps_xps(dev, s);
1533 int system_if_up(struct device *dev)
1535 system_if_get_settings(dev, &dev->orig_settings);
1536 /* Only keep orig settings based on what needs to be set */
1537 dev->orig_settings.valid_flags = dev->orig_settings.flags;
1538 dev->orig_settings.flags &= dev->settings.flags;
1539 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
1540 return system_if_flags(dev->ifname, IFF_UP, 0);
1543 int system_if_down(struct device *dev)
1545 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
1546 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
1550 struct if_check_data {
1556 #ifndef IFF_LOWER_UP
1557 #define IFF_LOWER_UP 0x10000
1560 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1562 struct nlmsghdr *nh = nlmsg_hdr(msg);
1563 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1564 struct if_check_data *chk = (struct if_check_data *)arg;
1566 if (nh->nlmsg_type != RTM_NEWLINK)
1569 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1570 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1575 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1577 struct if_check_data *chk = (struct if_check_data *)arg;
1582 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1584 struct if_check_data *chk = (struct if_check_data *)arg;
1586 device_set_present(chk->dev, false);
1587 device_set_link(chk->dev, false);
1588 chk->pending = err->error;
1593 int system_if_check(struct device *dev)
1595 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1597 struct ifinfomsg ifi = {
1598 .ifi_family = AF_UNSPEC,
1601 struct if_check_data chk = {
1607 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1611 if (nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1612 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1615 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1616 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1617 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1619 nl_send_auto_complete(sock_rtnl, msg);
1620 while (chk.pending > 0)
1621 nl_recvmsgs(sock_rtnl, cb);
1633 system_if_get_parent(struct device *dev)
1635 char buf[64], *devname;
1636 int ifindex, iflink, len;
1639 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1640 f = fopen(buf, "r");
1644 len = fread(buf, 1, sizeof(buf) - 1, f);
1651 iflink = strtoul(buf, NULL, 0);
1652 ifindex = system_if_resolve(dev);
1653 if (!iflink || iflink == ifindex)
1656 devname = if_indextoname(iflink, buf);
1660 return device_get(devname, true);
1664 read_string_file(int dir_fd, const char *file, char *buf, int len)
1670 fd = openat(dir_fd, file, O_RDONLY);
1675 len = read(fd, buf, len - 1);
1679 } else if (len > 0) {
1682 c = strchr(buf, '\n');
1695 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1700 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1702 *val = strtoull(buf, NULL, 0);
1707 /* Assume advertised flags == supported flags */
1708 static const struct {
1711 } ethtool_link_modes[] = {
1712 { ADVERTISED_10baseT_Half, "10H" },
1713 { ADVERTISED_10baseT_Full, "10F" },
1714 { ADVERTISED_100baseT_Half, "100H" },
1715 { ADVERTISED_100baseT_Full, "100F" },
1716 { ADVERTISED_1000baseT_Half, "1000H" },
1717 { ADVERTISED_1000baseT_Full, "1000F" },
1720 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1723 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1724 if (mask & ethtool_link_modes[i].mask)
1725 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1730 system_if_force_external(const char *ifname)
1735 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1736 return stat(buf, &s) == 0;
1740 system_if_dump_info(struct device *dev, struct blob_buf *b)
1742 struct ethtool_cmd ecmd;
1748 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
1749 dir_fd = open(buf, O_DIRECTORY);
1751 memset(&ecmd, 0, sizeof(ecmd));
1752 memset(&ifr, 0, sizeof(ifr));
1753 strcpy(ifr.ifr_name, dev->ifname);
1754 ifr.ifr_data = (caddr_t) &ecmd;
1755 ecmd.cmd = ETHTOOL_GSET;
1757 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1758 c = blobmsg_open_array(b, "link-advertising");
1759 system_add_link_modes(b, ecmd.advertising);
1760 blobmsg_close_array(b, c);
1762 c = blobmsg_open_array(b, "link-supported");
1763 system_add_link_modes(b, ecmd.supported);
1764 blobmsg_close_array(b, c);
1766 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1767 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1768 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1769 blobmsg_add_string_buffer(b);
1777 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1779 const char *const counters[] = {
1780 "collisions", "rx_frame_errors", "tx_compressed",
1781 "multicast", "rx_length_errors", "tx_dropped",
1782 "rx_bytes", "rx_missed_errors", "tx_errors",
1783 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1784 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1785 "rx_dropped", "tx_aborted_errors", "tx_packets",
1786 "rx_errors", "tx_bytes", "tx_window_errors",
1787 "rx_fifo_errors", "tx_carrier_errors",
1794 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1795 stats_dir = open(buf, O_DIRECTORY);
1799 for (i = 0; i < ARRAY_SIZE(counters); i++)
1800 if (read_uint64_file(stats_dir, counters[i], &val))
1801 blobmsg_add_u64(b, counters[i], val);
1807 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1809 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1810 int alen = v4 ? 4 : 16;
1811 unsigned int flags = 0;
1812 struct ifaddrmsg ifa = {
1813 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1814 .ifa_prefixlen = addr->mask,
1815 .ifa_index = dev->ifindex,
1819 if (cmd == RTM_NEWADDR)
1820 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1822 msg = nlmsg_alloc_simple(cmd, flags);
1826 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1827 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1829 if (addr->broadcast)
1830 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1831 if (addr->point_to_point)
1832 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1834 time_t now = system_get_rtime();
1835 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1837 if (addr->preferred_until) {
1838 int64_t preferred = addr->preferred_until - now;
1841 else if (preferred > UINT32_MAX)
1842 preferred = UINT32_MAX;
1844 cinfo.ifa_prefered = preferred;
1847 if (addr->valid_until) {
1848 int64_t valid = addr->valid_until - now;
1853 else if (valid > UINT32_MAX)
1856 cinfo.ifa_valid = valid;
1859 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1861 if (cmd == RTM_NEWADDR && (addr->flags & DEVADDR_OFFLINK))
1862 nla_put_u32(msg, IFA_FLAGS, IFA_F_NOPREFIXROUTE);
1865 return system_rtnl_call(msg);
1868 int system_add_address(struct device *dev, struct device_addr *addr)
1870 return system_addr(dev, addr, RTM_NEWADDR);
1873 int system_del_address(struct device *dev, struct device_addr *addr)
1875 return system_addr(dev, addr, RTM_DELADDR);
1878 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1880 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1882 unsigned int flags = 0;
1885 have_gw = !!route->nexthop.in.s_addr;
1887 have_gw = route->nexthop.in6.s6_addr32[0] ||
1888 route->nexthop.in6.s6_addr32[1] ||
1889 route->nexthop.in6.s6_addr32[2] ||
1890 route->nexthop.in6.s6_addr32[3];
1892 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1893 ? route->table : RT_TABLE_MAIN;
1895 struct rtmsg rtm = {
1896 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1897 .rtm_dst_len = route->mask,
1898 .rtm_src_len = route->sourcemask,
1899 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1900 .rtm_protocol = (route->flags & DEVROUTE_PROTO) ? route->proto : RTPROT_STATIC,
1901 .rtm_scope = RT_SCOPE_NOWHERE,
1902 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1903 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1907 if (cmd == RTM_NEWROUTE) {
1908 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1910 if (!dev) { // Add null-route
1911 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1912 rtm.rtm_type = RTN_UNREACHABLE;
1915 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1918 if (route->flags & DEVROUTE_TYPE) {
1919 rtm.rtm_type = route->type;
1920 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
1921 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
1922 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
1923 rtm.rtm_table = RT_TABLE_LOCAL;
1926 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT) {
1927 rtm.rtm_scope = RT_SCOPE_HOST;
1928 } else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
1929 rtm.rtm_type == RTN_ANYCAST) {
1930 rtm.rtm_scope = RT_SCOPE_LINK;
1931 } else if (rtm.rtm_type == RTN_BLACKHOLE || rtm.rtm_type == RTN_UNREACHABLE ||
1932 rtm.rtm_type == RTN_PROHIBIT || rtm.rtm_type == RTN_FAILED_POLICY ||
1933 rtm.rtm_type == RTN_THROW) {
1934 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1939 msg = nlmsg_alloc_simple(cmd, flags);
1943 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1946 nla_put(msg, RTA_DST, alen, &route->addr);
1948 if (route->sourcemask) {
1949 if (rtm.rtm_family == AF_INET)
1950 nla_put(msg, RTA_PREFSRC, alen, &route->source);
1952 nla_put(msg, RTA_SRC, alen, &route->source);
1955 if (route->metric > 0)
1956 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1959 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1962 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1965 nla_put_u32(msg, RTA_TABLE, table);
1967 if (route->flags & DEVROUTE_MTU) {
1968 struct nlattr *metrics;
1970 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1971 goto nla_put_failure;
1973 nla_put_u32(msg, RTAX_MTU, route->mtu);
1975 nla_nest_end(msg, metrics);
1978 return system_rtnl_call(msg);
1985 int system_add_route(struct device *dev, struct device_route *route)
1987 return system_rt(dev, route, RTM_NEWROUTE);
1990 int system_del_route(struct device *dev, struct device_route *route)
1992 return system_rt(dev, route, RTM_DELROUTE);
1995 int system_flush_routes(void)
1997 const char *names[] = {
1998 "/proc/sys/net/ipv4/route/flush",
1999 "/proc/sys/net/ipv6/route/flush"
2003 for (i = 0; i < ARRAY_SIZE(names); i++) {
2004 fd = open(names[i], O_WRONLY);
2008 if (write(fd, "-1", 2)) {}
2014 bool system_resolve_rt_type(const char *type, unsigned int *id)
2016 return system_rtn_aton(type, id);
2019 bool system_resolve_rt_proto(const char *type, unsigned int *id)
2023 unsigned int n, proto = 256;
2024 n = strtoul(type, &e, 0);
2025 if (!*e && e != type)
2027 else if (!strcmp(type, "unspec"))
2028 proto = RTPROT_UNSPEC;
2029 else if (!strcmp(type, "kernel"))
2030 proto = RTPROT_KERNEL;
2031 else if (!strcmp(type, "boot"))
2032 proto = RTPROT_BOOT;
2033 else if (!strcmp(type, "static"))
2034 proto = RTPROT_STATIC;
2035 else if ((f = fopen("/etc/iproute2/rt_protos", "r")) != NULL) {
2036 while (fgets(buf, sizeof(buf) - 1, f) != NULL) {
2037 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
2040 n = strtoul(e, NULL, 10);
2041 e = strtok(NULL, " \t\n");
2043 if (e && !strcmp(e, type)) {
2058 bool system_resolve_rt_table(const char *name, unsigned int *id)
2062 unsigned int n, table = RT_TABLE_UNSPEC;
2064 /* first try to parse table as number */
2065 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
2068 /* handle well known aliases */
2069 else if (!strcmp(name, "default"))
2070 table = RT_TABLE_DEFAULT;
2071 else if (!strcmp(name, "main"))
2072 table = RT_TABLE_MAIN;
2073 else if (!strcmp(name, "local"))
2074 table = RT_TABLE_LOCAL;
2076 /* try to look up name in /etc/iproute2/rt_tables */
2077 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
2079 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
2081 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
2084 n = strtoul(e, NULL, 10);
2085 e = strtok(NULL, " \t\n");
2087 if (e && !strcmp(e, name))
2097 if (table == RT_TABLE_UNSPEC)
2104 bool system_is_default_rt_table(unsigned int id)
2106 return (id == RT_TABLE_MAIN);
2109 bool system_resolve_rpfilter(const char *filter, unsigned int *id)
2114 if (!strcmp(filter, "strict"))
2116 else if (!strcmp(filter, "loose"))
2119 n = strtoul(filter, &e, 0);
2120 if (*e || e == filter || n > 2)
2128 static int system_iprule(struct iprule *rule, int cmd)
2130 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
2133 struct rtmsg rtm = {
2134 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
2135 .rtm_protocol = RTPROT_STATIC,
2136 .rtm_scope = RT_SCOPE_UNIVERSE,
2137 .rtm_table = RT_TABLE_UNSPEC,
2138 .rtm_type = RTN_UNSPEC,
2142 if (cmd == RTM_NEWRULE)
2143 rtm.rtm_type = RTN_UNICAST;
2146 rtm.rtm_flags |= FIB_RULE_INVERT;
2148 if (rule->flags & IPRULE_SRC)
2149 rtm.rtm_src_len = rule->src_mask;
2151 if (rule->flags & IPRULE_DEST)
2152 rtm.rtm_dst_len = rule->dest_mask;
2154 if (rule->flags & IPRULE_TOS)
2155 rtm.rtm_tos = rule->tos;
2157 if (rule->flags & IPRULE_LOOKUP) {
2158 if (rule->lookup < 256)
2159 rtm.rtm_table = rule->lookup;
2162 if (rule->flags & IPRULE_ACTION)
2163 rtm.rtm_type = rule->action;
2164 else if (rule->flags & IPRULE_GOTO)
2165 rtm.rtm_type = FR_ACT_GOTO;
2166 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
2167 rtm.rtm_type = FR_ACT_NOP;
2169 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
2174 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
2176 if (rule->flags & IPRULE_IN)
2177 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
2179 if (rule->flags & IPRULE_OUT)
2180 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
2182 if (rule->flags & IPRULE_SRC)
2183 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
2185 if (rule->flags & IPRULE_DEST)
2186 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
2188 if (rule->flags & IPRULE_PRIORITY)
2189 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
2190 else if (cmd == RTM_NEWRULE)
2191 nla_put_u32(msg, FRA_PRIORITY, rule->order);
2193 if (rule->flags & IPRULE_FWMARK)
2194 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
2196 if (rule->flags & IPRULE_FWMASK)
2197 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
2199 if (rule->flags & IPRULE_LOOKUP) {
2200 if (rule->lookup >= 256)
2201 nla_put_u32(msg, FRA_TABLE, rule->lookup);
2204 if (rule->flags & IPRULE_SUP_PREFIXLEN)
2205 nla_put_u32(msg, FRA_SUPPRESS_PREFIXLEN, rule->sup_prefixlen);
2207 if (rule->flags & IPRULE_GOTO)
2208 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
2210 return system_rtnl_call(msg);
2213 int system_add_iprule(struct iprule *rule)
2215 return system_iprule(rule, RTM_NEWRULE);
2218 int system_del_iprule(struct iprule *rule)
2220 return system_iprule(rule, RTM_DELRULE);
2223 int system_flush_iprules(void)
2228 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
2229 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
2231 memset(&rule, 0, sizeof(rule));
2234 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2237 rule.lookup = RT_TABLE_LOCAL;
2238 rv |= system_iprule(&rule, RTM_NEWRULE);
2240 rule.priority = 32766;
2241 rule.lookup = RT_TABLE_MAIN;
2242 rv |= system_iprule(&rule, RTM_NEWRULE);
2244 rule.priority = 32767;
2245 rule.lookup = RT_TABLE_DEFAULT;
2246 rv |= system_iprule(&rule, RTM_NEWRULE);
2249 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2252 rule.lookup = RT_TABLE_LOCAL;
2253 rv |= system_iprule(&rule, RTM_NEWRULE);
2255 rule.priority = 32766;
2256 rule.lookup = RT_TABLE_MAIN;
2257 rv |= system_iprule(&rule, RTM_NEWRULE);
2262 bool system_resolve_iprule_action(const char *action, unsigned int *id)
2264 return system_rtn_aton(action, id);
2267 time_t system_get_rtime(void)
2272 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
2275 if (gettimeofday(&tv, NULL) == 0)
2282 #define IP_DF 0x4000
2285 static int tunnel_ioctl(const char *name, int cmd, void *p)
2289 memset(&ifr, 0, sizeof(ifr));
2290 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
2291 ifr.ifr_ifru.ifru_data = p;
2292 return ioctl(sock_ioctl, cmd, &ifr);
2295 #ifdef IFLA_IPTUN_MAX
2296 static int system_add_ip6_tunnel(const char *name, const unsigned int link,
2297 struct blob_attr **tb)
2299 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2300 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2301 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2302 struct blob_attr *cur;
2303 int ret = 0, ttl = 0;
2308 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2309 nla_put_string(nlm, IFLA_IFNAME, name);
2312 nla_put_u32(nlm, IFLA_LINK, link);
2314 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2320 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2321 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2328 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2330 if ((cur = tb[TUNNEL_ATTR_TTL]))
2331 ttl = blobmsg_get_u32(cur);
2333 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2334 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2335 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
2337 struct in6_addr in6buf;
2338 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2339 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2343 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2346 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2347 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2351 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2354 #ifdef IFLA_IPTUN_FMR_MAX
2355 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2356 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2357 struct blob_attr *dcur;
2358 unsigned drem, fmrcnt = 0;
2360 blobmsg_for_each_attr(dcur, cur, drem) {
2361 if (blobmsg_type(dcur) != BLOBMSG_TYPE_ARRAY ||
2362 strcmp(blobmsg_name(dcur), "fmrs") ||
2363 blobmsg_check_array(dcur, BLOBMSG_TYPE_UNSPEC) <= 0)
2366 struct blob_attr *rcur;
2368 blobmsg_for_each_attr(rcur, dcur, rrem) {
2369 struct blob_attr *tb_fmr[__FMR_DATA_ATTR_MAX], *tb_cur;
2370 struct in6_addr ip6prefix;
2371 struct in_addr ip4prefix;
2372 unsigned ip4len, ip6len, ealen, offset;
2374 blobmsg_parse(fmr_data_attr_list.params, __FMR_DATA_ATTR_MAX, tb_fmr,
2375 blobmsg_data(rcur), blobmsg_len(rcur));
2377 if (!(tb_cur = tb_fmr[FMR_DATA_PREFIX6]) ||
2378 !parse_ip_and_netmask(AF_INET6,
2379 blobmsg_data(tb_cur), &ip6prefix,
2385 if (!(tb_cur = tb_fmr[FMR_DATA_PREFIX4]) ||
2386 !parse_ip_and_netmask(AF_INET,
2387 blobmsg_data(tb_cur), &ip4prefix,
2393 if (!(tb_cur = tb_fmr[FMR_DATA_EALEN])) {
2397 ealen = blobmsg_get_u32(tb_cur);
2399 if (!(tb_cur = tb_fmr[FMR_DATA_OFFSET])) {
2403 offset = blobmsg_get_u32(tb_cur);
2405 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2407 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2408 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2409 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2410 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2411 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2412 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2414 nla_nest_end(nlm, rule);
2417 nla_nest_end(nlm, fmrs);
2421 nla_nest_end(nlm, infodata);
2422 nla_nest_end(nlm, linkinfo);
2424 return system_rtnl_call(nlm);
2432 #ifdef IFLA_IPTUN_MAX
2433 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
2434 static int system_add_gre_tunnel(const char *name, const char *kind,
2435 const unsigned int link, struct blob_attr **tb, bool v6)
2438 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2439 struct blob_attr *cur;
2440 uint32_t ikey = 0, okey = 0, flags = 0, flowinfo = 0;
2441 uint16_t iflags = 0, oflags = 0;
2443 int ret = 0, ttl = 0;
2445 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2449 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2450 nla_put_string(nlm, IFLA_IFNAME, name);
2452 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2458 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2459 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2466 nla_put_u32(nlm, IFLA_GRE_LINK, link);
2468 if ((cur = tb[TUNNEL_ATTR_TTL]))
2469 ttl = blobmsg_get_u32(cur);
2471 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2472 char *str = blobmsg_get_string(cur);
2473 if (strcmp(str, "inherit")) {
2476 if (!system_tos_aton(str, &uval)) {
2482 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
2487 flags |= IP6_TNL_F_USE_ORIG_TCLASS;
2493 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2494 struct blob_attr *tb_data[__GRE_DATA_ATTR_MAX];
2496 blobmsg_parse(gre_data_attr_list.params, __GRE_DATA_ATTR_MAX, tb_data,
2497 blobmsg_data(cur), blobmsg_len(cur));
2499 if ((cur = tb_data[GRE_DATA_IKEY])) {
2500 if ((ikey = blobmsg_get_u32(cur)))
2504 if ((cur = tb_data[GRE_DATA_OKEY])) {
2505 if ((okey = blobmsg_get_u32(cur)))
2509 if ((cur = tb_data[GRE_DATA_ICSUM])) {
2510 if (blobmsg_get_bool(cur))
2514 if ((cur = tb_data[GRE_DATA_OCSUM])) {
2515 if (blobmsg_get_bool(cur))
2519 if ((cur = tb_data[GRE_DATA_ISEQNO])) {
2520 if (blobmsg_get_bool(cur))
2524 if ((cur = tb[GRE_DATA_OSEQNO])) {
2525 if (blobmsg_get_bool(cur))
2531 struct in6_addr in6buf;
2532 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2533 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2537 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
2540 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2541 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2545 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
2547 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, 4);
2550 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
2553 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags);
2558 struct in_addr inbuf;
2561 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2562 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2566 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
2569 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2570 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2574 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
2576 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
2578 okey = inbuf.s_addr;
2583 ikey = inbuf.s_addr;
2589 if ((cur = tb[TUNNEL_ATTR_DF]))
2590 set_df = blobmsg_get_bool(cur);
2593 /* ttl != 0 and nopmtudisc are incompatible */
2601 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
2603 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
2607 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
2610 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
2613 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
2616 nla_put_u32(nlm, IFLA_GRE_OKEY, htonl(okey));
2619 nla_put_u32(nlm, IFLA_GRE_IKEY, htonl(ikey));
2621 nla_nest_end(nlm, infodata);
2622 nla_nest_end(nlm, linkinfo);
2624 return system_rtnl_call(nlm);
2633 static int system_add_vti_tunnel(const char *name, const char *kind,
2634 const unsigned int link, struct blob_attr **tb, bool v6)
2637 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2638 struct blob_attr *cur;
2641 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2645 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2646 nla_put_string(nlm, IFLA_IFNAME, name);
2648 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2654 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2655 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2662 nla_put_u32(nlm, IFLA_VTI_LINK, link);
2665 struct in6_addr in6buf;
2666 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2667 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2671 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(in6buf), &in6buf);
2674 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2675 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2679 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(in6buf), &in6buf);
2683 struct in_addr inbuf;
2685 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2686 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2690 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(inbuf), &inbuf);
2693 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2694 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2698 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(inbuf), &inbuf);
2703 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2704 struct blob_attr *tb_data[__VTI_DATA_ATTR_MAX];
2705 uint32_t ikey = 0, okey = 0;
2707 blobmsg_parse(vti_data_attr_list.params, __VTI_DATA_ATTR_MAX, tb_data,
2708 blobmsg_data(cur), blobmsg_len(cur));
2710 if ((cur = tb_data[VTI_DATA_IKEY])) {
2711 if ((ikey = blobmsg_get_u32(cur)))
2712 nla_put_u32(nlm, IFLA_VTI_IKEY, htonl(ikey));
2715 if ((cur = tb_data[VTI_DATA_OKEY])) {
2716 if ((okey = blobmsg_get_u32(cur)))
2717 nla_put_u32(nlm, IFLA_VTI_OKEY, htonl(okey));
2721 nla_nest_end(nlm, infodata);
2722 nla_nest_end(nlm, linkinfo);
2724 return system_rtnl_call(nlm);
2732 #ifdef IFLA_VXLAN_MAX
2733 static int system_add_vxlan(const char *name, const unsigned int link, struct blob_attr **tb, bool v6)
2735 struct blob_attr *tb_data[__VXLAN_DATA_ATTR_MAX];
2737 struct nlattr *linkinfo, *data;
2738 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
2739 struct blob_attr *cur;
2742 if ((cur = tb[TUNNEL_ATTR_DATA]))
2743 blobmsg_parse(vxlan_data_attr_list.params, __VXLAN_DATA_ATTR_MAX, tb_data,
2744 blobmsg_data(cur), blobmsg_len(cur));
2748 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
2753 nlmsg_append(msg, &iim, sizeof(iim), 0);
2755 nla_put_string(msg, IFLA_IFNAME, name);
2757 if ((cur = tb_data[VXLAN_DATA_ATTR_MACADDR])) {
2758 struct ether_addr *ea = ether_aton(blobmsg_get_string(cur));
2764 nla_put(msg, IFLA_ADDRESS, ETH_ALEN, ea);
2767 if ((cur = tb[TUNNEL_ATTR_MTU])) {
2768 uint32_t mtu = blobmsg_get_u32(cur);
2769 nla_put_u32(msg, IFLA_MTU, mtu);
2772 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO))) {
2777 nla_put_string(msg, IFLA_INFO_KIND, "vxlan");
2779 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) {
2785 nla_put_u32(msg, IFLA_VXLAN_LINK, link);
2787 if ((cur = tb_data[VXLAN_DATA_ATTR_ID])) {
2788 uint32_t id = blobmsg_get_u32(cur);
2789 if (id >= (1u << 24) - 1) {
2794 nla_put_u32(msg, IFLA_VXLAN_ID, id);
2798 struct in6_addr in6buf;
2799 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2800 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2804 nla_put(msg, IFLA_VXLAN_LOCAL6, sizeof(in6buf), &in6buf);
2807 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2808 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2812 nla_put(msg, IFLA_VXLAN_GROUP6, sizeof(in6buf), &in6buf);
2815 struct in_addr inbuf;
2817 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2818 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2822 nla_put(msg, IFLA_VXLAN_LOCAL, sizeof(inbuf), &inbuf);
2825 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2826 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2830 nla_put(msg, IFLA_VXLAN_GROUP, sizeof(inbuf), &inbuf);
2834 uint32_t port = 4789;
2835 if ((cur = tb_data[VXLAN_DATA_ATTR_PORT])) {
2836 port = blobmsg_get_u32(cur);
2837 if (port < 1 || port > 65535) {
2842 nla_put_u16(msg, IFLA_VXLAN_PORT, htons(port));
2844 if ((cur = tb_data[VXLAN_DATA_ATTR_RXCSUM])) {
2845 bool rxcsum = blobmsg_get_bool(cur);
2846 nla_put_u8(msg, IFLA_VXLAN_UDP_ZERO_CSUM6_RX, !rxcsum);
2849 if ((cur = tb_data[VXLAN_DATA_ATTR_TXCSUM])) {
2850 bool txcsum = blobmsg_get_bool(cur);
2851 nla_put_u8(msg, IFLA_VXLAN_UDP_CSUM, txcsum);
2852 nla_put_u8(msg, IFLA_VXLAN_UDP_ZERO_CSUM6_TX, !txcsum);
2855 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2856 char *str = blobmsg_get_string(cur);
2859 if (strcmp(str, "inherit")) {
2860 if (!system_tos_aton(str, &tos))
2864 nla_put_u8(msg, IFLA_VXLAN_TOS, tos);
2867 if ((cur = tb[TUNNEL_ATTR_TTL])) {
2868 uint32_t ttl = blobmsg_get_u32(cur);
2869 if (ttl < 1 || ttl > 255) {
2874 nla_put_u8(msg, IFLA_VXLAN_TTL, ttl);
2877 nla_nest_end(msg, data);
2878 nla_nest_end(msg, linkinfo);
2880 ret = system_rtnl_call(msg);
2882 D(SYSTEM, "Error adding vxlan '%s': %d\n", name, ret);
2892 static int system_add_sit_tunnel(const char *name, const unsigned int link, struct blob_attr **tb)
2894 struct blob_attr *cur;
2897 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
2901 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2902 struct blob_attr *tb_data[__SIXRD_DATA_ATTR_MAX];
2904 struct ip_tunnel_6rd p6;
2906 blobmsg_parse(sixrd_data_attr_list.params, __SIXRD_DATA_ATTR_MAX, tb_data,
2907 blobmsg_data(cur), blobmsg_len(cur));
2909 memset(&p6, 0, sizeof(p6));
2911 if ((cur = tb_data[SIXRD_DATA_PREFIX])) {
2912 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
2913 &p6.prefix, &mask) || mask > 128) {
2918 p6.prefixlen = mask;
2921 if ((cur = tb_data[SIXRD_DATA_RELAY_PREFIX])) {
2922 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
2923 &p6.relay_prefix, &mask) || mask > 32) {
2928 p6.relay_prefixlen = mask;
2931 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
2941 __system_del_ip_tunnel(name, tb);
2945 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
2947 struct blob_attr *cur;
2949 struct ip_tunnel_parm p = {
2958 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
2959 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
2962 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
2963 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
2966 if ((cur = tb[TUNNEL_ATTR_DF]))
2967 set_df = blobmsg_get_bool(cur);
2969 if ((cur = tb[TUNNEL_ATTR_TTL]))
2970 p.iph.ttl = blobmsg_get_u32(cur);
2972 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2973 char *str = blobmsg_get_string(cur);
2974 if (strcmp(str, "inherit")) {
2977 if (!system_tos_aton(str, &uval))
2985 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
2986 /* ttl !=0 and nopmtudisc are incompatible */
2987 if (p.iph.ttl && p.iph.frag_off == 0)
2990 strncpy(p.name, name, sizeof(p.name));
2992 switch (p.iph.protocol) {
2994 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
2996 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
3003 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
3005 struct blob_attr *cur;
3008 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
3010 str = blobmsg_data(cur);
3012 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
3013 !strcmp(str, "greip6") || !strcmp(str, "gretapip6") ||
3014 !strcmp(str, "vtiip") || !strcmp(str, "vtiip6") ||
3015 !strcmp(str, "vxlan") || !strcmp(str, "vxlan6"))
3016 return system_link_del(name);
3018 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
3021 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
3023 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
3025 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
3026 blob_data(attr), blob_len(attr));
3028 return __system_del_ip_tunnel(name, tb);
3031 int system_update_ipv6_mtu(struct device *dev, int mtu)
3037 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
3040 fd = open(buf, O_RDWR);
3045 ssize_t len = read(fd, buf, sizeof(buf) - 1);
3052 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) > 0)
3061 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
3063 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
3064 struct blob_attr *cur;
3067 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
3068 blob_data(attr), blob_len(attr));
3070 __system_del_ip_tunnel(name, tb);
3072 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
3074 str = blobmsg_data(cur);
3076 unsigned int ttl = 0;
3077 if ((cur = tb[TUNNEL_ATTR_TTL])) {
3078 ttl = blobmsg_get_u32(cur);
3083 unsigned int link = 0;
3084 if ((cur = tb[TUNNEL_ATTR_LINK])) {
3085 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
3089 if (iface->l3_dev.dev)
3090 link = iface->l3_dev.dev->ifindex;
3093 if (!strcmp(str, "sit"))
3094 return system_add_sit_tunnel(name, link, tb);
3095 #ifdef IFLA_IPTUN_MAX
3096 else if (!strcmp(str, "ipip6")) {
3097 return system_add_ip6_tunnel(name, link, tb);
3098 } else if (!strcmp(str, "greip")) {
3099 return system_add_gre_tunnel(name, "gre", link, tb, false);
3100 } else if (!strcmp(str, "gretapip")) {
3101 return system_add_gre_tunnel(name, "gretap", link, tb, false);
3102 } else if (!strcmp(str, "greip6")) {
3103 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
3104 } else if (!strcmp(str, "gretapip6")) {
3105 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
3107 } else if (!strcmp(str, "vtiip")) {
3108 return system_add_vti_tunnel(name, "vti", link, tb, false);
3109 } else if (!strcmp(str, "vtiip6")) {
3110 return system_add_vti_tunnel(name, "vti6", link, tb, true);
3112 #ifdef IFLA_VXLAN_MAX
3113 } else if(!strcmp(str, "vxlan")) {
3114 return system_add_vxlan(name, link, tb, false);
3115 } else if(!strcmp(str, "vxlan6")) {
3116 return system_add_vxlan(name, link, tb, true);
3119 } else if (!strcmp(str, "ipip")) {
3120 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);