diff --git a/src/charon/Makefile.am b/src/charon/Makefile.am index d7454f60f..024205ac0 100644 --- a/src/charon/Makefile.am +++ b/src/charon/Makefile.am @@ -38,7 +38,7 @@ encoding/payloads/sa_payload.h encoding/payloads/vendor_id_payload.c encoding/pa encoding/payloads/vendor_id_payload.h encoding/payloads/proposal_substructure.c encoding/payloads/payload.c \ encoding/parser.h encoding/message.c encoding/generator.c encoding/message.h encoding/generator.h \ encoding/parser.c daemon.c daemon.h network/packet.c \ -network/interfaces.c network/interfaces.h network/socket.c network/packet.h network/socket.h queues/jobs/job.h queues/jobs/job.c \ +network/socket.c network/packet.h network/socket.h queues/jobs/job.h queues/jobs/job.c \ queues/jobs/delete_established_ike_sa_job.c queues/jobs/retransmit_request_job.h queues/jobs/initiate_job.h \ queues/jobs/incoming_packet_job.c queues/jobs/delete_half_open_ike_sa_job.c \ queues/jobs/delete_established_ike_sa_job.h queues/jobs/delete_half_open_ike_sa_job.h \ diff --git a/src/charon/daemon.c b/src/charon/daemon.c index a368ee428..a5ac5c63e 100644 --- a/src/charon/daemon.c +++ b/src/charon/daemon.c @@ -178,7 +178,6 @@ static void initialize(private_daemon_t *this, bool strict) this->public.configuration = configuration_create(); this->public.socket = socket_create(IKEV2_UDP_PORT, IKEV2_NATT_PORT); - this->public.interfaces = interfaces_create(IKEV2_UDP_PORT); this->public.ike_sa_manager = ike_sa_manager_create(); this->public.job_queue = job_queue_create(); this->public.event_queue = event_queue_create(); @@ -210,75 +209,32 @@ static void destroy(private_daemon_t *this) /* destruction is a non trivial task, we need to follow * a strict order to prevent threading issues! * Kill active threads first, except the sender, as - * the killed IKE_SA want to send delete messages. + * the killed IKE_SA want to send delete messages. */ - if (this->public.receiver != NULL) - { /* we don't want to receive anything... */ - this->public.receiver->destroy(this->public.receiver); - } - if (this->public.stroke != NULL) - { /* ignore all incoming user requests */ - this->public.stroke->destroy(this->public.stroke); - } - if (this->public.scheduler != NULL) - { /* stop scheduing jobs */ - this->public.scheduler->destroy(this->public.scheduler); - } - if (this->public.thread_pool != NULL) - { /* stop processing jobs */ - this->public.thread_pool->destroy(this->public.thread_pool); - } - if (this->public.ike_sa_manager != NULL) - { /* shut down manager with all IKE SAs */ - this->public.ike_sa_manager->destroy(this->public.ike_sa_manager); - } - if (this->public.kernel_interface != NULL) - { /* all child SAs should be down now, so kill kernel interface */ - this->public.kernel_interface->destroy(this->public.kernel_interface); - } + /* we don't want to receive anything anymore... */ + DESTROY_IF(this->public.receiver); + /* ignore all incoming user requests */ + DESTROY_IF(this->public.stroke); + /* stop scheduing jobs */ + DESTROY_IF(this->public.scheduler); + /* stop processing jobs */ + DESTROY_IF(this->public.thread_pool); + /* shut down manager with all IKE SAs */ + DESTROY_IF(this->public.ike_sa_manager); + /* all child SAs should be down now, so kill kernel interface */ + DESTROY_IF(this->public.kernel_interface); /* destroy other infrastructure */ - if (this->public.job_queue != NULL) - { - this->public.job_queue->destroy(this->public.job_queue); - } - if (this->public.event_queue != NULL) - { - this->public.event_queue->destroy(this->public.event_queue); - } - if (this->public.interfaces != NULL) - { - this->public.interfaces->destroy(this->public.interfaces); - } - if (this->public.configuration != NULL) - { - this->public.configuration->destroy(this->public.configuration); - } - if (this->public.credentials != NULL) - { - this->public.credentials->destroy(this->public.credentials); - } - if (this->public.connections != NULL) - { - this->public.connections->destroy(this->public.connections); - } - if (this->public.policies != NULL) - { - this->public.policies->destroy(this->public.policies); - } + DESTROY_IF(this->public.job_queue); + DESTROY_IF(this->public.event_queue); + DESTROY_IF(this->public.configuration); + DESTROY_IF(this->public.credentials); + DESTROY_IF(this->public.connections); + DESTROY_IF(this->public.policies); /* we hope the sender could send the outstanding deletes, but * we shut down here at any cost */ - if (this->public.sender != NULL) - { - this->public.sender->destroy(this->public.sender); - } - if (this->public.send_queue != NULL) - { - this->public.send_queue->destroy(this->public.send_queue); - } - if (this->public.socket != NULL) - { - this->public.socket->destroy(this->public.socket); - } + DESTROY_IF(this->public.sender); + DESTROY_IF(this->public.send_queue); + DESTROY_IF(this->public.socket); free(this); } @@ -323,7 +279,6 @@ private_daemon_t *daemon_create(void) /* NULL members for clean destruction */ this->public.socket = NULL; - this->public.interfaces = NULL; this->public.ike_sa_manager = NULL; this->public.job_queue = NULL; this->public.event_queue = NULL; @@ -385,6 +340,8 @@ int main(int argc, char *argv[]) private_daemon_t *private_charon; FILE *pid_file; struct stat stb; + linked_list_t *list; + host_t *host; /* handle arguments */ for (;;) @@ -449,6 +406,20 @@ int main(int argc, char *argv[]) fclose(pid_file); } + /* log socket info */ + list = charon->socket->create_local_address_list(charon->socket); + private_charon->logger->log(private_charon->logger, CONTROL, + "listening on %d addresses:", + list->get_count(list)); + while (list->remove_first(list, (void**)&host) == SUCCESS) + { + private_charon->logger->log(private_charon->logger, CONTROL, + " %s", host->get_string(host)); + host->destroy(host); + + } + list->destroy(list); + /* run daemon */ private_charon->run(private_charon); diff --git a/src/charon/daemon.h b/src/charon/daemon.h index 4c2423a03..b3ba35fb8 100644 --- a/src/charon/daemon.h +++ b/src/charon/daemon.h @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -277,11 +276,6 @@ struct daemon_t { */ socket_t *socket; - /** - * A interfaces_t instance. - */ - interfaces_t *interfaces; - /** * A send_queue_t instance. */ diff --git a/src/charon/debug b/src/charon/debug new file mode 100755 index 000000000..0a246bad0 --- /dev/null +++ b/src/charon/debug @@ -0,0 +1,6 @@ +#!/bin/bash +make install || exit +ipsec start --nofork & +sleep 1 +gdb /usr/local/libexec/ipsec/charon `cat /var/run/charon.pid` +ipsec stop diff --git a/src/charon/encoding/payloads/proposal_substructure.c b/src/charon/encoding/payloads/proposal_substructure.c index 540e44587..4d2eae0bc 100644 --- a/src/charon/encoding/payloads/proposal_substructure.c +++ b/src/charon/encoding/payloads/proposal_substructure.c @@ -644,6 +644,8 @@ proposal_substructure_t *proposal_substructure_create_from_proposal(proposal_t * *((u_int64_t*)this->spi.ptr) = proposal->get_spi(proposal); } break; + default: + break; } this->proposal_number = 0; this->protocol_id = proposal->get_protocol(proposal); diff --git a/src/charon/network/interfaces.c b/src/charon/network/interfaces.c deleted file mode 100644 index b1244c97f..000000000 --- a/src/charon/network/interfaces.c +++ /dev/null @@ -1,154 +0,0 @@ -/** - * @file interfaces.c - * - * @brief Implementation of interfaces_t. - * - */ - -/* - * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include -#include -#include - -#include "interfaces.h" - -typedef struct private_interfaces_t private_interfaces_t; - -/** - * Private data of an interfaces_t object. - */ -struct private_interfaces_t { - - /** - * Public part of a interfaces_t object. - */ - interfaces_t public; - - /** - * port that gets added to the host_t obbjects - */ - u_int16_t port; - - /** - * list of addresses - */ - linked_list_t *addresses; -}; - -/** - * Implements interfaces_t.create_address_iterator - */ -static iterator_t* create_address_iterator(private_interfaces_t *this) -{ - return this->addresses->create_iterator(this->addresses, TRUE); -} - -/** - * Implements interfaces_t.is_local_address - */ -static bool is_local_address(private_interfaces_t *this, host_t *host) -{ - iterator_t *iterator; - host_t *lhost; - - if (host->is_anyaddr(host)) - { - return FALSE; - } - - iterator = this->addresses->create_iterator(this->addresses, TRUE); - while (iterator->iterate(iterator, (void**)&lhost)) - { - if (host->get_family(host) == lhost->get_family(lhost) && - streq(host->get_string(host), lhost->get_string(lhost))) - { - iterator->destroy(iterator); - return TRUE; - } - } - - iterator->destroy(iterator); - return FALSE; -} - -/** - * Implements interfaces_t.destroy. - */ -static void destroy(private_interfaces_t *this) -{ - host_t *host; - while (this->addresses->remove_last(this->addresses, (void**)&host) == SUCCESS) - { - host->destroy(host); - } - this->addresses->destroy(this->addresses); - free(this); -} - -static status_t initialize(private_interfaces_t *this) -{ - struct ifaddrs *list; - struct ifaddrs *cur; - host_t *host; - - if (getifaddrs(&list) < 0) - { - return FAILED; - } - - for (cur = list; cur != NULL; cur = cur->ifa_next) - { - if (!(cur->ifa_flags & IFF_UP)) - continue; - - if (cur->ifa_addr == NULL || cur->ifa_addr->sa_family != AF_INET) - continue; - - host = host_create_from_sockaddr(cur->ifa_addr); - if (host) { - host->set_port(host, this->port); - this->addresses->insert_last(this->addresses, (void*) host); - } - } - - freeifaddrs(list); - return SUCCESS; -} - -/* - * Documented in header - */ -interfaces_t *interfaces_create(u_int16_t port) -{ - private_interfaces_t *this = malloc_thing(private_interfaces_t); - - this->port = port; - - this->public.create_address_iterator = (iterator_t* (*) (interfaces_t*)) create_address_iterator; - this->public.is_local_address = (bool (*) (interfaces_t*, host_t*)) is_local_address; - this->public.destroy = (void (*) (interfaces_t*)) destroy; - - this->addresses = linked_list_create(); - - if (initialize(this) != SUCCESS) - { - destroy(this); - return NULL; - } - - return &this->public; -} diff --git a/src/charon/network/interfaces.h b/src/charon/network/interfaces.h deleted file mode 100644 index 33143e07c..000000000 --- a/src/charon/network/interfaces.h +++ /dev/null @@ -1,80 +0,0 @@ -/** - * @file interfaces.h - * - * @brief Interface of interfaces_t. - * - */ - -/* - * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef INTERFACES_H_ -#define INTERFACES_H_ - -#include -#include - -typedef struct interfaces_t interfaces_t; - -/** - * @brief Provides methods to enumerate local interfaces - * - * @b Constructors: - * - interfaces_create() - * - * @todo Handle changes in interface list. - * - * @ingroup network - */ -struct interfaces_t { - - /** - * @brief Get an iterator over addresses of local interfaces - * - * @param this calling object - * @return iterator over host_t objects - */ - iterator_t* (*create_address_iterator) (interfaces_t *this); - - /** - * @brief Check if address is associated with a local interface - * - * @param this calling object - * @param host address to set as destination - * @return TRUE if address is associated with a local interface, FALSE otherwise - */ - bool (*is_local_address) (interfaces_t *this, host_t *host); - - /** - * @brief Destroy the object, freeing contained data. - * - * @param this object to destroy - */ - void (*destroy) (interfaces_t *ifaces); -}; - -/** - * @brief Create an object of type interfaces_t - * - * @param port the port that gets added to the addresses - * - * @return interfaces_t object - * - * @ingroup network - */ -interfaces_t *interfaces_create(u_int16_t port); - - -#endif /* INTERFACES_H_ */ diff --git a/src/charon/network/socket.c b/src/charon/network/socket.c index c0c53ff54..aca48ec5e 100644 --- a/src/charon/network/socket.c +++ b/src/charon/network/socket.c @@ -36,6 +36,8 @@ #include #include #include +#include +#include #include "socket.h" @@ -106,22 +108,6 @@ struct private_socket_t{ * logger for this socket */ logger_t *logger; - - /** - * Setup a send socket - * - * @param this calling object - * @param port the port - * @param send_fd returns the file descriptor of this new socket - */ - status_t (*setup_send_socket) (private_socket_t *this, u_int16_t port, int *send_fd); - - /** - * Initialize - * - * @param this calling object - */ - status_t (*initialize) (private_socket_t *this); }; /** @@ -246,6 +232,108 @@ status_t sender(private_socket_t *this, packet_t *packet) return SUCCESS; } +/** + * implements socket_t.is_local_address + */ +static bool is_local_address(private_socket_t *this, host_t *host) +{ + struct ifaddrs *list; + struct ifaddrs *cur; + bool found = FALSE; + + if (getifaddrs(&list) < 0) + { + return FALSE; + } + + for (cur = list; cur != NULL; cur = cur->ifa_next) + { + if (!(cur->ifa_flags & IFF_UP)) + { + /* ignore interface which are down */ + continue; + } + + if (cur->ifa_addr == NULL || + cur->ifa_addr->sa_family != host->get_family(host)) + { + /* no match in family */ + continue; + } + + switch (cur->ifa_addr->sa_family) + { + case AF_INET: + { + struct sockaddr_in *listed, *requested; + listed = (struct sockaddr_in*)cur->ifa_addr; + requested = (struct sockaddr_in*)host->get_sockaddr(host); + if (listed->sin_addr.s_addr == requested->sin_addr.s_addr) + { + found = TRUE; + } + break; + } + case AF_INET6: + { + struct sockaddr_in6 *listed, *requested; + listed = (struct sockaddr_in6*)cur->ifa_addr; + requested = (struct sockaddr_in6*)host->get_sockaddr(host); + if (memcmp(&listed->sin6_addr, &requested->sin6_addr, + sizeof(listed->sin6_addr)) == 0) + { + found = TRUE; + } + break; + } + default: + break; + } + + if (found) + { + break; + } + } + freeifaddrs(list); + return found; +} + + +/** + * implements socket_t.create_local_address_list + */ +static linked_list_t* create_local_address_list(private_socket_t *this) +{ + struct ifaddrs *list; + struct ifaddrs *cur; + host_t *host; + linked_list_t *result = linked_list_create(); + + if (getifaddrs(&list) < 0) + { + return result; + } + + for (cur = list; cur != NULL; cur = cur->ifa_next) + { + if (!(cur->ifa_flags & IFF_UP)) + { + /* ignore interface which are down */ + continue; + } + + host = host_create_from_sockaddr(cur->ifa_addr); + if (host) + { + /* address supported, add to list */ + result->insert_last(result, host); + } + } + freeifaddrs(list); + return result; +} + /** * setup a send socket on a specified port */ @@ -389,12 +477,12 @@ static status_t initialize(private_socket_t *this) } /* setup the send sockets */ - if (this->setup_send_socket(this, this->port, &this->send_fd) != SUCCESS) + if (setup_send_socket(this, this->port, &this->send_fd) != SUCCESS) { this->logger->log(this->logger, ERROR, "unable to setup send socket on port %d!", this->port); return FAILED; } - if (this->setup_send_socket(this, this->natt_port, &this->natt_fd) != SUCCESS) + if (setup_send_socket(this, this->natt_port, &this->natt_fd) != SUCCESS) { this->logger->log(this->logger, ERROR, "unable to setup send socket on port %d!", this->natt_port); return FAILED; @@ -429,13 +517,11 @@ socket_t *socket_create(u_int16_t port, u_int16_t natt_port) { private_socket_t *this = malloc_thing(private_socket_t); - /* private functions */ - this->initialize = (status_t(*)(private_socket_t*))initialize; - this->setup_send_socket = (status_t(*)(private_socket_t*,u_int16_t, int*))setup_send_socket; - /* 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_local_address = (bool(*)(socket_t*, host_t*))is_local_address; + this->public.create_local_address_list = (linked_list_t*(*)(socket_t*))create_local_address_list; this->public.destroy = (void(*)(socket_t*)) destroy; this->logger = logger_manager->get_logger(logger_manager, SOCKET); @@ -443,7 +529,7 @@ socket_t *socket_create(u_int16_t port, u_int16_t natt_port) this->port = port; this->natt_port = natt_port; - if (this->initialize(this) != SUCCESS) + if (initialize(this) != SUCCESS) { free(this); charon->kill(charon, "could not init socket!"); diff --git a/src/charon/network/socket.h b/src/charon/network/socket.h index b8defc369..9d74651da 100644 --- a/src/charon/network/socket.h +++ b/src/charon/network/socket.h @@ -28,6 +28,8 @@ #include #include +#include +#include /** @@ -57,27 +59,23 @@ typedef struct socket_t socket_t; * * @todo add IPv6 support * - * @todo We currently use multiple sockets for historic reasons. With the - * new RAW socket mechanism, we could use just one socket and filter - * addresses in userspace (or via linux socket filter). This would allow - * realtime interface/address management in a easy way... - * * @ingroup network */ struct socket_t { + /** * @brief Receive a packet. * * Reads a packet from the socket and sets source/dest * appropriately. * - * @param sock socket_t object to work on + * @param this socket_t object to work on * @param packet pinter gets address from allocated packet_t * @return * - SUCCESS when packet successfully received * - FAILED when unable to receive */ - status_t (*receive) (socket_t *sock, packet_t **packet); + status_t (*receive) (socket_t *this, packet_t **packet); /** * @brief Send a packet. @@ -86,22 +84,39 @@ struct socket_t { * Packet is sent using default routing mechanisms, thus the * source address in packet is ignored. * - * @param sock socket_t object to work on + * @param this socket_t object to work on * @param packet[out] packet_t to send * @return * - SUCCESS when packet successfully sent * - FAILED when unable to send */ - status_t (*send) (socket_t *sock, packet_t *packet); + status_t (*send) (socket_t *this, packet_t *packet); + + /** + * @brief Check if an address is an address of this host. + * + * @param this socket_t object to work on + * @param host address to check + * @return TRUE if local address, FALSE otherwise + */ + bool (*is_local_address) (socket_t *this, host_t *host); + + /** + * @brief Create a list of hosts with all local addresses. + * + * @param this socket_t object to work on + * @return list with host_t objects + */ + linked_list_t *(*create_local_address_list) (socket_t *this); /** * @brief Destroy sockets. * * close sockets and destroy socket_t object * - * @param sock socket_t to destroy + * @param this socket_t to destroy */ - void (*destroy) (socket_t *sock); + void (*destroy) (socket_t *this); }; /** diff --git a/src/charon/sa/child_sa.c b/src/charon/sa/child_sa.c index 5d2ec12dc..2e8155678 100644 --- a/src/charon/sa/child_sa.c +++ b/src/charon/sa/child_sa.c @@ -24,6 +24,8 @@ #include "child_sa.h" +#include + #include diff --git a/src/charon/sa/transactions/ike_sa_init.c b/src/charon/sa/transactions/ike_sa_init.c index 5b852c3e6..c5e50a843 100644 --- a/src/charon/sa/transactions/ike_sa_init.c +++ b/src/charon/sa/transactions/ike_sa_init.c @@ -368,17 +368,18 @@ static status_t get_request(private_ike_sa_init_t *this, message_t **result) { /* build NAT_DETECTION notifys */ notify_payload_t *notify; - iterator_t *iterator; + linked_list_t *list; host_t *host; /* N(NAT_DETECTION_SOURCE_IP)+ */ - iterator = charon->interfaces->create_address_iterator(charon->interfaces); - while (iterator->iterate(iterator, (void**)&host)) + list = charon->socket->create_local_address_list(charon->socket); + while (list->remove_first(list, (void**)&host) == SUCCESS) { notify = build_natd_payload(this, NAT_DETECTION_SOURCE_IP, host); + host->destroy(host); request->add_payload(request, (payload_t*)notify); } - iterator->destroy(iterator); + list->destroy(list); /* N(NAT_DETECTION_DESTINATION_IP) */ notify = build_natd_payload(this, NAT_DETECTION_DESTINATION_IP, other); diff --git a/src/charon/threads/stroke_interface.c b/src/charon/threads/stroke_interface.c index 47b38ea57..c3837744c 100755 --- a/src/charon/threads/stroke_interface.c +++ b/src/charon/threads/stroke_interface.c @@ -205,7 +205,7 @@ static void stroke_add_conn(private_stroke_t *this, stroke_msg_t *msg) return; } - if (charon->interfaces->is_local_address(charon->interfaces, other_host)) + if (charon->socket->is_local_address(charon->socket, other_host)) { stroke_end_t tmp_end; host_t *tmp_host; @@ -220,7 +220,7 @@ static void stroke_add_conn(private_stroke_t *this, stroke_msg_t *msg) msg->add_conn.me = msg->add_conn.other; msg->add_conn.other = tmp_end; } - else if (!charon->interfaces->is_local_address(charon->interfaces, my_host)) + else if (!charon->socket->is_local_address(charon->socket, my_host)) { this->stroke_logger->log(this->stroke_logger, ERROR, "left nor right host is our side, aborting"); goto destroy_hosts; @@ -635,6 +635,22 @@ static void stroke_terminate(private_stroke_t *this, stroke_msg_t *msg) */ static void stroke_status(private_stroke_t *this, stroke_msg_t *msg) { + linked_list_t *list; + host_t *host; + + list = charon->socket->create_local_address_list(charon->socket); + this->logger->log(this->logger, CONTROL|LEVEL1, + "listening on %d addresses:", + list->get_count(list)); + while (list->remove_first(list, (void**)&host) == SUCCESS) + { + this->logger->log(this->logger, CONTROL|LEVEL1, + " %s", host->get_string(host)); + host->destroy(host); + + } + list->destroy(list); + if (msg->status.name) { pop_string(msg, &(msg->status.name));