aboutsummaryrefslogtreecommitdiffstats
path: root/src/libcharon/plugins/kernel_libipsec
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2013-06-16 10:47:39 +0200
committerTobias Brunner <tobias@strongswan.org>2013-06-21 17:03:21 +0200
commit1f31a2bc2eeb92bf47272a784e88d893e450a17c (patch)
treec362ec0e5dbc69069b0c6b2555b9015265a5ec86 /src/libcharon/plugins/kernel_libipsec
parent93e4df3761bc496a1bae71705f13f3f5a29288ed (diff)
downloadstrongswan-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.c35
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);