Use a hashtable to quickly check for usable IP addresses/interfaces
This commit is contained in:
@@ -132,12 +132,72 @@ static bool iface_entry_by_index(iface_entry_t *this, int *ifindex)
|
|||||||
return this->ifindex == *ifindex;
|
return this->ifindex == *ifindex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* check if an interface is up
|
||||||
|
*/
|
||||||
|
static inline bool iface_entry_up(iface_entry_t *iface)
|
||||||
|
{
|
||||||
|
return (iface->flags & IFF_UP) == IFF_UP;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* check if an interface is up and usable
|
* check if an interface is up and usable
|
||||||
*/
|
*/
|
||||||
static inline bool iface_entry_up_and_usable(iface_entry_t *iface)
|
static inline bool iface_entry_up_and_usable(iface_entry_t *iface)
|
||||||
{
|
{
|
||||||
return iface->usable && (iface->flags & IFF_UP) == IFF_UP;
|
return iface->usable && iface_entry_up(iface);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct addr_map_entry_t addr_map_entry_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entry that maps an IP address to an interface entry
|
||||||
|
*/
|
||||||
|
struct addr_map_entry_t {
|
||||||
|
/** The IP address */
|
||||||
|
host_t *ip;
|
||||||
|
|
||||||
|
/** The interface this address is installed on */
|
||||||
|
iface_entry_t *iface;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hash a addr_map_entry_t object, all entries with the same IP address
|
||||||
|
* are stored in the same bucket
|
||||||
|
*/
|
||||||
|
static u_int addr_map_entry_hash(addr_map_entry_t *this)
|
||||||
|
{
|
||||||
|
return chunk_hash(this->ip->get_address(this->ip));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compare two addr_map_entry_t objects, two entries are equal if they are
|
||||||
|
* installed on the same interface
|
||||||
|
*/
|
||||||
|
static bool addr_map_entry_equals(addr_map_entry_t *a, addr_map_entry_t *b)
|
||||||
|
{
|
||||||
|
return a->iface->ifindex == b->iface->ifindex &&
|
||||||
|
a->ip->ip_equals(a->ip, b->ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used with get_match this finds an address entry if it is installed on
|
||||||
|
* an up and usable interface
|
||||||
|
*/
|
||||||
|
static bool addr_map_entry_match_up_and_usable(addr_map_entry_t *a,
|
||||||
|
addr_map_entry_t *b)
|
||||||
|
{
|
||||||
|
return iface_entry_up_and_usable(b->iface) &&
|
||||||
|
a->ip->ip_equals(a->ip, b->ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used with get_match this finds an address entry if it is installed on
|
||||||
|
* any active local interface
|
||||||
|
*/
|
||||||
|
static bool addr_map_entry_match_up(addr_map_entry_t *a, addr_map_entry_t *b)
|
||||||
|
{
|
||||||
|
return iface_entry_up(b->iface) && a->ip->ip_equals(a->ip, b->ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct route_entry_t route_entry_t;
|
typedef struct route_entry_t route_entry_t;
|
||||||
@@ -272,6 +332,11 @@ struct private_kernel_netlink_net_t {
|
|||||||
*/
|
*/
|
||||||
linked_list_t *ifaces;
|
linked_list_t *ifaces;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map for IP addresses to iface_entry_t objects (addr_map_entry_t)
|
||||||
|
*/
|
||||||
|
hashtable_t *addrs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* netlink rt socket (routing)
|
* netlink rt socket (routing)
|
||||||
*/
|
*/
|
||||||
@@ -485,6 +550,48 @@ static int get_vip_refcount(private_kernel_netlink_net_t *this, host_t* ip)
|
|||||||
return refcount;
|
return refcount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an address map entry
|
||||||
|
*/
|
||||||
|
static void addr_map_entry_add(private_kernel_netlink_net_t *this,
|
||||||
|
addr_entry_t *addr, iface_entry_t *iface)
|
||||||
|
{
|
||||||
|
addr_map_entry_t *entry;
|
||||||
|
|
||||||
|
if (addr->virtual)
|
||||||
|
{ /* don't map virtual IPs */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
INIT(entry,
|
||||||
|
.ip = addr->ip,
|
||||||
|
.iface = iface,
|
||||||
|
);
|
||||||
|
entry = this->addrs->put(this->addrs, entry, entry);
|
||||||
|
free(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove an address map entry (the argument order is a bit strange because
|
||||||
|
* it is also used with linked_list_t.invoke_function)
|
||||||
|
*/
|
||||||
|
static void addr_map_entry_remove(addr_entry_t *addr, iface_entry_t *iface,
|
||||||
|
private_kernel_netlink_net_t *this)
|
||||||
|
{
|
||||||
|
addr_map_entry_t *entry, lookup = {
|
||||||
|
.ip = addr->ip,
|
||||||
|
.iface = iface,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (addr->virtual)
|
||||||
|
{ /* these are never mapped, but this check avoids problems if a
|
||||||
|
* virtual IP equals a regular one */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
entry = this->addrs->remove(this->addrs, &lookup);
|
||||||
|
free(entry);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get the first non-virtual ip address on the given interface.
|
* get the first non-virtual ip address on the given interface.
|
||||||
* if a candidate address is given, we first search for that address and if not
|
* if a candidate address is given, we first search for that address and if not
|
||||||
@@ -681,6 +788,8 @@ static void process_link(private_kernel_netlink_net_t *this,
|
|||||||
DBG1(DBG_KNL, "interface %s deleted", current->ifname);
|
DBG1(DBG_KNL, "interface %s deleted", current->ifname);
|
||||||
}
|
}
|
||||||
this->ifaces->remove_at(this->ifaces, enumerator);
|
this->ifaces->remove_at(this->ifaces, enumerator);
|
||||||
|
current->addrs->invoke_function(current->addrs,
|
||||||
|
(void*)addr_map_entry_remove, current, this);
|
||||||
iface_entry_destroy(current);
|
iface_entry_destroy(current);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -774,6 +883,7 @@ static void process_addr(private_kernel_netlink_net_t *this,
|
|||||||
DBG1(DBG_KNL, "%H disappeared from %s",
|
DBG1(DBG_KNL, "%H disappeared from %s",
|
||||||
host, iface->ifname);
|
host, iface->ifname);
|
||||||
}
|
}
|
||||||
|
addr_map_entry_remove(addr, iface, this);
|
||||||
addr_entry_destroy(addr);
|
addr_entry_destroy(addr);
|
||||||
}
|
}
|
||||||
else if (hdr->nlmsg_type == RTM_NEWADDR && addr->virtual)
|
else if (hdr->nlmsg_type == RTM_NEWADDR && addr->virtual)
|
||||||
@@ -798,6 +908,7 @@ static void process_addr(private_kernel_netlink_net_t *this,
|
|||||||
addr->scope = msg->ifa_scope;
|
addr->scope = msg->ifa_scope;
|
||||||
|
|
||||||
iface->addrs->insert_last(iface->addrs, addr);
|
iface->addrs->insert_last(iface->addrs, addr);
|
||||||
|
addr_map_entry_add(this, addr, iface);
|
||||||
if (event && iface->usable)
|
if (event && iface->usable)
|
||||||
{
|
{
|
||||||
DBG1(DBG_KNL, "%H appeared on %s", host, iface->ifname);
|
DBG1(DBG_KNL, "%H appeared on %s", host, iface->ifname);
|
||||||
@@ -1059,59 +1170,37 @@ METHOD(kernel_net_t, create_address_enumerator, enumerator_t*,
|
|||||||
METHOD(kernel_net_t, get_interface_name, bool,
|
METHOD(kernel_net_t, get_interface_name, bool,
|
||||||
private_kernel_netlink_net_t *this, host_t* ip, char **name)
|
private_kernel_netlink_net_t *this, host_t* ip, char **name)
|
||||||
{
|
{
|
||||||
enumerator_t *ifaces, *addrs;
|
addr_map_entry_t *entry, lookup = {
|
||||||
iface_entry_t *iface;
|
.ip = ip,
|
||||||
addr_entry_t *addr;
|
};
|
||||||
bool found = FALSE, ignored = FALSE;
|
|
||||||
|
|
||||||
if (ip->is_anyaddr(ip))
|
if (ip->is_anyaddr(ip))
|
||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->mutex->lock(this->mutex);
|
this->mutex->lock(this->mutex);
|
||||||
ifaces = this->ifaces->create_enumerator(this->ifaces);
|
/* first try to find it on an up and usable interface */
|
||||||
while (ifaces->enumerate(ifaces, &iface))
|
entry = this->addrs->get_match(this->addrs, &lookup,
|
||||||
|
(void*)addr_map_entry_match_up_and_usable);
|
||||||
|
if (entry)
|
||||||
{
|
{
|
||||||
addrs = iface->addrs->create_enumerator(iface->addrs);
|
if (name)
|
||||||
while (addrs->enumerate(addrs, &addr))
|
|
||||||
{
|
|
||||||
if (ip->ip_equals(ip, addr->ip))
|
|
||||||
{
|
|
||||||
found = TRUE;
|
|
||||||
if (!iface->usable)
|
|
||||||
{
|
|
||||||
ignored = TRUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (name)
|
|
||||||
{
|
|
||||||
*name = strdup(iface->ifname);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
addrs->destroy(addrs);
|
|
||||||
if (found)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ifaces->destroy(ifaces);
|
|
||||||
this->mutex->unlock(this->mutex);
|
|
||||||
|
|
||||||
if (!ignored)
|
|
||||||
{
|
|
||||||
if (!found)
|
|
||||||
{
|
|
||||||
DBG2(DBG_KNL, "%H is not a local address", ip);
|
|
||||||
}
|
|
||||||
else if (name)
|
|
||||||
{
|
{
|
||||||
|
*name = strdup(entry->iface->ifname);
|
||||||
DBG2(DBG_KNL, "%H is on interface %s", ip, *name);
|
DBG2(DBG_KNL, "%H is on interface %s", ip, *name);
|
||||||
}
|
}
|
||||||
|
this->mutex->unlock(this->mutex);
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
return found && !ignored;
|
/* maybe it is installed on an ignored interface */
|
||||||
|
entry = this->addrs->get_match(this->addrs, &lookup,
|
||||||
|
(void*)addr_map_entry_match_up);
|
||||||
|
if (!entry)
|
||||||
|
{
|
||||||
|
DBG2(DBG_KNL, "%H is not a local address or the interface is down", ip);
|
||||||
|
}
|
||||||
|
this->mutex->unlock(this->mutex);
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1955,6 +2044,7 @@ METHOD(kernel_net_t, destroy, void,
|
|||||||
{
|
{
|
||||||
enumerator_t *enumerator;
|
enumerator_t *enumerator;
|
||||||
route_entry_t *route;
|
route_entry_t *route;
|
||||||
|
addr_map_entry_t *addr;
|
||||||
|
|
||||||
if (this->routing_table)
|
if (this->routing_table)
|
||||||
{
|
{
|
||||||
@@ -1982,6 +2072,14 @@ METHOD(kernel_net_t, destroy, void,
|
|||||||
this->net_changes->destroy(this->net_changes);
|
this->net_changes->destroy(this->net_changes);
|
||||||
this->net_changes_lock->destroy(this->net_changes_lock);
|
this->net_changes_lock->destroy(this->net_changes_lock);
|
||||||
|
|
||||||
|
enumerator = this->addrs->create_enumerator(this->addrs);
|
||||||
|
while (enumerator->enumerate(enumerator, NULL, (void**)&addr))
|
||||||
|
{
|
||||||
|
free(addr);
|
||||||
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
this->addrs->destroy(this->addrs);
|
||||||
|
|
||||||
this->ifaces->destroy_function(this->ifaces, (void*)iface_entry_destroy);
|
this->ifaces->destroy_function(this->ifaces, (void*)iface_entry_destroy);
|
||||||
this->rt_exclude->destroy(this->rt_exclude);
|
this->rt_exclude->destroy(this->rt_exclude);
|
||||||
this->condvar->destroy(this->condvar);
|
this->condvar->destroy(this->condvar);
|
||||||
@@ -2020,6 +2118,9 @@ kernel_netlink_net_t *kernel_netlink_net_create()
|
|||||||
.net_changes = hashtable_create(
|
.net_changes = hashtable_create(
|
||||||
(hashtable_hash_t)net_change_hash,
|
(hashtable_hash_t)net_change_hash,
|
||||||
(hashtable_equals_t)net_change_equals, 16),
|
(hashtable_equals_t)net_change_equals, 16),
|
||||||
|
.addrs = hashtable_create(
|
||||||
|
(hashtable_hash_t)addr_map_entry_hash,
|
||||||
|
(hashtable_equals_t)addr_map_entry_equals, 16),
|
||||||
.net_changes_lock = mutex_create(MUTEX_TYPE_DEFAULT),
|
.net_changes_lock = mutex_create(MUTEX_TYPE_DEFAULT),
|
||||||
.ifaces = linked_list_create(),
|
.ifaces = linked_list_create(),
|
||||||
.mutex = mutex_create(MUTEX_TYPE_RECURSIVE),
|
.mutex = mutex_create(MUTEX_TYPE_RECURSIVE),
|
||||||
|
|||||||
@@ -99,14 +99,73 @@ static void iface_entry_destroy(iface_entry_t *this)
|
|||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* check if an interface is up
|
||||||
|
*/
|
||||||
|
static inline bool iface_entry_up(iface_entry_t *iface)
|
||||||
|
{
|
||||||
|
return (iface->flags & IFF_UP) == IFF_UP;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* check if an interface is up and usable
|
* check if an interface is up and usable
|
||||||
*/
|
*/
|
||||||
static inline bool iface_entry_up_and_usable(iface_entry_t *iface)
|
static inline bool iface_entry_up_and_usable(iface_entry_t *iface)
|
||||||
{
|
{
|
||||||
return iface->usable && (iface->flags & IFF_UP) == IFF_UP;
|
return iface->usable && iface_entry_up(iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct addr_map_entry_t addr_map_entry_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entry that maps an IP address to an interface entry
|
||||||
|
*/
|
||||||
|
struct addr_map_entry_t {
|
||||||
|
/** The IP address */
|
||||||
|
host_t *ip;
|
||||||
|
|
||||||
|
/** The interface this address is installed on */
|
||||||
|
iface_entry_t *iface;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hash a addr_map_entry_t object, all entries with the same IP address
|
||||||
|
* are stored in the same bucket
|
||||||
|
*/
|
||||||
|
static u_int addr_map_entry_hash(addr_map_entry_t *this)
|
||||||
|
{
|
||||||
|
return chunk_hash(this->ip->get_address(this->ip));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compare two addr_map_entry_t objects, two entries are equal if they are
|
||||||
|
* installed on the same interface
|
||||||
|
*/
|
||||||
|
static bool addr_map_entry_equals(addr_map_entry_t *a, addr_map_entry_t *b)
|
||||||
|
{
|
||||||
|
return a->iface->ifindex == b->iface->ifindex &&
|
||||||
|
a->ip->ip_equals(a->ip, b->ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used with get_match this finds an address entry if it is installed on
|
||||||
|
* an up and usable interface
|
||||||
|
*/
|
||||||
|
static bool addr_map_entry_match_up_and_usable(addr_map_entry_t *a,
|
||||||
|
addr_map_entry_t *b)
|
||||||
|
{
|
||||||
|
return iface_entry_up_and_usable(b->iface) &&
|
||||||
|
a->ip->ip_equals(a->ip, b->ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used with get_match this finds an address entry if it is installed on
|
||||||
|
* any active local interface
|
||||||
|
*/
|
||||||
|
static bool addr_map_entry_match_up(addr_map_entry_t *a, addr_map_entry_t *b)
|
||||||
|
{
|
||||||
|
return iface_entry_up(b->iface) && a->ip->ip_equals(a->ip, b->ip);
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct private_kernel_pfroute_net_t private_kernel_pfroute_net_t;
|
typedef struct private_kernel_pfroute_net_t private_kernel_pfroute_net_t;
|
||||||
|
|
||||||
@@ -130,6 +189,11 @@ struct private_kernel_pfroute_net_t
|
|||||||
*/
|
*/
|
||||||
linked_list_t *ifaces;
|
linked_list_t *ifaces;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map for IP addresses to iface_entry_t objects (addr_map_entry_t)
|
||||||
|
*/
|
||||||
|
hashtable_t *addrs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* mutex to lock access to the PF_ROUTE socket
|
* mutex to lock access to the PF_ROUTE socket
|
||||||
*/
|
*/
|
||||||
@@ -156,6 +220,48 @@ struct private_kernel_pfroute_net_t
|
|||||||
timeval_t last_roam;
|
timeval_t last_roam;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an address map entry
|
||||||
|
*/
|
||||||
|
static void addr_map_entry_add(private_kernel_netlink_net_t *this,
|
||||||
|
addr_entry_t *addr, iface_entry_t *iface)
|
||||||
|
{
|
||||||
|
addr_map_entry_t *entry;
|
||||||
|
|
||||||
|
if (addr->virtual)
|
||||||
|
{ /* don't map virtual IPs */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
INIT(entry,
|
||||||
|
.ip = addr->ip,
|
||||||
|
.iface = iface,
|
||||||
|
);
|
||||||
|
entry = this->addrs->put(this->addrs, entry, entry);
|
||||||
|
free(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove an address map entry (the argument order is a bit strange because
|
||||||
|
* it is also used with linked_list_t.invoke_function)
|
||||||
|
*/
|
||||||
|
static void addr_map_entry_remove(addr_entry_t *addr, iface_entry_t *iface,
|
||||||
|
private_kernel_netlink_net_t *this)
|
||||||
|
{
|
||||||
|
addr_map_entry_t *entry, lookup = {
|
||||||
|
.ip = addr->ip,
|
||||||
|
.iface = iface,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (addr->virtual)
|
||||||
|
{ /* these are never mapped, but this check avoid problems if a virtual IP
|
||||||
|
* equals a regular one */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
entry = this->addrs->remove(this->addrs, &lookup);
|
||||||
|
free(entry);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* callback function that raises the delayed roam event
|
* callback function that raises the delayed roam event
|
||||||
*/
|
*/
|
||||||
@@ -246,6 +352,7 @@ static void process_addr(private_kernel_pfroute_net_t *this,
|
|||||||
DBG1(DBG_KNL, "%H disappeared from %s",
|
DBG1(DBG_KNL, "%H disappeared from %s",
|
||||||
host, iface->ifname);
|
host, iface->ifname);
|
||||||
}
|
}
|
||||||
|
addr_map_entry_remove(addr, iface, this);
|
||||||
addr_entry_destroy(addr);
|
addr_entry_destroy(addr);
|
||||||
}
|
}
|
||||||
else if (ifa->ifam_type == RTM_NEWADDR && addr->virtual)
|
else if (ifa->ifam_type == RTM_NEWADDR && addr->virtual)
|
||||||
@@ -264,6 +371,7 @@ static void process_addr(private_kernel_pfroute_net_t *this,
|
|||||||
addr->virtual = FALSE;
|
addr->virtual = FALSE;
|
||||||
addr->refcount = 1;
|
addr->refcount = 1;
|
||||||
iface->addrs->insert_last(iface->addrs, addr);
|
iface->addrs->insert_last(iface->addrs, addr);
|
||||||
|
addr_map_entry_add(this, addr, iface);
|
||||||
if (iface->usable)
|
if (iface->usable)
|
||||||
{
|
{
|
||||||
DBG1(DBG_KNL, "%H appeared on %s", host, iface->ifname);
|
DBG1(DBG_KNL, "%H appeared on %s", host, iface->ifname);
|
||||||
@@ -496,59 +604,37 @@ METHOD(kernel_net_t, create_address_enumerator, enumerator_t*,
|
|||||||
METHOD(kernel_net_t, get_interface_name, bool,
|
METHOD(kernel_net_t, get_interface_name, bool,
|
||||||
private_kernel_pfroute_net_t *this, host_t* ip, char **name)
|
private_kernel_pfroute_net_t *this, host_t* ip, char **name)
|
||||||
{
|
{
|
||||||
enumerator_t *ifaces, *addrs;
|
addr_map_entry_t *entry, lookup = {
|
||||||
iface_entry_t *iface;
|
.ip = ip,
|
||||||
addr_entry_t *addr;
|
};
|
||||||
bool found = FALSE, ignored = FALSE;
|
|
||||||
|
|
||||||
if (ip->is_anyaddr(ip))
|
if (ip->is_anyaddr(ip))
|
||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->mutex->lock(this->mutex);
|
this->mutex->lock(this->mutex);
|
||||||
ifaces = this->ifaces->create_enumerator(this->ifaces);
|
/* first try to find it on an up and usable interface */
|
||||||
while (ifaces->enumerate(ifaces, &iface))
|
entry = this->addrs->get_match(this->addrs, &lookup,
|
||||||
|
(void*)addr_map_entry_match_up_and_usable);
|
||||||
|
if (entry)
|
||||||
{
|
{
|
||||||
addrs = iface->addrs->create_enumerator(iface->addrs);
|
if (name)
|
||||||
while (addrs->enumerate(addrs, &addr))
|
|
||||||
{
|
|
||||||
if (ip->ip_equals(ip, addr->ip))
|
|
||||||
{
|
|
||||||
found = TRUE;
|
|
||||||
if (!iface->usable)
|
|
||||||
{
|
|
||||||
ignored = TRUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (name)
|
|
||||||
{
|
|
||||||
*name = strdup(iface->ifname);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
addrs->destroy(addrs);
|
|
||||||
if (found)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ifaces->destroy(ifaces);
|
|
||||||
this->mutex->unlock(this->mutex);
|
|
||||||
|
|
||||||
if (!ignored)
|
|
||||||
{
|
|
||||||
if (!found)
|
|
||||||
{
|
|
||||||
DBG2(DBG_KNL, "%H is not a local address", ip);
|
|
||||||
}
|
|
||||||
else if (name)
|
|
||||||
{
|
{
|
||||||
|
*name = strdup(entry->iface->ifname);
|
||||||
DBG2(DBG_KNL, "%H is on interface %s", ip, *name);
|
DBG2(DBG_KNL, "%H is on interface %s", ip, *name);
|
||||||
}
|
}
|
||||||
|
this->mutex->unlock(this->mutex);
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
return found && !ignored;
|
/* maybe it is installed on an ignored interface */
|
||||||
|
entry = this->addrs->get_match(this->addrs, &lookup,
|
||||||
|
(void*)addr_map_entry_match_up);
|
||||||
|
if (!entry)
|
||||||
|
{ /* the address does not exist, is on a down interface */
|
||||||
|
DBG2(DBG_KNL, "%H is not a local address or the interface is down", ip);
|
||||||
|
}
|
||||||
|
this->mutex->unlock(this->mutex);
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(kernel_net_t, get_source_addr, host_t*,
|
METHOD(kernel_net_t, get_source_addr, host_t*,
|
||||||
@@ -678,6 +764,8 @@ static status_t init_address_list(private_kernel_pfroute_net_t *this)
|
|||||||
METHOD(kernel_net_t, destroy, void,
|
METHOD(kernel_net_t, destroy, void,
|
||||||
private_kernel_pfroute_net_t *this)
|
private_kernel_pfroute_net_t *this)
|
||||||
{
|
{
|
||||||
|
enumerator_t *enumerator;
|
||||||
|
|
||||||
if (this->socket > 0)
|
if (this->socket > 0)
|
||||||
{
|
{
|
||||||
close(this->socket);
|
close(this->socket);
|
||||||
@@ -686,6 +774,13 @@ METHOD(kernel_net_t, destroy, void,
|
|||||||
{
|
{
|
||||||
close(this->socket_events);
|
close(this->socket_events);
|
||||||
}
|
}
|
||||||
|
enumerator = this->addrs->create_enumerator(this->addrs);
|
||||||
|
while (enumerator->enumerate(enumerator, NULL, (void**)&addr))
|
||||||
|
{
|
||||||
|
free(addr);
|
||||||
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
this->addrs->destroy(this->addrs);
|
||||||
this->ifaces->destroy_function(this->ifaces, (void*)iface_entry_destroy);
|
this->ifaces->destroy_function(this->ifaces, (void*)iface_entry_destroy);
|
||||||
this->mutex->destroy(this->mutex);
|
this->mutex->destroy(this->mutex);
|
||||||
this->mutex_pfroute->destroy(this->mutex_pfroute);
|
this->mutex_pfroute->destroy(this->mutex_pfroute);
|
||||||
@@ -715,6 +810,9 @@ kernel_pfroute_net_t *kernel_pfroute_net_create()
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
.ifaces = linked_list_create(),
|
.ifaces = linked_list_create(),
|
||||||
|
.addrs = hashtable_create(
|
||||||
|
(hashtable_hash_t)addr_map_entry_hash,
|
||||||
|
(hashtable_equals_t)addr_map_entry_equals, 16),
|
||||||
.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
|
.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
|
||||||
.mutex_pfroute = mutex_create(MUTEX_TYPE_DEFAULT),
|
.mutex_pfroute = mutex_create(MUTEX_TYPE_DEFAULT),
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user