diff options
author | Tobias Brunner <tobias@strongswan.org> | 2013-06-16 10:47:39 +0200 |
---|---|---|
committer | Tobias Brunner <tobias@strongswan.org> | 2013-06-21 17:03:21 +0200 |
commit | 1f31a2bc2eeb92bf47272a784e88d893e450a17c (patch) | |
tree | c362ec0e5dbc69069b0c6b2555b9015265a5ec86 /src/libcharon/plugins/kernel_libipsec | |
parent | 93e4df3761bc496a1bae71705f13f3f5a29288ed (diff) | |
download | strongswan-1f31a2bc2eeb92bf47272a784e88d893e450a17c.tar.bz2 strongswan-1f31a2bc2eeb92bf47272a784e88d893e450a17c.tar.xz |
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.
Diffstat (limited to 'src/libcharon/plugins/kernel_libipsec')
-rw-r--r-- | src/libcharon/plugins/kernel_libipsec/kernel_libipsec_ipsec.c | 35 |
1 files changed, 26 insertions, 9 deletions
diff --git a/src/libcharon/plugins/kernel_libipsec/kernel_libipsec_ipsec.c b/src/libcharon/plugins/kernel_libipsec/kernel_libipsec_ipsec.c index f605501ba..45b34062d 100644 --- a/src/libcharon/plugins/kernel_libipsec/kernel_libipsec_ipsec.c +++ b/src/libcharon/plugins/kernel_libipsec/kernel_libipsec_ipsec.c @@ -96,8 +96,10 @@ typedef struct route_entry_t route_entry_t; struct route_entry_t { /** Name of the interface the route is bound to */ char *if_name; - /** Source ip of the route */ + /** Source IP of the route */ host_t *src_ip; + /** Gateway of the route */ + host_t *gateway; /** Destination net */ chunk_t dst_net; /** Destination net prefixlen */ @@ -113,6 +115,7 @@ static void route_entry_destroy(route_entry_t *this) { free(this->if_name); DESTROY_IF(this->src_ip); + DESTROY_IF(this->gateway); chunk_free(&this->dst_net); 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) { - return a->if_name && b->if_name && streq(a->if_name, b->if_name) && - 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->src_ip && !b->src_ip) || (a->src_ip && b->src_ip && + a->src_ip->ip_equals(a->src_ip, b->src_ip))) + { + 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; @@ -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)), .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) { @@ -403,7 +420,7 @@ static bool install_route(private_kernel_libipsec_ipsec_t *this, } /* uninstall previously installed route */ 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) { 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); 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)) { case ALREADY_DONE: @@ -537,7 +554,7 @@ METHOD(kernel_ipsec_t, del_policy, status_t, route_entry_t *route = policy->route; 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) { 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; hydra->kernel_interface->del_route(hydra->kernel_interface, - route->dst_net, route->prefixlen, NULL, route->src_ip, - route->if_name); + route->dst_net, route->prefixlen, route->gateway, + route->src_ip, route->if_name); remove_exclude_route(this, route); } policy_entry_destroy(pol); |