kernel-pfroute: implement get_nexthop()

This commit is contained in:
Martin Willi
2013-05-06 16:10:12 +02:00
parent 272bcac894
commit 9bc342eae4
@@ -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.
*/