aboutsummaryrefslogtreecommitdiffstats
path: root/src/libhydra/plugins
diff options
context:
space:
mode:
authorMartin Willi <martin@revosec.ch>2013-04-18 18:26:49 +0200
committerMartin Willi <martin@revosec.ch>2013-05-06 16:10:12 +0200
commit9bc342eae471831ca328e00a6bf65be1b2608f7a (patch)
treeb00c53ec0f856a98f27366f2a1ccd9851d31f24b /src/libhydra/plugins
parent272bcac894648dbfa3d17a6c606fe7a2966919da (diff)
downloadstrongswan-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.c79
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.
*/