diff --git a/configure.in b/configure.in index e3eccd977..7c4895954 100644 --- a/configure.in +++ b/configure.in @@ -114,6 +114,8 @@ ARG_DISBL_SET([kernel-netlink], [disable the netlink kernel interface.]) ARG_ENABL_SET([kernel-pfkey], [enable the PF_KEY kernel interface.]) ARG_ENABL_SET([kernel-pfroute], [enable the PF_ROUTE kernel interface.]) ARG_ENABL_SET([kernel-klips], [enable the KLIPS kernel interface.]) +ARG_DISBL_SET([socket-default], [disable default socket implementation for charon.]) +ARG_ENABL_SET([socket-raw], [enable raw socket implementation of charon, enforced if pluto is enabled]) ARG_ENABL_SET([nat-transport], [enable NAT traversal with IPsec transport mode in pluto.]) ARG_DISBL_SET([vendor-id], [disable the sending of the strongSwan vendor ID in pluto.]) ARG_DISBL_SET([xauth-vid], [disable the sending of the XAUTH vendor ID.]) @@ -234,6 +236,14 @@ if test x$medcli = xtrue; then mediation=true fi +if test x$pluto = xtrue; then + if test x$socket_raw = xfalse; then + AC_MSG_NOTICE([Enforcing --enable-socket-raw/--disable-socket-default, as pluto is enabled]) + socket_default=false + socket_raw=true + fi +fi + dnl =========================================== dnl check required libraries and header files dnl =========================================== @@ -800,6 +810,8 @@ AM_CONDITIONAL(USE_KERNEL_NETLINK, test x$kernel_netlink = xtrue) AM_CONDITIONAL(USE_KERNEL_PFKEY, test x$kernel_pfkey = xtrue) AM_CONDITIONAL(USE_KERNEL_PFROUTE, test x$kernel_pfroute = xtrue) AM_CONDITIONAL(USE_KERNEL_KLIPS, test x$kernel_klips = xtrue) +AM_CONDITIONAL(USE_SOCKET_DEFAULT, test x$socket_default = xtrue) +AM_CONDITIONAL(USE_SOCKET_RAW, test x$socket_raw = xtrue) dnl other options dnl ============= @@ -894,6 +906,8 @@ AC_OUTPUT( src/charon/plugins/kernel_pfkey/Makefile src/charon/plugins/kernel_pfroute/Makefile src/charon/plugins/kernel_klips/Makefile + src/charon/plugins/socket_default/Makefile + src/charon/plugins/socket_raw/Makefile src/charon/plugins/smp/Makefile src/charon/plugins/sql/Makefile src/charon/plugins/medsrv/Makefile diff --git a/src/charon/Makefile.am b/src/charon/Makefile.am index 0a021402c..000515bb7 100644 --- a/src/charon/Makefile.am +++ b/src/charon/Makefile.am @@ -45,7 +45,7 @@ kernel/kernel_net.h \ network/packet.c network/packet.h \ network/receiver.c network/receiver.h \ network/sender.c network/sender.h \ -network/socket.h \ +network/socket_manager.c network/socket_manager.h network/socket.h \ processing/jobs/job.h \ processing/jobs/acquire_job.c processing/jobs/acquire_job.h \ processing/jobs/callback_job.c processing/jobs/callback_job.h \ @@ -109,13 +109,6 @@ charon_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la -lm $(PTHREADL # compile options ################# -# Use RAW socket if pluto gets built -if USE_PLUTO - charon_SOURCES += network/socket-raw.c -else - charon_SOURCES += network/socket.c -endif - if USE_ME charon_SOURCES += encoding/payloads/endpoint_notify.c encoding/payloads/endpoint_notify.h \ processing/jobs/initiate_mediation_job.c processing/jobs/initiate_mediation_job.h \ @@ -161,6 +154,16 @@ if USE_KERNEL_NETLINK PLUGINS += kernel-netlink endif +if USE_SOCKET_DEFAULT + SUBDIRS += plugins/socket_default + PLUGINS += socket-default +endif + +if USE_SOCKET_RAW + SUBDIRS += plugins/socket_raw + PLUGINS += socket-raw +endif + if USE_STROKE SUBDIRS += plugins/stroke PLUGINS += stroke diff --git a/src/charon/daemon.c b/src/charon/daemon.c index e71225fd1..abaab7e03 100644 --- a/src/charon/daemon.c +++ b/src/charon/daemon.c @@ -185,6 +185,7 @@ static void destroy(private_daemon_t *this) { this->public.ike_sa_manager->flush(this->public.ike_sa_manager); } + DESTROY_IF(this->public.receiver); /* unload plugins to release threads */ lib->plugins->unload(lib->plugins); #ifdef CAPABILITIES @@ -204,7 +205,6 @@ static void destroy(private_daemon_t *this) DESTROY_IF(this->public.backends); DESTROY_IF(this->public.credentials); DESTROY_IF(this->public.sender); - DESTROY_IF(this->public.receiver); DESTROY_IF(this->public.socket); /* wait until all threads are gone */ DESTROY_IF(this->public.processor); @@ -494,7 +494,7 @@ static bool initialize(private_daemon_t *this, bool syslog, level_t levels[]) this->public.sim = sim_manager_create(); this->public.backends = backend_manager_create(); this->public.kernel_interface = kernel_interface_create(); - this->public.socket = socket_create(); + this->public.socket = socket_manager_create(); this->public.traps = trap_manager_create(); /* load plugins, further infrastructure may need it */ diff --git a/src/charon/daemon.h b/src/charon/daemon.h index cb5946d5d..c0a449e61 100644 --- a/src/charon/daemon.h +++ b/src/charon/daemon.h @@ -148,7 +148,7 @@ typedef struct daemon_t daemon_t; #include #include -#include +#include #include #include #include @@ -200,9 +200,9 @@ typedef struct daemon_t daemon_t; struct daemon_t { /** - * A socket_t instance. + * Socket manager instance */ - socket_t *socket; + socket_manager_t *socket; /** * A ike_sa_manager_t instance. diff --git a/src/charon/network/socket.h b/src/charon/network/socket.h index 83bb9d4c9..798d3411a 100644 --- a/src/charon/network/socket.h +++ b/src/charon/network/socket.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger - * Copyright (C) 2005-2008 Martin Willi + * Copyright (C) 2005-2010 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil * @@ -27,29 +27,10 @@ typedef struct socket_t socket_t; #include #include -#include #include /** - * Maximum size of a packet. - * - * 3000 Bytes should be sufficient, see IKEv2 RFC. However, to run our - * multi-CA test with 2 intermediate CAs, we increase that to 5000 bytes. - */ -#define MAX_PACKET 5000 - -/** - * Abstraction of all sockets (IPv4/IPv6 send/receive). - * - * All available sockets are bound and the receive function - * reads from them. There are actually two implementations: - * The first uses raw sockets to allow binding of other daemons (pluto) to - * UDP/500. An installed "Linux socket filter" filters out all non-IKEv2 - * traffic and handles just IKEv2 messages. An other daemon (pluto) must - * handle all traffic separately, e.g. ignore IKEv2 traffic, since charon - * handles that. - * The other implementation uses normal sockets and is built if - * --disable-pluto is given to the configure script. + * Socket interface definition. */ struct socket_t { @@ -85,18 +66,6 @@ struct socket_t { * @return enumerator over (int fd, int family, int port) */ enumerator_t *(*create_enumerator) (socket_t *this); - - /** - * Destroy socket. - */ - void (*destroy) (socket_t *this); }; -/** - * Create a socket_t, which binds multiple sockets. - * - * @return socket_t object - */ -socket_t *socket_create(); - #endif /** SOCKET_H_ @}*/ diff --git a/src/charon/network/socket_manager.c b/src/charon/network/socket_manager.c new file mode 100644 index 000000000..5bd9356cd --- /dev/null +++ b/src/charon/network/socket_manager.c @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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 "socket_manager.h" + +#include +#include +#include +#include + +typedef struct private_socket_manager_t private_socket_manager_t; + +/** + * Private data of an socket_manager_t object. + */ +struct private_socket_manager_t { + + /** + * Public socket_manager_t interface. + */ + socket_manager_t public; + + /** + * List of registered socket + */ + linked_list_t *sockets; + + /** + * Lock for sockets list + */ + rwlock_t *lock; +}; + +METHOD(socket_manager_t, receiver, status_t, + private_socket_manager_t *this, packet_t **packet) +{ + socket_t *socket; + status_t status; + + this->lock->read_lock(this->lock); + if (this->sockets->get_first(this->sockets, (void**)&socket) != SUCCESS) + { + DBG1(DBG_NET, "no socket implementation registered, receiving failed"); + this->lock->unlock(this->lock); + return NOT_SUPPORTED; + } + /* receive is blocking and the thread can be cancelled */ + thread_cleanup_push((thread_cleanup_t)this->lock->unlock, this->lock); + status = socket->receive(socket, packet); + thread_cleanup_pop(TRUE); + return status; +} + +METHOD(socket_manager_t, sender, status_t, + private_socket_manager_t *this, packet_t *packet) +{ + socket_t *socket; + status_t status; + + this->lock->read_lock(this->lock); + if (this->sockets->get_first(this->sockets, (void**)&socket) != SUCCESS) + { + DBG1(DBG_NET, "no socket implementation registered, sending failed"); + this->lock->unlock(this->lock); + return NOT_SUPPORTED; + } + status = socket->send(socket, packet); + this->lock->unlock(this->lock); + return status; +} + +METHOD(socket_manager_t, create_enumerator, enumerator_t*, + private_socket_manager_t *this) +{ + socket_t *socket; + + this->lock->read_lock(this->lock); + if (this->sockets->get_first(this->sockets, (void**)&socket) != SUCCESS) + { + this->lock->unlock(this->lock); + return enumerator_create_empty(); + } + return enumerator_create_cleaner(socket->create_enumerator(socket), + (void*)this->lock->unlock, this->lock); +} + +METHOD(socket_manager_t, add_socket, void, + private_socket_manager_t *this, socket_t *socket) +{ + this->lock->write_lock(this->lock); + this->sockets->insert_last(this->sockets, socket); + this->lock->unlock(this->lock); +} + +METHOD(socket_manager_t, remove_socket, void, + private_socket_manager_t *this, socket_t *socket) +{ + this->lock->write_lock(this->lock); + this->sockets->remove(this->sockets, socket, NULL); + this->lock->unlock(this->lock); +} + +METHOD(socket_manager_t, destroy, void, + private_socket_manager_t *this) +{ + this->sockets->destroy(this->sockets); + this->lock->destroy(this->lock); + free(this); +} + +/** + * See header + */ +socket_manager_t *socket_manager_create() +{ + private_socket_manager_t *this; + + INIT(this, + .public = { + .send = _sender, + .receive = _receiver, + .create_enumerator = _create_enumerator, + .add_socket = _add_socket, + .remove_socket = _remove_socket, + .destroy = _destroy, + }, + .sockets = linked_list_create(), + .lock = rwlock_create(RWLOCK_TYPE_DEFAULT), + ); + + return &this->public; +} + diff --git a/src/charon/network/socket_manager.h b/src/charon/network/socket_manager.h new file mode 100644 index 000000000..da38f56a9 --- /dev/null +++ b/src/charon/network/socket_manager.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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. + */ + +/** + * @defgroup socket_manager socket_manager + * @{ @ingroup network + */ + +#ifndef SOCKET_MANAGER_H_ +#define SOCKET_MANAGER_H_ + +#include + +typedef struct socket_manager_t socket_manager_t; + +/** + * Handle pluggable socket implementations and send/receive packets through it. + */ +struct socket_manager_t { + + /** + * Receive a packet using the registered socket. + * + * @param packet allocated packet that has been received + * @return + * - SUCCESS when packet successfully received + * - FAILED when unable to receive + */ + status_t (*receive) (socket_manager_t *this, packet_t **packet); + + /** + * Send a packet using the registered socket. + * + * @param packet packet to send out + * @return + * - SUCCESS when packet successfully sent + * - FAILED when unable to send + */ + status_t (*send) (socket_manager_t *this, packet_t *packet); + + /** + * Enumerate all underlying socket file descriptors of the active socket. + * + * @return enumerator over (int fd, int family, int port) + */ + enumerator_t *(*create_enumerator) (socket_manager_t *this); + + /** + * Register a socket implementation. + */ + void (*add_socket)(socket_manager_t *this, socket_t *socket); + + /** + * Unregister a registered socket implementation. + */ + void (*remove_socket)(socket_manager_t *this, socket_t *socket); + + /** + * Destroy a socket_manager_t. + */ + void (*destroy)(socket_manager_t *this); +}; + +/** + * Create a socket_manager instance. + */ +socket_manager_t *socket_manager_create(); + +#endif /** SOCKET_MANAGER_H_ @}*/ diff --git a/src/charon/plugins/socket_default/Makefile.am b/src/charon/plugins/socket_default/Makefile.am new file mode 100644 index 000000000..bf7bf05d9 --- /dev/null +++ b/src/charon/plugins/socket_default/Makefile.am @@ -0,0 +1,11 @@ + +INCLUDES = -I${linux_headers} -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon + +AM_CFLAGS = -rdynamic + +plugin_LTLIBRARIES = libstrongswan-socket-default.la + +libstrongswan_socket_default_la_SOURCES = \ + socket_default_plugin.h socket_default_plugin.c \ + socket_default_socket.h socket_default_socket.c +libstrongswan_socket_default_la_LDFLAGS = -module -avoid-version diff --git a/src/charon/plugins/socket_default/socket_default_plugin.c b/src/charon/plugins/socket_default/socket_default_plugin.c new file mode 100644 index 000000000..4f455b418 --- /dev/null +++ b/src/charon/plugins/socket_default/socket_default_plugin.c @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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 "socket_default_plugin.h" + +#include "socket_default_socket.h" + +#include + +typedef struct private_socket_default_plugin_t private_socket_default_plugin_t; + +/** + * Private data of socket plugin + */ +struct private_socket_default_plugin_t { + + /** + * Implements plugin interface + */ + socket_default_plugin_t public; + + /** + * Socket instance. + */ + socket_default_socket_t *socket; +}; + +METHOD(plugin_t, destroy, void, + private_socket_default_plugin_t *this) +{ + charon->socket->remove_socket(charon->socket, &this->socket->socket); + this->socket->destroy(this->socket); + free(this); +} + +/* + * see header file + */ +plugin_t *plugin_create() +{ + private_socket_default_plugin_t *this; + + INIT(this, + .public.plugin.destroy = _destroy, + .socket = socket_default_socket_create(), + ); + + if (!this->socket) + { + free(this); + return NULL; + } + charon->socket->add_socket(charon->socket, &this->socket->socket); + + return &this->public.plugin; +} + diff --git a/src/charon/plugins/socket_default/socket_default_plugin.h b/src/charon/plugins/socket_default/socket_default_plugin.h new file mode 100644 index 000000000..af98bb5da --- /dev/null +++ b/src/charon/plugins/socket_default/socket_default_plugin.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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. + */ + +/** + * @defgroup socket_default socket_default + * @ingroup cplugins + * + * @defgroup socket_default_plugin socket_default_plugin + * @{ @ingroup socket_default + */ + +#ifndef SOCKET_DEFAULT_PLUGIN_H_ +#define SOCKET_DEFAULT_PLUGIN_H_ + +#include + +typedef struct socket_default_plugin_t socket_default_plugin_t; + +/** + * Default socket implementation plugin. + */ +struct socket_default_plugin_t { + + /** + * implements plugin interface + */ + plugin_t plugin; +}; + +/** + * Create a socket_default_plugin instance. + */ +plugin_t *plugin_create(); + +#endif /** SOCKET_DEFAULT_PLUGIN_H_ @}*/ diff --git a/src/charon/network/socket.c b/src/charon/plugins/socket_default/socket_default_socket.c similarity index 90% rename from src/charon/network/socket.c rename to src/charon/plugins/socket_default/socket_default_socket.c index 81f860b15..d69f30975 100644 --- a/src/charon/network/socket.c +++ b/src/charon/plugins/socket_default/socket_default_socket.c @@ -1,7 +1,7 @@ /* * Copyright (C) 2006-2009 Tobias Brunner * Copyright (C) 2006 Daniel Roethlisberger - * Copyright (C) 2005-2007 Martin Willi + * Copyright (C) 2005-2010 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil * @@ -23,6 +23,8 @@ #define __EXTENSIONS__ #endif +#include "socket_default_socket.h" + #include #include #include @@ -40,11 +42,12 @@ #include #endif -#include "socket.h" - #include #include +/* Maximum size of a packet */ +#define MAX_PACKET 5000 + /* length of non-esp marker */ #define MARKER_LEN sizeof(u_int32_t) @@ -82,16 +85,17 @@ static const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; #endif -typedef struct private_socket_t private_socket_t; +typedef struct private_socket_default_socket_t private_socket_default_socket_t; /** * Private data of an socket_t object */ -struct private_socket_t { +struct private_socket_default_socket_t { + /** * public functions */ - socket_t public; + socket_default_socket_t public; /** * IPv4 socket (500) @@ -114,10 +118,8 @@ struct private_socket_t { int ipv6_natt; }; -/** - * implementation of socket_t.receive - */ -static status_t receiver(private_socket_t *this, packet_t **packet) +METHOD(socket_t, receiver, status_t, + private_socket_default_socket_t *this, packet_t **packet) { char buffer[MAX_PACKET]; chunk_t data; @@ -304,10 +306,8 @@ static status_t receiver(private_socket_t *this, packet_t **packet) return SUCCESS; } -/** - * implementation of socket_t.send - */ -status_t sender(private_socket_t *this, packet_t *packet) +METHOD(socket_t, sender, status_t, + private_socket_default_socket_t *this, packet_t *packet) { int sport, skt, family; ssize_t bytes_sent; @@ -446,7 +446,8 @@ status_t sender(private_socket_t *this, packet_t *packet) /** * open a socket to send and receive packets */ -static int open_socket(private_socket_t *this, int family, u_int16_t port) +static int open_socket(private_socket_default_socket_t *this, + int family, u_int16_t port) { int on = TRUE; struct sockaddr_storage addr; @@ -541,7 +542,7 @@ typedef struct { /** implements enumerator_t */ enumerator_t public; /** sockets we enumerate */ - private_socket_t *socket; + private_socket_default_socket_t *socket; /** counter */ int index; } socket_enumerator_t; @@ -556,10 +557,14 @@ static bool enumerate(socket_enumerator_t *this, int *fd, int *family, int *port int family; int port; } sockets[] = { - { offsetof(private_socket_t, ipv4), AF_INET, IKEV2_UDP_PORT }, - { offsetof(private_socket_t, ipv6), AF_INET6, IKEV2_UDP_PORT }, - { offsetof(private_socket_t, ipv4_natt), AF_INET, IKEV2_NATT_PORT }, - { offsetof(private_socket_t, ipv6_natt), AF_INET6, IKEV2_NATT_PORT } + { offsetof(private_socket_default_socket_t, ipv4), + AF_INET, IKEV2_UDP_PORT }, + { offsetof(private_socket_default_socket_t, ipv6), + AF_INET6, IKEV2_UDP_PORT }, + { offsetof(private_socket_default_socket_t, ipv4_natt), + AF_INET, IKEV2_NATT_PORT }, + { offsetof(private_socket_default_socket_t, ipv6_natt), + AF_INET6, IKEV2_NATT_PORT } }; while(++this->index < countof(sockets)) @@ -577,10 +582,8 @@ static bool enumerate(socket_enumerator_t *this, int *fd, int *family, int *port return FALSE; } -/** - * implementation of socket_t.create_enumerator - */ -static enumerator_t *create_enumerator(private_socket_t *this) +METHOD(socket_t, create_enumerator, enumerator_t*, + private_socket_default_socket_t *this) { socket_enumerator_t *enumerator; @@ -592,10 +595,8 @@ static enumerator_t *create_enumerator(private_socket_t *this) return &enumerator->public; } -/** - * implementation of socket_t.destroy - */ -static void destroy(private_socket_t *this) +METHOD(socket_default_socket_t, destroy, void, + private_socket_default_socket_t *this) { if (this->ipv4) { @@ -619,20 +620,20 @@ static void destroy(private_socket_t *this) /* * See header for description */ -socket_t *socket_create() +socket_default_socket_t *socket_default_socket_create() { - private_socket_t *this = malloc_thing(private_socket_t); + private_socket_default_socket_t *this; - /* public functions */ - this->public.send = (status_t(*)(socket_t*, packet_t*))sender; - this->public.receive = (status_t(*)(socket_t*, packet_t**))receiver; - this->public.create_enumerator = (enumerator_t*(*)(socket_t*))create_enumerator; - this->public.destroy = (void(*)(socket_t*)) destroy; - - this->ipv4 = 0; - this->ipv6 = 0; - this->ipv4_natt = 0; - this->ipv6_natt = 0; + INIT(this, + .public = { + .socket = { + .send = _sender, + .receive = _receiver, + .create_enumerator = _create_enumerator, + }, + .destroy = _destroy, + }, + ); #ifdef __APPLE__ { @@ -678,8 +679,8 @@ socket_t *socket_create() { DBG1(DBG_NET, "could not create any sockets"); destroy(this); - charon->kill(charon, "socket initialization failed"); + return NULL; } - return (socket_t*)this; + return &this->public; } diff --git a/src/charon/plugins/socket_default/socket_default_socket.h b/src/charon/plugins/socket_default/socket_default_socket.h new file mode 100644 index 000000000..755016662 --- /dev/null +++ b/src/charon/plugins/socket_default/socket_default_socket.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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. + */ + +/** + * @defgroup socket_default_socket socket_default_socket + * @{ @ingroup socket_default + */ + +#ifndef SOCKET_DEFAULT_SOCKET_H_ +#define SOCKET_DEFAULT_SOCKET_H_ + +typedef struct socket_default_socket_t socket_default_socket_t; + +#include + +/** + * Default socket, binds to port 500/4500 using any IPv4/IPv6 address. + */ +struct socket_default_socket_t { + + /** + * Implements the socket_t interface. + */ + socket_t socket; + + /** + * Destroy a socket_default_socket_t. + */ + void (*destroy)(socket_default_socket_t *this); +}; + +/** + * Create a socket_default_socket instance. + */ +socket_default_socket_t *socket_default_socket_create(); + +#endif /** SOCKET_DEFAULT_SOCKET_H_ @}*/ diff --git a/src/charon/plugins/socket_raw/Makefile.am b/src/charon/plugins/socket_raw/Makefile.am new file mode 100644 index 000000000..e9a342a59 --- /dev/null +++ b/src/charon/plugins/socket_raw/Makefile.am @@ -0,0 +1,11 @@ + +INCLUDES = -I${linux_headers} -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon + +AM_CFLAGS = -rdynamic + +plugin_LTLIBRARIES = libstrongswan-socket-raw.la + +libstrongswan_socket_raw_la_SOURCES = \ + socket_raw_plugin.h socket_raw_plugin.c \ + socket_raw_socket.h socket_raw_socket.c +libstrongswan_socket_raw_la_LDFLAGS = -module -avoid-version diff --git a/src/charon/plugins/socket_raw/socket_raw_plugin.c b/src/charon/plugins/socket_raw/socket_raw_plugin.c new file mode 100644 index 000000000..76eb71fc1 --- /dev/null +++ b/src/charon/plugins/socket_raw/socket_raw_plugin.c @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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 "socket_raw_plugin.h" + +#include "socket_raw_socket.h" + +#include + +typedef struct private_socket_raw_plugin_t private_socket_raw_plugin_t; + +/** + * Private data of socket plugin + */ +struct private_socket_raw_plugin_t { + + /** + * Implements plugin interface + */ + socket_raw_plugin_t public; + + /** + * Raw socket instance. + */ + socket_raw_socket_t *socket; +}; + +METHOD(plugin_t, destroy, void, + private_socket_raw_plugin_t *this) +{ + charon->socket->remove_socket(charon->socket, &this->socket->socket); + this->socket->destroy(this->socket); + free(this); +} + +/* + * see header file + */ +plugin_t *plugin_create() +{ + private_socket_raw_plugin_t *this; + + INIT(this, + .public.plugin.destroy = _destroy, + .socket = socket_raw_socket_create(), + ); + + if (!this->socket) + { + free(this); + return NULL; + } + charon->socket->add_socket(charon->socket, &this->socket->socket); + + return &this->public.plugin; +} + diff --git a/src/charon/plugins/socket_raw/socket_raw_plugin.h b/src/charon/plugins/socket_raw/socket_raw_plugin.h new file mode 100644 index 000000000..1a295f8f3 --- /dev/null +++ b/src/charon/plugins/socket_raw/socket_raw_plugin.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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. + */ + +/** + * @defgroup socket_raw socket_raw + * @ingroup cplugins + * + * @defgroup socket_raw_plugin socket_raw_plugin + * @{ @ingroup socket_raw + */ + +#ifndef SOCKET_RAW_PLUGIN_H_ +#define SOCKET_RAW_PLUGIN_H_ + +#include + +typedef struct socket_raw_plugin_t socket_raw_plugin_t; + +/** + * RAW socket implementation plugin. + */ +struct socket_raw_plugin_t { + + /** + * implements plugin interface + */ + plugin_t plugin; +}; + +/** + * Create a socket_raw_plugin instance. + */ +plugin_t *plugin_create(); + +#endif /** SOCKET_RAW_PLUGIN_H_ @}*/ diff --git a/src/charon/network/socket-raw.c b/src/charon/plugins/socket_raw/socket_raw_socket.c similarity index 88% rename from src/charon/network/socket-raw.c rename to src/charon/plugins/socket_raw/socket_raw_socket.c index 6cc0463b2..78358568c 100644 --- a/src/charon/network/socket-raw.c +++ b/src/charon/plugins/socket_raw/socket_raw_socket.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger - * Copyright (C) 2005-2008 Martin Willi + * Copyright (C) 2005-2010 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil * @@ -18,6 +18,8 @@ /* for struct in6_pktinfo */ #define _GNU_SOURCE +#include "socket_raw_socket.h" + #include #include #include @@ -34,11 +36,12 @@ #include #include -#include "socket.h" - #include #include +/* Maximum size of a packet */ +#define MAX_PACKET 5000 + /* constants for packet handling */ #define IP_LEN sizeof(struct iphdr) #define IP6_LEN sizeof(struct ip6_hdr) @@ -65,62 +68,61 @@ #define IPV6_2292PKTINFO 2 #endif /*IPV6_2292PKTINFO*/ -typedef struct private_socket_t private_socket_t; +typedef struct private_socket_raw_socket_t private_socket_raw_socket_t; /** * Private data of an socket_t object */ -struct private_socket_t{ +struct private_socket_raw_socket_t { + /** * public functions */ - socket_t public; + socket_raw_socket_t public; - /** - * regular port - */ - int port; + /** + * regular port + */ + int port; - /** - * port used for nat-t - */ - int natt_port; + /** + * port used for nat-t + */ + int natt_port; - /** - * raw receiver socket for IPv4 - */ - int recv4; + /** + * raw receiver socket for IPv4 + */ + int recv4; - /** - * raw receiver socket for IPv6 - */ - int recv6; + /** + * raw receiver socket for IPv6 + */ + int recv6; - /** - * send socket on regular port for IPv4 - */ - int send4; + /** + * send socket on regular port for IPv4 + */ + int send4; - /** - * send socket on regular port for IPv6 - */ - int send6; + /** + * send socket on regular port for IPv6 + */ + int send6; - /** - * send socket on nat-t port for IPv4 - */ - int send4_natt; + /** + * send socket on nat-t port for IPv4 + */ + int send4_natt; - /** - * send socket on nat-t port for IPv6 - */ - int send6_natt; + /** + * send socket on nat-t port for IPv6 + */ + int send6_natt; }; -/** - * implementation of socket_t.receive - */ -static status_t receiver(private_socket_t *this, packet_t **packet) +METHOD(socket_t, receiver, status_t, + private_socket_raw_socket_t *this, packet_t **packet) { char buffer[MAX_PACKET]; chunk_t data; @@ -296,10 +298,8 @@ static status_t receiver(private_socket_t *this, packet_t **packet) return SUCCESS; } -/** - * implementation of socket_t.send - */ -status_t sender(private_socket_t *this, packet_t *packet) +METHOD(socket_t, sender, status_t, + private_socket_raw_socket_t *this, packet_t *packet) { int sport, skt, family; ssize_t bytes_sent; @@ -423,7 +423,8 @@ status_t sender(private_socket_t *this, packet_t *packet) /** * open a socket to send packets */ -static int open_send_socket(private_socket_t *this, int family, u_int16_t port) +static int open_send_socket(private_socket_raw_socket_t *this, + int family, u_int16_t port) { int on = TRUE; int type = UDP_ENCAP_ESPINUDP; @@ -497,7 +498,7 @@ static int open_send_socket(private_socket_t *this, int family, u_int16_t port) /** * open a socket to receive packets */ -static int open_recv_socket(private_socket_t *this, int family) +static int open_recv_socket(private_socket_raw_socket_t *this, int family) { int skt; int on = TRUE; @@ -599,7 +600,7 @@ typedef struct { /** implements enumerator_t */ enumerator_t public; /** sockets we enumerate */ - private_socket_t *socket; + private_socket_raw_socket_t *socket; /** counter */ int index; } socket_enumerator_t; @@ -614,12 +615,12 @@ static bool enumerate(socket_enumerator_t *this, int *fd, int *family, int *port int family; int port; } sockets[] = { - { offsetof(private_socket_t, recv4), AF_INET, IKEV2_UDP_PORT }, - { offsetof(private_socket_t, recv6), AF_INET6, IKEV2_UDP_PORT }, - { offsetof(private_socket_t, send4), AF_INET, IKEV2_UDP_PORT }, - { offsetof(private_socket_t, send6), AF_INET6, IKEV2_UDP_PORT }, - { offsetof(private_socket_t, send4_natt), AF_INET, IKEV2_NATT_PORT }, - { offsetof(private_socket_t, send6_natt), AF_INET6, IKEV2_NATT_PORT } + { offsetof(private_socket_raw_socket_t, recv4), AF_INET, IKEV2_UDP_PORT }, + { offsetof(private_socket_raw_socket_t, recv6), AF_INET6, IKEV2_UDP_PORT }, + { offsetof(private_socket_raw_socket_t, send4), AF_INET, IKEV2_UDP_PORT }, + { offsetof(private_socket_raw_socket_t, send6), AF_INET6, IKEV2_UDP_PORT }, + { offsetof(private_socket_raw_socket_t, send4_natt), AF_INET, IKEV2_NATT_PORT }, + { offsetof(private_socket_raw_socket_t, send6_natt), AF_INET6, IKEV2_NATT_PORT } }; while(++this->index < countof(sockets)) @@ -637,10 +638,8 @@ static bool enumerate(socket_enumerator_t *this, int *fd, int *family, int *port return FALSE; } -/** - * implementation of socket_t.create_enumerator - */ -static enumerator_t *create_enumerator(private_socket_t *this) +METHOD(socket_t, create_enumerator, enumerator_t*, + private_socket_raw_socket_t *this) { socket_enumerator_t *enumerator; @@ -652,10 +651,8 @@ static enumerator_t *create_enumerator(private_socket_t *this) return &enumerator->public; } -/** - * implementation of socket_t.destroy - */ -static void destroy(private_socket_t *this) +METHOD(socket_raw_socket_t, destroy, void, + private_socket_raw_socket_t *this) { if (this->recv4) { @@ -687,22 +684,20 @@ static void destroy(private_socket_t *this) /* * See header for description */ -socket_t *socket_create() +socket_raw_socket_t *socket_raw_socket_create() { - private_socket_t *this = malloc_thing(private_socket_t); + private_socket_raw_socket_t *this; - /* public functions */ - this->public.send = (status_t(*)(socket_t*, packet_t*))sender; - this->public.receive = (status_t(*)(socket_t*, packet_t**))receiver; - this->public.create_enumerator = (enumerator_t*(*)(socket_t*))create_enumerator; - this->public.destroy = (void(*)(socket_t*)) destroy; - - this->recv4 = 0; - this->recv6 = 0; - this->send4 = 0; - this->send6 = 0; - this->send4_natt = 0; - this->send6_natt = 0; + INIT(this, + .public = { + .socket = { + .send = _sender, + .receive = _receiver, + .create_enumerator = _create_enumerator, + }, + .destroy = _destroy, + }, + ); this->recv4 = open_recv_socket(this, AF_INET); if (this->recv4 == 0) @@ -754,8 +749,8 @@ socket_t *socket_create() { DBG1(DBG_NET, "could not create any sockets"); destroy(this); - charon->kill(charon, "socket initialization failed"); + return NULL; } - return (socket_t*)this; + return &this->public; } diff --git a/src/charon/plugins/socket_raw/socket_raw_socket.h b/src/charon/plugins/socket_raw/socket_raw_socket.h new file mode 100644 index 000000000..94cf666e8 --- /dev/null +++ b/src/charon/plugins/socket_raw/socket_raw_socket.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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. + */ + +/** + * @defgroup socket_raw_socket socket_raw_socket + * @{ @ingroup socket_raw + */ + +#ifndef SOCKET_RAW_SOCKET_H_ +#define SOCKET_RAW_SOCKET_H_ + +typedef struct socket_raw_socket_t socket_raw_socket_t; + +#include + +/** + * Raw socket, binds to port 500/4500 using any IPv4/IPv6 address. + * + * This imeplementation uses raw sockets to allow binding of other daemons + * (pluto) to UDP/500/4500. An installed "Linux socket filter" filters out + * all non-IKEv2 traffic and handles just IKEv2 messages. An other daemon + * must handle all traffic separately, e.g. ignore IKEv2 traffic, since charon + * handles that. + */ +struct socket_raw_socket_t { + + /** + * Implements the socket_t interface. + */ + socket_t socket; + + /** + * Destroy a socket_raw_socket_t. + */ + void (*destroy)(socket_raw_socket_t *this); +}; + +/** + * Create a socket_raw_socket instance. + */ +socket_raw_socket_t *socket_raw_socket_create(); + +#endif /** SOCKET_RAW_SOCKET_H_ @}*/