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) - 1);
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) - 1);
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) - 1);
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 if (ioctl(sock_ioctl, SIOCSIFVLAN, &ifr) < 0)
1257 ifr.cmd = DEL_VLAN_CMD;
1260 ifr.cmd = ADD_VLAN_CMD;
1263 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
1264 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
1267 int system_vlan_add(struct device *dev, int id)
1269 return system_vlan(dev, id);
1272 int system_vlan_del(struct device *dev)
1274 return system_vlan(dev, -1);
1277 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
1280 struct nlattr *linkinfo, *data;
1281 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
1284 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1289 nlmsg_append(msg, &iim, sizeof(iim), 0);
1290 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
1291 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
1293 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1294 goto nla_put_failure;
1296 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
1298 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1299 goto nla_put_failure;
1301 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
1303 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
1304 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
1306 if(cfg->proto == VLAN_PROTO_8021AD)
1307 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);
1310 nla_nest_end(msg, data);
1311 nla_nest_end(msg, linkinfo);
1313 rv = system_rtnl_call(msg);
1315 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
1324 int system_vlandev_del(struct device *vlandev)
1326 return system_link_del(vlandev->ifname);
1330 system_if_get_settings(struct device *dev, struct device_settings *s)
1335 memset(&ifr, 0, sizeof(ifr));
1336 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
1338 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
1339 s->mtu = ifr.ifr_mtu;
1340 s->flags |= DEV_OPT_MTU;
1343 s->mtu6 = system_update_ipv6_mtu(dev, 0);
1345 s->flags |= DEV_OPT_MTU6;
1347 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
1348 s->txqueuelen = ifr.ifr_qlen;
1349 s->flags |= DEV_OPT_TXQUEUELEN;
1352 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
1353 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
1354 s->flags |= DEV_OPT_MACADDR;
1357 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
1358 s->ipv6 = !strtoul(buf, NULL, 0);
1359 s->flags |= DEV_OPT_IPV6;
1362 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
1363 s->promisc = ifr.ifr_flags & IFF_PROMISC;
1364 s->flags |= DEV_OPT_PROMISC;
1366 s->multicast = ifr.ifr_flags & IFF_MULTICAST;
1367 s->flags |= DEV_OPT_MULTICAST;
1370 if (!system_get_rpfilter(dev, buf, sizeof(buf))) {
1371 s->rpfilter = strtoul(buf, NULL, 0);
1372 s->flags |= DEV_OPT_RPFILTER;
1375 if (!system_get_acceptlocal(dev, buf, sizeof(buf))) {
1376 s->acceptlocal = strtoul(buf, NULL, 0);
1377 s->flags |= DEV_OPT_ACCEPTLOCAL;
1380 if (!system_get_igmpversion(dev, buf, sizeof(buf))) {
1381 s->igmpversion = strtoul(buf, NULL, 0);
1382 s->flags |= DEV_OPT_IGMPVERSION;
1385 if (!system_get_mldversion(dev, buf, sizeof(buf))) {
1386 s->mldversion = strtoul(buf, NULL, 0);
1387 s->flags |= DEV_OPT_MLDVERSION;
1390 if (!system_get_neigh4reachabletime(dev, buf, sizeof(buf))) {
1391 s->neigh4reachabletime = strtoul(buf, NULL, 0);
1392 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1395 if (!system_get_neigh6reachabletime(dev, buf, sizeof(buf))) {
1396 s->neigh6reachabletime = strtoul(buf, NULL, 0);
1397 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1400 if (!system_get_neigh4locktime(dev, buf, sizeof(buf))) {
1401 s->neigh4locktime = strtol(buf, NULL, 0);
1402 s->flags |= DEV_OPT_NEIGHLOCKTIME;
1405 if (!system_get_neigh4gcstaletime(dev, buf, sizeof(buf))) {
1406 s->neigh4gcstaletime = strtoul(buf, NULL, 0);
1407 s->flags |= DEV_OPT_NEIGHGCSTALETIME;
1410 if (!system_get_neigh6gcstaletime(dev, buf, sizeof(buf))) {
1411 s->neigh6gcstaletime = strtoul(buf, NULL, 0);
1412 s->flags |= DEV_OPT_NEIGHGCSTALETIME;
1415 if (!system_get_dadtransmits(dev, buf, sizeof(buf))) {
1416 s->dadtransmits = strtoul(buf, NULL, 0);
1417 s->flags |= DEV_OPT_DADTRANSMITS;
1420 if (!system_get_sendredirects(dev, buf, sizeof(buf))) {
1421 s->sendredirects = strtoul(buf, NULL, 0);
1422 s->flags |= DEV_OPT_SENDREDIRECTS;
1427 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
1432 memset(&ifr, 0, sizeof(ifr));
1433 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
1434 if (s->flags & DEV_OPT_MTU & apply_mask) {
1435 ifr.ifr_mtu = s->mtu;
1436 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
1437 s->flags &= ~DEV_OPT_MTU;
1439 if (s->flags & DEV_OPT_MTU6 & apply_mask) {
1440 system_update_ipv6_mtu(dev, s->mtu6);
1442 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
1443 ifr.ifr_qlen = s->txqueuelen;
1444 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
1445 s->flags &= ~DEV_OPT_TXQUEUELEN;
1447 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
1448 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
1449 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
1450 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
1451 s->flags &= ~DEV_OPT_MACADDR;
1453 if (s->flags & DEV_OPT_IPV6 & apply_mask)
1454 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
1455 if (s->flags & DEV_OPT_PROMISC & apply_mask) {
1456 if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
1457 !s->promisc ? IFF_PROMISC : 0) < 0)
1458 s->flags &= ~DEV_OPT_PROMISC;
1460 if (s->flags & DEV_OPT_RPFILTER & apply_mask) {
1461 snprintf(buf, sizeof(buf), "%u", s->rpfilter);
1462 system_set_rpfilter(dev, buf);
1464 if (s->flags & DEV_OPT_ACCEPTLOCAL & apply_mask)
1465 system_set_acceptlocal(dev, s->acceptlocal ? "1" : "0");
1466 if (s->flags & DEV_OPT_IGMPVERSION & apply_mask) {
1467 snprintf(buf, sizeof(buf), "%u", s->igmpversion);
1468 system_set_igmpversion(dev, buf);
1470 if (s->flags & DEV_OPT_MLDVERSION & apply_mask) {
1471 snprintf(buf, sizeof(buf), "%u", s->mldversion);
1472 system_set_mldversion(dev, buf);
1474 if (s->flags & DEV_OPT_NEIGHREACHABLETIME & apply_mask) {
1475 snprintf(buf, sizeof(buf), "%u", s->neigh4reachabletime);
1476 system_set_neigh4reachabletime(dev, buf);
1477 snprintf(buf, sizeof(buf), "%u", s->neigh6reachabletime);
1478 system_set_neigh6reachabletime(dev, buf);
1480 if (s->flags & DEV_OPT_NEIGHLOCKTIME & apply_mask) {
1481 snprintf(buf, sizeof(buf), "%d", s->neigh4locktime);
1482 system_set_neigh4locktime(dev, buf);
1484 if (s->flags & DEV_OPT_NEIGHGCSTALETIME & apply_mask) {
1485 snprintf(buf, sizeof(buf), "%u", s->neigh4gcstaletime);
1486 system_set_neigh4gcstaletime(dev, buf);
1487 snprintf(buf, sizeof(buf), "%u", s->neigh6gcstaletime);
1488 system_set_neigh6gcstaletime(dev, buf);
1490 if (s->flags & DEV_OPT_DADTRANSMITS & apply_mask) {
1491 snprintf(buf, sizeof(buf), "%u", s->dadtransmits);
1492 system_set_dadtransmits(dev, buf);
1494 if (s->flags & DEV_OPT_MULTICAST & apply_mask) {
1495 if (system_if_flags(dev->ifname, s->multicast ? IFF_MULTICAST : 0,
1496 !s->multicast ? IFF_MULTICAST : 0) < 0)
1497 s->flags &= ~DEV_OPT_MULTICAST;
1499 if (s->flags & DEV_OPT_SENDREDIRECTS & apply_mask)
1500 system_set_sendredirects(dev, s->sendredirects ? "1" : "0");
1503 int system_if_up(struct device *dev)
1505 system_if_get_settings(dev, &dev->orig_settings);
1506 /* Only keep orig settings based on what needs to be set */
1507 dev->orig_settings.valid_flags = dev->orig_settings.flags;
1508 dev->orig_settings.flags &= dev->settings.flags;
1509 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
1510 return system_if_flags(dev->ifname, IFF_UP, 0);
1513 int system_if_down(struct device *dev)
1515 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
1516 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
1520 struct if_check_data {
1526 #ifndef IFF_LOWER_UP
1527 #define IFF_LOWER_UP 0x10000
1530 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1532 struct nlmsghdr *nh = nlmsg_hdr(msg);
1533 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1534 struct if_check_data *chk = (struct if_check_data *)arg;
1536 if (nh->nlmsg_type != RTM_NEWLINK)
1539 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1540 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1545 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1547 struct if_check_data *chk = (struct if_check_data *)arg;
1552 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1554 struct if_check_data *chk = (struct if_check_data *)arg;
1556 device_set_present(chk->dev, false);
1557 device_set_link(chk->dev, false);
1558 chk->pending = err->error;
1563 int system_if_check(struct device *dev)
1565 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1567 struct ifinfomsg ifi = {
1568 .ifi_family = AF_UNSPEC,
1571 struct if_check_data chk = {
1580 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1584 if (nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1585 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1588 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1589 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1590 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1592 nl_send_auto_complete(sock_rtnl, msg);
1593 while (chk.pending > 0)
1594 nl_recvmsgs(sock_rtnl, cb);
1606 system_if_get_parent(struct device *dev)
1608 char buf[64], *devname;
1609 int ifindex, iflink, len;
1612 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1613 f = fopen(buf, "r");
1617 len = fread(buf, 1, sizeof(buf) - 1, f);
1624 iflink = strtoul(buf, NULL, 0);
1625 ifindex = system_if_resolve(dev);
1626 if (!iflink || iflink == ifindex)
1629 devname = if_indextoname(iflink, buf);
1633 return device_get(devname, true);
1637 read_string_file(int dir_fd, const char *file, char *buf, int len)
1643 fd = openat(dir_fd, file, O_RDONLY);
1648 len = read(fd, buf, len - 1);
1652 } else if (len > 0) {
1655 c = strchr(buf, '\n');
1668 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1673 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1675 *val = strtoull(buf, NULL, 0);
1680 /* Assume advertised flags == supported flags */
1681 static const struct {
1684 } ethtool_link_modes[] = {
1685 { ADVERTISED_10baseT_Half, "10H" },
1686 { ADVERTISED_10baseT_Full, "10F" },
1687 { ADVERTISED_100baseT_Half, "100H" },
1688 { ADVERTISED_100baseT_Full, "100F" },
1689 { ADVERTISED_1000baseT_Half, "1000H" },
1690 { ADVERTISED_1000baseT_Full, "1000F" },
1693 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1696 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1697 if (mask & ethtool_link_modes[i].mask)
1698 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1703 system_if_force_external(const char *ifname)
1708 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1709 return stat(buf, &s) == 0;
1713 system_if_dump_info(struct device *dev, struct blob_buf *b)
1715 struct ethtool_cmd ecmd;
1720 memset(&ecmd, 0, sizeof(ecmd));
1721 memset(&ifr, 0, sizeof(ifr));
1722 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
1723 ifr.ifr_data = (caddr_t) &ecmd;
1724 ecmd.cmd = ETHTOOL_GSET;
1726 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1727 c = blobmsg_open_array(b, "link-advertising");
1728 system_add_link_modes(b, ecmd.advertising);
1729 blobmsg_close_array(b, c);
1731 c = blobmsg_open_array(b, "link-partner-advertising");
1732 system_add_link_modes(b, ecmd.lp_advertising);
1733 blobmsg_close_array(b, c);
1735 c = blobmsg_open_array(b, "link-supported");
1736 system_add_link_modes(b, ecmd.supported);
1737 blobmsg_close_array(b, c);
1739 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1740 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1741 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1742 blobmsg_add_string_buffer(b);
1744 blobmsg_add_u8(b, "autoneg", !!ecmd.autoneg);
1751 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1753 const char *const counters[] = {
1754 "collisions", "rx_frame_errors", "tx_compressed",
1755 "multicast", "rx_length_errors", "tx_dropped",
1756 "rx_bytes", "rx_missed_errors", "tx_errors",
1757 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1758 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1759 "rx_dropped", "tx_aborted_errors", "tx_packets",
1760 "rx_errors", "tx_bytes", "tx_window_errors",
1761 "rx_fifo_errors", "tx_carrier_errors",
1768 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1769 stats_dir = open(buf, O_DIRECTORY);
1773 for (i = 0; i < ARRAY_SIZE(counters); i++)
1774 if (read_uint64_file(stats_dir, counters[i], &val))
1775 blobmsg_add_u64(b, counters[i], val);
1781 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1783 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1784 int alen = v4 ? 4 : 16;
1785 unsigned int flags = 0;
1786 struct ifaddrmsg ifa = {
1787 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1788 .ifa_prefixlen = addr->mask,
1789 .ifa_index = dev->ifindex,
1793 if (cmd == RTM_NEWADDR)
1794 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1796 msg = nlmsg_alloc_simple(cmd, flags);
1800 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1801 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1803 if (addr->broadcast)
1804 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1805 if (addr->point_to_point)
1806 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1808 time_t now = system_get_rtime();
1809 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1811 if (addr->preferred_until) {
1812 int64_t preferred = addr->preferred_until - now;
1815 else if (preferred > UINT32_MAX)
1816 preferred = UINT32_MAX;
1818 cinfo.ifa_prefered = preferred;
1821 if (addr->valid_until) {
1822 int64_t valid = addr->valid_until - now;
1827 else if (valid > UINT32_MAX)
1830 cinfo.ifa_valid = valid;
1833 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1835 if (cmd == RTM_NEWADDR && (addr->flags & DEVADDR_OFFLINK))
1836 nla_put_u32(msg, IFA_FLAGS, IFA_F_NOPREFIXROUTE);
1839 return system_rtnl_call(msg);
1842 int system_add_address(struct device *dev, struct device_addr *addr)
1844 return system_addr(dev, addr, RTM_NEWADDR);
1847 int system_del_address(struct device *dev, struct device_addr *addr)
1849 return system_addr(dev, addr, RTM_DELADDR);
1852 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1854 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1856 unsigned int flags = 0;
1859 have_gw = !!route->nexthop.in.s_addr;
1861 have_gw = route->nexthop.in6.s6_addr32[0] ||
1862 route->nexthop.in6.s6_addr32[1] ||
1863 route->nexthop.in6.s6_addr32[2] ||
1864 route->nexthop.in6.s6_addr32[3];
1866 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1867 ? route->table : RT_TABLE_MAIN;
1869 struct rtmsg rtm = {
1870 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1871 .rtm_dst_len = route->mask,
1872 .rtm_src_len = route->sourcemask,
1873 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1874 .rtm_protocol = (route->flags & DEVROUTE_PROTO) ? route->proto : RTPROT_STATIC,
1875 .rtm_scope = RT_SCOPE_NOWHERE,
1876 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1877 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1881 if (cmd == RTM_NEWROUTE) {
1882 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1884 if (!dev) { // Add null-route
1885 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1886 rtm.rtm_type = RTN_UNREACHABLE;
1889 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1892 if (route->flags & DEVROUTE_TYPE) {
1893 rtm.rtm_type = route->type;
1894 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
1895 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
1896 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
1897 rtm.rtm_table = RT_TABLE_LOCAL;
1900 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT) {
1901 rtm.rtm_scope = RT_SCOPE_HOST;
1902 } else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
1903 rtm.rtm_type == RTN_ANYCAST) {
1904 rtm.rtm_scope = RT_SCOPE_LINK;
1905 } else if (rtm.rtm_type == RTN_BLACKHOLE || rtm.rtm_type == RTN_UNREACHABLE ||
1906 rtm.rtm_type == RTN_PROHIBIT || rtm.rtm_type == RTN_FAILED_POLICY ||
1907 rtm.rtm_type == RTN_THROW) {
1908 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1913 msg = nlmsg_alloc_simple(cmd, flags);
1917 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1920 nla_put(msg, RTA_DST, alen, &route->addr);
1922 if (route->sourcemask) {
1923 if (rtm.rtm_family == AF_INET)
1924 nla_put(msg, RTA_PREFSRC, alen, &route->source);
1926 nla_put(msg, RTA_SRC, alen, &route->source);
1929 if (route->metric > 0)
1930 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1933 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1936 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1939 nla_put_u32(msg, RTA_TABLE, table);
1941 if (route->flags & DEVROUTE_MTU) {
1942 struct nlattr *metrics;
1944 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1945 goto nla_put_failure;
1947 nla_put_u32(msg, RTAX_MTU, route->mtu);
1949 nla_nest_end(msg, metrics);
1952 return system_rtnl_call(msg);
1959 int system_add_route(struct device *dev, struct device_route *route)
1961 return system_rt(dev, route, RTM_NEWROUTE);
1964 int system_del_route(struct device *dev, struct device_route *route)
1966 return system_rt(dev, route, RTM_DELROUTE);
1969 int system_flush_routes(void)
1971 const char *names[] = {
1972 "/proc/sys/net/ipv4/route/flush",
1973 "/proc/sys/net/ipv6/route/flush"
1977 for (i = 0; i < ARRAY_SIZE(names); i++) {
1978 fd = open(names[i], O_WRONLY);
1982 if (write(fd, "-1", 2)) {}
1988 bool system_resolve_rt_type(const char *type, unsigned int *id)
1990 return system_rtn_aton(type, id);
1993 bool system_resolve_rt_proto(const char *type, unsigned int *id)
1997 unsigned int n, proto = 256;
1998 n = strtoul(type, &e, 0);
1999 if (!*e && e != type)
2001 else if (!strcmp(type, "unspec"))
2002 proto = RTPROT_UNSPEC;
2003 else if (!strcmp(type, "kernel"))
2004 proto = RTPROT_KERNEL;
2005 else if (!strcmp(type, "boot"))
2006 proto = RTPROT_BOOT;
2007 else if (!strcmp(type, "static"))
2008 proto = RTPROT_STATIC;
2009 else if ((f = fopen("/etc/iproute2/rt_protos", "r")) != NULL) {
2010 while (fgets(buf, sizeof(buf) - 1, f) != NULL) {
2011 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
2014 n = strtoul(e, NULL, 10);
2015 e = strtok(NULL, " \t\n");
2017 if (e && !strcmp(e, type)) {
2032 bool system_resolve_rt_table(const char *name, unsigned int *id)
2036 unsigned int n, table = RT_TABLE_UNSPEC;
2038 /* first try to parse table as number */
2039 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
2042 /* handle well known aliases */
2043 else if (!strcmp(name, "default"))
2044 table = RT_TABLE_DEFAULT;
2045 else if (!strcmp(name, "main"))
2046 table = RT_TABLE_MAIN;
2047 else if (!strcmp(name, "local"))
2048 table = RT_TABLE_LOCAL;
2050 /* try to look up name in /etc/iproute2/rt_tables */
2051 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
2053 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
2055 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
2058 n = strtoul(e, NULL, 10);
2059 e = strtok(NULL, " \t\n");
2061 if (e && !strcmp(e, name))
2071 if (table == RT_TABLE_UNSPEC)
2078 bool system_is_default_rt_table(unsigned int id)
2080 return (id == RT_TABLE_MAIN);
2083 bool system_resolve_rpfilter(const char *filter, unsigned int *id)
2088 if (!strcmp(filter, "strict"))
2090 else if (!strcmp(filter, "loose"))
2093 n = strtoul(filter, &e, 0);
2094 if (*e || e == filter || n > 2)
2102 static int system_iprule(struct iprule *rule, int cmd)
2104 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
2107 struct rtmsg rtm = {
2108 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
2109 .rtm_protocol = RTPROT_STATIC,
2110 .rtm_scope = RT_SCOPE_UNIVERSE,
2111 .rtm_table = RT_TABLE_UNSPEC,
2112 .rtm_type = RTN_UNSPEC,
2116 if (cmd == RTM_NEWRULE)
2117 rtm.rtm_type = RTN_UNICAST;
2120 rtm.rtm_flags |= FIB_RULE_INVERT;
2122 if (rule->flags & IPRULE_SRC)
2123 rtm.rtm_src_len = rule->src_mask;
2125 if (rule->flags & IPRULE_DEST)
2126 rtm.rtm_dst_len = rule->dest_mask;
2128 if (rule->flags & IPRULE_TOS)
2129 rtm.rtm_tos = rule->tos;
2131 if (rule->flags & IPRULE_LOOKUP) {
2132 if (rule->lookup < 256)
2133 rtm.rtm_table = rule->lookup;
2136 if (rule->flags & IPRULE_ACTION)
2137 rtm.rtm_type = rule->action;
2138 else if (rule->flags & IPRULE_GOTO)
2139 rtm.rtm_type = FR_ACT_GOTO;
2140 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
2141 rtm.rtm_type = FR_ACT_NOP;
2143 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
2148 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
2150 if (rule->flags & IPRULE_IN)
2151 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
2153 if (rule->flags & IPRULE_OUT)
2154 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
2156 if (rule->flags & IPRULE_SRC)
2157 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
2159 if (rule->flags & IPRULE_DEST)
2160 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
2162 if (rule->flags & IPRULE_PRIORITY)
2163 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
2164 else if (cmd == RTM_NEWRULE)
2165 nla_put_u32(msg, FRA_PRIORITY, rule->order);
2167 if (rule->flags & IPRULE_FWMARK)
2168 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
2170 if (rule->flags & IPRULE_FWMASK)
2171 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
2173 if (rule->flags & IPRULE_LOOKUP) {
2174 if (rule->lookup >= 256)
2175 nla_put_u32(msg, FRA_TABLE, rule->lookup);
2178 if (rule->flags & IPRULE_SUP_PREFIXLEN)
2179 nla_put_u32(msg, FRA_SUPPRESS_PREFIXLEN, rule->sup_prefixlen);
2181 if (rule->flags & IPRULE_GOTO)
2182 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
2184 return system_rtnl_call(msg);
2187 int system_add_iprule(struct iprule *rule)
2189 return system_iprule(rule, RTM_NEWRULE);
2192 int system_del_iprule(struct iprule *rule)
2194 return system_iprule(rule, RTM_DELRULE);
2197 int system_flush_iprules(void)
2202 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
2203 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
2205 memset(&rule, 0, sizeof(rule));
2208 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2211 rule.lookup = RT_TABLE_LOCAL;
2212 rv |= system_iprule(&rule, RTM_NEWRULE);
2214 rule.priority = 32766;
2215 rule.lookup = RT_TABLE_MAIN;
2216 rv |= system_iprule(&rule, RTM_NEWRULE);
2218 rule.priority = 32767;
2219 rule.lookup = RT_TABLE_DEFAULT;
2220 rv |= system_iprule(&rule, RTM_NEWRULE);
2223 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2226 rule.lookup = RT_TABLE_LOCAL;
2227 rv |= system_iprule(&rule, RTM_NEWRULE);
2229 rule.priority = 32766;
2230 rule.lookup = RT_TABLE_MAIN;
2231 rv |= system_iprule(&rule, RTM_NEWRULE);
2236 bool system_resolve_iprule_action(const char *action, unsigned int *id)
2238 return system_rtn_aton(action, id);
2241 time_t system_get_rtime(void)
2246 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
2249 if (gettimeofday(&tv, NULL) == 0)
2256 #define IP_DF 0x4000
2259 static int tunnel_ioctl(const char *name, int cmd, void *p)
2263 memset(&ifr, 0, sizeof(ifr));
2264 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name) - 1);
2265 ifr.ifr_ifru.ifru_data = p;
2266 return ioctl(sock_ioctl, cmd, &ifr);
2269 #ifdef IFLA_IPTUN_MAX
2270 static int system_add_ip6_tunnel(const char *name, const unsigned int link,
2271 struct blob_attr **tb)
2273 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2274 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2275 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2276 struct blob_attr *cur;
2277 int ret = 0, ttl = 0;
2282 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2283 nla_put_string(nlm, IFLA_IFNAME, name);
2286 nla_put_u32(nlm, IFLA_LINK, link);
2288 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2294 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2295 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2302 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2304 if ((cur = tb[TUNNEL_ATTR_TTL]))
2305 ttl = blobmsg_get_u32(cur);
2307 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2308 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2310 struct in6_addr in6buf;
2311 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2312 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2316 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2319 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2320 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2324 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2327 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2328 struct blob_attr *tb_data[__IPIP6_DATA_ATTR_MAX];
2330 blobmsg_parse(ipip6_data_attr_list.params, __IPIP6_DATA_ATTR_MAX, tb_data,
2331 blobmsg_data(cur), blobmsg_len(cur));
2333 if ((cur = tb_data[IPIP6_DATA_ENCAPLIMIT])) {
2334 char *str = blobmsg_get_string(cur);
2336 if (strcmp(str, "ignore")) {
2338 unsigned encap_limit = strtoul(str, &e, 0);
2340 if (e == str || *e || encap_limit > 255) {
2345 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, encap_limit);
2347 nla_put_u32(nlm, IFLA_IPTUN_FLAGS, IP6_TNL_F_IGN_ENCAP_LIMIT);
2350 #ifdef IFLA_IPTUN_FMR_MAX
2351 if ((cur = tb_data[IPIP6_DATA_FMRS])) {
2352 struct blob_attr *rcur;
2353 unsigned rrem, fmrcnt = 0;
2354 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2361 blobmsg_for_each_attr(rcur, cur, rrem) {
2362 struct blob_attr *tb_fmr[__FMR_DATA_ATTR_MAX], *tb_cur;
2363 struct in6_addr ip6prefix;
2364 struct in_addr ip4prefix;
2365 unsigned ip4len, ip6len, ealen, offset;
2367 blobmsg_parse(fmr_data_attr_list.params, __FMR_DATA_ATTR_MAX, tb_fmr,
2368 blobmsg_data(rcur), blobmsg_len(rcur));
2370 if (!(tb_cur = tb_fmr[FMR_DATA_PREFIX6]) ||
2371 !parse_ip_and_netmask(AF_INET6,
2372 blobmsg_data(tb_cur), &ip6prefix,
2378 if (!(tb_cur = tb_fmr[FMR_DATA_PREFIX4]) ||
2379 !parse_ip_and_netmask(AF_INET,
2380 blobmsg_data(tb_cur), &ip4prefix,
2386 if (!(tb_cur = tb_fmr[FMR_DATA_EALEN])) {
2390 ealen = blobmsg_get_u32(tb_cur);
2392 if (!(tb_cur = tb_fmr[FMR_DATA_OFFSET])) {
2396 offset = blobmsg_get_u32(tb_cur);
2398 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2404 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2405 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2406 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2407 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2408 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2409 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2411 nla_nest_end(nlm, rule);
2414 nla_nest_end(nlm, fmrs);
2419 nla_nest_end(nlm, infodata);
2420 nla_nest_end(nlm, linkinfo);
2422 return system_rtnl_call(nlm);
2430 #ifdef IFLA_IPTUN_MAX
2431 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
2432 static int system_add_gre_tunnel(const char *name, const char *kind,
2433 const unsigned int link, struct blob_attr **tb, bool v6)
2436 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2437 struct blob_attr *cur;
2438 uint32_t ikey = 0, okey = 0, flags = 0, flowinfo = 0;
2439 uint16_t iflags = 0, oflags = 0;
2441 int ret = 0, ttl = 0;
2443 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2447 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2448 nla_put_string(nlm, IFLA_IFNAME, name);
2450 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2456 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2457 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2464 nla_put_u32(nlm, IFLA_GRE_LINK, link);
2466 if ((cur = tb[TUNNEL_ATTR_TTL]))
2467 ttl = blobmsg_get_u32(cur);
2469 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2470 char *str = blobmsg_get_string(cur);
2471 if (strcmp(str, "inherit")) {
2474 if (!system_tos_aton(str, &uval)) {
2480 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
2485 flags |= IP6_TNL_F_USE_ORIG_TCLASS;
2491 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2492 struct blob_attr *tb_data[__GRE_DATA_ATTR_MAX];
2494 blobmsg_parse(gre_data_attr_list.params, __GRE_DATA_ATTR_MAX, tb_data,
2495 blobmsg_data(cur), blobmsg_len(cur));
2497 if ((cur = tb_data[GRE_DATA_IKEY])) {
2498 if ((ikey = blobmsg_get_u32(cur)))
2502 if ((cur = tb_data[GRE_DATA_OKEY])) {
2503 if ((okey = blobmsg_get_u32(cur)))
2507 if ((cur = tb_data[GRE_DATA_ICSUM])) {
2508 if (blobmsg_get_bool(cur))
2512 if ((cur = tb_data[GRE_DATA_OCSUM])) {
2513 if (blobmsg_get_bool(cur))
2517 if ((cur = tb_data[GRE_DATA_ISEQNO])) {
2518 if (blobmsg_get_bool(cur))
2522 if ((cur = tb[GRE_DATA_OSEQNO])) {
2523 if (blobmsg_get_bool(cur))
2529 struct in6_addr in6buf;
2530 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2531 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2535 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
2538 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2539 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2543 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
2545 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, 4);
2548 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
2551 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags);
2556 struct in_addr inbuf;
2559 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2560 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2564 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
2567 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2568 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2572 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
2574 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
2576 okey = inbuf.s_addr;
2581 ikey = inbuf.s_addr;
2587 if ((cur = tb[TUNNEL_ATTR_DF]))
2588 set_df = blobmsg_get_bool(cur);
2591 /* ttl != 0 and nopmtudisc are incompatible */
2599 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
2601 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
2605 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
2608 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
2611 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
2614 nla_put_u32(nlm, IFLA_GRE_OKEY, htonl(okey));
2617 nla_put_u32(nlm, IFLA_GRE_IKEY, htonl(ikey));
2619 nla_nest_end(nlm, infodata);
2620 nla_nest_end(nlm, linkinfo);
2622 return system_rtnl_call(nlm);
2631 static int system_add_vti_tunnel(const char *name, const char *kind,
2632 const unsigned int link, struct blob_attr **tb, bool v6)
2635 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2636 struct blob_attr *cur;
2639 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2643 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2644 nla_put_string(nlm, IFLA_IFNAME, name);
2646 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2652 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2653 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2660 nla_put_u32(nlm, IFLA_VTI_LINK, link);
2663 struct in6_addr in6buf;
2664 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2665 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2669 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(in6buf), &in6buf);
2672 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2673 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2677 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(in6buf), &in6buf);
2681 struct in_addr inbuf;
2683 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2684 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2688 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(inbuf), &inbuf);
2691 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2692 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2696 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(inbuf), &inbuf);
2701 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2702 struct blob_attr *tb_data[__VTI_DATA_ATTR_MAX];
2703 uint32_t ikey = 0, okey = 0;
2705 blobmsg_parse(vti_data_attr_list.params, __VTI_DATA_ATTR_MAX, tb_data,
2706 blobmsg_data(cur), blobmsg_len(cur));
2708 if ((cur = tb_data[VTI_DATA_IKEY])) {
2709 if ((ikey = blobmsg_get_u32(cur)))
2710 nla_put_u32(nlm, IFLA_VTI_IKEY, htonl(ikey));
2713 if ((cur = tb_data[VTI_DATA_OKEY])) {
2714 if ((okey = blobmsg_get_u32(cur)))
2715 nla_put_u32(nlm, IFLA_VTI_OKEY, htonl(okey));
2719 nla_nest_end(nlm, infodata);
2720 nla_nest_end(nlm, linkinfo);
2722 return system_rtnl_call(nlm);
2730 #ifdef IFLA_VXLAN_MAX
2731 static int system_add_vxlan(const char *name, const unsigned int link, struct blob_attr **tb, bool v6)
2733 struct blob_attr *tb_data[__VXLAN_DATA_ATTR_MAX];
2735 struct nlattr *linkinfo, *data;
2736 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
2737 struct blob_attr *cur;
2740 if ((cur = tb[TUNNEL_ATTR_DATA]))
2741 blobmsg_parse(vxlan_data_attr_list.params, __VXLAN_DATA_ATTR_MAX, tb_data,
2742 blobmsg_data(cur), blobmsg_len(cur));
2746 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
2751 nlmsg_append(msg, &iim, sizeof(iim), 0);
2753 nla_put_string(msg, IFLA_IFNAME, name);
2755 if ((cur = tb_data[VXLAN_DATA_ATTR_MACADDR])) {
2756 struct ether_addr *ea = ether_aton(blobmsg_get_string(cur));
2762 nla_put(msg, IFLA_ADDRESS, ETH_ALEN, ea);
2765 if ((cur = tb[TUNNEL_ATTR_MTU])) {
2766 uint32_t mtu = blobmsg_get_u32(cur);
2767 nla_put_u32(msg, IFLA_MTU, mtu);
2770 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO))) {
2775 nla_put_string(msg, IFLA_INFO_KIND, "vxlan");
2777 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) {
2783 nla_put_u32(msg, IFLA_VXLAN_LINK, link);
2785 if ((cur = tb_data[VXLAN_DATA_ATTR_ID])) {
2786 uint32_t id = blobmsg_get_u32(cur);
2787 if (id >= (1u << 24) - 1) {
2792 nla_put_u32(msg, IFLA_VXLAN_ID, id);
2796 struct in6_addr in6buf;
2797 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2798 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2802 nla_put(msg, IFLA_VXLAN_LOCAL6, sizeof(in6buf), &in6buf);
2805 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2806 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2810 nla_put(msg, IFLA_VXLAN_GROUP6, sizeof(in6buf), &in6buf);
2813 struct in_addr inbuf;
2815 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2816 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2820 nla_put(msg, IFLA_VXLAN_LOCAL, sizeof(inbuf), &inbuf);
2823 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2824 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2828 nla_put(msg, IFLA_VXLAN_GROUP, sizeof(inbuf), &inbuf);
2832 uint32_t port = 4789;
2833 if ((cur = tb_data[VXLAN_DATA_ATTR_PORT])) {
2834 port = blobmsg_get_u32(cur);
2835 if (port < 1 || port > 65535) {
2840 nla_put_u16(msg, IFLA_VXLAN_PORT, htons(port));
2842 if ((cur = tb_data[VXLAN_DATA_ATTR_RXCSUM])) {
2843 bool rxcsum = blobmsg_get_bool(cur);
2844 nla_put_u8(msg, IFLA_VXLAN_UDP_ZERO_CSUM6_RX, !rxcsum);
2847 if ((cur = tb_data[VXLAN_DATA_ATTR_TXCSUM])) {
2848 bool txcsum = blobmsg_get_bool(cur);
2849 nla_put_u8(msg, IFLA_VXLAN_UDP_CSUM, txcsum);
2850 nla_put_u8(msg, IFLA_VXLAN_UDP_ZERO_CSUM6_TX, !txcsum);
2853 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2854 char *str = blobmsg_get_string(cur);
2857 if (strcmp(str, "inherit")) {
2858 if (!system_tos_aton(str, &tos)) {
2864 nla_put_u8(msg, IFLA_VXLAN_TOS, tos);
2867 if ((cur = tb[TUNNEL_ATTR_TTL])) {
2868 uint32_t ttl = blobmsg_get_u32(cur);
2869 if (ttl < 1 || ttl > 255) {
2874 nla_put_u8(msg, IFLA_VXLAN_TTL, ttl);
2877 nla_nest_end(msg, data);
2878 nla_nest_end(msg, linkinfo);
2880 ret = system_rtnl_call(msg);
2882 D(SYSTEM, "Error adding vxlan '%s': %d\n", name, ret);
2892 static int system_add_sit_tunnel(const char *name, const unsigned int link, struct blob_attr **tb)
2894 struct blob_attr *cur;
2897 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
2901 if ((cur = tb[TUNNEL_ATTR_DATA])) {
2902 struct blob_attr *tb_data[__SIXRD_DATA_ATTR_MAX];
2904 struct ip_tunnel_6rd p6;
2906 blobmsg_parse(sixrd_data_attr_list.params, __SIXRD_DATA_ATTR_MAX, tb_data,
2907 blobmsg_data(cur), blobmsg_len(cur));
2909 memset(&p6, 0, sizeof(p6));
2911 if ((cur = tb_data[SIXRD_DATA_PREFIX])) {
2912 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
2913 &p6.prefix, &mask) || mask > 128) {
2918 p6.prefixlen = mask;
2921 if ((cur = tb_data[SIXRD_DATA_RELAY_PREFIX])) {
2922 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
2923 &p6.relay_prefix, &mask) || mask > 32) {
2928 p6.relay_prefixlen = mask;
2931 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
2941 __system_del_ip_tunnel(name, tb);
2945 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
2947 struct blob_attr *cur;
2949 struct ip_tunnel_parm p = {
2958 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
2959 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
2962 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
2963 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
2966 if ((cur = tb[TUNNEL_ATTR_DF]))
2967 set_df = blobmsg_get_bool(cur);
2969 if ((cur = tb[TUNNEL_ATTR_TTL]))
2970 p.iph.ttl = blobmsg_get_u32(cur);
2972 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2973 char *str = blobmsg_get_string(cur);
2974 if (strcmp(str, "inherit")) {
2977 if (!system_tos_aton(str, &uval))
2985 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
2986 /* ttl !=0 and nopmtudisc are incompatible */
2987 if (p.iph.ttl && p.iph.frag_off == 0)
2990 strncpy(p.name, name, sizeof(p.name) - 1);
2992 switch (p.iph.protocol) {
2994 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
2996 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
3003 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
3005 struct blob_attr *cur;
3008 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
3010 str = blobmsg_data(cur);
3012 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
3013 !strcmp(str, "greip6") || !strcmp(str, "gretapip6") ||
3014 !strcmp(str, "vtiip") || !strcmp(str, "vtiip6") ||
3015 !strcmp(str, "vxlan") || !strcmp(str, "vxlan6"))
3016 return system_link_del(name);
3018 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
3021 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
3023 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
3025 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
3026 blob_data(attr), blob_len(attr));
3028 return __system_del_ip_tunnel(name, tb);
3031 int system_update_ipv6_mtu(struct device *dev, int mtu)
3037 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
3040 fd = open(buf, O_RDWR);
3045 ssize_t len = read(fd, buf, sizeof(buf) - 1);
3052 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) > 0)
3061 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
3063 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
3064 struct blob_attr *cur;
3067 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
3068 blob_data(attr), blob_len(attr));
3070 __system_del_ip_tunnel(name, tb);
3072 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
3074 str = blobmsg_data(cur);
3076 unsigned int ttl = 0;
3077 if ((cur = tb[TUNNEL_ATTR_TTL])) {
3078 ttl = blobmsg_get_u32(cur);
3083 unsigned int link = 0;
3084 if ((cur = tb[TUNNEL_ATTR_LINK])) {
3085 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
3089 if (iface->l3_dev.dev)
3090 link = iface->l3_dev.dev->ifindex;
3093 if (!strcmp(str, "sit"))
3094 return system_add_sit_tunnel(name, link, tb);
3095 #ifdef IFLA_IPTUN_MAX
3096 else if (!strcmp(str, "ipip6")) {
3097 return system_add_ip6_tunnel(name, link, tb);
3098 } else if (!strcmp(str, "greip")) {
3099 return system_add_gre_tunnel(name, "gre", link, tb, false);
3100 } else if (!strcmp(str, "gretapip")) {
3101 return system_add_gre_tunnel(name, "gretap", link, tb, false);
3102 } else if (!strcmp(str, "greip6")) {
3103 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
3104 } else if (!strcmp(str, "gretapip6")) {
3105 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
3107 } else if (!strcmp(str, "vtiip")) {
3108 return system_add_vti_tunnel(name, "vti", link, tb, false);
3109 } else if (!strcmp(str, "vtiip6")) {
3110 return system_add_vti_tunnel(name, "vti6", link, tb, true);
3112 #ifdef IFLA_VXLAN_MAX
3113 } else if(!strcmp(str, "vxlan")) {
3114 return system_add_vxlan(name, link, tb, false);
3115 } else if(!strcmp(str, "vxlan6")) {
3116 return system_add_vxlan(name, link, tb, true);
3119 } else if (!strcmp(str, "ipip")) {
3120 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);