diff options
author | Martin Willi <martin@revosec.ch> | 2013-04-18 18:26:49 +0200 |
---|---|---|
committer | Martin Willi <martin@revosec.ch> | 2013-05-06 16:10:12 +0200 |
commit | 9bc342eae471831ca328e00a6bf65be1b2608f7a (patch) | |
tree | b00c53ec0f856a98f27366f2a1ccd9851d31f24b /src/libhydra/plugins | |
parent | 272bcac894648dbfa3d17a6c606fe7a2966919da (diff) | |
download | strongswan-9bc342eae471831ca328e00a6bf65be1b2608f7a.tar.bz2 strongswan-9bc342eae471831ca328e00a6bf65be1b2608f7a.tar.xz |
kernel-pfroute: implement get_nexthop()
Diffstat (limited to 'src/libhydra/plugins')
-rw-r--r-- | src/libhydra/plugins/kernel_pfroute/kernel_pfroute_net.c | 79 |
1 files changed, 73 insertions, 6 deletions
diff --git a/src/libhydra/plugins/kernel_pfroute/kernel_pfroute_net.c b/src/libhydra/plugins/kernel_pfroute/kernel_pfroute_net.c index caab3150d..face73e6b 100644 --- a/src/libhydra/plugins/kernel_pfroute/kernel_pfroute_net.c +++ b/src/libhydra/plugins/kernel_pfroute/kernel_pfroute_net.c @@ -746,12 +746,6 @@ METHOD(kernel_net_t, get_source_addr, host_t*, return NULL; } -METHOD(kernel_net_t, get_nexthop, host_t*, - private_kernel_pfroute_net_t *this, host_t *dest, host_t *src) -{ - return NULL; -} - METHOD(kernel_net_t, add_ip, status_t, private_kernel_pfroute_net_t *this, host_t *virtual_ip, int prefix, char *iface) @@ -906,6 +900,79 @@ METHOD(kernel_net_t, del_route, status_t, return manage_route(this, RTM_DELETE, dst_net, prefixlen, gateway, if_name); } +METHOD(kernel_net_t, get_nexthop, host_t*, + private_kernel_pfroute_net_t *this, host_t *dest, host_t *src) +{ + struct { + struct rt_msghdr hdr; + char buf[sizeof(struct sockaddr_storage) * RTAX_MAX]; + } msg = { + .hdr = { + .rtm_version = RTM_VERSION, + .rtm_type = RTM_GET, + .rtm_pid = this->pid, + .rtm_seq = ++this->seq, + }, + }; + host_t *hop = NULL; + enumerator_t *enumerator; + struct sockaddr *addr; + int type; + + msg.hdr.rtm_msglen = sizeof(struct rt_msghdr); + for (type = 0; type < RTAX_MAX; type++) + { + switch (type) + { + case RTAX_DST: + add_rt_addr(&msg.hdr, RTA_DST, dest); + break; + case RTAX_IFA: + add_rt_addr(&msg.hdr, RTA_IFA, src); + break; + default: + break; + } + } + this->mutex->lock(this->mutex); + + this->waiting_seq = msg.hdr.rtm_seq; + if (send(this->socket, &msg, msg.hdr.rtm_msglen, 0) == msg.hdr.rtm_msglen) + { + while (TRUE) + { + if (this->condvar->timed_wait(this->condvar, this->mutex, 1000)) + { /* timed out? */ + break; + } + if (this->reply->rtm_msglen < sizeof(*this->reply) || + msg.hdr.rtm_seq != this->reply->rtm_seq) + { + continue; + } + enumerator = create_rtmsg_enumerator(this->reply, + sizeof(*this->reply)); + while (enumerator->enumerate(enumerator, &type, &addr)) + { + if (type == RTAX_GATEWAY) + { + hop = host_create_from_sockaddr(addr); + break; + } + } + enumerator->destroy(enumerator); + break; + } + } + else + { + DBG1(DBG_KNL, "PF_ROUTE lookup failed: %s", strerror(errno)); + } + this->mutex->unlock(this->mutex); + + return hop; +} + /** * Initialize a list of local addresses. */ |