kernel-libipsec: Install a gateway for routes on platforms other than Linux

This seems required e.g. on FreeBSD but doesn't work on Linux.
This commit is contained in:
Tobias Brunner
2013-06-21 17:03:21 +02:00
parent 93e4df3761
commit 1f31a2bc2e
@@ -96,8 +96,10 @@ typedef struct route_entry_t route_entry_t;
struct route_entry_t { struct route_entry_t {
/** Name of the interface the route is bound to */ /** Name of the interface the route is bound to */
char *if_name; char *if_name;
/** Source ip of the route */ /** Source IP of the route */
host_t *src_ip; host_t *src_ip;
/** Gateway of the route */
host_t *gateway;
/** Destination net */ /** Destination net */
chunk_t dst_net; chunk_t dst_net;
/** Destination net prefixlen */ /** Destination net prefixlen */
@@ -113,6 +115,7 @@ static void route_entry_destroy(route_entry_t *this)
{ {
free(this->if_name); free(this->if_name);
DESTROY_IF(this->src_ip); DESTROY_IF(this->src_ip);
DESTROY_IF(this->gateway);
chunk_free(&this->dst_net); chunk_free(&this->dst_net);
free(this); free(this);
} }
@@ -122,9 +125,18 @@ static void route_entry_destroy(route_entry_t *this)
*/ */
static bool route_entry_equals(route_entry_t *a, route_entry_t *b) static bool route_entry_equals(route_entry_t *a, route_entry_t *b)
{ {
return a->if_name && b->if_name && streq(a->if_name, b->if_name) && if ((!a->src_ip && !b->src_ip) || (a->src_ip && b->src_ip &&
a->src_ip->ip_equals(a->src_ip, b->src_ip) && a->src_ip->ip_equals(a->src_ip, b->src_ip)))
chunk_equals(a->dst_net, b->dst_net) && a->prefixlen == b->prefixlen; {
if ((!a->gateway && !b->gateway) || (a->gateway && b->gateway &&
a->gateway->ip_equals(a->gateway, b->gateway)))
{
return a->if_name && b->if_name && streq(a->if_name, b->if_name) &&
chunk_equals(a->dst_net, b->dst_net) &&
a->prefixlen == b->prefixlen;
}
}
return FALSE;
} }
typedef struct policy_entry_t policy_entry_t; typedef struct policy_entry_t policy_entry_t;
@@ -390,6 +402,11 @@ static bool install_route(private_kernel_libipsec_ipsec_t *this,
.dst_net = chunk_clone(policy->dst.net->get_address(policy->dst.net)), .dst_net = chunk_clone(policy->dst.net->get_address(policy->dst.net)),
.prefixlen = policy->dst.mask, .prefixlen = policy->dst.mask,
); );
#ifndef __linux__
/* on Linux we cant't install a gateway */
route->gateway = hydra->kernel_interface->get_nexthop(
hydra->kernel_interface, dst, src);
#endif
if (policy->route) if (policy->route)
{ {
@@ -403,7 +420,7 @@ static bool install_route(private_kernel_libipsec_ipsec_t *this,
} }
/* uninstall previously installed route */ /* uninstall previously installed route */
if (hydra->kernel_interface->del_route(hydra->kernel_interface, if (hydra->kernel_interface->del_route(hydra->kernel_interface,
old->dst_net, old->prefixlen, NULL, old->dst_net, old->prefixlen, old->gateway,
old->src_ip, old->if_name) != SUCCESS) old->src_ip, old->if_name) != SUCCESS)
{ {
DBG1(DBG_KNL, "error uninstalling route installed with policy " DBG1(DBG_KNL, "error uninstalling route installed with policy "
@@ -425,7 +442,7 @@ static bool install_route(private_kernel_libipsec_ipsec_t *this,
dst_ts, route->src_ip, route->if_name); dst_ts, route->src_ip, route->if_name);
switch (hydra->kernel_interface->add_route(hydra->kernel_interface, switch (hydra->kernel_interface->add_route(hydra->kernel_interface,
route->dst_net, route->prefixlen, NULL, route->dst_net, route->prefixlen, route->gateway,
route->src_ip, route->if_name)) route->src_ip, route->if_name))
{ {
case ALREADY_DONE: case ALREADY_DONE:
@@ -537,7 +554,7 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
route_entry_t *route = policy->route; route_entry_t *route = policy->route;
if (hydra->kernel_interface->del_route(hydra->kernel_interface, if (hydra->kernel_interface->del_route(hydra->kernel_interface,
route->dst_net, route->prefixlen, NULL, route->src_ip, route->dst_net, route->prefixlen, route->gateway, route->src_ip,
route->if_name) != SUCCESS) route->if_name) != SUCCESS)
{ {
DBG1(DBG_KNL, "error uninstalling route installed with " DBG1(DBG_KNL, "error uninstalling route installed with "
@@ -568,8 +585,8 @@ METHOD(kernel_ipsec_t, flush_policies, status_t,
route_entry_t *route = pol->route; route_entry_t *route = pol->route;
hydra->kernel_interface->del_route(hydra->kernel_interface, hydra->kernel_interface->del_route(hydra->kernel_interface,
route->dst_net, route->prefixlen, NULL, route->src_ip, route->dst_net, route->prefixlen, route->gateway,
route->if_name); route->src_ip, route->if_name);
remove_exclude_route(this, route); remove_exclude_route(this, route);
} }
policy_entry_destroy(pol); policy_entry_destroy(pol);