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 RT_TABLE_PRELOCAL
48 #define RT_TABLE_PRELOCAL 128
51 #ifndef IFA_F_NOPREFIXROUTE
52 #define IFA_F_NOPREFIXROUTE 0x200
56 #define IFA_FLAGS (IFA_MULTICAST + 1)
66 #include <netlink/msg.h>
67 #include <netlink/attr.h>
68 #include <netlink/socket.h>
69 #include <libubox/uloop.h>
76 struct uloop_fd uloop;
81 static int sock_ioctl = -1;
82 static struct nl_sock *sock_rtnl = NULL;
84 static int cb_rtnl_event(struct nl_msg *msg, void *arg);
85 static void handle_hotplug_event(struct uloop_fd *u, unsigned int events);
87 static char dev_buf[256];
90 handler_nl_event(struct uloop_fd *u, unsigned int events)
92 struct event_socket *ev = container_of(u, struct event_socket, uloop);
94 socklen_t errlen = sizeof(err);
97 nl_recvmsgs_default(ev->sock);
101 if (getsockopt(u->fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen))
106 // Increase rx buffer size on netlink socket
108 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
111 // Request full dump since some info got dropped
112 struct rtgenmsg msg = { .rtgen_family = AF_UNSPEC };
113 nl_send_simple(ev->sock, RTM_GETLINK, NLM_F_DUMP, &msg, sizeof(msg));
123 uloop_fd_delete(&ev->uloop);
127 static struct nl_sock *
128 create_socket(int protocol, int groups)
130 struct nl_sock *sock;
132 sock = nl_socket_alloc();
137 nl_join_groups(sock, groups);
139 if (nl_connect(sock, protocol))
146 create_raw_event_socket(struct event_socket *ev, int protocol, int groups,
147 uloop_fd_handler cb, int flags)
149 ev->sock = create_socket(protocol, groups);
153 ev->uloop.fd = nl_socket_get_fd(ev->sock);
155 if (uloop_fd_add(&ev->uloop, ULOOP_READ|flags))
162 create_event_socket(struct event_socket *ev, int protocol,
163 int (*cb)(struct nl_msg *msg, void *arg))
165 if (!create_raw_event_socket(ev, protocol, 0, handler_nl_event, ULOOP_ERROR_CB))
168 // Install the valid custom callback handler
169 nl_socket_modify_cb(ev->sock, NL_CB_VALID, NL_CB_CUSTOM, cb, NULL);
171 // Disable sequence number checking on event sockets
172 nl_socket_disable_seq_check(ev->sock);
174 // Increase rx buffer size to 65K on event sockets
176 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
183 system_rtn_aton(const char *src, unsigned int *dst)
188 if (!strcmp(src, "local"))
190 else if (!strcmp(src, "nat"))
192 else if (!strcmp(src, "broadcast"))
194 else if (!strcmp(src, "anycast"))
196 else if (!strcmp(src, "multicast"))
198 else if (!strcmp(src, "prohibit"))
200 else if (!strcmp(src, "unreachable"))
202 else if (!strcmp(src, "blackhole"))
204 else if (!strcmp(src, "xresolve"))
206 else if (!strcmp(src, "unicast"))
208 else if (!strcmp(src, "throw"))
210 else if (!strcmp(src, "failed_policy"))
211 n = RTN_FAILED_POLICY;
213 n = strtoul(src, &e, 0);
214 if (!e || *e || e == src || n > 255)
223 system_tos_aton(const char *src, unsigned *dst)
227 *dst = strtoul(src, &e, 16);
228 if (e == src || *e || *dst > 255)
234 int system_init(void)
236 static struct event_socket rtnl_event;
237 static struct event_socket hotplug_event;
239 sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0);
240 system_fd_set_cloexec(sock_ioctl);
242 // Prepare socket for routing / address control
243 sock_rtnl = create_socket(NETLINK_ROUTE, 0);
247 if (!create_event_socket(&rtnl_event, NETLINK_ROUTE, cb_rtnl_event))
250 if (!create_raw_event_socket(&hotplug_event, NETLINK_KOBJECT_UEVENT, 1,
251 handle_hotplug_event, 0))
254 // Receive network link events form kernel
255 nl_socket_add_membership(rtnl_event.sock, RTNLGRP_LINK);
260 static void system_set_sysctl(const char *path, const char *val)
264 fd = open(path, O_WRONLY);
268 if (write(fd, val, strlen(val))) {}
272 static void system_set_dev_sysctl(const char *path, const char *device, const char *val)
274 snprintf(dev_buf, sizeof(dev_buf), path, device);
275 system_set_sysctl(dev_buf, val);
278 static void system_set_disable_ipv6(struct device *dev, const char *val)
280 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val);
283 static void system_set_rpfilter(struct device *dev, const char *val)
285 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter", dev->ifname, val);
288 static void system_set_acceptlocal(struct device *dev, const char *val)
290 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local", dev->ifname, val);
293 static void system_set_igmpversion(struct device *dev, const char *val)
295 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version", dev->ifname, val);
298 static void system_set_mldversion(struct device *dev, const char *val)
300 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version", dev->ifname, val);
303 static void system_set_neigh4reachabletime(struct device *dev, const char *val)
305 system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms", dev->ifname, val);
308 static void system_set_neigh6reachabletime(struct device *dev, const char *val)
310 system_set_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms", dev->ifname, val);
313 static void system_set_dadtransmits(struct device *dev, const char *val)
315 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits", dev->ifname, val);
318 static void system_bridge_set_multicast_to_unicast(struct device *dev, const char *val)
320 system_set_dev_sysctl("/sys/class/net/%s/brport/multicast_to_unicast", dev->ifname, val);
323 static void system_bridge_set_hairpin_mode(struct device *dev, const char *val)
325 system_set_dev_sysctl("/sys/class/net/%s/brport/hairpin_mode", dev->ifname, val);
328 static void system_bridge_set_multicast_router(struct device *dev, const char *val, bool bridge)
330 system_set_dev_sysctl(bridge ? "/sys/class/net/%s/bridge/multicast_router" :
331 "/sys/class/net/%s/brport/multicast_router",
335 static void system_bridge_set_robustness(struct device *dev, const char *val)
337 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_startup_query_count",
339 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_last_member_count",
343 static void system_bridge_set_query_interval(struct device *dev, const char *val)
345 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_query_interval",
349 static void system_bridge_set_query_response_interval(struct device *dev, const char *val)
351 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_query_response_interval",
355 static void system_bridge_set_last_member_interval(struct device *dev, const char *val)
357 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_last_member_interval",
361 static void system_bridge_set_membership_interval(struct device *dev, const char *val)
363 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_membership_interval",
367 static void system_bridge_set_other_querier_timeout(struct device *dev, const char *val)
369 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier_interval",
373 static void system_bridge_set_startup_query_interval(struct device *dev, const char *val)
375 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_startup_query_interval",
379 static int system_get_sysctl(const char *path, char *buf, const size_t buf_sz)
381 int fd = -1, ret = -1;
383 fd = open(path, O_RDONLY);
387 ssize_t len = read(fd, buf, buf_sz - 1);
401 system_get_dev_sysctl(const char *path, const char *device, char *buf, const size_t buf_sz)
403 snprintf(dev_buf, sizeof(dev_buf), path, device);
404 return system_get_sysctl(dev_buf, buf, buf_sz);
407 static int system_get_disable_ipv6(struct device *dev, char *buf, const size_t buf_sz)
409 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6",
410 dev->ifname, buf, buf_sz);
413 static int system_get_rpfilter(struct device *dev, char *buf, const size_t buf_sz)
415 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter",
416 dev->ifname, buf, buf_sz);
419 static int system_get_acceptlocal(struct device *dev, char *buf, const size_t buf_sz)
421 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local",
422 dev->ifname, buf, buf_sz);
425 static int system_get_igmpversion(struct device *dev, char *buf, const size_t buf_sz)
427 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version",
428 dev->ifname, buf, buf_sz);
431 static int system_get_mldversion(struct device *dev, char *buf, const size_t buf_sz)
433 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version",
434 dev->ifname, buf, buf_sz);
437 static int system_get_neigh4reachabletime(struct device *dev, char *buf, const size_t buf_sz)
439 return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms",
440 dev->ifname, buf, buf_sz);
443 static int system_get_neigh6reachabletime(struct device *dev, char *buf, const size_t buf_sz)
445 return system_get_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms",
446 dev->ifname, buf, buf_sz);
449 static int system_get_dadtransmits(struct device *dev, char *buf, const size_t buf_sz)
451 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits",
452 dev->ifname, buf, buf_sz);
455 // Evaluate netlink messages
456 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
458 struct nlmsghdr *nh = nlmsg_hdr(msg);
459 struct nlattr *nla[__IFLA_MAX];
463 if (nh->nlmsg_type != RTM_NEWLINK)
466 nlmsg_parse(nh, sizeof(struct ifinfomsg), nla, __IFLA_MAX - 1, NULL);
467 if (!nla[IFLA_IFNAME])
470 struct device *dev = device_get(nla_data(nla[IFLA_IFNAME]), false);
474 if (!system_get_dev_sysctl("/sys/class/net/%s/carrier", dev->ifname, buf, sizeof(buf)))
475 link_state = strtoul(buf, NULL, 0);
477 device_set_link(dev, link_state ? true : false);
484 handle_hotplug_msg(char *data, int size)
486 const char *subsystem = NULL, *interface = NULL;
487 char *cur, *end, *sep;
492 if (!strncmp(data, "add@", 4))
494 else if (!strncmp(data, "remove@", 7))
499 skip = strlen(data) + 1;
502 for (cur = data + skip; cur < end; cur += skip) {
503 skip = strlen(cur) + 1;
505 sep = strchr(cur, '=');
510 if (!strcmp(cur, "INTERFACE"))
512 else if (!strcmp(cur, "SUBSYSTEM")) {
514 if (strcmp(subsystem, "net") != 0)
517 if (subsystem && interface)
523 dev = device_get(interface, false);
527 if (dev->type != &simple_device_type)
530 if (add && system_if_force_external(dev->ifname))
533 device_set_present(dev, add);
537 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
539 struct event_socket *ev = container_of(u, struct event_socket, uloop);
540 struct sockaddr_nl nla;
541 unsigned char *buf = NULL;
544 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
546 handle_hotplug_msg((char *) buf, size);
552 static int system_rtnl_call(struct nl_msg *msg)
556 ret = nl_send_auto_complete(sock_rtnl, msg);
562 return nl_wait_for_ack(sock_rtnl);
565 int system_bridge_delbr(struct device *bridge)
567 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
570 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
574 memset(&ifr, 0, sizeof(ifr));
576 ifr.ifr_ifindex = dev->ifindex;
579 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
580 return ioctl(sock_ioctl, cmd, &ifr);
583 static bool system_is_bridge(const char *name, char *buf, int buflen)
587 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
588 if (stat(buf, &st) < 0)
594 static char *system_get_bridge(const char *name, char *buf, int buflen)
600 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
601 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
605 len = readlink(gl.gl_pathv[0], buf, buflen);
613 path = strrchr(buf, '/');
621 system_bridge_set_wireless(struct device *bridge, struct device *dev)
623 bool mcast_to_ucast = dev->wireless_ap;
626 if (bridge->settings.flags & DEV_OPT_MULTICAST_TO_UNICAST &&
627 !bridge->settings.multicast_to_unicast)
628 mcast_to_ucast = false;
630 if (!mcast_to_ucast || dev->wireless_isolate)
633 system_bridge_set_multicast_to_unicast(dev, mcast_to_ucast ? "1" : "0");
634 system_bridge_set_hairpin_mode(dev, hairpin ? "1" : "0");
637 int system_bridge_addif(struct device *bridge, struct device *dev)
643 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
644 if (!oldbr || strcmp(oldbr, bridge->ifname) != 0)
645 ret = system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
648 system_bridge_set_wireless(bridge, dev);
650 if (dev->settings.flags & DEV_OPT_MULTICAST_ROUTER) {
651 snprintf(buf, sizeof(buf), "%i", dev->settings.multicast_router);
652 system_bridge_set_multicast_router(dev, buf, false);
658 int system_bridge_delif(struct device *bridge, struct device *dev)
660 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
663 int system_if_resolve(struct device *dev)
666 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
667 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
668 return ifr.ifr_ifindex;
673 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
677 memset(&ifr, 0, sizeof(ifr));
678 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
679 ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
680 ifr.ifr_flags |= add;
681 ifr.ifr_flags &= ~rem;
682 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
694 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
696 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
698 return ifa->ifa_index == ifindex;
701 static bool check_route(struct nlmsghdr *hdr, int ifindex)
703 struct rtmsg *r = NLMSG_DATA(hdr);
704 struct nlattr *tb[__RTA_MAX];
706 if (r->rtm_protocol == RTPROT_KERNEL &&
707 r->rtm_family == AF_INET6)
710 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
714 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
717 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
722 static int cb_clear_event(struct nl_msg *msg, void *arg)
724 struct clear_data *clr = arg;
725 struct nlmsghdr *hdr = nlmsg_hdr(msg);
726 bool (*cb)(struct nlmsghdr *, int ifindex);
732 if (hdr->nlmsg_type != RTM_NEWADDR)
739 if (hdr->nlmsg_type != RTM_NEWROUTE)
746 if (hdr->nlmsg_type != RTM_NEWRULE)
755 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
758 if (type == RTM_DELRULE)
759 D(SYSTEM, "Remove a rule\n");
761 D(SYSTEM, "Remove %s from device %s\n",
762 type == RTM_DELADDR ? "an address" : "a route",
764 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
765 hdr = nlmsg_hdr(clr->msg);
766 hdr->nlmsg_type = type;
767 hdr->nlmsg_flags = NLM_F_REQUEST;
769 nl_socket_disable_auto_ack(sock_rtnl);
770 nl_send_auto_complete(sock_rtnl, clr->msg);
771 nl_socket_enable_auto_ack(sock_rtnl);
777 cb_finish_event(struct nl_msg *msg, void *arg)
785 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
788 *pending = err->error;
793 system_if_clear_entries(struct device *dev, int type, int af)
795 struct clear_data clr;
796 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
799 .rtm_flags = RTM_F_CLONED,
801 int flags = NLM_F_DUMP;
810 clr.size = sizeof(struct rtgenmsg);
813 clr.size = sizeof(struct rtmsg);
822 clr.msg = nlmsg_alloc_simple(type, flags);
826 nlmsg_append(clr.msg, &rtm, clr.size, 0);
827 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
828 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
829 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
831 nl_send_auto_complete(sock_rtnl, clr.msg);
833 nl_recvmsgs(sock_rtnl, cb);
841 * Clear bridge (membership) state and bring down device
843 void system_if_clear_state(struct device *dev)
845 static char buf[256];
848 device_set_ifindex(dev, system_if_resolve(dev));
849 if (dev->external || !dev->ifindex)
852 system_if_flags(dev->ifname, 0, IFF_UP);
854 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
855 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
856 system_bridge_delbr(dev);
860 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
862 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
863 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
866 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
867 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
868 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
869 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
870 system_set_disable_ipv6(dev, "0");
873 static inline unsigned long
874 sec_to_jiffies(int val)
876 return (unsigned long) val * 100;
879 static void system_bridge_conf_multicast_deps(struct device *bridge,
880 struct bridge_config *cfg,
886 if (cfg->flags & BRIDGE_OPT_ROBUSTNESS ||
887 cfg->flags & BRIDGE_OPT_QUERY_INTERVAL ||
888 cfg->flags & BRIDGE_OPT_QUERY_RESPONSE_INTERVAL) {
889 val = cfg->robustness * cfg->query_interval +
890 cfg->query_response_interval;
892 snprintf(buf, buf_len, "%i", val);
893 system_bridge_set_membership_interval(bridge, buf);
895 val = cfg->robustness * cfg->query_interval +
896 cfg->query_response_interval / 2;
898 snprintf(buf, buf_len, "%i", val);
899 system_bridge_set_other_querier_timeout(bridge, buf);
902 if (cfg->flags & BRIDGE_OPT_QUERY_INTERVAL) {
903 val = cfg->query_interval / 4;
905 snprintf(buf, buf_len, "%i", val);
906 system_bridge_set_startup_query_interval(bridge, buf);
910 static void system_bridge_conf_multicast(struct device *bridge,
911 struct bridge_config *cfg,
915 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
916 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
918 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier",
919 bridge->ifname, cfg->multicast_querier ? "1" : "0");
921 snprintf(buf, buf_len, "%i", cfg->hash_max);
922 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/hash_max",
923 bridge->ifname, buf);
925 if (bridge->settings.flags & DEV_OPT_MULTICAST_ROUTER) {
926 snprintf(buf, buf_len, "%i", bridge->settings.multicast_router);
927 system_bridge_set_multicast_router(bridge, buf, true);
930 if (cfg->flags & BRIDGE_OPT_ROBUSTNESS) {
931 snprintf(buf, buf_len, "%i", cfg->robustness);
932 system_bridge_set_robustness(bridge, buf);
935 if (cfg->flags & BRIDGE_OPT_QUERY_INTERVAL) {
936 snprintf(buf, buf_len, "%i", cfg->query_interval);
937 system_bridge_set_query_interval(bridge, buf);
940 if (cfg->flags & BRIDGE_OPT_QUERY_RESPONSE_INTERVAL) {
941 snprintf(buf, buf_len, "%i", cfg->query_response_interval);
942 system_bridge_set_query_response_interval(bridge, buf);
945 if (cfg->flags & BRIDGE_OPT_LAST_MEMBER_INTERVAL) {
946 snprintf(buf, buf_len, "%i", cfg->last_member_interval);
947 system_bridge_set_last_member_interval(bridge, buf);
950 system_bridge_conf_multicast_deps(bridge, cfg, buf, buf_len);
953 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
956 unsigned long args[4] = {};
958 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
961 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
962 args[1] = !!cfg->stp;
963 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
965 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
966 args[1] = sec_to_jiffies(cfg->forward_delay);
967 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
969 system_bridge_conf_multicast(bridge, cfg, buf, sizeof(buf));
971 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
972 args[1] = cfg->priority;
973 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
975 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
976 args[0] = BRCTL_SET_AGEING_TIME;
977 args[1] = sec_to_jiffies(cfg->ageing_time);
978 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
981 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
982 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
983 args[1] = sec_to_jiffies(cfg->hello_time);
984 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
987 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
988 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
989 args[1] = sec_to_jiffies(cfg->max_age);
990 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
996 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
999 struct nlattr *linkinfo, *data;
1000 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
1002 static const struct {
1004 enum macvlan_mode val;
1006 { "private", MACVLAN_MODE_PRIVATE },
1007 { "vepa", MACVLAN_MODE_VEPA },
1008 { "bridge", MACVLAN_MODE_BRIDGE },
1009 { "passthru", MACVLAN_MODE_PASSTHRU },
1012 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1017 nlmsg_append(msg, &iim, sizeof(iim), 0);
1019 if (cfg->flags & MACVLAN_OPT_MACADDR)
1020 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
1021 nla_put_string(msg, IFLA_IFNAME, macvlan->ifname);
1022 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
1024 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1025 goto nla_put_failure;
1027 nla_put_string(msg, IFLA_INFO_KIND, "macvlan");
1029 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1030 goto nla_put_failure;
1033 for (i = 0; i < ARRAY_SIZE(modes); i++) {
1034 if (strcmp(cfg->mode, modes[i].name) != 0)
1037 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
1042 nla_nest_end(msg, data);
1043 nla_nest_end(msg, linkinfo);
1045 rv = system_rtnl_call(msg);
1047 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
1056 static int system_link_del(const char *ifname)
1059 struct ifinfomsg iim = {
1060 .ifi_family = AF_UNSPEC,
1064 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
1069 nlmsg_append(msg, &iim, sizeof(iim), 0);
1070 nla_put_string(msg, IFLA_IFNAME, ifname);
1071 return system_rtnl_call(msg);
1074 int system_macvlan_del(struct device *macvlan)
1076 return system_link_del(macvlan->ifname);
1079 static int system_vlan(struct device *dev, int id)
1081 struct vlan_ioctl_args ifr = {
1082 .cmd = SET_VLAN_NAME_TYPE_CMD,
1083 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
1086 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
1089 ifr.cmd = DEL_VLAN_CMD;
1092 ifr.cmd = ADD_VLAN_CMD;
1095 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
1096 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
1099 int system_vlan_add(struct device *dev, int id)
1101 return system_vlan(dev, id);
1104 int system_vlan_del(struct device *dev)
1106 return system_vlan(dev, -1);
1109 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
1112 struct nlattr *linkinfo, *data;
1113 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
1116 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
1121 nlmsg_append(msg, &iim, sizeof(iim), 0);
1122 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
1123 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
1125 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
1126 goto nla_put_failure;
1128 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
1130 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
1131 goto nla_put_failure;
1133 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
1135 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
1136 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
1138 if(cfg->proto == VLAN_PROTO_8021AD)
1139 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);
1142 nla_nest_end(msg, data);
1143 nla_nest_end(msg, linkinfo);
1145 rv = system_rtnl_call(msg);
1147 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
1156 int system_vlandev_del(struct device *vlandev)
1158 return system_link_del(vlandev->ifname);
1162 system_if_get_settings(struct device *dev, struct device_settings *s)
1167 memset(&ifr, 0, sizeof(ifr));
1168 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1170 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
1171 s->mtu = ifr.ifr_mtu;
1172 s->flags |= DEV_OPT_MTU;
1175 s->mtu6 = system_update_ipv6_mtu(dev, 0);
1177 s->flags |= DEV_OPT_MTU6;
1179 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
1180 s->txqueuelen = ifr.ifr_qlen;
1181 s->flags |= DEV_OPT_TXQUEUELEN;
1184 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
1185 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
1186 s->flags |= DEV_OPT_MACADDR;
1189 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
1190 s->ipv6 = !strtoul(buf, NULL, 0);
1191 s->flags |= DEV_OPT_IPV6;
1194 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
1195 s->promisc = ifr.ifr_flags & IFF_PROMISC;
1196 s->flags |= DEV_OPT_PROMISC;
1198 s->multicast = ifr.ifr_flags & IFF_MULTICAST;
1199 s->flags |= DEV_OPT_MULTICAST;
1202 if (!system_get_rpfilter(dev, buf, sizeof(buf))) {
1203 s->rpfilter = strtoul(buf, NULL, 0);
1204 s->flags |= DEV_OPT_RPFILTER;
1207 if (!system_get_acceptlocal(dev, buf, sizeof(buf))) {
1208 s->acceptlocal = strtoul(buf, NULL, 0);
1209 s->flags |= DEV_OPT_ACCEPTLOCAL;
1212 if (!system_get_igmpversion(dev, buf, sizeof(buf))) {
1213 s->igmpversion = strtoul(buf, NULL, 0);
1214 s->flags |= DEV_OPT_IGMPVERSION;
1217 if (!system_get_mldversion(dev, buf, sizeof(buf))) {
1218 s->mldversion = strtoul(buf, NULL, 0);
1219 s->flags |= DEV_OPT_MLDVERSION;
1222 if (!system_get_neigh4reachabletime(dev, buf, sizeof(buf))) {
1223 s->neigh4reachabletime = strtoul(buf, NULL, 0);
1224 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1227 if (!system_get_neigh6reachabletime(dev, buf, sizeof(buf))) {
1228 s->neigh6reachabletime = strtoul(buf, NULL, 0);
1229 s->flags |= DEV_OPT_NEIGHREACHABLETIME;
1232 if (!system_get_dadtransmits(dev, buf, sizeof(buf))) {
1233 s->dadtransmits = strtoul(buf, NULL, 0);
1234 s->flags |= DEV_OPT_DADTRANSMITS;
1239 system_if_set_rps_xps_val(const char *path, int val)
1245 if (glob(path, 0, NULL, &gl))
1248 snprintf(val_buf, sizeof(val_buf), "%x", val);
1249 for (i = 0; i < gl.gl_pathc; i++)
1250 system_set_sysctl(gl.gl_pathv[i], val_buf);
1256 system_if_apply_rps_xps(struct device *dev, struct device_settings *s)
1258 long n_cpus = sysconf(_SC_NPROCESSORS_ONLN);
1264 val = (1 << n_cpus) - 1;
1265 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/rps_cpus", dev->ifname);
1266 system_if_set_rps_xps_val(dev_buf, s->rps ? val : 0);
1268 snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/xps_cpus", dev->ifname);
1269 system_if_set_rps_xps_val(dev_buf, s->xps ? val : 0);
1273 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
1278 memset(&ifr, 0, sizeof(ifr));
1279 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1280 if (s->flags & DEV_OPT_MTU & apply_mask) {
1281 ifr.ifr_mtu = s->mtu;
1282 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
1283 s->flags &= ~DEV_OPT_MTU;
1285 if (s->flags & DEV_OPT_MTU6 & apply_mask) {
1286 system_update_ipv6_mtu(dev, s->mtu6);
1288 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
1289 ifr.ifr_qlen = s->txqueuelen;
1290 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
1291 s->flags &= ~DEV_OPT_TXQUEUELEN;
1293 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
1294 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
1295 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
1296 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
1297 s->flags &= ~DEV_OPT_MACADDR;
1299 if (s->flags & DEV_OPT_IPV6 & apply_mask)
1300 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
1301 if (s->flags & DEV_OPT_PROMISC & apply_mask) {
1302 if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
1303 !s->promisc ? IFF_PROMISC : 0) < 0)
1304 s->flags &= ~DEV_OPT_PROMISC;
1306 if (s->flags & DEV_OPT_RPFILTER & apply_mask) {
1307 snprintf(buf, sizeof(buf), "%d", s->rpfilter);
1308 system_set_rpfilter(dev, buf);
1310 if (s->flags & DEV_OPT_ACCEPTLOCAL & apply_mask)
1311 system_set_acceptlocal(dev, s->acceptlocal ? "1" : "0");
1312 if (s->flags & DEV_OPT_IGMPVERSION & apply_mask) {
1313 snprintf(buf, sizeof(buf), "%d", s->igmpversion);
1314 system_set_igmpversion(dev, buf);
1316 if (s->flags & DEV_OPT_MLDVERSION & apply_mask) {
1317 snprintf(buf, sizeof(buf), "%d", s->mldversion);
1318 system_set_mldversion(dev, buf);
1320 if (s->flags & DEV_OPT_NEIGHREACHABLETIME & apply_mask) {
1321 snprintf(buf, sizeof(buf), "%d", s->neigh4reachabletime);
1322 system_set_neigh4reachabletime(dev, buf);
1323 snprintf(buf, sizeof(buf), "%d", s->neigh6reachabletime);
1324 system_set_neigh6reachabletime(dev, buf);
1326 if (s->flags & DEV_OPT_DADTRANSMITS & apply_mask) {
1327 snprintf(buf, sizeof(buf), "%d", s->dadtransmits);
1328 system_set_dadtransmits(dev, buf);
1330 if (s->flags & DEV_OPT_MULTICAST & apply_mask) {
1331 if (system_if_flags(dev->ifname, s->multicast ? IFF_MULTICAST : 0,
1332 !s->multicast ? IFF_MULTICAST : 0) < 0)
1333 s->flags &= ~DEV_OPT_MULTICAST;
1336 system_if_apply_rps_xps(dev, s);
1339 int system_if_up(struct device *dev)
1341 system_if_get_settings(dev, &dev->orig_settings);
1342 /* Only keep orig settings based on what needs to be set */
1343 dev->orig_settings.valid_flags = dev->orig_settings.flags;
1344 dev->orig_settings.flags &= dev->settings.flags;
1345 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
1346 return system_if_flags(dev->ifname, IFF_UP, 0);
1349 int system_if_down(struct device *dev)
1351 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
1352 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
1356 struct if_check_data {
1362 #ifndef IFF_LOWER_UP
1363 #define IFF_LOWER_UP 0x10000
1366 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1368 struct nlmsghdr *nh = nlmsg_hdr(msg);
1369 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1370 struct if_check_data *chk = (struct if_check_data *)arg;
1372 if (nh->nlmsg_type != RTM_NEWLINK)
1375 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1376 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1381 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1383 struct if_check_data *chk = (struct if_check_data *)arg;
1388 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1390 struct if_check_data *chk = (struct if_check_data *)arg;
1392 device_set_present(chk->dev, false);
1393 device_set_link(chk->dev, false);
1394 chk->pending = err->error;
1399 int system_if_check(struct device *dev)
1401 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1403 struct ifinfomsg ifi = {
1404 .ifi_family = AF_UNSPEC,
1407 struct if_check_data chk = {
1413 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1417 if (nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1418 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1421 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1422 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1423 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1425 nl_send_auto_complete(sock_rtnl, msg);
1426 while (chk.pending > 0)
1427 nl_recvmsgs(sock_rtnl, cb);
1439 system_if_get_parent(struct device *dev)
1441 char buf[64], *devname;
1442 int ifindex, iflink, len;
1445 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1446 f = fopen(buf, "r");
1450 len = fread(buf, 1, sizeof(buf) - 1, f);
1457 iflink = strtoul(buf, NULL, 0);
1458 ifindex = system_if_resolve(dev);
1459 if (!iflink || iflink == ifindex)
1462 devname = if_indextoname(iflink, buf);
1466 return device_get(devname, true);
1470 read_string_file(int dir_fd, const char *file, char *buf, int len)
1476 fd = openat(dir_fd, file, O_RDONLY);
1481 len = read(fd, buf, len - 1);
1485 } else if (len > 0) {
1488 c = strchr(buf, '\n');
1501 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1506 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1508 *val = strtoull(buf, NULL, 0);
1513 /* Assume advertised flags == supported flags */
1514 static const struct {
1517 } ethtool_link_modes[] = {
1518 { ADVERTISED_10baseT_Half, "10H" },
1519 { ADVERTISED_10baseT_Full, "10F" },
1520 { ADVERTISED_100baseT_Half, "100H" },
1521 { ADVERTISED_100baseT_Full, "100F" },
1522 { ADVERTISED_1000baseT_Half, "1000H" },
1523 { ADVERTISED_1000baseT_Full, "1000F" },
1526 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1529 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1530 if (mask & ethtool_link_modes[i].mask)
1531 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1536 system_if_force_external(const char *ifname)
1541 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1542 return stat(buf, &s) == 0;
1546 system_if_dump_info(struct device *dev, struct blob_buf *b)
1548 struct ethtool_cmd ecmd;
1554 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
1555 dir_fd = open(buf, O_DIRECTORY);
1557 memset(&ecmd, 0, sizeof(ecmd));
1558 memset(&ifr, 0, sizeof(ifr));
1559 strcpy(ifr.ifr_name, dev->ifname);
1560 ifr.ifr_data = (caddr_t) &ecmd;
1561 ecmd.cmd = ETHTOOL_GSET;
1563 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1564 c = blobmsg_open_array(b, "link-advertising");
1565 system_add_link_modes(b, ecmd.advertising);
1566 blobmsg_close_array(b, c);
1568 c = blobmsg_open_array(b, "link-supported");
1569 system_add_link_modes(b, ecmd.supported);
1570 blobmsg_close_array(b, c);
1572 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1573 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1574 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1575 blobmsg_add_string_buffer(b);
1583 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1585 const char *const counters[] = {
1586 "collisions", "rx_frame_errors", "tx_compressed",
1587 "multicast", "rx_length_errors", "tx_dropped",
1588 "rx_bytes", "rx_missed_errors", "tx_errors",
1589 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1590 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1591 "rx_dropped", "tx_aborted_errors", "tx_packets",
1592 "rx_errors", "tx_bytes", "tx_window_errors",
1593 "rx_fifo_errors", "tx_carrier_errors",
1600 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1601 stats_dir = open(buf, O_DIRECTORY);
1605 for (i = 0; i < ARRAY_SIZE(counters); i++)
1606 if (read_uint64_file(stats_dir, counters[i], &val))
1607 blobmsg_add_u64(b, counters[i], val);
1613 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1615 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1616 int alen = v4 ? 4 : 16;
1617 unsigned int flags = 0;
1618 struct ifaddrmsg ifa = {
1619 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1620 .ifa_prefixlen = addr->mask,
1621 .ifa_index = dev->ifindex,
1625 if (cmd == RTM_NEWADDR)
1626 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1628 msg = nlmsg_alloc_simple(cmd, flags);
1632 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1633 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1635 if (addr->broadcast)
1636 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1637 if (addr->point_to_point)
1638 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1640 time_t now = system_get_rtime();
1641 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1643 if (addr->preferred_until) {
1644 int64_t preferred = addr->preferred_until - now;
1647 else if (preferred > UINT32_MAX)
1648 preferred = UINT32_MAX;
1650 cinfo.ifa_prefered = preferred;
1653 if (addr->valid_until) {
1654 int64_t valid = addr->valid_until - now;
1659 else if (valid > UINT32_MAX)
1662 cinfo.ifa_valid = valid;
1665 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1667 if (cmd == RTM_NEWADDR && (addr->flags & DEVADDR_OFFLINK))
1668 nla_put_u32(msg, IFA_FLAGS, IFA_F_NOPREFIXROUTE);
1671 return system_rtnl_call(msg);
1674 int system_add_address(struct device *dev, struct device_addr *addr)
1676 return system_addr(dev, addr, RTM_NEWADDR);
1679 int system_del_address(struct device *dev, struct device_addr *addr)
1681 return system_addr(dev, addr, RTM_DELADDR);
1684 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1686 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1688 unsigned int flags = 0;
1691 have_gw = !!route->nexthop.in.s_addr;
1693 have_gw = route->nexthop.in6.s6_addr32[0] ||
1694 route->nexthop.in6.s6_addr32[1] ||
1695 route->nexthop.in6.s6_addr32[2] ||
1696 route->nexthop.in6.s6_addr32[3];
1698 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1699 ? route->table : RT_TABLE_MAIN;
1701 struct rtmsg rtm = {
1702 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1703 .rtm_dst_len = route->mask,
1704 .rtm_src_len = route->sourcemask,
1705 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1706 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
1707 .rtm_scope = RT_SCOPE_NOWHERE,
1708 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1709 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1713 if (cmd == RTM_NEWROUTE) {
1714 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1716 if (!dev) { // Add null-route
1717 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1718 rtm.rtm_type = RTN_UNREACHABLE;
1721 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1724 if (route->flags & DEVROUTE_TYPE) {
1725 rtm.rtm_type = route->type;
1726 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
1727 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
1728 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
1729 rtm.rtm_table = RT_TABLE_LOCAL;
1732 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT) {
1733 rtm.rtm_scope = RT_SCOPE_HOST;
1734 } else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
1735 rtm.rtm_type == RTN_ANYCAST) {
1736 rtm.rtm_scope = RT_SCOPE_LINK;
1737 } else if (rtm.rtm_type == RTN_BLACKHOLE || rtm.rtm_type == RTN_UNREACHABLE ||
1738 rtm.rtm_type == RTN_PROHIBIT || rtm.rtm_type == RTN_FAILED_POLICY) {
1739 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1744 msg = nlmsg_alloc_simple(cmd, flags);
1748 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1751 nla_put(msg, RTA_DST, alen, &route->addr);
1753 if (route->sourcemask) {
1754 if (rtm.rtm_family == AF_INET)
1755 nla_put(msg, RTA_PREFSRC, alen, &route->source);
1757 nla_put(msg, RTA_SRC, alen, &route->source);
1760 if (route->metric > 0)
1761 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1764 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1767 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1770 nla_put_u32(msg, RTA_TABLE, table);
1772 if (route->flags & DEVROUTE_MTU) {
1773 struct nlattr *metrics;
1775 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1776 goto nla_put_failure;
1778 nla_put_u32(msg, RTAX_MTU, route->mtu);
1780 nla_nest_end(msg, metrics);
1783 return system_rtnl_call(msg);
1790 int system_add_route(struct device *dev, struct device_route *route)
1792 return system_rt(dev, route, RTM_NEWROUTE);
1795 int system_del_route(struct device *dev, struct device_route *route)
1797 return system_rt(dev, route, RTM_DELROUTE);
1800 int system_flush_routes(void)
1802 const char *names[] = {
1803 "/proc/sys/net/ipv4/route/flush",
1804 "/proc/sys/net/ipv6/route/flush"
1808 for (i = 0; i < ARRAY_SIZE(names); i++) {
1809 fd = open(names[i], O_WRONLY);
1813 if (write(fd, "-1", 2)) {}
1819 bool system_resolve_rt_type(const char *type, unsigned int *id)
1821 return system_rtn_aton(type, id);
1824 bool system_resolve_rt_table(const char *name, unsigned int *id)
1828 unsigned int n, table = RT_TABLE_UNSPEC;
1830 /* first try to parse table as number */
1831 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1834 /* handle well known aliases */
1835 else if (!strcmp(name, "default"))
1836 table = RT_TABLE_DEFAULT;
1837 else if (!strcmp(name, "main"))
1838 table = RT_TABLE_MAIN;
1839 else if (!strcmp(name, "local"))
1840 table = RT_TABLE_LOCAL;
1841 else if (!strcmp(name, "prelocal"))
1842 table = RT_TABLE_PRELOCAL;
1844 /* try to look up name in /etc/iproute2/rt_tables */
1845 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1847 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1849 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1852 n = strtoul(e, NULL, 10);
1853 e = strtok(NULL, " \t\n");
1855 if (e && !strcmp(e, name))
1865 if (table == RT_TABLE_UNSPEC)
1872 bool system_is_default_rt_table(unsigned int id)
1874 return (id == RT_TABLE_MAIN);
1877 bool system_resolve_rpfilter(const char *filter, unsigned int *id)
1882 if (!strcmp(filter, "strict"))
1884 else if (!strcmp(filter, "loose"))
1887 n = strtoul(filter, &e, 0);
1888 if (*e || e == filter || n > 2)
1896 static int system_iprule(struct iprule *rule, int cmd)
1898 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1901 struct rtmsg rtm = {
1902 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1903 .rtm_protocol = RTPROT_STATIC,
1904 .rtm_scope = RT_SCOPE_UNIVERSE,
1905 .rtm_table = RT_TABLE_UNSPEC,
1906 .rtm_type = RTN_UNSPEC,
1910 if (cmd == RTM_NEWRULE)
1911 rtm.rtm_type = RTN_UNICAST;
1914 rtm.rtm_flags |= FIB_RULE_INVERT;
1916 if (rule->flags & IPRULE_SRC)
1917 rtm.rtm_src_len = rule->src_mask;
1919 if (rule->flags & IPRULE_DEST)
1920 rtm.rtm_dst_len = rule->dest_mask;
1922 if (rule->flags & IPRULE_TOS)
1923 rtm.rtm_tos = rule->tos;
1925 if (rule->flags & IPRULE_LOOKUP) {
1926 if (rule->lookup < 256)
1927 rtm.rtm_table = rule->lookup;
1930 if (rule->flags & IPRULE_ACTION)
1931 rtm.rtm_type = rule->action;
1932 else if (rule->flags & IPRULE_GOTO)
1933 rtm.rtm_type = FR_ACT_GOTO;
1934 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1935 rtm.rtm_type = FR_ACT_NOP;
1937 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1942 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1944 if (rule->flags & IPRULE_IN)
1945 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1947 if (rule->flags & IPRULE_OUT)
1948 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1950 if (rule->flags & IPRULE_SRC)
1951 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1953 if (rule->flags & IPRULE_DEST)
1954 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1956 if (rule->flags & IPRULE_PRIORITY)
1957 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1958 else if (cmd == RTM_NEWRULE)
1959 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1961 if (rule->flags & IPRULE_FWMARK)
1962 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1964 if (rule->flags & IPRULE_FWMASK)
1965 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1967 if (rule->flags & IPRULE_LOOKUP) {
1968 if (rule->lookup >= 256)
1969 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1972 if (rule->flags & IPRULE_GOTO)
1973 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1975 return system_rtnl_call(msg);
1978 int system_add_iprule(struct iprule *rule)
1980 return system_iprule(rule, RTM_NEWRULE);
1983 int system_del_iprule(struct iprule *rule)
1985 return system_iprule(rule, RTM_DELRULE);
1988 int system_flush_iprules(void)
1993 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1994 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1996 memset(&rule, 0, sizeof(rule));
1999 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2002 rule.lookup = RT_TABLE_PRELOCAL;
2003 rv |= system_iprule(&rule, RTM_NEWRULE);
2006 rule.lookup = RT_TABLE_LOCAL;
2007 rv |= system_iprule(&rule, RTM_NEWRULE);
2009 rule.priority = 32766;
2010 rule.lookup = RT_TABLE_MAIN;
2011 rv |= system_iprule(&rule, RTM_NEWRULE);
2013 rule.priority = 32767;
2014 rule.lookup = RT_TABLE_DEFAULT;
2015 rv |= system_iprule(&rule, RTM_NEWRULE);
2018 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
2021 rule.lookup = RT_TABLE_PRELOCAL;
2022 rv |= system_iprule(&rule, RTM_NEWRULE);
2025 rule.lookup = RT_TABLE_LOCAL;
2026 rv |= system_iprule(&rule, RTM_NEWRULE);
2028 rule.priority = 32766;
2029 rule.lookup = RT_TABLE_MAIN;
2030 rv |= system_iprule(&rule, RTM_NEWRULE);
2035 bool system_resolve_iprule_action(const char *action, unsigned int *id)
2037 return system_rtn_aton(action, id);
2040 time_t system_get_rtime(void)
2045 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
2048 if (gettimeofday(&tv, NULL) == 0)
2055 #define IP_DF 0x4000
2058 static int tunnel_ioctl(const char *name, int cmd, void *p)
2062 memset(&ifr, 0, sizeof(ifr));
2063 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
2064 ifr.ifr_ifru.ifru_data = p;
2065 return ioctl(sock_ioctl, cmd, &ifr);
2068 #ifdef IFLA_IPTUN_MAX
2069 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
2070 static int system_add_gre_tunnel(const char *name, const char *kind,
2071 const unsigned int link, struct blob_attr **tb, bool v6)
2074 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2075 struct blob_attr *cur;
2076 uint32_t ikey = 0, okey = 0, flags = 0, flowinfo = 0;
2077 uint16_t iflags = 0, oflags = 0;
2079 int ret = 0, ttl = 64;
2081 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2085 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2086 nla_put_string(nlm, IFLA_IFNAME, name);
2088 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2094 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2095 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2102 nla_put_u32(nlm, IFLA_GRE_LINK, link);
2104 if ((cur = tb[TUNNEL_ATTR_TTL]))
2105 ttl = blobmsg_get_u32(cur);
2107 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
2109 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2110 char *str = blobmsg_get_string(cur);
2111 if (strcmp(str, "inherit")) {
2114 if (!system_tos_aton(str, &uval)) {
2120 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
2125 flags |= IP6_TNL_F_USE_ORIG_TCLASS;
2131 if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) {
2132 uint8_t icsum, ocsum, iseqno, oseqno;
2133 if (sscanf(blobmsg_get_string(cur), "%u,%u,%hhu,%hhu,%hhu,%hhu",
2134 &ikey, &okey, &icsum, &ocsum, &iseqno, &oseqno) < 6) {
2159 struct in6_addr in6buf;
2160 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2161 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2165 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
2168 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2169 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2173 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
2175 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, 4);
2178 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
2181 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags);
2183 struct in_addr inbuf;
2186 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2187 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2191 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
2194 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2195 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2199 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
2201 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
2203 okey = inbuf.s_addr;
2208 ikey = inbuf.s_addr;
2214 if ((cur = tb[TUNNEL_ATTR_DF]))
2215 set_df = blobmsg_get_bool(cur);
2217 /* ttl !=0 and nopmtudisc are incompatible */
2218 if (ttl && !set_df) {
2223 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
2225 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
2229 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
2232 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
2235 nla_put_u32(nlm, IFLA_GRE_OKEY, okey);
2238 nla_put_u32(nlm, IFLA_GRE_IKEY, ikey);
2240 nla_nest_end(nlm, infodata);
2241 nla_nest_end(nlm, linkinfo);
2243 return system_rtnl_call(nlm);
2252 static int system_add_vti_tunnel(const char *name, const char *kind,
2253 const unsigned int link, struct blob_attr **tb, bool v6)
2256 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
2257 struct blob_attr *cur;
2258 uint32_t ikey = 0, okey = 0;
2261 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2265 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2266 nla_put_string(nlm, IFLA_IFNAME, name);
2268 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2274 nla_put_string(nlm, IFLA_INFO_KIND, kind);
2275 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2282 nla_put_u32(nlm, IFLA_VTI_LINK, link);
2284 if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) {
2285 if (sscanf(blobmsg_get_string(cur), "%u,%u",
2286 &ikey, &okey) < 2) {
2293 struct in6_addr in6buf;
2294 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2295 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2299 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(in6buf), &in6buf);
2302 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2303 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2307 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(in6buf), &in6buf);
2311 struct in_addr inbuf;
2313 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2314 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2318 nla_put(nlm, IFLA_VTI_LOCAL, sizeof(inbuf), &inbuf);
2321 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2322 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
2326 nla_put(nlm, IFLA_VTI_REMOTE, sizeof(inbuf), &inbuf);
2332 nla_put_u32(nlm, IFLA_VTI_OKEY, htonl(okey));
2335 nla_put_u32(nlm, IFLA_VTI_IKEY, htonl(ikey));
2337 nla_nest_end(nlm, infodata);
2338 nla_nest_end(nlm, linkinfo);
2340 return system_rtnl_call(nlm);
2348 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
2350 struct blob_attr *cur;
2352 struct ip_tunnel_parm p = {
2361 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
2362 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
2365 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
2366 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
2369 if ((cur = tb[TUNNEL_ATTR_DF]))
2370 set_df = blobmsg_get_bool(cur);
2372 if ((cur = tb[TUNNEL_ATTR_TTL]))
2373 p.iph.ttl = blobmsg_get_u32(cur);
2375 if ((cur = tb[TUNNEL_ATTR_TOS])) {
2376 char *str = blobmsg_get_string(cur);
2377 if (strcmp(str, "inherit")) {
2380 if (!system_tos_aton(str, &uval))
2388 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
2389 /* ttl !=0 and nopmtudisc are incompatible */
2390 if (p.iph.ttl && p.iph.frag_off == 0)
2393 strncpy(p.name, name, sizeof(p.name));
2395 switch (p.iph.protocol) {
2397 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
2399 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
2406 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
2408 struct blob_attr *cur;
2411 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2413 str = blobmsg_data(cur);
2415 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
2416 !strcmp(str, "greip6") || !strcmp(str, "gretapip6") ||
2417 !strcmp(str, "vtiip") || !strcmp(str, "vtiip6"))
2418 return system_link_del(name);
2420 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
2423 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
2425 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2427 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2428 blob_data(attr), blob_len(attr));
2430 return __system_del_ip_tunnel(name, tb);
2433 int system_update_ipv6_mtu(struct device *dev, int mtu)
2437 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
2440 int fd = open(buf, O_RDWR);
2443 ssize_t len = read(fd, buf, sizeof(buf) - 1);
2450 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) > 0)
2459 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
2461 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2462 struct blob_attr *cur;
2465 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2466 blob_data(attr), blob_len(attr));
2468 __system_del_ip_tunnel(name, tb);
2470 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2472 str = blobmsg_data(cur);
2474 unsigned int ttl = 0;
2475 if ((cur = tb[TUNNEL_ATTR_TTL])) {
2476 ttl = blobmsg_get_u32(cur);
2481 unsigned int link = 0;
2482 if ((cur = tb[TUNNEL_ATTR_LINK])) {
2483 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
2487 if (iface->l3_dev.dev)
2488 link = iface->l3_dev.dev->ifindex;
2491 if (!strcmp(str, "sit")) {
2492 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
2496 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
2498 struct ip_tunnel_6rd p6;
2500 memset(&p6, 0, sizeof(p6));
2502 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
2503 &p6.prefix, &mask) || mask > 128)
2505 p6.prefixlen = mask;
2507 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
2508 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
2509 &p6.relay_prefix, &mask) || mask > 32)
2511 p6.relay_prefixlen = mask;
2514 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
2515 __system_del_ip_tunnel(name, tb);
2520 #ifdef IFLA_IPTUN_MAX
2521 } else if (!strcmp(str, "ipip6")) {
2522 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2523 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2524 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2530 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2531 nla_put_string(nlm, IFLA_IFNAME, name);
2534 nla_put_u32(nlm, IFLA_LINK, link);
2536 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2541 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2542 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2549 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2551 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2552 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2553 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
2555 struct in6_addr in6buf;
2556 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2557 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2561 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2564 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2565 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2569 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2572 #ifdef IFLA_IPTUN_FMR_MAX
2573 if ((cur = tb[TUNNEL_ATTR_FMRS])) {
2574 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2576 struct blob_attr *fmr;
2577 unsigned rem, fmrcnt = 0;
2578 blobmsg_for_each_attr(fmr, cur, rem) {
2579 if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
2582 unsigned ip4len, ip6len, ealen, offset = 6;
2586 if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
2587 ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) {
2592 struct in6_addr ip6prefix;
2593 struct in_addr ip4prefix;
2594 if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
2595 inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) {
2600 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2602 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2603 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2604 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2605 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2606 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2607 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2609 nla_nest_end(nlm, rule);
2612 nla_nest_end(nlm, fmrs);
2616 nla_nest_end(nlm, infodata);
2617 nla_nest_end(nlm, linkinfo);
2619 return system_rtnl_call(nlm);
2623 } else if (!strcmp(str, "greip")) {
2624 return system_add_gre_tunnel(name, "gre", link, tb, false);
2625 } else if (!strcmp(str, "gretapip")) {
2626 return system_add_gre_tunnel(name, "gretap", link, tb, false);
2627 } else if (!strcmp(str, "greip6")) {
2628 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
2629 } else if (!strcmp(str, "gretapip6")) {
2630 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
2632 } else if (!strcmp(str, "vtiip")) {
2633 return system_add_vti_tunnel(name, "vti", link, tb, false);
2634 } else if (!strcmp(str, "vtiip6")) {
2635 return system_add_vti_tunnel(name, "vti6", link, tb, true);
2638 } else if (!strcmp(str, "ipip")) {
2639 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);