kernel-netlink: Implement passthrough type routes and use them on Linux
Enables us to ignore any future kernel features for routes unless we actually need to consider them for the source IP routes. Also enables us to actually really skip IPsec processing for those networks (because even the routes don't touch those packets). It's more what users expect. Co-authored-by: Tobias Brunner <tobias@strongswan.org>
This commit is contained in:
parent
4958acc0c2
commit
09f4bccfea
|
@ -256,14 +256,14 @@ METHOD(kernel_net_t, del_ip, status_t,
|
|||
|
||||
METHOD(kernel_net_t, add_route, status_t,
|
||||
private_android_net_t *this, chunk_t dst_net, uint8_t prefixlen,
|
||||
host_t *gateway, host_t *src_ip, char *if_name)
|
||||
host_t *gateway, host_t *src_ip, char *if_name, bool pass)
|
||||
{
|
||||
return NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
METHOD(kernel_net_t, del_route, status_t,
|
||||
private_android_net_t *this, chunk_t dst_net, uint8_t prefixlen,
|
||||
host_t *gateway, host_t *src_ip, char *if_name)
|
||||
host_t *gateway, host_t *src_ip, char *if_name, bool pass)
|
||||
{
|
||||
return NOT_SUPPORTED;
|
||||
}
|
||||
|
|
|
@ -614,26 +614,28 @@ METHOD(kernel_interface_t, del_ip, status_t,
|
|||
|
||||
METHOD(kernel_interface_t, add_route, status_t,
|
||||
private_kernel_interface_t *this, chunk_t dst_net,
|
||||
uint8_t prefixlen, host_t *gateway, host_t *src_ip, char *if_name)
|
||||
uint8_t prefixlen, host_t *gateway, host_t *src_ip, char *if_name,
|
||||
bool pass)
|
||||
{
|
||||
if (!this->net)
|
||||
{
|
||||
return NOT_SUPPORTED;
|
||||
}
|
||||
return this->net->add_route(this->net, dst_net, prefixlen, gateway,
|
||||
src_ip, if_name);
|
||||
src_ip, if_name, pass);
|
||||
}
|
||||
|
||||
METHOD(kernel_interface_t, del_route, status_t,
|
||||
private_kernel_interface_t *this, chunk_t dst_net,
|
||||
uint8_t prefixlen, host_t *gateway, host_t *src_ip, char *if_name)
|
||||
uint8_t prefixlen, host_t *gateway, host_t *src_ip, char *if_name,
|
||||
bool pass)
|
||||
{
|
||||
if (!this->net)
|
||||
{
|
||||
return NOT_SUPPORTED;
|
||||
}
|
||||
return this->net->del_route(this->net, dst_net, prefixlen, gateway,
|
||||
src_ip, if_name);
|
||||
src_ip, if_name, pass);
|
||||
}
|
||||
|
||||
METHOD(kernel_interface_t, bypass_socket, bool,
|
||||
|
|
|
@ -375,12 +375,13 @@ struct kernel_interface_t {
|
|||
* @param gateway gateway for this route
|
||||
* @param src_ip source ip of the route
|
||||
* @param if_name name of the interface the route is bound to
|
||||
* @param pass TRUE if route is installed for passthrough policy
|
||||
* @return SUCCESS if operation completed
|
||||
* ALREADY_DONE if the route already exists
|
||||
*/
|
||||
status_t (*add_route) (kernel_interface_t *this, chunk_t dst_net,
|
||||
uint8_t prefixlen, host_t *gateway, host_t *src_ip,
|
||||
char *if_name);
|
||||
char *if_name, bool pass);
|
||||
|
||||
/**
|
||||
* Delete a route.
|
||||
|
@ -390,11 +391,12 @@ struct kernel_interface_t {
|
|||
* @param gateway gateway for this route
|
||||
* @param src_ip source ip of the route
|
||||
* @param if_name name of the interface the route is bound to
|
||||
* @param pass TRUE if route was installed for passthrough policy
|
||||
* @return SUCCESS if operation completed
|
||||
*/
|
||||
status_t (*del_route) (kernel_interface_t *this, chunk_t dst_net,
|
||||
uint8_t prefixlen, host_t *gateway, host_t *src_ip,
|
||||
char *if_name);
|
||||
char *if_name, bool pass);
|
||||
|
||||
/**
|
||||
* Set up a bypass policy for a given socket.
|
||||
|
|
|
@ -165,12 +165,13 @@ struct kernel_net_t {
|
|||
* @param gateway gateway for this route
|
||||
* @param src_ip source ip of the route
|
||||
* @param if_name name of the interface the route is bound to
|
||||
* @param pass TRUE if route is installed for passthrough policy
|
||||
* @return SUCCESS if operation completed
|
||||
* ALREADY_DONE if the route already exists
|
||||
*/
|
||||
status_t (*add_route) (kernel_net_t *this, chunk_t dst_net,
|
||||
uint8_t prefixlen, host_t *gateway, host_t *src_ip,
|
||||
char *if_name);
|
||||
char *if_name, bool pass);
|
||||
|
||||
/**
|
||||
* Delete a route.
|
||||
|
@ -180,11 +181,12 @@ struct kernel_net_t {
|
|||
* @param gateway gateway for this route
|
||||
* @param src_ip source ip of the route
|
||||
* @param if_name name of the interface the route is bound to
|
||||
* @param pass TRUE if route was installed for passthrough policy
|
||||
* @return SUCCESS if operation completed
|
||||
*/
|
||||
status_t (*del_route) (kernel_net_t *this, chunk_t dst_net,
|
||||
uint8_t prefixlen, host_t *gateway, host_t *src_ip,
|
||||
char *if_name);
|
||||
char *if_name, bool pass);
|
||||
|
||||
/**
|
||||
* Destroy the implementation.
|
||||
|
|
|
@ -715,14 +715,14 @@ static status_t manage_route(private_kernel_iph_net_t *this, bool add,
|
|||
|
||||
METHOD(kernel_net_t, add_route, status_t,
|
||||
private_kernel_iph_net_t *this, chunk_t dst, uint8_t prefixlen,
|
||||
host_t *gateway, host_t *src, char *name)
|
||||
host_t *gateway, host_t *src, char *name, bool pass)
|
||||
{
|
||||
return manage_route(this, TRUE, dst, prefixlen, gateway, name);
|
||||
}
|
||||
|
||||
METHOD(kernel_net_t, del_route, status_t,
|
||||
private_kernel_iph_net_t *this, chunk_t dst, uint8_t prefixlen,
|
||||
host_t *gateway, host_t *src, char *name)
|
||||
host_t *gateway, host_t *src, char *name, bool pass)
|
||||
{
|
||||
return manage_route(this, FALSE, dst, prefixlen, gateway, name);
|
||||
}
|
||||
|
|
|
@ -315,7 +315,7 @@ static void add_exclude_route(private_kernel_libipsec_ipsec_t *this,
|
|||
if (charon->kernel->get_interface(charon->kernel, src, &if_name) &&
|
||||
charon->kernel->add_route(charon->kernel, dst->get_address(dst),
|
||||
dst->get_family(dst) == AF_INET ? 32 : 128,
|
||||
gtw, src, if_name) == SUCCESS)
|
||||
gtw, src, if_name, TRUE) == SUCCESS)
|
||||
{
|
||||
INIT(exclude,
|
||||
.dst = dst->clone(dst),
|
||||
|
@ -363,7 +363,7 @@ static void remove_exclude_route(private_kernel_libipsec_ipsec_t *this,
|
|||
charon->kernel->del_route(charon->kernel, dst->get_address(dst),
|
||||
dst->get_family(dst) == AF_INET ? 32 : 128,
|
||||
route->exclude->gtw, route->exclude->src,
|
||||
if_name) != SUCCESS)
|
||||
if_name, TRUE) != SUCCESS)
|
||||
{
|
||||
DBG1(DBG_KNL, "uninstalling exclude route for %H failed", dst);
|
||||
}
|
||||
|
@ -449,8 +449,8 @@ static bool install_route(private_kernel_libipsec_ipsec_t *this,
|
|||
}
|
||||
/* uninstall previously installed route */
|
||||
if (charon->kernel->del_route(charon->kernel, old->dst_net,
|
||||
old->prefixlen, old->gateway,
|
||||
old->src_ip, old->if_name) != SUCCESS)
|
||||
old->prefixlen, old->gateway, old->src_ip,
|
||||
old->if_name, FALSE) != SUCCESS)
|
||||
{
|
||||
DBG1(DBG_KNL, "error uninstalling route installed with policy "
|
||||
"%R === %R %N", src_ts, dst_ts, policy_dir_names,
|
||||
|
@ -481,7 +481,7 @@ static bool install_route(private_kernel_libipsec_ipsec_t *this,
|
|||
|
||||
switch (charon->kernel->add_route(charon->kernel, route->dst_net,
|
||||
route->prefixlen, route->gateway,
|
||||
route->src_ip, route->if_name))
|
||||
route->src_ip, route->if_name, FALSE))
|
||||
{
|
||||
case ALREADY_DONE:
|
||||
/* route exists, do not uninstall */
|
||||
|
@ -586,8 +586,8 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
|
|||
route_entry_t *route = policy->route;
|
||||
|
||||
if (charon->kernel->del_route(charon->kernel, route->dst_net,
|
||||
route->prefixlen, route->gateway,
|
||||
route->src_ip, route->if_name) != SUCCESS)
|
||||
route->prefixlen, route->gateway, route->src_ip,
|
||||
route->if_name, FALSE) != SUCCESS)
|
||||
{
|
||||
DBG1(DBG_KNL, "error uninstalling route installed with "
|
||||
"policy %R === %R %N", id->src_ts, id->dst_ts,
|
||||
|
@ -618,7 +618,7 @@ METHOD(kernel_ipsec_t, flush_policies, status_t,
|
|||
|
||||
charon->kernel->del_route(charon->kernel, route->dst_net,
|
||||
route->prefixlen, route->gateway,
|
||||
route->src_ip, route->if_name);
|
||||
route->src_ip, route->if_name, FALSE);
|
||||
remove_exclude_route(this, route);
|
||||
}
|
||||
policy_entry_destroy(pol);
|
||||
|
|
|
@ -390,6 +390,9 @@ struct route_entry_t {
|
|||
|
||||
/** Destination net prefixlen */
|
||||
uint8_t prefixlen;
|
||||
|
||||
/** Whether the route was installed for a passthrough policy */
|
||||
bool pass;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -410,6 +413,7 @@ static void route_entry_destroy(route_entry_t *this)
|
|||
static bool route_entry_equals(route_entry_t *a, route_entry_t *b)
|
||||
{
|
||||
if (a->if_name && b->if_name && streq(a->if_name, b->if_name) &&
|
||||
a->pass == b->pass &&
|
||||
a->src_ip->ip_equals(a->src_ip, b->src_ip) &&
|
||||
chunk_equals(a->dst_net, b->dst_net) && a->prefixlen == b->prefixlen)
|
||||
{
|
||||
|
@ -2614,6 +2618,7 @@ static void install_route(private_kernel_netlink_ipsec_t *this,
|
|||
|
||||
INIT(route,
|
||||
.prefixlen = policy->sel.prefixlen_d,
|
||||
.pass = mapping->type == POLICY_PASS,
|
||||
);
|
||||
|
||||
if (charon->kernel->get_address_by_ts(charon->kernel, out->src_ts,
|
||||
|
@ -2664,7 +2669,8 @@ static void install_route(private_kernel_netlink_ipsec_t *this,
|
|||
/* uninstall previously installed route */
|
||||
if (charon->kernel->del_route(charon->kernel, old->dst_net,
|
||||
old->prefixlen, old->gateway,
|
||||
old->src_ip, old->if_name) != SUCCESS)
|
||||
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,
|
||||
|
@ -2678,7 +2684,8 @@ static void install_route(private_kernel_netlink_ipsec_t *this,
|
|||
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->src_ip, route->if_name,
|
||||
route->pass))
|
||||
{
|
||||
default:
|
||||
DBG1(DBG_KNL, "unable to install source route for %H",
|
||||
|
@ -3207,7 +3214,8 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
|
|||
route_entry_t *route = current->route;
|
||||
if (charon->kernel->del_route(charon->kernel, route->dst_net,
|
||||
route->prefixlen, route->gateway,
|
||||
route->src_ip, route->if_name) != SUCCESS)
|
||||
route->src_ip, route->if_name,
|
||||
route->pass) != SUCCESS)
|
||||
{
|
||||
DBG1(DBG_KNL, "error uninstalling route installed with policy "
|
||||
"%R === %R %N%s", id->src_ts, id->dst_ts, policy_dir_names,
|
||||
|
|
|
@ -286,6 +286,9 @@ struct route_entry_t {
|
|||
|
||||
/** Destination net prefixlen */
|
||||
uint8_t prefixlen;
|
||||
|
||||
/** Whether the route was installed for a passthrough policy */
|
||||
bool pass;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -301,6 +304,7 @@ static route_entry_t *route_entry_clone(route_entry_t *this)
|
|||
.gateway = this->gateway ? this->gateway->clone(this->gateway) : NULL,
|
||||
.dst_net = chunk_clone(this->dst_net),
|
||||
.prefixlen = this->prefixlen,
|
||||
.pass = this->pass,
|
||||
);
|
||||
return route;
|
||||
}
|
||||
|
@ -332,6 +336,7 @@ static u_int route_entry_hash(route_entry_t *this)
|
|||
static bool route_entry_equals(route_entry_t *a, route_entry_t *b)
|
||||
{
|
||||
if (a->if_name && b->if_name && streq(a->if_name, b->if_name) &&
|
||||
a->pass == b->pass &&
|
||||
a->src_ip->ip_equals(a->src_ip, b->src_ip) &&
|
||||
chunk_equals(a->dst_net, b->dst_net) && a->prefixlen == b->prefixlen)
|
||||
{
|
||||
|
@ -544,7 +549,7 @@ struct private_kernel_netlink_net_t {
|
|||
static status_t manage_srcroute(private_kernel_netlink_net_t *this,
|
||||
int nlmsg_type, int flags, chunk_t dst_net,
|
||||
uint8_t prefixlen, host_t *gateway,
|
||||
host_t *src_ip, char *if_name);
|
||||
host_t *src_ip, char *if_name, bool pass);
|
||||
|
||||
/**
|
||||
* Clear the queued network changes.
|
||||
|
@ -580,6 +585,10 @@ static job_requeue_t reinstall_routes(private_kernel_netlink_net_t *this)
|
|||
net_change_t *change, lookup = {
|
||||
.if_name = route->if_name,
|
||||
};
|
||||
if (route->pass)
|
||||
{ /* no need to reinstall these, they don't reference interfaces */
|
||||
continue;
|
||||
}
|
||||
/* check if a change for the outgoing interface is queued */
|
||||
change = this->net_changes->get(this->net_changes, &lookup);
|
||||
if (!change)
|
||||
|
@ -598,7 +607,7 @@ static job_requeue_t reinstall_routes(private_kernel_netlink_net_t *this)
|
|||
{
|
||||
manage_srcroute(this, RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL,
|
||||
route->dst_net, route->prefixlen, route->gateway,
|
||||
route->src_ip, route->if_name);
|
||||
route->src_ip, route->if_name, route->pass);
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
@ -2632,7 +2641,7 @@ METHOD(kernel_net_t, del_ip, status_t,
|
|||
static status_t manage_srcroute(private_kernel_netlink_net_t *this,
|
||||
int nlmsg_type, int flags, chunk_t dst_net,
|
||||
uint8_t prefixlen, host_t *gateway,
|
||||
host_t *src_ip, char *if_name)
|
||||
host_t *src_ip, char *if_name, bool pass)
|
||||
{
|
||||
netlink_buf_t request;
|
||||
struct nlmsghdr *hdr;
|
||||
|
@ -2653,12 +2662,12 @@ static status_t manage_srcroute(private_kernel_netlink_net_t *this,
|
|||
half_net = chunk_alloca(dst_net.len);
|
||||
memset(half_net.ptr, 0, half_net.len);
|
||||
half_prefixlen = 1;
|
||||
|
||||
/* no throw routes in the main table */
|
||||
status = manage_srcroute(this, nlmsg_type, flags, half_net,
|
||||
half_prefixlen, gateway, src_ip, if_name);
|
||||
half_prefixlen, gateway, src_ip, if_name, FALSE);
|
||||
half_net.ptr[0] |= 0x80;
|
||||
status |= manage_srcroute(this, nlmsg_type, flags, half_net,
|
||||
half_prefixlen, gateway, src_ip, if_name);
|
||||
half_prefixlen, gateway, src_ip, if_name, FALSE);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -2670,10 +2679,10 @@ static status_t manage_srcroute(private_kernel_netlink_net_t *this,
|
|||
hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
|
||||
|
||||
msg = NLMSG_DATA(hdr);
|
||||
msg->rtm_family = src_ip->get_family(src_ip);
|
||||
msg->rtm_family = (dst_net.len == 4) ? AF_INET : AF_INET6;
|
||||
msg->rtm_dst_len = prefixlen;
|
||||
msg->rtm_protocol = RTPROT_STATIC;
|
||||
msg->rtm_type = RTN_UNICAST;
|
||||
msg->rtm_type = pass ? RTN_THROW : RTN_UNICAST;
|
||||
msg->rtm_scope = RT_SCOPE_UNIVERSE;
|
||||
|
||||
if (this->routing_table < 256)
|
||||
|
@ -2691,42 +2700,48 @@ static status_t manage_srcroute(private_kernel_netlink_net_t *this,
|
|||
#endif /* HAVE_RTA_TABLE */
|
||||
}
|
||||
netlink_add_attribute(hdr, RTA_DST, dst_net, sizeof(request));
|
||||
chunk = src_ip->get_address(src_ip);
|
||||
netlink_add_attribute(hdr, RTA_PREFSRC, chunk, sizeof(request));
|
||||
if (gateway && gateway->get_family(gateway) == src_ip->get_family(src_ip))
|
||||
{
|
||||
chunk = gateway->get_address(gateway);
|
||||
netlink_add_attribute(hdr, RTA_GATEWAY, chunk, sizeof(request));
|
||||
}
|
||||
ifindex = get_interface_index(this, if_name);
|
||||
chunk.ptr = (char*)&ifindex;
|
||||
chunk.len = sizeof(ifindex);
|
||||
netlink_add_attribute(hdr, RTA_OIF, chunk, sizeof(request));
|
||||
|
||||
if (this->mtu || this->mss)
|
||||
/* only when installing regular routes do we need all the parameters,
|
||||
* deletes are done by destination net (except if metrics are used, which
|
||||
* we don't support), for throw routes we don't need any of them either */
|
||||
if (nlmsg_type == RTM_NEWROUTE && !pass)
|
||||
{
|
||||
chunk = chunk_alloca(RTA_LENGTH((sizeof(struct rtattr) +
|
||||
sizeof(uint32_t)) * 2));
|
||||
chunk.len = 0;
|
||||
rta = (struct rtattr*)chunk.ptr;
|
||||
if (this->mtu)
|
||||
chunk = src_ip->get_address(src_ip);
|
||||
netlink_add_attribute(hdr, RTA_PREFSRC, chunk, sizeof(request));
|
||||
if (gateway && gateway->get_family(gateway) == src_ip->get_family(src_ip))
|
||||
{
|
||||
rta->rta_type = RTAX_MTU;
|
||||
rta->rta_len = RTA_LENGTH(sizeof(uint32_t));
|
||||
memcpy(RTA_DATA(rta), &this->mtu, sizeof(uint32_t));
|
||||
chunk.len = rta->rta_len;
|
||||
chunk = gateway->get_address(gateway);
|
||||
netlink_add_attribute(hdr, RTA_GATEWAY, chunk, sizeof(request));
|
||||
}
|
||||
if (this->mss)
|
||||
{
|
||||
rta = (struct rtattr*)(chunk.ptr + RTA_ALIGN(chunk.len));
|
||||
rta->rta_type = RTAX_ADVMSS;
|
||||
rta->rta_len = RTA_LENGTH(sizeof(uint32_t));
|
||||
memcpy(RTA_DATA(rta), &this->mss, sizeof(uint32_t));
|
||||
chunk.len = RTA_ALIGN(chunk.len) + rta->rta_len;
|
||||
}
|
||||
netlink_add_attribute(hdr, RTA_METRICS, chunk, sizeof(request));
|
||||
}
|
||||
ifindex = get_interface_index(this, if_name);
|
||||
chunk.ptr = (char*)&ifindex;
|
||||
chunk.len = sizeof(ifindex);
|
||||
netlink_add_attribute(hdr, RTA_OIF, chunk, sizeof(request));
|
||||
|
||||
if (this->mtu || this->mss)
|
||||
{
|
||||
chunk = chunk_alloca(RTA_LENGTH((sizeof(struct rtattr) +
|
||||
sizeof(uint32_t)) * 2));
|
||||
chunk.len = 0;
|
||||
rta = (struct rtattr*)chunk.ptr;
|
||||
if (this->mtu)
|
||||
{
|
||||
rta->rta_type = RTAX_MTU;
|
||||
rta->rta_len = RTA_LENGTH(sizeof(uint32_t));
|
||||
memcpy(RTA_DATA(rta), &this->mtu, sizeof(uint32_t));
|
||||
chunk.len = rta->rta_len;
|
||||
}
|
||||
if (this->mss)
|
||||
{
|
||||
rta = (struct rtattr*)(chunk.ptr + RTA_ALIGN(chunk.len));
|
||||
rta->rta_type = RTAX_ADVMSS;
|
||||
rta->rta_len = RTA_LENGTH(sizeof(uint32_t));
|
||||
memcpy(RTA_DATA(rta), &this->mss, sizeof(uint32_t));
|
||||
chunk.len = RTA_ALIGN(chunk.len) + rta->rta_len;
|
||||
}
|
||||
netlink_add_attribute(hdr, RTA_METRICS, chunk, sizeof(request));
|
||||
}
|
||||
}
|
||||
return this->socket->send_ack(this->socket, hdr);
|
||||
}
|
||||
|
||||
|
@ -2769,7 +2784,7 @@ static bool route_with_dst(route_entry_lookup_t *a, route_entry_t *b)
|
|||
|
||||
METHOD(kernel_net_t, add_route, status_t,
|
||||
private_kernel_netlink_net_t *this, chunk_t dst_net, uint8_t prefixlen,
|
||||
host_t *gateway, host_t *src_ip, char *if_name)
|
||||
host_t *gateway, host_t *src_ip, char *if_name, bool pass)
|
||||
{
|
||||
status_t status;
|
||||
route_entry_t *found;
|
||||
|
@ -2780,10 +2795,16 @@ METHOD(kernel_net_t, add_route, status_t,
|
|||
.gateway = gateway,
|
||||
.src_ip = src_ip,
|
||||
.if_name = if_name,
|
||||
.pass = pass,
|
||||
},
|
||||
.this = this,
|
||||
};
|
||||
|
||||
if (!this->routing_table)
|
||||
{ /* treat these as regular routes if installing in the main table */
|
||||
pass = lookup.route.pass = FALSE;
|
||||
}
|
||||
|
||||
this->routes_lock->lock(this->routes_lock);
|
||||
found = this->routes->get(this->routes, &lookup.route);
|
||||
if (found)
|
||||
|
@ -2808,7 +2829,8 @@ METHOD(kernel_net_t, add_route, status_t,
|
|||
else
|
||||
{
|
||||
status = manage_srcroute(this, RTM_NEWROUTE, NLM_F_CREATE|NLM_F_REPLACE,
|
||||
dst_net, prefixlen, gateway, src_ip, if_name);
|
||||
dst_net, prefixlen, gateway, src_ip, if_name,
|
||||
pass);
|
||||
}
|
||||
if (status == SUCCESS)
|
||||
{
|
||||
|
@ -2821,7 +2843,7 @@ METHOD(kernel_net_t, add_route, status_t,
|
|||
|
||||
METHOD(kernel_net_t, del_route, status_t,
|
||||
private_kernel_netlink_net_t *this, chunk_t dst_net, uint8_t prefixlen,
|
||||
host_t *gateway, host_t *src_ip, char *if_name)
|
||||
host_t *gateway, host_t *src_ip, char *if_name, bool pass)
|
||||
{
|
||||
status_t status;
|
||||
route_entry_t *found;
|
||||
|
@ -2832,10 +2854,16 @@ METHOD(kernel_net_t, del_route, status_t,
|
|||
.gateway = gateway,
|
||||
.src_ip = src_ip,
|
||||
.if_name = if_name,
|
||||
.pass = pass,
|
||||
},
|
||||
.this = this,
|
||||
};
|
||||
|
||||
if (!this->routing_table)
|
||||
{ /* treat these as regular routes if installing in the main table */
|
||||
pass = lookup.route.pass = FALSE;
|
||||
}
|
||||
|
||||
this->routes_lock->lock(this->routes_lock);
|
||||
found = this->routes->remove(this->routes, &lookup.route);
|
||||
if (!found)
|
||||
|
@ -2860,12 +2888,12 @@ METHOD(kernel_net_t, del_route, status_t,
|
|||
{
|
||||
status = manage_srcroute(this, RTM_NEWROUTE, NLM_F_CREATE|NLM_F_REPLACE,
|
||||
found->dst_net, found->prefixlen, found->gateway,
|
||||
found->src_ip, found->if_name);
|
||||
found->src_ip, found->if_name, found->pass);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = manage_srcroute(this, RTM_DELROUTE, 0, dst_net, prefixlen,
|
||||
gateway, src_ip, if_name);
|
||||
gateway, src_ip, if_name, pass);
|
||||
}
|
||||
this->routes_lock->unlock(this->routes_lock);
|
||||
return status;
|
||||
|
@ -3111,7 +3139,8 @@ METHOD(kernel_net_t, destroy, void,
|
|||
while (enumerator->enumerate(enumerator, NULL, (void**)&route))
|
||||
{
|
||||
manage_srcroute(this, RTM_DELROUTE, 0, route->dst_net, route->prefixlen,
|
||||
route->gateway, route->src_ip, route->if_name);
|
||||
route->gateway, route->src_ip, route->if_name,
|
||||
route->pass);
|
||||
route_entry_destroy(route);
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
|
|
@ -2332,7 +2332,7 @@ static void add_exclude_route(private_kernel_pfkey_ipsec_t *this,
|
|||
charon->kernel->add_route(charon->kernel,
|
||||
dst->get_address(dst),
|
||||
dst->get_family(dst) == AF_INET ? 32 : 128,
|
||||
gtw, src, if_name) == SUCCESS)
|
||||
gtw, src, if_name, FALSE) == SUCCESS)
|
||||
{
|
||||
INIT(exclude,
|
||||
.dst = dst->clone(dst),
|
||||
|
@ -2399,7 +2399,7 @@ static void remove_exclude_route(private_kernel_pfkey_ipsec_t *this,
|
|||
dst->get_address(dst),
|
||||
dst->get_family(dst) == AF_INET ? 32 : 128,
|
||||
route->exclude->gtw, route->exclude->src,
|
||||
if_name) != SUCCESS)
|
||||
if_name, FALSE) != SUCCESS)
|
||||
{
|
||||
DBG1(DBG_KNL, "uninstalling exclude route for %H failed", dst);
|
||||
}
|
||||
|
@ -2479,8 +2479,8 @@ static bool install_route(private_kernel_pfkey_ipsec_t *this,
|
|||
}
|
||||
/* uninstall previously installed route */
|
||||
if (charon->kernel->del_route(charon->kernel, old->dst_net,
|
||||
old->prefixlen, old->gateway,
|
||||
old->src_ip, old->if_name) != SUCCESS)
|
||||
old->prefixlen, old->gateway,
|
||||
old->src_ip, old->if_name, FALSE) != SUCCESS)
|
||||
{
|
||||
DBG1(DBG_KNL, "error uninstalling route installed with policy "
|
||||
"%R === %R %N", out->src_ts, out->dst_ts,
|
||||
|
@ -2512,7 +2512,7 @@ static bool install_route(private_kernel_pfkey_ipsec_t *this,
|
|||
|
||||
switch (charon->kernel->add_route(charon->kernel, route->dst_net,
|
||||
route->prefixlen, route->gateway,
|
||||
route->src_ip, route->if_name))
|
||||
route->src_ip, route->if_name, FALSE))
|
||||
{
|
||||
case ALREADY_DONE:
|
||||
/* route exists, do not uninstall */
|
||||
|
@ -3067,8 +3067,8 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
|
|||
{
|
||||
route_entry_t *route = policy->route;
|
||||
if (charon->kernel->del_route(charon->kernel, route->dst_net,
|
||||
route->prefixlen, route->gateway,
|
||||
route->src_ip, route->if_name) != SUCCESS)
|
||||
route->prefixlen, route->gateway,
|
||||
route->src_ip, route->if_name, FALSE) != SUCCESS)
|
||||
{
|
||||
DBG1(DBG_KNL, "error uninstalling route installed with "
|
||||
"policy %R === %R %N", id->src_ts, id->dst_ts,
|
||||
|
|
|
@ -1494,7 +1494,7 @@ static status_t manage_route(private_kernel_pfroute_net_t *this, int op,
|
|||
|
||||
METHOD(kernel_net_t, add_route, status_t,
|
||||
private_kernel_pfroute_net_t *this, chunk_t dst_net, uint8_t prefixlen,
|
||||
host_t *gateway, host_t *src_ip, char *if_name)
|
||||
host_t *gateway, host_t *src_ip, char *if_name, bool pass)
|
||||
{
|
||||
status_t status;
|
||||
route_entry_t *found, route = {
|
||||
|
@ -1523,7 +1523,7 @@ METHOD(kernel_net_t, add_route, status_t,
|
|||
|
||||
METHOD(kernel_net_t, del_route, status_t,
|
||||
private_kernel_pfroute_net_t *this, chunk_t dst_net, uint8_t prefixlen,
|
||||
host_t *gateway, host_t *src_ip, char *if_name)
|
||||
host_t *gateway, host_t *src_ip, char *if_name, bool pass)
|
||||
{
|
||||
status_t status;
|
||||
route_entry_t *found, route = {
|
||||
|
|
|
@ -1402,7 +1402,8 @@ static bool uninstall_route(private_kernel_wfp_ipsec_t *this,
|
|||
if (charon->kernel->get_interface(charon->kernel, src, &name))
|
||||
{
|
||||
res = charon->kernel->del_route(charon->kernel,
|
||||
dst->get_address(dst), mask, gtw, src, name) == SUCCESS;
|
||||
dst->get_address(dst), mask, gtw, src,
|
||||
name, FALSE) == SUCCESS;
|
||||
free(name);
|
||||
}
|
||||
route = this->routes->remove(this->routes, route);
|
||||
|
@ -1446,8 +1447,8 @@ static bool install_route(private_kernel_wfp_ipsec_t *this,
|
|||
{
|
||||
if (charon->kernel->get_interface(charon->kernel, src, &name))
|
||||
{
|
||||
if (charon->kernel->add_route(charon->kernel,
|
||||
dst->get_address(dst), mask, gtw, src, name) == SUCCESS)
|
||||
if (charon->kernel->add_route(charon->kernel, dst->get_address(dst),
|
||||
mask, gtw, src, name, FALSE) == SUCCESS)
|
||||
{
|
||||
INIT(route,
|
||||
.dst = dst->clone(dst),
|
||||
|
|
Loading…
Reference in New Issue