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/version.h>
43 #ifndef RTN_FAILED_POLICY
44 #define RTN_FAILED_POLICY 12
47 #ifndef IFA_F_NOPREFIXROUTE
48 #define IFA_F_NOPREFIXROUTE 0x200
52 #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 static int system_vlan(struct device *dev, int id)
1137 struct vlan_ioctl_args ifr = {
1138 .cmd = SET_VLAN_NAME_TYPE_CMD,
1139 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
1142 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
1145 ifr.cmd = DEL_VLAN_CMD;
1148 ifr.cmd = ADD_VLAN_CMD;
1151 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
1152 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
1155 int system_vlan_add(struct device *dev, int id)
1157 return system_vlan(dev, id);
1160 int system_vlan_del(struct device *dev)
1162 return system_vlan(dev, -1);
1165 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
1168 struct nlattr *linkinfo, *data;
1169 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
1172 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1177 nlmsg_append(msg, &iim, sizeof(iim), 0);
1178 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
1179 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
1181 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1182 goto nla_put_failure;
1184 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
1186 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1187 goto nla_put_failure;
1189 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
1191 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
1192 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
1194 if(cfg->proto == VLAN_PROTO_8021AD)
1195 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);
1198 nla_nest_end(msg, data);
1199 nla_nest_end(msg, linkinfo);
1201 rv = system_rtnl_call(msg);
1203 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
1212 int system_vlandev_del(struct device *vlandev)
1214 return system_link_del(vlandev->ifname);
1218 system_if_get_settings(struct device *dev, struct device_settings *s)
1223 memset(&ifr, 0, sizeof(ifr));
1224 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1226 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
1227 s->mtu = ifr.ifr_mtu;
1228 s->flags |= DEV_OPT_MTU;
1231 s->mtu6 = system_update_ipv6_mtu(dev, 0);
1233 s->flags |= DEV_OPT_MTU6;
1235 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
1236 s->txqueuelen = ifr.ifr_qlen;
1237 s->flags |= DEV_OPT_TXQUEUELEN;
1240 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
1241 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
1242 s->flags |= DEV_OPT_MACADDR;
1245 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
1246 s->ipv6 = !strtoul(buf, NULL, 0);
1247 s->flags |= DEV_OPT_IPV6;
1250 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
1251 s->promisc = ifr.ifr_flags & IFF_PROMISC;
1252 s->flags |= DEV_OPT_PROMISC;
1254 s->multicast = ifr.ifr_flags & IFF_MULTICAST;
1255 s->flags |= DEV_OPT_MULTICAST;
1258 if (!system_get_rpfilter(dev, buf, sizeof(buf))) {
1259 s->rpfilter = strtoul(buf, NULL, 0);
1260 s->flags |= DEV_OPT_RPFILTER;
1263 if (!system_get_acceptlocal(dev, buf, sizeof(buf))) {
1264 s->acceptlocal = strtoul(buf, NULL, 0);
1265 s->flags |= DEV_OPT_ACCEPTLOCAL;
1268 if (!system_get_igmpversion(dev, buf, sizeof(buf))) {
1269 s->igmpversion = strtoul(buf, NULL, 0);
1270 s->flags |= DEV_OPT_IGMPVERSION;
1273 if (!system_get_mldversion(dev, buf, sizeof(buf))) {
1274 s->mldversion = strtoul(buf, NULL, 0);
1275 s->flags |= DEV_OPT_MLDVERSION;
1278 if (!system_get_neigh4reachabletime(dev, buf, sizeof(buf))) {
1279 s->neigh4reachabletime = strtoul(buf, NULL, 0);
1280 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1283 if (!system_get_neigh6reachabletime(dev, buf, sizeof(buf))) {
1284 s->neigh6reachabletime = strtoul(buf, NULL, 0);
1285 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1288 if (!system_get_neigh4gcstaletime(dev, buf, sizeof(buf))) {
1289 s->neigh4gcstaletime = strtoul(buf, NULL, 0);
1290 s->flags |= DEV_OPT_NEIGHGCSTALETIME;
1293 if (!system_get_neigh6gcstaletime(dev, buf, sizeof(buf))) {
1294 s->neigh6gcstaletime = strtoul(buf, NULL, 0);
1295 s->flags |= DEV_OPT_NEIGHGCSTALETIME;
1298 if (!system_get_dadtransmits(dev, buf, sizeof(buf))) {
1299 s->dadtransmits = strtoul(buf, NULL, 0);
1300 s->flags |= DEV_OPT_DADTRANSMITS;
1303 if (!system_get_sendredirects(dev, buf, sizeof(buf))) {
1304 s->sendredirects = strtoul(buf, NULL, 0);
1305 s->flags |= DEV_OPT_SENDREDIRECTS;
1310 system_if_set_rps_xps_val(const char *path, int val)
1316 if (glob(path, 0, NULL, &gl))
1319 snprintf(val_buf, sizeof(val_buf), "%x", val);
1320 for (i = 0; i < gl.gl_pathc; i++)
1321 system_set_sysctl(gl.gl_pathv[i], val_buf);
1327 system_if_apply_rps_xps(struct device *dev, struct device_settings *s)
1329 long n_cpus = sysconf(_SC_NPROCESSORS_ONLN);
1335 val = (1 << n_cpus) - 1;
1336 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/rps_cpus", dev->ifname);
1337 system_if_set_rps_xps_val(dev_buf, s->rps ? val : 0);
1339 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/xps_cpus", dev->ifname);
1340 system_if_set_rps_xps_val(dev_buf, s->xps ? val : 0);
1344 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
1349 memset(&ifr, 0, sizeof(ifr));
1350 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1351 if (s->flags & DEV_OPT_MTU & apply_mask) {
1352 ifr.ifr_mtu = s->mtu;
1353 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
1354 s->flags &= ~DEV_OPT_MTU;
1356 if (s->flags & DEV_OPT_MTU6 & apply_mask) {
1357 system_update_ipv6_mtu(dev, s->mtu6);
1359 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
1360 ifr.ifr_qlen = s->txqueuelen;
1361 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
1362 s->flags &= ~DEV_OPT_TXQUEUELEN;
1364 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
1365 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
1366 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
1367 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
1368 s->flags &= ~DEV_OPT_MACADDR;
1370 if (s->flags & DEV_OPT_IPV6 & apply_mask)
1371 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
1372 if (s->flags & DEV_OPT_PROMISC & apply_mask) {
1373 if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
1374 !s->promisc ? IFF_PROMISC : 0) < 0)
1375 s->flags &= ~DEV_OPT_PROMISC;
1377 if (s->flags & DEV_OPT_RPFILTER & apply_mask) {
1378 snprintf(buf, sizeof(buf), "%d", s->rpfilter);
1379 system_set_rpfilter(dev, buf);
1381 if (s->flags & DEV_OPT_ACCEPTLOCAL & apply_mask)
1382 system_set_acceptlocal(dev, s->acceptlocal ? "1" : "0");
1383 if (s->flags & DEV_OPT_IGMPVERSION & apply_mask) {
1384 snprintf(buf, sizeof(buf), "%d", s->igmpversion);
1385 system_set_igmpversion(dev, buf);
1387 if (s->flags & DEV_OPT_MLDVERSION & apply_mask) {
1388 snprintf(buf, sizeof(buf), "%d", s->mldversion);
1389 system_set_mldversion(dev, buf);
1391 if (s->flags & DEV_OPT_NEIGHREACHABLETIME & apply_mask) {
1392 snprintf(buf, sizeof(buf), "%d", s->neigh4reachabletime);
1393 system_set_neigh4reachabletime(dev, buf);
1394 snprintf(buf, sizeof(buf), "%d", s->neigh6reachabletime);
1395 system_set_neigh6reachabletime(dev, buf);
1397 if (s->flags & DEV_OPT_NEIGHGCSTALETIME & apply_mask) {
1398 snprintf(buf, sizeof(buf), "%d", s->neigh4gcstaletime);
1399 system_set_neigh4gcstaletime(dev, buf);
1400 snprintf(buf, sizeof(buf), "%d", s->neigh6gcstaletime);
1401 system_set_neigh6gcstaletime(dev, buf);
1403 if (s->flags & DEV_OPT_DADTRANSMITS & apply_mask) {
1404 snprintf(buf, sizeof(buf), "%d", s->dadtransmits);
1405 system_set_dadtransmits(dev, buf);
1407 if (s->flags & DEV_OPT_MULTICAST & apply_mask) {
1408 if (system_if_flags(dev->ifname, s->multicast ? IFF_MULTICAST : 0,
1409 !s->multicast ? IFF_MULTICAST : 0) < 0)
1410 s->flags &= ~DEV_OPT_MULTICAST;
1412 if (s->flags & DEV_OPT_SENDREDIRECTS & apply_mask)
1413 system_set_sendredirects(dev, s->sendredirects ? "1" : "0");
1415 system_if_apply_rps_xps(dev, s);
1418 int system_if_up(struct device *dev)
1420 system_if_get_settings(dev, &dev->orig_settings);
1421 /* Only keep orig settings based on what needs to be set */
1422 dev->orig_settings.valid_flags = dev->orig_settings.flags;
1423 dev->orig_settings.flags &= dev->settings.flags;
1424 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
1425 return system_if_flags(dev->ifname, IFF_UP, 0);
1428 int system_if_down(struct device *dev)
1430 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
1431 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
1435 struct if_check_data {
1441 #ifndef IFF_LOWER_UP
1442 #define IFF_LOWER_UP 0x10000
1445 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1447 struct nlmsghdr *nh = nlmsg_hdr(msg);
1448 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1449 struct if_check_data *chk = (struct if_check_data *)arg;
1451 if (nh->nlmsg_type != RTM_NEWLINK)
1454 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1455 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1460 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1462 struct if_check_data *chk = (struct if_check_data *)arg;
1467 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1469 struct if_check_data *chk = (struct if_check_data *)arg;
1471 device_set_present(chk->dev, false);
1472 device_set_link(chk->dev, false);
1473 chk->pending = err->error;
1478 int system_if_check(struct device *dev)
1480 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1482 struct ifinfomsg ifi = {
1483 .ifi_family = AF_UNSPEC,
1486 struct if_check_data chk = {
1492 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1496 if (nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1497 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1500 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1501 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1502 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1504 nl_send_auto_complete(sock_rtnl, msg);
1505 while (chk.pending > 0)
1506 nl_recvmsgs(sock_rtnl, cb);
1518 system_if_get_parent(struct device *dev)
1520 char buf[64], *devname;
1521 int ifindex, iflink, len;
1524 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1525 f = fopen(buf, "r");
1529 len = fread(buf, 1, sizeof(buf) - 1, f);
1536 iflink = strtoul(buf, NULL, 0);
1537 ifindex = system_if_resolve(dev);
1538 if (!iflink || iflink == ifindex)
1541 devname = if_indextoname(iflink, buf);
1545 return device_get(devname, true);
1549 read_string_file(int dir_fd, const char *file, char *buf, int len)
1555 fd = openat(dir_fd, file, O_RDONLY);
1560 len = read(fd, buf, len - 1);
1564 } else if (len > 0) {
1567 c = strchr(buf, '\n');
1580 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1585 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1587 *val = strtoull(buf, NULL, 0);
1592 /* Assume advertised flags == supported flags */
1593 static const struct {
1596 } ethtool_link_modes[] = {
1597 { ADVERTISED_10baseT_Half, "10H" },
1598 { ADVERTISED_10baseT_Full, "10F" },
1599 { ADVERTISED_100baseT_Half, "100H" },
1600 { ADVERTISED_100baseT_Full, "100F" },
1601 { ADVERTISED_1000baseT_Half, "1000H" },
1602 { ADVERTISED_1000baseT_Full, "1000F" },
1605 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1608 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1609 if (mask & ethtool_link_modes[i].mask)
1610 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1615 system_if_force_external(const char *ifname)
1620 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1621 return stat(buf, &s) == 0;
1625 system_if_dump_info(struct device *dev, struct blob_buf *b)
1627 struct ethtool_cmd ecmd;
1633 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
1634 dir_fd = open(buf, O_DIRECTORY);
1636 memset(&ecmd, 0, sizeof(ecmd));
1637 memset(&ifr, 0, sizeof(ifr));
1638 strcpy(ifr.ifr_name, dev->ifname);
1639 ifr.ifr_data = (caddr_t) &ecmd;
1640 ecmd.cmd = ETHTOOL_GSET;
1642 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1643 c = blobmsg_open_array(b, "link-advertising");
1644 system_add_link_modes(b, ecmd.advertising);
1645 blobmsg_close_array(b, c);
1647 c = blobmsg_open_array(b, "link-supported");
1648 system_add_link_modes(b, ecmd.supported);
1649 blobmsg_close_array(b, c);
1651 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1652 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1653 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1654 blobmsg_add_string_buffer(b);
1662 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1664 const char *const counters[] = {
1665 "collisions", "rx_frame_errors", "tx_compressed",
1666 "multicast", "rx_length_errors", "tx_dropped",
1667 "rx_bytes", "rx_missed_errors", "tx_errors",
1668 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1669 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1670 "rx_dropped", "tx_aborted_errors", "tx_packets",
1671 "rx_errors", "tx_bytes", "tx_window_errors",
1672 "rx_fifo_errors", "tx_carrier_errors",
1679 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1680 stats_dir = open(buf, O_DIRECTORY);
1684 for (i = 0; i < ARRAY_SIZE(counters); i++)
1685 if (read_uint64_file(stats_dir, counters[i], &val))
1686 blobmsg_add_u64(b, counters[i], val);
1692 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1694 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1695 int alen = v4 ? 4 : 16;
1696 unsigned int flags = 0;
1697 struct ifaddrmsg ifa = {
1698 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1699 .ifa_prefixlen = addr->mask,
1700 .ifa_index = dev->ifindex,
1704 if (cmd == RTM_NEWADDR)
1705 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1707 msg = nlmsg_alloc_simple(cmd, flags);
1711 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1712 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1714 if (addr->broadcast)
1715 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1716 if (addr->point_to_point)
1717 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1719 time_t now = system_get_rtime();
1720 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1722 if (addr->preferred_until) {
1723 int64_t preferred = addr->preferred_until - now;
1726 else if (preferred > UINT32_MAX)
1727 preferred = UINT32_MAX;
1729 cinfo.ifa_prefered = preferred;
1732 if (addr->valid_until) {
1733 int64_t valid = addr->valid_until - now;
1738 else if (valid > UINT32_MAX)
1741 cinfo.ifa_valid = valid;
1744 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1746 if (cmd == RTM_NEWADDR && (addr->flags & DEVADDR_OFFLINK))
1747 nla_put_u32(msg, IFA_FLAGS, IFA_F_NOPREFIXROUTE);
1750 return system_rtnl_call(msg);
1753 int system_add_address(struct device *dev, struct device_addr *addr)
1755 return system_addr(dev, addr, RTM_NEWADDR);
1758 int system_del_address(struct device *dev, struct device_addr *addr)
1760 return system_addr(dev, addr, RTM_DELADDR);
1763 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1765 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1767 unsigned int flags = 0;
1770 have_gw = !!route->nexthop.in.s_addr;
1772 have_gw = route->nexthop.in6.s6_addr32[0] ||
1773 route->nexthop.in6.s6_addr32[1] ||
1774 route->nexthop.in6.s6_addr32[2] ||
1775 route->nexthop.in6.s6_addr32[3];
1777 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1778 ? route->table : RT_TABLE_MAIN;
1780 struct rtmsg rtm = {
1781 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1782 .rtm_dst_len = route->mask,
1783 .rtm_src_len = route->sourcemask,
1784 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1785 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
1786 .rtm_scope = RT_SCOPE_NOWHERE,
1787 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1788 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1792 if (cmd == RTM_NEWROUTE) {
1793 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1795 if (!dev) { // Add null-route
1796 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1797 rtm.rtm_type = RTN_UNREACHABLE;
1800 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1803 if (route->flags & DEVROUTE_TYPE) {
1804 rtm.rtm_type = route->type;
1805 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
1806 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
1807 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
1808 rtm.rtm_table = RT_TABLE_LOCAL;
1811 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT) {
1812 rtm.rtm_scope = RT_SCOPE_HOST;
1813 } else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
1814 rtm.rtm_type == RTN_ANYCAST) {
1815 rtm.rtm_scope = RT_SCOPE_LINK;
1816 } else if (rtm.rtm_type == RTN_BLACKHOLE || rtm.rtm_type == RTN_UNREACHABLE ||
1817 rtm.rtm_type == RTN_PROHIBIT || rtm.rtm_type == RTN_FAILED_POLICY) {
1818 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1823 msg = nlmsg_alloc_simple(cmd, flags);
1827 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1830 nla_put(msg, RTA_DST, alen, &route->addr);
1832 if (route->sourcemask) {
1833 if (rtm.rtm_family == AF_INET)
1834 nla_put(msg, RTA_PREFSRC, alen, &route->source);
1836 nla_put(msg, RTA_SRC, alen, &route->source);
1839 if (route->metric > 0)
1840 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1843 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1846 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1849 nla_put_u32(msg, RTA_TABLE, table);
1851 if (route->flags & DEVROUTE_MTU) {
1852 struct nlattr *metrics;
1854 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1855 goto nla_put_failure;
1857 nla_put_u32(msg, RTAX_MTU, route->mtu);
1859 nla_nest_end(msg, metrics);
1862 return system_rtnl_call(msg);
1869 int system_add_route(struct device *dev, struct device_route *route)
1871 return system_rt(dev, route, RTM_NEWROUTE);
1874 int system_del_route(struct device *dev, struct device_route *route)
1876 return system_rt(dev, route, RTM_DELROUTE);
1879 int system_flush_routes(void)
1881 const char *names[] = {
1882 "/proc/sys/net/ipv4/route/flush",
1883 "/proc/sys/net/ipv6/route/flush"
1887 for (i = 0; i < ARRAY_SIZE(names); i++) {
1888 fd = open(names[i], O_WRONLY);
1892 if (write(fd, "-1", 2)) {}
1898 bool system_resolve_rt_type(const char *type, unsigned int *id)
1900 return system_rtn_aton(type, id);
1903 bool system_resolve_rt_table(const char *name, unsigned int *id)
1907 unsigned int n, table = RT_TABLE_UNSPEC;
1909 /* first try to parse table as number */
1910 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1913 /* handle well known aliases */
1914 else if (!strcmp(name, "default"))
1915 table = RT_TABLE_DEFAULT;
1916 else if (!strcmp(name, "main"))
1917 table = RT_TABLE_MAIN;
1918 else if (!strcmp(name, "local"))
1919 table = RT_TABLE_LOCAL;
1921 /* try to look up name in /etc/iproute2/rt_tables */
1922 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1924 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1926 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1929 n = strtoul(e, NULL, 10);
1930 e = strtok(NULL, " \t\n");
1932 if (e && !strcmp(e, name))
1942 if (table == RT_TABLE_UNSPEC)
1949 bool system_is_default_rt_table(unsigned int id)
1951 return (id == RT_TABLE_MAIN);
1954 bool system_resolve_rpfilter(const char *filter, unsigned int *id)
1959 if (!strcmp(filter, "strict"))
1961 else if (!strcmp(filter, "loose"))
1964 n = strtoul(filter, &e, 0);
1965 if (*e || e == filter || n > 2)
1973 static int system_iprule(struct iprule *rule, int cmd)
1975 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1978 struct rtmsg rtm = {
1979 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1980 .rtm_protocol = RTPROT_STATIC,
1981 .rtm_scope = RT_SCOPE_UNIVERSE,
1982 .rtm_table = RT_TABLE_UNSPEC,
1983 .rtm_type = RTN_UNSPEC,
1987 if (cmd == RTM_NEWRULE)
1988 rtm.rtm_type = RTN_UNICAST;
1991 rtm.rtm_flags |= FIB_RULE_INVERT;
1993 if (rule->flags & IPRULE_SRC)
1994 rtm.rtm_src_len = rule->src_mask;
1996 if (rule->flags & IPRULE_DEST)
1997 rtm.rtm_dst_len = rule->dest_mask;
1999 if (rule->flags & IPRULE_TOS)
2000 rtm.rtm_tos = rule->tos;
2002 if (rule->flags & IPRULE_LOOKUP) {
2003 if (rule->lookup < 256)
2004 rtm.rtm_table = rule->lookup;
2007 if (rule->flags & IPRULE_ACTION)
2008 rtm.rtm_type = rule->action;
2009 else if (rule->flags & IPRULE_GOTO)
2010 rtm.rtm_type = FR_ACT_GOTO;
2011 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
2012 rtm.rtm_type = FR_ACT_NOP;
2014 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
2019 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
2021 if (rule->flags & IPRULE_IN)
2022 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
2024 if (rule->flags & IPRULE_OUT)
2025 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
2027 if (rule->flags & IPRULE_SRC)
2028 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
2030 if (rule->flags & IPRULE_DEST)
2031 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
2033 if (rule->flags & IPRULE_PRIORITY)
2034 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
2035 else if (cmd == RTM_NEWRULE)
2036 nla_put_u32(msg, FRA_PRIORITY, rule->order);
2038 if (rule->flags & IPRULE_FWMARK)
2039 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
2041 if (rule->flags & IPRULE_FWMASK)
2042 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
2044 if (rule->flags & IPRULE_LOOKUP) {
2045 if (rule->lookup >= 256)
2046 nla_put_u32(msg, FRA_TABLE, rule->lookup);
2049 if (rule->flags & IPRULE_GOTO)
2050 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
2052 return system_rtnl_call(msg);
2055 int system_add_iprule(struct iprule *rule)
2057 return system_iprule(rule, RTM_NEWRULE);
2060 int system_del_iprule(struct iprule *rule)
2062 return system_iprule(rule, RTM_DELRULE);
2065 int system_flush_iprules(void)
2070 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
2071 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
2073 memset(&rule, 0, sizeof(rule));
2076 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2079 rule.lookup = RT_TABLE_LOCAL;
2080 rv |= system_iprule(&rule, RTM_NEWRULE);
2082 rule.priority = 32766;
2083 rule.lookup = RT_TABLE_MAIN;
2084 rv |= system_iprule(&rule, RTM_NEWRULE);
2086 rule.priority = 32767;
2087 rule.lookup = RT_TABLE_DEFAULT;
2088 rv |= system_iprule(&rule, RTM_NEWRULE);
2091 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2094 rule.lookup = RT_TABLE_LOCAL;
2095 rv |= system_iprule(&rule, RTM_NEWRULE);
2097 rule.priority = 32766;
2098 rule.lookup = RT_TABLE_MAIN;
2099 rv |= system_iprule(&rule, RTM_NEWRULE);
2104 bool system_resolve_iprule_action(const char *action, unsigned int *id)
2106 return system_rtn_aton(action, id);
2109 time_t system_get_rtime(void)
2114 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
2117 if (gettimeofday(&tv, NULL) == 0)
2124 #define IP_DF 0x4000
2127 static int tunnel_ioctl(const char *name, int cmd, void *p)
2131 memset(&ifr, 0, sizeof(ifr));
2132 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
2133 ifr.ifr_ifru.ifru_data = p;
2134 return ioctl(sock_ioctl, cmd, &ifr);
2137 #ifdef IFLA_IPTUN_MAX
2138 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
2139 static int system_add_gre_tunnel(const char *name, const char *kind,
2140 const unsigned int link, struct blob_attr **tb, bool v6)
2143 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2144 struct blob_attr *cur;
2145 uint32_t ikey = 0, okey = 0, flags = 0, flowinfo = 0;
2146 uint16_t iflags = 0, oflags = 0;
2148 int ret = 0, ttl = 0;
2150 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2154 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2155 nla_put_string(nlm, IFLA_IFNAME, name);
2157 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2163 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2164 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2171 nla_put_u32(nlm, IFLA_GRE_LINK, link);
2173 if ((cur = tb[TUNNEL_ATTR_TTL]))
2174 ttl = blobmsg_get_u32(cur);
2176 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2177 char *str = blobmsg_get_string(cur);
2178 if (strcmp(str, "inherit")) {
2181 if (!system_tos_aton(str, &uval)) {
2187 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
2192 flags |= IP6_TNL_F_USE_ORIG_TCLASS;
2198 if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) {
2199 uint8_t icsum, ocsum, iseqno, oseqno;
2200 if (sscanf(blobmsg_get_string(cur), "%u,%u,%hhu,%hhu,%hhu,%hhu",
2201 &ikey, &okey, &icsum, &ocsum, &iseqno, &oseqno) < 6) {
2226 struct in6_addr in6buf;
2227 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2228 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2232 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
2235 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2236 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2240 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
2242 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, 4);
2245 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
2248 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags);
2253 struct in_addr inbuf;
2256 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2257 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2261 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
2264 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2265 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2269 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
2271 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
2273 okey = inbuf.s_addr;
2278 ikey = inbuf.s_addr;
2284 if ((cur = tb[TUNNEL_ATTR_DF]))
2285 set_df = blobmsg_get_bool(cur);
2288 /* ttl != 0 and nopmtudisc are incompatible */
2296 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
2298 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
2302 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
2305 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
2308 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
2311 nla_put_u32(nlm, IFLA_GRE_OKEY, okey);
2314 nla_put_u32(nlm, IFLA_GRE_IKEY, ikey);
2316 nla_nest_end(nlm, infodata);
2317 nla_nest_end(nlm, linkinfo);
2319 return system_rtnl_call(nlm);
2328 static int system_add_vti_tunnel(const char *name, const char *kind,
2329 const unsigned int link, struct blob_attr **tb, bool v6)
2332 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2333 struct blob_attr *cur;
2334 uint32_t ikey = 0, okey = 0;
2337 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2341 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2342 nla_put_string(nlm, IFLA_IFNAME, name);
2344 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2350 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2351 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2358 nla_put_u32(nlm, IFLA_VTI_LINK, link);
2360 if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) {
2361 if (sscanf(blobmsg_get_string(cur), "%u,%u",
2362 &ikey, &okey) < 2) {
2369 struct in6_addr in6buf;
2370 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2371 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2375 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(in6buf), &in6buf);
2378 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2379 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2383 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(in6buf), &in6buf);
2387 struct in_addr inbuf;
2389 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2390 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2394 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(inbuf), &inbuf);
2397 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2398 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2402 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(inbuf), &inbuf);
2408 nla_put_u32(nlm, IFLA_VTI_OKEY, htonl(okey));
2411 nla_put_u32(nlm, IFLA_VTI_IKEY, htonl(ikey));
2413 nla_nest_end(nlm, infodata);
2414 nla_nest_end(nlm, linkinfo);
2416 return system_rtnl_call(nlm);
2424 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
2426 struct blob_attr *cur;
2428 struct ip_tunnel_parm p = {
2437 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
2438 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
2441 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
2442 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
2445 if ((cur = tb[TUNNEL_ATTR_DF]))
2446 set_df = blobmsg_get_bool(cur);
2448 if ((cur = tb[TUNNEL_ATTR_TTL]))
2449 p.iph.ttl = blobmsg_get_u32(cur);
2451 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2452 char *str = blobmsg_get_string(cur);
2453 if (strcmp(str, "inherit")) {
2456 if (!system_tos_aton(str, &uval))
2464 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
2465 /* ttl !=0 and nopmtudisc are incompatible */
2466 if (p.iph.ttl && p.iph.frag_off == 0)
2469 strncpy(p.name, name, sizeof(p.name));
2471 switch (p.iph.protocol) {
2473 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
2475 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
2482 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
2484 struct blob_attr *cur;
2487 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2489 str = blobmsg_data(cur);
2491 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
2492 !strcmp(str, "greip6") || !strcmp(str, "gretapip6") ||
2493 !strcmp(str, "vtiip") || !strcmp(str, "vtiip6"))
2494 return system_link_del(name);
2496 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
2499 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
2501 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2503 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2504 blob_data(attr), blob_len(attr));
2506 return __system_del_ip_tunnel(name, tb);
2509 int system_update_ipv6_mtu(struct device *dev, int mtu)
2515 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
2518 fd = open(buf, O_RDWR);
2523 ssize_t len = read(fd, buf, sizeof(buf) - 1);
2530 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) > 0)
2539 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
2541 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2542 struct blob_attr *cur;
2545 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2546 blob_data(attr), blob_len(attr));
2548 __system_del_ip_tunnel(name, tb);
2550 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2552 str = blobmsg_data(cur);
2554 unsigned int ttl = 0;
2555 if ((cur = tb[TUNNEL_ATTR_TTL])) {
2556 ttl = blobmsg_get_u32(cur);
2561 unsigned int link = 0;
2562 if ((cur = tb[TUNNEL_ATTR_LINK])) {
2563 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
2567 if (iface->l3_dev.dev)
2568 link = iface->l3_dev.dev->ifindex;
2571 if (!strcmp(str, "sit")) {
2572 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
2576 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
2578 struct ip_tunnel_6rd p6;
2580 memset(&p6, 0, sizeof(p6));
2582 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
2583 &p6.prefix, &mask) || mask > 128)
2585 p6.prefixlen = mask;
2587 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
2588 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
2589 &p6.relay_prefix, &mask) || mask > 32)
2591 p6.relay_prefixlen = mask;
2594 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
2595 __system_del_ip_tunnel(name, tb);
2600 #ifdef IFLA_IPTUN_MAX
2601 } else if (!strcmp(str, "ipip6")) {
2602 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2603 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2604 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2610 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2611 nla_put_string(nlm, IFLA_IFNAME, name);
2614 nla_put_u32(nlm, IFLA_LINK, link);
2616 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2621 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2622 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2629 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2631 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2632 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2633 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
2635 struct in6_addr in6buf;
2636 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2637 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2641 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2644 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2645 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2649 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2652 #ifdef IFLA_IPTUN_FMR_MAX
2653 if ((cur = tb[TUNNEL_ATTR_FMRS])) {
2654 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2656 struct blob_attr *fmr;
2657 unsigned rem, fmrcnt = 0;
2658 blobmsg_for_each_attr(fmr, cur, rem) {
2659 if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
2662 unsigned ip4len, ip6len, ealen, offset = 6;
2666 if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
2667 ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) {
2672 struct in6_addr ip6prefix;
2673 struct in_addr ip4prefix;
2674 if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
2675 inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) {
2680 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2682 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2683 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2684 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2685 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2686 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2687 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2689 nla_nest_end(nlm, rule);
2692 nla_nest_end(nlm, fmrs);
2696 nla_nest_end(nlm, infodata);
2697 nla_nest_end(nlm, linkinfo);
2699 return system_rtnl_call(nlm);
2703 } else if (!strcmp(str, "greip")) {
2704 return system_add_gre_tunnel(name, "gre", link, tb, false);
2705 } else if (!strcmp(str, "gretapip")) {
2706 return system_add_gre_tunnel(name, "gretap", link, tb, false);
2707 } else if (!strcmp(str, "greip6")) {
2708 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
2709 } else if (!strcmp(str, "gretapip6")) {
2710 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
2712 } else if (!strcmp(str, "vtiip")) {
2713 return system_add_vti_tunnel(name, "vti", link, tb, false);
2714 } else if (!strcmp(str, "vtiip6")) {
2715 return system_add_vti_tunnel(name, "vti6", link, tb, true);
2718 } else if (!strcmp(str, "ipip")) {
2719 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);