aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2016-10-12 09:52:45 +0200
committerTobias Brunner <tobias@strongswan.org>2017-02-08 10:38:28 +0100
commiteac584a37db2e9a3d8590503995ccffc39b55bbb (patch)
treeaf83118b6c98fe485383143e203fbceada84e42d
parent324fc2cb522926e8f6c9c0076c7410beb025b3cb (diff)
downloadstrongswan-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.c130
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,