kernel-netlink: Allow blank source address in routes for passthrough policies
This commit is contained in:
@@ -2622,88 +2622,92 @@ static void install_route(private_kernel_netlink_ipsec_t *this,
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (charon->kernel->get_address_by_ts(charon->kernel, out->src_ts,
|
if (charon->kernel->get_address_by_ts(charon->kernel, out->src_ts,
|
||||||
&route->src_ip, NULL) == SUCCESS)
|
&route->src_ip, NULL) != SUCCESS)
|
||||||
{
|
{
|
||||||
if (!ipsec->dst->is_anyaddr(ipsec->dst))
|
if (!route->pass)
|
||||||
{
|
{
|
||||||
route->gateway = charon->kernel->get_nexthop(charon->kernel,
|
free(route);
|
||||||
ipsec->dst, -1, ipsec->src,
|
return;
|
||||||
&route->if_name);
|
|
||||||
}
|
}
|
||||||
else
|
/* allow blank source IP for passthrough policies */
|
||||||
{ /* for shunt policies */
|
route->src_ip = host_create_any(policy->sel.family);
|
||||||
iface = xfrm2host(policy->sel.family, &policy->sel.daddr, 0);
|
}
|
||||||
route->gateway = charon->kernel->get_nexthop(charon->kernel,
|
|
||||||
iface, policy->sel.prefixlen_d,
|
|
||||||
route->src_ip, &route->if_name);
|
|
||||||
iface->destroy(iface);
|
|
||||||
}
|
|
||||||
route->dst_net = chunk_alloc(policy->sel.family == AF_INET ? 4 : 16);
|
|
||||||
memcpy(route->dst_net.ptr, &policy->sel.daddr, route->dst_net.len);
|
|
||||||
|
|
||||||
/* get the interface to install the route for, if we haven't one yet.
|
if (!ipsec->dst->is_anyaddr(ipsec->dst))
|
||||||
* If we have a local address, use it. Otherwise (for shunt policies)
|
{
|
||||||
* use the route's source address. */
|
route->gateway = charon->kernel->get_nexthop(charon->kernel,
|
||||||
if (!route->if_name)
|
ipsec->dst, -1, ipsec->src,
|
||||||
{
|
&route->if_name);
|
||||||
iface = ipsec->src;
|
|
||||||
if (iface->is_anyaddr(iface))
|
|
||||||
{
|
|
||||||
iface = route->src_ip;
|
|
||||||
}
|
|
||||||
if (!charon->kernel->get_interface(charon->kernel, iface,
|
|
||||||
&route->if_name))
|
|
||||||
{
|
|
||||||
route_entry_destroy(route);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (policy->route)
|
|
||||||
{
|
|
||||||
route_entry_t *old = policy->route;
|
|
||||||
if (route_entry_equals(old, route))
|
|
||||||
{
|
|
||||||
route_entry_destroy(route);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/* uninstall previously installed route */
|
|
||||||
if (charon->kernel->del_route(charon->kernel, old->dst_net,
|
|
||||||
old->prefixlen, old->gateway,
|
|
||||||
old->src_ip, old->if_name,
|
|
||||||
old->pass) != SUCCESS)
|
|
||||||
{
|
|
||||||
DBG1(DBG_KNL, "error uninstalling route installed with policy "
|
|
||||||
"%R === %R %N", out->src_ts, out->dst_ts, policy_dir_names,
|
|
||||||
policy->direction);
|
|
||||||
}
|
|
||||||
route_entry_destroy(old);
|
|
||||||
policy->route = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
DBG2(DBG_KNL, "installing route: %R via %H src %H dev %s", out->dst_ts,
|
|
||||||
route->gateway, route->src_ip, route->if_name);
|
|
||||||
switch (charon->kernel->add_route(charon->kernel, route->dst_net,
|
|
||||||
route->prefixlen, route->gateway,
|
|
||||||
route->src_ip, route->if_name,
|
|
||||||
route->pass))
|
|
||||||
{
|
|
||||||
default:
|
|
||||||
DBG1(DBG_KNL, "unable to install source route for %H",
|
|
||||||
route->src_ip);
|
|
||||||
/* FALL */
|
|
||||||
case ALREADY_DONE:
|
|
||||||
/* route exists, do not uninstall */
|
|
||||||
route_entry_destroy(route);
|
|
||||||
break;
|
|
||||||
case SUCCESS:
|
|
||||||
/* cache the installed route */
|
|
||||||
policy->route = route;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{ /* for shunt policies */
|
||||||
|
iface = xfrm2host(policy->sel.family, &policy->sel.daddr, 0);
|
||||||
|
route->gateway = charon->kernel->get_nexthop(charon->kernel,
|
||||||
|
iface, policy->sel.prefixlen_d,
|
||||||
|
route->src_ip, &route->if_name);
|
||||||
|
iface->destroy(iface);
|
||||||
|
}
|
||||||
|
route->dst_net = chunk_alloc(policy->sel.family == AF_INET ? 4 : 16);
|
||||||
|
memcpy(route->dst_net.ptr, &policy->sel.daddr, route->dst_net.len);
|
||||||
|
|
||||||
|
/* get the interface to install the route for, if we haven't one yet.
|
||||||
|
* If we have a local address, use it. Otherwise (for shunt policies)
|
||||||
|
* use the route's source address. */
|
||||||
|
if (!route->if_name)
|
||||||
{
|
{
|
||||||
free(route);
|
iface = ipsec->src;
|
||||||
|
if (iface->is_anyaddr(iface))
|
||||||
|
{
|
||||||
|
iface = route->src_ip;
|
||||||
|
}
|
||||||
|
if (!charon->kernel->get_interface(charon->kernel, iface,
|
||||||
|
&route->if_name))
|
||||||
|
{
|
||||||
|
route_entry_destroy(route);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (policy->route)
|
||||||
|
{
|
||||||
|
route_entry_t *old = policy->route;
|
||||||
|
if (route_entry_equals(old, route))
|
||||||
|
{
|
||||||
|
route_entry_destroy(route);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* uninstall previously installed route */
|
||||||
|
if (charon->kernel->del_route(charon->kernel, old->dst_net,
|
||||||
|
old->prefixlen, old->gateway,
|
||||||
|
old->src_ip, old->if_name,
|
||||||
|
old->pass) != SUCCESS)
|
||||||
|
{
|
||||||
|
DBG1(DBG_KNL, "error uninstalling route installed with policy "
|
||||||
|
"%R === %R %N", out->src_ts, out->dst_ts, policy_dir_names,
|
||||||
|
policy->direction);
|
||||||
|
}
|
||||||
|
route_entry_destroy(old);
|
||||||
|
policy->route = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
DBG2(DBG_KNL, "installing route: %R via %H src %H dev %s", out->dst_ts,
|
||||||
|
route->gateway, route->src_ip, route->if_name);
|
||||||
|
switch (charon->kernel->add_route(charon->kernel, route->dst_net,
|
||||||
|
route->prefixlen, route->gateway,
|
||||||
|
route->src_ip, route->if_name,
|
||||||
|
route->pass))
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
DBG1(DBG_KNL, "unable to install source route for %H",
|
||||||
|
route->src_ip);
|
||||||
|
/* FALL */
|
||||||
|
case ALREADY_DONE:
|
||||||
|
/* route exists, do not uninstall */
|
||||||
|
route_entry_destroy(route);
|
||||||
|
break;
|
||||||
|
case SUCCESS:
|
||||||
|
/* cache the installed route */
|
||||||
|
policy->route = route;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user