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>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2
10 * as published by the Free Software Foundation
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
19 #include <sys/socket.h>
20 #include <sys/ioctl.h>
22 #include <sys/syscall.h>
25 #include <net/if_arp.h>
27 #include <arpa/inet.h>
28 #include <netinet/in.h>
30 #include <linux/rtnetlink.h>
31 #include <linux/sockios.h>
33 #include <linux/if_addr.h>
34 #include <linux/if_link.h>
35 #include <linux/if_vlan.h>
36 #include <linux/if_bridge.h>
37 #include <linux/if_tunnel.h>
38 #include <linux/ip6_tunnel.h>
39 #include <linux/ethtool.h>
40 #include <linux/fib_rules.h>
41 #include <linux/veth.h>
42 #include <linux/version.h>
44 #ifndef RTN_FAILED_POLICY
45 #define RTN_FAILED_POLICY 12
48 #ifndef IFA_F_NOPREFIXROUTE
49 #define IFA_F_NOPREFIXROUTE 0x200
53 #define IFA_FLAGS (IFA_MULTICAST + 1)
62 #include <netlink/msg.h>
63 #include <netlink/attr.h>
64 #include <netlink/socket.h>
65 #include <libubox/uloop.h>
72 struct uloop_fd uloop;
77 static int sock_ioctl = -1;
78 static struct nl_sock *sock_rtnl = NULL;
80 static int cb_rtnl_event(struct nl_msg *msg, void *arg);
81 static void handle_hotplug_event(struct uloop_fd *u, unsigned int events);
83 static char dev_buf[256];
86 handler_nl_event(struct uloop_fd *u, unsigned int events)
88 struct event_socket *ev = container_of(u, struct event_socket, uloop);
90 socklen_t errlen = sizeof(err);
93 nl_recvmsgs_default(ev->sock);
97 if (getsockopt(u->fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen))
102 // Increase rx buffer size on netlink socket
104 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
107 // Request full dump since some info got dropped
108 struct rtgenmsg msg = { .rtgen_family = AF_UNSPEC };
109 nl_send_simple(ev->sock, RTM_GETLINK, NLM_F_DUMP, &msg, sizeof(msg));
119 uloop_fd_delete(&ev->uloop);
123 static struct nl_sock *
124 create_socket(int protocol, int groups)
126 struct nl_sock *sock;
128 sock = nl_socket_alloc();
133 nl_join_groups(sock, groups);
135 if (nl_connect(sock, protocol))
142 create_raw_event_socket(struct event_socket *ev, int protocol, int groups,
143 uloop_fd_handler cb, int flags)
145 ev->sock = create_socket(protocol, groups);
149 ev->uloop.fd = nl_socket_get_fd(ev->sock);
151 if (uloop_fd_add(&ev->uloop, ULOOP_READ|flags))
158 create_event_socket(struct event_socket *ev, int protocol,
159 int (*cb)(struct nl_msg *msg, void *arg))
161 if (!create_raw_event_socket(ev, protocol, 0, handler_nl_event, ULOOP_ERROR_CB))
164 // Install the valid custom callback handler
165 nl_socket_modify_cb(ev->sock, NL_CB_VALID, NL_CB_CUSTOM, cb, NULL);
167 // Disable sequence number checking on event sockets
168 nl_socket_disable_seq_check(ev->sock);
170 // Increase rx buffer size to 65K on event sockets
172 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
179 system_rtn_aton(const char *src, unsigned int *dst)
184 if (!strcmp(src, "local"))
186 else if (!strcmp(src, "nat"))
188 else if (!strcmp(src, "broadcast"))
190 else if (!strcmp(src, "anycast"))
192 else if (!strcmp(src, "multicast"))
194 else if (!strcmp(src, "prohibit"))
196 else if (!strcmp(src, "unreachable"))
198 else if (!strcmp(src, "blackhole"))
200 else if (!strcmp(src, "xresolve"))
202 else if (!strcmp(src, "unicast"))
204 else if (!strcmp(src, "throw"))
206 else if (!strcmp(src, "failed_policy"))
207 n = RTN_FAILED_POLICY;
209 n = strtoul(src, &e, 0);
210 if (!e || *e || e == src || n > 255)
219 system_tos_aton(const char *src, unsigned *dst)
223 *dst = strtoul(src, &e, 16);
224 if (e == src || *e || *dst > 255)
230 int system_init(void)
232 static struct event_socket rtnl_event;
233 static struct event_socket hotplug_event;
235 sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0);
236 system_fd_set_cloexec(sock_ioctl);
238 // Prepare socket for routing / address control
239 sock_rtnl = create_socket(NETLINK_ROUTE, 0);
243 if (!create_event_socket(&rtnl_event, NETLINK_ROUTE, cb_rtnl_event))
246 if (!create_raw_event_socket(&hotplug_event, NETLINK_KOBJECT_UEVENT, 1,
247 handle_hotplug_event, 0))
250 // Receive network link events form kernel
251 nl_socket_add_membership(rtnl_event.sock, RTNLGRP_LINK);
256 static void system_set_sysctl(const char *path, const char *val)
260 fd = open(path, O_WRONLY);
264 if (write(fd, val, strlen(val))) {}
268 static void system_set_dev_sysctl(const char *path, const char *device, const char *val)
270 snprintf(dev_buf, sizeof(dev_buf), path, device);
271 system_set_sysctl(dev_buf, val);
274 static void system_set_disable_ipv6(struct device *dev, const char *val)
276 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val);
279 static void system_set_rpfilter(struct device *dev, const char *val)
281 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter", dev->ifname, val);
284 static void system_set_acceptlocal(struct device *dev, const char *val)
286 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local", dev->ifname, val);
289 static void system_set_igmpversion(struct device *dev, const char *val)
291 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version", dev->ifname, val);
294 static void system_set_mldversion(struct device *dev, const char *val)
296 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version", dev->ifname, val);
299 static void system_set_neigh4reachabletime(struct device *dev, const char *val)
301 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms", dev->ifname, val);
304 static void system_set_neigh6reachabletime(struct device *dev, const char *val)
306 system_set_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms", dev->ifname, val);
309 static void system_set_neigh4gcstaletime(struct device *dev, const char *val)
311 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/gc_stale_time", dev->ifname, val);
314 static void system_set_neigh6gcstaletime(struct device *dev, const char *val)
316 system_set_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/gc_stale_time", dev->ifname, val);
319 static void system_set_dadtransmits(struct device *dev, const char *val)
321 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits", dev->ifname, val);
324 static void system_bridge_set_multicast_to_unicast(struct device *dev, const char *val)
326 system_set_dev_sysctl("/sys/class/net/%s/brport/multicast_to_unicast", dev->ifname, val);
329 static void system_bridge_set_multicast_fast_leave(struct device *dev, const char *val)
331 system_set_dev_sysctl("/sys/class/net/%s/brport/multicast_fast_leave", dev->ifname, val);
334 static void system_bridge_set_hairpin_mode(struct device *dev, const char *val)
336 system_set_dev_sysctl("/sys/class/net/%s/brport/hairpin_mode", dev->ifname, val);
339 static void system_bridge_set_multicast_router(struct device *dev, const char *val, bool bridge)
341 system_set_dev_sysctl(bridge ? "/sys/class/net/%s/bridge/multicast_router" :
342 "/sys/class/net/%s/brport/multicast_router",
346 static void system_bridge_set_robustness(struct device *dev, const char *val)
348 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_startup_query_count",
350 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_last_member_count",
354 static void system_bridge_set_query_interval(struct device *dev, const char *val)
356 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_query_interval",
360 static void system_bridge_set_query_response_interval(struct device *dev, const char *val)
362 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_query_response_interval",
366 static void system_bridge_set_last_member_interval(struct device *dev, const char *val)
368 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_last_member_interval",
372 static void system_bridge_set_membership_interval(struct device *dev, const char *val)
374 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_membership_interval",
378 static void system_bridge_set_other_querier_timeout(struct device *dev, const char *val)
380 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier_interval",
384 static void system_bridge_set_startup_query_interval(struct device *dev, const char *val)
386 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_startup_query_interval",
390 static void system_bridge_set_learning(struct device *dev, const char *val)
392 system_set_dev_sysctl("/sys/class/net/%s/brport/learning", dev->ifname, val);
395 static void system_bridge_set_unicast_flood(struct device *dev, const char *val)
397 system_set_dev_sysctl("/sys/class/net/%s/brport/unicast_flood", dev->ifname, val);
400 static void system_set_sendredirects(struct device *dev, const char *val)
402 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/send_redirects", dev->ifname, val);
405 static int system_get_sysctl(const char *path, char *buf, const size_t buf_sz)
407 int fd = -1, ret = -1;
409 fd = open(path, O_RDONLY);
413 ssize_t len = read(fd, buf, buf_sz - 1);
427 system_get_dev_sysctl(const char *path, const char *device, char *buf, const size_t buf_sz)
429 snprintf(dev_buf, sizeof(dev_buf), path, device);
430 return system_get_sysctl(dev_buf, buf, buf_sz);
433 static int system_get_disable_ipv6(struct device *dev, char *buf, const size_t buf_sz)
435 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6",
436 dev->ifname, buf, buf_sz);
439 static int system_get_rpfilter(struct device *dev, char *buf, const size_t buf_sz)
441 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter",
442 dev->ifname, buf, buf_sz);
445 static int system_get_acceptlocal(struct device *dev, char *buf, const size_t buf_sz)
447 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local",
448 dev->ifname, buf, buf_sz);
451 static int system_get_igmpversion(struct device *dev, char *buf, const size_t buf_sz)
453 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version",
454 dev->ifname, buf, buf_sz);
457 static int system_get_mldversion(struct device *dev, char *buf, const size_t buf_sz)
459 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version",
460 dev->ifname, buf, buf_sz);
463 static int system_get_neigh4reachabletime(struct device *dev, char *buf, const size_t buf_sz)
465 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms",
466 dev->ifname, buf, buf_sz);
469 static int system_get_neigh6reachabletime(struct device *dev, char *buf, const size_t buf_sz)
471 return system_get_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms",
472 dev->ifname, buf, buf_sz);
475 static int system_get_neigh4gcstaletime(struct device *dev, char *buf, const size_t buf_sz)
477 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/gc_stale_time",
478 dev->ifname, buf, buf_sz);
481 static int system_get_neigh6gcstaletime(struct device *dev, char *buf, const size_t buf_sz)
483 return system_get_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/gc_stale_time",
484 dev->ifname, buf, buf_sz);
487 static int system_get_dadtransmits(struct device *dev, char *buf, const size_t buf_sz)
489 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits",
490 dev->ifname, buf, buf_sz);
493 static int system_get_sendredirects(struct device *dev, char *buf, const size_t buf_sz)
495 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/send_redirects",
496 dev->ifname, buf, buf_sz);
499 // Evaluate netlink messages
500 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
502 struct nlmsghdr *nh = nlmsg_hdr(msg);
503 struct nlattr *nla[__IFLA_MAX];
507 if (nh->nlmsg_type != RTM_NEWLINK)
510 nlmsg_parse(nh, sizeof(struct ifinfomsg), nla, __IFLA_MAX - 1, NULL);
511 if (!nla[IFLA_IFNAME])
514 struct device *dev = device_find(nla_data(nla[IFLA_IFNAME]));
518 if (!system_get_dev_sysctl("/sys/class/net/%s/carrier", dev->ifname, buf, sizeof(buf)))
519 link_state = strtoul(buf, NULL, 0);
521 device_set_link(dev, link_state ? true : false);
528 handle_hotplug_msg(char *data, int size)
530 const char *subsystem = NULL, *interface = NULL;
531 char *cur, *end, *sep;
536 if (!strncmp(data, "add@", 4))
538 else if (!strncmp(data, "remove@", 7))
543 skip = strlen(data) + 1;
546 for (cur = data + skip; cur < end; cur += skip) {
547 skip = strlen(cur) + 1;
549 sep = strchr(cur, '=');
554 if (!strcmp(cur, "INTERFACE"))
556 else if (!strcmp(cur, "SUBSYSTEM")) {
558 if (strcmp(subsystem, "net") != 0)
561 if (subsystem && interface)
567 dev = device_find(interface);
571 if (dev->type != &simple_device_type)
574 if (add && system_if_force_external(dev->ifname))
577 device_set_present(dev, add);
581 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
583 struct event_socket *ev = container_of(u, struct event_socket, uloop);
584 struct sockaddr_nl nla;
585 unsigned char *buf = NULL;
588 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
590 handle_hotplug_msg((char *) buf, size);
596 static int system_rtnl_call(struct nl_msg *msg)
600 ret = nl_send_auto_complete(sock_rtnl, msg);
606 return nl_wait_for_ack(sock_rtnl);
609 int system_bridge_delbr(struct device *bridge)
611 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
614 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
618 memset(&ifr, 0, sizeof(ifr));
620 ifr.ifr_ifindex = dev->ifindex;
623 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
624 return ioctl(sock_ioctl, cmd, &ifr);
627 static bool system_is_bridge(const char *name, char *buf, int buflen)
631 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
632 if (stat(buf, &st) < 0)
638 static char *system_get_bridge(const char *name, char *buf, int buflen)
644 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
645 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
649 len = readlink(gl.gl_pathv[0], buf, buflen);
657 path = strrchr(buf, '/');
665 system_bridge_set_wireless(struct device *bridge, struct device *dev)
667 bool mcast_to_ucast = dev->wireless_ap;
670 if (bridge->settings.flags & DEV_OPT_MULTICAST_TO_UNICAST &&
671 !bridge->settings.multicast_to_unicast)
672 mcast_to_ucast = false;
674 if (!mcast_to_ucast || dev->wireless_isolate)
677 system_bridge_set_multicast_to_unicast(dev, mcast_to_ucast ? "1" : "0");
678 system_bridge_set_hairpin_mode(dev, hairpin ? "1" : "0");
681 int system_bridge_addif(struct device *bridge, struct device *dev)
687 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
688 if (!oldbr || strcmp(oldbr, bridge->ifname) != 0)
689 ret = system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
692 system_bridge_set_wireless(bridge, dev);
694 if (dev->settings.flags & DEV_OPT_MULTICAST_ROUTER) {
695 snprintf(buf, sizeof(buf), "%i", dev->settings.multicast_router);
696 system_bridge_set_multicast_router(dev, buf, false);
699 if (dev->settings.flags & DEV_OPT_MULTICAST_FAST_LEAVE &&
700 dev->settings.multicast_fast_leave)
701 system_bridge_set_multicast_fast_leave(dev, "1");
703 if (dev->settings.flags & DEV_OPT_LEARNING &&
704 !dev->settings.learning)
705 system_bridge_set_learning(dev, "0");
707 if (dev->settings.flags & DEV_OPT_UNICAST_FLOOD &&
708 !dev->settings.unicast_flood)
709 system_bridge_set_unicast_flood(dev, "0");
714 int system_bridge_delif(struct device *bridge, struct device *dev)
716 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
719 int system_if_resolve(struct device *dev)
722 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
723 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
724 return ifr.ifr_ifindex;
729 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
733 memset(&ifr, 0, sizeof(ifr));
734 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
735 ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
736 ifr.ifr_flags |= add;
737 ifr.ifr_flags &= ~rem;
738 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
750 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
752 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
754 return ifa->ifa_index == ifindex;
757 static bool check_route(struct nlmsghdr *hdr, int ifindex)
759 struct rtmsg *r = NLMSG_DATA(hdr);
760 struct nlattr *tb[__RTA_MAX];
762 if (r->rtm_protocol == RTPROT_KERNEL &&
763 r->rtm_family == AF_INET6)
766 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
770 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
773 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
778 static int cb_clear_event(struct nl_msg *msg, void *arg)
780 struct clear_data *clr = arg;
781 struct nlmsghdr *hdr = nlmsg_hdr(msg);
782 bool (*cb)(struct nlmsghdr *, int ifindex);
788 if (hdr->nlmsg_type != RTM_NEWADDR)
795 if (hdr->nlmsg_type != RTM_NEWROUTE)
802 if (hdr->nlmsg_type != RTM_NEWRULE)
811 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
814 if (type == RTM_DELRULE)
815 D(SYSTEM, "Remove a rule\n");
817 D(SYSTEM, "Remove %s from device %s\n",
818 type == RTM_DELADDR ? "an address" : "a route",
820 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
821 hdr = nlmsg_hdr(clr->msg);
822 hdr->nlmsg_type = type;
823 hdr->nlmsg_flags = NLM_F_REQUEST;
825 nl_socket_disable_auto_ack(sock_rtnl);
826 nl_send_auto_complete(sock_rtnl, clr->msg);
827 nl_socket_enable_auto_ack(sock_rtnl);
833 cb_finish_event(struct nl_msg *msg, void *arg)
841 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
844 *pending = err->error;
849 system_if_clear_entries(struct device *dev, int type, int af)
851 struct clear_data clr;
852 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
855 .rtm_flags = RTM_F_CLONED,
857 int flags = NLM_F_DUMP;
866 clr.size = sizeof(struct rtgenmsg);
869 clr.size = sizeof(struct rtmsg);
878 clr.msg = nlmsg_alloc_simple(type, flags);
882 nlmsg_append(clr.msg, &rtm, clr.size, 0);
883 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
884 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
885 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
887 nl_send_auto_complete(sock_rtnl, clr.msg);
889 nl_recvmsgs(sock_rtnl, cb);
897 * Clear bridge (membership) state and bring down device
899 void system_if_clear_state(struct device *dev)
901 static char buf[256];
904 device_set_ifindex(dev, system_if_resolve(dev));
905 if (dev->external || !dev->ifindex)
908 system_if_flags(dev->ifname, 0, IFF_UP);
910 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
911 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
912 system_bridge_delbr(dev);
916 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
918 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
919 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
922 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
923 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
924 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
925 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
926 system_set_disable_ipv6(dev, "0");
929 static inline unsigned long
930 sec_to_jiffies(int val)
932 return (unsigned long) val * 100;
935 static void system_bridge_conf_multicast_deps(struct device *bridge,
936 struct bridge_config *cfg,
942 if (cfg->flags & BRIDGE_OPT_ROBUSTNESS ||
943 cfg->flags & BRIDGE_OPT_QUERY_INTERVAL ||
944 cfg->flags & BRIDGE_OPT_QUERY_RESPONSE_INTERVAL) {
945 val = cfg->robustness * cfg->query_interval +
946 cfg->query_response_interval;
948 snprintf(buf, buf_len, "%i", val);
949 system_bridge_set_membership_interval(bridge, buf);
951 val = cfg->robustness * cfg->query_interval +
952 cfg->query_response_interval / 2;
954 snprintf(buf, buf_len, "%i", val);
955 system_bridge_set_other_querier_timeout(bridge, buf);
958 if (cfg->flags & BRIDGE_OPT_QUERY_INTERVAL) {
959 val = cfg->query_interval / 4;
961 snprintf(buf, buf_len, "%i", val);
962 system_bridge_set_startup_query_interval(bridge, buf);
966 static void system_bridge_conf_multicast(struct device *bridge,
967 struct bridge_config *cfg,
971 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
972 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
974 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier",
975 bridge->ifname, cfg->multicast_querier ? "1" : "0");
977 snprintf(buf, buf_len, "%i", cfg->hash_max);
978 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/hash_max",
979 bridge->ifname, buf);
981 if (bridge->settings.flags & DEV_OPT_MULTICAST_ROUTER) {
982 snprintf(buf, buf_len, "%i", bridge->settings.multicast_router);
983 system_bridge_set_multicast_router(bridge, buf, true);
986 if (cfg->flags & BRIDGE_OPT_ROBUSTNESS) {
987 snprintf(buf, buf_len, "%i", cfg->robustness);
988 system_bridge_set_robustness(bridge, buf);
991 if (cfg->flags & BRIDGE_OPT_QUERY_INTERVAL) {
992 snprintf(buf, buf_len, "%i", cfg->query_interval);
993 system_bridge_set_query_interval(bridge, buf);
996 if (cfg->flags & BRIDGE_OPT_QUERY_RESPONSE_INTERVAL) {
997 snprintf(buf, buf_len, "%i", cfg->query_response_interval);
998 system_bridge_set_query_response_interval(bridge, buf);
1001 if (cfg->flags & BRIDGE_OPT_LAST_MEMBER_INTERVAL) {
1002 snprintf(buf, buf_len, "%i", cfg->last_member_interval);
1003 system_bridge_set_last_member_interval(bridge, buf);
1006 system_bridge_conf_multicast_deps(bridge, cfg, buf, buf_len);
1009 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
1012 unsigned long args[4] = {};
1014 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
1017 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
1018 args[1] = !!cfg->stp;
1019 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1021 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
1022 args[1] = sec_to_jiffies(cfg->forward_delay);
1023 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1025 system_bridge_conf_multicast(bridge, cfg, buf, sizeof(buf));
1027 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
1028 args[1] = cfg->priority;
1029 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1031 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
1032 args[0] = BRCTL_SET_AGEING_TIME;
1033 args[1] = sec_to_jiffies(cfg->ageing_time);
1034 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1037 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
1038 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
1039 args[1] = sec_to_jiffies(cfg->hello_time);
1040 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1043 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
1044 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
1045 args[1] = sec_to_jiffies(cfg->max_age);
1046 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1052 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
1055 struct nlattr *linkinfo, *data;
1056 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
1058 static const struct {
1060 enum macvlan_mode val;
1062 { "private", MACVLAN_MODE_PRIVATE },
1063 { "vepa", MACVLAN_MODE_VEPA },
1064 { "bridge", MACVLAN_MODE_BRIDGE },
1065 { "passthru", MACVLAN_MODE_PASSTHRU },
1068 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1073 nlmsg_append(msg, &iim, sizeof(iim), 0);
1075 if (cfg->flags & MACVLAN_OPT_MACADDR)
1076 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
1077 nla_put_string(msg, IFLA_IFNAME, macvlan->ifname);
1078 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
1080 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1081 goto nla_put_failure;
1083 nla_put_string(msg, IFLA_INFO_KIND, "macvlan");
1085 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1086 goto nla_put_failure;
1089 for (i = 0; i < ARRAY_SIZE(modes); i++) {
1090 if (strcmp(cfg->mode, modes[i].name) != 0)
1093 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
1098 nla_nest_end(msg, data);
1099 nla_nest_end(msg, linkinfo);
1101 rv = system_rtnl_call(msg);
1103 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
1112 static int system_link_del(const char *ifname)
1115 struct ifinfomsg iim = {
1116 .ifi_family = AF_UNSPEC,
1120 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
1125 nlmsg_append(msg, &iim, sizeof(iim), 0);
1126 nla_put_string(msg, IFLA_IFNAME, ifname);
1127 return system_rtnl_call(msg);
1130 int system_macvlan_del(struct device *macvlan)
1132 return system_link_del(macvlan->ifname);
1135 int system_veth_add(struct device *veth, struct veth_config *cfg)
1138 struct ifinfomsg empty_iim = {};
1139 struct nlattr *linkinfo, *data, *veth_info;
1142 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1147 nlmsg_append(msg, &empty_iim, sizeof(empty_iim), 0);
1149 if (cfg->flags & VETH_OPT_MACADDR)
1150 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
1151 nla_put_string(msg, IFLA_IFNAME, veth->ifname);
1153 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1154 goto nla_put_failure;
1156 nla_put_string(msg, IFLA_INFO_KIND, "veth");
1158 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1159 goto nla_put_failure;
1161 if (!(veth_info = nla_nest_start(msg, VETH_INFO_PEER)))
1162 goto nla_put_failure;
1164 nlmsg_append(msg, &empty_iim, sizeof(empty_iim), 0);
1166 if (cfg->flags & VETH_OPT_PEER_NAME)
1167 nla_put_string(msg, IFLA_IFNAME, cfg->peer_name);
1168 if (cfg->flags & VETH_OPT_PEER_MACADDR)
1169 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->peer_macaddr), cfg->peer_macaddr);
1171 nla_nest_end(msg, veth_info);
1172 nla_nest_end(msg, data);
1173 nla_nest_end(msg, linkinfo);
1175 rv = system_rtnl_call(msg);
1177 if (cfg->flags & VETH_OPT_PEER_NAME)
1178 D(SYSTEM, "Error adding veth '%s' with peer '%s': %d\n", veth->ifname, cfg->peer_name, rv);
1180 D(SYSTEM, "Error adding veth '%s': %d\n", veth->ifname, rv);
1190 int system_veth_del(struct device *veth)
1192 return system_link_del(veth->ifname);
1195 static int system_vlan(struct device *dev, int id)
1197 struct vlan_ioctl_args ifr = {
1198 .cmd = SET_VLAN_NAME_TYPE_CMD,
1199 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
1202 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
1205 ifr.cmd = DEL_VLAN_CMD;
1208 ifr.cmd = ADD_VLAN_CMD;
1211 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
1212 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
1215 int system_vlan_add(struct device *dev, int id)
1217 return system_vlan(dev, id);
1220 int system_vlan_del(struct device *dev)
1222 return system_vlan(dev, -1);
1225 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
1228 struct nlattr *linkinfo, *data;
1229 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
1232 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1237 nlmsg_append(msg, &iim, sizeof(iim), 0);
1238 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
1239 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
1241 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1242 goto nla_put_failure;
1244 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
1246 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1247 goto nla_put_failure;
1249 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
1251 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
1252 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
1254 if(cfg->proto == VLAN_PROTO_8021AD)
1255 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);
1258 nla_nest_end(msg, data);
1259 nla_nest_end(msg, linkinfo);
1261 rv = system_rtnl_call(msg);
1263 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
1272 int system_vlandev_del(struct device *vlandev)
1274 return system_link_del(vlandev->ifname);
1278 system_if_get_settings(struct device *dev, struct device_settings *s)
1283 memset(&ifr, 0, sizeof(ifr));
1284 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1286 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
1287 s->mtu = ifr.ifr_mtu;
1288 s->flags |= DEV_OPT_MTU;
1291 s->mtu6 = system_update_ipv6_mtu(dev, 0);
1293 s->flags |= DEV_OPT_MTU6;
1295 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
1296 s->txqueuelen = ifr.ifr_qlen;
1297 s->flags |= DEV_OPT_TXQUEUELEN;
1300 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
1301 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
1302 s->flags |= DEV_OPT_MACADDR;
1305 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
1306 s->ipv6 = !strtoul(buf, NULL, 0);
1307 s->flags |= DEV_OPT_IPV6;
1310 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
1311 s->promisc = ifr.ifr_flags & IFF_PROMISC;
1312 s->flags |= DEV_OPT_PROMISC;
1314 s->multicast = ifr.ifr_flags & IFF_MULTICAST;
1315 s->flags |= DEV_OPT_MULTICAST;
1318 if (!system_get_rpfilter(dev, buf, sizeof(buf))) {
1319 s->rpfilter = strtoul(buf, NULL, 0);
1320 s->flags |= DEV_OPT_RPFILTER;
1323 if (!system_get_acceptlocal(dev, buf, sizeof(buf))) {
1324 s->acceptlocal = strtoul(buf, NULL, 0);
1325 s->flags |= DEV_OPT_ACCEPTLOCAL;
1328 if (!system_get_igmpversion(dev, buf, sizeof(buf))) {
1329 s->igmpversion = strtoul(buf, NULL, 0);
1330 s->flags |= DEV_OPT_IGMPVERSION;
1333 if (!system_get_mldversion(dev, buf, sizeof(buf))) {
1334 s->mldversion = strtoul(buf, NULL, 0);
1335 s->flags |= DEV_OPT_MLDVERSION;
1338 if (!system_get_neigh4reachabletime(dev, buf, sizeof(buf))) {
1339 s->neigh4reachabletime = strtoul(buf, NULL, 0);
1340 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1343 if (!system_get_neigh6reachabletime(dev, buf, sizeof(buf))) {
1344 s->neigh6reachabletime = strtoul(buf, NULL, 0);
1345 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1348 if (!system_get_neigh4gcstaletime(dev, buf, sizeof(buf))) {
1349 s->neigh4gcstaletime = strtoul(buf, NULL, 0);
1350 s->flags |= DEV_OPT_NEIGHGCSTALETIME;
1353 if (!system_get_neigh6gcstaletime(dev, buf, sizeof(buf))) {
1354 s->neigh6gcstaletime = strtoul(buf, NULL, 0);
1355 s->flags |= DEV_OPT_NEIGHGCSTALETIME;
1358 if (!system_get_dadtransmits(dev, buf, sizeof(buf))) {
1359 s->dadtransmits = strtoul(buf, NULL, 0);
1360 s->flags |= DEV_OPT_DADTRANSMITS;
1363 if (!system_get_sendredirects(dev, buf, sizeof(buf))) {
1364 s->sendredirects = strtoul(buf, NULL, 0);
1365 s->flags |= DEV_OPT_SENDREDIRECTS;
1370 system_if_set_rps_xps_val(const char *path, int val)
1376 if (glob(path, 0, NULL, &gl))
1379 snprintf(val_buf, sizeof(val_buf), "%x", val);
1380 for (i = 0; i < gl.gl_pathc; i++)
1381 system_set_sysctl(gl.gl_pathv[i], val_buf);
1387 system_if_apply_rps_xps(struct device *dev, struct device_settings *s)
1389 long n_cpus = sysconf(_SC_NPROCESSORS_ONLN);
1395 val = (1 << n_cpus) - 1;
1396 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/rps_cpus", dev->ifname);
1397 system_if_set_rps_xps_val(dev_buf, s->rps ? val : 0);
1399 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/xps_cpus", dev->ifname);
1400 system_if_set_rps_xps_val(dev_buf, s->xps ? val : 0);
1404 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
1409 memset(&ifr, 0, sizeof(ifr));
1410 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1411 if (s->flags & DEV_OPT_MTU & apply_mask) {
1412 ifr.ifr_mtu = s->mtu;
1413 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
1414 s->flags &= ~DEV_OPT_MTU;
1416 if (s->flags & DEV_OPT_MTU6 & apply_mask) {
1417 system_update_ipv6_mtu(dev, s->mtu6);
1419 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
1420 ifr.ifr_qlen = s->txqueuelen;
1421 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
1422 s->flags &= ~DEV_OPT_TXQUEUELEN;
1424 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
1425 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
1426 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
1427 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
1428 s->flags &= ~DEV_OPT_MACADDR;
1430 if (s->flags & DEV_OPT_IPV6 & apply_mask)
1431 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
1432 if (s->flags & DEV_OPT_PROMISC & apply_mask) {
1433 if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
1434 !s->promisc ? IFF_PROMISC : 0) < 0)
1435 s->flags &= ~DEV_OPT_PROMISC;
1437 if (s->flags & DEV_OPT_RPFILTER & apply_mask) {
1438 snprintf(buf, sizeof(buf), "%d", s->rpfilter);
1439 system_set_rpfilter(dev, buf);
1441 if (s->flags & DEV_OPT_ACCEPTLOCAL & apply_mask)
1442 system_set_acceptlocal(dev, s->acceptlocal ? "1" : "0");
1443 if (s->flags & DEV_OPT_IGMPVERSION & apply_mask) {
1444 snprintf(buf, sizeof(buf), "%d", s->igmpversion);
1445 system_set_igmpversion(dev, buf);
1447 if (s->flags & DEV_OPT_MLDVERSION & apply_mask) {
1448 snprintf(buf, sizeof(buf), "%d", s->mldversion);
1449 system_set_mldversion(dev, buf);
1451 if (s->flags & DEV_OPT_NEIGHREACHABLETIME & apply_mask) {
1452 snprintf(buf, sizeof(buf), "%d", s->neigh4reachabletime);
1453 system_set_neigh4reachabletime(dev, buf);
1454 snprintf(buf, sizeof(buf), "%d", s->neigh6reachabletime);
1455 system_set_neigh6reachabletime(dev, buf);
1457 if (s->flags & DEV_OPT_NEIGHGCSTALETIME & apply_mask) {
1458 snprintf(buf, sizeof(buf), "%d", s->neigh4gcstaletime);
1459 system_set_neigh4gcstaletime(dev, buf);
1460 snprintf(buf, sizeof(buf), "%d", s->neigh6gcstaletime);
1461 system_set_neigh6gcstaletime(dev, buf);
1463 if (s->flags & DEV_OPT_DADTRANSMITS & apply_mask) {
1464 snprintf(buf, sizeof(buf), "%d", s->dadtransmits);
1465 system_set_dadtransmits(dev, buf);
1467 if (s->flags & DEV_OPT_MULTICAST & apply_mask) {
1468 if (system_if_flags(dev->ifname, s->multicast ? IFF_MULTICAST : 0,
1469 !s->multicast ? IFF_MULTICAST : 0) < 0)
1470 s->flags &= ~DEV_OPT_MULTICAST;
1472 if (s->flags & DEV_OPT_SENDREDIRECTS & apply_mask)
1473 system_set_sendredirects(dev, s->sendredirects ? "1" : "0");
1475 system_if_apply_rps_xps(dev, s);
1478 int system_if_up(struct device *dev)
1480 system_if_get_settings(dev, &dev->orig_settings);
1481 /* Only keep orig settings based on what needs to be set */
1482 dev->orig_settings.valid_flags = dev->orig_settings.flags;
1483 dev->orig_settings.flags &= dev->settings.flags;
1484 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
1485 return system_if_flags(dev->ifname, IFF_UP, 0);
1488 int system_if_down(struct device *dev)
1490 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
1491 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
1495 struct if_check_data {
1501 #ifndef IFF_LOWER_UP
1502 #define IFF_LOWER_UP 0x10000
1505 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1507 struct nlmsghdr *nh = nlmsg_hdr(msg);
1508 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1509 struct if_check_data *chk = (struct if_check_data *)arg;
1511 if (nh->nlmsg_type != RTM_NEWLINK)
1514 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1515 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1520 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1522 struct if_check_data *chk = (struct if_check_data *)arg;
1527 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1529 struct if_check_data *chk = (struct if_check_data *)arg;
1531 device_set_present(chk->dev, false);
1532 device_set_link(chk->dev, false);
1533 chk->pending = err->error;
1538 int system_if_check(struct device *dev)
1540 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1542 struct ifinfomsg ifi = {
1543 .ifi_family = AF_UNSPEC,
1546 struct if_check_data chk = {
1552 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1556 if (nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1557 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1560 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1561 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1562 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1564 nl_send_auto_complete(sock_rtnl, msg);
1565 while (chk.pending > 0)
1566 nl_recvmsgs(sock_rtnl, cb);
1578 system_if_get_parent(struct device *dev)
1580 char buf[64], *devname;
1581 int ifindex, iflink, len;
1584 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1585 f = fopen(buf, "r");
1589 len = fread(buf, 1, sizeof(buf) - 1, f);
1596 iflink = strtoul(buf, NULL, 0);
1597 ifindex = system_if_resolve(dev);
1598 if (!iflink || iflink == ifindex)
1601 devname = if_indextoname(iflink, buf);
1605 return device_get(devname, true);
1609 read_string_file(int dir_fd, const char *file, char *buf, int len)
1615 fd = openat(dir_fd, file, O_RDONLY);
1620 len = read(fd, buf, len - 1);
1624 } else if (len > 0) {
1627 c = strchr(buf, '\n');
1640 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1645 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1647 *val = strtoull(buf, NULL, 0);
1652 /* Assume advertised flags == supported flags */
1653 static const struct {
1656 } ethtool_link_modes[] = {
1657 { ADVERTISED_10baseT_Half, "10H" },
1658 { ADVERTISED_10baseT_Full, "10F" },
1659 { ADVERTISED_100baseT_Half, "100H" },
1660 { ADVERTISED_100baseT_Full, "100F" },
1661 { ADVERTISED_1000baseT_Half, "1000H" },
1662 { ADVERTISED_1000baseT_Full, "1000F" },
1665 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1668 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1669 if (mask & ethtool_link_modes[i].mask)
1670 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1675 system_if_force_external(const char *ifname)
1680 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1681 return stat(buf, &s) == 0;
1685 system_if_dump_info(struct device *dev, struct blob_buf *b)
1687 struct ethtool_cmd ecmd;
1693 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
1694 dir_fd = open(buf, O_DIRECTORY);
1696 memset(&ecmd, 0, sizeof(ecmd));
1697 memset(&ifr, 0, sizeof(ifr));
1698 strcpy(ifr.ifr_name, dev->ifname);
1699 ifr.ifr_data = (caddr_t) &ecmd;
1700 ecmd.cmd = ETHTOOL_GSET;
1702 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1703 c = blobmsg_open_array(b, "link-advertising");
1704 system_add_link_modes(b, ecmd.advertising);
1705 blobmsg_close_array(b, c);
1707 c = blobmsg_open_array(b, "link-supported");
1708 system_add_link_modes(b, ecmd.supported);
1709 blobmsg_close_array(b, c);
1711 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1712 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1713 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1714 blobmsg_add_string_buffer(b);
1722 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1724 const char *const counters[] = {
1725 "collisions", "rx_frame_errors", "tx_compressed",
1726 "multicast", "rx_length_errors", "tx_dropped",
1727 "rx_bytes", "rx_missed_errors", "tx_errors",
1728 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1729 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1730 "rx_dropped", "tx_aborted_errors", "tx_packets",
1731 "rx_errors", "tx_bytes", "tx_window_errors",
1732 "rx_fifo_errors", "tx_carrier_errors",
1739 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1740 stats_dir = open(buf, O_DIRECTORY);
1744 for (i = 0; i < ARRAY_SIZE(counters); i++)
1745 if (read_uint64_file(stats_dir, counters[i], &val))
1746 blobmsg_add_u64(b, counters[i], val);
1752 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1754 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1755 int alen = v4 ? 4 : 16;
1756 unsigned int flags = 0;
1757 struct ifaddrmsg ifa = {
1758 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1759 .ifa_prefixlen = addr->mask,
1760 .ifa_index = dev->ifindex,
1764 if (cmd == RTM_NEWADDR)
1765 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1767 msg = nlmsg_alloc_simple(cmd, flags);
1771 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1772 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1774 if (addr->broadcast)
1775 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1776 if (addr->point_to_point)
1777 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1779 time_t now = system_get_rtime();
1780 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1782 if (addr->preferred_until) {
1783 int64_t preferred = addr->preferred_until - now;
1786 else if (preferred > UINT32_MAX)
1787 preferred = UINT32_MAX;
1789 cinfo.ifa_prefered = preferred;
1792 if (addr->valid_until) {
1793 int64_t valid = addr->valid_until - now;
1798 else if (valid > UINT32_MAX)
1801 cinfo.ifa_valid = valid;
1804 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1806 if (cmd == RTM_NEWADDR && (addr->flags & DEVADDR_OFFLINK))
1807 nla_put_u32(msg, IFA_FLAGS, IFA_F_NOPREFIXROUTE);
1810 return system_rtnl_call(msg);
1813 int system_add_address(struct device *dev, struct device_addr *addr)
1815 return system_addr(dev, addr, RTM_NEWADDR);
1818 int system_del_address(struct device *dev, struct device_addr *addr)
1820 return system_addr(dev, addr, RTM_DELADDR);
1823 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1825 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1827 unsigned int flags = 0;
1830 have_gw = !!route->nexthop.in.s_addr;
1832 have_gw = route->nexthop.in6.s6_addr32[0] ||
1833 route->nexthop.in6.s6_addr32[1] ||
1834 route->nexthop.in6.s6_addr32[2] ||
1835 route->nexthop.in6.s6_addr32[3];
1837 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1838 ? route->table : RT_TABLE_MAIN;
1840 struct rtmsg rtm = {
1841 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1842 .rtm_dst_len = route->mask,
1843 .rtm_src_len = route->sourcemask,
1844 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1845 .rtm_protocol = (route->flags & DEVROUTE_PROTO) ? route->proto : RTPROT_STATIC,
1846 .rtm_scope = RT_SCOPE_NOWHERE,
1847 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1848 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1852 if (cmd == RTM_NEWROUTE) {
1853 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1855 if (!dev) { // Add null-route
1856 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1857 rtm.rtm_type = RTN_UNREACHABLE;
1860 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1863 if (route->flags & DEVROUTE_TYPE) {
1864 rtm.rtm_type = route->type;
1865 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
1866 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
1867 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
1868 rtm.rtm_table = RT_TABLE_LOCAL;
1871 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT) {
1872 rtm.rtm_scope = RT_SCOPE_HOST;
1873 } else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
1874 rtm.rtm_type == RTN_ANYCAST) {
1875 rtm.rtm_scope = RT_SCOPE_LINK;
1876 } else if (rtm.rtm_type == RTN_BLACKHOLE || rtm.rtm_type == RTN_UNREACHABLE ||
1877 rtm.rtm_type == RTN_PROHIBIT || rtm.rtm_type == RTN_FAILED_POLICY) {
1878 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1883 msg = nlmsg_alloc_simple(cmd, flags);
1887 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1890 nla_put(msg, RTA_DST, alen, &route->addr);
1892 if (route->sourcemask) {
1893 if (rtm.rtm_family == AF_INET)
1894 nla_put(msg, RTA_PREFSRC, alen, &route->source);
1896 nla_put(msg, RTA_SRC, alen, &route->source);
1899 if (route->metric > 0)
1900 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1903 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1906 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1909 nla_put_u32(msg, RTA_TABLE, table);
1911 if (route->flags & DEVROUTE_MTU) {
1912 struct nlattr *metrics;
1914 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1915 goto nla_put_failure;
1917 nla_put_u32(msg, RTAX_MTU, route->mtu);
1919 nla_nest_end(msg, metrics);
1922 return system_rtnl_call(msg);
1929 int system_add_route(struct device *dev, struct device_route *route)
1931 return system_rt(dev, route, RTM_NEWROUTE);
1934 int system_del_route(struct device *dev, struct device_route *route)
1936 return system_rt(dev, route, RTM_DELROUTE);
1939 int system_flush_routes(void)
1941 const char *names[] = {
1942 "/proc/sys/net/ipv4/route/flush",
1943 "/proc/sys/net/ipv6/route/flush"
1947 for (i = 0; i < ARRAY_SIZE(names); i++) {
1948 fd = open(names[i], O_WRONLY);
1952 if (write(fd, "-1", 2)) {}
1958 bool system_resolve_rt_type(const char *type, unsigned int *id)
1960 return system_rtn_aton(type, id);
1963 bool system_resolve_rt_proto(const char *type, unsigned int *id)
1967 unsigned int n, proto = 256;
1969 if ((n = strtoul(type, &e, 0)) >= 0 && !*e && e != type)
1971 else if (!strcmp(type, "unspec"))
1972 proto = RTPROT_UNSPEC;
1973 else if (!strcmp(type, "kernel"))
1974 proto = RTPROT_KERNEL;
1975 else if (!strcmp(type, "boot"))
1976 proto = RTPROT_BOOT;
1977 else if (!strcmp(type, "static"))
1978 proto = RTPROT_STATIC;
1979 else if ((f = fopen("/etc/iproute2/rt_protos", "r")) != NULL) {
1980 while (fgets(buf, sizeof(buf) - 1, f) != NULL) {
1981 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1984 n = strtoul(e, NULL, 10);
1985 e = strtok(NULL, " \t\n");
1987 if (e && !strcmp(e, type)) {
2002 bool system_resolve_rt_table(const char *name, unsigned int *id)
2006 unsigned int n, table = RT_TABLE_UNSPEC;
2008 /* first try to parse table as number */
2009 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
2012 /* handle well known aliases */
2013 else if (!strcmp(name, "default"))
2014 table = RT_TABLE_DEFAULT;
2015 else if (!strcmp(name, "main"))
2016 table = RT_TABLE_MAIN;
2017 else if (!strcmp(name, "local"))
2018 table = RT_TABLE_LOCAL;
2020 /* try to look up name in /etc/iproute2/rt_tables */
2021 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
2023 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
2025 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
2028 n = strtoul(e, NULL, 10);
2029 e = strtok(NULL, " \t\n");
2031 if (e && !strcmp(e, name))
2041 if (table == RT_TABLE_UNSPEC)
2048 bool system_is_default_rt_table(unsigned int id)
2050 return (id == RT_TABLE_MAIN);
2053 bool system_resolve_rpfilter(const char *filter, unsigned int *id)
2058 if (!strcmp(filter, "strict"))
2060 else if (!strcmp(filter, "loose"))
2063 n = strtoul(filter, &e, 0);
2064 if (*e || e == filter || n > 2)
2072 static int system_iprule(struct iprule *rule, int cmd)
2074 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
2077 struct rtmsg rtm = {
2078 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
2079 .rtm_protocol = RTPROT_STATIC,
2080 .rtm_scope = RT_SCOPE_UNIVERSE,
2081 .rtm_table = RT_TABLE_UNSPEC,
2082 .rtm_type = RTN_UNSPEC,
2086 if (cmd == RTM_NEWRULE)
2087 rtm.rtm_type = RTN_UNICAST;
2090 rtm.rtm_flags |= FIB_RULE_INVERT;
2092 if (rule->flags & IPRULE_SRC)
2093 rtm.rtm_src_len = rule->src_mask;
2095 if (rule->flags & IPRULE_DEST)
2096 rtm.rtm_dst_len = rule->dest_mask;
2098 if (rule->flags & IPRULE_TOS)
2099 rtm.rtm_tos = rule->tos;
2101 if (rule->flags & IPRULE_LOOKUP) {
2102 if (rule->lookup < 256)
2103 rtm.rtm_table = rule->lookup;
2106 if (rule->flags & IPRULE_ACTION)
2107 rtm.rtm_type = rule->action;
2108 else if (rule->flags & IPRULE_GOTO)
2109 rtm.rtm_type = FR_ACT_GOTO;
2110 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
2111 rtm.rtm_type = FR_ACT_NOP;
2113 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
2118 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
2120 if (rule->flags & IPRULE_IN)
2121 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
2123 if (rule->flags & IPRULE_OUT)
2124 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
2126 if (rule->flags & IPRULE_SRC)
2127 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
2129 if (rule->flags & IPRULE_DEST)
2130 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
2132 if (rule->flags & IPRULE_PRIORITY)
2133 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
2134 else if (cmd == RTM_NEWRULE)
2135 nla_put_u32(msg, FRA_PRIORITY, rule->order);
2137 if (rule->flags & IPRULE_FWMARK)
2138 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
2140 if (rule->flags & IPRULE_FWMASK)
2141 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
2143 if (rule->flags & IPRULE_LOOKUP) {
2144 if (rule->lookup >= 256)
2145 nla_put_u32(msg, FRA_TABLE, rule->lookup);
2148 if (rule->flags & IPRULE_GOTO)
2149 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
2151 return system_rtnl_call(msg);
2154 int system_add_iprule(struct iprule *rule)
2156 return system_iprule(rule, RTM_NEWRULE);
2159 int system_del_iprule(struct iprule *rule)
2161 return system_iprule(rule, RTM_DELRULE);
2164 int system_flush_iprules(void)
2169 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
2170 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
2172 memset(&rule, 0, sizeof(rule));
2175 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2178 rule.lookup = RT_TABLE_LOCAL;
2179 rv |= system_iprule(&rule, RTM_NEWRULE);
2181 rule.priority = 32766;
2182 rule.lookup = RT_TABLE_MAIN;
2183 rv |= system_iprule(&rule, RTM_NEWRULE);
2185 rule.priority = 32767;
2186 rule.lookup = RT_TABLE_DEFAULT;
2187 rv |= system_iprule(&rule, RTM_NEWRULE);
2190 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2193 rule.lookup = RT_TABLE_LOCAL;
2194 rv |= system_iprule(&rule, RTM_NEWRULE);
2196 rule.priority = 32766;
2197 rule.lookup = RT_TABLE_MAIN;
2198 rv |= system_iprule(&rule, RTM_NEWRULE);
2203 bool system_resolve_iprule_action(const char *action, unsigned int *id)
2205 return system_rtn_aton(action, id);
2208 time_t system_get_rtime(void)
2213 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
2216 if (gettimeofday(&tv, NULL) == 0)
2223 #define IP_DF 0x4000
2226 static int tunnel_ioctl(const char *name, int cmd, void *p)
2230 memset(&ifr, 0, sizeof(ifr));
2231 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
2232 ifr.ifr_ifru.ifru_data = p;
2233 return ioctl(sock_ioctl, cmd, &ifr);
2236 #ifdef IFLA_IPTUN_MAX
2237 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
2238 static int system_add_gre_tunnel(const char *name, const char *kind,
2239 const unsigned int link, struct blob_attr **tb, bool v6)
2242 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2243 struct blob_attr *cur;
2244 uint32_t ikey = 0, okey = 0, flags = 0, flowinfo = 0;
2245 uint16_t iflags = 0, oflags = 0;
2247 int ret = 0, ttl = 0;
2249 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2253 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2254 nla_put_string(nlm, IFLA_IFNAME, name);
2256 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2262 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2263 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2270 nla_put_u32(nlm, IFLA_GRE_LINK, link);
2272 if ((cur = tb[TUNNEL_ATTR_TTL]))
2273 ttl = blobmsg_get_u32(cur);
2275 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2276 char *str = blobmsg_get_string(cur);
2277 if (strcmp(str, "inherit")) {
2280 if (!system_tos_aton(str, &uval)) {
2286 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
2291 flags |= IP6_TNL_F_USE_ORIG_TCLASS;
2297 if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) {
2298 uint8_t icsum, ocsum, iseqno, oseqno;
2299 if (sscanf(blobmsg_get_string(cur), "%u,%u,%hhu,%hhu,%hhu,%hhu",
2300 &ikey, &okey, &icsum, &ocsum, &iseqno, &oseqno) < 6) {
2325 struct in6_addr in6buf;
2326 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2327 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2331 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
2334 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2335 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2339 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
2341 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, 4);
2344 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
2347 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags);
2352 struct in_addr inbuf;
2355 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2356 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2360 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
2363 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2364 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2368 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
2370 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
2372 okey = inbuf.s_addr;
2377 ikey = inbuf.s_addr;
2383 if ((cur = tb[TUNNEL_ATTR_DF]))
2384 set_df = blobmsg_get_bool(cur);
2387 /* ttl != 0 and nopmtudisc are incompatible */
2395 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
2397 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
2401 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
2404 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
2407 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
2410 nla_put_u32(nlm, IFLA_GRE_OKEY, okey);
2413 nla_put_u32(nlm, IFLA_GRE_IKEY, ikey);
2415 nla_nest_end(nlm, infodata);
2416 nla_nest_end(nlm, linkinfo);
2418 return system_rtnl_call(nlm);
2427 static int system_add_vti_tunnel(const char *name, const char *kind,
2428 const unsigned int link, struct blob_attr **tb, bool v6)
2431 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2432 struct blob_attr *cur;
2433 uint32_t ikey = 0, okey = 0;
2436 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2440 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2441 nla_put_string(nlm, IFLA_IFNAME, name);
2443 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2449 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2450 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2457 nla_put_u32(nlm, IFLA_VTI_LINK, link);
2459 if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) {
2460 if (sscanf(blobmsg_get_string(cur), "%u,%u",
2461 &ikey, &okey) < 2) {
2468 struct in6_addr in6buf;
2469 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2470 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2474 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(in6buf), &in6buf);
2477 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2478 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2482 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(in6buf), &in6buf);
2486 struct in_addr inbuf;
2488 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2489 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2493 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(inbuf), &inbuf);
2496 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2497 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2501 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(inbuf), &inbuf);
2507 nla_put_u32(nlm, IFLA_VTI_OKEY, htonl(okey));
2510 nla_put_u32(nlm, IFLA_VTI_IKEY, htonl(ikey));
2512 nla_nest_end(nlm, infodata);
2513 nla_nest_end(nlm, linkinfo);
2515 return system_rtnl_call(nlm);
2523 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
2525 struct blob_attr *cur;
2527 struct ip_tunnel_parm p = {
2536 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
2537 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
2540 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
2541 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
2544 if ((cur = tb[TUNNEL_ATTR_DF]))
2545 set_df = blobmsg_get_bool(cur);
2547 if ((cur = tb[TUNNEL_ATTR_TTL]))
2548 p.iph.ttl = blobmsg_get_u32(cur);
2550 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2551 char *str = blobmsg_get_string(cur);
2552 if (strcmp(str, "inherit")) {
2555 if (!system_tos_aton(str, &uval))
2563 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
2564 /* ttl !=0 and nopmtudisc are incompatible */
2565 if (p.iph.ttl && p.iph.frag_off == 0)
2568 strncpy(p.name, name, sizeof(p.name));
2570 switch (p.iph.protocol) {
2572 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
2574 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
2581 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
2583 struct blob_attr *cur;
2586 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2588 str = blobmsg_data(cur);
2590 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
2591 !strcmp(str, "greip6") || !strcmp(str, "gretapip6") ||
2592 !strcmp(str, "vtiip") || !strcmp(str, "vtiip6"))
2593 return system_link_del(name);
2595 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
2598 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
2600 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2602 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2603 blob_data(attr), blob_len(attr));
2605 return __system_del_ip_tunnel(name, tb);
2608 int system_update_ipv6_mtu(struct device *dev, int mtu)
2614 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
2617 fd = open(buf, O_RDWR);
2622 ssize_t len = read(fd, buf, sizeof(buf) - 1);
2629 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) > 0)
2638 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
2640 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2641 struct blob_attr *cur;
2644 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2645 blob_data(attr), blob_len(attr));
2647 __system_del_ip_tunnel(name, tb);
2649 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2651 str = blobmsg_data(cur);
2653 unsigned int ttl = 0;
2654 if ((cur = tb[TUNNEL_ATTR_TTL])) {
2655 ttl = blobmsg_get_u32(cur);
2660 unsigned int link = 0;
2661 if ((cur = tb[TUNNEL_ATTR_LINK])) {
2662 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
2666 if (iface->l3_dev.dev)
2667 link = iface->l3_dev.dev->ifindex;
2670 if (!strcmp(str, "sit")) {
2671 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
2675 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
2677 struct ip_tunnel_6rd p6;
2679 memset(&p6, 0, sizeof(p6));
2681 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
2682 &p6.prefix, &mask) || mask > 128)
2684 p6.prefixlen = mask;
2686 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
2687 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
2688 &p6.relay_prefix, &mask) || mask > 32)
2690 p6.relay_prefixlen = mask;
2693 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
2694 __system_del_ip_tunnel(name, tb);
2699 #ifdef IFLA_IPTUN_MAX
2700 } else if (!strcmp(str, "ipip6")) {
2701 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2702 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2703 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2709 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2710 nla_put_string(nlm, IFLA_IFNAME, name);
2713 nla_put_u32(nlm, IFLA_LINK, link);
2715 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2720 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2721 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2728 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2730 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2731 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2732 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
2734 struct in6_addr in6buf;
2735 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2736 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2740 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2743 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2744 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2748 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2751 #ifdef IFLA_IPTUN_FMR_MAX
2752 if ((cur = tb[TUNNEL_ATTR_FMRS])) {
2753 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2755 struct blob_attr *fmr;
2756 unsigned rem, fmrcnt = 0;
2757 blobmsg_for_each_attr(fmr, cur, rem) {
2758 if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
2761 unsigned ip4len, ip6len, ealen, offset = 6;
2765 if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
2766 ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) {
2771 struct in6_addr ip6prefix;
2772 struct in_addr ip4prefix;
2773 if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
2774 inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) {
2779 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2781 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2782 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2783 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2784 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2785 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2786 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2788 nla_nest_end(nlm, rule);
2791 nla_nest_end(nlm, fmrs);
2795 nla_nest_end(nlm, infodata);
2796 nla_nest_end(nlm, linkinfo);
2798 return system_rtnl_call(nlm);
2802 } else if (!strcmp(str, "greip")) {
2803 return system_add_gre_tunnel(name, "gre", link, tb, false);
2804 } else if (!strcmp(str, "gretapip")) {
2805 return system_add_gre_tunnel(name, "gretap", link, tb, false);
2806 } else if (!strcmp(str, "greip6")) {
2807 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
2808 } else if (!strcmp(str, "gretapip6")) {
2809 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
2811 } else if (!strcmp(str, "vtiip")) {
2812 return system_add_vti_tunnel(name, "vti", link, tb, false);
2813 } else if (!strcmp(str, "vtiip6")) {
2814 return system_add_vti_tunnel(name, "vti6", link, tb, true);
2817 } else if (!strcmp(str, "ipip")) {
2818 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);