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)
208 system_tos_aton(const char *src, unsigned *dst)
212 *dst = strtoul(src, &e, 16);
213 if (e == src || *e || *dst > 255)
219 int system_init(void)
221 static struct event_socket rtnl_event;
222 static struct event_socket hotplug_event;
224 sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0);
225 system_fd_set_cloexec(sock_ioctl);
227 // Prepare socket for routing / address control
228 sock_rtnl = create_socket(NETLINK_ROUTE, 0);
232 if (!create_event_socket(&rtnl_event, NETLINK_ROUTE, cb_rtnl_event))
235 if (!create_raw_event_socket(&hotplug_event, NETLINK_KOBJECT_UEVENT, 1,
236 handle_hotplug_event, 0))
239 // Receive network link events form kernel
240 nl_socket_add_membership(rtnl_event.sock, RTNLGRP_LINK);
245 static void system_set_sysctl(const char *path, const char *val)
249 fd = open(path, O_WRONLY);
253 if (write(fd, val, strlen(val))) {}
257 static void system_set_dev_sysctl(const char *path, const char *device, const char *val)
259 snprintf(dev_buf, sizeof(dev_buf), path, device);
260 system_set_sysctl(dev_buf, val);
263 static void system_set_disable_ipv6(struct device *dev, const char *val)
265 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val);
268 static void system_set_rpfilter(struct device *dev, const char *val)
270 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter", dev->ifname, val);
273 static void system_set_acceptlocal(struct device *dev, const char *val)
275 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local", dev->ifname, val);
278 static void system_set_igmpversion(struct device *dev, const char *val)
280 system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version", dev->ifname, val);
283 static void system_set_mldversion(struct device *dev, const char *val)
285 system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version", dev->ifname, val);
288 static int system_get_sysctl(const char *path, char *buf, const size_t buf_sz)
290 int fd = -1, ret = -1;
292 fd = open(path, O_RDONLY);
296 ssize_t len = read(fd, buf, buf_sz - 1);
310 system_get_dev_sysctl(const char *path, const char *device, char *buf, const size_t buf_sz)
312 snprintf(dev_buf, sizeof(dev_buf), path, device);
313 return system_get_sysctl(dev_buf, buf, buf_sz);
316 static int system_get_disable_ipv6(struct device *dev, char *buf, const size_t buf_sz)
318 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6",
319 dev->ifname, buf, buf_sz);
322 static int system_get_rpfilter(struct device *dev, char *buf, const size_t buf_sz)
324 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter",
325 dev->ifname, buf, buf_sz);
328 static int system_get_acceptlocal(struct device *dev, char *buf, const size_t buf_sz)
330 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local",
331 dev->ifname, buf, buf_sz);
334 static int system_get_igmpversion(struct device *dev, char *buf, const size_t buf_sz)
336 return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version",
337 dev->ifname, buf, buf_sz);
340 static int system_get_mldversion(struct device *dev, char *buf, const size_t buf_sz)
342 return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version",
343 dev->ifname, buf, buf_sz);
346 // Evaluate netlink messages
347 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
349 struct nlmsghdr *nh = nlmsg_hdr(msg);
350 struct ifinfomsg *ifi = NLMSG_DATA(nh);
351 struct nlattr *nla[__IFLA_MAX];
355 if (nh->nlmsg_type != RTM_NEWLINK)
358 nlmsg_parse(nh, sizeof(*ifi), nla, __IFLA_MAX - 1, NULL);
359 if (!nla[IFLA_IFNAME])
362 struct device *dev = device_get(nla_data(nla[IFLA_IFNAME]), false);
363 if (!dev || dev->type->keep_link_status)
366 if (!system_get_dev_sysctl("/sys/class/net/%s/carrier", dev->ifname, buf, sizeof(buf)))
367 link_state = strtoul(buf, NULL, 0);
369 device_set_link(dev, link_state ? true : false);
376 handle_hotplug_msg(char *data, int size)
378 const char *subsystem = NULL, *interface = NULL;
379 char *cur, *end, *sep;
384 if (!strncmp(data, "add@", 4))
386 else if (!strncmp(data, "remove@", 7))
391 skip = strlen(data) + 1;
394 for (cur = data + skip; cur < end; cur += skip) {
395 skip = strlen(cur) + 1;
397 sep = strchr(cur, '=');
402 if (!strcmp(cur, "INTERFACE"))
404 else if (!strcmp(cur, "SUBSYSTEM")) {
406 if (strcmp(subsystem, "net") != 0)
409 if (subsystem && interface)
415 dev = device_get(interface, false);
419 if (dev->type != &simple_device_type)
422 if (add && system_if_force_external(dev->ifname))
425 device_set_present(dev, add);
429 handle_hotplug_event(struct uloop_fd *u, unsigned int events)
431 struct event_socket *ev = container_of(u, struct event_socket, uloop);
432 struct sockaddr_nl nla;
433 unsigned char *buf = NULL;
436 while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
438 handle_hotplug_msg((char *) buf, size);
444 static int system_rtnl_call(struct nl_msg *msg)
448 ret = nl_send_auto_complete(sock_rtnl, msg);
454 return nl_wait_for_ack(sock_rtnl);
457 int system_bridge_delbr(struct device *bridge)
459 return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
462 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
466 memset(&ifr, 0, sizeof(ifr));
468 ifr.ifr_ifindex = dev->ifindex;
471 strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
472 return ioctl(sock_ioctl, cmd, &ifr);
475 static bool system_is_bridge(const char *name, char *buf, int buflen)
479 snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
480 if (stat(buf, &st) < 0)
486 static char *system_get_bridge(const char *name, char *buf, int buflen)
492 snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
493 if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
497 len = readlink(gl.gl_pathv[0], buf, buflen);
505 path = strrchr(buf, '/');
512 static void system_bridge_set_wireless(const char *bridge, const char *dev)
514 snprintf(dev_buf, sizeof(dev_buf),
515 "/sys/devices/virtual/net/%s/brif/%s/multicast_to_unicast",
517 system_set_sysctl(dev_buf, "1");
520 int system_bridge_addif(struct device *bridge, struct device *dev)
525 oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
526 if (!oldbr || strcmp(oldbr, bridge->ifname) != 0)
527 ret = system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
530 system_bridge_set_wireless(bridge->ifname, dev->ifname);
535 int system_bridge_delif(struct device *bridge, struct device *dev)
537 return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
540 int system_if_resolve(struct device *dev)
543 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
544 if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
545 return ifr.ifr_ifindex;
550 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
554 memset(&ifr, 0, sizeof(ifr));
555 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
556 ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
557 ifr.ifr_flags |= add;
558 ifr.ifr_flags &= ~rem;
559 return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
571 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
573 struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
575 return ifa->ifa_index == ifindex;
578 static bool check_route(struct nlmsghdr *hdr, int ifindex)
580 struct rtmsg *r = NLMSG_DATA(hdr);
581 struct nlattr *tb[__RTA_MAX];
583 if (r->rtm_protocol == RTPROT_KERNEL &&
584 r->rtm_family == AF_INET6)
587 nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
591 return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
594 static bool check_rule(struct nlmsghdr *hdr, int ifindex)
599 static int cb_clear_event(struct nl_msg *msg, void *arg)
601 struct clear_data *clr = arg;
602 struct nlmsghdr *hdr = nlmsg_hdr(msg);
603 bool (*cb)(struct nlmsghdr *, int ifindex);
609 if (hdr->nlmsg_type != RTM_NEWADDR)
616 if (hdr->nlmsg_type != RTM_NEWROUTE)
623 if (hdr->nlmsg_type != RTM_NEWRULE)
632 if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
635 if (type == RTM_DELRULE)
636 D(SYSTEM, "Remove a rule\n");
638 D(SYSTEM, "Remove %s from device %s\n",
639 type == RTM_DELADDR ? "an address" : "a route",
641 memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
642 hdr = nlmsg_hdr(clr->msg);
643 hdr->nlmsg_type = type;
644 hdr->nlmsg_flags = NLM_F_REQUEST;
646 nl_socket_disable_auto_ack(sock_rtnl);
647 nl_send_auto_complete(sock_rtnl, clr->msg);
648 nl_socket_enable_auto_ack(sock_rtnl);
654 cb_finish_event(struct nl_msg *msg, void *arg)
662 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
665 *pending = err->error;
670 system_if_clear_entries(struct device *dev, int type, int af)
672 struct clear_data clr;
673 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
676 .rtm_flags = RTM_F_CLONED,
678 int flags = NLM_F_DUMP;
687 clr.size = sizeof(struct rtgenmsg);
690 clr.size = sizeof(struct rtmsg);
699 clr.msg = nlmsg_alloc_simple(type, flags);
703 nlmsg_append(clr.msg, &rtm, clr.size, 0);
704 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
705 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
706 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
708 nl_send_auto_complete(sock_rtnl, clr.msg);
710 nl_recvmsgs(sock_rtnl, cb);
718 * Clear bridge (membership) state and bring down device
720 void system_if_clear_state(struct device *dev)
722 static char buf[256];
725 device_set_ifindex(dev, system_if_resolve(dev));
726 if (dev->external || !dev->ifindex)
729 system_if_flags(dev->ifname, 0, IFF_UP);
731 if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
732 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
733 system_bridge_delbr(dev);
737 bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
739 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
740 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
743 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
744 system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
745 system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
746 system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
747 system_set_disable_ipv6(dev, "0");
750 static inline unsigned long
751 sec_to_jiffies(int val)
753 return (unsigned long) val * 100;
756 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
758 unsigned long args[4] = {};
760 if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
763 args[0] = BRCTL_SET_BRIDGE_STP_STATE;
764 args[1] = !!cfg->stp;
765 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
767 args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
768 args[1] = sec_to_jiffies(cfg->forward_delay);
769 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
771 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
772 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
774 system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier",
775 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
777 args[0] = BRCTL_SET_BRIDGE_PRIORITY;
778 args[1] = cfg->priority;
779 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
781 if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
782 args[0] = BRCTL_SET_AGEING_TIME;
783 args[1] = sec_to_jiffies(cfg->ageing_time);
784 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
787 if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
788 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
789 args[1] = sec_to_jiffies(cfg->hello_time);
790 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
793 if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
794 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
795 args[1] = sec_to_jiffies(cfg->max_age);
796 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
802 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg)
805 struct nlattr *linkinfo, *data;
806 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
808 static const struct {
810 enum macvlan_mode val;
812 { "private", MACVLAN_MODE_PRIVATE },
813 { "vepa", MACVLAN_MODE_VEPA },
814 { "bridge", MACVLAN_MODE_BRIDGE },
815 { "passthru", MACVLAN_MODE_PASSTHRU },
818 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
823 nlmsg_append(msg, &iim, sizeof(iim), 0);
825 if (cfg->flags & MACVLAN_OPT_MACADDR)
826 nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr);
827 nla_put_string(msg, IFLA_IFNAME, macvlan->ifname);
828 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
830 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
831 goto nla_put_failure;
833 nla_put_string(msg, IFLA_INFO_KIND, "macvlan");
835 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
836 goto nla_put_failure;
839 for (i = 0; i < ARRAY_SIZE(modes); i++) {
840 if (strcmp(cfg->mode, modes[i].name) != 0)
843 nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val);
848 nla_nest_end(msg, data);
849 nla_nest_end(msg, linkinfo);
851 rv = system_rtnl_call(msg);
853 D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv);
862 static int system_link_del(const char *ifname)
865 struct ifinfomsg iim = {
866 .ifi_family = AF_UNSPEC,
870 msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST);
875 nlmsg_append(msg, &iim, sizeof(iim), 0);
876 nla_put_string(msg, IFLA_IFNAME, ifname);
877 return system_rtnl_call(msg);
880 int system_macvlan_del(struct device *macvlan)
882 return system_link_del(macvlan->ifname);
885 static int system_vlan(struct device *dev, int id)
887 struct vlan_ioctl_args ifr = {
888 .cmd = SET_VLAN_NAME_TYPE_CMD,
889 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
892 ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
895 ifr.cmd = DEL_VLAN_CMD;
898 ifr.cmd = ADD_VLAN_CMD;
901 strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
902 return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
905 int system_vlan_add(struct device *dev, int id)
907 return system_vlan(dev, id);
910 int system_vlan_del(struct device *dev)
912 return system_vlan(dev, -1);
915 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
918 struct nlattr *linkinfo, *data;
919 struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
922 msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
927 nlmsg_append(msg, &iim, sizeof(iim), 0);
928 nla_put_string(msg, IFLA_IFNAME, vlandev->ifname);
929 nla_put_u32(msg, IFLA_LINK, dev->ifindex);
931 if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO)))
932 goto nla_put_failure;
934 nla_put_string(msg, IFLA_INFO_KIND, "vlan");
936 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
937 goto nla_put_failure;
939 nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid);
941 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
942 nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto));
944 if(cfg->proto == VLAN_PROTO_8021AD)
945 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);
948 nla_nest_end(msg, data);
949 nla_nest_end(msg, linkinfo);
951 rv = system_rtnl_call(msg);
953 D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv);
962 int system_vlandev_del(struct device *vlandev)
964 return system_link_del(vlandev->ifname);
968 system_if_get_settings(struct device *dev, struct device_settings *s)
973 memset(&ifr, 0, sizeof(ifr));
974 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
976 if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
977 s->mtu = ifr.ifr_mtu;
978 s->flags |= DEV_OPT_MTU;
981 if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
982 s->txqueuelen = ifr.ifr_qlen;
983 s->flags |= DEV_OPT_TXQUEUELEN;
986 if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
987 memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
988 s->flags |= DEV_OPT_MACADDR;
991 if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) {
992 s->ipv6 = !strtoul(buf, NULL, 0);
993 s->flags |= DEV_OPT_IPV6;
996 if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
997 s->promisc = ifr.ifr_flags & IFF_PROMISC;
998 s->flags |= DEV_OPT_PROMISC;
1001 if (!system_get_rpfilter(dev, buf, sizeof(buf))) {
1002 s->rpfilter = strtoul(buf, NULL, 0);
1003 s->flags |= DEV_OPT_RPFILTER;
1006 if (!system_get_acceptlocal(dev, buf, sizeof(buf))) {
1007 s->acceptlocal = strtoul(buf, NULL, 0);
1008 s->flags |= DEV_OPT_ACCEPTLOCAL;
1011 if (!system_get_igmpversion(dev, buf, sizeof(buf))) {
1012 s->igmpversion = strtoul(buf, NULL, 0);
1013 s->flags |= DEV_OPT_IGMPVERSION;
1016 if (!system_get_mldversion(dev, buf, sizeof(buf))) {
1017 s->mldversion = strtoul(buf, NULL, 0);
1018 s->flags |= DEV_OPT_MLDVERSION;
1023 system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
1030 memset(&ifr, 0, sizeof(ifr));
1031 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
1032 if (s->flags & DEV_OPT_MTU & apply_mask) {
1033 ifr.ifr_mtu = s->mtu;
1034 if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
1035 s->flags &= ~DEV_OPT_MTU;
1037 if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
1038 ifr.ifr_qlen = s->txqueuelen;
1039 if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
1040 s->flags &= ~DEV_OPT_TXQUEUELEN;
1042 if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
1043 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
1044 memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
1045 if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
1046 s->flags &= ~DEV_OPT_MACADDR;
1048 if (s->flags & DEV_OPT_IPV6 & apply_mask)
1049 system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
1050 if (s->flags & DEV_OPT_PROMISC & apply_mask) {
1051 if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
1052 !s->promisc ? IFF_PROMISC : 0) < 0)
1053 s->flags &= ~DEV_OPT_PROMISC;
1055 if (s->flags & DEV_OPT_RPFILTER & apply_mask) {
1058 snprintf(buf, sizeof(buf), "%d", s->rpfilter);
1059 system_set_rpfilter(dev, buf);
1061 if (s->flags & DEV_OPT_ACCEPTLOCAL & apply_mask)
1062 system_set_acceptlocal(dev, s->acceptlocal ? "1" : "0");
1063 if (s->flags & DEV_OPT_IGMPVERSION & apply_mask) {
1066 snprintf(buf, sizeof(buf), "%d", s->igmpversion);
1067 system_set_igmpversion(dev, buf);
1069 if (s->flags & DEV_OPT_MLDVERSION & apply_mask) {
1072 snprintf(buf, sizeof(buf), "%d", s->mldversion);
1073 system_set_mldversion(dev, buf);
1077 int system_if_up(struct device *dev)
1079 system_if_get_settings(dev, &dev->orig_settings);
1080 /* Only keep orig settings based on what needs to be set */
1081 dev->orig_settings.flags &= dev->settings.flags;
1082 system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
1083 return system_if_flags(dev->ifname, IFF_UP, 0);
1086 int system_if_down(struct device *dev)
1088 int ret = system_if_flags(dev->ifname, 0, IFF_UP);
1089 system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
1093 struct if_check_data {
1099 #ifndef IFF_LOWER_UP
1100 #define IFF_LOWER_UP 0x10000
1103 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
1105 struct nlmsghdr *nh = nlmsg_hdr(msg);
1106 struct ifinfomsg *ifi = NLMSG_DATA(nh);
1107 struct if_check_data *chk = (struct if_check_data *)arg;
1109 if (nh->nlmsg_type != RTM_NEWLINK)
1112 device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
1113 device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
1118 static int cb_if_check_ack(struct nl_msg *msg, void *arg)
1120 struct if_check_data *chk = (struct if_check_data *)arg;
1125 static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
1127 struct if_check_data *chk = (struct if_check_data *)arg;
1129 device_set_present(chk->dev, false);
1130 device_set_link(chk->dev, false);
1131 chk->pending = err->error;
1136 int system_if_check(struct device *dev)
1138 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
1140 struct ifinfomsg ifi = {
1141 .ifi_family = AF_UNSPEC,
1144 struct if_check_data chk = {
1150 msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
1151 if (!msg || nlmsg_append(msg, &ifi, sizeof(ifi), 0) ||
1152 nla_put_string(msg, IFLA_IFNAME, dev->ifname))
1155 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk);
1156 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk);
1157 nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk);
1159 nl_send_auto_complete(sock_rtnl, msg);
1160 while (chk.pending > 0)
1161 nl_recvmsgs(sock_rtnl, cb);
1172 system_if_get_parent(struct device *dev)
1174 char buf[64], *devname;
1175 int ifindex, iflink, len;
1178 snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
1179 f = fopen(buf, "r");
1183 len = fread(buf, 1, sizeof(buf) - 1, f);
1190 iflink = strtoul(buf, NULL, 0);
1191 ifindex = system_if_resolve(dev);
1192 if (!iflink || iflink == ifindex)
1195 devname = if_indextoname(iflink, buf);
1199 return device_get(devname, true);
1203 read_string_file(int dir_fd, const char *file, char *buf, int len)
1209 fd = openat(dir_fd, file, O_RDONLY);
1214 len = read(fd, buf, len - 1);
1218 } else if (len > 0) {
1221 c = strchr(buf, '\n');
1234 read_uint64_file(int dir_fd, const char *file, uint64_t *val)
1239 ret = read_string_file(dir_fd, file, buf, sizeof(buf));
1241 *val = strtoull(buf, NULL, 0);
1246 /* Assume advertised flags == supported flags */
1247 static const struct {
1250 } ethtool_link_modes[] = {
1251 { ADVERTISED_10baseT_Half, "10H" },
1252 { ADVERTISED_10baseT_Full, "10F" },
1253 { ADVERTISED_100baseT_Half, "100H" },
1254 { ADVERTISED_100baseT_Full, "100F" },
1255 { ADVERTISED_1000baseT_Half, "1000H" },
1256 { ADVERTISED_1000baseT_Full, "1000F" },
1259 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
1262 for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
1263 if (mask & ethtool_link_modes[i].mask)
1264 blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
1269 system_if_force_external(const char *ifname)
1274 snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
1275 return stat(buf, &s) == 0;
1279 system_if_dump_info(struct device *dev, struct blob_buf *b)
1281 struct ethtool_cmd ecmd;
1287 snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
1288 dir_fd = open(buf, O_DIRECTORY);
1290 memset(&ecmd, 0, sizeof(ecmd));
1291 memset(&ifr, 0, sizeof(ifr));
1292 strcpy(ifr.ifr_name, dev->ifname);
1293 ifr.ifr_data = (caddr_t) &ecmd;
1294 ecmd.cmd = ETHTOOL_GSET;
1296 if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
1297 c = blobmsg_open_array(b, "link-advertising");
1298 system_add_link_modes(b, ecmd.advertising);
1299 blobmsg_close_array(b, c);
1301 c = blobmsg_open_array(b, "link-supported");
1302 system_add_link_modes(b, ecmd.supported);
1303 blobmsg_close_array(b, c);
1305 s = blobmsg_alloc_string_buffer(b, "speed", 8);
1306 snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
1307 ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
1308 blobmsg_add_string_buffer(b);
1316 system_if_dump_stats(struct device *dev, struct blob_buf *b)
1318 const char *const counters[] = {
1319 "collisions", "rx_frame_errors", "tx_compressed",
1320 "multicast", "rx_length_errors", "tx_dropped",
1321 "rx_bytes", "rx_missed_errors", "tx_errors",
1322 "rx_compressed", "rx_over_errors", "tx_fifo_errors",
1323 "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
1324 "rx_dropped", "tx_aborted_errors", "tx_packets",
1325 "rx_errors", "tx_bytes", "tx_window_errors",
1326 "rx_fifo_errors", "tx_carrier_errors",
1333 snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
1334 stats_dir = open(buf, O_DIRECTORY);
1338 for (i = 0; i < ARRAY_SIZE(counters); i++)
1339 if (read_uint64_file(stats_dir, counters[i], &val))
1340 blobmsg_add_u64(b, counters[i], val);
1346 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
1348 bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
1349 int alen = v4 ? 4 : 16;
1350 unsigned int flags = 0;
1351 struct ifaddrmsg ifa = {
1352 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
1353 .ifa_prefixlen = addr->mask,
1354 .ifa_index = dev->ifindex,
1358 if (cmd == RTM_NEWADDR)
1359 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1361 msg = nlmsg_alloc_simple(cmd, flags);
1365 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1366 nla_put(msg, IFA_LOCAL, alen, &addr->addr);
1368 if (addr->broadcast)
1369 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
1370 if (addr->point_to_point)
1371 nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
1373 time_t now = system_get_rtime();
1374 struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
1376 if (addr->preferred_until) {
1377 int64_t preferred = addr->preferred_until - now;
1380 else if (preferred > UINT32_MAX)
1381 preferred = UINT32_MAX;
1383 cinfo.ifa_prefered = preferred;
1386 if (addr->valid_until) {
1387 int64_t valid = addr->valid_until - now;
1390 else if (valid > UINT32_MAX)
1393 cinfo.ifa_valid = valid;
1396 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1399 return system_rtnl_call(msg);
1402 int system_add_address(struct device *dev, struct device_addr *addr)
1404 return system_addr(dev, addr, RTM_NEWADDR);
1407 int system_del_address(struct device *dev, struct device_addr *addr)
1409 return system_addr(dev, addr, RTM_DELADDR);
1412 static int system_rt(struct device *dev, struct device_route *route, int cmd)
1414 int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
1416 unsigned int flags = 0;
1419 have_gw = !!route->nexthop.in.s_addr;
1421 have_gw = route->nexthop.in6.s6_addr32[0] ||
1422 route->nexthop.in6.s6_addr32[1] ||
1423 route->nexthop.in6.s6_addr32[2] ||
1424 route->nexthop.in6.s6_addr32[3];
1426 unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
1427 ? route->table : RT_TABLE_MAIN;
1429 struct rtmsg rtm = {
1430 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1431 .rtm_dst_len = route->mask,
1432 .rtm_src_len = route->sourcemask,
1433 .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
1434 .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
1435 .rtm_scope = RT_SCOPE_NOWHERE,
1436 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
1437 .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0,
1441 if (cmd == RTM_NEWROUTE) {
1442 flags |= NLM_F_CREATE | NLM_F_REPLACE;
1444 if (!dev) { // Add null-route
1445 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1446 rtm.rtm_type = RTN_UNREACHABLE;
1449 rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
1452 if (route->flags & DEVROUTE_TYPE) {
1453 rtm.rtm_type = route->type;
1454 if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) {
1455 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST ||
1456 rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST)
1457 rtm.rtm_table = RT_TABLE_LOCAL;
1460 if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT) {
1461 rtm.rtm_scope = RT_SCOPE_HOST;
1462 } else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST ||
1463 rtm.rtm_type == RTN_ANYCAST) {
1464 rtm.rtm_scope = RT_SCOPE_LINK;
1465 } else if (rtm.rtm_type == RTN_BLACKHOLE || rtm.rtm_type == RTN_UNREACHABLE ||
1466 rtm.rtm_type == RTN_PROHIBIT || rtm.rtm_type == RTN_FAILED_POLICY) {
1467 rtm.rtm_scope = RT_SCOPE_UNIVERSE;
1472 msg = nlmsg_alloc_simple(cmd, flags);
1476 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1479 nla_put(msg, RTA_DST, alen, &route->addr);
1481 if (route->sourcemask) {
1482 if (rtm.rtm_family == AF_INET)
1483 nla_put(msg, RTA_PREFSRC, alen, &route->source);
1485 nla_put(msg, RTA_SRC, alen, &route->source);
1488 if (route->metric > 0)
1489 nla_put_u32(msg, RTA_PRIORITY, route->metric);
1492 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
1495 nla_put_u32(msg, RTA_OIF, dev->ifindex);
1498 nla_put_u32(msg, RTA_TABLE, table);
1500 if (route->flags & DEVROUTE_MTU) {
1501 struct nlattr *metrics;
1503 if (!(metrics = nla_nest_start(msg, RTA_METRICS)))
1504 goto nla_put_failure;
1506 nla_put_u32(msg, RTAX_MTU, route->mtu);
1508 nla_nest_end(msg, metrics);
1511 return system_rtnl_call(msg);
1518 int system_add_route(struct device *dev, struct device_route *route)
1520 return system_rt(dev, route, RTM_NEWROUTE);
1523 int system_del_route(struct device *dev, struct device_route *route)
1525 return system_rt(dev, route, RTM_DELROUTE);
1528 int system_flush_routes(void)
1530 const char *names[] = {
1531 "/proc/sys/net/ipv4/route/flush",
1532 "/proc/sys/net/ipv6/route/flush"
1536 for (i = 0; i < ARRAY_SIZE(names); i++) {
1537 fd = open(names[i], O_WRONLY);
1541 if (write(fd, "-1", 2)) {}
1547 bool system_resolve_rt_type(const char *type, unsigned int *id)
1549 return system_rtn_aton(type, id);
1552 bool system_resolve_rt_table(const char *name, unsigned int *id)
1556 unsigned int n, table = RT_TABLE_UNSPEC;
1558 /* first try to parse table as number */
1559 if ((n = strtoul(name, &e, 0)) > 0 && !*e)
1562 /* handle well known aliases */
1563 else if (!strcmp(name, "default"))
1564 table = RT_TABLE_DEFAULT;
1565 else if (!strcmp(name, "main"))
1566 table = RT_TABLE_MAIN;
1567 else if (!strcmp(name, "local"))
1568 table = RT_TABLE_LOCAL;
1570 /* try to look up name in /etc/iproute2/rt_tables */
1571 else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
1573 while (fgets(buf, sizeof(buf) - 1, f) != NULL)
1575 if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
1578 n = strtoul(e, NULL, 10);
1579 e = strtok(NULL, " \t\n");
1581 if (e && !strcmp(e, name))
1591 if (table == RT_TABLE_UNSPEC)
1598 bool system_is_default_rt_table(unsigned int id)
1600 return (id == RT_TABLE_MAIN);
1603 bool system_resolve_rpfilter(const char *filter, unsigned int *id)
1608 if (!strcmp(filter, "strict"))
1610 else if (!strcmp(filter, "loose"))
1613 n = strtoul(filter, &e, 0);
1614 if (*e || e == filter || n > 2)
1622 static int system_iprule(struct iprule *rule, int cmd)
1624 int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
1627 struct rtmsg rtm = {
1628 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
1629 .rtm_protocol = RTPROT_STATIC,
1630 .rtm_scope = RT_SCOPE_UNIVERSE,
1631 .rtm_table = RT_TABLE_UNSPEC,
1632 .rtm_type = RTN_UNSPEC,
1636 if (cmd == RTM_NEWRULE) {
1637 rtm.rtm_type = RTN_UNICAST;
1638 rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
1642 rtm.rtm_flags |= FIB_RULE_INVERT;
1644 if (rule->flags & IPRULE_SRC)
1645 rtm.rtm_src_len = rule->src_mask;
1647 if (rule->flags & IPRULE_DEST)
1648 rtm.rtm_dst_len = rule->dest_mask;
1650 if (rule->flags & IPRULE_TOS)
1651 rtm.rtm_tos = rule->tos;
1653 if (rule->flags & IPRULE_LOOKUP) {
1654 if (rule->lookup < 256)
1655 rtm.rtm_table = rule->lookup;
1658 if (rule->flags & IPRULE_ACTION)
1659 rtm.rtm_type = rule->action;
1660 else if (rule->flags & IPRULE_GOTO)
1661 rtm.rtm_type = FR_ACT_GOTO;
1662 else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
1663 rtm.rtm_type = FR_ACT_NOP;
1665 msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
1670 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1672 if (rule->flags & IPRULE_IN)
1673 nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
1675 if (rule->flags & IPRULE_OUT)
1676 nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
1678 if (rule->flags & IPRULE_SRC)
1679 nla_put(msg, FRA_SRC, alen, &rule->src_addr);
1681 if (rule->flags & IPRULE_DEST)
1682 nla_put(msg, FRA_DST, alen, &rule->dest_addr);
1684 if (rule->flags & IPRULE_PRIORITY)
1685 nla_put_u32(msg, FRA_PRIORITY, rule->priority);
1686 else if (cmd == RTM_NEWRULE)
1687 nla_put_u32(msg, FRA_PRIORITY, rule->order);
1689 if (rule->flags & IPRULE_FWMARK)
1690 nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
1692 if (rule->flags & IPRULE_FWMASK)
1693 nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
1695 if (rule->flags & IPRULE_LOOKUP) {
1696 if (rule->lookup >= 256)
1697 nla_put_u32(msg, FRA_TABLE, rule->lookup);
1700 if (rule->flags & IPRULE_GOTO)
1701 nla_put_u32(msg, FRA_GOTO, rule->gotoid);
1703 return system_rtnl_call(msg);
1706 int system_add_iprule(struct iprule *rule)
1708 return system_iprule(rule, RTM_NEWRULE);
1711 int system_del_iprule(struct iprule *rule)
1713 return system_iprule(rule, RTM_DELRULE);
1716 int system_flush_iprules(void)
1721 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
1722 system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
1724 memset(&rule, 0, sizeof(rule));
1727 rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1730 rule.lookup = RT_TABLE_LOCAL;
1731 rv |= system_iprule(&rule, RTM_NEWRULE);
1733 rule.priority = 32766;
1734 rule.lookup = RT_TABLE_MAIN;
1735 rv |= system_iprule(&rule, RTM_NEWRULE);
1737 rule.priority = 32767;
1738 rule.lookup = RT_TABLE_DEFAULT;
1739 rv |= system_iprule(&rule, RTM_NEWRULE);
1742 rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
1745 rule.lookup = RT_TABLE_LOCAL;
1746 rv |= system_iprule(&rule, RTM_NEWRULE);
1748 rule.priority = 32766;
1749 rule.lookup = RT_TABLE_MAIN;
1750 rv |= system_iprule(&rule, RTM_NEWRULE);
1755 bool system_resolve_iprule_action(const char *action, unsigned int *id)
1757 return system_rtn_aton(action, id);
1760 time_t system_get_rtime(void)
1765 if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
1768 if (gettimeofday(&tv, NULL) == 0)
1775 #define IP_DF 0x4000
1778 static int tunnel_ioctl(const char *name, int cmd, void *p)
1782 memset(&ifr, 0, sizeof(ifr));
1783 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1784 ifr.ifr_ifru.ifru_data = p;
1785 return ioctl(sock_ioctl, cmd, &ifr);
1788 #ifdef IFLA_IPTUN_MAX
1789 #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
1790 static int system_add_gre_tunnel(const char *name, const char *kind,
1791 const unsigned int link, struct blob_attr **tb, bool v6)
1794 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
1795 struct blob_attr *cur;
1796 uint32_t ikey = 0, okey = 0, flags = 0, flowinfo = 0;
1797 uint16_t iflags = 0, oflags = 0;
1799 int ret = 0, ttl = 64;
1801 nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
1805 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
1806 nla_put_string(nlm, IFLA_IFNAME, name);
1808 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
1814 nla_put_string(nlm, IFLA_INFO_KIND, kind);
1815 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
1822 nla_put_u32(nlm, IFLA_GRE_LINK, link);
1824 if ((cur = tb[TUNNEL_ATTR_TTL]))
1825 ttl = blobmsg_get_u32(cur);
1827 nla_put_u8(nlm, IFLA_GRE_TTL, ttl);
1829 if ((cur = tb[TUNNEL_ATTR_TOS])) {
1830 char *str = blobmsg_get_string(cur);
1831 if (strcmp(str, "inherit")) {
1834 if (!system_tos_aton(str, &uval)) {
1840 flowinfo |= htonl(uval << 20) & IP6_FLOWINFO_TCLASS;
1845 flags |= IP6_TNL_F_USE_ORIG_TCLASS;
1851 if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) {
1852 uint8_t icsum, ocsum, iseqno, oseqno;
1853 if (sscanf(blobmsg_get_string(cur), "%u,%u,%hhu,%hhu,%hhu,%hhu",
1854 &ikey, &okey, &icsum, &ocsum, &iseqno, &oseqno) < 6) {
1879 struct in6_addr in6buf;
1880 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1881 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1885 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(in6buf), &in6buf);
1888 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
1889 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
1893 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(in6buf), &in6buf);
1895 nla_put_u8(nlm, IFLA_GRE_ENCAP_LIMIT, 4);
1898 nla_put_u32(nlm, IFLA_GRE_FLOWINFO, flowinfo);
1901 nla_put_u32(nlm, IFLA_GRE_FLAGS, flags);
1903 struct in_addr inbuf;
1906 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
1907 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
1911 nla_put(nlm, IFLA_GRE_LOCAL, sizeof(inbuf), &inbuf);
1914 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
1915 if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
1919 nla_put(nlm, IFLA_GRE_REMOTE, sizeof(inbuf), &inbuf);
1921 if (IN_MULTICAST(ntohl(inbuf.s_addr))) {
1923 okey = inbuf.s_addr;
1928 ikey = inbuf.s_addr;
1934 if ((cur = tb[TUNNEL_ATTR_DF]))
1935 set_df = blobmsg_get_bool(cur);
1937 /* ttl !=0 and nopmtudisc are incompatible */
1938 if (ttl && !set_df) {
1943 nla_put_u8(nlm, IFLA_GRE_PMTUDISC, set_df ? 1 : 0);
1945 nla_put_u8(nlm, IFLA_GRE_TOS, tos);
1949 nla_put_u16(nlm, IFLA_GRE_OFLAGS, oflags);
1952 nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags);
1955 nla_put_u32(nlm, IFLA_GRE_OKEY, okey);
1958 nla_put_u32(nlm, IFLA_GRE_IKEY, ikey);
1960 nla_nest_end(nlm, infodata);
1961 nla_nest_end(nlm, linkinfo);
1963 return system_rtnl_call(nlm);
1971 static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
1973 struct blob_attr *cur;
1975 struct ip_tunnel_parm p = {
1984 if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
1985 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
1988 if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
1989 inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
1992 if ((cur = tb[TUNNEL_ATTR_DF]))
1993 set_df = blobmsg_get_bool(cur);
1995 if ((cur = tb[TUNNEL_ATTR_TTL]))
1996 p.iph.ttl = blobmsg_get_u32(cur);
1998 if ((cur = tb[TUNNEL_ATTR_TOS])) {
1999 char *str = blobmsg_get_string(cur);
2000 if (strcmp(str, "inherit")) {
2003 if (!system_tos_aton(str, &uval))
2011 p.iph.frag_off = set_df ? htons(IP_DF) : 0;
2012 /* ttl !=0 and nopmtudisc are incompatible */
2013 if (p.iph.ttl && p.iph.frag_off == 0)
2016 strncpy(p.name, name, sizeof(p.name));
2018 switch (p.iph.protocol) {
2020 return tunnel_ioctl("tunl0", SIOCADDTUNNEL, &p);
2022 return tunnel_ioctl("sit0", SIOCADDTUNNEL, &p);
2029 static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
2031 struct blob_attr *cur;
2034 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2036 str = blobmsg_data(cur);
2038 if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
2039 !strcmp(str, "greip6") || !strcmp(str, "gretapip6"))
2040 return system_link_del(name);
2042 return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
2045 int system_del_ip_tunnel(const char *name, struct blob_attr *attr)
2047 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2049 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2050 blob_data(attr), blob_len(attr));
2052 return __system_del_ip_tunnel(name, tb);
2055 int system_update_ipv6_mtu(struct device *dev, int mtu)
2059 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
2062 int fd = open(buf, O_RDWR);
2063 ssize_t len = read(fd, buf, sizeof(buf) - 1);
2070 if (!mtu || ret <= mtu)
2073 lseek(fd, 0, SEEK_SET);
2074 if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) <= 0)
2082 int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
2084 struct blob_attr *tb[__TUNNEL_ATTR_MAX];
2085 struct blob_attr *cur;
2088 blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
2089 blob_data(attr), blob_len(attr));
2091 __system_del_ip_tunnel(name, tb);
2093 if (!(cur = tb[TUNNEL_ATTR_TYPE]))
2095 str = blobmsg_data(cur);
2097 unsigned int ttl = 0;
2098 if ((cur = tb[TUNNEL_ATTR_TTL])) {
2099 ttl = blobmsg_get_u32(cur);
2104 unsigned int link = 0;
2105 if ((cur = tb[TUNNEL_ATTR_LINK])) {
2106 struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
2110 if (iface->l3_dev.dev)
2111 link = iface->l3_dev.dev->ifindex;
2114 if (!strcmp(str, "sit")) {
2115 if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0)
2119 if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
2121 struct ip_tunnel_6rd p6;
2123 memset(&p6, 0, sizeof(p6));
2125 if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
2126 &p6.prefix, &mask) || mask > 128)
2128 p6.prefixlen = mask;
2130 if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
2131 if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
2132 &p6.relay_prefix, &mask) || mask > 32)
2134 p6.relay_prefixlen = mask;
2137 if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
2138 __system_del_ip_tunnel(name, tb);
2143 #ifdef IFLA_IPTUN_MAX
2144 } else if (!strcmp(str, "ipip6")) {
2145 struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
2146 NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
2147 struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
2153 nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
2154 nla_put_string(nlm, IFLA_IFNAME, name);
2157 nla_put_u32(nlm, IFLA_LINK, link);
2159 struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
2164 nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
2165 struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
2172 nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
2174 nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
2175 nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
2176 nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
2178 struct in6_addr in6buf;
2179 if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
2180 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2184 nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
2187 if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
2188 if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
2192 nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
2195 #ifdef IFLA_IPTUN_FMR_MAX
2196 if ((cur = tb[TUNNEL_ATTR_FMRS])) {
2197 struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
2199 struct blob_attr *fmr;
2200 unsigned rem, fmrcnt = 0;
2201 blobmsg_for_each_attr(fmr, cur, rem) {
2202 if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
2205 unsigned ip4len, ip6len, ealen, offset = 6;
2209 if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
2210 ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) {
2215 struct in6_addr ip6prefix;
2216 struct in_addr ip4prefix;
2217 if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
2218 inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) {
2223 struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
2225 nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
2226 nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
2227 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
2228 nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
2229 nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
2230 nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
2232 nla_nest_end(nlm, rule);
2235 nla_nest_end(nlm, fmrs);
2239 nla_nest_end(nlm, infodata);
2240 nla_nest_end(nlm, linkinfo);
2242 return system_rtnl_call(nlm);
2246 } else if (!strcmp(str, "greip")) {
2247 return system_add_gre_tunnel(name, "gre", link, tb, false);
2248 } else if (!strcmp(str, "gretapip")) {
2249 return system_add_gre_tunnel(name, "gretap", link, tb, false);
2250 } else if (!strcmp(str, "greip6")) {
2251 return system_add_gre_tunnel(name, "ip6gre", link, tb, true);
2252 } else if (!strcmp(str, "gretapip6")) {
2253 return system_add_gre_tunnel(name, "ip6gretap", link, tb, true);
2255 } else if (!strcmp(str, "ipip")) {
2256 return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);