diff options
author | Tobias Brunner <tobias@strongswan.org> | 2016-10-12 09:52:45 +0200 |
---|---|---|
committer | Tobias Brunner <tobias@strongswan.org> | 2017-02-08 10:38:28 +0100 |
commit | eac584a37db2e9a3d8590503995ccffc39b55bbb (patch) | |
tree | af83118b6c98fe485383143e203fbceada84e42d | |
parent | 324fc2cb522926e8f6c9c0076c7410beb025b3cb (diff) | |
download | strongswan-eac584a37db2e9a3d8590503995ccffc39b55bbb.tar.bz2 strongswan-eac584a37db2e9a3d8590503995ccffc39b55bbb.tar.xz |
kernel-netlink: Implement enumerator for local subnets
-rw-r--r-- | src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c b/src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c index 4ecd97634..a31f312b9 100644 --- a/src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c +++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c @@ -2125,6 +2125,135 @@ METHOD(kernel_net_t, get_nexthop, host_t*, return get_route(this, dest, prefix, TRUE, src, iface, 0); } +/** enumerator over subnets */ +typedef struct { + enumerator_t public; + private_kernel_netlink_net_t *private; + /** message from the kernel */ + struct nlmsghdr *msg; + /** current message from the kernel */ + struct nlmsghdr *current; + /** remaining length */ + size_t len; + /** last subnet enumerated */ + host_t *net; +} subnet_enumerator_t; + +METHOD(enumerator_t, destroy_subnet_enumerator, void, + subnet_enumerator_t *this) +{ + DESTROY_IF(this->net); + free(this->msg); + free(this); +} + +METHOD(enumerator_t, enumerate_subnets, bool, + subnet_enumerator_t *this, host_t **net, uint8_t *mask) +{ + if (!this->current) + { + this->current = this->msg; + } + else + { + this->current = NLMSG_NEXT(this->current, this->len); + DESTROY_IF(this->net); + this->net = NULL; + } + + while (NLMSG_OK(this->current, this->len)) + { + switch (this->current->nlmsg_type) + { + case NLMSG_DONE: + break; + case RTM_NEWROUTE: + { + struct rtmsg *msg; + struct rtattr *rta; + size_t rtasize; + chunk_t dst = chunk_empty; + + msg = NLMSG_DATA(this->current); + + if (!route_usable(this->current)) + { + break; + } + else if (msg->rtm_table && ( + msg->rtm_table == RT_TABLE_LOCAL || + msg->rtm_table == this->private->routing_table)) + { /* ignore our own and the local routing tables */ + break; + } + + rta = RTM_RTA(msg); + rtasize = RTM_PAYLOAD(this->current); + while (RTA_OK(rta, rtasize)) + { + if (rta->rta_type == RTA_DST) + { + dst = chunk_create(RTA_DATA(rta), RTA_PAYLOAD(rta)); + break; + } + rta = RTA_NEXT(rta, rtasize); + } + + if (dst.ptr) + { + this->net = host_create_from_chunk(msg->rtm_family, dst, 0); + *net = this->net; + *mask = msg->rtm_dst_len; + return TRUE; + } + break; + } + default: + break; + } + this->current = NLMSG_NEXT(this->current, this->len); + } + return FALSE; +} + +METHOD(kernel_net_t, create_local_subnet_enumerator, enumerator_t*, + private_kernel_netlink_net_t *this) +{ + netlink_buf_t request; + struct nlmsghdr *hdr, *out; + struct rtmsg *msg; + size_t len; + subnet_enumerator_t *enumerator; + + memset(&request, 0, sizeof(request)); + + hdr = &request.hdr; + hdr->nlmsg_flags = NLM_F_REQUEST; + hdr->nlmsg_type = RTM_GETROUTE; + hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); + hdr->nlmsg_flags |= NLM_F_DUMP; + + msg = NLMSG_DATA(hdr); + msg->rtm_scope = RT_SCOPE_LINK; + + if (this->socket->send(this->socket, hdr, &out, &len) != SUCCESS) + { + DBG2(DBG_KNL, "enumerating local subnets failed"); + return enumerator_create_empty(); + } + + INIT(enumerator, + .public = { + .enumerate = (void*)_enumerate_subnets, + .destroy = _destroy_subnet_enumerator, + }, + .private = this, + .msg = out, + .len = len, + ); + return &enumerator->public; +} + /** * Manages the creation and deletion of ip addresses on an interface. * By setting the appropriate nlmsg_type, the ip will be set or unset. @@ -2761,6 +2890,7 @@ kernel_netlink_net_t *kernel_netlink_net_create() .interface = { .get_interface = _get_interface_name, .create_address_enumerator = _create_address_enumerator, + .create_local_subnet_enumerator = _create_local_subnet_enumerator, .get_source_addr = _get_source_addr, .get_nexthop = _get_nexthop, .add_ip = _add_ip, |