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;
949 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
956 memset(&ifr, 0, sizeof(ifr));
957 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
958 if (s->flags & DEV_OPT_MTU & apply_mask) {
959 ifr.ifr_mtu = s->mtu;
960 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
961 s->flags &= ~DEV_OPT_MTU;
963 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
964 ifr.ifr_qlen = s->txqueuelen;
965 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
966 s->flags &= ~DEV_OPT_TXQUEUELEN;
968 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
969 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
970 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
971 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
972 s->flags &= ~DEV_OPT_MACADDR;
974 if (s->flags & DEV_OPT_IPV6 & apply_mask)
975 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
978 int system_if_up(struct device *dev)
980 system_if_get_settings(dev, &dev->orig_settings);
981 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
982 device_set_ifindex(dev, system_if_resolve(dev));
983 return system_if_flags(dev->ifname, IFF_UP, 0);
986 int system_if_down(struct device *dev)
988 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
989 dev->orig_settings.flags &= dev->settings.flags;
990 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
994 struct if_check_data {
1000 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1002 struct nlmsghdr *nh = nlmsg_hdr(msg);
1003 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1004 struct if_check_data *chk = (struct if_check_data *)arg;
1006 if (nh->nlmsg_type != RTM_NEWLINK)
1009 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1010 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1015 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1017 struct if_check_data *chk = (struct if_check_data *)arg;
1022 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1024 struct if_check_data *chk = (struct if_check_data *)arg;
1026 device_set_present(chk->dev, false);
1027 device_set_link(chk->dev, false);
1028 chk->pending = err->error;
1033 int system_if_check(struct device *dev)
1035 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1037 struct ifinfomsg ifi = {
1038 .ifi_family = AF_UNSPEC,
1041 struct if_check_data chk = {
1047 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1048 if (!msg || nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1049 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1052 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1053 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1054 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1056 nl_send_auto_complete(sock_rtnl, msg);
1057 while (chk.pending > 0)
1058 nl_recvmsgs(sock_rtnl, cb);
1069 system_if_get_parent(struct device *dev)
1071 char buf[64], *devname;
1072 int ifindex, iflink, len;
1075 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1076 f = fopen(buf, "r");
1080 len = fread(buf, 1, sizeof(buf) - 1, f);
1087 iflink = strtoul(buf, NULL, 0);
1088 ifindex = system_if_resolve(dev);
1089 if (!iflink || iflink == ifindex)
1092 devname = if_indextoname(iflink, buf);
1096 return device_get(devname, true);
1100 read_string_file(int dir_fd, const char *file, char *buf, int len)
1106 fd = openat(dir_fd, file, O_RDONLY);
1111 len = read(fd, buf, len - 1);
1115 } else if (len > 0) {
1118 c = strchr(buf, '\n');
1131 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1136 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1138 *val = strtoull(buf, NULL, 0);
1143 /* Assume advertised flags == supported flags */
1144 static const struct {
1147 } ethtool_link_modes[] = {
1148 { ADVERTISED_10baseT_Half, "10H" },
1149 { ADVERTISED_10baseT_Full, "10F" },
1150 { ADVERTISED_100baseT_Half, "100H" },
1151 { ADVERTISED_100baseT_Full, "100F" },
1152 { ADVERTISED_1000baseT_Half, "1000H" },
1153 { ADVERTISED_1000baseT_Full, "1000F" },
1156 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1159 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1160 if (mask & ethtool_link_modes[i].mask)
1161 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1166 system_if_force_external(const char *ifname)
1171 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1172 return stat(buf, &s) == 0;
1176 system_if_dump_info(struct device *dev, struct blob_buf *b)
1178 struct ethtool_cmd ecmd;
1184 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
1185 dir_fd = open(buf, O_DIRECTORY);
1187 memset(&ecmd, 0, sizeof(ecmd));
1188 memset(&ifr, 0, sizeof(ifr));
1189 strcpy(ifr.ifr_name, dev->ifname);
1190 ifr.ifr_data = (caddr_t) &ecmd;
1191 ecmd.cmd = ETHTOOL_GSET;
1193 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1194 c = blobmsg_open_array(b, "link-advertising");
1195 system_add_link_modes(b, ecmd.advertising);
1196 blobmsg_close_array(b, c);
1198 c = blobmsg_open_array(b, "link-supported");
1199 system_add_link_modes(b, ecmd.supported);
1200 blobmsg_close_array(b, c);
1202 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1203 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1204 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1205 blobmsg_add_string_buffer(b);
1213 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1215 const char *const counters[] = {
1216 "collisions", "rx_frame_errors", "tx_compressed",
1217 "multicast", "rx_length_errors", "tx_dropped",
1218 "rx_bytes", "rx_missed_errors", "tx_errors",
1219 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1220 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1221 "rx_dropped", "tx_aborted_errors", "tx_packets",
1222 "rx_errors", "tx_bytes", "tx_window_errors",
1223 "rx_fifo_errors", "tx_carrier_errors",
1230 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1231 stats_dir = open(buf, O_DIRECTORY);
1235 for (i = 0; i < ARRAY_SIZE(counters); i++)
1236 if (read_uint64_file(stats_dir, counters[i], &val))
1237 blobmsg_add_u64(b, counters[i], val);
1243 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1245 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1246 int alen = v4 ? 4 : 16;
1247 unsigned int flags = 0;
1248 struct ifaddrmsg ifa = {
1249 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1250 .ifa_prefixlen = addr->mask,
1251 .ifa_index = dev->ifindex,
1255 if (cmd == RTM_NEWADDR)
1256 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1258 msg = nlmsg_alloc_simple(cmd, flags);
1262 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1263 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1265 if (addr->broadcast)
1266 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1267 if (addr->point_to_point)
1268 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1270 time_t now = system_get_rtime();
1271 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1273 if (addr->preferred_until) {
1274 int64_t preferred = addr->preferred_until - now;
1277 else if (preferred > UINT32_MAX)
1278 preferred = UINT32_MAX;
1280 cinfo.ifa_prefered = preferred;
1283 if (addr->valid_until) {
1284 int64_t valid = addr->valid_until - now;
1287 else if (valid > UINT32_MAX)
1290 cinfo.ifa_valid = valid;
1293 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1296 return system_rtnl_call(msg);
1299 int system_add_address(struct device *dev, struct device_addr *addr)
1301 return system_addr(dev, addr, RTM_NEWADDR);
1304 int system_del_address(struct device *dev, struct device_addr *addr)
1306 return system_addr(dev, addr, RTM_DELADDR);
1309 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1311 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1313 unsigned int flags = 0;
1316 have_gw = !!route->nexthop.in.s_addr;
1318 have_gw = route->nexthop.in6.s6_addr32[0] ||
1319 route->nexthop.in6.s6_addr32[1] ||
1320 route->nexthop.in6.s6_addr32[2] ||
1321 route->nexthop.in6.s6_addr32[3];
1323 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1324 ? route->table : RT_TABLE_MAIN;
1326 struct rtmsg rtm = {
1327 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1328 .rtm_dst_len = route->mask,
1329 .rtm_src_len = route->sourcemask,
1330 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1331 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
1332 .rtm_scope = RT_SCOPE_NOWHERE,
1333 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1334 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1338 if (cmd == RTM_NEWROUTE) {
1339 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1341 if (!dev) { // Add null-route
1342 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1343 rtm.rtm_type = RTN_UNREACHABLE;
1346 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1349 if (route->flags & DEVROUTE_TYPE) {
1350 rtm.rtm_type = route->type;
1351 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
1352 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
1353 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
1354 rtm.rtm_table = RT_TABLE_LOCAL;
1357 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT)
1358 rtm.rtm_scope = RT_SCOPE_HOST;
1359 else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
1360 rtm.rtm_type == RTN_ANYCAST)
1361 rtm.rtm_scope = RT_SCOPE_LINK;
1364 msg = nlmsg_alloc_simple(cmd, flags);
1368 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1371 nla_put(msg, RTA_DST, alen, &route->addr);
1373 if (route->sourcemask)
1374 nla_put(msg, RTA_SRC, alen, &route->source);
1376 if (route->metric > 0)
1377 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1380 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1383 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1386 nla_put_u32(msg, RTA_TABLE, table);
1388 if (route->flags & DEVROUTE_MTU) {
1389 struct nlattr *metrics;
1391 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1392 goto nla_put_failure;
1394 nla_put_u32(msg, RTAX_MTU, route->mtu);
1396 nla_nest_end(msg, metrics);
1399 return system_rtnl_call(msg);
1406 int system_add_route(struct device *dev, struct device_route *route)
1408 return system_rt(dev, route, RTM_NEWROUTE);
1411 int system_del_route(struct device *dev, struct device_route *route)
1413 return system_rt(dev, route, RTM_DELROUTE);
1416 int system_flush_routes(void)
1418 const char *names[] = {
1419 "/proc/sys/net/ipv4/route/flush",
1420 "/proc/sys/net/ipv6/route/flush"
1424 for (i = 0; i < ARRAY_SIZE(names); i++) {
1425 fd = open(names[i], O_WRONLY);
1429 if (write(fd, "-1", 2)) {}
1435 bool system_resolve_rt_type(const char *type, unsigned int *id)
1437 return system_rtn_aton(type, id);
1440 bool system_resolve_rt_table(const char *name, unsigned int *id)
1444 unsigned int n, table = RT_TABLE_UNSPEC;
1446 /* first try to parse table as number */
1447 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1450 /* handle well known aliases */
1451 else if (!strcmp(name, "default"))
1452 table = RT_TABLE_DEFAULT;
1453 else if (!strcmp(name, "main"))
1454 table = RT_TABLE_MAIN;
1455 else if (!strcmp(name, "local"))
1456 table = RT_TABLE_LOCAL;
1458 /* try to look up name in /etc/iproute2/rt_tables */
1459 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1461 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1463 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1466 n = strtoul(e, NULL, 10);
1467 e = strtok(NULL, " \t\n");
1469 if (e && !strcmp(e, name))
1479 if (table == RT_TABLE_UNSPEC)
1486 bool system_is_default_rt_table(unsigned int id)
1488 return (id == RT_TABLE_MAIN);
1491 static int system_iprule(struct iprule *rule, int cmd)
1493 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1496 struct rtmsg rtm = {
1497 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1498 .rtm_protocol = RTPROT_STATIC,
1499 .rtm_scope = RT_SCOPE_UNIVERSE,
1500 .rtm_table = RT_TABLE_UNSPEC,
1501 .rtm_type = RTN_UNSPEC,
1505 if (cmd == RTM_NEWRULE) {
1506 rtm.rtm_type = RTN_UNICAST;
1507 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1511 rtm.rtm_flags |= FIB_RULE_INVERT;
1513 if (rule->flags & IPRULE_SRC)
1514 rtm.rtm_src_len = rule->src_mask;
1516 if (rule->flags & IPRULE_DEST)
1517 rtm.rtm_dst_len = rule->dest_mask;
1519 if (rule->flags & IPRULE_TOS)
1520 rtm.rtm_tos = rule->tos;
1522 if (rule->flags & IPRULE_LOOKUP) {
1523 if (rule->lookup < 256)
1524 rtm.rtm_table = rule->lookup;
1527 if (rule->flags & IPRULE_ACTION)
1528 rtm.rtm_type = rule->action;
1529 else if (rule->flags & IPRULE_GOTO)
1530 rtm.rtm_type = FR_ACT_GOTO;
1531 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1532 rtm.rtm_type = FR_ACT_NOP;
1534 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1539 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1541 if (rule->flags & IPRULE_IN)
1542 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1544 if (rule->flags & IPRULE_OUT)
1545 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1547 if (rule->flags & IPRULE_SRC)
1548 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1550 if (rule->flags & IPRULE_DEST)
1551 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1553 if (rule->flags & IPRULE_PRIORITY)
1554 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1555 else if (cmd == RTM_NEWRULE)
1556 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1558 if (rule->flags & IPRULE_FWMARK)
1559 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1561 if (rule->flags & IPRULE_FWMASK)
1562 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1564 if (rule->flags & IPRULE_LOOKUP) {
1565 if (rule->lookup >= 256)
1566 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1569 if (rule->flags & IPRULE_GOTO)
1570 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1572 return system_rtnl_call(msg);
1575 int system_add_iprule(struct iprule *rule)
1577 return system_iprule(rule, RTM_NEWRULE);
1580 int system_del_iprule(struct iprule *rule)
1582 return system_iprule(rule, RTM_DELRULE);
1585 int system_flush_iprules(void)
1590 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1591 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1593 memset(&rule, 0, sizeof(rule));
1596 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1599 rule.lookup = RT_TABLE_LOCAL;
1600 rv |= system_iprule(&rule, RTM_NEWRULE);
1602 rule.priority = 32766;
1603 rule.lookup = RT_TABLE_MAIN;
1604 rv |= system_iprule(&rule, RTM_NEWRULE);
1606 rule.priority = 32767;
1607 rule.lookup = RT_TABLE_DEFAULT;
1608 rv |= system_iprule(&rule, RTM_NEWRULE);
1611 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1614 rule.lookup = RT_TABLE_LOCAL;
1615 rv |= system_iprule(&rule, RTM_NEWRULE);
1617 rule.priority = 32766;
1618 rule.lookup = RT_TABLE_MAIN;
1619 rv |= system_iprule(&rule, RTM_NEWRULE);
1624 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1626 return system_rtn_aton(action, id);
1629 time_t system_get_rtime(void)
1634 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1637 if (gettimeofday(&tv, NULL) == 0)
1644 #define IP_DF 0x4000
1647 static int tunnel_ioctl(const char *name, int cmd, void *p)
1651 memset(&ifr, 0, sizeof(ifr));
1652 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1653 ifr.ifr_ifru.ifru_data = p;
1654 return ioctl(sock_ioctl, cmd, &ifr);
1657 #ifdef IFLA_IPTUN_MAX
1658 static int system_add_gre_tunnel(const char *name, const char *kind,
1659 const unsigned int link, struct blob_attr **tb, bool v6)
1662 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
1663 struct blob_attr *cur;
1664 uint32_t ikey = 0, okey = 0;
1665 uint16_t iflags = 0, oflags = 0;
1666 int ret = 0, ttl = 64;
1668 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
1672 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
1673 nla_put_string(nlm, IFLA_IFNAME, name);
1675 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
1681 nla_put_string(nlm, IFLA_INFO_KIND, kind);
1682 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
1689 nla_put_u32(nlm, IFLA_GRE_LINK, link);
1691 if ((cur = tb[TUNNEL_ATTR_TTL]))
1692 ttl = blobmsg_get_u32(cur);
1694 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
1696 if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) {
1697 uint8_t icsum, ocsum, iseqno, oseqno;
1698 if (sscanf(blobmsg_get_string(cur), "%u,%u,%hhu,%hhu,%hhu,%hhu",
1699 &ikey, &okey, &icsum, &ocsum, &iseqno, &oseqno) < 6) {
1724 struct in6_addr in6buf;
1725 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1726 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1730 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
1733 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
1734 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1738 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
1740 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, 4);
1742 struct in_addr inbuf;
1745 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1746 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
1750 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
1753 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
1754 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
1758 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
1760 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
1762 okey = inbuf.s_addr;
1767 ikey = inbuf.s_addr;
1773 if ((cur = tb[TUNNEL_ATTR_DF]))
1774 set_df = blobmsg_get_bool(cur);
1776 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
1780 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
1783 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
1786 nla_put_u32(nlm, IFLA_GRE_OKEY, okey);
1789 nla_put_u32(nlm, IFLA_GRE_IKEY, ikey);
1791 nla_nest_end(nlm, infodata);
1792 nla_nest_end(nlm, linkinfo);
1794 return system_rtnl_call(nlm);
1802 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
1804 struct blob_attr *cur;
1807 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
1809 str = blobmsg_data(cur);
1811 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
1812 !strcmp(str, "greip6") || !strcmp(str, "gretapip6"))
1813 return system_link_del(name);
1815 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
1818 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
1820 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
1822 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
1823 blob_data(attr), blob_len(attr));
1825 return __system_del_ip_tunnel(name, tb);
1828 int system_update_ipv6_mtu(struct device *dev, int mtu)
1832 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
1835 int fd = open(buf, O_RDWR);
1836 ssize_t len = read(fd, buf, sizeof(buf) - 1);
1843 if (!mtu || ret <= mtu)
1846 lseek(fd, 0, SEEK_SET);
1847 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) <= 0)
1855 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
1857 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
1858 struct blob_attr *cur;
1862 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
1863 blob_data(attr), blob_len(attr));
1865 __system_del_ip_tunnel(name, tb);
1867 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
1869 str = blobmsg_data(cur);
1871 if ((cur = tb[TUNNEL_ATTR_DF]))
1872 set_df = blobmsg_get_bool(cur);
1874 unsigned int ttl = 0;
1875 if ((cur = tb[TUNNEL_ATTR_TTL])) {
1876 ttl = blobmsg_get_u32(cur);
1877 if (ttl > 255 || (!set_df && ttl))
1881 unsigned int link = 0;
1882 if ((cur = tb[TUNNEL_ATTR_LINK])) {
1883 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
1887 if (iface->l3_dev.dev)
1888 link = iface->l3_dev.dev->ifindex;
1891 if (!strcmp(str, "sit")) {
1892 struct ip_tunnel_parm p = {
1897 .frag_off = set_df ? htons(IP_DF) : 0,
1898 .protocol = IPPROTO_IPV6,
1903 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
1904 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
1907 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
1908 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
1911 strncpy(p.name, name, sizeof(p.name));
1912 if (tunnel_ioctl("sit0", SIOCADDTUNNEL, &p) < 0)
1916 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
1918 struct ip_tunnel_6rd p6;
1920 memset(&p6, 0, sizeof(p6));
1922 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
1923 &p6.prefix, &mask) || mask > 128)
1925 p6.prefixlen = mask;
1927 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
1928 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
1929 &p6.relay_prefix, &mask) || mask > 32)
1931 p6.relay_prefixlen = mask;
1934 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
1935 __system_del_ip_tunnel(name, tb);
1940 #ifdef IFLA_IPTUN_MAX
1941 } else if (!strcmp(str, "ipip6")) {
1942 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
1943 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
1944 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
1950 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
1951 nla_put_string(nlm, IFLA_IFNAME, name);
1954 nla_put_u32(nlm, IFLA_LINK, link);
1956 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
1961 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
1962 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
1969 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
1971 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
1972 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
1973 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
1975 struct in6_addr in6buf;
1976 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1977 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1981 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
1984 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
1985 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1989 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
1992 #ifdef IFLA_IPTUN_FMR_MAX
1993 if ((cur = tb[TUNNEL_ATTR_FMRS])) {
1994 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
1996 struct blob_attr *fmr;
1997 unsigned rem, fmrcnt = 0;
1998 blobmsg_for_each_attr(fmr, cur, rem) {
1999 if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
2002 unsigned ip4len, ip6len, ealen, offset = 6;
2006 if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
2007 ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) {
2012 struct in6_addr ip6prefix;
2013 struct in_addr ip4prefix;
2014 if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
2015 inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) {
2020 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2022 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2023 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2024 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2025 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2026 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2027 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2029 nla_nest_end(nlm, rule);
2032 nla_nest_end(nlm, fmrs);
2036 nla_nest_end(nlm, infodata);
2037 nla_nest_end(nlm, linkinfo);
2039 return system_rtnl_call(nlm);
2043 } else if (!strcmp(str, "greip")) {
2044 return system_add_gre_tunnel(name, "gre", link, tb, false);
2045 } else if (!strcmp(str, "gretapip")) {
2046 return system_add_gre_tunnel(name, "gretap", link, tb, false);
2047 } else if (!strcmp(str, "greip6")) {
2048 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
2049 } else if (!strcmp(str, "gretapip6")) {
2050 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);