moved interface enumeration code to socket, where it belongs

query interfaces every time we need it to respect changes in network config
added address listing on startup and "ipsec statusall"
This commit is contained in:
Martin Willi 2006-08-28 08:45:22 +00:00
parent 834b2ce2e2
commit 4c23a8c9ec
12 changed files with 207 additions and 348 deletions

View File

@ -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 \

View File

@ -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);

View File

@ -32,7 +32,6 @@
#include <threads/thread_pool.h>
#include <threads/stroke_interface.h>
#include <network/socket.h>
#include <network/interfaces.h>
#include <sa/ike_sa_manager.h>
#include <queues/send_queue.h>
#include <queues/job_queue.h>
@ -277,11 +276,6 @@ struct daemon_t {
*/
socket_t *socket;
/**
* A interfaces_t instance.
*/
interfaces_t *interfaces;
/**
* A send_queue_t instance.
*/

6
src/charon/debug Executable file
View File

@ -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

View File

@ -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);

View File

@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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 <net/if.h>
#include <ifaddrs.h>
#include <string.h>
#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;
}

View File

@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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 <utils/linked_list.h>
#include <utils/host.h>
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_ */

View File

@ -36,6 +36,8 @@
#include <netinet/udp.h>
#include <linux/ipsec.h>
#include <linux/filter.h>
#include <net/if.h>
#include <ifaddrs.h>
#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!");

View File

@ -28,6 +28,8 @@
#include <types.h>
#include <network/packet.h>
#include <utils/host.h>
#include <utils/linked_list.h>
/**
@ -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);
};
/**

View File

@ -24,6 +24,8 @@
#include "child_sa.h"
#include <string.h>
#include <daemon.h>

View File

@ -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);

View File

@ -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));