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_link.h>
34 #include <linux/if_vlan.h>
35 #include <linux/if_bridge.h>
36 #include <linux/if_tunnel.h>
37 #include <linux/ip6_tunnel.h>
38 #include <linux/ethtool.h>
39 #include <linux/fib_rules.h>
40 #include <linux/version.h>
42 #ifndef RTN_FAILED_POLICY
43 #define RTN_FAILED_POLICY 12
51 #include <netlink/msg.h>
52 #include <netlink/attr.h>
53 #include <netlink/socket.h>
54 #include <libubox/uloop.h>
61 struct uloop_fd uloop;
66 static int sock_ioctl = -1;
67 static struct nl_sock *sock_rtnl = NULL;
69 static int cb_rtnl_event(struct nl_msg *msg, void *arg);
70 static void handle_hotplug_event(struct uloop_fd *u, unsigned int events);
72 static char dev_buf[256];
75 handler_nl_event(struct uloop_fd *u, unsigned int events)
77 struct event_socket *ev = container_of(u, struct event_socket, uloop);
79 socklen_t errlen = sizeof(err);
82 nl_recvmsgs_default(ev->sock);
86 if (getsockopt(u->fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen))
91 // Increase rx buffer size on netlink socket
93 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
96 // Request full dump since some info got dropped
97 struct rtgenmsg msg = { .rtgen_family = AF_UNSPEC };
98 nl_send_simple(ev->sock, RTM_GETLINK, NLM_F_DUMP, &msg, sizeof(msg));
108 uloop_fd_delete(&ev->uloop);
112 static struct nl_sock *
113 create_socket(int protocol, int groups)
115 struct nl_sock *sock;
117 sock = nl_socket_alloc();
122 nl_join_groups(sock, groups);
124 if (nl_connect(sock, protocol))
131 create_raw_event_socket(struct event_socket *ev, int protocol, int groups,
132 uloop_fd_handler cb, int flags)
134 ev->sock = create_socket(protocol, groups);
138 ev->uloop.fd = nl_socket_get_fd(ev->sock);
140 if (uloop_fd_add(&ev->uloop, ULOOP_READ|flags))
147 create_event_socket(struct event_socket *ev, int protocol,
148 int (*cb)(struct nl_msg *msg, void *arg))
150 if (!create_raw_event_socket(ev, protocol, 0, handler_nl_event, ULOOP_ERROR_CB))
153 // Install the valid custom callback handler
154 nl_socket_modify_cb(ev->sock, NL_CB_VALID, NL_CB_CUSTOM, cb, NULL);
156 // Disable sequence number checking on event sockets
157 nl_socket_disable_seq_check(ev->sock);
159 // Increase rx buffer size to 65K on event sockets
161 if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0))
168 system_rtn_aton(const char *src, unsigned int *dst)
173 if (!strcmp(src, "local"))
175 else if (!strcmp(src, "nat"))
177 else if (!strcmp(src, "broadcast"))
179 else if (!strcmp(src, "anycast"))
181 else if (!strcmp(src, "multicast"))
183 else if (!strcmp(src, "prohibit"))
185 else if (!strcmp(src, "unreachable"))
187 else if (!strcmp(src, "blackhole"))
189 else if (!strcmp(src, "xresolve"))
191 else if (!strcmp(src, "unicast"))
193 else if (!strcmp(src, "throw"))
195 else if (!strcmp(src, "failed_policy"))
196 n = RTN_FAILED_POLICY;
198 n = strtoul(src, &e, 0);
199 if (!e || *e || e == src || n > 255)
207 int system_init(void)
209 static struct event_socket rtnl_event;
210 static struct event_socket hotplug_event;
212 sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0);
213 system_fd_set_cloexec(sock_ioctl);
215 // Prepare socket for routing / address control
216 sock_rtnl = create_socket(NETLINK_ROUTE, 0);
220 if (!create_event_socket(&rtnl_event, NETLINK_ROUTE, cb_rtnl_event))
223 if (!create_raw_event_socket(&hotplug_event, NETLINK_KOBJECT_UEVENT, 1,
224 handle_hotplug_event, 0))
227 // Receive network link events form kernel
228 nl_socket_add_membership(rtnl_event.sock, RTNLGRP_LINK);
233 static void system_set_sysctl(const char *path, const char *val)
237 fd = open(path, O_WRONLY);
241 if (write(fd, val, strlen(val))) {}
245 static void system_set_dev_sysctl(const char *path, const char *device, const char *val)
247 snprintf(dev_buf, sizeof(dev_buf), path, device);
248 system_set_sysctl(dev_buf, val);
251 static void system_set_disable_ipv6(struct device *dev, const char *val)
253 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val);
256 static int system_get_sysctl(const char *path, char *buf, const size_t buf_sz)
258 int fd = -1, ret = -1;
260 fd = open(path, O_RDONLY);
264 ssize_t len = read(fd, buf, buf_sz - 1);
278 system_get_dev_sysctl(const char *path, const char *device, char *buf, const size_t buf_sz)
280 snprintf(dev_buf, sizeof(dev_buf), path, device);
281 return system_get_sysctl(dev_buf, buf, buf_sz);
284 static int system_get_disable_ipv6(struct device *dev, char *buf, const size_t buf_sz)
286 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6",
287 dev->ifname, buf, buf_sz);
291 #define IFF_LOWER_UP 0x10000
294 // Evaluate netlink messages
295 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
297 struct nlmsghdr *nh = nlmsg_hdr(msg);
298 struct ifinfomsg *ifi = NLMSG_DATA(nh);
299 struct nlattr *nla[__IFLA_MAX];
301 if (nh->nlmsg_type != RTM_NEWLINK)
304 nlmsg_parse(nh, sizeof(*ifi), nla, __IFLA_MAX - 1, NULL);
305 if (!nla[IFLA_IFNAME])
308 struct device *dev = device_get(nla_data(nla[IFLA_IFNAME]), false);
312 device_set_ifindex(dev, ifi->ifi_index);
313 device_set_link(dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
320 handle_hotplug_msg(char *data, int size)
322 const char *subsystem = NULL, *interface = NULL;
323 char *cur, *end, *sep;
328 if (!strncmp(data, "add@", 4))
330 else if (!strncmp(data, "remove@", 7))
335 skip = strlen(data) + 1;
338 for (cur = data + skip; cur < end; cur += skip) {
339 skip = strlen(cur) + 1;
341 sep = strchr(cur, '=');
346 if (!strcmp(cur, "INTERFACE"))
348 else if (!strcmp(cur, "SUBSYSTEM")) {
350 if (strcmp(subsystem, "net") != 0)
353 if (subsystem && interface)
359 dev = device_get(interface, false);
363 if (dev->type != &simple_device_type)
366 if (add && system_if_force_external(dev->ifname))
369 device_set_present(dev, add);
373 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
375 struct event_socket *ev = container_of(u, struct event_socket, uloop);
376 struct sockaddr_nl nla;
377 unsigned char *buf = NULL;
380 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
382 handle_hotplug_msg((char *) buf, size);
388 static int system_rtnl_call(struct nl_msg *msg)
392 ret = nl_send_auto_complete(sock_rtnl, msg);
398 return nl_wait_for_ack(sock_rtnl);
401 int system_bridge_delbr(struct device *bridge)
403 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
406 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
410 memset(&ifr, 0, sizeof(ifr));
412 ifr.ifr_ifindex = dev->ifindex;
415 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
416 return ioctl(sock_ioctl, cmd, &ifr);
419 static bool system_is_bridge(const char *name, char *buf, int buflen)
423 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
424 if (stat(buf, &st) < 0)
430 static char *system_get_bridge(const char *name, char *buf, int buflen)
436 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
437 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
440 if (gl.gl_pathc == 0)
443 len = readlink(gl.gl_pathv[0], buf, buflen);
448 path = strrchr(buf, '/');
455 static void system_bridge_set_wireless(const char *bridge, const char *dev)
457 snprintf(dev_buf, sizeof(dev_buf),
458 "/sys/devices/virtual/net/%s/brif/%s/multicast_to_unicast",
460 system_set_sysctl(dev_buf, "1");
463 int system_bridge_addif(struct device *bridge, struct device *dev)
468 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
469 if (!oldbr || strcmp(oldbr, bridge->ifname) != 0)
470 ret = system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
473 system_bridge_set_wireless(bridge->ifname, dev->ifname);
478 int system_bridge_delif(struct device *bridge, struct device *dev)
480 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
483 static int system_if_resolve(struct device *dev)
486 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
487 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
488 return ifr.ifr_ifindex;
493 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
497 memset(&ifr, 0, sizeof(ifr));
498 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
499 ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
500 ifr.ifr_flags |= add;
501 ifr.ifr_flags &= ~rem;
502 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
514 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
516 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
518 return ifa->ifa_index == ifindex;
521 static bool check_route(struct nlmsghdr *hdr, int ifindex)
523 struct rtmsg *r = NLMSG_DATA(hdr);
524 struct nlattr *tb[__RTA_MAX];
526 if (r->rtm_protocol == RTPROT_KERNEL &&
527 r->rtm_family == AF_INET6)
530 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
534 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
537 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
542 static int cb_clear_event(struct nl_msg *msg, void *arg)
544 struct clear_data *clr = arg;
545 struct nlmsghdr *hdr = nlmsg_hdr(msg);
546 bool (*cb)(struct nlmsghdr *, int ifindex);
552 if (hdr->nlmsg_type != RTM_NEWADDR)
559 if (hdr->nlmsg_type != RTM_NEWROUTE)
566 if (hdr->nlmsg_type != RTM_NEWRULE)
575 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
578 if (type == RTM_DELRULE)
579 D(SYSTEM, "Remove a rule\n");
581 D(SYSTEM, "Remove %s from device %s\n",
582 type == RTM_DELADDR ? "an address" : "a route",
584 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
585 hdr = nlmsg_hdr(clr->msg);
586 hdr->nlmsg_type = type;
587 hdr->nlmsg_flags = NLM_F_REQUEST;
589 nl_socket_disable_auto_ack(sock_rtnl);
590 nl_send_auto_complete(sock_rtnl, clr->msg);
591 nl_socket_enable_auto_ack(sock_rtnl);
597 cb_finish_event(struct nl_msg *msg, void *arg)
605 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
608 *pending = err->error;
613 system_if_clear_entries(struct device *dev, int type, int af)
615 struct clear_data clr;
616 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
619 .rtm_flags = RTM_F_CLONED,
621 int flags = NLM_F_DUMP;
630 clr.size = sizeof(struct rtgenmsg);
633 clr.size = sizeof(struct rtmsg);
642 clr.msg = nlmsg_alloc_simple(type, flags);
646 nlmsg_append(clr.msg, &rtm, clr.size, 0);
647 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
648 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
649 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
651 nl_send_auto_complete(sock_rtnl, clr.msg);
653 nl_recvmsgs(sock_rtnl, cb);
661 * Clear bridge (membership) state and bring down device
663 void system_if_clear_state(struct device *dev)
665 static char buf[256];
668 device_set_ifindex(dev, system_if_resolve(dev));
669 if (dev->external || !dev->ifindex)
672 system_if_flags(dev->ifname, 0, IFF_UP);
674 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
675 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
676 system_bridge_delbr(dev);
680 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
682 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
683 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
686 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
687 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
688 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
689 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
690 system_set_disable_ipv6(dev, "0");
693 static inline unsigned long
694 sec_to_jiffies(int val)
696 return (unsigned long) val * 100;
699 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
701 unsigned long args[4] = {};
703 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
706 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
707 args[1] = !!cfg->stp;
708 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
710 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
711 args[1] = sec_to_jiffies(cfg->forward_delay);
712 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
714 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
715 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
717 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier",
718 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
720 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
721 args[1] = cfg->priority;
722 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
724 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
725 args[0] = BRCTL_SET_AGEING_TIME;
726 args[1] = sec_to_jiffies(cfg->ageing_time);
727 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
730 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
731 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
732 args[1] = sec_to_jiffies(cfg->hello_time);
733 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
736 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
737 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
738 args[1] = sec_to_jiffies(cfg->max_age);
739 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
745 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
748 struct nlattr *linkinfo, *data;
749 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
750 int ifindex = system_if_resolve(dev);
752 static const struct {
754 enum macvlan_mode val;
756 { "private", MACVLAN_MODE_PRIVATE },
757 { "vepa", MACVLAN_MODE_VEPA },
758 { "bridge", MACVLAN_MODE_BRIDGE },
759 { "passthru", MACVLAN_MODE_PASSTHRU },
765 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
770 nlmsg_append(msg, &iim, sizeof(iim), 0);
772 if (cfg->flags & MACVLAN_OPT_MACADDR)
773 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
774 nla_put_string(msg, IFLA_IFNAME, macvlan->ifname);
775 nla_put_u32(msg, IFLA_LINK, ifindex);
777 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
778 goto nla_put_failure;
780 nla_put_string(msg, IFLA_INFO_KIND, "macvlan");
782 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
783 goto nla_put_failure;
786 for (i = 0; i < ARRAY_SIZE(modes); i++) {
787 if (strcmp(cfg->mode, modes[i].name) != 0)
790 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
795 nla_nest_end(msg, data);
796 nla_nest_end(msg, linkinfo);
798 rv = system_rtnl_call(msg);
800 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
809 static int system_link_del(const char *ifname)
812 struct ifinfomsg iim = {
813 .ifi_family = AF_UNSPEC,
817 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
822 nlmsg_append(msg, &iim, sizeof(iim), 0);
823 nla_put_string(msg, IFLA_IFNAME, ifname);
824 return system_rtnl_call(msg);
827 int system_macvlan_del(struct device *macvlan)
829 return system_link_del(macvlan->ifname);
832 static int system_vlan(struct device *dev, int id)
834 struct vlan_ioctl_args ifr = {
835 .cmd = SET_VLAN_NAME_TYPE_CMD,
836 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
839 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
842 ifr.cmd = DEL_VLAN_CMD;
845 ifr.cmd = ADD_VLAN_CMD;
848 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
849 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
852 int system_vlan_add(struct device *dev, int id)
854 return system_vlan(dev, id);
857 int system_vlan_del(struct device *dev)
859 return system_vlan(dev, -1);
862 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
865 struct nlattr *linkinfo, *data;
866 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
867 int ifindex = system_if_resolve(dev);
873 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
878 nlmsg_append(msg, &iim, sizeof(iim), 0);
879 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
880 nla_put_u32(msg, IFLA_LINK, ifindex);
882 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
883 goto nla_put_failure;
885 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
887 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
888 goto nla_put_failure;
890 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
892 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
893 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
895 if(cfg->proto == VLAN_PROTO_8021AD)
896 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);
899 nla_nest_end(msg, data);
900 nla_nest_end(msg, linkinfo);
902 rv = system_rtnl_call(msg);
904 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
913 int system_vlandev_del(struct device *vlandev)
915 return system_link_del(vlandev->ifname);
919 system_if_get_settings(struct device *dev, struct device_settings *s)
924 memset(&ifr, 0, sizeof(ifr));
925 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
927 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
928 s->mtu = ifr.ifr_mtu;
929 s->flags |= DEV_OPT_MTU;
932 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
933 s->txqueuelen = ifr.ifr_qlen;
934 s->flags |= DEV_OPT_TXQUEUELEN;
937 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
938 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
939 s->flags |= DEV_OPT_MACADDR;
942 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
943 s->ipv6 = !strtoul(buf, NULL, 0);
944 s->flags |= DEV_OPT_IPV6;
947 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
948 s->promisc = ifr.ifr_flags & IFF_PROMISC;
949 s->flags |= DEV_OPT_PROMISC;
954 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
961 memset(&ifr, 0, sizeof(ifr));
962 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
963 if (s->flags & DEV_OPT_MTU & apply_mask) {
964 ifr.ifr_mtu = s->mtu;
965 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
966 s->flags &= ~DEV_OPT_MTU;
968 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
969 ifr.ifr_qlen = s->txqueuelen;
970 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
971 s->flags &= ~DEV_OPT_TXQUEUELEN;
973 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
974 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
975 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
976 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
977 s->flags &= ~DEV_OPT_MACADDR;
979 if (s->flags & DEV_OPT_IPV6 & apply_mask)
980 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
981 if (s->flags & DEV_OPT_PROMISC & apply_mask) {
982 if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
983 !s->promisc ? IFF_PROMISC : 0) < 0)
984 s->flags &= ~DEV_OPT_PROMISC;
988 int system_if_up(struct device *dev)
990 system_if_get_settings(dev, &dev->orig_settings);
991 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
992 device_set_ifindex(dev, system_if_resolve(dev));
993 return system_if_flags(dev->ifname, IFF_UP, 0);
996 int system_if_down(struct device *dev)
998 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
999 dev->orig_settings.flags &= dev->settings.flags;
1000 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
1004 struct if_check_data {
1010 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1012 struct nlmsghdr *nh = nlmsg_hdr(msg);
1013 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1014 struct if_check_data *chk = (struct if_check_data *)arg;
1016 if (nh->nlmsg_type != RTM_NEWLINK)
1019 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1020 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1025 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1027 struct if_check_data *chk = (struct if_check_data *)arg;
1032 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1034 struct if_check_data *chk = (struct if_check_data *)arg;
1036 device_set_present(chk->dev, false);
1037 device_set_link(chk->dev, false);
1038 chk->pending = err->error;
1043 int system_if_check(struct device *dev)
1045 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1047 struct ifinfomsg ifi = {
1048 .ifi_family = AF_UNSPEC,
1051 struct if_check_data chk = {
1057 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1058 if (!msg || nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1059 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1062 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1063 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1064 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1066 nl_send_auto_complete(sock_rtnl, msg);
1067 while (chk.pending > 0)
1068 nl_recvmsgs(sock_rtnl, cb);
1079 system_if_get_parent(struct device *dev)
1081 char buf[64], *devname;
1082 int ifindex, iflink, len;
1085 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1086 f = fopen(buf, "r");
1090 len = fread(buf, 1, sizeof(buf) - 1, f);
1097 iflink = strtoul(buf, NULL, 0);
1098 ifindex = system_if_resolve(dev);
1099 if (!iflink || iflink == ifindex)
1102 devname = if_indextoname(iflink, buf);
1106 return device_get(devname, true);
1110 read_string_file(int dir_fd, const char *file, char *buf, int len)
1116 fd = openat(dir_fd, file, O_RDONLY);
1121 len = read(fd, buf, len - 1);
1125 } else if (len > 0) {
1128 c = strchr(buf, '\n');
1141 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1146 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1148 *val = strtoull(buf, NULL, 0);
1153 /* Assume advertised flags == supported flags */
1154 static const struct {
1157 } ethtool_link_modes[] = {
1158 { ADVERTISED_10baseT_Half, "10H" },
1159 { ADVERTISED_10baseT_Full, "10F" },
1160 { ADVERTISED_100baseT_Half, "100H" },
1161 { ADVERTISED_100baseT_Full, "100F" },
1162 { ADVERTISED_1000baseT_Half, "1000H" },
1163 { ADVERTISED_1000baseT_Full, "1000F" },
1166 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1169 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1170 if (mask & ethtool_link_modes[i].mask)
1171 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1176 system_if_force_external(const char *ifname)
1181 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1182 return stat(buf, &s) == 0;
1186 system_if_dump_info(struct device *dev, struct blob_buf *b)
1188 struct ethtool_cmd ecmd;
1194 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
1195 dir_fd = open(buf, O_DIRECTORY);
1197 memset(&ecmd, 0, sizeof(ecmd));
1198 memset(&ifr, 0, sizeof(ifr));
1199 strcpy(ifr.ifr_name, dev->ifname);
1200 ifr.ifr_data = (caddr_t) &ecmd;
1201 ecmd.cmd = ETHTOOL_GSET;
1203 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1204 c = blobmsg_open_array(b, "link-advertising");
1205 system_add_link_modes(b, ecmd.advertising);
1206 blobmsg_close_array(b, c);
1208 c = blobmsg_open_array(b, "link-supported");
1209 system_add_link_modes(b, ecmd.supported);
1210 blobmsg_close_array(b, c);
1212 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1213 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1214 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1215 blobmsg_add_string_buffer(b);
1223 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1225 const char *const counters[] = {
1226 "collisions", "rx_frame_errors", "tx_compressed",
1227 "multicast", "rx_length_errors", "tx_dropped",
1228 "rx_bytes", "rx_missed_errors", "tx_errors",
1229 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1230 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1231 "rx_dropped", "tx_aborted_errors", "tx_packets",
1232 "rx_errors", "tx_bytes", "tx_window_errors",
1233 "rx_fifo_errors", "tx_carrier_errors",
1240 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1241 stats_dir = open(buf, O_DIRECTORY);
1245 for (i = 0; i < ARRAY_SIZE(counters); i++)
1246 if (read_uint64_file(stats_dir, counters[i], &val))
1247 blobmsg_add_u64(b, counters[i], val);
1253 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1255 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1256 int alen = v4 ? 4 : 16;
1257 unsigned int flags = 0;
1258 struct ifaddrmsg ifa = {
1259 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1260 .ifa_prefixlen = addr->mask,
1261 .ifa_index = dev->ifindex,
1265 if (cmd == RTM_NEWADDR)
1266 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1268 msg = nlmsg_alloc_simple(cmd, flags);
1272 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1273 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1275 if (addr->broadcast)
1276 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1277 if (addr->point_to_point)
1278 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1280 time_t now = system_get_rtime();
1281 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1283 if (addr->preferred_until) {
1284 int64_t preferred = addr->preferred_until - now;
1287 else if (preferred > UINT32_MAX)
1288 preferred = UINT32_MAX;
1290 cinfo.ifa_prefered = preferred;
1293 if (addr->valid_until) {
1294 int64_t valid = addr->valid_until - now;
1297 else if (valid > UINT32_MAX)
1300 cinfo.ifa_valid = valid;
1303 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1306 return system_rtnl_call(msg);
1309 int system_add_address(struct device *dev, struct device_addr *addr)
1311 return system_addr(dev, addr, RTM_NEWADDR);
1314 int system_del_address(struct device *dev, struct device_addr *addr)
1316 return system_addr(dev, addr, RTM_DELADDR);
1319 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1321 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1323 unsigned int flags = 0;
1326 have_gw = !!route->nexthop.in.s_addr;
1328 have_gw = route->nexthop.in6.s6_addr32[0] ||
1329 route->nexthop.in6.s6_addr32[1] ||
1330 route->nexthop.in6.s6_addr32[2] ||
1331 route->nexthop.in6.s6_addr32[3];
1333 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1334 ? route->table : RT_TABLE_MAIN;
1336 struct rtmsg rtm = {
1337 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1338 .rtm_dst_len = route->mask,
1339 .rtm_src_len = route->sourcemask,
1340 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1341 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
1342 .rtm_scope = RT_SCOPE_NOWHERE,
1343 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1344 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1348 if (cmd == RTM_NEWROUTE) {
1349 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1351 if (!dev) { // Add null-route
1352 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1353 rtm.rtm_type = RTN_UNREACHABLE;
1356 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1359 if (route->flags & DEVROUTE_TYPE) {
1360 rtm.rtm_type = route->type;
1361 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
1362 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
1363 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
1364 rtm.rtm_table = RT_TABLE_LOCAL;
1367 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT)
1368 rtm.rtm_scope = RT_SCOPE_HOST;
1369 else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
1370 rtm.rtm_type == RTN_ANYCAST)
1371 rtm.rtm_scope = RT_SCOPE_LINK;
1374 msg = nlmsg_alloc_simple(cmd, flags);
1378 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1381 nla_put(msg, RTA_DST, alen, &route->addr);
1383 if (route->sourcemask)
1384 nla_put(msg, RTA_SRC, alen, &route->source);
1386 if (route->metric > 0)
1387 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1390 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1393 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1396 nla_put_u32(msg, RTA_TABLE, table);
1398 if (route->flags & DEVROUTE_MTU) {
1399 struct nlattr *metrics;
1401 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1402 goto nla_put_failure;
1404 nla_put_u32(msg, RTAX_MTU, route->mtu);
1406 nla_nest_end(msg, metrics);
1409 return system_rtnl_call(msg);
1416 int system_add_route(struct device *dev, struct device_route *route)
1418 return system_rt(dev, route, RTM_NEWROUTE);
1421 int system_del_route(struct device *dev, struct device_route *route)
1423 return system_rt(dev, route, RTM_DELROUTE);
1426 int system_flush_routes(void)
1428 const char *names[] = {
1429 "/proc/sys/net/ipv4/route/flush",
1430 "/proc/sys/net/ipv6/route/flush"
1434 for (i = 0; i < ARRAY_SIZE(names); i++) {
1435 fd = open(names[i], O_WRONLY);
1439 if (write(fd, "-1", 2)) {}
1445 bool system_resolve_rt_type(const char *type, unsigned int *id)
1447 return system_rtn_aton(type, id);
1450 bool system_resolve_rt_table(const char *name, unsigned int *id)
1454 unsigned int n, table = RT_TABLE_UNSPEC;
1456 /* first try to parse table as number */
1457 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1460 /* handle well known aliases */
1461 else if (!strcmp(name, "default"))
1462 table = RT_TABLE_DEFAULT;
1463 else if (!strcmp(name, "main"))
1464 table = RT_TABLE_MAIN;
1465 else if (!strcmp(name, "local"))
1466 table = RT_TABLE_LOCAL;
1468 /* try to look up name in /etc/iproute2/rt_tables */
1469 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1471 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1473 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1476 n = strtoul(e, NULL, 10);
1477 e = strtok(NULL, " \t\n");
1479 if (e && !strcmp(e, name))
1489 if (table == RT_TABLE_UNSPEC)
1496 bool system_is_default_rt_table(unsigned int id)
1498 return (id == RT_TABLE_MAIN);
1501 static int system_iprule(struct iprule *rule, int cmd)
1503 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1506 struct rtmsg rtm = {
1507 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1508 .rtm_protocol = RTPROT_STATIC,
1509 .rtm_scope = RT_SCOPE_UNIVERSE,
1510 .rtm_table = RT_TABLE_UNSPEC,
1511 .rtm_type = RTN_UNSPEC,
1515 if (cmd == RTM_NEWRULE) {
1516 rtm.rtm_type = RTN_UNICAST;
1517 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1521 rtm.rtm_flags |= FIB_RULE_INVERT;
1523 if (rule->flags & IPRULE_SRC)
1524 rtm.rtm_src_len = rule->src_mask;
1526 if (rule->flags & IPRULE_DEST)
1527 rtm.rtm_dst_len = rule->dest_mask;
1529 if (rule->flags & IPRULE_TOS)
1530 rtm.rtm_tos = rule->tos;
1532 if (rule->flags & IPRULE_LOOKUP) {
1533 if (rule->lookup < 256)
1534 rtm.rtm_table = rule->lookup;
1537 if (rule->flags & IPRULE_ACTION)
1538 rtm.rtm_type = rule->action;
1539 else if (rule->flags & IPRULE_GOTO)
1540 rtm.rtm_type = FR_ACT_GOTO;
1541 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1542 rtm.rtm_type = FR_ACT_NOP;
1544 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1549 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1551 if (rule->flags & IPRULE_IN)
1552 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1554 if (rule->flags & IPRULE_OUT)
1555 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1557 if (rule->flags & IPRULE_SRC)
1558 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1560 if (rule->flags & IPRULE_DEST)
1561 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1563 if (rule->flags & IPRULE_PRIORITY)
1564 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1565 else if (cmd == RTM_NEWRULE)
1566 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1568 if (rule->flags & IPRULE_FWMARK)
1569 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1571 if (rule->flags & IPRULE_FWMASK)
1572 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1574 if (rule->flags & IPRULE_LOOKUP) {
1575 if (rule->lookup >= 256)
1576 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1579 if (rule->flags & IPRULE_GOTO)
1580 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1582 return system_rtnl_call(msg);
1585 int system_add_iprule(struct iprule *rule)
1587 return system_iprule(rule, RTM_NEWRULE);
1590 int system_del_iprule(struct iprule *rule)
1592 return system_iprule(rule, RTM_DELRULE);
1595 int system_flush_iprules(void)
1600 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1601 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1603 memset(&rule, 0, sizeof(rule));
1606 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1609 rule.lookup = RT_TABLE_LOCAL;
1610 rv |= system_iprule(&rule, RTM_NEWRULE);
1612 rule.priority = 32766;
1613 rule.lookup = RT_TABLE_MAIN;
1614 rv |= system_iprule(&rule, RTM_NEWRULE);
1616 rule.priority = 32767;
1617 rule.lookup = RT_TABLE_DEFAULT;
1618 rv |= system_iprule(&rule, RTM_NEWRULE);
1621 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1624 rule.lookup = RT_TABLE_LOCAL;
1625 rv |= system_iprule(&rule, RTM_NEWRULE);
1627 rule.priority = 32766;
1628 rule.lookup = RT_TABLE_MAIN;
1629 rv |= system_iprule(&rule, RTM_NEWRULE);
1634 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1636 return system_rtn_aton(action, id);
1639 time_t system_get_rtime(void)
1644 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1647 if (gettimeofday(&tv, NULL) == 0)
1654 #define IP_DF 0x4000
1657 static int tunnel_ioctl(const char *name, int cmd, void *p)
1661 memset(&ifr, 0, sizeof(ifr));
1662 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1663 ifr.ifr_ifru.ifru_data = p;
1664 return ioctl(sock_ioctl, cmd, &ifr);
1667 #ifdef IFLA_IPTUN_MAX
1668 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
1669 static int system_add_gre_tunnel(const char *name, const char *kind,
1670 const unsigned int link, struct blob_attr **tb, bool v6)
1673 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
1674 struct blob_attr *cur;
1675 uint32_t ikey = 0, okey = 0, flags = 0, flowinfo = 0;
1676 uint16_t iflags = 0, oflags = 0;
1678 int ret = 0, ttl = 64;
1680 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
1684 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
1685 nla_put_string(nlm, IFLA_IFNAME, name);
1687 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
1693 nla_put_string(nlm, IFLA_INFO_KIND, kind);
1694 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
1701 nla_put_u32(nlm, IFLA_GRE_LINK, link);
1703 if ((cur = tb[TUNNEL_ATTR_TTL]))
1704 ttl = blobmsg_get_u32(cur);
1706 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
1708 if ((cur = tb[TUNNEL_ATTR_TOS])) {
1709 char *str = blobmsg_get_string(cur);
1710 if (strcmp(str, "inherit")) {
1714 uval = strtoul(str, &e, 16);
1715 if (e == str || *e || uval > 255) {
1720 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
1725 flags |= IP6_TNL_F_USE_ORIG_TCLASS;
1731 if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) {
1732 uint8_t icsum, ocsum, iseqno, oseqno;
1733 if (sscanf(blobmsg_get_string(cur), "%u,%u,%hhu,%hhu,%hhu,%hhu",
1734 &ikey, &okey, &icsum, &ocsum, &iseqno, &oseqno) < 6) {
1759 struct in6_addr in6buf;
1760 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1761 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1765 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
1768 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
1769 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1773 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
1775 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, 4);
1778 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
1781 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags);
1783 struct in_addr inbuf;
1786 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1787 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
1791 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
1794 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
1795 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
1799 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
1801 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
1803 okey = inbuf.s_addr;
1808 ikey = inbuf.s_addr;
1814 if ((cur = tb[TUNNEL_ATTR_DF]))
1815 set_df = blobmsg_get_bool(cur);
1817 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
1819 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
1823 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
1826 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
1829 nla_put_u32(nlm, IFLA_GRE_OKEY, okey);
1832 nla_put_u32(nlm, IFLA_GRE_IKEY, ikey);
1834 nla_nest_end(nlm, infodata);
1835 nla_nest_end(nlm, linkinfo);
1837 return system_rtnl_call(nlm);
1845 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
1847 struct blob_attr *cur;
1850 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
1852 str = blobmsg_data(cur);
1854 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
1855 !strcmp(str, "greip6") || !strcmp(str, "gretapip6"))
1856 return system_link_del(name);
1858 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
1861 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
1863 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
1865 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
1866 blob_data(attr), blob_len(attr));
1868 return __system_del_ip_tunnel(name, tb);
1871 int system_update_ipv6_mtu(struct device *dev, int mtu)
1875 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
1878 int fd = open(buf, O_RDWR);
1879 ssize_t len = read(fd, buf, sizeof(buf) - 1);
1886 if (!mtu || ret <= mtu)
1889 lseek(fd, 0, SEEK_SET);
1890 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) <= 0)
1898 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
1900 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
1901 struct blob_attr *cur;
1905 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
1906 blob_data(attr), blob_len(attr));
1908 __system_del_ip_tunnel(name, tb);
1910 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
1912 str = blobmsg_data(cur);
1914 if ((cur = tb[TUNNEL_ATTR_DF]))
1915 set_df = blobmsg_get_bool(cur);
1917 unsigned int ttl = 0;
1918 if ((cur = tb[TUNNEL_ATTR_TTL])) {
1919 ttl = blobmsg_get_u32(cur);
1920 if (ttl > 255 || (!set_df && ttl))
1924 unsigned int link = 0;
1925 if ((cur = tb[TUNNEL_ATTR_LINK])) {
1926 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
1930 if (iface->l3_dev.dev)
1931 link = iface->l3_dev.dev->ifindex;
1934 if (!strcmp(str, "sit")) {
1935 struct ip_tunnel_parm p = {
1940 .frag_off = set_df ? htons(IP_DF) : 0,
1941 .protocol = IPPROTO_IPV6,
1946 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
1947 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
1950 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
1951 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
1954 strncpy(p.name, name, sizeof(p.name));
1955 if (tunnel_ioctl("sit0", SIOCADDTUNNEL, &p) < 0)
1959 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
1961 struct ip_tunnel_6rd p6;
1963 memset(&p6, 0, sizeof(p6));
1965 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
1966 &p6.prefix, &mask) || mask > 128)
1968 p6.prefixlen = mask;
1970 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
1971 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
1972 &p6.relay_prefix, &mask) || mask > 32)
1974 p6.relay_prefixlen = mask;
1977 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
1978 __system_del_ip_tunnel(name, tb);
1983 #ifdef IFLA_IPTUN_MAX
1984 } else if (!strcmp(str, "ipip6")) {
1985 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
1986 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
1987 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
1993 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
1994 nla_put_string(nlm, IFLA_IFNAME, name);
1997 nla_put_u32(nlm, IFLA_LINK, link);
1999 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2004 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2005 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2012 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2014 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2015 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2016 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
2018 struct in6_addr in6buf;
2019 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2020 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2024 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2027 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2028 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2032 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2035 #ifdef IFLA_IPTUN_FMR_MAX
2036 if ((cur = tb[TUNNEL_ATTR_FMRS])) {
2037 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2039 struct blob_attr *fmr;
2040 unsigned rem, fmrcnt = 0;
2041 blobmsg_for_each_attr(fmr, cur, rem) {
2042 if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
2045 unsigned ip4len, ip6len, ealen, offset = 6;
2049 if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
2050 ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) {
2055 struct in6_addr ip6prefix;
2056 struct in_addr ip4prefix;
2057 if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
2058 inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) {
2063 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2065 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2066 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2067 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2068 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2069 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2070 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2072 nla_nest_end(nlm, rule);
2075 nla_nest_end(nlm, fmrs);
2079 nla_nest_end(nlm, infodata);
2080 nla_nest_end(nlm, linkinfo);
2082 return system_rtnl_call(nlm);
2086 } else if (!strcmp(str, "greip")) {
2087 return system_add_gre_tunnel(name, "gre", link, tb, false);
2088 } else if (!strcmp(str, "gretapip")) {
2089 return system_add_gre_tunnel(name, "gretap", link, tb, false);
2090 } else if (!strcmp(str, "greip6")) {
2091 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
2092 } else if (!strcmp(str, "gretapip6")) {
2093 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);