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_neigh4locktime(struct device *dev, const char *val)
321 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/locktime", dev->ifname, val);
324 static void system_set_dadtransmits(struct device *dev, const char *val)
326 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits", dev->ifname, val);
329 static void system_bridge_set_multicast_to_unicast(struct device *dev, const char *val)
331 system_set_dev_sysctl("/sys/class/net/%s/brport/multicast_to_unicast", dev->ifname, val);
334 static void system_bridge_set_multicast_fast_leave(struct device *dev, const char *val)
336 system_set_dev_sysctl("/sys/class/net/%s/brport/multicast_fast_leave", dev->ifname, val);
339 static void system_bridge_set_hairpin_mode(struct device *dev, const char *val)
341 system_set_dev_sysctl("/sys/class/net/%s/brport/hairpin_mode", dev->ifname, val);
344 static void system_bridge_set_multicast_router(struct device *dev, const char *val, bool bridge)
346 system_set_dev_sysctl(bridge ? "/sys/class/net/%s/bridge/multicast_router" :
347 "/sys/class/net/%s/brport/multicast_router",
351 static void system_bridge_set_robustness(struct device *dev, const char *val)
353 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_startup_query_count",
355 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_last_member_count",
359 static void system_bridge_set_query_interval(struct device *dev, const char *val)
361 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_query_interval",
365 static void system_bridge_set_query_response_interval(struct device *dev, const char *val)
367 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_query_response_interval",
371 static void system_bridge_set_last_member_interval(struct device *dev, const char *val)
373 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_last_member_interval",
377 static void system_bridge_set_membership_interval(struct device *dev, const char *val)
379 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_membership_interval",
383 static void system_bridge_set_other_querier_timeout(struct device *dev, const char *val)
385 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier_interval",
389 static void system_bridge_set_startup_query_interval(struct device *dev, const char *val)
391 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_startup_query_interval",
395 static void system_bridge_set_learning(struct device *dev, const char *val)
397 system_set_dev_sysctl("/sys/class/net/%s/brport/learning", dev->ifname, val);
400 static void system_bridge_set_unicast_flood(struct device *dev, const char *val)
402 system_set_dev_sysctl("/sys/class/net/%s/brport/unicast_flood", dev->ifname, val);
405 static void system_set_sendredirects(struct device *dev, const char *val)
407 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/send_redirects", dev->ifname, val);
410 static int system_get_sysctl(const char *path, char *buf, const size_t buf_sz)
412 int fd = -1, ret = -1;
414 fd = open(path, O_RDONLY);
418 ssize_t len = read(fd, buf, buf_sz - 1);
432 system_get_dev_sysctl(const char *path, const char *device, char *buf, const size_t buf_sz)
434 snprintf(dev_buf, sizeof(dev_buf), path, device);
435 return system_get_sysctl(dev_buf, buf, buf_sz);
438 static int system_get_disable_ipv6(struct device *dev, char *buf, const size_t buf_sz)
440 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6",
441 dev->ifname, buf, buf_sz);
444 static int system_get_rpfilter(struct device *dev, char *buf, const size_t buf_sz)
446 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter",
447 dev->ifname, buf, buf_sz);
450 static int system_get_acceptlocal(struct device *dev, char *buf, const size_t buf_sz)
452 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local",
453 dev->ifname, buf, buf_sz);
456 static int system_get_igmpversion(struct device *dev, char *buf, const size_t buf_sz)
458 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version",
459 dev->ifname, buf, buf_sz);
462 static int system_get_mldversion(struct device *dev, char *buf, const size_t buf_sz)
464 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version",
465 dev->ifname, buf, buf_sz);
468 static int system_get_neigh4reachabletime(struct device *dev, char *buf, const size_t buf_sz)
470 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms",
471 dev->ifname, buf, buf_sz);
474 static int system_get_neigh6reachabletime(struct device *dev, char *buf, const size_t buf_sz)
476 return system_get_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms",
477 dev->ifname, buf, buf_sz);
480 static int system_get_neigh4gcstaletime(struct device *dev, char *buf, const size_t buf_sz)
482 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/gc_stale_time",
483 dev->ifname, buf, buf_sz);
486 static int system_get_neigh6gcstaletime(struct device *dev, char *buf, const size_t buf_sz)
488 return system_get_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/gc_stale_time",
489 dev->ifname, buf, buf_sz);
492 static int system_get_neigh4locktime(struct device *dev, char *buf, const size_t buf_sz)
494 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/locktime",
495 dev->ifname, buf, buf_sz);
498 static int system_get_dadtransmits(struct device *dev, char *buf, const size_t buf_sz)
500 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits",
501 dev->ifname, buf, buf_sz);
504 static int system_get_sendredirects(struct device *dev, char *buf, const size_t buf_sz)
506 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/send_redirects",
507 dev->ifname, buf, buf_sz);
510 // Evaluate netlink messages
511 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
513 struct nlmsghdr *nh = nlmsg_hdr(msg);
514 struct nlattr *nla[__IFLA_MAX];
518 if (nh->nlmsg_type != RTM_NEWLINK)
521 nlmsg_parse(nh, sizeof(struct ifinfomsg), nla, __IFLA_MAX - 1, NULL);
522 if (!nla[IFLA_IFNAME])
525 struct device *dev = device_find(nla_data(nla[IFLA_IFNAME]));
529 if (!system_get_dev_sysctl("/sys/class/net/%s/carrier", dev->ifname, buf, sizeof(buf)))
530 link_state = strtoul(buf, NULL, 0);
532 device_set_link(dev, link_state ? true : false);
539 handle_hotplug_msg(char *data, int size)
541 const char *subsystem = NULL, *interface = NULL;
542 char *cur, *end, *sep;
547 if (!strncmp(data, "add@", 4))
549 else if (!strncmp(data, "remove@", 7))
554 skip = strlen(data) + 1;
557 for (cur = data + skip; cur < end; cur += skip) {
558 skip = strlen(cur) + 1;
560 sep = strchr(cur, '=');
565 if (!strcmp(cur, "INTERFACE"))
567 else if (!strcmp(cur, "SUBSYSTEM")) {
569 if (strcmp(subsystem, "net") != 0)
572 if (subsystem && interface)
578 dev = device_find(interface);
582 if (dev->type != &simple_device_type)
585 if (add && system_if_force_external(dev->ifname))
588 device_set_present(dev, add);
592 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
594 struct event_socket *ev = container_of(u, struct event_socket, uloop);
595 struct sockaddr_nl nla;
596 unsigned char *buf = NULL;
599 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
601 handle_hotplug_msg((char *) buf, size);
607 static int system_rtnl_call(struct nl_msg *msg)
611 ret = nl_send_auto_complete(sock_rtnl, msg);
617 return nl_wait_for_ack(sock_rtnl);
620 int system_bridge_delbr(struct device *bridge)
622 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
625 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
629 memset(&ifr, 0, sizeof(ifr));
631 ifr.ifr_ifindex = dev->ifindex;
634 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
635 return ioctl(sock_ioctl, cmd, &ifr);
638 static bool system_is_bridge(const char *name, char *buf, int buflen)
642 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
643 if (stat(buf, &st) < 0)
649 static char *system_get_bridge(const char *name, char *buf, int buflen)
655 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
656 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
660 len = readlink(gl.gl_pathv[0], buf, buflen);
668 path = strrchr(buf, '/');
676 system_bridge_set_wireless(struct device *bridge, struct device *dev)
678 bool mcast_to_ucast = dev->wireless_ap;
681 if (bridge->settings.flags & DEV_OPT_MULTICAST_TO_UNICAST &&
682 !bridge->settings.multicast_to_unicast)
683 mcast_to_ucast = false;
685 if (!mcast_to_ucast || dev->wireless_isolate)
688 system_bridge_set_multicast_to_unicast(dev, mcast_to_ucast ? "1" : "0");
689 system_bridge_set_hairpin_mode(dev, hairpin ? "1" : "0");
692 int system_bridge_addif(struct device *bridge, struct device *dev)
698 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
699 if (!oldbr || strcmp(oldbr, bridge->ifname) != 0)
700 ret = system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
703 system_bridge_set_wireless(bridge, dev);
705 if (dev->settings.flags & DEV_OPT_MULTICAST_ROUTER) {
706 snprintf(buf, sizeof(buf), "%i", dev->settings.multicast_router);
707 system_bridge_set_multicast_router(dev, buf, false);
710 if (dev->settings.flags & DEV_OPT_MULTICAST_FAST_LEAVE &&
711 dev->settings.multicast_fast_leave)
712 system_bridge_set_multicast_fast_leave(dev, "1");
714 if (dev->settings.flags & DEV_OPT_LEARNING &&
715 !dev->settings.learning)
716 system_bridge_set_learning(dev, "0");
718 if (dev->settings.flags & DEV_OPT_UNICAST_FLOOD &&
719 !dev->settings.unicast_flood)
720 system_bridge_set_unicast_flood(dev, "0");
725 int system_bridge_delif(struct device *bridge, struct device *dev)
727 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
730 int system_if_resolve(struct device *dev)
733 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
734 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
735 return ifr.ifr_ifindex;
740 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
744 memset(&ifr, 0, sizeof(ifr));
745 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
746 ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
747 ifr.ifr_flags |= add;
748 ifr.ifr_flags &= ~rem;
749 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
761 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
763 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
765 return ifa->ifa_index == ifindex;
768 static bool check_route(struct nlmsghdr *hdr, int ifindex)
770 struct rtmsg *r = NLMSG_DATA(hdr);
771 struct nlattr *tb[__RTA_MAX];
773 if (r->rtm_protocol == RTPROT_KERNEL &&
774 r->rtm_family == AF_INET6)
777 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
781 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
784 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
789 static int cb_clear_event(struct nl_msg *msg, void *arg)
791 struct clear_data *clr = arg;
792 struct nlmsghdr *hdr = nlmsg_hdr(msg);
793 bool (*cb)(struct nlmsghdr *, int ifindex);
799 if (hdr->nlmsg_type != RTM_NEWADDR)
806 if (hdr->nlmsg_type != RTM_NEWROUTE)
813 if (hdr->nlmsg_type != RTM_NEWRULE)
822 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
825 if (type == RTM_DELRULE)
826 D(SYSTEM, "Remove a rule\n");
828 D(SYSTEM, "Remove %s from device %s\n",
829 type == RTM_DELADDR ? "an address" : "a route",
831 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
832 hdr = nlmsg_hdr(clr->msg);
833 hdr->nlmsg_type = type;
834 hdr->nlmsg_flags = NLM_F_REQUEST;
836 nl_socket_disable_auto_ack(sock_rtnl);
837 nl_send_auto_complete(sock_rtnl, clr->msg);
838 nl_socket_enable_auto_ack(sock_rtnl);
844 cb_finish_event(struct nl_msg *msg, void *arg)
852 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
855 *pending = err->error;
860 system_if_clear_entries(struct device *dev, int type, int af)
862 struct clear_data clr;
863 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
866 .rtm_flags = RTM_F_CLONED,
868 int flags = NLM_F_DUMP;
877 clr.size = sizeof(struct rtgenmsg);
880 clr.size = sizeof(struct rtmsg);
889 clr.msg = nlmsg_alloc_simple(type, flags);
893 nlmsg_append(clr.msg, &rtm, clr.size, 0);
894 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
895 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
896 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
898 nl_send_auto_complete(sock_rtnl, clr.msg);
900 nl_recvmsgs(sock_rtnl, cb);
908 * Clear bridge (membership) state and bring down device
910 void system_if_clear_state(struct device *dev)
912 static char buf[256];
915 device_set_ifindex(dev, system_if_resolve(dev));
916 if (dev->external || !dev->ifindex)
919 system_if_flags(dev->ifname, 0, IFF_UP);
921 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
922 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
923 system_bridge_delbr(dev);
927 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
929 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
930 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
933 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
934 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
935 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
936 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
937 system_set_disable_ipv6(dev, "0");
940 static inline unsigned long
941 sec_to_jiffies(int val)
943 return (unsigned long) val * 100;
946 static void system_bridge_conf_multicast_deps(struct device *bridge,
947 struct bridge_config *cfg,
953 if (cfg->flags & BRIDGE_OPT_ROBUSTNESS ||
954 cfg->flags & BRIDGE_OPT_QUERY_INTERVAL ||
955 cfg->flags & BRIDGE_OPT_QUERY_RESPONSE_INTERVAL) {
956 val = cfg->robustness * cfg->query_interval +
957 cfg->query_response_interval;
959 snprintf(buf, buf_len, "%i", val);
960 system_bridge_set_membership_interval(bridge, buf);
962 val = cfg->robustness * cfg->query_interval +
963 cfg->query_response_interval / 2;
965 snprintf(buf, buf_len, "%i", val);
966 system_bridge_set_other_querier_timeout(bridge, buf);
969 if (cfg->flags & BRIDGE_OPT_QUERY_INTERVAL) {
970 val = cfg->query_interval / 4;
972 snprintf(buf, buf_len, "%i", val);
973 system_bridge_set_startup_query_interval(bridge, buf);
977 static void system_bridge_conf_multicast(struct device *bridge,
978 struct bridge_config *cfg,
982 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
983 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
985 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier",
986 bridge->ifname, cfg->multicast_querier ? "1" : "0");
988 snprintf(buf, buf_len, "%i", cfg->hash_max);
989 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/hash_max",
990 bridge->ifname, buf);
992 if (bridge->settings.flags & DEV_OPT_MULTICAST_ROUTER) {
993 snprintf(buf, buf_len, "%i", bridge->settings.multicast_router);
994 system_bridge_set_multicast_router(bridge, buf, true);
997 if (cfg->flags & BRIDGE_OPT_ROBUSTNESS) {
998 snprintf(buf, buf_len, "%i", cfg->robustness);
999 system_bridge_set_robustness(bridge, buf);
1002 if (cfg->flags & BRIDGE_OPT_QUERY_INTERVAL) {
1003 snprintf(buf, buf_len, "%i", cfg->query_interval);
1004 system_bridge_set_query_interval(bridge, buf);
1007 if (cfg->flags & BRIDGE_OPT_QUERY_RESPONSE_INTERVAL) {
1008 snprintf(buf, buf_len, "%i", cfg->query_response_interval);
1009 system_bridge_set_query_response_interval(bridge, buf);
1012 if (cfg->flags & BRIDGE_OPT_LAST_MEMBER_INTERVAL) {
1013 snprintf(buf, buf_len, "%i", cfg->last_member_interval);
1014 system_bridge_set_last_member_interval(bridge, buf);
1017 system_bridge_conf_multicast_deps(bridge, cfg, buf, buf_len);
1020 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
1023 unsigned long args[4] = {};
1025 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
1028 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
1029 args[1] = !!cfg->stp;
1030 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1032 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
1033 args[1] = sec_to_jiffies(cfg->forward_delay);
1034 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1036 system_bridge_conf_multicast(bridge, cfg, buf, sizeof(buf));
1038 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
1039 args[1] = cfg->priority;
1040 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1042 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
1043 args[0] = BRCTL_SET_AGEING_TIME;
1044 args[1] = sec_to_jiffies(cfg->ageing_time);
1045 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1048 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
1049 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
1050 args[1] = sec_to_jiffies(cfg->hello_time);
1051 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1054 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
1055 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
1056 args[1] = sec_to_jiffies(cfg->max_age);
1057 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1063 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
1066 struct nlattr *linkinfo, *data;
1067 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
1069 static const struct {
1071 enum macvlan_mode val;
1073 { "private", MACVLAN_MODE_PRIVATE },
1074 { "vepa", MACVLAN_MODE_VEPA },
1075 { "bridge", MACVLAN_MODE_BRIDGE },
1076 { "passthru", MACVLAN_MODE_PASSTHRU },
1079 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1084 nlmsg_append(msg, &iim, sizeof(iim), 0);
1086 if (cfg->flags & MACVLAN_OPT_MACADDR)
1087 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
1088 nla_put_string(msg, IFLA_IFNAME, macvlan->ifname);
1089 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
1091 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1092 goto nla_put_failure;
1094 nla_put_string(msg, IFLA_INFO_KIND, "macvlan");
1096 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1097 goto nla_put_failure;
1100 for (i = 0; i < ARRAY_SIZE(modes); i++) {
1101 if (strcmp(cfg->mode, modes[i].name) != 0)
1104 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
1109 nla_nest_end(msg, data);
1110 nla_nest_end(msg, linkinfo);
1112 rv = system_rtnl_call(msg);
1114 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
1123 static int system_link_del(const char *ifname)
1126 struct ifinfomsg iim = {
1127 .ifi_family = AF_UNSPEC,
1131 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
1136 nlmsg_append(msg, &iim, sizeof(iim), 0);
1137 nla_put_string(msg, IFLA_IFNAME, ifname);
1138 return system_rtnl_call(msg);
1141 int system_macvlan_del(struct device *macvlan)
1143 return system_link_del(macvlan->ifname);
1146 int system_veth_add(struct device *veth, struct veth_config *cfg)
1149 struct ifinfomsg empty_iim = {};
1150 struct nlattr *linkinfo, *data, *veth_info;
1153 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1158 nlmsg_append(msg, &empty_iim, sizeof(empty_iim), 0);
1160 if (cfg->flags & VETH_OPT_MACADDR)
1161 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
1162 nla_put_string(msg, IFLA_IFNAME, veth->ifname);
1164 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1165 goto nla_put_failure;
1167 nla_put_string(msg, IFLA_INFO_KIND, "veth");
1169 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1170 goto nla_put_failure;
1172 if (!(veth_info = nla_nest_start(msg, VETH_INFO_PEER)))
1173 goto nla_put_failure;
1175 nlmsg_append(msg, &empty_iim, sizeof(empty_iim), 0);
1177 if (cfg->flags & VETH_OPT_PEER_NAME)
1178 nla_put_string(msg, IFLA_IFNAME, cfg->peer_name);
1179 if (cfg->flags & VETH_OPT_PEER_MACADDR)
1180 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->peer_macaddr), cfg->peer_macaddr);
1182 nla_nest_end(msg, veth_info);
1183 nla_nest_end(msg, data);
1184 nla_nest_end(msg, linkinfo);
1186 rv = system_rtnl_call(msg);
1188 if (cfg->flags & VETH_OPT_PEER_NAME)
1189 D(SYSTEM, "Error adding veth '%s' with peer '%s': %d\n", veth->ifname, cfg->peer_name, rv);
1191 D(SYSTEM, "Error adding veth '%s': %d\n", veth->ifname, rv);
1201 int system_veth_del(struct device *veth)
1203 return system_link_del(veth->ifname);
1206 static int system_vlan(struct device *dev, int id)
1208 struct vlan_ioctl_args ifr = {
1209 .cmd = SET_VLAN_NAME_TYPE_CMD,
1210 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
1213 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
1216 ifr.cmd = DEL_VLAN_CMD;
1219 ifr.cmd = ADD_VLAN_CMD;
1222 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
1223 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
1226 int system_vlan_add(struct device *dev, int id)
1228 return system_vlan(dev, id);
1231 int system_vlan_del(struct device *dev)
1233 return system_vlan(dev, -1);
1236 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
1239 struct nlattr *linkinfo, *data;
1240 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
1243 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1248 nlmsg_append(msg, &iim, sizeof(iim), 0);
1249 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
1250 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
1252 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1253 goto nla_put_failure;
1255 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
1257 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1258 goto nla_put_failure;
1260 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
1262 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
1263 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
1265 if(cfg->proto == VLAN_PROTO_8021AD)
1266 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);
1269 nla_nest_end(msg, data);
1270 nla_nest_end(msg, linkinfo);
1272 rv = system_rtnl_call(msg);
1274 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
1283 int system_vlandev_del(struct device *vlandev)
1285 return system_link_del(vlandev->ifname);
1289 system_if_get_settings(struct device *dev, struct device_settings *s)
1294 memset(&ifr, 0, sizeof(ifr));
1295 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1297 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
1298 s->mtu = ifr.ifr_mtu;
1299 s->flags |= DEV_OPT_MTU;
1302 s->mtu6 = system_update_ipv6_mtu(dev, 0);
1304 s->flags |= DEV_OPT_MTU6;
1306 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
1307 s->txqueuelen = ifr.ifr_qlen;
1308 s->flags |= DEV_OPT_TXQUEUELEN;
1311 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
1312 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
1313 s->flags |= DEV_OPT_MACADDR;
1316 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
1317 s->ipv6 = !strtoul(buf, NULL, 0);
1318 s->flags |= DEV_OPT_IPV6;
1321 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
1322 s->promisc = ifr.ifr_flags & IFF_PROMISC;
1323 s->flags |= DEV_OPT_PROMISC;
1325 s->multicast = ifr.ifr_flags & IFF_MULTICAST;
1326 s->flags |= DEV_OPT_MULTICAST;
1329 if (!system_get_rpfilter(dev, buf, sizeof(buf))) {
1330 s->rpfilter = strtoul(buf, NULL, 0);
1331 s->flags |= DEV_OPT_RPFILTER;
1334 if (!system_get_acceptlocal(dev, buf, sizeof(buf))) {
1335 s->acceptlocal = strtoul(buf, NULL, 0);
1336 s->flags |= DEV_OPT_ACCEPTLOCAL;
1339 if (!system_get_igmpversion(dev, buf, sizeof(buf))) {
1340 s->igmpversion = strtoul(buf, NULL, 0);
1341 s->flags |= DEV_OPT_IGMPVERSION;
1344 if (!system_get_mldversion(dev, buf, sizeof(buf))) {
1345 s->mldversion = strtoul(buf, NULL, 0);
1346 s->flags |= DEV_OPT_MLDVERSION;
1349 if (!system_get_neigh4reachabletime(dev, buf, sizeof(buf))) {
1350 s->neigh4reachabletime = strtoul(buf, NULL, 0);
1351 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1354 if (!system_get_neigh6reachabletime(dev, buf, sizeof(buf))) {
1355 s->neigh6reachabletime = strtoul(buf, NULL, 0);
1356 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1359 if (!system_get_neigh4locktime(dev, buf, sizeof(buf))) {
1360 s->neigh4locktime = strtoul(buf, NULL, 0);
1361 s->flags |= DEV_OPT_NEIGHLOCKTIME;
1364 if (!system_get_neigh4gcstaletime(dev, buf, sizeof(buf))) {
1365 s->neigh4gcstaletime = strtoul(buf, NULL, 0);
1366 s->flags |= DEV_OPT_NEIGHGCSTALETIME;
1369 if (!system_get_neigh6gcstaletime(dev, buf, sizeof(buf))) {
1370 s->neigh6gcstaletime = strtoul(buf, NULL, 0);
1371 s->flags |= DEV_OPT_NEIGHGCSTALETIME;
1374 if (!system_get_dadtransmits(dev, buf, sizeof(buf))) {
1375 s->dadtransmits = strtoul(buf, NULL, 0);
1376 s->flags |= DEV_OPT_DADTRANSMITS;
1379 if (!system_get_sendredirects(dev, buf, sizeof(buf))) {
1380 s->sendredirects = strtoul(buf, NULL, 0);
1381 s->flags |= DEV_OPT_SENDREDIRECTS;
1386 system_if_set_rps_xps_val(const char *path, int val)
1392 if (glob(path, 0, NULL, &gl))
1395 snprintf(val_buf, sizeof(val_buf), "%x", val);
1396 for (i = 0; i < gl.gl_pathc; i++)
1397 system_set_sysctl(gl.gl_pathv[i], val_buf);
1403 system_if_apply_rps_xps(struct device *dev, struct device_settings *s)
1405 long n_cpus = sysconf(_SC_NPROCESSORS_ONLN);
1411 val = (1 << n_cpus) - 1;
1412 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/rps_cpus", dev->ifname);
1413 system_if_set_rps_xps_val(dev_buf, s->rps ? val : 0);
1415 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/xps_cpus", dev->ifname);
1416 system_if_set_rps_xps_val(dev_buf, s->xps ? val : 0);
1420 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
1425 memset(&ifr, 0, sizeof(ifr));
1426 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1427 if (s->flags & DEV_OPT_MTU & apply_mask) {
1428 ifr.ifr_mtu = s->mtu;
1429 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
1430 s->flags &= ~DEV_OPT_MTU;
1432 if (s->flags & DEV_OPT_MTU6 & apply_mask) {
1433 system_update_ipv6_mtu(dev, s->mtu6);
1435 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
1436 ifr.ifr_qlen = s->txqueuelen;
1437 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
1438 s->flags &= ~DEV_OPT_TXQUEUELEN;
1440 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
1441 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
1442 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
1443 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
1444 s->flags &= ~DEV_OPT_MACADDR;
1446 if (s->flags & DEV_OPT_IPV6 & apply_mask)
1447 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
1448 if (s->flags & DEV_OPT_PROMISC & apply_mask) {
1449 if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
1450 !s->promisc ? IFF_PROMISC : 0) < 0)
1451 s->flags &= ~DEV_OPT_PROMISC;
1453 if (s->flags & DEV_OPT_RPFILTER & apply_mask) {
1454 snprintf(buf, sizeof(buf), "%d", s->rpfilter);
1455 system_set_rpfilter(dev, buf);
1457 if (s->flags & DEV_OPT_ACCEPTLOCAL & apply_mask)
1458 system_set_acceptlocal(dev, s->acceptlocal ? "1" : "0");
1459 if (s->flags & DEV_OPT_IGMPVERSION & apply_mask) {
1460 snprintf(buf, sizeof(buf), "%d", s->igmpversion);
1461 system_set_igmpversion(dev, buf);
1463 if (s->flags & DEV_OPT_MLDVERSION & apply_mask) {
1464 snprintf(buf, sizeof(buf), "%d", s->mldversion);
1465 system_set_mldversion(dev, buf);
1467 if (s->flags & DEV_OPT_NEIGHREACHABLETIME & apply_mask) {
1468 snprintf(buf, sizeof(buf), "%d", s->neigh4reachabletime);
1469 system_set_neigh4reachabletime(dev, buf);
1470 snprintf(buf, sizeof(buf), "%d", s->neigh6reachabletime);
1471 system_set_neigh6reachabletime(dev, buf);
1473 if (s->flags & DEV_OPT_NEIGHLOCKTIME & apply_mask) {
1474 snprintf(buf, sizeof(buf), "%d", s->neigh4locktime);
1475 system_set_neigh4locktime(dev, buf);
1477 if (s->flags & DEV_OPT_NEIGHGCSTALETIME & apply_mask) {
1478 snprintf(buf, sizeof(buf), "%d", s->neigh4gcstaletime);
1479 system_set_neigh4gcstaletime(dev, buf);
1480 snprintf(buf, sizeof(buf), "%d", s->neigh6gcstaletime);
1481 system_set_neigh6gcstaletime(dev, buf);
1483 if (s->flags & DEV_OPT_DADTRANSMITS & apply_mask) {
1484 snprintf(buf, sizeof(buf), "%d", s->dadtransmits);
1485 system_set_dadtransmits(dev, buf);
1487 if (s->flags & DEV_OPT_MULTICAST & apply_mask) {
1488 if (system_if_flags(dev->ifname, s->multicast ? IFF_MULTICAST : 0,
1489 !s->multicast ? IFF_MULTICAST : 0) < 0)
1490 s->flags &= ~DEV_OPT_MULTICAST;
1492 if (s->flags & DEV_OPT_SENDREDIRECTS & apply_mask)
1493 system_set_sendredirects(dev, s->sendredirects ? "1" : "0");
1495 system_if_apply_rps_xps(dev, s);
1498 int system_if_up(struct device *dev)
1500 system_if_get_settings(dev, &dev->orig_settings);
1501 /* Only keep orig settings based on what needs to be set */
1502 dev->orig_settings.valid_flags = dev->orig_settings.flags;
1503 dev->orig_settings.flags &= dev->settings.flags;
1504 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
1505 return system_if_flags(dev->ifname, IFF_UP, 0);
1508 int system_if_down(struct device *dev)
1510 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
1511 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
1515 struct if_check_data {
1521 #ifndef IFF_LOWER_UP
1522 #define IFF_LOWER_UP 0x10000
1525 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1527 struct nlmsghdr *nh = nlmsg_hdr(msg);
1528 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1529 struct if_check_data *chk = (struct if_check_data *)arg;
1531 if (nh->nlmsg_type != RTM_NEWLINK)
1534 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1535 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1540 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1542 struct if_check_data *chk = (struct if_check_data *)arg;
1547 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1549 struct if_check_data *chk = (struct if_check_data *)arg;
1551 device_set_present(chk->dev, false);
1552 device_set_link(chk->dev, false);
1553 chk->pending = err->error;
1558 int system_if_check(struct device *dev)
1560 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1562 struct ifinfomsg ifi = {
1563 .ifi_family = AF_UNSPEC,
1566 struct if_check_data chk = {
1572 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1576 if (nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1577 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1580 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1581 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1582 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1584 nl_send_auto_complete(sock_rtnl, msg);
1585 while (chk.pending > 0)
1586 nl_recvmsgs(sock_rtnl, cb);
1598 system_if_get_parent(struct device *dev)
1600 char buf[64], *devname;
1601 int ifindex, iflink, len;
1604 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1605 f = fopen(buf, "r");
1609 len = fread(buf, 1, sizeof(buf) - 1, f);
1616 iflink = strtoul(buf, NULL, 0);
1617 ifindex = system_if_resolve(dev);
1618 if (!iflink || iflink == ifindex)
1621 devname = if_indextoname(iflink, buf);
1625 return device_get(devname, true);
1629 read_string_file(int dir_fd, const char *file, char *buf, int len)
1635 fd = openat(dir_fd, file, O_RDONLY);
1640 len = read(fd, buf, len - 1);
1644 } else if (len > 0) {
1647 c = strchr(buf, '\n');
1660 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1665 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1667 *val = strtoull(buf, NULL, 0);
1672 /* Assume advertised flags == supported flags */
1673 static const struct {
1676 } ethtool_link_modes[] = {
1677 { ADVERTISED_10baseT_Half, "10H" },
1678 { ADVERTISED_10baseT_Full, "10F" },
1679 { ADVERTISED_100baseT_Half, "100H" },
1680 { ADVERTISED_100baseT_Full, "100F" },
1681 { ADVERTISED_1000baseT_Half, "1000H" },
1682 { ADVERTISED_1000baseT_Full, "1000F" },
1685 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1688 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1689 if (mask & ethtool_link_modes[i].mask)
1690 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1695 system_if_force_external(const char *ifname)
1700 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1701 return stat(buf, &s) == 0;
1705 system_if_dump_info(struct device *dev, struct blob_buf *b)
1707 struct ethtool_cmd ecmd;
1713 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
1714 dir_fd = open(buf, O_DIRECTORY);
1716 memset(&ecmd, 0, sizeof(ecmd));
1717 memset(&ifr, 0, sizeof(ifr));
1718 strcpy(ifr.ifr_name, dev->ifname);
1719 ifr.ifr_data = (caddr_t) &ecmd;
1720 ecmd.cmd = ETHTOOL_GSET;
1722 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1723 c = blobmsg_open_array(b, "link-advertising");
1724 system_add_link_modes(b, ecmd.advertising);
1725 blobmsg_close_array(b, c);
1727 c = blobmsg_open_array(b, "link-supported");
1728 system_add_link_modes(b, ecmd.supported);
1729 blobmsg_close_array(b, c);
1731 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1732 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1733 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1734 blobmsg_add_string_buffer(b);
1742 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1744 const char *const counters[] = {
1745 "collisions", "rx_frame_errors", "tx_compressed",
1746 "multicast", "rx_length_errors", "tx_dropped",
1747 "rx_bytes", "rx_missed_errors", "tx_errors",
1748 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1749 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1750 "rx_dropped", "tx_aborted_errors", "tx_packets",
1751 "rx_errors", "tx_bytes", "tx_window_errors",
1752 "rx_fifo_errors", "tx_carrier_errors",
1759 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1760 stats_dir = open(buf, O_DIRECTORY);
1764 for (i = 0; i < ARRAY_SIZE(counters); i++)
1765 if (read_uint64_file(stats_dir, counters[i], &val))
1766 blobmsg_add_u64(b, counters[i], val);
1772 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1774 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1775 int alen = v4 ? 4 : 16;
1776 unsigned int flags = 0;
1777 struct ifaddrmsg ifa = {
1778 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1779 .ifa_prefixlen = addr->mask,
1780 .ifa_index = dev->ifindex,
1784 if (cmd == RTM_NEWADDR)
1785 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1787 msg = nlmsg_alloc_simple(cmd, flags);
1791 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1792 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1794 if (addr->broadcast)
1795 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1796 if (addr->point_to_point)
1797 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1799 time_t now = system_get_rtime();
1800 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1802 if (addr->preferred_until) {
1803 int64_t preferred = addr->preferred_until - now;
1806 else if (preferred > UINT32_MAX)
1807 preferred = UINT32_MAX;
1809 cinfo.ifa_prefered = preferred;
1812 if (addr->valid_until) {
1813 int64_t valid = addr->valid_until - now;
1818 else if (valid > UINT32_MAX)
1821 cinfo.ifa_valid = valid;
1824 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1826 if (cmd == RTM_NEWADDR && (addr->flags & DEVADDR_OFFLINK))
1827 nla_put_u32(msg, IFA_FLAGS, IFA_F_NOPREFIXROUTE);
1830 return system_rtnl_call(msg);
1833 int system_add_address(struct device *dev, struct device_addr *addr)
1835 return system_addr(dev, addr, RTM_NEWADDR);
1838 int system_del_address(struct device *dev, struct device_addr *addr)
1840 return system_addr(dev, addr, RTM_DELADDR);
1843 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1845 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1847 unsigned int flags = 0;
1850 have_gw = !!route->nexthop.in.s_addr;
1852 have_gw = route->nexthop.in6.s6_addr32[0] ||
1853 route->nexthop.in6.s6_addr32[1] ||
1854 route->nexthop.in6.s6_addr32[2] ||
1855 route->nexthop.in6.s6_addr32[3];
1857 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1858 ? route->table : RT_TABLE_MAIN;
1860 struct rtmsg rtm = {
1861 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1862 .rtm_dst_len = route->mask,
1863 .rtm_src_len = route->sourcemask,
1864 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1865 .rtm_protocol = (route->flags & DEVROUTE_PROTO) ? route->proto : RTPROT_STATIC,
1866 .rtm_scope = RT_SCOPE_NOWHERE,
1867 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1868 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1872 if (cmd == RTM_NEWROUTE) {
1873 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1875 if (!dev) { // Add null-route
1876 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1877 rtm.rtm_type = RTN_UNREACHABLE;
1880 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1883 if (route->flags & DEVROUTE_TYPE) {
1884 rtm.rtm_type = route->type;
1885 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
1886 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
1887 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
1888 rtm.rtm_table = RT_TABLE_LOCAL;
1891 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT) {
1892 rtm.rtm_scope = RT_SCOPE_HOST;
1893 } else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
1894 rtm.rtm_type == RTN_ANYCAST) {
1895 rtm.rtm_scope = RT_SCOPE_LINK;
1896 } else if (rtm.rtm_type == RTN_BLACKHOLE || rtm.rtm_type == RTN_UNREACHABLE ||
1897 rtm.rtm_type == RTN_PROHIBIT || rtm.rtm_type == RTN_FAILED_POLICY) {
1898 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1903 msg = nlmsg_alloc_simple(cmd, flags);
1907 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1910 nla_put(msg, RTA_DST, alen, &route->addr);
1912 if (route->sourcemask) {
1913 if (rtm.rtm_family == AF_INET)
1914 nla_put(msg, RTA_PREFSRC, alen, &route->source);
1916 nla_put(msg, RTA_SRC, alen, &route->source);
1919 if (route->metric > 0)
1920 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1923 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1926 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1929 nla_put_u32(msg, RTA_TABLE, table);
1931 if (route->flags & DEVROUTE_MTU) {
1932 struct nlattr *metrics;
1934 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1935 goto nla_put_failure;
1937 nla_put_u32(msg, RTAX_MTU, route->mtu);
1939 nla_nest_end(msg, metrics);
1942 return system_rtnl_call(msg);
1949 int system_add_route(struct device *dev, struct device_route *route)
1951 return system_rt(dev, route, RTM_NEWROUTE);
1954 int system_del_route(struct device *dev, struct device_route *route)
1956 return system_rt(dev, route, RTM_DELROUTE);
1959 int system_flush_routes(void)
1961 const char *names[] = {
1962 "/proc/sys/net/ipv4/route/flush",
1963 "/proc/sys/net/ipv6/route/flush"
1967 for (i = 0; i < ARRAY_SIZE(names); i++) {
1968 fd = open(names[i], O_WRONLY);
1972 if (write(fd, "-1", 2)) {}
1978 bool system_resolve_rt_type(const char *type, unsigned int *id)
1980 return system_rtn_aton(type, id);
1983 bool system_resolve_rt_proto(const char *type, unsigned int *id)
1987 unsigned int n, proto = 256;
1989 if ((n = strtoul(type, &e, 0)) >= 0 && !*e && e != type)
1991 else if (!strcmp(type, "unspec"))
1992 proto = RTPROT_UNSPEC;
1993 else if (!strcmp(type, "kernel"))
1994 proto = RTPROT_KERNEL;
1995 else if (!strcmp(type, "boot"))
1996 proto = RTPROT_BOOT;
1997 else if (!strcmp(type, "static"))
1998 proto = RTPROT_STATIC;
1999 else if ((f = fopen("/etc/iproute2/rt_protos", "r")) != NULL) {
2000 while (fgets(buf, sizeof(buf) - 1, f) != NULL) {
2001 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
2004 n = strtoul(e, NULL, 10);
2005 e = strtok(NULL, " \t\n");
2007 if (e && !strcmp(e, type)) {
2022 bool system_resolve_rt_table(const char *name, unsigned int *id)
2026 unsigned int n, table = RT_TABLE_UNSPEC;
2028 /* first try to parse table as number */
2029 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
2032 /* handle well known aliases */
2033 else if (!strcmp(name, "default"))
2034 table = RT_TABLE_DEFAULT;
2035 else if (!strcmp(name, "main"))
2036 table = RT_TABLE_MAIN;
2037 else if (!strcmp(name, "local"))
2038 table = RT_TABLE_LOCAL;
2040 /* try to look up name in /etc/iproute2/rt_tables */
2041 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
2043 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
2045 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
2048 n = strtoul(e, NULL, 10);
2049 e = strtok(NULL, " \t\n");
2051 if (e && !strcmp(e, name))
2061 if (table == RT_TABLE_UNSPEC)
2068 bool system_is_default_rt_table(unsigned int id)
2070 return (id == RT_TABLE_MAIN);
2073 bool system_resolve_rpfilter(const char *filter, unsigned int *id)
2078 if (!strcmp(filter, "strict"))
2080 else if (!strcmp(filter, "loose"))
2083 n = strtoul(filter, &e, 0);
2084 if (*e || e == filter || n > 2)
2092 static int system_iprule(struct iprule *rule, int cmd)
2094 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
2097 struct rtmsg rtm = {
2098 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
2099 .rtm_protocol = RTPROT_STATIC,
2100 .rtm_scope = RT_SCOPE_UNIVERSE,
2101 .rtm_table = RT_TABLE_UNSPEC,
2102 .rtm_type = RTN_UNSPEC,
2106 if (cmd == RTM_NEWRULE)
2107 rtm.rtm_type = RTN_UNICAST;
2110 rtm.rtm_flags |= FIB_RULE_INVERT;
2112 if (rule->flags & IPRULE_SRC)
2113 rtm.rtm_src_len = rule->src_mask;
2115 if (rule->flags & IPRULE_DEST)
2116 rtm.rtm_dst_len = rule->dest_mask;
2118 if (rule->flags & IPRULE_TOS)
2119 rtm.rtm_tos = rule->tos;
2121 if (rule->flags & IPRULE_LOOKUP) {
2122 if (rule->lookup < 256)
2123 rtm.rtm_table = rule->lookup;
2126 if (rule->flags & IPRULE_ACTION)
2127 rtm.rtm_type = rule->action;
2128 else if (rule->flags & IPRULE_GOTO)
2129 rtm.rtm_type = FR_ACT_GOTO;
2130 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
2131 rtm.rtm_type = FR_ACT_NOP;
2133 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
2138 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
2140 if (rule->flags & IPRULE_IN)
2141 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
2143 if (rule->flags & IPRULE_OUT)
2144 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
2146 if (rule->flags & IPRULE_SRC)
2147 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
2149 if (rule->flags & IPRULE_DEST)
2150 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
2152 if (rule->flags & IPRULE_PRIORITY)
2153 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
2154 else if (cmd == RTM_NEWRULE)
2155 nla_put_u32(msg, FRA_PRIORITY, rule->order);
2157 if (rule->flags & IPRULE_FWMARK)
2158 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
2160 if (rule->flags & IPRULE_FWMASK)
2161 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
2163 if (rule->flags & IPRULE_LOOKUP) {
2164 if (rule->lookup >= 256)
2165 nla_put_u32(msg, FRA_TABLE, rule->lookup);
2168 if (rule->flags & IPRULE_GOTO)
2169 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
2171 return system_rtnl_call(msg);
2174 int system_add_iprule(struct iprule *rule)
2176 return system_iprule(rule, RTM_NEWRULE);
2179 int system_del_iprule(struct iprule *rule)
2181 return system_iprule(rule, RTM_DELRULE);
2184 int system_flush_iprules(void)
2189 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
2190 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
2192 memset(&rule, 0, sizeof(rule));
2195 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2198 rule.lookup = RT_TABLE_LOCAL;
2199 rv |= system_iprule(&rule, RTM_NEWRULE);
2201 rule.priority = 32766;
2202 rule.lookup = RT_TABLE_MAIN;
2203 rv |= system_iprule(&rule, RTM_NEWRULE);
2205 rule.priority = 32767;
2206 rule.lookup = RT_TABLE_DEFAULT;
2207 rv |= system_iprule(&rule, RTM_NEWRULE);
2210 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2213 rule.lookup = RT_TABLE_LOCAL;
2214 rv |= system_iprule(&rule, RTM_NEWRULE);
2216 rule.priority = 32766;
2217 rule.lookup = RT_TABLE_MAIN;
2218 rv |= system_iprule(&rule, RTM_NEWRULE);
2223 bool system_resolve_iprule_action(const char *action, unsigned int *id)
2225 return system_rtn_aton(action, id);
2228 time_t system_get_rtime(void)
2233 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
2236 if (gettimeofday(&tv, NULL) == 0)
2243 #define IP_DF 0x4000
2246 static int tunnel_ioctl(const char *name, int cmd, void *p)
2250 memset(&ifr, 0, sizeof(ifr));
2251 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
2252 ifr.ifr_ifru.ifru_data = p;
2253 return ioctl(sock_ioctl, cmd, &ifr);
2256 #ifdef IFLA_IPTUN_MAX
2257 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
2258 static int system_add_gre_tunnel(const char *name, const char *kind,
2259 const unsigned int link, struct blob_attr **tb, bool v6)
2262 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2263 struct blob_attr *cur;
2264 uint32_t ikey = 0, okey = 0, flags = 0, flowinfo = 0;
2265 uint16_t iflags = 0, oflags = 0;
2267 int ret = 0, ttl = 0;
2269 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2273 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2274 nla_put_string(nlm, IFLA_IFNAME, name);
2276 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2282 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2283 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2290 nla_put_u32(nlm, IFLA_GRE_LINK, link);
2292 if ((cur = tb[TUNNEL_ATTR_TTL]))
2293 ttl = blobmsg_get_u32(cur);
2295 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2296 char *str = blobmsg_get_string(cur);
2297 if (strcmp(str, "inherit")) {
2300 if (!system_tos_aton(str, &uval)) {
2306 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
2311 flags |= IP6_TNL_F_USE_ORIG_TCLASS;
2317 if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) {
2318 uint8_t icsum, ocsum, iseqno, oseqno;
2319 if (sscanf(blobmsg_get_string(cur), "%u,%u,%hhu,%hhu,%hhu,%hhu",
2320 &ikey, &okey, &icsum, &ocsum, &iseqno, &oseqno) < 6) {
2345 struct in6_addr in6buf;
2346 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2347 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2351 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
2354 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2355 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2359 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
2361 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, 4);
2364 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
2367 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags);
2372 struct in_addr inbuf;
2375 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2376 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2380 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
2383 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2384 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2388 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
2390 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
2392 okey = inbuf.s_addr;
2397 ikey = inbuf.s_addr;
2403 if ((cur = tb[TUNNEL_ATTR_DF]))
2404 set_df = blobmsg_get_bool(cur);
2407 /* ttl != 0 and nopmtudisc are incompatible */
2415 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
2417 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
2421 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
2424 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
2427 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
2430 nla_put_u32(nlm, IFLA_GRE_OKEY, okey);
2433 nla_put_u32(nlm, IFLA_GRE_IKEY, ikey);
2435 nla_nest_end(nlm, infodata);
2436 nla_nest_end(nlm, linkinfo);
2438 return system_rtnl_call(nlm);
2447 static int system_add_vti_tunnel(const char *name, const char *kind,
2448 const unsigned int link, struct blob_attr **tb, bool v6)
2451 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2452 struct blob_attr *cur;
2453 uint32_t ikey = 0, okey = 0;
2456 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2460 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2461 nla_put_string(nlm, IFLA_IFNAME, name);
2463 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2469 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2470 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2477 nla_put_u32(nlm, IFLA_VTI_LINK, link);
2479 if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) {
2480 if (sscanf(blobmsg_get_string(cur), "%u,%u",
2481 &ikey, &okey) < 2) {
2488 struct in6_addr in6buf;
2489 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2490 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2494 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(in6buf), &in6buf);
2497 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2498 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2502 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(in6buf), &in6buf);
2506 struct in_addr inbuf;
2508 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2509 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2513 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(inbuf), &inbuf);
2516 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2517 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2521 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(inbuf), &inbuf);
2527 nla_put_u32(nlm, IFLA_VTI_OKEY, htonl(okey));
2530 nla_put_u32(nlm, IFLA_VTI_IKEY, htonl(ikey));
2532 nla_nest_end(nlm, infodata);
2533 nla_nest_end(nlm, linkinfo);
2535 return system_rtnl_call(nlm);
2543 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
2545 struct blob_attr *cur;
2547 struct ip_tunnel_parm p = {
2556 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
2557 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
2560 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
2561 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
2564 if ((cur = tb[TUNNEL_ATTR_DF]))
2565 set_df = blobmsg_get_bool(cur);
2567 if ((cur = tb[TUNNEL_ATTR_TTL]))
2568 p.iph.ttl = blobmsg_get_u32(cur);
2570 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2571 char *str = blobmsg_get_string(cur);
2572 if (strcmp(str, "inherit")) {
2575 if (!system_tos_aton(str, &uval))
2583 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
2584 /* ttl !=0 and nopmtudisc are incompatible */
2585 if (p.iph.ttl && p.iph.frag_off == 0)
2588 strncpy(p.name, name, sizeof(p.name));
2590 switch (p.iph.protocol) {
2592 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
2594 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
2601 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
2603 struct blob_attr *cur;
2606 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2608 str = blobmsg_data(cur);
2610 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
2611 !strcmp(str, "greip6") || !strcmp(str, "gretapip6") ||
2612 !strcmp(str, "vtiip") || !strcmp(str, "vtiip6"))
2613 return system_link_del(name);
2615 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
2618 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
2620 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2622 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2623 blob_data(attr), blob_len(attr));
2625 return __system_del_ip_tunnel(name, tb);
2628 int system_update_ipv6_mtu(struct device *dev, int mtu)
2634 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
2637 fd = open(buf, O_RDWR);
2642 ssize_t len = read(fd, buf, sizeof(buf) - 1);
2649 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) > 0)
2658 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
2660 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2661 struct blob_attr *cur;
2664 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2665 blob_data(attr), blob_len(attr));
2667 __system_del_ip_tunnel(name, tb);
2669 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2671 str = blobmsg_data(cur);
2673 unsigned int ttl = 0;
2674 if ((cur = tb[TUNNEL_ATTR_TTL])) {
2675 ttl = blobmsg_get_u32(cur);
2680 unsigned int link = 0;
2681 if ((cur = tb[TUNNEL_ATTR_LINK])) {
2682 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
2686 if (iface->l3_dev.dev)
2687 link = iface->l3_dev.dev->ifindex;
2690 if (!strcmp(str, "sit")) {
2691 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
2695 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
2697 struct ip_tunnel_6rd p6;
2699 memset(&p6, 0, sizeof(p6));
2701 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
2702 &p6.prefix, &mask) || mask > 128)
2704 p6.prefixlen = mask;
2706 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
2707 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
2708 &p6.relay_prefix, &mask) || mask > 32)
2710 p6.relay_prefixlen = mask;
2713 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
2714 __system_del_ip_tunnel(name, tb);
2719 #ifdef IFLA_IPTUN_MAX
2720 } else if (!strcmp(str, "ipip6")) {
2721 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2722 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2723 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2729 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2730 nla_put_string(nlm, IFLA_IFNAME, name);
2733 nla_put_u32(nlm, IFLA_LINK, link);
2735 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2740 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2741 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2748 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2750 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2751 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2752 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
2754 struct in6_addr in6buf;
2755 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2756 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2760 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2763 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2764 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2768 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2771 #ifdef IFLA_IPTUN_FMR_MAX
2772 if ((cur = tb[TUNNEL_ATTR_FMRS])) {
2773 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2775 struct blob_attr *fmr;
2776 unsigned rem, fmrcnt = 0;
2777 blobmsg_for_each_attr(fmr, cur, rem) {
2778 if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
2781 unsigned ip4len, ip6len, ealen, offset = 6;
2785 if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
2786 ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) {
2791 struct in6_addr ip6prefix;
2792 struct in_addr ip4prefix;
2793 if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
2794 inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) {
2799 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2801 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2802 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2803 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2804 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2805 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2806 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2808 nla_nest_end(nlm, rule);
2811 nla_nest_end(nlm, fmrs);
2815 nla_nest_end(nlm, infodata);
2816 nla_nest_end(nlm, linkinfo);
2818 return system_rtnl_call(nlm);
2822 } else if (!strcmp(str, "greip")) {
2823 return system_add_gre_tunnel(name, "gre", link, tb, false);
2824 } else if (!strcmp(str, "gretapip")) {
2825 return system_add_gre_tunnel(name, "gretap", link, tb, false);
2826 } else if (!strcmp(str, "greip6")) {
2827 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
2828 } else if (!strcmp(str, "gretapip6")) {
2829 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
2831 } else if (!strcmp(str, "vtiip")) {
2832 return system_add_vti_tunnel(name, "vti", link, tb, false);
2833 } else if (!strcmp(str, "vtiip6")) {
2834 return system_add_vti_tunnel(name, "vti6", link, tb, true);
2837 } else if (!strcmp(str, "ipip")) {
2838 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);