diff options
Diffstat (limited to 'Source/charon/network')
-rw-r--r-- | Source/charon/network/host.c | 27 | ||||
-rw-r--r-- | Source/charon/network/host.h | 11 | ||||
-rw-r--r-- | Source/charon/network/socket.c | 44 | ||||
-rw-r--r-- | Source/charon/network/socket.h | 9 |
4 files changed, 83 insertions, 8 deletions
diff --git a/Source/charon/network/host.c b/Source/charon/network/host.c index 7d120886e..245df8b05 100644 --- a/Source/charon/network/host.c +++ b/Source/charon/network/host.c @@ -208,11 +208,30 @@ static private_host_t *clone(private_host_t *this) return new; } +/** + * Impelements host_t.ip_equals + */ +static bool ip_equals(private_host_t *this, private_host_t *other) +{ + switch (this->family) + { + /* IPv4 */ + case AF_INET: + { + if ((this->address4.sin_family == other->address4.sin_family) && + (this->address4.sin_addr.s_addr == other->address4.sin_addr.s_addr)) + { + return TRUE; + } + } + } + return FALSE; +} /** * Impelements host_t.equals */ -static bool ip_is_equal(private_host_t *this, private_host_t *other) +static bool equals(private_host_t *this, private_host_t *other) { switch (this->family) { @@ -220,7 +239,8 @@ static bool ip_is_equal(private_host_t *this, private_host_t *other) case AF_INET: { if ((this->address4.sin_family == other->address4.sin_family) && - (this->address4.sin_addr.s_addr == other->address4.sin_addr.s_addr)) + (this->address4.sin_addr.s_addr == other->address4.sin_addr.s_addr) && + (this->address4.sin_port == other->address4.sin_port)) { return TRUE; } @@ -253,7 +273,8 @@ static private_host_t *host_create_empty() this->public.get_address = (char* (*) (host_t *))get_address; this->public.get_address_as_chunk = (chunk_t (*) (host_t *)) get_address_as_chunk; this->public.get_port = (u_int16_t (*) (host_t *))get_port; - this->public.ip_is_equal = (bool (*) (host_t *,host_t *)) ip_is_equal; + this->public.ip_equals = (bool (*) (host_t *,host_t *)) ip_equals; + this->public.equals = (bool (*) (host_t *,host_t *)) equals; this->public.is_default_route = (bool (*) (host_t *)) is_default_route; this->public.destroy = (void (*) (host_t*))destroy; diff --git a/Source/charon/network/host.h b/Source/charon/network/host.h index c5293bcdf..d81efffa6 100644 --- a/Source/charon/network/host.h +++ b/Source/charon/network/host.h @@ -155,7 +155,16 @@ struct host_t { * @param other the other to compare * @return TRUE if addresses are equal. */ - bool (*ip_is_equal) (host_t *this, host_t *other); + bool (*ip_equals) (host_t *this, host_t *other); + + /** + * @brief Compare two hosts, with port. + * + * @param this object to compare + * @param other the other to compare + * @return TRUE if addresses and ports are equal. + */ + bool (*equals) (host_t *this, host_t *other); /** * @brief Destroy this host object diff --git a/Source/charon/network/socket.c b/Source/charon/network/socket.c index 0b6610972..c7a7ab11b 100644 --- a/Source/charon/network/socket.c +++ b/Source/charon/network/socket.c @@ -97,6 +97,11 @@ struct interface_t { * Associated socket */ int socket_fd; + + /** + * Host with listening address + */ + host_t *address; }; typedef struct private_socket_t private_socket_t; @@ -366,8 +371,9 @@ static status_t build_interface_list(private_socket_t *this, u_int16_t port) memcpy(interface->name, buf[i].ifr_name, IFNAMSIZ); interface->name[IFNAMSIZ-1] = '\0'; interface->socket_fd = skt; + interface->address = host_create_from_sockaddr((struct sockaddr*)current); this->logger->log(this->logger, CONTROL, "listening on %s (%s)", - interface->name, inet_ntoa(current->sin_addr)); + interface->name, interface->address->get_address(interface->address)); this->interfaces->insert_last(this->interfaces, (void*)interface); } @@ -380,18 +386,47 @@ static status_t build_interface_list(private_socket_t *this, u_int16_t port) } /** + * implementation of socket_t.is_listening_on + */ +static bool is_listening_on(private_socket_t *this, host_t *host) +{ + iterator_t *iterator; + + /* listening on 0.0.0.0 is always TRUE */ + if (host->is_default_route(host)) + { + return TRUE; + } + + /* compare host with all interfaces */ + iterator = this->interfaces->create_iterator(this->interfaces, TRUE); + while (iterator->has_next(iterator)) + { + interface_t *interface; + iterator->current(iterator, (void**)&interface); + if (host->equals(host, interface->address)) + { + iterator->destroy(iterator); + return TRUE; + } + } + iterator->destroy(iterator); + return FALSE; +} + +/** * implementation of socket_t.destroy */ -void destroy(private_socket_t *this) +static void destroy(private_socket_t *this) { interface_t *interface; while (this->interfaces->remove_last(this->interfaces, (void**)&interface) == SUCCESS) { + interface->address->destroy(interface->address); close(interface->socket_fd); allocator_free(interface); } this->interfaces->destroy(this->interfaces); - charon->logger_manager->destroy_logger(charon->logger_manager, this->logger); close(this->master_fd); allocator_free(this); } @@ -406,9 +441,10 @@ socket_t *socket_create(u_int16_t port) /* public functions */ this->public.send = (status_t(*)(socket_t*, packet_t*))sender; this->public.receive = (status_t(*)(socket_t*, packet_t**))receiver; + this->public.is_listening_on = (bool (*)(socket_t*,host_t*))is_listening_on; this->public.destroy = (void(*)(socket_t*)) destroy; - this->logger = charon->logger_manager->create_logger(charon->logger_manager, SOCKET, NULL); + this->logger = charon->logger_manager->get_logger(charon->logger_manager, SOCKET); this->interfaces = linked_list_create(); if (build_interface_list(this, port) != SUCCESS) diff --git a/Source/charon/network/socket.h b/Source/charon/network/socket.h index 7e43ffab5..498e7700a 100644 --- a/Source/charon/network/socket.h +++ b/Source/charon/network/socket.h @@ -93,6 +93,15 @@ struct socket_t { status_t (*send) (socket_t *sock, packet_t *packet); /** + * @brief Check if socket listens on an address. + * + * @param sock socket_t object to work on + * @param host address to check + * @return TRUE if listening on host, FALSE otherwise + */ + bool (*is_listening_on) (socket_t *sock, host_t *host); + + /** * @brief Destroy sockets. * * close sockets and destroy socket_t object |