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:
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user