do not use a route if outgoing interface is down
other cleanups
This commit is contained in:
@@ -256,7 +256,7 @@ static status_t get_address_by_ts(private_kernel_interface_t *this,
|
|||||||
}
|
}
|
||||||
host->destroy(host);
|
host->destroy(host);
|
||||||
|
|
||||||
addrs = this->public.create_address_enumerator(&this->public, TRUE, TRUE);
|
addrs = create_address_enumerator(this, TRUE, TRUE);
|
||||||
while (addrs->enumerate(addrs, (void**)&host))
|
while (addrs->enumerate(addrs, (void**)&host))
|
||||||
{
|
{
|
||||||
if (ts->includes(ts, host))
|
if (ts->includes(ts, host))
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ struct private_kernel_netlink_net_t {
|
|||||||
* priority of used routing table
|
* priority of used routing table
|
||||||
*/
|
*/
|
||||||
int routing_table_prio;
|
int routing_table_prio;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* whether to react to RTM_NEWROUTE or RTM_DELROUTE events
|
* whether to react to RTM_NEWROUTE or RTM_DELROUTE events
|
||||||
*/
|
*/
|
||||||
@@ -207,7 +207,7 @@ static int get_vip_refcount(private_kernel_netlink_net_t *this, host_t* ip)
|
|||||||
static void fire_roam_job(private_kernel_netlink_net_t *this, bool address)
|
static void fire_roam_job(private_kernel_netlink_net_t *this, bool address)
|
||||||
{
|
{
|
||||||
struct timeval now;
|
struct timeval now;
|
||||||
|
|
||||||
if (gettimeofday(&now, NULL) == 0)
|
if (gettimeofday(&now, NULL) == 0)
|
||||||
{
|
{
|
||||||
if (timercmp(&now, &this->last_roam, >))
|
if (timercmp(&now, &this->last_roam, >))
|
||||||
@@ -700,6 +700,28 @@ static int get_interface_index(private_kernel_netlink_net_t *this, char* name)
|
|||||||
return ifindex;
|
return ifindex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if an interface with a given index is up
|
||||||
|
*/
|
||||||
|
static bool is_interface_up(private_kernel_netlink_net_t *this, int index)
|
||||||
|
{
|
||||||
|
enumerator_t *ifaces;
|
||||||
|
iface_entry_t *iface;
|
||||||
|
bool up = FALSE;
|
||||||
|
|
||||||
|
ifaces = this->ifaces->create_enumerator(this->ifaces);
|
||||||
|
while (ifaces->enumerate(ifaces, &iface))
|
||||||
|
{
|
||||||
|
if (iface->ifindex == index)
|
||||||
|
{
|
||||||
|
up = iface->flags & IFF_UP;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ifaces->destroy(ifaces);
|
||||||
|
return up;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* check if an address (chunk) addr is in subnet (net with net_len net bits)
|
* check if an address (chunk) addr is in subnet (net with net_len net bits)
|
||||||
*/
|
*/
|
||||||
@@ -786,6 +808,9 @@ static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest,
|
|||||||
size_t rtasize;
|
size_t rtasize;
|
||||||
chunk_t rta_gtw, rta_src, rta_dst;
|
chunk_t rta_gtw, rta_src, rta_dst;
|
||||||
u_int32_t rta_oif = 0;
|
u_int32_t rta_oif = 0;
|
||||||
|
enumerator_t *ifaces, *addrs;
|
||||||
|
iface_entry_t *iface;
|
||||||
|
addr_entry_t *addr;
|
||||||
|
|
||||||
rta_gtw = rta_src = rta_dst = chunk_empty;
|
rta_gtw = rta_src = rta_dst = chunk_empty;
|
||||||
msg = (struct rtmsg*)(NLMSG_DATA(current));
|
msg = (struct rtmsg*)(NLMSG_DATA(current));
|
||||||
@@ -813,71 +838,73 @@ static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest,
|
|||||||
}
|
}
|
||||||
rta = RTA_NEXT(rta, rtasize);
|
rta = RTA_NEXT(rta, rtasize);
|
||||||
}
|
}
|
||||||
|
if (rta_oif && !is_interface_up(this, rta_oif))
|
||||||
|
{ /* interface is down */
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
if (this->routing_table != 0 &&
|
||||||
|
msg->rtm_table == this->routing_table)
|
||||||
|
{ /* route is from our own ipsec routing table */
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
if (msg->rtm_dst_len <= best)
|
||||||
|
{ /* not better than a previous one */
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
if (msg->rtm_dst_len != 0 &&
|
||||||
|
(!rta_dst.ptr ||
|
||||||
|
!addr_in_subnet(chunk, rta_dst, msg->rtm_dst_len)))
|
||||||
|
{ /* is not the default route and not contained in our dst */
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
|
||||||
/* apply the route if:
|
best = msg->rtm_dst_len;
|
||||||
* - it is not from our own ipsec routing table
|
if (nexthop)
|
||||||
* - is better than a previous one
|
|
||||||
* - is the default route or
|
|
||||||
* - its destination net contains our destination
|
|
||||||
*/
|
|
||||||
if ((this->routing_table == 0 ||msg->rtm_table != this->routing_table)
|
|
||||||
&& msg->rtm_dst_len > best
|
|
||||||
&& (msg->rtm_dst_len == 0 || /* default route */
|
|
||||||
(rta_dst.ptr && addr_in_subnet(chunk, rta_dst, msg->rtm_dst_len))))
|
|
||||||
{
|
{
|
||||||
enumerator_t *ifaces, *addrs;
|
DESTROY_IF(gtw);
|
||||||
iface_entry_t *iface;
|
gtw = host_create_from_chunk(msg->rtm_family, rta_gtw, 0);
|
||||||
addr_entry_t *addr;
|
goto next;
|
||||||
|
}
|
||||||
best = msg->rtm_dst_len;
|
if (rta_src.ptr)
|
||||||
if (nexthop)
|
{
|
||||||
{
|
DESTROY_IF(src);
|
||||||
DESTROY_IF(gtw);
|
src = host_create_from_chunk(msg->rtm_family, rta_src, 0);
|
||||||
gtw = host_create_from_chunk(msg->rtm_family, rta_gtw, 0);
|
if (get_vip_refcount(this, src))
|
||||||
}
|
{ /* skip source address if it is installed by us */
|
||||||
else if (rta_src.ptr)
|
|
||||||
{
|
|
||||||
DESTROY_IF(src);
|
DESTROY_IF(src);
|
||||||
src = host_create_from_chunk(msg->rtm_family, rta_src, 0);
|
src = NULL;
|
||||||
if (get_vip_refcount(this, src))
|
|
||||||
{ /* skip source address if it is installed by us */
|
|
||||||
DESTROY_IF(src);
|
|
||||||
src = NULL;
|
|
||||||
current = NLMSG_NEXT(current, len);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
goto next;
|
||||||
|
}
|
||||||
|
/* no source addr, get one from the interfaces */
|
||||||
|
ifaces = this->ifaces->create_enumerator(this->ifaces);
|
||||||
|
while (ifaces->enumerate(ifaces, &iface))
|
||||||
|
{
|
||||||
|
if (iface->ifindex == rta_oif &&
|
||||||
|
iface->flags & IFF_UP)
|
||||||
{
|
{
|
||||||
/* no source addr, get one from the interfaces */
|
addrs = iface->addrs->create_enumerator(iface->addrs);
|
||||||
ifaces = this->ifaces->create_enumerator(this->ifaces);
|
while (addrs->enumerate(addrs, &addr))
|
||||||
while (ifaces->enumerate(ifaces, &iface))
|
|
||||||
{
|
{
|
||||||
if (iface->ifindex == rta_oif)
|
chunk_t ip = addr->ip->get_address(addr->ip);
|
||||||
|
if ((msg->rtm_dst_len == 0 &&
|
||||||
|
addr->ip->get_family(addr->ip) ==
|
||||||
|
dest->get_family(dest)) ||
|
||||||
|
addr_in_subnet(ip, rta_dst, msg->rtm_dst_len))
|
||||||
{
|
{
|
||||||
addrs = iface->addrs->create_enumerator(iface->addrs);
|
DESTROY_IF(src);
|
||||||
while (addrs->enumerate(addrs, &addr))
|
src = addr->ip->clone(addr->ip);
|
||||||
{
|
break;
|
||||||
chunk_t ip = addr->ip->get_address(addr->ip);
|
|
||||||
if ((msg->rtm_dst_len == 0 &&
|
|
||||||
addr->ip->get_family(addr->ip) ==
|
|
||||||
dest->get_family(dest)) ||
|
|
||||||
addr_in_subnet(ip, rta_dst, msg->rtm_dst_len))
|
|
||||||
{
|
|
||||||
DESTROY_IF(src);
|
|
||||||
src = addr->ip->clone(addr->ip);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
addrs->destroy(addrs);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ifaces->destroy(ifaces);
|
addrs->destroy(addrs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* FALL through */
|
ifaces->destroy(ifaces);
|
||||||
|
goto next;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
next:
|
||||||
current = NLMSG_NEXT(current, len);
|
current = NLMSG_NEXT(current, len);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user