2 * netifd - network interface daemon
3 * Copyright (C) 2012 Felix Fietkau <nbd@openwrt.org>
4 * Copyright (C) 2013 Jo-Philipp Wich <jow@openwrt.org>
5 * Copyright (C) 2013 Steven Barth <steven@midlink.org>
6 * Copyright (C) 2014 Gioacchino Mazzurco <gio@eigenlab.org>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2
10 * as published by the Free Software Foundation
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
19 #include <sys/socket.h>
20 #include <sys/ioctl.h>
22 #include <sys/syscall.h>
25 #include <net/if_arp.h>
27 #include <arpa/inet.h>
28 #include <netinet/in.h>
30 #include <linux/rtnetlink.h>
31 #include <linux/sockios.h>
33 #include <linux/if_addr.h>
34 #include <linux/if_link.h>
35 #include <linux/if_vlan.h>
36 #include <linux/if_bridge.h>
37 #include <linux/if_tunnel.h>
38 #include <linux/ip6_tunnel.h>
39 #include <linux/ethtool.h>
40 #include <linux/fib_rules.h>
41 #include <linux/version.h>
43 #ifndef RTN_FAILED_POLICY
44 #define RTN_FAILED_POLICY 12
47 #ifndef IFA_F_NOPREFIXROUTE
48 #define IFA_F_NOPREFIXROUTE 0x200
52 #define IFA_FLAGS (IFA_MULTICAST + 1)
62 #include <netlink/msg.h>
63 #include <netlink/attr.h>
64 #include <netlink/socket.h>
65 #include <libubox/uloop.h>
72 struct uloop_fd uloop;
77 static int sock_ioctl = -1;
78 static struct nl_sock *sock_rtnl = NULL;
80 static int cb_rtnl_event(struct nl_msg *msg, void *arg);
81 static void handle_hotplug_event(struct uloop_fd *u, unsigned int events);
83 static char dev_buf[256];
86 handler_nl_event(struct uloop_fd *u, unsigned int events)
88 struct event_socket *ev = container_of(u, struct event_socket, uloop);
90 socklen_t errlen = sizeof(err);
93 nl_recvmsgs_default(ev->sock);
97 if (getsockopt(u->fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen))
102 // Increase rx buffer size on netlink socket
104 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
107 // Request full dump since some info got dropped
108 struct rtgenmsg msg = { .rtgen_family = AF_UNSPEC };
109 nl_send_simple(ev->sock, RTM_GETLINK, NLM_F_DUMP, &msg, sizeof(msg));
119 uloop_fd_delete(&ev->uloop);
123 static struct nl_sock *
124 create_socket(int protocol, int groups)
126 struct nl_sock *sock;
128 sock = nl_socket_alloc();
133 nl_join_groups(sock, groups);
135 if (nl_connect(sock, protocol))
142 create_raw_event_socket(struct event_socket *ev, int protocol, int groups,
143 uloop_fd_handler cb, int flags)
145 ev->sock = create_socket(protocol, groups);
149 ev->uloop.fd = nl_socket_get_fd(ev->sock);
151 if (uloop_fd_add(&ev->uloop, ULOOP_READ|flags))
158 create_event_socket(struct event_socket *ev, int protocol,
159 int (*cb)(struct nl_msg *msg, void *arg))
161 if (!create_raw_event_socket(ev, protocol, 0, handler_nl_event, ULOOP_ERROR_CB))
164 // Install the valid custom callback handler
165 nl_socket_modify_cb(ev->sock, NL_CB_VALID, NL_CB_CUSTOM, cb, NULL);
167 // Disable sequence number checking on event sockets
168 nl_socket_disable_seq_check(ev->sock);
170 // Increase rx buffer size to 65K on event sockets
172 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
179 system_rtn_aton(const char *src, unsigned int *dst)
184 if (!strcmp(src, "local"))
186 else if (!strcmp(src, "nat"))
188 else if (!strcmp(src, "broadcast"))
190 else if (!strcmp(src, "anycast"))
192 else if (!strcmp(src, "multicast"))
194 else if (!strcmp(src, "prohibit"))
196 else if (!strcmp(src, "unreachable"))
198 else if (!strcmp(src, "blackhole"))
200 else if (!strcmp(src, "xresolve"))
202 else if (!strcmp(src, "unicast"))
204 else if (!strcmp(src, "throw"))
206 else if (!strcmp(src, "failed_policy"))
207 n = RTN_FAILED_POLICY;
209 n = strtoul(src, &e, 0);
210 if (!e || *e || e == src || n > 255)
219 system_tos_aton(const char *src, unsigned *dst)
223 *dst = strtoul(src, &e, 16);
224 if (e == src || *e || *dst > 255)
230 int system_init(void)
232 static struct event_socket rtnl_event;
233 static struct event_socket hotplug_event;
235 sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0);
236 system_fd_set_cloexec(sock_ioctl);
238 // Prepare socket for routing / address control
239 sock_rtnl = create_socket(NETLINK_ROUTE, 0);
243 if (!create_event_socket(&rtnl_event, NETLINK_ROUTE, cb_rtnl_event))
246 if (!create_raw_event_socket(&hotplug_event, NETLINK_KOBJECT_UEVENT, 1,
247 handle_hotplug_event, 0))
250 // Receive network link events form kernel
251 nl_socket_add_membership(rtnl_event.sock, RTNLGRP_LINK);
256 static void system_set_sysctl(const char *path, const char *val)
260 fd = open(path, O_WRONLY);
264 if (write(fd, val, strlen(val))) {}
268 static void system_set_dev_sysctl(const char *path, const char *device, const char *val)
270 snprintf(dev_buf, sizeof(dev_buf), path, device);
271 system_set_sysctl(dev_buf, val);
274 static void system_set_disable_ipv6(struct device *dev, const char *val)
276 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val);
279 static void system_set_rpfilter(struct device *dev, const char *val)
281 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter", dev->ifname, val);
284 static void system_set_acceptlocal(struct device *dev, const char *val)
286 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local", dev->ifname, val);
289 static void system_set_igmpversion(struct device *dev, const char *val)
291 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version", dev->ifname, val);
294 static void system_set_mldversion(struct device *dev, const char *val)
296 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version", dev->ifname, val);
299 static void system_set_neigh4reachabletime(struct device *dev, const char *val)
301 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms", dev->ifname, val);
304 static void system_set_neigh6reachabletime(struct device *dev, const char *val)
306 system_set_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms", dev->ifname, val);
309 static void system_set_neigh4gcstaletime(struct device *dev, const char *val)
311 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/gc_stale_time", dev->ifname, val);
314 static void system_set_neigh6gcstaletime(struct device *dev, const char *val)
316 system_set_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/gc_stale_time", dev->ifname, val);
319 static void system_set_dadtransmits(struct device *dev, const char *val)
321 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits", dev->ifname, val);
324 static void system_bridge_set_multicast_to_unicast(struct device *dev, const char *val)
326 system_set_dev_sysctl("/sys/class/net/%s/brport/multicast_to_unicast", dev->ifname, val);
329 static void system_bridge_set_hairpin_mode(struct device *dev, const char *val)
331 system_set_dev_sysctl("/sys/class/net/%s/brport/hairpin_mode", dev->ifname, val);
334 static void system_bridge_set_multicast_router(struct device *dev, const char *val, bool bridge)
336 system_set_dev_sysctl(bridge ? "/sys/class/net/%s/bridge/multicast_router" :
337 "/sys/class/net/%s/brport/multicast_router",
341 static void system_bridge_set_robustness(struct device *dev, const char *val)
343 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_startup_query_count",
345 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_last_member_count",
349 static void system_bridge_set_query_interval(struct device *dev, const char *val)
351 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_query_interval",
355 static void system_bridge_set_query_response_interval(struct device *dev, const char *val)
357 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_query_response_interval",
361 static void system_bridge_set_last_member_interval(struct device *dev, const char *val)
363 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_last_member_interval",
367 static void system_bridge_set_membership_interval(struct device *dev, const char *val)
369 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_membership_interval",
373 static void system_bridge_set_other_querier_timeout(struct device *dev, const char *val)
375 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier_interval",
379 static void system_bridge_set_startup_query_interval(struct device *dev, const char *val)
381 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_startup_query_interval",
385 static void system_bridge_set_learning(struct device *dev, const char *val)
387 system_set_dev_sysctl("/sys/class/net/%s/brport/learning", dev->ifname, val);
390 static void system_bridge_set_unicast_flood(struct device *dev, const char *val)
392 system_set_dev_sysctl("/sys/class/net/%s/brport/unicast_flood", dev->ifname, val);
395 static int system_get_sysctl(const char *path, char *buf, const size_t buf_sz)
397 int fd = -1, ret = -1;
399 fd = open(path, O_RDONLY);
403 ssize_t len = read(fd, buf, buf_sz - 1);
417 system_get_dev_sysctl(const char *path, const char *device, char *buf, const size_t buf_sz)
419 snprintf(dev_buf, sizeof(dev_buf), path, device);
420 return system_get_sysctl(dev_buf, buf, buf_sz);
423 static int system_get_disable_ipv6(struct device *dev, char *buf, const size_t buf_sz)
425 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6",
426 dev->ifname, buf, buf_sz);
429 static int system_get_rpfilter(struct device *dev, char *buf, const size_t buf_sz)
431 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter",
432 dev->ifname, buf, buf_sz);
435 static int system_get_acceptlocal(struct device *dev, char *buf, const size_t buf_sz)
437 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local",
438 dev->ifname, buf, buf_sz);
441 static int system_get_igmpversion(struct device *dev, char *buf, const size_t buf_sz)
443 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version",
444 dev->ifname, buf, buf_sz);
447 static int system_get_mldversion(struct device *dev, char *buf, const size_t buf_sz)
449 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version",
450 dev->ifname, buf, buf_sz);
453 static int system_get_neigh4reachabletime(struct device *dev, char *buf, const size_t buf_sz)
455 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms",
456 dev->ifname, buf, buf_sz);
459 static int system_get_neigh6reachabletime(struct device *dev, char *buf, const size_t buf_sz)
461 return system_get_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms",
462 dev->ifname, buf, buf_sz);
465 static int system_get_neigh4gcstaletime(struct device *dev, char *buf, const size_t buf_sz)
467 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/gc_stale_time",
468 dev->ifname, buf, buf_sz);
471 static int system_get_neigh6gcstaletime(struct device *dev, char *buf, const size_t buf_sz)
473 return system_get_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/gc_stale_time",
474 dev->ifname, buf, buf_sz);
477 static int system_get_dadtransmits(struct device *dev, char *buf, const size_t buf_sz)
479 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits",
480 dev->ifname, buf, buf_sz);
483 // Evaluate netlink messages
484 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
486 struct nlmsghdr *nh = nlmsg_hdr(msg);
487 struct nlattr *nla[__IFLA_MAX];
491 if (nh->nlmsg_type != RTM_NEWLINK)
494 nlmsg_parse(nh, sizeof(struct ifinfomsg), nla, __IFLA_MAX - 1, NULL);
495 if (!nla[IFLA_IFNAME])
498 struct device *dev = device_find(nla_data(nla[IFLA_IFNAME]));
502 if (!system_get_dev_sysctl("/sys/class/net/%s/carrier", dev->ifname, buf, sizeof(buf)))
503 link_state = strtoul(buf, NULL, 0);
505 device_set_link(dev, link_state ? true : false);
512 handle_hotplug_msg(char *data, int size)
514 const char *subsystem = NULL, *interface = NULL;
515 char *cur, *end, *sep;
520 if (!strncmp(data, "add@", 4))
522 else if (!strncmp(data, "remove@", 7))
527 skip = strlen(data) + 1;
530 for (cur = data + skip; cur < end; cur += skip) {
531 skip = strlen(cur) + 1;
533 sep = strchr(cur, '=');
538 if (!strcmp(cur, "INTERFACE"))
540 else if (!strcmp(cur, "SUBSYSTEM")) {
542 if (strcmp(subsystem, "net") != 0)
545 if (subsystem && interface)
551 dev = device_find(interface);
555 if (dev->type != &simple_device_type)
558 if (add && system_if_force_external(dev->ifname))
561 device_set_present(dev, add);
565 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
567 struct event_socket *ev = container_of(u, struct event_socket, uloop);
568 struct sockaddr_nl nla;
569 unsigned char *buf = NULL;
572 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
574 handle_hotplug_msg((char *) buf, size);
580 static int system_rtnl_call(struct nl_msg *msg)
584 ret = nl_send_auto_complete(sock_rtnl, msg);
590 return nl_wait_for_ack(sock_rtnl);
593 int system_bridge_delbr(struct device *bridge)
595 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
598 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
602 memset(&ifr, 0, sizeof(ifr));
604 ifr.ifr_ifindex = dev->ifindex;
607 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
608 return ioctl(sock_ioctl, cmd, &ifr);
611 static bool system_is_bridge(const char *name, char *buf, int buflen)
615 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
616 if (stat(buf, &st) < 0)
622 static char *system_get_bridge(const char *name, char *buf, int buflen)
628 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
629 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
633 len = readlink(gl.gl_pathv[0], buf, buflen);
641 path = strrchr(buf, '/');
649 system_bridge_set_wireless(struct device *bridge, struct device *dev)
651 bool mcast_to_ucast = dev->wireless_ap;
654 if (bridge->settings.flags & DEV_OPT_MULTICAST_TO_UNICAST &&
655 !bridge->settings.multicast_to_unicast)
656 mcast_to_ucast = false;
658 if (!mcast_to_ucast || dev->wireless_isolate)
661 system_bridge_set_multicast_to_unicast(dev, mcast_to_ucast ? "1" : "0");
662 system_bridge_set_hairpin_mode(dev, hairpin ? "1" : "0");
665 int system_bridge_addif(struct device *bridge, struct device *dev)
671 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
672 if (!oldbr || strcmp(oldbr, bridge->ifname) != 0)
673 ret = system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
676 system_bridge_set_wireless(bridge, dev);
678 if (dev->settings.flags & DEV_OPT_MULTICAST_ROUTER) {
679 snprintf(buf, sizeof(buf), "%i", dev->settings.multicast_router);
680 system_bridge_set_multicast_router(dev, buf, false);
683 if (dev->settings.flags & DEV_OPT_LEARNING &&
684 !dev->settings.learning)
685 system_bridge_set_learning(dev, "0");
687 if (dev->settings.flags & DEV_OPT_UNICAST_FLOOD &&
688 !dev->settings.unicast_flood)
689 system_bridge_set_unicast_flood(dev, "0");
694 int system_bridge_delif(struct device *bridge, struct device *dev)
696 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
699 int system_if_resolve(struct device *dev)
702 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
703 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
704 return ifr.ifr_ifindex;
709 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
713 memset(&ifr, 0, sizeof(ifr));
714 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
715 ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
716 ifr.ifr_flags |= add;
717 ifr.ifr_flags &= ~rem;
718 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
730 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
732 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
734 return ifa->ifa_index == ifindex;
737 static bool check_route(struct nlmsghdr *hdr, int ifindex)
739 struct rtmsg *r = NLMSG_DATA(hdr);
740 struct nlattr *tb[__RTA_MAX];
742 if (r->rtm_protocol == RTPROT_KERNEL &&
743 r->rtm_family == AF_INET6)
746 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
750 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
753 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
758 static int cb_clear_event(struct nl_msg *msg, void *arg)
760 struct clear_data *clr = arg;
761 struct nlmsghdr *hdr = nlmsg_hdr(msg);
762 bool (*cb)(struct nlmsghdr *, int ifindex);
768 if (hdr->nlmsg_type != RTM_NEWADDR)
775 if (hdr->nlmsg_type != RTM_NEWROUTE)
782 if (hdr->nlmsg_type != RTM_NEWRULE)
791 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
794 if (type == RTM_DELRULE)
795 D(SYSTEM, "Remove a rule\n");
797 D(SYSTEM, "Remove %s from device %s\n",
798 type == RTM_DELADDR ? "an address" : "a route",
800 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
801 hdr = nlmsg_hdr(clr->msg);
802 hdr->nlmsg_type = type;
803 hdr->nlmsg_flags = NLM_F_REQUEST;
805 nl_socket_disable_auto_ack(sock_rtnl);
806 nl_send_auto_complete(sock_rtnl, clr->msg);
807 nl_socket_enable_auto_ack(sock_rtnl);
813 cb_finish_event(struct nl_msg *msg, void *arg)
821 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
824 *pending = err->error;
829 system_if_clear_entries(struct device *dev, int type, int af)
831 struct clear_data clr;
832 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
835 .rtm_flags = RTM_F_CLONED,
837 int flags = NLM_F_DUMP;
846 clr.size = sizeof(struct rtgenmsg);
849 clr.size = sizeof(struct rtmsg);
858 clr.msg = nlmsg_alloc_simple(type, flags);
862 nlmsg_append(clr.msg, &rtm, clr.size, 0);
863 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
864 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
865 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
867 nl_send_auto_complete(sock_rtnl, clr.msg);
869 nl_recvmsgs(sock_rtnl, cb);
877 * Clear bridge (membership) state and bring down device
879 void system_if_clear_state(struct device *dev)
881 static char buf[256];
884 device_set_ifindex(dev, system_if_resolve(dev));
885 if (dev->external || !dev->ifindex)
888 system_if_flags(dev->ifname, 0, IFF_UP);
890 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
891 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
892 system_bridge_delbr(dev);
896 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
898 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
899 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
902 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
903 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
904 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
905 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
906 system_set_disable_ipv6(dev, "0");
909 static inline unsigned long
910 sec_to_jiffies(int val)
912 return (unsigned long) val * 100;
915 static void system_bridge_conf_multicast_deps(struct device *bridge,
916 struct bridge_config *cfg,
922 if (cfg->flags & BRIDGE_OPT_ROBUSTNESS ||
923 cfg->flags & BRIDGE_OPT_QUERY_INTERVAL ||
924 cfg->flags & BRIDGE_OPT_QUERY_RESPONSE_INTERVAL) {
925 val = cfg->robustness * cfg->query_interval +
926 cfg->query_response_interval;
928 snprintf(buf, buf_len, "%i", val);
929 system_bridge_set_membership_interval(bridge, buf);
931 val = cfg->robustness * cfg->query_interval +
932 cfg->query_response_interval / 2;
934 snprintf(buf, buf_len, "%i", val);
935 system_bridge_set_other_querier_timeout(bridge, buf);
938 if (cfg->flags & BRIDGE_OPT_QUERY_INTERVAL) {
939 val = cfg->query_interval / 4;
941 snprintf(buf, buf_len, "%i", val);
942 system_bridge_set_startup_query_interval(bridge, buf);
946 static void system_bridge_conf_multicast(struct device *bridge,
947 struct bridge_config *cfg,
951 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
952 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
954 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier",
955 bridge->ifname, cfg->multicast_querier ? "1" : "0");
957 snprintf(buf, buf_len, "%i", cfg->hash_max);
958 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/hash_max",
959 bridge->ifname, buf);
961 if (bridge->settings.flags & DEV_OPT_MULTICAST_ROUTER) {
962 snprintf(buf, buf_len, "%i", bridge->settings.multicast_router);
963 system_bridge_set_multicast_router(bridge, buf, true);
966 if (cfg->flags & BRIDGE_OPT_ROBUSTNESS) {
967 snprintf(buf, buf_len, "%i", cfg->robustness);
968 system_bridge_set_robustness(bridge, buf);
971 if (cfg->flags & BRIDGE_OPT_QUERY_INTERVAL) {
972 snprintf(buf, buf_len, "%i", cfg->query_interval);
973 system_bridge_set_query_interval(bridge, buf);
976 if (cfg->flags & BRIDGE_OPT_QUERY_RESPONSE_INTERVAL) {
977 snprintf(buf, buf_len, "%i", cfg->query_response_interval);
978 system_bridge_set_query_response_interval(bridge, buf);
981 if (cfg->flags & BRIDGE_OPT_LAST_MEMBER_INTERVAL) {
982 snprintf(buf, buf_len, "%i", cfg->last_member_interval);
983 system_bridge_set_last_member_interval(bridge, buf);
986 system_bridge_conf_multicast_deps(bridge, cfg, buf, buf_len);
989 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
992 unsigned long args[4] = {};
994 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
997 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
998 args[1] = !!cfg->stp;
999 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1001 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
1002 args[1] = sec_to_jiffies(cfg->forward_delay);
1003 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1005 system_bridge_conf_multicast(bridge, cfg, buf, sizeof(buf));
1007 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
1008 args[1] = cfg->priority;
1009 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1011 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
1012 args[0] = BRCTL_SET_AGEING_TIME;
1013 args[1] = sec_to_jiffies(cfg->ageing_time);
1014 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1017 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
1018 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
1019 args[1] = sec_to_jiffies(cfg->hello_time);
1020 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1023 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
1024 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
1025 args[1] = sec_to_jiffies(cfg->max_age);
1026 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
1032 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
1035 struct nlattr *linkinfo, *data;
1036 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
1038 static const struct {
1040 enum macvlan_mode val;
1042 { "private", MACVLAN_MODE_PRIVATE },
1043 { "vepa", MACVLAN_MODE_VEPA },
1044 { "bridge", MACVLAN_MODE_BRIDGE },
1045 { "passthru", MACVLAN_MODE_PASSTHRU },
1048 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1053 nlmsg_append(msg, &iim, sizeof(iim), 0);
1055 if (cfg->flags & MACVLAN_OPT_MACADDR)
1056 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
1057 nla_put_string(msg, IFLA_IFNAME, macvlan->ifname);
1058 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
1060 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1061 goto nla_put_failure;
1063 nla_put_string(msg, IFLA_INFO_KIND, "macvlan");
1065 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1066 goto nla_put_failure;
1069 for (i = 0; i < ARRAY_SIZE(modes); i++) {
1070 if (strcmp(cfg->mode, modes[i].name) != 0)
1073 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
1078 nla_nest_end(msg, data);
1079 nla_nest_end(msg, linkinfo);
1081 rv = system_rtnl_call(msg);
1083 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
1092 static int system_link_del(const char *ifname)
1095 struct ifinfomsg iim = {
1096 .ifi_family = AF_UNSPEC,
1100 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
1105 nlmsg_append(msg, &iim, sizeof(iim), 0);
1106 nla_put_string(msg, IFLA_IFNAME, ifname);
1107 return system_rtnl_call(msg);
1110 int system_macvlan_del(struct device *macvlan)
1112 return system_link_del(macvlan->ifname);
1115 static int system_vlan(struct device *dev, int id)
1117 struct vlan_ioctl_args ifr = {
1118 .cmd = SET_VLAN_NAME_TYPE_CMD,
1119 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
1122 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
1125 ifr.cmd = DEL_VLAN_CMD;
1128 ifr.cmd = ADD_VLAN_CMD;
1131 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
1132 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
1135 int system_vlan_add(struct device *dev, int id)
1137 return system_vlan(dev, id);
1140 int system_vlan_del(struct device *dev)
1142 return system_vlan(dev, -1);
1145 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
1148 struct nlattr *linkinfo, *data;
1149 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
1152 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1157 nlmsg_append(msg, &iim, sizeof(iim), 0);
1158 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
1159 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
1161 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1162 goto nla_put_failure;
1164 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
1166 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1167 goto nla_put_failure;
1169 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
1171 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
1172 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
1174 if(cfg->proto == VLAN_PROTO_8021AD)
1175 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);
1178 nla_nest_end(msg, data);
1179 nla_nest_end(msg, linkinfo);
1181 rv = system_rtnl_call(msg);
1183 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
1192 int system_vlandev_del(struct device *vlandev)
1194 return system_link_del(vlandev->ifname);
1198 system_if_get_settings(struct device *dev, struct device_settings *s)
1203 memset(&ifr, 0, sizeof(ifr));
1204 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1206 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
1207 s->mtu = ifr.ifr_mtu;
1208 s->flags |= DEV_OPT_MTU;
1211 s->mtu6 = system_update_ipv6_mtu(dev, 0);
1213 s->flags |= DEV_OPT_MTU6;
1215 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
1216 s->txqueuelen = ifr.ifr_qlen;
1217 s->flags |= DEV_OPT_TXQUEUELEN;
1220 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
1221 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
1222 s->flags |= DEV_OPT_MACADDR;
1225 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
1226 s->ipv6 = !strtoul(buf, NULL, 0);
1227 s->flags |= DEV_OPT_IPV6;
1230 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
1231 s->promisc = ifr.ifr_flags & IFF_PROMISC;
1232 s->flags |= DEV_OPT_PROMISC;
1234 s->multicast = ifr.ifr_flags & IFF_MULTICAST;
1235 s->flags |= DEV_OPT_MULTICAST;
1238 if (!system_get_rpfilter(dev, buf, sizeof(buf))) {
1239 s->rpfilter = strtoul(buf, NULL, 0);
1240 s->flags |= DEV_OPT_RPFILTER;
1243 if (!system_get_acceptlocal(dev, buf, sizeof(buf))) {
1244 s->acceptlocal = strtoul(buf, NULL, 0);
1245 s->flags |= DEV_OPT_ACCEPTLOCAL;
1248 if (!system_get_igmpversion(dev, buf, sizeof(buf))) {
1249 s->igmpversion = strtoul(buf, NULL, 0);
1250 s->flags |= DEV_OPT_IGMPVERSION;
1253 if (!system_get_mldversion(dev, buf, sizeof(buf))) {
1254 s->mldversion = strtoul(buf, NULL, 0);
1255 s->flags |= DEV_OPT_MLDVERSION;
1258 if (!system_get_neigh4reachabletime(dev, buf, sizeof(buf))) {
1259 s->neigh4reachabletime = strtoul(buf, NULL, 0);
1260 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1263 if (!system_get_neigh6reachabletime(dev, buf, sizeof(buf))) {
1264 s->neigh6reachabletime = strtoul(buf, NULL, 0);
1265 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1268 if (!system_get_neigh4gcstaletime(dev, buf, sizeof(buf))) {
1269 s->neigh4gcstaletime = strtoul(buf, NULL, 0);
1270 s->flags |= DEV_OPT_NEIGHGCSTALETIME;
1273 if (!system_get_neigh6gcstaletime(dev, buf, sizeof(buf))) {
1274 s->neigh6gcstaletime = strtoul(buf, NULL, 0);
1275 s->flags |= DEV_OPT_NEIGHGCSTALETIME;
1278 if (!system_get_dadtransmits(dev, buf, sizeof(buf))) {
1279 s->dadtransmits = strtoul(buf, NULL, 0);
1280 s->flags |= DEV_OPT_DADTRANSMITS;
1285 system_if_set_rps_xps_val(const char *path, int val)
1291 if (glob(path, 0, NULL, &gl))
1294 snprintf(val_buf, sizeof(val_buf), "%x", val);
1295 for (i = 0; i < gl.gl_pathc; i++)
1296 system_set_sysctl(gl.gl_pathv[i], val_buf);
1302 system_if_apply_rps_xps(struct device *dev, struct device_settings *s)
1304 long n_cpus = sysconf(_SC_NPROCESSORS_ONLN);
1310 val = (1 << n_cpus) - 1;
1311 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/rps_cpus", dev->ifname);
1312 system_if_set_rps_xps_val(dev_buf, s->rps ? val : 0);
1314 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/xps_cpus", dev->ifname);
1315 system_if_set_rps_xps_val(dev_buf, s->xps ? val : 0);
1319 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
1324 memset(&ifr, 0, sizeof(ifr));
1325 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1326 if (s->flags & DEV_OPT_MTU & apply_mask) {
1327 ifr.ifr_mtu = s->mtu;
1328 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
1329 s->flags &= ~DEV_OPT_MTU;
1331 if (s->flags & DEV_OPT_MTU6 & apply_mask) {
1332 system_update_ipv6_mtu(dev, s->mtu6);
1334 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
1335 ifr.ifr_qlen = s->txqueuelen;
1336 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
1337 s->flags &= ~DEV_OPT_TXQUEUELEN;
1339 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
1340 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
1341 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
1342 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
1343 s->flags &= ~DEV_OPT_MACADDR;
1345 if (s->flags & DEV_OPT_IPV6 & apply_mask)
1346 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
1347 if (s->flags & DEV_OPT_PROMISC & apply_mask) {
1348 if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
1349 !s->promisc ? IFF_PROMISC : 0) < 0)
1350 s->flags &= ~DEV_OPT_PROMISC;
1352 if (s->flags & DEV_OPT_RPFILTER & apply_mask) {
1353 snprintf(buf, sizeof(buf), "%d", s->rpfilter);
1354 system_set_rpfilter(dev, buf);
1356 if (s->flags & DEV_OPT_ACCEPTLOCAL & apply_mask)
1357 system_set_acceptlocal(dev, s->acceptlocal ? "1" : "0");
1358 if (s->flags & DEV_OPT_IGMPVERSION & apply_mask) {
1359 snprintf(buf, sizeof(buf), "%d", s->igmpversion);
1360 system_set_igmpversion(dev, buf);
1362 if (s->flags & DEV_OPT_MLDVERSION & apply_mask) {
1363 snprintf(buf, sizeof(buf), "%d", s->mldversion);
1364 system_set_mldversion(dev, buf);
1366 if (s->flags & DEV_OPT_NEIGHREACHABLETIME & apply_mask) {
1367 snprintf(buf, sizeof(buf), "%d", s->neigh4reachabletime);
1368 system_set_neigh4reachabletime(dev, buf);
1369 snprintf(buf, sizeof(buf), "%d", s->neigh6reachabletime);
1370 system_set_neigh6reachabletime(dev, buf);
1372 if (s->flags & DEV_OPT_NEIGHGCSTALETIME & apply_mask) {
1373 snprintf(buf, sizeof(buf), "%d", s->neigh4gcstaletime);
1374 system_set_neigh4gcstaletime(dev, buf);
1375 snprintf(buf, sizeof(buf), "%d", s->neigh6gcstaletime);
1376 system_set_neigh6gcstaletime(dev, buf);
1378 if (s->flags & DEV_OPT_DADTRANSMITS & apply_mask) {
1379 snprintf(buf, sizeof(buf), "%d", s->dadtransmits);
1380 system_set_dadtransmits(dev, buf);
1382 if (s->flags & DEV_OPT_MULTICAST & apply_mask) {
1383 if (system_if_flags(dev->ifname, s->multicast ? IFF_MULTICAST : 0,
1384 !s->multicast ? IFF_MULTICAST : 0) < 0)
1385 s->flags &= ~DEV_OPT_MULTICAST;
1388 system_if_apply_rps_xps(dev, s);
1391 int system_if_up(struct device *dev)
1393 system_if_get_settings(dev, &dev->orig_settings);
1394 /* Only keep orig settings based on what needs to be set */
1395 dev->orig_settings.valid_flags = dev->orig_settings.flags;
1396 dev->orig_settings.flags &= dev->settings.flags;
1397 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
1398 return system_if_flags(dev->ifname, IFF_UP, 0);
1401 int system_if_down(struct device *dev)
1403 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
1404 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
1408 struct if_check_data {
1414 #ifndef IFF_LOWER_UP
1415 #define IFF_LOWER_UP 0x10000
1418 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1420 struct nlmsghdr *nh = nlmsg_hdr(msg);
1421 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1422 struct if_check_data *chk = (struct if_check_data *)arg;
1424 if (nh->nlmsg_type != RTM_NEWLINK)
1427 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1428 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1433 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1435 struct if_check_data *chk = (struct if_check_data *)arg;
1440 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1442 struct if_check_data *chk = (struct if_check_data *)arg;
1444 device_set_present(chk->dev, false);
1445 device_set_link(chk->dev, false);
1446 chk->pending = err->error;
1451 int system_if_check(struct device *dev)
1453 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1455 struct ifinfomsg ifi = {
1456 .ifi_family = AF_UNSPEC,
1459 struct if_check_data chk = {
1465 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1469 if (nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1470 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1473 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1474 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1475 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1477 nl_send_auto_complete(sock_rtnl, msg);
1478 while (chk.pending > 0)
1479 nl_recvmsgs(sock_rtnl, cb);
1491 system_if_get_parent(struct device *dev)
1493 char buf[64], *devname;
1494 int ifindex, iflink, len;
1497 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1498 f = fopen(buf, "r");
1502 len = fread(buf, 1, sizeof(buf) - 1, f);
1509 iflink = strtoul(buf, NULL, 0);
1510 ifindex = system_if_resolve(dev);
1511 if (!iflink || iflink == ifindex)
1514 devname = if_indextoname(iflink, buf);
1518 return device_get(devname, true);
1522 read_string_file(int dir_fd, const char *file, char *buf, int len)
1528 fd = openat(dir_fd, file, O_RDONLY);
1533 len = read(fd, buf, len - 1);
1537 } else if (len > 0) {
1540 c = strchr(buf, '\n');
1553 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1558 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1560 *val = strtoull(buf, NULL, 0);
1565 /* Assume advertised flags == supported flags */
1566 static const struct {
1569 } ethtool_link_modes[] = {
1570 { ADVERTISED_10baseT_Half, "10H" },
1571 { ADVERTISED_10baseT_Full, "10F" },
1572 { ADVERTISED_100baseT_Half, "100H" },
1573 { ADVERTISED_100baseT_Full, "100F" },
1574 { ADVERTISED_1000baseT_Half, "1000H" },
1575 { ADVERTISED_1000baseT_Full, "1000F" },
1578 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1581 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1582 if (mask & ethtool_link_modes[i].mask)
1583 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1588 system_if_force_external(const char *ifname)
1593 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1594 return stat(buf, &s) == 0;
1598 system_if_dump_info(struct device *dev, struct blob_buf *b)
1600 struct ethtool_cmd ecmd;
1606 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
1607 dir_fd = open(buf, O_DIRECTORY);
1609 memset(&ecmd, 0, sizeof(ecmd));
1610 memset(&ifr, 0, sizeof(ifr));
1611 strcpy(ifr.ifr_name, dev->ifname);
1612 ifr.ifr_data = (caddr_t) &ecmd;
1613 ecmd.cmd = ETHTOOL_GSET;
1615 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1616 c = blobmsg_open_array(b, "link-advertising");
1617 system_add_link_modes(b, ecmd.advertising);
1618 blobmsg_close_array(b, c);
1620 c = blobmsg_open_array(b, "link-supported");
1621 system_add_link_modes(b, ecmd.supported);
1622 blobmsg_close_array(b, c);
1624 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1625 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1626 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1627 blobmsg_add_string_buffer(b);
1635 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1637 const char *const counters[] = {
1638 "collisions", "rx_frame_errors", "tx_compressed",
1639 "multicast", "rx_length_errors", "tx_dropped",
1640 "rx_bytes", "rx_missed_errors", "tx_errors",
1641 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1642 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1643 "rx_dropped", "tx_aborted_errors", "tx_packets",
1644 "rx_errors", "tx_bytes", "tx_window_errors",
1645 "rx_fifo_errors", "tx_carrier_errors",
1652 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1653 stats_dir = open(buf, O_DIRECTORY);
1657 for (i = 0; i < ARRAY_SIZE(counters); i++)
1658 if (read_uint64_file(stats_dir, counters[i], &val))
1659 blobmsg_add_u64(b, counters[i], val);
1665 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1667 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1668 int alen = v4 ? 4 : 16;
1669 unsigned int flags = 0;
1670 struct ifaddrmsg ifa = {
1671 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1672 .ifa_prefixlen = addr->mask,
1673 .ifa_index = dev->ifindex,
1677 if (cmd == RTM_NEWADDR)
1678 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1680 msg = nlmsg_alloc_simple(cmd, flags);
1684 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1685 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1687 if (addr->broadcast)
1688 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1689 if (addr->point_to_point)
1690 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1692 time_t now = system_get_rtime();
1693 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1695 if (addr->preferred_until) {
1696 int64_t preferred = addr->preferred_until - now;
1699 else if (preferred > UINT32_MAX)
1700 preferred = UINT32_MAX;
1702 cinfo.ifa_prefered = preferred;
1705 if (addr->valid_until) {
1706 int64_t valid = addr->valid_until - now;
1711 else if (valid > UINT32_MAX)
1714 cinfo.ifa_valid = valid;
1717 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1719 if (cmd == RTM_NEWADDR && (addr->flags & DEVADDR_OFFLINK))
1720 nla_put_u32(msg, IFA_FLAGS, IFA_F_NOPREFIXROUTE);
1723 return system_rtnl_call(msg);
1726 int system_add_address(struct device *dev, struct device_addr *addr)
1728 return system_addr(dev, addr, RTM_NEWADDR);
1731 int system_del_address(struct device *dev, struct device_addr *addr)
1733 return system_addr(dev, addr, RTM_DELADDR);
1736 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1738 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1740 unsigned int flags = 0;
1743 have_gw = !!route->nexthop.in.s_addr;
1745 have_gw = route->nexthop.in6.s6_addr32[0] ||
1746 route->nexthop.in6.s6_addr32[1] ||
1747 route->nexthop.in6.s6_addr32[2] ||
1748 route->nexthop.in6.s6_addr32[3];
1750 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1751 ? route->table : RT_TABLE_MAIN;
1753 struct rtmsg rtm = {
1754 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1755 .rtm_dst_len = route->mask,
1756 .rtm_src_len = route->sourcemask,
1757 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1758 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
1759 .rtm_scope = RT_SCOPE_NOWHERE,
1760 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1761 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1765 if (cmd == RTM_NEWROUTE) {
1766 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1768 if (!dev) { // Add null-route
1769 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1770 rtm.rtm_type = RTN_UNREACHABLE;
1773 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1776 if (route->flags & DEVROUTE_TYPE) {
1777 rtm.rtm_type = route->type;
1778 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
1779 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
1780 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
1781 rtm.rtm_table = RT_TABLE_LOCAL;
1784 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT) {
1785 rtm.rtm_scope = RT_SCOPE_HOST;
1786 } else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
1787 rtm.rtm_type == RTN_ANYCAST) {
1788 rtm.rtm_scope = RT_SCOPE_LINK;
1789 } else if (rtm.rtm_type == RTN_BLACKHOLE || rtm.rtm_type == RTN_UNREACHABLE ||
1790 rtm.rtm_type == RTN_PROHIBIT || rtm.rtm_type == RTN_FAILED_POLICY) {
1791 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1796 msg = nlmsg_alloc_simple(cmd, flags);
1800 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1803 nla_put(msg, RTA_DST, alen, &route->addr);
1805 if (route->sourcemask) {
1806 if (rtm.rtm_family == AF_INET)
1807 nla_put(msg, RTA_PREFSRC, alen, &route->source);
1809 nla_put(msg, RTA_SRC, alen, &route->source);
1812 if (route->metric > 0)
1813 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1816 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1819 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1822 nla_put_u32(msg, RTA_TABLE, table);
1824 if (route->flags & DEVROUTE_MTU) {
1825 struct nlattr *metrics;
1827 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1828 goto nla_put_failure;
1830 nla_put_u32(msg, RTAX_MTU, route->mtu);
1832 nla_nest_end(msg, metrics);
1835 return system_rtnl_call(msg);
1842 int system_add_route(struct device *dev, struct device_route *route)
1844 return system_rt(dev, route, RTM_NEWROUTE);
1847 int system_del_route(struct device *dev, struct device_route *route)
1849 return system_rt(dev, route, RTM_DELROUTE);
1852 int system_flush_routes(void)
1854 const char *names[] = {
1855 "/proc/sys/net/ipv4/route/flush",
1856 "/proc/sys/net/ipv6/route/flush"
1860 for (i = 0; i < ARRAY_SIZE(names); i++) {
1861 fd = open(names[i], O_WRONLY);
1865 if (write(fd, "-1", 2)) {}
1871 bool system_resolve_rt_type(const char *type, unsigned int *id)
1873 return system_rtn_aton(type, id);
1876 bool system_resolve_rt_table(const char *name, unsigned int *id)
1880 unsigned int n, table = RT_TABLE_UNSPEC;
1882 /* first try to parse table as number */
1883 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1886 /* handle well known aliases */
1887 else if (!strcmp(name, "default"))
1888 table = RT_TABLE_DEFAULT;
1889 else if (!strcmp(name, "main"))
1890 table = RT_TABLE_MAIN;
1891 else if (!strcmp(name, "local"))
1892 table = RT_TABLE_LOCAL;
1894 /* try to look up name in /etc/iproute2/rt_tables */
1895 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1897 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1899 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1902 n = strtoul(e, NULL, 10);
1903 e = strtok(NULL, " \t\n");
1905 if (e && !strcmp(e, name))
1915 if (table == RT_TABLE_UNSPEC)
1922 bool system_is_default_rt_table(unsigned int id)
1924 return (id == RT_TABLE_MAIN);
1927 bool system_resolve_rpfilter(const char *filter, unsigned int *id)
1932 if (!strcmp(filter, "strict"))
1934 else if (!strcmp(filter, "loose"))
1937 n = strtoul(filter, &e, 0);
1938 if (*e || e == filter || n > 2)
1946 static int system_iprule(struct iprule *rule, int cmd)
1948 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1951 struct rtmsg rtm = {
1952 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1953 .rtm_protocol = RTPROT_STATIC,
1954 .rtm_scope = RT_SCOPE_UNIVERSE,
1955 .rtm_table = RT_TABLE_UNSPEC,
1956 .rtm_type = RTN_UNSPEC,
1960 if (cmd == RTM_NEWRULE)
1961 rtm.rtm_type = RTN_UNICAST;
1964 rtm.rtm_flags |= FIB_RULE_INVERT;
1966 if (rule->flags & IPRULE_SRC)
1967 rtm.rtm_src_len = rule->src_mask;
1969 if (rule->flags & IPRULE_DEST)
1970 rtm.rtm_dst_len = rule->dest_mask;
1972 if (rule->flags & IPRULE_TOS)
1973 rtm.rtm_tos = rule->tos;
1975 if (rule->flags & IPRULE_LOOKUP) {
1976 if (rule->lookup < 256)
1977 rtm.rtm_table = rule->lookup;
1980 if (rule->flags & IPRULE_ACTION)
1981 rtm.rtm_type = rule->action;
1982 else if (rule->flags & IPRULE_GOTO)
1983 rtm.rtm_type = FR_ACT_GOTO;
1984 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1985 rtm.rtm_type = FR_ACT_NOP;
1987 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1992 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1994 if (rule->flags & IPRULE_IN)
1995 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1997 if (rule->flags & IPRULE_OUT)
1998 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
2000 if (rule->flags & IPRULE_SRC)
2001 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
2003 if (rule->flags & IPRULE_DEST)
2004 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
2006 if (rule->flags & IPRULE_PRIORITY)
2007 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
2008 else if (cmd == RTM_NEWRULE)
2009 nla_put_u32(msg, FRA_PRIORITY, rule->order);
2011 if (rule->flags & IPRULE_FWMARK)
2012 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
2014 if (rule->flags & IPRULE_FWMASK)
2015 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
2017 if (rule->flags & IPRULE_LOOKUP) {
2018 if (rule->lookup >= 256)
2019 nla_put_u32(msg, FRA_TABLE, rule->lookup);
2022 if (rule->flags & IPRULE_GOTO)
2023 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
2025 return system_rtnl_call(msg);
2028 int system_add_iprule(struct iprule *rule)
2030 return system_iprule(rule, RTM_NEWRULE);
2033 int system_del_iprule(struct iprule *rule)
2035 return system_iprule(rule, RTM_DELRULE);
2038 int system_flush_iprules(void)
2043 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
2044 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
2046 memset(&rule, 0, sizeof(rule));
2049 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2052 rule.lookup = RT_TABLE_LOCAL;
2053 rv |= system_iprule(&rule, RTM_NEWRULE);
2055 rule.priority = 32766;
2056 rule.lookup = RT_TABLE_MAIN;
2057 rv |= system_iprule(&rule, RTM_NEWRULE);
2059 rule.priority = 32767;
2060 rule.lookup = RT_TABLE_DEFAULT;
2061 rv |= system_iprule(&rule, RTM_NEWRULE);
2064 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2067 rule.lookup = RT_TABLE_LOCAL;
2068 rv |= system_iprule(&rule, RTM_NEWRULE);
2070 rule.priority = 32766;
2071 rule.lookup = RT_TABLE_MAIN;
2072 rv |= system_iprule(&rule, RTM_NEWRULE);
2077 bool system_resolve_iprule_action(const char *action, unsigned int *id)
2079 return system_rtn_aton(action, id);
2082 time_t system_get_rtime(void)
2087 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
2090 if (gettimeofday(&tv, NULL) == 0)
2097 #define IP_DF 0x4000
2100 static int tunnel_ioctl(const char *name, int cmd, void *p)
2104 memset(&ifr, 0, sizeof(ifr));
2105 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
2106 ifr.ifr_ifru.ifru_data = p;
2107 return ioctl(sock_ioctl, cmd, &ifr);
2110 #ifdef IFLA_IPTUN_MAX
2111 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
2112 static int system_add_gre_tunnel(const char *name, const char *kind,
2113 const unsigned int link, struct blob_attr **tb, bool v6)
2116 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2117 struct blob_attr *cur;
2118 uint32_t ikey = 0, okey = 0, flags = 0, flowinfo = 0;
2119 uint16_t iflags = 0, oflags = 0;
2121 int ret = 0, ttl = 64;
2123 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2127 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2128 nla_put_string(nlm, IFLA_IFNAME, name);
2130 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2136 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2137 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2144 nla_put_u32(nlm, IFLA_GRE_LINK, link);
2146 if ((cur = tb[TUNNEL_ATTR_TTL]))
2147 ttl = blobmsg_get_u32(cur);
2149 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
2151 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2152 char *str = blobmsg_get_string(cur);
2153 if (strcmp(str, "inherit")) {
2156 if (!system_tos_aton(str, &uval)) {
2162 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
2167 flags |= IP6_TNL_F_USE_ORIG_TCLASS;
2173 if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) {
2174 uint8_t icsum, ocsum, iseqno, oseqno;
2175 if (sscanf(blobmsg_get_string(cur), "%u,%u,%hhu,%hhu,%hhu,%hhu",
2176 &ikey, &okey, &icsum, &ocsum, &iseqno, &oseqno) < 6) {
2201 struct in6_addr in6buf;
2202 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2203 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2207 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
2210 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2211 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2215 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
2217 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, 4);
2220 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
2223 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags);
2225 struct in_addr inbuf;
2228 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2229 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2233 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
2236 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2237 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2241 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
2243 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
2245 okey = inbuf.s_addr;
2250 ikey = inbuf.s_addr;
2256 if ((cur = tb[TUNNEL_ATTR_DF]))
2257 set_df = blobmsg_get_bool(cur);
2259 /* ttl !=0 and nopmtudisc are incompatible */
2260 if (ttl && !set_df) {
2265 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
2267 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
2271 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
2274 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
2277 nla_put_u32(nlm, IFLA_GRE_OKEY, okey);
2280 nla_put_u32(nlm, IFLA_GRE_IKEY, ikey);
2282 nla_nest_end(nlm, infodata);
2283 nla_nest_end(nlm, linkinfo);
2285 return system_rtnl_call(nlm);
2294 static int system_add_vti_tunnel(const char *name, const char *kind,
2295 const unsigned int link, struct blob_attr **tb, bool v6)
2298 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2299 struct blob_attr *cur;
2300 uint32_t ikey = 0, okey = 0;
2303 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2307 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2308 nla_put_string(nlm, IFLA_IFNAME, name);
2310 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2316 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2317 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2324 nla_put_u32(nlm, IFLA_VTI_LINK, link);
2326 if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) {
2327 if (sscanf(blobmsg_get_string(cur), "%u,%u",
2328 &ikey, &okey) < 2) {
2335 struct in6_addr in6buf;
2336 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2337 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2341 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(in6buf), &in6buf);
2344 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2345 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2349 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(in6buf), &in6buf);
2353 struct in_addr inbuf;
2355 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2356 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2360 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(inbuf), &inbuf);
2363 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2364 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2368 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(inbuf), &inbuf);
2374 nla_put_u32(nlm, IFLA_VTI_OKEY, htonl(okey));
2377 nla_put_u32(nlm, IFLA_VTI_IKEY, htonl(ikey));
2379 nla_nest_end(nlm, infodata);
2380 nla_nest_end(nlm, linkinfo);
2382 return system_rtnl_call(nlm);
2390 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
2392 struct blob_attr *cur;
2394 struct ip_tunnel_parm p = {
2403 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
2404 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
2407 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
2408 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
2411 if ((cur = tb[TUNNEL_ATTR_DF]))
2412 set_df = blobmsg_get_bool(cur);
2414 if ((cur = tb[TUNNEL_ATTR_TTL]))
2415 p.iph.ttl = blobmsg_get_u32(cur);
2417 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2418 char *str = blobmsg_get_string(cur);
2419 if (strcmp(str, "inherit")) {
2422 if (!system_tos_aton(str, &uval))
2430 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
2431 /* ttl !=0 and nopmtudisc are incompatible */
2432 if (p.iph.ttl && p.iph.frag_off == 0)
2435 strncpy(p.name, name, sizeof(p.name));
2437 switch (p.iph.protocol) {
2439 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
2441 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
2448 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
2450 struct blob_attr *cur;
2453 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2455 str = blobmsg_data(cur);
2457 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
2458 !strcmp(str, "greip6") || !strcmp(str, "gretapip6") ||
2459 !strcmp(str, "vtiip") || !strcmp(str, "vtiip6"))
2460 return system_link_del(name);
2462 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
2465 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
2467 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2469 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2470 blob_data(attr), blob_len(attr));
2472 return __system_del_ip_tunnel(name, tb);
2475 int system_update_ipv6_mtu(struct device *dev, int mtu)
2479 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
2482 int fd = open(buf, O_RDWR);
2485 ssize_t len = read(fd, buf, sizeof(buf) - 1);
2492 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) > 0)
2501 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
2503 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2504 struct blob_attr *cur;
2507 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2508 blob_data(attr), blob_len(attr));
2510 __system_del_ip_tunnel(name, tb);
2512 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2514 str = blobmsg_data(cur);
2516 unsigned int ttl = 0;
2517 if ((cur = tb[TUNNEL_ATTR_TTL])) {
2518 ttl = blobmsg_get_u32(cur);
2523 unsigned int link = 0;
2524 if ((cur = tb[TUNNEL_ATTR_LINK])) {
2525 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
2529 if (iface->l3_dev.dev)
2530 link = iface->l3_dev.dev->ifindex;
2533 if (!strcmp(str, "sit")) {
2534 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
2538 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
2540 struct ip_tunnel_6rd p6;
2542 memset(&p6, 0, sizeof(p6));
2544 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
2545 &p6.prefix, &mask) || mask > 128)
2547 p6.prefixlen = mask;
2549 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
2550 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
2551 &p6.relay_prefix, &mask) || mask > 32)
2553 p6.relay_prefixlen = mask;
2556 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
2557 __system_del_ip_tunnel(name, tb);
2562 #ifdef IFLA_IPTUN_MAX
2563 } else if (!strcmp(str, "ipip6")) {
2564 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2565 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2566 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2572 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2573 nla_put_string(nlm, IFLA_IFNAME, name);
2576 nla_put_u32(nlm, IFLA_LINK, link);
2578 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2583 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2584 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2591 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2593 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2594 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2595 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
2597 struct in6_addr in6buf;
2598 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2599 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2603 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2606 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2607 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2611 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2614 #ifdef IFLA_IPTUN_FMR_MAX
2615 if ((cur = tb[TUNNEL_ATTR_FMRS])) {
2616 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2618 struct blob_attr *fmr;
2619 unsigned rem, fmrcnt = 0;
2620 blobmsg_for_each_attr(fmr, cur, rem) {
2621 if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
2624 unsigned ip4len, ip6len, ealen, offset = 6;
2628 if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
2629 ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) {
2634 struct in6_addr ip6prefix;
2635 struct in_addr ip4prefix;
2636 if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
2637 inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) {
2642 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2644 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2645 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2646 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2647 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2648 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2649 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2651 nla_nest_end(nlm, rule);
2654 nla_nest_end(nlm, fmrs);
2658 nla_nest_end(nlm, infodata);
2659 nla_nest_end(nlm, linkinfo);
2661 return system_rtnl_call(nlm);
2665 } else if (!strcmp(str, "greip")) {
2666 return system_add_gre_tunnel(name, "gre", link, tb, false);
2667 } else if (!strcmp(str, "gretapip")) {
2668 return system_add_gre_tunnel(name, "gretap", link, tb, false);
2669 } else if (!strcmp(str, "greip6")) {
2670 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
2671 } else if (!strcmp(str, "gretapip6")) {
2672 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
2674 } else if (!strcmp(str, "vtiip")) {
2675 return system_add_vti_tunnel(name, "vti", link, tb, false);
2676 } else if (!strcmp(str, "vtiip6")) {
2677 return system_add_vti_tunnel(name, "vti6", link, tb, true);
2680 } else if (!strcmp(str, "ipip")) {
2681 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);