2 * netifd - network interface daemon
3 * Copyright (C) 2012 Felix Fietkau <nbd@openwrt.org>
4 * Copyright (C) 2013 Jo-Philipp Wich <jow@openwrt.org>
5 * Copyright (C) 2013 Steven Barth <steven@midlink.org>
6 * Copyright (C) 2014 Gioacchino Mazzurco <gio@eigenlab.org>
7 * Copyright (C) 2017 Matthias Schiffer <mschiffer@universe-factory.net>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2
11 * as published by the Free Software Foundation
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
20 #include <sys/socket.h>
21 #include <sys/ioctl.h>
23 #include <sys/syscall.h>
26 #include <net/if_arp.h>
28 #include <arpa/inet.h>
29 #include <netinet/ether.h>
30 #include <netinet/in.h>
32 #include <linux/rtnetlink.h>
33 #include <linux/sockios.h>
35 #include <linux/if_addr.h>
36 #include <linux/if_link.h>
37 #include <linux/if_vlan.h>
38 #include <linux/if_bridge.h>
39 #include <linux/if_tunnel.h>
40 #include <linux/ip6_tunnel.h>
41 #include <linux/ethtool.h>
42 #include <linux/fib_rules.h>
43 #include <linux/veth.h>
44 #include <linux/version.h>
46 #ifndef RTN_FAILED_POLICY
47 #define RTN_FAILED_POLICY 12
50 #ifndef IFA_F_NOPREFIXROUTE
51 #define IFA_F_NOPREFIXROUTE 0x200
55 #define IFA_FLAGS (IFA_MULTICAST + 1)
64 #include <netlink/msg.h>
65 #include <netlink/attr.h>
66 #include <netlink/socket.h>
67 #include <libubox/uloop.h>
74 struct uloop_fd uloop;
79 static int sock_ioctl = -1;
80 static struct nl_sock *sock_rtnl = NULL;
82 static int cb_rtnl_event(struct nl_msg *msg, void *arg);
83 static void handle_hotplug_event(struct uloop_fd *u, unsigned int events);
84 static int system_add_proto_tunnel(const char *name, const uint8_t proto,
85 const unsigned int link, struct blob_attr **tb);
86 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb);
88 static char dev_buf[256];
91 handler_nl_event(struct uloop_fd *u, unsigned int events)
93 struct event_socket *ev = container_of(u, struct event_socket, uloop);
95 socklen_t errlen = sizeof(err);
98 nl_recvmsgs_default(ev->sock);
102 if (getsockopt(u->fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen))
107 // Increase rx buffer size on netlink socket
109 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
112 // Request full dump since some info got dropped
113 struct rtgenmsg msg = { .rtgen_family = AF_UNSPEC };
114 nl_send_simple(ev->sock, RTM_GETLINK, NLM_F_DUMP, &msg, sizeof(msg));
124 uloop_fd_delete(&ev->uloop);
128 static struct nl_sock *
129 create_socket(int protocol, int groups)
131 struct nl_sock *sock;
133 sock = nl_socket_alloc();
138 nl_join_groups(sock, groups);
140 if (nl_connect(sock, protocol))
147 create_raw_event_socket(struct event_socket *ev, int protocol, int groups,
148 uloop_fd_handler cb, int flags)
150 ev->sock = create_socket(protocol, groups);
154 ev->uloop.fd = nl_socket_get_fd(ev->sock);
156 if (uloop_fd_add(&ev->uloop, ULOOP_READ|flags))
163 create_event_socket(struct event_socket *ev, int protocol,
164 int (*cb)(struct nl_msg *msg, void *arg))
166 if (!create_raw_event_socket(ev, protocol, 0, handler_nl_event, ULOOP_ERROR_CB))
169 // Install the valid custom callback handler
170 nl_socket_modify_cb(ev->sock, NL_CB_VALID, NL_CB_CUSTOM, cb, NULL);
172 // Disable sequence number checking on event sockets
173 nl_socket_disable_seq_check(ev->sock);
175 // Increase rx buffer size to 65K on event sockets
177 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
184 system_rtn_aton(const char *src, unsigned int *dst)
189 if (!strcmp(src, "local"))
191 else if (!strcmp(src, "nat"))
193 else if (!strcmp(src, "broadcast"))
195 else if (!strcmp(src, "anycast"))
197 else if (!strcmp(src, "multicast"))
199 else if (!strcmp(src, "prohibit"))
201 else if (!strcmp(src, "unreachable"))
203 else if (!strcmp(src, "blackhole"))
205 else if (!strcmp(src, "xresolve"))
207 else if (!strcmp(src, "unicast"))
209 else if (!strcmp(src, "throw"))
211 else if (!strcmp(src, "failed_policy"))
212 n = RTN_FAILED_POLICY;
214 n = strtoul(src, &e, 0);
215 if (!e || *e || e == src || n > 255)
224 system_tos_aton(const char *src, unsigned *dst)
228 *dst = strtoul(src, &e, 16);
229 if (e == src || *e || *dst > 255)
235 int system_init(void)
237 static struct event_socket rtnl_event;
238 static struct event_socket hotplug_event;
240 sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0);
241 system_fd_set_cloexec(sock_ioctl);
243 // Prepare socket for routing / address control
244 sock_rtnl = create_socket(NETLINK_ROUTE, 0);
248 if (!create_event_socket(&rtnl_event, NETLINK_ROUTE, cb_rtnl_event))
251 if (!create_raw_event_socket(&hotplug_event, NETLINK_KOBJECT_UEVENT, 1,
252 handle_hotplug_event, 0))
255 // Receive network link events form kernel
256 nl_socket_add_membership(rtnl_event.sock, RTNLGRP_LINK);
261 static void system_set_sysctl(const char *path, const char *val)
265 fd = open(path, O_WRONLY);
269 if (write(fd, val, strlen(val))) {}
273 static void system_set_dev_sysctl(const char *path, const char *device, const char *val)
275 snprintf(dev_buf, sizeof(dev_buf), path, device);
276 system_set_sysctl(dev_buf, val);
279 static void system_set_disable_ipv6(struct device *dev, const char *val)
281 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val);
284 static void system_set_rpfilter(struct device *dev, const char *val)
286 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter", dev->ifname, val);
289 static void system_set_acceptlocal(struct device *dev, const char *val)
291 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local", dev->ifname, val);
294 static void system_set_igmpversion(struct device *dev, const char *val)
296 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version", dev->ifname, val);
299 static void system_set_mldversion(struct device *dev, const char *val)
301 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version", dev->ifname, val);
304 static void system_set_neigh4reachabletime(struct device *dev, const char *val)
306 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms", dev->ifname, val);
309 static void system_set_neigh6reachabletime(struct device *dev, const char *val)
311 system_set_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms", dev->ifname, val);
314 static void system_set_neigh4gcstaletime(struct device *dev, const char *val)
316 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/gc_stale_time", dev->ifname, val);
319 static void system_set_neigh6gcstaletime(struct device *dev, const char *val)
321 system_set_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/gc_stale_time", dev->ifname, val);
324 static void system_set_neigh4locktime(struct device *dev, const char *val)
326 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/locktime", dev->ifname, val);
329 static void system_set_dadtransmits(struct device *dev, const char *val)
331 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits", dev->ifname, val);
334 static void system_bridge_set_multicast_to_unicast(struct device *dev, const char *val)
336 system_set_dev_sysctl("/sys/class/net/%s/brport/multicast_to_unicast", dev->ifname, val);
339 static void system_bridge_set_multicast_fast_leave(struct device *dev, const char *val)
341 system_set_dev_sysctl("/sys/class/net/%s/brport/multicast_fast_leave", dev->ifname, val);
344 static void system_bridge_set_hairpin_mode(struct device *dev, const char *val)
346 system_set_dev_sysctl("/sys/class/net/%s/brport/hairpin_mode", dev->ifname, val);
349 static void system_bridge_set_isolate_mode(struct device *dev, const char *val)
351 system_set_dev_sysctl("/sys/class/net/%s/brport/isolate_mode", dev->ifname, val);
354 static void system_bridge_set_multicast_router(struct device *dev, const char *val, bool bridge)
356 system_set_dev_sysctl(bridge ? "/sys/class/net/%s/bridge/multicast_router" :
357 "/sys/class/net/%s/brport/multicast_router",
361 static void system_bridge_set_robustness(struct device *dev, const char *val)
363 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_startup_query_count",
365 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_last_member_count",
369 static void system_bridge_set_query_interval(struct device *dev, const char *val)
371 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_query_interval",
375 static void system_bridge_set_query_response_interval(struct device *dev, const char *val)
377 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_query_response_interval",
381 static void system_bridge_set_last_member_interval(struct device *dev, const char *val)
383 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_last_member_interval",
387 static void system_bridge_set_membership_interval(struct device *dev, const char *val)
389 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_membership_interval",
393 static void system_bridge_set_other_querier_timeout(struct device *dev, const char *val)
395 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier_interval",
399 static void system_bridge_set_startup_query_interval(struct device *dev, const char *val)
401 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_startup_query_interval",
405 static void system_bridge_set_learning(struct device *dev, const char *val)
407 system_set_dev_sysctl("/sys/class/net/%s/brport/learning", dev->ifname, val);
410 static void system_bridge_set_unicast_flood(struct device *dev, const char *val)
412 system_set_dev_sysctl("/sys/class/net/%s/brport/unicast_flood", dev->ifname, val);
415 static void system_set_sendredirects(struct device *dev, const char *val)
417 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/send_redirects", dev->ifname, val);
420 static int system_get_sysctl(const char *path, char *buf, const size_t buf_sz)
422 int fd = -1, ret = -1;
424 fd = open(path, O_RDONLY);
428 ssize_t len = read(fd, buf, buf_sz - 1);
442 system_get_dev_sysctl(const char *path, const char *device, char *buf, const size_t buf_sz)
444 snprintf(dev_buf, sizeof(dev_buf), path, device);
445 return system_get_sysctl(dev_buf, buf, buf_sz);
448 static int system_get_disable_ipv6(struct device *dev, char *buf, const size_t buf_sz)
450 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6",
451 dev->ifname, buf, buf_sz);
454 static int system_get_rpfilter(struct device *dev, char *buf, const size_t buf_sz)
456 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter",
457 dev->ifname, buf, buf_sz);
460 static int system_get_acceptlocal(struct device *dev, char *buf, const size_t buf_sz)
462 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local",
463 dev->ifname, buf, buf_sz);
466 static int system_get_igmpversion(struct device *dev, char *buf, const size_t buf_sz)
468 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version",
469 dev->ifname, buf, buf_sz);
472 static int system_get_mldversion(struct device *dev, char *buf, const size_t buf_sz)
474 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version",
475 dev->ifname, buf, buf_sz);
478 static int system_get_neigh4reachabletime(struct device *dev, char *buf, const size_t buf_sz)
480 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms",
481 dev->ifname, buf, buf_sz);
484 static int system_get_neigh6reachabletime(struct device *dev, char *buf, const size_t buf_sz)
486 return system_get_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms",
487 dev->ifname, buf, buf_sz);
490 static int system_get_neigh4gcstaletime(struct device *dev, char *buf, const size_t buf_sz)
492 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/gc_stale_time",
493 dev->ifname, buf, buf_sz);
496 static int system_get_neigh6gcstaletime(struct device *dev, char *buf, const size_t buf_sz)
498 return system_get_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/gc_stale_time",
499 dev->ifname, buf, buf_sz);
502 static int system_get_neigh4locktime(struct device *dev, char *buf, const size_t buf_sz)
504 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/locktime",
505 dev->ifname, buf, buf_sz);
508 static int system_get_dadtransmits(struct device *dev, char *buf, const size_t buf_sz)
510 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits",
511 dev->ifname, buf, buf_sz);
514 static int system_get_sendredirects(struct device *dev, char *buf, const size_t buf_sz)
516 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/send_redirects",
517 dev->ifname, buf, buf_sz);
520 // Evaluate netlink messages
521 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
523 struct nlmsghdr *nh = nlmsg_hdr(msg);
524 struct nlattr *nla[__IFLA_MAX];
528 if (nh->nlmsg_type != RTM_NEWLINK)
531 nlmsg_parse(nh, sizeof(struct ifinfomsg), nla, __IFLA_MAX - 1, NULL);
532 if (!nla[IFLA_IFNAME])
535 struct device *dev = device_find(nla_data(nla[IFLA_IFNAME]));
539 if (!system_get_dev_sysctl("/sys/class/net/%s/carrier", dev->ifname, buf, sizeof(buf)))
540 link_state = strtoul(buf, NULL, 0);
542 device_set_link(dev, link_state ? true : false);
549 handle_hotplug_msg(char *data, int size)
551 const char *subsystem = NULL, *interface = NULL, *interface_old = NULL;
552 char *cur, *end, *sep;
555 bool add, move = false;
557 if (!strncmp(data, "add@", 4))
559 else if (!strncmp(data, "remove@", 7))
561 else if (!strncmp(data, "move@", 5)) {
568 skip = strlen(data) + 1;
571 for (cur = data + skip; cur < end; cur += skip) {
572 skip = strlen(cur) + 1;
574 sep = strchr(cur, '=');
579 if (!strcmp(cur, "INTERFACE"))
581 else if (!strcmp(cur, "SUBSYSTEM")) {
583 if (strcmp(subsystem, "net") != 0)
585 } else if (!strcmp(cur, "DEVPATH_OLD")) {
586 interface_old = strrchr(sep + 1, '/');
592 if (subsystem && interface) {
593 if (move && interface_old)
602 dev = device_find(interface_old);
606 if (dev->type != &simple_device_type)
609 device_set_present(dev, false);
612 dev = device_find(interface);
616 if (dev->type != &simple_device_type)
619 if (add && system_if_force_external(dev->ifname))
622 device_set_present(dev, add);
626 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
628 struct event_socket *ev = container_of(u, struct event_socket, uloop);
629 struct sockaddr_nl nla;
630 unsigned char *buf = NULL;
633 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
635 handle_hotplug_msg((char *) buf, size);
641 static int system_rtnl_call(struct nl_msg *msg)
645 ret = nl_send_auto_complete(sock_rtnl, msg);
651 return nl_wait_for_ack(sock_rtnl);
654 int system_bridge_delbr(struct device *bridge)
656 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
659 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
663 memset(&ifr, 0, sizeof(ifr));
665 ifr.ifr_ifindex = dev->ifindex;
668 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
669 return ioctl(sock_ioctl, cmd, &ifr);
672 static bool system_is_bridge(const char *name, char *buf, int buflen)
676 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
677 if (stat(buf, &st) < 0)
683 static char *system_get_bridge(const char *name, char *buf, int buflen)
689 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
690 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
694 len = readlink(gl.gl_pathv[0], buf, buflen);
702 path = strrchr(buf, '/');
710 system_bridge_set_wireless(struct device *bridge, struct device *dev)
712 bool mcast_to_ucast = dev->wireless_ap;
715 if (bridge->settings.flags & DEV_OPT_MULTICAST_TO_UNICAST &&
716 !bridge->settings.multicast_to_unicast)
717 mcast_to_ucast = false;
719 if (!mcast_to_ucast || dev->wireless_isolate)
722 system_bridge_set_multicast_to_unicast(dev, mcast_to_ucast ? "1" : "0");
723 system_bridge_set_hairpin_mode(dev, hairpin ? "1" : "0");
726 int system_bridge_addif(struct device *bridge, struct device *dev)
732 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
733 if (!oldbr || strcmp(oldbr, bridge->ifname) != 0)
734 ret = system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
737 system_bridge_set_wireless(bridge, dev);
739 if (dev->settings.flags & DEV_OPT_MULTICAST_ROUTER) {
740 snprintf(buf, sizeof(buf), "%u", dev->settings.multicast_router);
741 system_bridge_set_multicast_router(dev, buf, false);
744 if (dev->settings.flags & DEV_OPT_MULTICAST_FAST_LEAVE &&
745 dev->settings.multicast_fast_leave)
746 system_bridge_set_multicast_fast_leave(dev, "1");
748 if (dev->settings.flags & DEV_OPT_LEARNING &&
749 !dev->settings.learning)
750 system_bridge_set_learning(dev, "0");
752 if (dev->settings.flags & DEV_OPT_UNICAST_FLOOD &&
753 !dev->settings.unicast_flood)
754 system_bridge_set_unicast_flood(dev, "0");
756 if (dev->settings.flags & DEV_OPT_ISOLATE &&
757 dev->settings.isolate)
758 system_bridge_set_isolate_mode(dev, "1");
763 int system_bridge_delif(struct device *bridge, struct device *dev)
765 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
768 int system_if_resolve(struct device *dev)
771 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
772 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
773 return ifr.ifr_ifindex;
778 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
782 memset(&ifr, 0, sizeof(ifr));
783 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
784 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) < 0)
787 ifr.ifr_flags |= add;
788 ifr.ifr_flags &= ~rem;
789 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
801 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
803 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
805 return ifa->ifa_index == ifindex;
808 static bool check_route(struct nlmsghdr *hdr, int ifindex)
810 struct rtmsg *r = NLMSG_DATA(hdr);
811 struct nlattr *tb[__RTA_MAX];
813 if (r->rtm_protocol == RTPROT_KERNEL &&
814 r->rtm_family == AF_INET6)
817 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
821 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
824 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
829 static int cb_clear_event(struct nl_msg *msg, void *arg)
831 struct clear_data *clr = arg;
832 struct nlmsghdr *hdr = nlmsg_hdr(msg);
833 bool (*cb)(struct nlmsghdr *, int ifindex);
839 if (hdr->nlmsg_type != RTM_NEWADDR)
846 if (hdr->nlmsg_type != RTM_NEWROUTE)
853 if (hdr->nlmsg_type != RTM_NEWRULE)
862 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
865 if (type == RTM_DELRULE)
866 D(SYSTEM, "Remove a rule\n");
868 D(SYSTEM, "Remove %s from device %s\n",
869 type == RTM_DELADDR ? "an address" : "a route",
871 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
872 hdr = nlmsg_hdr(clr->msg);
873 hdr->nlmsg_type = type;
874 hdr->nlmsg_flags = NLM_F_REQUEST;
876 nl_socket_disable_auto_ack(sock_rtnl);
877 nl_send_auto_complete(sock_rtnl, clr->msg);
878 nl_socket_enable_auto_ack(sock_rtnl);
884 cb_finish_event(struct nl_msg *msg, void *arg)
892 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
895 *pending = err->error;
900 system_if_clear_entries(struct device *dev, int type, int af)
902 struct clear_data clr;
903 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
906 .rtm_flags = RTM_F_CLONED,
908 int flags = NLM_F_DUMP;
917 clr.size = sizeof(struct rtgenmsg);
920 clr.size = sizeof(struct rtmsg);
929 clr.msg = nlmsg_alloc_simple(type, flags);
933 nlmsg_append(clr.msg, &rtm, clr.size, 0);
934 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
935 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
936 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
938 nl_send_auto_complete(sock_rtnl, clr.msg);
940 nl_recvmsgs(sock_rtnl, cb);
948 * Clear bridge (membership) state and bring down device
950 void system_if_clear_state(struct device *dev)
952 static char buf[256];
955 device_set_ifindex(dev, system_if_resolve(dev));
956 if (dev->external || !dev->ifindex)
959 system_if_flags(dev->ifname, 0, IFF_UP);
961 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
962 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
963 system_bridge_delbr(dev);
967 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
969 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
970 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
973 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
974 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
975 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
976 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
977 system_set_disable_ipv6(dev, "0");
980 static inline unsigned long
981 sec_to_jiffies(int val)
983 return (unsigned long) val * 100;
986 static void system_bridge_conf_multicast_deps(struct device *bridge,
987 struct bridge_config *cfg,
993 if (cfg->flags & BRIDGE_OPT_ROBUSTNESS ||
994 cfg->flags & BRIDGE_OPT_QUERY_INTERVAL ||
995 cfg->flags & BRIDGE_OPT_QUERY_RESPONSE_INTERVAL) {
996 val = cfg->robustness * cfg->query_interval +
997 cfg->query_response_interval;
999 snprintf(buf, buf_len, "%i", val);
1000 system_bridge_set_membership_interval(bridge, buf);
1002 val = cfg->robustness * cfg->query_interval +
1003 cfg->query_response_interval / 2;
1005 snprintf(buf, buf_len, "%i", val);
1006 system_bridge_set_other_querier_timeout(bridge, buf);
1009 if (cfg->flags & BRIDGE_OPT_QUERY_INTERVAL) {
1010 val = cfg->query_interval / 4;
1012 snprintf(buf, buf_len, "%i", val);
1013 system_bridge_set_startup_query_interval(bridge, buf);
1017 static void system_bridge_conf_multicast(struct device *bridge,
1018 struct bridge_config *cfg,
1022 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
1023 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
1025 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier",
1026 bridge->ifname, cfg->multicast_querier ? "1" : "0");
1028 snprintf(buf, buf_len, "%i", cfg->hash_max);
1029 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/hash_max",
1030 bridge->ifname, buf);
1032 if (bridge->settings.flags & DEV_OPT_MULTICAST_ROUTER) {
1033 snprintf(buf, buf_len, "%u", bridge->settings.multicast_router);
1034 system_bridge_set_multicast_router(bridge, buf, true);
1037 if (cfg->flags & BRIDGE_OPT_ROBUSTNESS) {
1038 snprintf(buf, buf_len, "%i", cfg->robustness);
1039 system_bridge_set_robustness(bridge, buf);
1042 if (cfg->flags & BRIDGE_OPT_QUERY_INTERVAL) {
1043 snprintf(buf, buf_len, "%i", cfg->query_interval);
1044 system_bridge_set_query_interval(bridge, buf);
1047 if (cfg->flags & BRIDGE_OPT_QUERY_RESPONSE_INTERVAL) {
1048 snprintf(buf, buf_len, "%i", cfg->query_response_interval);
1049 system_bridge_set_query_response_interval(bridge, buf);
1052 if (cfg->flags & BRIDGE_OPT_LAST_MEMBER_INTERVAL) {
1053 snprintf(buf, buf_len, "%i", cfg->last_member_interval);
1054 system_bridge_set_last_member_interval(bridge, buf);
1057 system_bridge_conf_multicast_deps(bridge, cfg, buf, buf_len);
1060 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
1063 unsigned long args[4] = {};
1065 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
1068 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
1069 args[1] = !!cfg->stp;
1070 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1072 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
1073 args[1] = sec_to_jiffies(cfg->forward_delay);
1074 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1076 system_bridge_conf_multicast(bridge, cfg, buf, sizeof(buf));
1078 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
1079 args[1] = cfg->priority;
1080 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1082 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
1083 args[0] = BRCTL_SET_AGEING_TIME;
1084 args[1] = sec_to_jiffies(cfg->ageing_time);
1085 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1088 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
1089 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
1090 args[1] = sec_to_jiffies(cfg->hello_time);
1091 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1094 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
1095 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
1096 args[1] = sec_to_jiffies(cfg->max_age);
1097 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1103 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
1106 struct nlattr *linkinfo, *data;
1107 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
1109 static const struct {
1111 enum macvlan_mode val;
1113 { "private", MACVLAN_MODE_PRIVATE },
1114 { "vepa", MACVLAN_MODE_VEPA },
1115 { "bridge", MACVLAN_MODE_BRIDGE },
1116 { "passthru", MACVLAN_MODE_PASSTHRU },
1119 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1124 nlmsg_append(msg, &iim, sizeof(iim), 0);
1126 if (cfg->flags & MACVLAN_OPT_MACADDR)
1127 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
1128 nla_put_string(msg, IFLA_IFNAME, macvlan->ifname);
1129 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
1131 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1132 goto nla_put_failure;
1134 nla_put_string(msg, IFLA_INFO_KIND, "macvlan");
1136 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1137 goto nla_put_failure;
1140 for (i = 0; i < ARRAY_SIZE(modes); i++) {
1141 if (strcmp(cfg->mode, modes[i].name) != 0)
1144 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
1149 nla_nest_end(msg, data);
1150 nla_nest_end(msg, linkinfo);
1152 rv = system_rtnl_call(msg);
1154 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
1163 static int system_link_del(const char *ifname)
1166 struct ifinfomsg iim = {
1167 .ifi_family = AF_UNSPEC,
1171 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
1176 nlmsg_append(msg, &iim, sizeof(iim), 0);
1177 nla_put_string(msg, IFLA_IFNAME, ifname);
1178 return system_rtnl_call(msg);
1181 int system_macvlan_del(struct device *macvlan)
1183 return system_link_del(macvlan->ifname);
1186 int system_veth_add(struct device *veth, struct veth_config *cfg)
1189 struct ifinfomsg empty_iim = {};
1190 struct nlattr *linkinfo, *data, *veth_info;
1193 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1198 nlmsg_append(msg, &empty_iim, sizeof(empty_iim), 0);
1200 if (cfg->flags & VETH_OPT_MACADDR)
1201 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
1202 nla_put_string(msg, IFLA_IFNAME, veth->ifname);
1204 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1205 goto nla_put_failure;
1207 nla_put_string(msg, IFLA_INFO_KIND, "veth");
1209 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1210 goto nla_put_failure;
1212 if (!(veth_info = nla_nest_start(msg, VETH_INFO_PEER)))
1213 goto nla_put_failure;
1215 nlmsg_append(msg, &empty_iim, sizeof(empty_iim), 0);
1217 if (cfg->flags & VETH_OPT_PEER_NAME)
1218 nla_put_string(msg, IFLA_IFNAME, cfg->peer_name);
1219 if (cfg->flags & VETH_OPT_PEER_MACADDR)
1220 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->peer_macaddr), cfg->peer_macaddr);
1222 nla_nest_end(msg, veth_info);
1223 nla_nest_end(msg, data);
1224 nla_nest_end(msg, linkinfo);
1226 rv = system_rtnl_call(msg);
1228 if (cfg->flags & VETH_OPT_PEER_NAME)
1229 D(SYSTEM, "Error adding veth '%s' with peer '%s': %d\n", veth->ifname, cfg->peer_name, rv);
1231 D(SYSTEM, "Error adding veth '%s': %d\n", veth->ifname, rv);
1241 int system_veth_del(struct device *veth)
1243 return system_link_del(veth->ifname);
1246 static int system_vlan(struct device *dev, int id)
1248 struct vlan_ioctl_args ifr = {
1249 .cmd = SET_VLAN_NAME_TYPE_CMD,
1250 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
1253 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
1256 ifr.cmd = DEL_VLAN_CMD;
1259 ifr.cmd = ADD_VLAN_CMD;
1262 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
1263 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
1266 int system_vlan_add(struct device *dev, int id)
1268 return system_vlan(dev, id);
1271 int system_vlan_del(struct device *dev)
1273 return system_vlan(dev, -1);
1276 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
1279 struct nlattr *linkinfo, *data;
1280 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
1283 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1288 nlmsg_append(msg, &iim, sizeof(iim), 0);
1289 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
1290 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
1292 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1293 goto nla_put_failure;
1295 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
1297 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1298 goto nla_put_failure;
1300 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
1302 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
1303 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
1305 if(cfg->proto == VLAN_PROTO_8021AD)
1306 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);
1309 nla_nest_end(msg, data);
1310 nla_nest_end(msg, linkinfo);
1312 rv = system_rtnl_call(msg);
1314 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
1323 int system_vlandev_del(struct device *vlandev)
1325 return system_link_del(vlandev->ifname);
1329 system_if_get_settings(struct device *dev, struct device_settings *s)
1334 memset(&ifr, 0, sizeof(ifr));
1335 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1337 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
1338 s->mtu = ifr.ifr_mtu;
1339 s->flags |= DEV_OPT_MTU;
1342 s->mtu6 = system_update_ipv6_mtu(dev, 0);
1344 s->flags |= DEV_OPT_MTU6;
1346 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
1347 s->txqueuelen = ifr.ifr_qlen;
1348 s->flags |= DEV_OPT_TXQUEUELEN;
1351 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
1352 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
1353 s->flags |= DEV_OPT_MACADDR;
1356 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
1357 s->ipv6 = !strtoul(buf, NULL, 0);
1358 s->flags |= DEV_OPT_IPV6;
1361 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
1362 s->promisc = ifr.ifr_flags & IFF_PROMISC;
1363 s->flags |= DEV_OPT_PROMISC;
1365 s->multicast = ifr.ifr_flags & IFF_MULTICAST;
1366 s->flags |= DEV_OPT_MULTICAST;
1369 if (!system_get_rpfilter(dev, buf, sizeof(buf))) {
1370 s->rpfilter = strtoul(buf, NULL, 0);
1371 s->flags |= DEV_OPT_RPFILTER;
1374 if (!system_get_acceptlocal(dev, buf, sizeof(buf))) {
1375 s->acceptlocal = strtoul(buf, NULL, 0);
1376 s->flags |= DEV_OPT_ACCEPTLOCAL;
1379 if (!system_get_igmpversion(dev, buf, sizeof(buf))) {
1380 s->igmpversion = strtoul(buf, NULL, 0);
1381 s->flags |= DEV_OPT_IGMPVERSION;
1384 if (!system_get_mldversion(dev, buf, sizeof(buf))) {
1385 s->mldversion = strtoul(buf, NULL, 0);
1386 s->flags |= DEV_OPT_MLDVERSION;
1389 if (!system_get_neigh4reachabletime(dev, buf, sizeof(buf))) {
1390 s->neigh4reachabletime = strtoul(buf, NULL, 0);
1391 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1394 if (!system_get_neigh6reachabletime(dev, buf, sizeof(buf))) {
1395 s->neigh6reachabletime = strtoul(buf, NULL, 0);
1396 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1399 if (!system_get_neigh4locktime(dev, buf, sizeof(buf))) {
1400 s->neigh4locktime = strtol(buf, NULL, 0);
1401 s->flags |= DEV_OPT_NEIGHLOCKTIME;
1404 if (!system_get_neigh4gcstaletime(dev, buf, sizeof(buf))) {
1405 s->neigh4gcstaletime = strtoul(buf, NULL, 0);
1406 s->flags |= DEV_OPT_NEIGHGCSTALETIME;
1409 if (!system_get_neigh6gcstaletime(dev, buf, sizeof(buf))) {
1410 s->neigh6gcstaletime = strtoul(buf, NULL, 0);
1411 s->flags |= DEV_OPT_NEIGHGCSTALETIME;
1414 if (!system_get_dadtransmits(dev, buf, sizeof(buf))) {
1415 s->dadtransmits = strtoul(buf, NULL, 0);
1416 s->flags |= DEV_OPT_DADTRANSMITS;
1419 if (!system_get_sendredirects(dev, buf, sizeof(buf))) {
1420 s->sendredirects = strtoul(buf, NULL, 0);
1421 s->flags |= DEV_OPT_SENDREDIRECTS;
1426 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
1431 memset(&ifr, 0, sizeof(ifr));
1432 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1433 if (s->flags & DEV_OPT_MTU & apply_mask) {
1434 ifr.ifr_mtu = s->mtu;
1435 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
1436 s->flags &= ~DEV_OPT_MTU;
1438 if (s->flags & DEV_OPT_MTU6 & apply_mask) {
1439 system_update_ipv6_mtu(dev, s->mtu6);
1441 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
1442 ifr.ifr_qlen = s->txqueuelen;
1443 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
1444 s->flags &= ~DEV_OPT_TXQUEUELEN;
1446 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
1447 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
1448 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
1449 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
1450 s->flags &= ~DEV_OPT_MACADDR;
1452 if (s->flags & DEV_OPT_IPV6 & apply_mask)
1453 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
1454 if (s->flags & DEV_OPT_PROMISC & apply_mask) {
1455 if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
1456 !s->promisc ? IFF_PROMISC : 0) < 0)
1457 s->flags &= ~DEV_OPT_PROMISC;
1459 if (s->flags & DEV_OPT_RPFILTER & apply_mask) {
1460 snprintf(buf, sizeof(buf), "%u", s->rpfilter);
1461 system_set_rpfilter(dev, buf);
1463 if (s->flags & DEV_OPT_ACCEPTLOCAL & apply_mask)
1464 system_set_acceptlocal(dev, s->acceptlocal ? "1" : "0");
1465 if (s->flags & DEV_OPT_IGMPVERSION & apply_mask) {
1466 snprintf(buf, sizeof(buf), "%u", s->igmpversion);
1467 system_set_igmpversion(dev, buf);
1469 if (s->flags & DEV_OPT_MLDVERSION & apply_mask) {
1470 snprintf(buf, sizeof(buf), "%u", s->mldversion);
1471 system_set_mldversion(dev, buf);
1473 if (s->flags & DEV_OPT_NEIGHREACHABLETIME & apply_mask) {
1474 snprintf(buf, sizeof(buf), "%u", s->neigh4reachabletime);
1475 system_set_neigh4reachabletime(dev, buf);
1476 snprintf(buf, sizeof(buf), "%u", s->neigh6reachabletime);
1477 system_set_neigh6reachabletime(dev, buf);
1479 if (s->flags & DEV_OPT_NEIGHLOCKTIME & apply_mask) {
1480 snprintf(buf, sizeof(buf), "%d", s->neigh4locktime);
1481 system_set_neigh4locktime(dev, buf);
1483 if (s->flags & DEV_OPT_NEIGHGCSTALETIME & apply_mask) {
1484 snprintf(buf, sizeof(buf), "%u", s->neigh4gcstaletime);
1485 system_set_neigh4gcstaletime(dev, buf);
1486 snprintf(buf, sizeof(buf), "%u", s->neigh6gcstaletime);
1487 system_set_neigh6gcstaletime(dev, buf);
1489 if (s->flags & DEV_OPT_DADTRANSMITS & apply_mask) {
1490 snprintf(buf, sizeof(buf), "%u", s->dadtransmits);
1491 system_set_dadtransmits(dev, buf);
1493 if (s->flags & DEV_OPT_MULTICAST & apply_mask) {
1494 if (system_if_flags(dev->ifname, s->multicast ? IFF_MULTICAST : 0,
1495 !s->multicast ? IFF_MULTICAST : 0) < 0)
1496 s->flags &= ~DEV_OPT_MULTICAST;
1498 if (s->flags & DEV_OPT_SENDREDIRECTS & apply_mask)
1499 system_set_sendredirects(dev, s->sendredirects ? "1" : "0");
1502 int system_if_up(struct device *dev)
1504 system_if_get_settings(dev, &dev->orig_settings);
1505 /* Only keep orig settings based on what needs to be set */
1506 dev->orig_settings.valid_flags = dev->orig_settings.flags;
1507 dev->orig_settings.flags &= dev->settings.flags;
1508 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
1509 return system_if_flags(dev->ifname, IFF_UP, 0);
1512 int system_if_down(struct device *dev)
1514 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
1515 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
1519 struct if_check_data {
1525 #ifndef IFF_LOWER_UP
1526 #define IFF_LOWER_UP 0x10000
1529 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1531 struct nlmsghdr *nh = nlmsg_hdr(msg);
1532 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1533 struct if_check_data *chk = (struct if_check_data *)arg;
1535 if (nh->nlmsg_type != RTM_NEWLINK)
1538 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1539 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1544 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1546 struct if_check_data *chk = (struct if_check_data *)arg;
1551 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1553 struct if_check_data *chk = (struct if_check_data *)arg;
1555 device_set_present(chk->dev, false);
1556 device_set_link(chk->dev, false);
1557 chk->pending = err->error;
1562 int system_if_check(struct device *dev)
1564 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1566 struct ifinfomsg ifi = {
1567 .ifi_family = AF_UNSPEC,
1570 struct if_check_data chk = {
1579 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1583 if (nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1584 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1587 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1588 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1589 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1591 nl_send_auto_complete(sock_rtnl, msg);
1592 while (chk.pending > 0)
1593 nl_recvmsgs(sock_rtnl, cb);
1605 system_if_get_parent(struct device *dev)
1607 char buf[64], *devname;
1608 int ifindex, iflink, len;
1611 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1612 f = fopen(buf, "r");
1616 len = fread(buf, 1, sizeof(buf) - 1, f);
1623 iflink = strtoul(buf, NULL, 0);
1624 ifindex = system_if_resolve(dev);
1625 if (!iflink || iflink == ifindex)
1628 devname = if_indextoname(iflink, buf);
1632 return device_get(devname, true);
1636 read_string_file(int dir_fd, const char *file, char *buf, int len)
1642 fd = openat(dir_fd, file, O_RDONLY);
1647 len = read(fd, buf, len - 1);
1651 } else if (len > 0) {
1654 c = strchr(buf, '\n');
1667 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1672 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1674 *val = strtoull(buf, NULL, 0);
1679 /* Assume advertised flags == supported flags */
1680 static const struct {
1683 } ethtool_link_modes[] = {
1684 { ADVERTISED_10baseT_Half, "10H" },
1685 { ADVERTISED_10baseT_Full, "10F" },
1686 { ADVERTISED_100baseT_Half, "100H" },
1687 { ADVERTISED_100baseT_Full, "100F" },
1688 { ADVERTISED_1000baseT_Half, "1000H" },
1689 { ADVERTISED_1000baseT_Full, "1000F" },
1692 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1695 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1696 if (mask & ethtool_link_modes[i].mask)
1697 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1702 system_if_force_external(const char *ifname)
1707 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1708 return stat(buf, &s) == 0;
1712 system_if_dump_info(struct device *dev, struct blob_buf *b)
1714 struct ethtool_cmd ecmd;
1719 memset(&ecmd, 0, sizeof(ecmd));
1720 memset(&ifr, 0, sizeof(ifr));
1721 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1722 ifr.ifr_data = (caddr_t) &ecmd;
1723 ecmd.cmd = ETHTOOL_GSET;
1725 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1726 c = blobmsg_open_array(b, "link-advertising");
1727 system_add_link_modes(b, ecmd.advertising);
1728 blobmsg_close_array(b, c);
1730 c = blobmsg_open_array(b, "link-supported");
1731 system_add_link_modes(b, ecmd.supported);
1732 blobmsg_close_array(b, c);
1734 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1735 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1736 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1737 blobmsg_add_string_buffer(b);
1744 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1746 const char *const counters[] = {
1747 "collisions", "rx_frame_errors", "tx_compressed",
1748 "multicast", "rx_length_errors", "tx_dropped",
1749 "rx_bytes", "rx_missed_errors", "tx_errors",
1750 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1751 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1752 "rx_dropped", "tx_aborted_errors", "tx_packets",
1753 "rx_errors", "tx_bytes", "tx_window_errors",
1754 "rx_fifo_errors", "tx_carrier_errors",
1761 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1762 stats_dir = open(buf, O_DIRECTORY);
1766 for (i = 0; i < ARRAY_SIZE(counters); i++)
1767 if (read_uint64_file(stats_dir, counters[i], &val))
1768 blobmsg_add_u64(b, counters[i], val);
1774 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1776 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1777 int alen = v4 ? 4 : 16;
1778 unsigned int flags = 0;
1779 struct ifaddrmsg ifa = {
1780 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1781 .ifa_prefixlen = addr->mask,
1782 .ifa_index = dev->ifindex,
1786 if (cmd == RTM_NEWADDR)
1787 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1789 msg = nlmsg_alloc_simple(cmd, flags);
1793 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1794 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1796 if (addr->broadcast)
1797 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1798 if (addr->point_to_point)
1799 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1801 time_t now = system_get_rtime();
1802 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1804 if (addr->preferred_until) {
1805 int64_t preferred = addr->preferred_until - now;
1808 else if (preferred > UINT32_MAX)
1809 preferred = UINT32_MAX;
1811 cinfo.ifa_prefered = preferred;
1814 if (addr->valid_until) {
1815 int64_t valid = addr->valid_until - now;
1820 else if (valid > UINT32_MAX)
1823 cinfo.ifa_valid = valid;
1826 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1828 if (cmd == RTM_NEWADDR && (addr->flags & DEVADDR_OFFLINK))
1829 nla_put_u32(msg, IFA_FLAGS, IFA_F_NOPREFIXROUTE);
1832 return system_rtnl_call(msg);
1835 int system_add_address(struct device *dev, struct device_addr *addr)
1837 return system_addr(dev, addr, RTM_NEWADDR);
1840 int system_del_address(struct device *dev, struct device_addr *addr)
1842 return system_addr(dev, addr, RTM_DELADDR);
1845 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1847 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1849 unsigned int flags = 0;
1852 have_gw = !!route->nexthop.in.s_addr;
1854 have_gw = route->nexthop.in6.s6_addr32[0] ||
1855 route->nexthop.in6.s6_addr32[1] ||
1856 route->nexthop.in6.s6_addr32[2] ||
1857 route->nexthop.in6.s6_addr32[3];
1859 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1860 ? route->table : RT_TABLE_MAIN;
1862 struct rtmsg rtm = {
1863 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1864 .rtm_dst_len = route->mask,
1865 .rtm_src_len = route->sourcemask,
1866 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1867 .rtm_protocol = (route->flags & DEVROUTE_PROTO) ? route->proto : RTPROT_STATIC,
1868 .rtm_scope = RT_SCOPE_NOWHERE,
1869 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1870 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1874 if (cmd == RTM_NEWROUTE) {
1875 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1877 if (!dev) { // Add null-route
1878 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1879 rtm.rtm_type = RTN_UNREACHABLE;
1882 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1885 if (route->flags & DEVROUTE_TYPE) {
1886 rtm.rtm_type = route->type;
1887 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
1888 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
1889 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
1890 rtm.rtm_table = RT_TABLE_LOCAL;
1893 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT) {
1894 rtm.rtm_scope = RT_SCOPE_HOST;
1895 } else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
1896 rtm.rtm_type == RTN_ANYCAST) {
1897 rtm.rtm_scope = RT_SCOPE_LINK;
1898 } else if (rtm.rtm_type == RTN_BLACKHOLE || rtm.rtm_type == RTN_UNREACHABLE ||
1899 rtm.rtm_type == RTN_PROHIBIT || rtm.rtm_type == RTN_FAILED_POLICY ||
1900 rtm.rtm_type == RTN_THROW) {
1901 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1906 msg = nlmsg_alloc_simple(cmd, flags);
1910 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1913 nla_put(msg, RTA_DST, alen, &route->addr);
1915 if (route->sourcemask) {
1916 if (rtm.rtm_family == AF_INET)
1917 nla_put(msg, RTA_PREFSRC, alen, &route->source);
1919 nla_put(msg, RTA_SRC, alen, &route->source);
1922 if (route->metric > 0)
1923 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1926 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1929 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1932 nla_put_u32(msg, RTA_TABLE, table);
1934 if (route->flags & DEVROUTE_MTU) {
1935 struct nlattr *metrics;
1937 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1938 goto nla_put_failure;
1940 nla_put_u32(msg, RTAX_MTU, route->mtu);
1942 nla_nest_end(msg, metrics);
1945 return system_rtnl_call(msg);
1952 int system_add_route(struct device *dev, struct device_route *route)
1954 return system_rt(dev, route, RTM_NEWROUTE);
1957 int system_del_route(struct device *dev, struct device_route *route)
1959 return system_rt(dev, route, RTM_DELROUTE);
1962 int system_flush_routes(void)
1964 const char *names[] = {
1965 "/proc/sys/net/ipv4/route/flush",
1966 "/proc/sys/net/ipv6/route/flush"
1970 for (i = 0; i < ARRAY_SIZE(names); i++) {
1971 fd = open(names[i], O_WRONLY);
1975 if (write(fd, "-1", 2)) {}
1981 bool system_resolve_rt_type(const char *type, unsigned int *id)
1983 return system_rtn_aton(type, id);
1986 bool system_resolve_rt_proto(const char *type, unsigned int *id)
1990 unsigned int n, proto = 256;
1991 n = strtoul(type, &e, 0);
1992 if (!*e && e != type)
1994 else if (!strcmp(type, "unspec"))
1995 proto = RTPROT_UNSPEC;
1996 else if (!strcmp(type, "kernel"))
1997 proto = RTPROT_KERNEL;
1998 else if (!strcmp(type, "boot"))
1999 proto = RTPROT_BOOT;
2000 else if (!strcmp(type, "static"))
2001 proto = RTPROT_STATIC;
2002 else if ((f = fopen("/etc/iproute2/rt_protos", "r")) != NULL) {
2003 while (fgets(buf, sizeof(buf) - 1, f) != NULL) {
2004 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
2007 n = strtoul(e, NULL, 10);
2008 e = strtok(NULL, " \t\n");
2010 if (e && !strcmp(e, type)) {
2025 bool system_resolve_rt_table(const char *name, unsigned int *id)
2029 unsigned int n, table = RT_TABLE_UNSPEC;
2031 /* first try to parse table as number */
2032 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
2035 /* handle well known aliases */
2036 else if (!strcmp(name, "default"))
2037 table = RT_TABLE_DEFAULT;
2038 else if (!strcmp(name, "main"))
2039 table = RT_TABLE_MAIN;
2040 else if (!strcmp(name, "local"))
2041 table = RT_TABLE_LOCAL;
2043 /* try to look up name in /etc/iproute2/rt_tables */
2044 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
2046 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
2048 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
2051 n = strtoul(e, NULL, 10);
2052 e = strtok(NULL, " \t\n");
2054 if (e && !strcmp(e, name))
2064 if (table == RT_TABLE_UNSPEC)
2071 bool system_is_default_rt_table(unsigned int id)
2073 return (id == RT_TABLE_MAIN);
2076 bool system_resolve_rpfilter(const char *filter, unsigned int *id)
2081 if (!strcmp(filter, "strict"))
2083 else if (!strcmp(filter, "loose"))
2086 n = strtoul(filter, &e, 0);
2087 if (*e || e == filter || n > 2)
2095 static int system_iprule(struct iprule *rule, int cmd)
2097 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
2100 struct rtmsg rtm = {
2101 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
2102 .rtm_protocol = RTPROT_STATIC,
2103 .rtm_scope = RT_SCOPE_UNIVERSE,
2104 .rtm_table = RT_TABLE_UNSPEC,
2105 .rtm_type = RTN_UNSPEC,
2109 if (cmd == RTM_NEWRULE)
2110 rtm.rtm_type = RTN_UNICAST;
2113 rtm.rtm_flags |= FIB_RULE_INVERT;
2115 if (rule->flags & IPRULE_SRC)
2116 rtm.rtm_src_len = rule->src_mask;
2118 if (rule->flags & IPRULE_DEST)
2119 rtm.rtm_dst_len = rule->dest_mask;
2121 if (rule->flags & IPRULE_TOS)
2122 rtm.rtm_tos = rule->tos;
2124 if (rule->flags & IPRULE_LOOKUP) {
2125 if (rule->lookup < 256)
2126 rtm.rtm_table = rule->lookup;
2129 if (rule->flags & IPRULE_ACTION)
2130 rtm.rtm_type = rule->action;
2131 else if (rule->flags & IPRULE_GOTO)
2132 rtm.rtm_type = FR_ACT_GOTO;
2133 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
2134 rtm.rtm_type = FR_ACT_NOP;
2136 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
2141 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
2143 if (rule->flags & IPRULE_IN)
2144 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
2146 if (rule->flags & IPRULE_OUT)
2147 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
2149 if (rule->flags & IPRULE_SRC)
2150 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
2152 if (rule->flags & IPRULE_DEST)
2153 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
2155 if (rule->flags & IPRULE_PRIORITY)
2156 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
2157 else if (cmd == RTM_NEWRULE)
2158 nla_put_u32(msg, FRA_PRIORITY, rule->order);
2160 if (rule->flags & IPRULE_FWMARK)
2161 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
2163 if (rule->flags & IPRULE_FWMASK)
2164 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
2166 if (rule->flags & IPRULE_LOOKUP) {
2167 if (rule->lookup >= 256)
2168 nla_put_u32(msg, FRA_TABLE, rule->lookup);
2171 if (rule->flags & IPRULE_SUP_PREFIXLEN)
2172 nla_put_u32(msg, FRA_SUPPRESS_PREFIXLEN, rule->sup_prefixlen);
2174 if (rule->flags & IPRULE_GOTO)
2175 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
2177 return system_rtnl_call(msg);
2180 int system_add_iprule(struct iprule *rule)
2182 return system_iprule(rule, RTM_NEWRULE);
2185 int system_del_iprule(struct iprule *rule)
2187 return system_iprule(rule, RTM_DELRULE);
2190 int system_flush_iprules(void)
2195 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
2196 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
2198 memset(&rule, 0, sizeof(rule));
2201 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2204 rule.lookup = RT_TABLE_LOCAL;
2205 rv |= system_iprule(&rule, RTM_NEWRULE);
2207 rule.priority = 32766;
2208 rule.lookup = RT_TABLE_MAIN;
2209 rv |= system_iprule(&rule, RTM_NEWRULE);
2211 rule.priority = 32767;
2212 rule.lookup = RT_TABLE_DEFAULT;
2213 rv |= system_iprule(&rule, RTM_NEWRULE);
2216 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2219 rule.lookup = RT_TABLE_LOCAL;
2220 rv |= system_iprule(&rule, RTM_NEWRULE);
2222 rule.priority = 32766;
2223 rule.lookup = RT_TABLE_MAIN;
2224 rv |= system_iprule(&rule, RTM_NEWRULE);
2229 bool system_resolve_iprule_action(const char *action, unsigned int *id)
2231 return system_rtn_aton(action, id);
2234 time_t system_get_rtime(void)
2239 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
2242 if (gettimeofday(&tv, NULL) == 0)
2249 #define IP_DF 0x4000
2252 static int tunnel_ioctl(const char *name, int cmd, void *p)
2256 memset(&ifr, 0, sizeof(ifr));
2257 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
2258 ifr.ifr_ifru.ifru_data = p;
2259 return ioctl(sock_ioctl, cmd, &ifr);
2262 #ifdef IFLA_IPTUN_MAX
2263 static int system_add_ip6_tunnel(const char *name, const unsigned int link,
2264 struct blob_attr **tb)
2266 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2267 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2268 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2269 struct blob_attr *cur;
2270 int ret = 0, ttl = 0;
2275 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2276 nla_put_string(nlm, IFLA_IFNAME, name);
2279 nla_put_u32(nlm, IFLA_LINK, link);
2281 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2287 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2288 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2295 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2297 if ((cur = tb[TUNNEL_ATTR_TTL]))
2298 ttl = blobmsg_get_u32(cur);
2300 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2301 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2302 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
2304 struct in6_addr in6buf;
2305 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2306 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2310 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2313 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2314 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2318 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2321 #ifdef IFLA_IPTUN_FMR_MAX
2322 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2323 struct blob_attr *dcur;
2324 unsigned drem, fmrcnt = 0;
2325 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2332 blobmsg_for_each_attr(dcur, cur, drem) {
2333 if (blobmsg_type(dcur) != BLOBMSG_TYPE_ARRAY ||
2334 strcmp(blobmsg_name(dcur), "fmrs") ||
2335 blobmsg_check_array(dcur, BLOBMSG_TYPE_UNSPEC) <= 0)
2338 struct blob_attr *rcur;
2340 blobmsg_for_each_attr(rcur, dcur, rrem) {
2341 struct blob_attr *tb_fmr[__FMR_DATA_ATTR_MAX], *tb_cur;
2342 struct in6_addr ip6prefix;
2343 struct in_addr ip4prefix;
2344 unsigned ip4len, ip6len, ealen, offset;
2346 blobmsg_parse(fmr_data_attr_list.params, __FMR_DATA_ATTR_MAX, tb_fmr,
2347 blobmsg_data(rcur), blobmsg_len(rcur));
2349 if (!(tb_cur = tb_fmr[FMR_DATA_PREFIX6]) ||
2350 !parse_ip_and_netmask(AF_INET6,
2351 blobmsg_data(tb_cur), &ip6prefix,
2357 if (!(tb_cur = tb_fmr[FMR_DATA_PREFIX4]) ||
2358 !parse_ip_and_netmask(AF_INET,
2359 blobmsg_data(tb_cur), &ip4prefix,
2365 if (!(tb_cur = tb_fmr[FMR_DATA_EALEN])) {
2369 ealen = blobmsg_get_u32(tb_cur);
2371 if (!(tb_cur = tb_fmr[FMR_DATA_OFFSET])) {
2375 offset = blobmsg_get_u32(tb_cur);
2377 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2383 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2384 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2385 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2386 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2387 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2388 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2390 nla_nest_end(nlm, rule);
2393 nla_nest_end(nlm, fmrs);
2397 nla_nest_end(nlm, infodata);
2398 nla_nest_end(nlm, linkinfo);
2400 return system_rtnl_call(nlm);
2408 #ifdef IFLA_IPTUN_MAX
2409 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
2410 static int system_add_gre_tunnel(const char *name, const char *kind,
2411 const unsigned int link, struct blob_attr **tb, bool v6)
2414 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2415 struct blob_attr *cur;
2416 uint32_t ikey = 0, okey = 0, flags = 0, flowinfo = 0;
2417 uint16_t iflags = 0, oflags = 0;
2419 int ret = 0, ttl = 0;
2421 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2425 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2426 nla_put_string(nlm, IFLA_IFNAME, name);
2428 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2434 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2435 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2442 nla_put_u32(nlm, IFLA_GRE_LINK, link);
2444 if ((cur = tb[TUNNEL_ATTR_TTL]))
2445 ttl = blobmsg_get_u32(cur);
2447 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2448 char *str = blobmsg_get_string(cur);
2449 if (strcmp(str, "inherit")) {
2452 if (!system_tos_aton(str, &uval)) {
2458 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
2463 flags |= IP6_TNL_F_USE_ORIG_TCLASS;
2469 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2470 struct blob_attr *tb_data[__GRE_DATA_ATTR_MAX];
2472 blobmsg_parse(gre_data_attr_list.params, __GRE_DATA_ATTR_MAX, tb_data,
2473 blobmsg_data(cur), blobmsg_len(cur));
2475 if ((cur = tb_data[GRE_DATA_IKEY])) {
2476 if ((ikey = blobmsg_get_u32(cur)))
2480 if ((cur = tb_data[GRE_DATA_OKEY])) {
2481 if ((okey = blobmsg_get_u32(cur)))
2485 if ((cur = tb_data[GRE_DATA_ICSUM])) {
2486 if (blobmsg_get_bool(cur))
2490 if ((cur = tb_data[GRE_DATA_OCSUM])) {
2491 if (blobmsg_get_bool(cur))
2495 if ((cur = tb_data[GRE_DATA_ISEQNO])) {
2496 if (blobmsg_get_bool(cur))
2500 if ((cur = tb[GRE_DATA_OSEQNO])) {
2501 if (blobmsg_get_bool(cur))
2507 struct in6_addr in6buf;
2508 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2509 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2513 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
2516 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2517 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2521 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
2523 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, 4);
2526 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
2529 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags);
2534 struct in_addr inbuf;
2537 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2538 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2542 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
2545 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2546 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2550 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
2552 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
2554 okey = inbuf.s_addr;
2559 ikey = inbuf.s_addr;
2565 if ((cur = tb[TUNNEL_ATTR_DF]))
2566 set_df = blobmsg_get_bool(cur);
2569 /* ttl != 0 and nopmtudisc are incompatible */
2577 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
2579 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
2583 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
2586 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
2589 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
2592 nla_put_u32(nlm, IFLA_GRE_OKEY, htonl(okey));
2595 nla_put_u32(nlm, IFLA_GRE_IKEY, htonl(ikey));
2597 nla_nest_end(nlm, infodata);
2598 nla_nest_end(nlm, linkinfo);
2600 return system_rtnl_call(nlm);
2609 static int system_add_vti_tunnel(const char *name, const char *kind,
2610 const unsigned int link, struct blob_attr **tb, bool v6)
2613 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2614 struct blob_attr *cur;
2617 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2621 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2622 nla_put_string(nlm, IFLA_IFNAME, name);
2624 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2630 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2631 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2638 nla_put_u32(nlm, IFLA_VTI_LINK, link);
2641 struct in6_addr in6buf;
2642 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2643 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2647 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(in6buf), &in6buf);
2650 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2651 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2655 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(in6buf), &in6buf);
2659 struct in_addr inbuf;
2661 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2662 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2666 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(inbuf), &inbuf);
2669 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2670 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2674 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(inbuf), &inbuf);
2679 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2680 struct blob_attr *tb_data[__VTI_DATA_ATTR_MAX];
2681 uint32_t ikey = 0, okey = 0;
2683 blobmsg_parse(vti_data_attr_list.params, __VTI_DATA_ATTR_MAX, tb_data,
2684 blobmsg_data(cur), blobmsg_len(cur));
2686 if ((cur = tb_data[VTI_DATA_IKEY])) {
2687 if ((ikey = blobmsg_get_u32(cur)))
2688 nla_put_u32(nlm, IFLA_VTI_IKEY, htonl(ikey));
2691 if ((cur = tb_data[VTI_DATA_OKEY])) {
2692 if ((okey = blobmsg_get_u32(cur)))
2693 nla_put_u32(nlm, IFLA_VTI_OKEY, htonl(okey));
2697 nla_nest_end(nlm, infodata);
2698 nla_nest_end(nlm, linkinfo);
2700 return system_rtnl_call(nlm);
2708 #ifdef IFLA_VXLAN_MAX
2709 static int system_add_vxlan(const char *name, const unsigned int link, struct blob_attr **tb, bool v6)
2711 struct blob_attr *tb_data[__VXLAN_DATA_ATTR_MAX];
2713 struct nlattr *linkinfo, *data;
2714 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
2715 struct blob_attr *cur;
2718 if ((cur = tb[TUNNEL_ATTR_DATA]))
2719 blobmsg_parse(vxlan_data_attr_list.params, __VXLAN_DATA_ATTR_MAX, tb_data,
2720 blobmsg_data(cur), blobmsg_len(cur));
2724 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
2729 nlmsg_append(msg, &iim, sizeof(iim), 0);
2731 nla_put_string(msg, IFLA_IFNAME, name);
2733 if ((cur = tb_data[VXLAN_DATA_ATTR_MACADDR])) {
2734 struct ether_addr *ea = ether_aton(blobmsg_get_string(cur));
2740 nla_put(msg, IFLA_ADDRESS, ETH_ALEN, ea);
2743 if ((cur = tb[TUNNEL_ATTR_MTU])) {
2744 uint32_t mtu = blobmsg_get_u32(cur);
2745 nla_put_u32(msg, IFLA_MTU, mtu);
2748 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO))) {
2753 nla_put_string(msg, IFLA_INFO_KIND, "vxlan");
2755 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) {
2761 nla_put_u32(msg, IFLA_VXLAN_LINK, link);
2763 if ((cur = tb_data[VXLAN_DATA_ATTR_ID])) {
2764 uint32_t id = blobmsg_get_u32(cur);
2765 if (id >= (1u << 24) - 1) {
2770 nla_put_u32(msg, IFLA_VXLAN_ID, id);
2774 struct in6_addr in6buf;
2775 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2776 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2780 nla_put(msg, IFLA_VXLAN_LOCAL6, sizeof(in6buf), &in6buf);
2783 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2784 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2788 nla_put(msg, IFLA_VXLAN_GROUP6, sizeof(in6buf), &in6buf);
2791 struct in_addr inbuf;
2793 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2794 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2798 nla_put(msg, IFLA_VXLAN_LOCAL, sizeof(inbuf), &inbuf);
2801 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2802 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2806 nla_put(msg, IFLA_VXLAN_GROUP, sizeof(inbuf), &inbuf);
2810 uint32_t port = 4789;
2811 if ((cur = tb_data[VXLAN_DATA_ATTR_PORT])) {
2812 port = blobmsg_get_u32(cur);
2813 if (port < 1 || port > 65535) {
2818 nla_put_u16(msg, IFLA_VXLAN_PORT, htons(port));
2820 if ((cur = tb_data[VXLAN_DATA_ATTR_RXCSUM])) {
2821 bool rxcsum = blobmsg_get_bool(cur);
2822 nla_put_u8(msg, IFLA_VXLAN_UDP_ZERO_CSUM6_RX, !rxcsum);
2825 if ((cur = tb_data[VXLAN_DATA_ATTR_TXCSUM])) {
2826 bool txcsum = blobmsg_get_bool(cur);
2827 nla_put_u8(msg, IFLA_VXLAN_UDP_CSUM, txcsum);
2828 nla_put_u8(msg, IFLA_VXLAN_UDP_ZERO_CSUM6_TX, !txcsum);
2831 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2832 char *str = blobmsg_get_string(cur);
2835 if (strcmp(str, "inherit")) {
2836 if (!system_tos_aton(str, &tos)) {
2842 nla_put_u8(msg, IFLA_VXLAN_TOS, tos);
2845 if ((cur = tb[TUNNEL_ATTR_TTL])) {
2846 uint32_t ttl = blobmsg_get_u32(cur);
2847 if (ttl < 1 || ttl > 255) {
2852 nla_put_u8(msg, IFLA_VXLAN_TTL, ttl);
2855 nla_nest_end(msg, data);
2856 nla_nest_end(msg, linkinfo);
2858 ret = system_rtnl_call(msg);
2860 D(SYSTEM, "Error adding vxlan '%s': %d\n", name, ret);
2870 static int system_add_sit_tunnel(const char *name, const unsigned int link, struct blob_attr **tb)
2872 struct blob_attr *cur;
2875 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
2879 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2880 struct blob_attr *tb_data[__SIXRD_DATA_ATTR_MAX];
2882 struct ip_tunnel_6rd p6;
2884 blobmsg_parse(sixrd_data_attr_list.params, __SIXRD_DATA_ATTR_MAX, tb_data,
2885 blobmsg_data(cur), blobmsg_len(cur));
2887 memset(&p6, 0, sizeof(p6));
2889 if ((cur = tb_data[SIXRD_DATA_PREFIX])) {
2890 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
2891 &p6.prefix, &mask) || mask > 128) {
2896 p6.prefixlen = mask;
2899 if ((cur = tb_data[SIXRD_DATA_RELAY_PREFIX])) {
2900 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
2901 &p6.relay_prefix, &mask) || mask > 32) {
2906 p6.relay_prefixlen = mask;
2909 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
2919 __system_del_ip_tunnel(name, tb);
2923 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
2925 struct blob_attr *cur;
2927 struct ip_tunnel_parm p = {
2936 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
2937 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
2940 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
2941 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
2944 if ((cur = tb[TUNNEL_ATTR_DF]))
2945 set_df = blobmsg_get_bool(cur);
2947 if ((cur = tb[TUNNEL_ATTR_TTL]))
2948 p.iph.ttl = blobmsg_get_u32(cur);
2950 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2951 char *str = blobmsg_get_string(cur);
2952 if (strcmp(str, "inherit")) {
2955 if (!system_tos_aton(str, &uval))
2963 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
2964 /* ttl !=0 and nopmtudisc are incompatible */
2965 if (p.iph.ttl && p.iph.frag_off == 0)
2968 strncpy(p.name, name, sizeof(p.name));
2970 switch (p.iph.protocol) {
2972 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
2974 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
2981 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
2983 struct blob_attr *cur;
2986 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2988 str = blobmsg_data(cur);
2990 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
2991 !strcmp(str, "greip6") || !strcmp(str, "gretapip6") ||
2992 !strcmp(str, "vtiip") || !strcmp(str, "vtiip6") ||
2993 !strcmp(str, "vxlan") || !strcmp(str, "vxlan6"))
2994 return system_link_del(name);
2996 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
2999 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
3001 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
3003 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
3004 blob_data(attr), blob_len(attr));
3006 return __system_del_ip_tunnel(name, tb);
3009 int system_update_ipv6_mtu(struct device *dev, int mtu)
3015 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
3018 fd = open(buf, O_RDWR);
3023 ssize_t len = read(fd, buf, sizeof(buf) - 1);
3030 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) > 0)
3039 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
3041 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
3042 struct blob_attr *cur;
3045 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
3046 blob_data(attr), blob_len(attr));
3048 __system_del_ip_tunnel(name, tb);
3050 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
3052 str = blobmsg_data(cur);
3054 unsigned int ttl = 0;
3055 if ((cur = tb[TUNNEL_ATTR_TTL])) {
3056 ttl = blobmsg_get_u32(cur);
3061 unsigned int link = 0;
3062 if ((cur = tb[TUNNEL_ATTR_LINK])) {
3063 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
3067 if (iface->l3_dev.dev)
3068 link = iface->l3_dev.dev->ifindex;
3071 if (!strcmp(str, "sit"))
3072 return system_add_sit_tunnel(name, link, tb);
3073 #ifdef IFLA_IPTUN_MAX
3074 else if (!strcmp(str, "ipip6")) {
3075 return system_add_ip6_tunnel(name, link, tb);
3076 } else if (!strcmp(str, "greip")) {
3077 return system_add_gre_tunnel(name, "gre", link, tb, false);
3078 } else if (!strcmp(str, "gretapip")) {
3079 return system_add_gre_tunnel(name, "gretap", link, tb, false);
3080 } else if (!strcmp(str, "greip6")) {
3081 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
3082 } else if (!strcmp(str, "gretapip6")) {
3083 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
3085 } else if (!strcmp(str, "vtiip")) {
3086 return system_add_vti_tunnel(name, "vti", link, tb, false);
3087 } else if (!strcmp(str, "vtiip6")) {
3088 return system_add_vti_tunnel(name, "vti6", link, tb, true);
3090 #ifdef IFLA_VXLAN_MAX
3091 } else if(!strcmp(str, "vxlan")) {
3092 return system_add_vxlan(name, link, tb, false);
3093 } else if(!strcmp(str, "vxlan6")) {
3094 return system_add_vxlan(name, link, tb, true);
3097 } else if (!strcmp(str, "ipip")) {
3098 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);