diff options
Diffstat (limited to 'src/charon/kernel/kernel_interface.c')
-rw-r--r-- | src/charon/kernel/kernel_interface.c | 32 |
1 files changed, 24 insertions, 8 deletions
diff --git a/src/charon/kernel/kernel_interface.c b/src/charon/kernel/kernel_interface.c index 9847f30a3..bf5479bfe 100644 --- a/src/charon/kernel/kernel_interface.c +++ b/src/charon/kernel/kernel_interface.c @@ -228,6 +228,9 @@ struct addr_entry_t { /** The ip address */ host_t *ip; + /** virtual IP managed by us */ + bool virtual; + /** Number of times this IP is used, if virtual */ u_int refcount; }; @@ -690,6 +693,7 @@ static void process_addr(private_kernel_interface_t *this, found = TRUE; addr = malloc_thing(addr_entry_t); addr->ip = host->clone(host); + addr->virtual = FALSE; addr->refcount = 1; iface->addrs->insert_last(iface->addrs, addr); @@ -1070,6 +1074,10 @@ static status_t init_address_list(private_kernel_interface_t *this) static hook_result_t addr_hook(private_kernel_interface_t *this, addr_entry_t *in, host_t **out) { + if (in->virtual) + { /* skip virtual interfaces added by us */ + return HOOK_SKIP; + } *out = in->ip; return HOOK_NEXT; } @@ -1107,6 +1115,11 @@ static iterator_t *create_address_iterator(private_kernel_interface_t *this) { iterator_t *iterator; + /* This iterator is not only hooked, is is double-hooked. As we have stored + * our addresses in iface_entry->addr_entry->ip, we need to iterate the + * entries in each interface we iterate. This does the iface_hook. The + * addr_hook returns the ip instead of the addr_entry. */ + iterator = this->ifaces->create_iterator_locked(this->ifaces, &this->mutex); iterator->set_iterator_hook(iterator, (iterator_hook_t*)iface_hook, this); return iterator; @@ -1368,6 +1381,8 @@ static host_t* get_source_addr(private_kernel_interface_t *this, host_t *dest) size_t len; host_t *source = NULL; + DBG2(DBG_KNL, "getting source address to reach %H", dest); + memset(&request, 0, sizeof(request)); hdr = (struct nlmsghdr*)request; @@ -1378,10 +1393,10 @@ static host_t* get_source_addr(private_kernel_interface_t *this, host_t *dest) msg = (struct rtmsg*)NLMSG_DATA(hdr); msg->rtm_family = dest->get_family(dest); msg->rtm_dst_len = msg->rtm_family == AF_INET ? 32 : 128; - msg->rtm_table = RT_TABLE_MAIN; - msg->rtm_protocol = RTPROT_STATIC; + msg->rtm_table = RT_TABLE_UNSPEC; + msg->rtm_protocol = RTPROT_UNSPEC; msg->rtm_type = RTN_UNICAST; - msg->rtm_scope = RT_SCOPE_UNIVERSE; + msg->rtm_scope = RT_SCOPE_HOST; chunk = dest->get_address(dest); add_attribute(hdr, RTA_DST, chunk, sizeof(request)); @@ -1427,12 +1442,13 @@ static host_t* get_source_addr(private_kernel_interface_t *this, host_t *dest) } break; } - if (source == NULL) + free(out); + if (source) { - DBG2(DBG_KNL, "no route found to %H", dest); + return source; } - free(out); - return source; + DBG2(DBG_KNL, "no route found to %H", dest); + return NULL; } /** @@ -1481,6 +1497,7 @@ static status_t add_ip(private_kernel_interface_t *this, addr = malloc_thing(addr_entry_t); addr->ip = virtual_ip->clone(virtual_ip); addr->refcount = 1; + addr->virtual = TRUE; pthread_mutex_lock(&this->mutex); iface->addrs->insert_last(iface->addrs, addr); pthread_mutex_unlock(&this->mutex); @@ -2298,7 +2315,6 @@ kernel_interface_t *kernel_interface_create() private_kernel_interface_t *this = malloc_thing(private_kernel_interface_t); struct sockaddr_nl addr; - /* public functions */ this->public.get_spi = (status_t(*)(kernel_interface_t*,host_t*,host_t*,protocol_id_t,u_int32_t,u_int32_t*))get_spi; this->public.add_sa = (status_t(*)(kernel_interface_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,u_int64_t,u_int64_t,algorithm_t*,algorithm_t*,prf_plus_t*,natt_conf_t*,mode_t,bool))add_sa; |