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;
547 char *cur, *end, *sep;
552 if (!strncmp(data, "add@", 4))
554 else if (!strncmp(data, "remove@", 7))
559 skip = strlen(data) + 1;
562 for (cur = data + skip; cur < end; cur += skip) {
563 skip = strlen(cur) + 1;
565 sep = strchr(cur, '=');
570 if (!strcmp(cur, "INTERFACE"))
572 else if (!strcmp(cur, "SUBSYSTEM")) {
574 if (strcmp(subsystem, "net") != 0)
577 if (subsystem && interface)
583 dev = device_find(interface);
587 if (dev->type != &simple_device_type)
590 if (add && system_if_force_external(dev->ifname))
593 device_set_present(dev, add);
597 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
599 struct event_socket *ev = container_of(u, struct event_socket, uloop);
600 struct sockaddr_nl nla;
601 unsigned char *buf = NULL;
604 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
606 handle_hotplug_msg((char *) buf, size);
612 static int system_rtnl_call(struct nl_msg *msg)
616 ret = nl_send_auto_complete(sock_rtnl, msg);
622 return nl_wait_for_ack(sock_rtnl);
625 int system_bridge_delbr(struct device *bridge)
627 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
630 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
634 memset(&ifr, 0, sizeof(ifr));
636 ifr.ifr_ifindex = dev->ifindex;
639 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
640 return ioctl(sock_ioctl, cmd, &ifr);
643 static bool system_is_bridge(const char *name, char *buf, int buflen)
647 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
648 if (stat(buf, &st) < 0)
654 static char *system_get_bridge(const char *name, char *buf, int buflen)
660 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
661 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
665 len = readlink(gl.gl_pathv[0], buf, buflen);
673 path = strrchr(buf, '/');
681 system_bridge_set_wireless(struct device *bridge, struct device *dev)
683 bool mcast_to_ucast = dev->wireless_ap;
686 if (bridge->settings.flags & DEV_OPT_MULTICAST_TO_UNICAST &&
687 !bridge->settings.multicast_to_unicast)
688 mcast_to_ucast = false;
690 if (!mcast_to_ucast || dev->wireless_isolate)
693 system_bridge_set_multicast_to_unicast(dev, mcast_to_ucast ? "1" : "0");
694 system_bridge_set_hairpin_mode(dev, hairpin ? "1" : "0");
697 int system_bridge_addif(struct device *bridge, struct device *dev)
703 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
704 if (!oldbr || strcmp(oldbr, bridge->ifname) != 0)
705 ret = system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
708 system_bridge_set_wireless(bridge, dev);
710 if (dev->settings.flags & DEV_OPT_MULTICAST_ROUTER) {
711 snprintf(buf, sizeof(buf), "%u", dev->settings.multicast_router);
712 system_bridge_set_multicast_router(dev, buf, false);
715 if (dev->settings.flags & DEV_OPT_MULTICAST_FAST_LEAVE &&
716 dev->settings.multicast_fast_leave)
717 system_bridge_set_multicast_fast_leave(dev, "1");
719 if (dev->settings.flags & DEV_OPT_LEARNING &&
720 !dev->settings.learning)
721 system_bridge_set_learning(dev, "0");
723 if (dev->settings.flags & DEV_OPT_UNICAST_FLOOD &&
724 !dev->settings.unicast_flood)
725 system_bridge_set_unicast_flood(dev, "0");
730 int system_bridge_delif(struct device *bridge, struct device *dev)
732 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
735 int system_if_resolve(struct device *dev)
738 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
739 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
740 return ifr.ifr_ifindex;
745 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
749 memset(&ifr, 0, sizeof(ifr));
750 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
751 ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
752 ifr.ifr_flags |= add;
753 ifr.ifr_flags &= ~rem;
754 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
766 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
768 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
770 return ifa->ifa_index == ifindex;
773 static bool check_route(struct nlmsghdr *hdr, int ifindex)
775 struct rtmsg *r = NLMSG_DATA(hdr);
776 struct nlattr *tb[__RTA_MAX];
778 if (r->rtm_protocol == RTPROT_KERNEL &&
779 r->rtm_family == AF_INET6)
782 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
786 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
789 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
794 static int cb_clear_event(struct nl_msg *msg, void *arg)
796 struct clear_data *clr = arg;
797 struct nlmsghdr *hdr = nlmsg_hdr(msg);
798 bool (*cb)(struct nlmsghdr *, int ifindex);
804 if (hdr->nlmsg_type != RTM_NEWADDR)
811 if (hdr->nlmsg_type != RTM_NEWROUTE)
818 if (hdr->nlmsg_type != RTM_NEWRULE)
827 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
830 if (type == RTM_DELRULE)
831 D(SYSTEM, "Remove a rule\n");
833 D(SYSTEM, "Remove %s from device %s\n",
834 type == RTM_DELADDR ? "an address" : "a route",
836 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
837 hdr = nlmsg_hdr(clr->msg);
838 hdr->nlmsg_type = type;
839 hdr->nlmsg_flags = NLM_F_REQUEST;
841 nl_socket_disable_auto_ack(sock_rtnl);
842 nl_send_auto_complete(sock_rtnl, clr->msg);
843 nl_socket_enable_auto_ack(sock_rtnl);
849 cb_finish_event(struct nl_msg *msg, void *arg)
857 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
860 *pending = err->error;
865 system_if_clear_entries(struct device *dev, int type, int af)
867 struct clear_data clr;
868 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
871 .rtm_flags = RTM_F_CLONED,
873 int flags = NLM_F_DUMP;
882 clr.size = sizeof(struct rtgenmsg);
885 clr.size = sizeof(struct rtmsg);
894 clr.msg = nlmsg_alloc_simple(type, flags);
898 nlmsg_append(clr.msg, &rtm, clr.size, 0);
899 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
900 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
901 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
903 nl_send_auto_complete(sock_rtnl, clr.msg);
905 nl_recvmsgs(sock_rtnl, cb);
913 * Clear bridge (membership) state and bring down device
915 void system_if_clear_state(struct device *dev)
917 static char buf[256];
920 device_set_ifindex(dev, system_if_resolve(dev));
921 if (dev->external || !dev->ifindex)
924 system_if_flags(dev->ifname, 0, IFF_UP);
926 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
927 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
928 system_bridge_delbr(dev);
932 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
934 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
935 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
938 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
939 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
940 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
941 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
942 system_set_disable_ipv6(dev, "0");
945 static inline unsigned long
946 sec_to_jiffies(int val)
948 return (unsigned long) val * 100;
951 static void system_bridge_conf_multicast_deps(struct device *bridge,
952 struct bridge_config *cfg,
958 if (cfg->flags & BRIDGE_OPT_ROBUSTNESS ||
959 cfg->flags & BRIDGE_OPT_QUERY_INTERVAL ||
960 cfg->flags & BRIDGE_OPT_QUERY_RESPONSE_INTERVAL) {
961 val = cfg->robustness * cfg->query_interval +
962 cfg->query_response_interval;
964 snprintf(buf, buf_len, "%i", val);
965 system_bridge_set_membership_interval(bridge, buf);
967 val = cfg->robustness * cfg->query_interval +
968 cfg->query_response_interval / 2;
970 snprintf(buf, buf_len, "%i", val);
971 system_bridge_set_other_querier_timeout(bridge, buf);
974 if (cfg->flags & BRIDGE_OPT_QUERY_INTERVAL) {
975 val = cfg->query_interval / 4;
977 snprintf(buf, buf_len, "%i", val);
978 system_bridge_set_startup_query_interval(bridge, buf);
982 static void system_bridge_conf_multicast(struct device *bridge,
983 struct bridge_config *cfg,
987 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
988 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
990 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier",
991 bridge->ifname, cfg->multicast_querier ? "1" : "0");
993 snprintf(buf, buf_len, "%i", cfg->hash_max);
994 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/hash_max",
995 bridge->ifname, buf);
997 if (bridge->settings.flags & DEV_OPT_MULTICAST_ROUTER) {
998 snprintf(buf, buf_len, "%u", bridge->settings.multicast_router);
999 system_bridge_set_multicast_router(bridge, buf, true);
1002 if (cfg->flags & BRIDGE_OPT_ROBUSTNESS) {
1003 snprintf(buf, buf_len, "%i", cfg->robustness);
1004 system_bridge_set_robustness(bridge, buf);
1007 if (cfg->flags & BRIDGE_OPT_QUERY_INTERVAL) {
1008 snprintf(buf, buf_len, "%i", cfg->query_interval);
1009 system_bridge_set_query_interval(bridge, buf);
1012 if (cfg->flags & BRIDGE_OPT_QUERY_RESPONSE_INTERVAL) {
1013 snprintf(buf, buf_len, "%i", cfg->query_response_interval);
1014 system_bridge_set_query_response_interval(bridge, buf);
1017 if (cfg->flags & BRIDGE_OPT_LAST_MEMBER_INTERVAL) {
1018 snprintf(buf, buf_len, "%i", cfg->last_member_interval);
1019 system_bridge_set_last_member_interval(bridge, buf);
1022 system_bridge_conf_multicast_deps(bridge, cfg, buf, buf_len);
1025 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
1028 unsigned long args[4] = {};
1030 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
1033 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
1034 args[1] = !!cfg->stp;
1035 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1037 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
1038 args[1] = sec_to_jiffies(cfg->forward_delay);
1039 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1041 system_bridge_conf_multicast(bridge, cfg, buf, sizeof(buf));
1043 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
1044 args[1] = cfg->priority;
1045 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1047 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
1048 args[0] = BRCTL_SET_AGEING_TIME;
1049 args[1] = sec_to_jiffies(cfg->ageing_time);
1050 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1053 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
1054 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
1055 args[1] = sec_to_jiffies(cfg->hello_time);
1056 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1059 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
1060 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
1061 args[1] = sec_to_jiffies(cfg->max_age);
1062 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1068 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
1071 struct nlattr *linkinfo, *data;
1072 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
1074 static const struct {
1076 enum macvlan_mode val;
1078 { "private", MACVLAN_MODE_PRIVATE },
1079 { "vepa", MACVLAN_MODE_VEPA },
1080 { "bridge", MACVLAN_MODE_BRIDGE },
1081 { "passthru", MACVLAN_MODE_PASSTHRU },
1084 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1089 nlmsg_append(msg, &iim, sizeof(iim), 0);
1091 if (cfg->flags & MACVLAN_OPT_MACADDR)
1092 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
1093 nla_put_string(msg, IFLA_IFNAME, macvlan->ifname);
1094 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
1096 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1097 goto nla_put_failure;
1099 nla_put_string(msg, IFLA_INFO_KIND, "macvlan");
1101 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1102 goto nla_put_failure;
1105 for (i = 0; i < ARRAY_SIZE(modes); i++) {
1106 if (strcmp(cfg->mode, modes[i].name) != 0)
1109 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
1114 nla_nest_end(msg, data);
1115 nla_nest_end(msg, linkinfo);
1117 rv = system_rtnl_call(msg);
1119 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
1128 static int system_link_del(const char *ifname)
1131 struct ifinfomsg iim = {
1132 .ifi_family = AF_UNSPEC,
1136 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
1141 nlmsg_append(msg, &iim, sizeof(iim), 0);
1142 nla_put_string(msg, IFLA_IFNAME, ifname);
1143 return system_rtnl_call(msg);
1146 int system_macvlan_del(struct device *macvlan)
1148 return system_link_del(macvlan->ifname);
1151 int system_veth_add(struct device *veth, struct veth_config *cfg)
1154 struct ifinfomsg empty_iim = {};
1155 struct nlattr *linkinfo, *data, *veth_info;
1158 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1163 nlmsg_append(msg, &empty_iim, sizeof(empty_iim), 0);
1165 if (cfg->flags & VETH_OPT_MACADDR)
1166 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
1167 nla_put_string(msg, IFLA_IFNAME, veth->ifname);
1169 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1170 goto nla_put_failure;
1172 nla_put_string(msg, IFLA_INFO_KIND, "veth");
1174 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1175 goto nla_put_failure;
1177 if (!(veth_info = nla_nest_start(msg, VETH_INFO_PEER)))
1178 goto nla_put_failure;
1180 nlmsg_append(msg, &empty_iim, sizeof(empty_iim), 0);
1182 if (cfg->flags & VETH_OPT_PEER_NAME)
1183 nla_put_string(msg, IFLA_IFNAME, cfg->peer_name);
1184 if (cfg->flags & VETH_OPT_PEER_MACADDR)
1185 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->peer_macaddr), cfg->peer_macaddr);
1187 nla_nest_end(msg, veth_info);
1188 nla_nest_end(msg, data);
1189 nla_nest_end(msg, linkinfo);
1191 rv = system_rtnl_call(msg);
1193 if (cfg->flags & VETH_OPT_PEER_NAME)
1194 D(SYSTEM, "Error adding veth '%s' with peer '%s': %d\n", veth->ifname, cfg->peer_name, rv);
1196 D(SYSTEM, "Error adding veth '%s': %d\n", veth->ifname, rv);
1206 int system_veth_del(struct device *veth)
1208 return system_link_del(veth->ifname);
1211 static int system_vlan(struct device *dev, int id)
1213 struct vlan_ioctl_args ifr = {
1214 .cmd = SET_VLAN_NAME_TYPE_CMD,
1215 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
1218 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
1221 ifr.cmd = DEL_VLAN_CMD;
1224 ifr.cmd = ADD_VLAN_CMD;
1227 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
1228 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
1231 int system_vlan_add(struct device *dev, int id)
1233 return system_vlan(dev, id);
1236 int system_vlan_del(struct device *dev)
1238 return system_vlan(dev, -1);
1241 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
1244 struct nlattr *linkinfo, *data;
1245 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
1248 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1253 nlmsg_append(msg, &iim, sizeof(iim), 0);
1254 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
1255 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
1257 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1258 goto nla_put_failure;
1260 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
1262 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1263 goto nla_put_failure;
1265 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
1267 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
1268 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
1270 if(cfg->proto == VLAN_PROTO_8021AD)
1271 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);
1274 nla_nest_end(msg, data);
1275 nla_nest_end(msg, linkinfo);
1277 rv = system_rtnl_call(msg);
1279 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
1288 int system_vlandev_del(struct device *vlandev)
1290 return system_link_del(vlandev->ifname);
1294 system_if_get_settings(struct device *dev, struct device_settings *s)
1299 memset(&ifr, 0, sizeof(ifr));
1300 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1302 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
1303 s->mtu = ifr.ifr_mtu;
1304 s->flags |= DEV_OPT_MTU;
1307 s->mtu6 = system_update_ipv6_mtu(dev, 0);
1309 s->flags |= DEV_OPT_MTU6;
1311 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
1312 s->txqueuelen = ifr.ifr_qlen;
1313 s->flags |= DEV_OPT_TXQUEUELEN;
1316 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
1317 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
1318 s->flags |= DEV_OPT_MACADDR;
1321 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
1322 s->ipv6 = !strtoul(buf, NULL, 0);
1323 s->flags |= DEV_OPT_IPV6;
1326 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
1327 s->promisc = ifr.ifr_flags & IFF_PROMISC;
1328 s->flags |= DEV_OPT_PROMISC;
1330 s->multicast = ifr.ifr_flags & IFF_MULTICAST;
1331 s->flags |= DEV_OPT_MULTICAST;
1334 if (!system_get_rpfilter(dev, buf, sizeof(buf))) {
1335 s->rpfilter = strtoul(buf, NULL, 0);
1336 s->flags |= DEV_OPT_RPFILTER;
1339 if (!system_get_acceptlocal(dev, buf, sizeof(buf))) {
1340 s->acceptlocal = strtoul(buf, NULL, 0);
1341 s->flags |= DEV_OPT_ACCEPTLOCAL;
1344 if (!system_get_igmpversion(dev, buf, sizeof(buf))) {
1345 s->igmpversion = strtoul(buf, NULL, 0);
1346 s->flags |= DEV_OPT_IGMPVERSION;
1349 if (!system_get_mldversion(dev, buf, sizeof(buf))) {
1350 s->mldversion = strtoul(buf, NULL, 0);
1351 s->flags |= DEV_OPT_MLDVERSION;
1354 if (!system_get_neigh4reachabletime(dev, buf, sizeof(buf))) {
1355 s->neigh4reachabletime = strtoul(buf, NULL, 0);
1356 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1359 if (!system_get_neigh6reachabletime(dev, buf, sizeof(buf))) {
1360 s->neigh6reachabletime = strtoul(buf, NULL, 0);
1361 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1364 if (!system_get_neigh4locktime(dev, buf, sizeof(buf))) {
1365 s->neigh4locktime = strtol(buf, NULL, 0);
1366 s->flags |= DEV_OPT_NEIGHLOCKTIME;
1369 if (!system_get_neigh4gcstaletime(dev, buf, sizeof(buf))) {
1370 s->neigh4gcstaletime = strtoul(buf, NULL, 0);
1371 s->flags |= DEV_OPT_NEIGHGCSTALETIME;
1374 if (!system_get_neigh6gcstaletime(dev, buf, sizeof(buf))) {
1375 s->neigh6gcstaletime = strtoul(buf, NULL, 0);
1376 s->flags |= DEV_OPT_NEIGHGCSTALETIME;
1379 if (!system_get_dadtransmits(dev, buf, sizeof(buf))) {
1380 s->dadtransmits = strtoul(buf, NULL, 0);
1381 s->flags |= DEV_OPT_DADTRANSMITS;
1384 if (!system_get_sendredirects(dev, buf, sizeof(buf))) {
1385 s->sendredirects = strtoul(buf, NULL, 0);
1386 s->flags |= DEV_OPT_SENDREDIRECTS;
1391 system_if_set_rps_xps_val(const char *path, char *fmt, int val)
1397 if (glob(path, 0, NULL, &gl))
1400 snprintf(val_buf, sizeof(val_buf), fmt, val);
1401 for (i = 0; i < gl.gl_pathc; i++)
1402 system_set_sysctl(gl.gl_pathv[i], val_buf);
1408 system_if_apply_rps_xps(struct device *dev, struct device_settings *s)
1410 long n_cpus = sysconf(_SC_NPROCESSORS_ONLN);
1411 int val, rps_val, rps_flow_cnt, xps_val;
1416 val = (1 << n_cpus) - 1;
1417 rps_val = s->rps_val ? s->rps_val : val;
1418 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/rps_cpus", dev->ifname);
1419 system_if_set_rps_xps_val(dev_buf, "%x", s->rps ? rps_val : 0);
1421 rps_flow_cnt = s->rps_flow_cnt ? s->rps_flow_cnt : 0;
1422 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/rps_flow_cnt", dev->ifname);
1423 system_if_set_rps_xps_val(dev_buf, "%d", s->rps ? rps_flow_cnt : 0);
1425 xps_val = s->xps_val ? s->xps_val : val;
1426 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/xps_cpus", dev->ifname);
1427 system_if_set_rps_xps_val(dev_buf, "%x", s->xps ? xps_val : 0);
1431 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
1436 memset(&ifr, 0, sizeof(ifr));
1437 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1438 if (s->flags & DEV_OPT_MTU & apply_mask) {
1439 ifr.ifr_mtu = s->mtu;
1440 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
1441 s->flags &= ~DEV_OPT_MTU;
1443 if (s->flags & DEV_OPT_MTU6 & apply_mask) {
1444 system_update_ipv6_mtu(dev, s->mtu6);
1446 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
1447 ifr.ifr_qlen = s->txqueuelen;
1448 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
1449 s->flags &= ~DEV_OPT_TXQUEUELEN;
1451 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
1452 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
1453 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
1454 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
1455 s->flags &= ~DEV_OPT_MACADDR;
1457 if (s->flags & DEV_OPT_IPV6 & apply_mask)
1458 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
1459 if (s->flags & DEV_OPT_PROMISC & apply_mask) {
1460 if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
1461 !s->promisc ? IFF_PROMISC : 0) < 0)
1462 s->flags &= ~DEV_OPT_PROMISC;
1464 if (s->flags & DEV_OPT_RPFILTER & apply_mask) {
1465 snprintf(buf, sizeof(buf), "%u", s->rpfilter);
1466 system_set_rpfilter(dev, buf);
1468 if (s->flags & DEV_OPT_ACCEPTLOCAL & apply_mask)
1469 system_set_acceptlocal(dev, s->acceptlocal ? "1" : "0");
1470 if (s->flags & DEV_OPT_IGMPVERSION & apply_mask) {
1471 snprintf(buf, sizeof(buf), "%u", s->igmpversion);
1472 system_set_igmpversion(dev, buf);
1474 if (s->flags & DEV_OPT_MLDVERSION & apply_mask) {
1475 snprintf(buf, sizeof(buf), "%u", s->mldversion);
1476 system_set_mldversion(dev, buf);
1478 if (s->flags & DEV_OPT_NEIGHREACHABLETIME & apply_mask) {
1479 snprintf(buf, sizeof(buf), "%u", s->neigh4reachabletime);
1480 system_set_neigh4reachabletime(dev, buf);
1481 snprintf(buf, sizeof(buf), "%u", s->neigh6reachabletime);
1482 system_set_neigh6reachabletime(dev, buf);
1484 if (s->flags & DEV_OPT_NEIGHLOCKTIME & apply_mask) {
1485 snprintf(buf, sizeof(buf), "%d", s->neigh4locktime);
1486 system_set_neigh4locktime(dev, buf);
1488 if (s->flags & DEV_OPT_NEIGHGCSTALETIME & apply_mask) {
1489 snprintf(buf, sizeof(buf), "%u", s->neigh4gcstaletime);
1490 system_set_neigh4gcstaletime(dev, buf);
1491 snprintf(buf, sizeof(buf), "%u", s->neigh6gcstaletime);
1492 system_set_neigh6gcstaletime(dev, buf);
1494 if (s->flags & DEV_OPT_DADTRANSMITS & apply_mask) {
1495 snprintf(buf, sizeof(buf), "%u", s->dadtransmits);
1496 system_set_dadtransmits(dev, buf);
1498 if (s->flags & DEV_OPT_MULTICAST & apply_mask) {
1499 if (system_if_flags(dev->ifname, s->multicast ? IFF_MULTICAST : 0,
1500 !s->multicast ? IFF_MULTICAST : 0) < 0)
1501 s->flags &= ~DEV_OPT_MULTICAST;
1503 if (s->flags & DEV_OPT_SENDREDIRECTS & apply_mask)
1504 system_set_sendredirects(dev, s->sendredirects ? "1" : "0");
1506 system_if_apply_rps_xps(dev, s);
1509 int system_if_up(struct device *dev)
1511 system_if_get_settings(dev, &dev->orig_settings);
1512 /* Only keep orig settings based on what needs to be set */
1513 dev->orig_settings.valid_flags = dev->orig_settings.flags;
1514 dev->orig_settings.flags &= dev->settings.flags;
1515 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
1516 return system_if_flags(dev->ifname, IFF_UP, 0);
1519 int system_if_down(struct device *dev)
1521 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
1522 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
1526 struct if_check_data {
1532 #ifndef IFF_LOWER_UP
1533 #define IFF_LOWER_UP 0x10000
1536 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1538 struct nlmsghdr *nh = nlmsg_hdr(msg);
1539 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1540 struct if_check_data *chk = (struct if_check_data *)arg;
1542 if (nh->nlmsg_type != RTM_NEWLINK)
1545 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1546 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1551 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1553 struct if_check_data *chk = (struct if_check_data *)arg;
1558 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1560 struct if_check_data *chk = (struct if_check_data *)arg;
1562 device_set_present(chk->dev, false);
1563 device_set_link(chk->dev, false);
1564 chk->pending = err->error;
1569 int system_if_check(struct device *dev)
1571 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1573 struct ifinfomsg ifi = {
1574 .ifi_family = AF_UNSPEC,
1577 struct if_check_data chk = {
1583 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1587 if (nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1588 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1591 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1592 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1593 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1595 nl_send_auto_complete(sock_rtnl, msg);
1596 while (chk.pending > 0)
1597 nl_recvmsgs(sock_rtnl, cb);
1609 system_if_get_parent(struct device *dev)
1611 char buf[64], *devname;
1612 int ifindex, iflink, len;
1615 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1616 f = fopen(buf, "r");
1620 len = fread(buf, 1, sizeof(buf) - 1, f);
1627 iflink = strtoul(buf, NULL, 0);
1628 ifindex = system_if_resolve(dev);
1629 if (!iflink || iflink == ifindex)
1632 devname = if_indextoname(iflink, buf);
1636 return device_get(devname, true);
1640 read_string_file(int dir_fd, const char *file, char *buf, int len)
1646 fd = openat(dir_fd, file, O_RDONLY);
1651 len = read(fd, buf, len - 1);
1655 } else if (len > 0) {
1658 c = strchr(buf, '\n');
1671 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1676 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1678 *val = strtoull(buf, NULL, 0);
1683 /* Assume advertised flags == supported flags */
1684 static const struct {
1687 } ethtool_link_modes[] = {
1688 { ADVERTISED_10baseT_Half, "10H" },
1689 { ADVERTISED_10baseT_Full, "10F" },
1690 { ADVERTISED_100baseT_Half, "100H" },
1691 { ADVERTISED_100baseT_Full, "100F" },
1692 { ADVERTISED_1000baseT_Half, "1000H" },
1693 { ADVERTISED_1000baseT_Full, "1000F" },
1696 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1699 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1700 if (mask & ethtool_link_modes[i].mask)
1701 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1706 system_if_force_external(const char *ifname)
1711 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1712 return stat(buf, &s) == 0;
1716 system_if_dump_info(struct device *dev, struct blob_buf *b)
1718 struct ethtool_cmd ecmd;
1724 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
1725 dir_fd = open(buf, O_DIRECTORY);
1727 memset(&ecmd, 0, sizeof(ecmd));
1728 memset(&ifr, 0, sizeof(ifr));
1729 strcpy(ifr.ifr_name, dev->ifname);
1730 ifr.ifr_data = (caddr_t) &ecmd;
1731 ecmd.cmd = ETHTOOL_GSET;
1733 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1734 c = blobmsg_open_array(b, "link-advertising");
1735 system_add_link_modes(b, ecmd.advertising);
1736 blobmsg_close_array(b, c);
1738 c = blobmsg_open_array(b, "link-supported");
1739 system_add_link_modes(b, ecmd.supported);
1740 blobmsg_close_array(b, c);
1742 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1743 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1744 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1745 blobmsg_add_string_buffer(b);
1753 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1755 const char *const counters[] = {
1756 "collisions", "rx_frame_errors", "tx_compressed",
1757 "multicast", "rx_length_errors", "tx_dropped",
1758 "rx_bytes", "rx_missed_errors", "tx_errors",
1759 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1760 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1761 "rx_dropped", "tx_aborted_errors", "tx_packets",
1762 "rx_errors", "tx_bytes", "tx_window_errors",
1763 "rx_fifo_errors", "tx_carrier_errors",
1770 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1771 stats_dir = open(buf, O_DIRECTORY);
1775 for (i = 0; i < ARRAY_SIZE(counters); i++)
1776 if (read_uint64_file(stats_dir, counters[i], &val))
1777 blobmsg_add_u64(b, counters[i], val);
1783 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1785 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1786 int alen = v4 ? 4 : 16;
1787 unsigned int flags = 0;
1788 struct ifaddrmsg ifa = {
1789 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1790 .ifa_prefixlen = addr->mask,
1791 .ifa_index = dev->ifindex,
1795 if (cmd == RTM_NEWADDR)
1796 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1798 msg = nlmsg_alloc_simple(cmd, flags);
1802 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1803 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1805 if (addr->broadcast)
1806 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1807 if (addr->point_to_point)
1808 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1810 time_t now = system_get_rtime();
1811 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1813 if (addr->preferred_until) {
1814 int64_t preferred = addr->preferred_until - now;
1817 else if (preferred > UINT32_MAX)
1818 preferred = UINT32_MAX;
1820 cinfo.ifa_prefered = preferred;
1823 if (addr->valid_until) {
1824 int64_t valid = addr->valid_until - now;
1829 else if (valid > UINT32_MAX)
1832 cinfo.ifa_valid = valid;
1835 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1837 if (cmd == RTM_NEWADDR && (addr->flags & DEVADDR_OFFLINK))
1838 nla_put_u32(msg, IFA_FLAGS, IFA_F_NOPREFIXROUTE);
1841 return system_rtnl_call(msg);
1844 int system_add_address(struct device *dev, struct device_addr *addr)
1846 return system_addr(dev, addr, RTM_NEWADDR);
1849 int system_del_address(struct device *dev, struct device_addr *addr)
1851 return system_addr(dev, addr, RTM_DELADDR);
1854 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1856 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1858 unsigned int flags = 0;
1861 have_gw = !!route->nexthop.in.s_addr;
1863 have_gw = route->nexthop.in6.s6_addr32[0] ||
1864 route->nexthop.in6.s6_addr32[1] ||
1865 route->nexthop.in6.s6_addr32[2] ||
1866 route->nexthop.in6.s6_addr32[3];
1868 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1869 ? route->table : RT_TABLE_MAIN;
1871 struct rtmsg rtm = {
1872 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1873 .rtm_dst_len = route->mask,
1874 .rtm_src_len = route->sourcemask,
1875 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1876 .rtm_protocol = (route->flags & DEVROUTE_PROTO) ? route->proto : RTPROT_STATIC,
1877 .rtm_scope = RT_SCOPE_NOWHERE,
1878 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1879 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1883 if (cmd == RTM_NEWROUTE) {
1884 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1886 if (!dev) { // Add null-route
1887 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1888 rtm.rtm_type = RTN_UNREACHABLE;
1891 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1894 if (route->flags & DEVROUTE_TYPE) {
1895 rtm.rtm_type = route->type;
1896 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
1897 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
1898 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
1899 rtm.rtm_table = RT_TABLE_LOCAL;
1902 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT) {
1903 rtm.rtm_scope = RT_SCOPE_HOST;
1904 } else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
1905 rtm.rtm_type == RTN_ANYCAST) {
1906 rtm.rtm_scope = RT_SCOPE_LINK;
1907 } else if (rtm.rtm_type == RTN_BLACKHOLE || rtm.rtm_type == RTN_UNREACHABLE ||
1908 rtm.rtm_type == RTN_PROHIBIT || rtm.rtm_type == RTN_FAILED_POLICY ||
1909 rtm.rtm_type == RTN_THROW) {
1910 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1915 msg = nlmsg_alloc_simple(cmd, flags);
1919 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1922 nla_put(msg, RTA_DST, alen, &route->addr);
1924 if (route->sourcemask) {
1925 if (rtm.rtm_family == AF_INET)
1926 nla_put(msg, RTA_PREFSRC, alen, &route->source);
1928 nla_put(msg, RTA_SRC, alen, &route->source);
1931 if (route->metric > 0)
1932 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1935 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1938 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1941 nla_put_u32(msg, RTA_TABLE, table);
1943 if (route->flags & DEVROUTE_MTU) {
1944 struct nlattr *metrics;
1946 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1947 goto nla_put_failure;
1949 nla_put_u32(msg, RTAX_MTU, route->mtu);
1951 nla_nest_end(msg, metrics);
1954 return system_rtnl_call(msg);
1961 int system_add_route(struct device *dev, struct device_route *route)
1963 return system_rt(dev, route, RTM_NEWROUTE);
1966 int system_del_route(struct device *dev, struct device_route *route)
1968 return system_rt(dev, route, RTM_DELROUTE);
1971 int system_flush_routes(void)
1973 const char *names[] = {
1974 "/proc/sys/net/ipv4/route/flush",
1975 "/proc/sys/net/ipv6/route/flush"
1979 for (i = 0; i < ARRAY_SIZE(names); i++) {
1980 fd = open(names[i], O_WRONLY);
1984 if (write(fd, "-1", 2)) {}
1990 bool system_resolve_rt_type(const char *type, unsigned int *id)
1992 return system_rtn_aton(type, id);
1995 bool system_resolve_rt_proto(const char *type, unsigned int *id)
1999 unsigned int n, proto = 256;
2000 n = strtoul(type, &e, 0);
2001 if (!*e && e != type)
2003 else if (!strcmp(type, "unspec"))
2004 proto = RTPROT_UNSPEC;
2005 else if (!strcmp(type, "kernel"))
2006 proto = RTPROT_KERNEL;
2007 else if (!strcmp(type, "boot"))
2008 proto = RTPROT_BOOT;
2009 else if (!strcmp(type, "static"))
2010 proto = RTPROT_STATIC;
2011 else if ((f = fopen("/etc/iproute2/rt_protos", "r")) != NULL) {
2012 while (fgets(buf, sizeof(buf) - 1, f) != NULL) {
2013 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
2016 n = strtoul(e, NULL, 10);
2017 e = strtok(NULL, " \t\n");
2019 if (e && !strcmp(e, type)) {
2034 bool system_resolve_rt_table(const char *name, unsigned int *id)
2038 unsigned int n, table = RT_TABLE_UNSPEC;
2040 /* first try to parse table as number */
2041 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
2044 /* handle well known aliases */
2045 else if (!strcmp(name, "default"))
2046 table = RT_TABLE_DEFAULT;
2047 else if (!strcmp(name, "main"))
2048 table = RT_TABLE_MAIN;
2049 else if (!strcmp(name, "local"))
2050 table = RT_TABLE_LOCAL;
2052 /* try to look up name in /etc/iproute2/rt_tables */
2053 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
2055 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
2057 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
2060 n = strtoul(e, NULL, 10);
2061 e = strtok(NULL, " \t\n");
2063 if (e && !strcmp(e, name))
2073 if (table == RT_TABLE_UNSPEC)
2080 bool system_is_default_rt_table(unsigned int id)
2082 return (id == RT_TABLE_MAIN);
2085 bool system_resolve_rpfilter(const char *filter, unsigned int *id)
2090 if (!strcmp(filter, "strict"))
2092 else if (!strcmp(filter, "loose"))
2095 n = strtoul(filter, &e, 0);
2096 if (*e || e == filter || n > 2)
2104 static int system_iprule(struct iprule *rule, int cmd)
2106 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
2109 struct rtmsg rtm = {
2110 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
2111 .rtm_protocol = RTPROT_STATIC,
2112 .rtm_scope = RT_SCOPE_UNIVERSE,
2113 .rtm_table = RT_TABLE_UNSPEC,
2114 .rtm_type = RTN_UNSPEC,
2118 if (cmd == RTM_NEWRULE)
2119 rtm.rtm_type = RTN_UNICAST;
2122 rtm.rtm_flags |= FIB_RULE_INVERT;
2124 if (rule->flags & IPRULE_SRC)
2125 rtm.rtm_src_len = rule->src_mask;
2127 if (rule->flags & IPRULE_DEST)
2128 rtm.rtm_dst_len = rule->dest_mask;
2130 if (rule->flags & IPRULE_TOS)
2131 rtm.rtm_tos = rule->tos;
2133 if (rule->flags & IPRULE_LOOKUP) {
2134 if (rule->lookup < 256)
2135 rtm.rtm_table = rule->lookup;
2138 if (rule->flags & IPRULE_ACTION)
2139 rtm.rtm_type = rule->action;
2140 else if (rule->flags & IPRULE_GOTO)
2141 rtm.rtm_type = FR_ACT_GOTO;
2142 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
2143 rtm.rtm_type = FR_ACT_NOP;
2145 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
2150 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
2152 if (rule->flags & IPRULE_IN)
2153 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
2155 if (rule->flags & IPRULE_OUT)
2156 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
2158 if (rule->flags & IPRULE_SRC)
2159 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
2161 if (rule->flags & IPRULE_DEST)
2162 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
2164 if (rule->flags & IPRULE_PRIORITY)
2165 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
2166 else if (cmd == RTM_NEWRULE)
2167 nla_put_u32(msg, FRA_PRIORITY, rule->order);
2169 if (rule->flags & IPRULE_FWMARK)
2170 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
2172 if (rule->flags & IPRULE_FWMASK)
2173 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
2175 if (rule->flags & IPRULE_LOOKUP) {
2176 if (rule->lookup >= 256)
2177 nla_put_u32(msg, FRA_TABLE, rule->lookup);
2180 if (rule->flags & IPRULE_SUP_PREFIXLEN)
2181 nla_put_u32(msg, FRA_SUPPRESS_PREFIXLEN, rule->sup_prefixlen);
2183 if (rule->flags & IPRULE_GOTO)
2184 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
2186 return system_rtnl_call(msg);
2189 int system_add_iprule(struct iprule *rule)
2191 return system_iprule(rule, RTM_NEWRULE);
2194 int system_del_iprule(struct iprule *rule)
2196 return system_iprule(rule, RTM_DELRULE);
2199 int system_flush_iprules(void)
2204 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
2205 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
2207 memset(&rule, 0, sizeof(rule));
2210 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2213 rule.lookup = RT_TABLE_LOCAL;
2214 rv |= system_iprule(&rule, RTM_NEWRULE);
2216 rule.priority = 32766;
2217 rule.lookup = RT_TABLE_MAIN;
2218 rv |= system_iprule(&rule, RTM_NEWRULE);
2220 rule.priority = 32767;
2221 rule.lookup = RT_TABLE_DEFAULT;
2222 rv |= system_iprule(&rule, RTM_NEWRULE);
2225 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2228 rule.lookup = RT_TABLE_LOCAL;
2229 rv |= system_iprule(&rule, RTM_NEWRULE);
2231 rule.priority = 32766;
2232 rule.lookup = RT_TABLE_MAIN;
2233 rv |= system_iprule(&rule, RTM_NEWRULE);
2238 bool system_resolve_iprule_action(const char *action, unsigned int *id)
2240 return system_rtn_aton(action, id);
2243 time_t system_get_rtime(void)
2248 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
2251 if (gettimeofday(&tv, NULL) == 0)
2258 #define IP_DF 0x4000
2261 static int tunnel_ioctl(const char *name, int cmd, void *p)
2265 memset(&ifr, 0, sizeof(ifr));
2266 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
2267 ifr.ifr_ifru.ifru_data = p;
2268 return ioctl(sock_ioctl, cmd, &ifr);
2271 #ifdef IFLA_IPTUN_MAX
2272 static int system_add_ip6_tunnel(const char *name, const unsigned int link,
2273 struct blob_attr **tb)
2275 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2276 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2277 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2278 struct blob_attr *cur;
2279 int ret = 0, ttl = 0;
2284 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2285 nla_put_string(nlm, IFLA_IFNAME, name);
2288 nla_put_u32(nlm, IFLA_LINK, link);
2290 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2296 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2297 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2304 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2306 if ((cur = tb[TUNNEL_ATTR_TTL]))
2307 ttl = blobmsg_get_u32(cur);
2309 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2310 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2311 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
2313 struct in6_addr in6buf;
2314 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2315 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2319 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2322 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2323 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2327 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2330 #ifdef IFLA_IPTUN_FMR_MAX
2331 if ((cur = tb[TUNNEL_ATTR_FMRS])) {
2332 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2334 struct blob_attr *fmr;
2335 unsigned rem, fmrcnt = 0;
2336 blobmsg_for_each_attr(fmr, cur, rem) {
2337 if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
2340 unsigned ip4len, ip6len, ealen, offset = 6;
2344 if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
2345 ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) {
2350 struct in6_addr ip6prefix;
2351 struct in_addr ip4prefix;
2352 if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
2353 inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) {
2358 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2360 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2361 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2362 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2363 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2364 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2365 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2367 nla_nest_end(nlm, rule);
2370 nla_nest_end(nlm, fmrs);
2374 nla_nest_end(nlm, infodata);
2375 nla_nest_end(nlm, linkinfo);
2377 return system_rtnl_call(nlm);
2385 #ifdef IFLA_IPTUN_MAX
2386 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
2387 static int system_add_gre_tunnel(const char *name, const char *kind,
2388 const unsigned int link, struct blob_attr **tb, bool v6)
2391 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2392 struct blob_attr *cur;
2393 uint32_t ikey = 0, okey = 0, flags = 0, flowinfo = 0;
2394 uint16_t iflags = 0, oflags = 0;
2396 int ret = 0, ttl = 0;
2398 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2402 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2403 nla_put_string(nlm, IFLA_IFNAME, name);
2405 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2411 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2412 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2419 nla_put_u32(nlm, IFLA_GRE_LINK, link);
2421 if ((cur = tb[TUNNEL_ATTR_TTL]))
2422 ttl = blobmsg_get_u32(cur);
2424 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2425 char *str = blobmsg_get_string(cur);
2426 if (strcmp(str, "inherit")) {
2429 if (!system_tos_aton(str, &uval)) {
2435 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
2440 flags |= IP6_TNL_F_USE_ORIG_TCLASS;
2446 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2447 struct blob_attr *tb_data[__GRE_DATA_ATTR_MAX];
2449 blobmsg_parse(gre_data_attr_list.params, __GRE_DATA_ATTR_MAX, tb_data,
2450 blobmsg_data(cur), blobmsg_len(cur));
2452 if ((cur = tb_data[GRE_DATA_IKEY])) {
2453 if ((ikey = blobmsg_get_u32(cur)))
2457 if ((cur = tb_data[GRE_DATA_OKEY])) {
2458 if ((okey = blobmsg_get_u32(cur)))
2462 if ((cur = tb_data[GRE_DATA_ICSUM])) {
2463 if (blobmsg_get_bool(cur))
2467 if ((cur = tb_data[GRE_DATA_OCSUM])) {
2468 if (blobmsg_get_bool(cur))
2472 if ((cur = tb_data[GRE_DATA_ISEQNO])) {
2473 if (blobmsg_get_bool(cur))
2477 if ((cur = tb[GRE_DATA_OSEQNO])) {
2478 if (blobmsg_get_bool(cur))
2484 struct in6_addr in6buf;
2485 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2486 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2490 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
2493 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2494 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2498 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
2500 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, 4);
2503 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
2506 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags);
2511 struct in_addr inbuf;
2514 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2515 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2519 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
2522 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2523 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2527 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
2529 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
2531 okey = inbuf.s_addr;
2536 ikey = inbuf.s_addr;
2542 if ((cur = tb[TUNNEL_ATTR_DF]))
2543 set_df = blobmsg_get_bool(cur);
2546 /* ttl != 0 and nopmtudisc are incompatible */
2554 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
2556 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
2560 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
2563 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
2566 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
2569 nla_put_u32(nlm, IFLA_GRE_OKEY, htonl(okey));
2572 nla_put_u32(nlm, IFLA_GRE_IKEY, htonl(ikey));
2574 nla_nest_end(nlm, infodata);
2575 nla_nest_end(nlm, linkinfo);
2577 return system_rtnl_call(nlm);
2586 static int system_add_vti_tunnel(const char *name, const char *kind,
2587 const unsigned int link, struct blob_attr **tb, bool v6)
2590 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2591 struct blob_attr *cur;
2594 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2598 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2599 nla_put_string(nlm, IFLA_IFNAME, name);
2601 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2607 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2608 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2615 nla_put_u32(nlm, IFLA_VTI_LINK, link);
2618 struct in6_addr in6buf;
2619 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2620 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2624 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(in6buf), &in6buf);
2627 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2628 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2632 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(in6buf), &in6buf);
2636 struct in_addr inbuf;
2638 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2639 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2643 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(inbuf), &inbuf);
2646 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2647 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2651 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(inbuf), &inbuf);
2656 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2657 struct blob_attr *tb_data[__VTI_DATA_ATTR_MAX];
2658 uint32_t ikey = 0, okey = 0;
2660 blobmsg_parse(vti_data_attr_list.params, __VTI_DATA_ATTR_MAX, tb_data,
2661 blobmsg_data(cur), blobmsg_len(cur));
2663 if ((cur = tb_data[VTI_DATA_IKEY])) {
2664 if ((ikey = blobmsg_get_u32(cur)))
2665 nla_put_u32(nlm, IFLA_VTI_IKEY, htonl(ikey));
2668 if ((cur = tb_data[VTI_DATA_OKEY])) {
2669 if ((okey = blobmsg_get_u32(cur)))
2670 nla_put_u32(nlm, IFLA_VTI_OKEY, htonl(okey));
2674 nla_nest_end(nlm, infodata);
2675 nla_nest_end(nlm, linkinfo);
2677 return system_rtnl_call(nlm);
2685 #ifdef IFLA_VXLAN_MAX
2686 static int system_add_vxlan(const char *name, const unsigned int link, struct blob_attr **tb, bool v6)
2688 struct blob_attr *tb_data[__VXLAN_DATA_ATTR_MAX];
2690 struct nlattr *linkinfo, *data;
2691 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
2692 struct blob_attr *cur;
2695 if ((cur = tb[TUNNEL_ATTR_DATA]))
2696 blobmsg_parse(vxlan_data_attr_list.params, __VXLAN_DATA_ATTR_MAX, tb_data,
2697 blobmsg_data(cur), blobmsg_len(cur));
2701 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
2706 nlmsg_append(msg, &iim, sizeof(iim), 0);
2708 nla_put_string(msg, IFLA_IFNAME, name);
2710 if ((cur = tb_data[VXLAN_DATA_ATTR_MACADDR])) {
2711 struct ether_addr *ea = ether_aton(blobmsg_get_string(cur));
2717 nla_put(msg, IFLA_ADDRESS, ETH_ALEN, ea);
2720 if ((cur = tb[TUNNEL_ATTR_MTU])) {
2721 uint32_t mtu = blobmsg_get_u32(cur);
2722 nla_put_u32(msg, IFLA_MTU, mtu);
2725 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO))) {
2730 nla_put_string(msg, IFLA_INFO_KIND, "vxlan");
2732 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) {
2738 nla_put_u32(msg, IFLA_VXLAN_LINK, link);
2740 if ((cur = tb_data[VXLAN_DATA_ATTR_ID])) {
2741 uint32_t id = blobmsg_get_u32(cur);
2742 if (id >= (1u << 24) - 1) {
2747 nla_put_u32(msg, IFLA_VXLAN_ID, id);
2751 struct in6_addr in6buf;
2752 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2753 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2757 nla_put(msg, IFLA_VXLAN_LOCAL6, sizeof(in6buf), &in6buf);
2760 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2761 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2765 nla_put(msg, IFLA_VXLAN_GROUP6, sizeof(in6buf), &in6buf);
2768 struct in_addr inbuf;
2770 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2771 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2775 nla_put(msg, IFLA_VXLAN_LOCAL, sizeof(inbuf), &inbuf);
2778 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2779 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2783 nla_put(msg, IFLA_VXLAN_GROUP, sizeof(inbuf), &inbuf);
2787 uint32_t port = 4789;
2788 if ((cur = tb_data[VXLAN_DATA_ATTR_PORT])) {
2789 port = blobmsg_get_u32(cur);
2790 if (port < 1 || port > 65535) {
2795 nla_put_u16(msg, IFLA_VXLAN_PORT, htons(port));
2797 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2798 char *str = blobmsg_get_string(cur);
2801 if (strcmp(str, "inherit")) {
2802 if (!system_tos_aton(str, &tos))
2806 nla_put_u8(msg, IFLA_VXLAN_TOS, tos);
2809 if ((cur = tb[TUNNEL_ATTR_TTL])) {
2810 uint32_t ttl = blobmsg_get_u32(cur);
2811 if (ttl < 1 || ttl > 255) {
2816 nla_put_u8(msg, IFLA_VXLAN_TTL, ttl);
2819 nla_nest_end(msg, data);
2820 nla_nest_end(msg, linkinfo);
2822 ret = system_rtnl_call(msg);
2824 D(SYSTEM, "Error adding vxlan '%s': %d\n", name, ret);
2834 static int system_add_sit_tunnel(const char *name, const unsigned int link, struct blob_attr **tb)
2836 struct blob_attr *cur;
2839 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
2843 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2844 struct blob_attr *tb_data[__SIXRD_DATA_ATTR_MAX];
2846 struct ip_tunnel_6rd p6;
2848 blobmsg_parse(sixrd_data_attr_list.params, __SIXRD_DATA_ATTR_MAX, tb_data,
2849 blobmsg_data(cur), blobmsg_len(cur));
2851 memset(&p6, 0, sizeof(p6));
2853 if ((cur = tb_data[SIXRD_DATA_PREFIX])) {
2854 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
2855 &p6.prefix, &mask) || mask > 128) {
2860 p6.prefixlen = mask;
2863 if ((cur = tb_data[SIXRD_DATA_RELAY_PREFIX])) {
2864 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
2865 &p6.relay_prefix, &mask) || mask > 32) {
2870 p6.relay_prefixlen = mask;
2873 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
2883 __system_del_ip_tunnel(name, tb);
2887 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
2889 struct blob_attr *cur;
2891 struct ip_tunnel_parm p = {
2900 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
2901 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
2904 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
2905 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
2908 if ((cur = tb[TUNNEL_ATTR_DF]))
2909 set_df = blobmsg_get_bool(cur);
2911 if ((cur = tb[TUNNEL_ATTR_TTL]))
2912 p.iph.ttl = blobmsg_get_u32(cur);
2914 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2915 char *str = blobmsg_get_string(cur);
2916 if (strcmp(str, "inherit")) {
2919 if (!system_tos_aton(str, &uval))
2927 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
2928 /* ttl !=0 and nopmtudisc are incompatible */
2929 if (p.iph.ttl && p.iph.frag_off == 0)
2932 strncpy(p.name, name, sizeof(p.name));
2934 switch (p.iph.protocol) {
2936 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
2938 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
2945 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
2947 struct blob_attr *cur;
2950 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2952 str = blobmsg_data(cur);
2954 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
2955 !strcmp(str, "greip6") || !strcmp(str, "gretapip6") ||
2956 !strcmp(str, "vtiip") || !strcmp(str, "vtiip6") ||
2957 !strcmp(str, "vxlan") || !strcmp(str, "vxlan6"))
2958 return system_link_del(name);
2960 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
2963 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
2965 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2967 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2968 blob_data(attr), blob_len(attr));
2970 return __system_del_ip_tunnel(name, tb);
2973 int system_update_ipv6_mtu(struct device *dev, int mtu)
2979 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
2982 fd = open(buf, O_RDWR);
2987 ssize_t len = read(fd, buf, sizeof(buf) - 1);
2994 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) > 0)
3003 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
3005 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
3006 struct blob_attr *cur;
3009 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
3010 blob_data(attr), blob_len(attr));
3012 __system_del_ip_tunnel(name, tb);
3014 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
3016 str = blobmsg_data(cur);
3018 unsigned int ttl = 0;
3019 if ((cur = tb[TUNNEL_ATTR_TTL])) {
3020 ttl = blobmsg_get_u32(cur);
3025 unsigned int link = 0;
3026 if ((cur = tb[TUNNEL_ATTR_LINK])) {
3027 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
3031 if (iface->l3_dev.dev)
3032 link = iface->l3_dev.dev->ifindex;
3035 if (!strcmp(str, "sit"))
3036 return system_add_sit_tunnel(name, link, tb);
3037 #ifdef IFLA_IPTUN_MAX
3038 else if (!strcmp(str, "ipip6")) {
3039 return system_add_ip6_tunnel(name, link, tb);
3040 } else if (!strcmp(str, "greip")) {
3041 return system_add_gre_tunnel(name, "gre", link, tb, false);
3042 } else if (!strcmp(str, "gretapip")) {
3043 return system_add_gre_tunnel(name, "gretap", link, tb, false);
3044 } else if (!strcmp(str, "greip6")) {
3045 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
3046 } else if (!strcmp(str, "gretapip6")) {
3047 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
3049 } else if (!strcmp(str, "vtiip")) {
3050 return system_add_vti_tunnel(name, "vti", link, tb, false);
3051 } else if (!strcmp(str, "vtiip6")) {
3052 return system_add_vti_tunnel(name, "vti6", link, tb, true);
3054 #ifdef IFLA_VXLAN_MAX
3055 } else if(!strcmp(str, "vxlan")) {
3056 return system_add_vxlan(name, link, tb, false);
3057 } else if(!strcmp(str, "vxlan6")) {
3058 return system_add_vxlan(name, link, tb, true);
3061 } else if (!strcmp(str, "ipip")) {
3062 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);