diff options
Diffstat (limited to 'src/charon/sa/tasks')
-rw-r--r-- | src/charon/sa/tasks/child_create.c | 6 | ||||
-rw-r--r-- | src/charon/sa/tasks/ike_auth.c | 16 | ||||
-rw-r--r-- | src/charon/sa/tasks/ike_init.c | 17 | ||||
-rw-r--r-- | src/charon/sa/tasks/ike_mobike.c | 126 | ||||
-rw-r--r-- | src/charon/sa/tasks/ike_mobike.h | 21 | ||||
-rw-r--r-- | src/charon/sa/tasks/ike_natd.c | 106 | ||||
-rw-r--r-- | src/charon/sa/tasks/ike_p2p.c | 851 | ||||
-rw-r--r-- | src/charon/sa/tasks/ike_p2p.h | 110 | ||||
-rw-r--r-- | src/charon/sa/tasks/task.c | 4 | ||||
-rw-r--r-- | src/charon/sa/tasks/task.h | 5 |
10 files changed, 1214 insertions, 48 deletions
diff --git a/src/charon/sa/tasks/child_create.c b/src/charon/sa/tasks/child_create.c index 42f34a94b..3947a84d1 100644 --- a/src/charon/sa/tasks/child_create.c +++ b/src/charon/sa/tasks/child_create.c @@ -722,7 +722,8 @@ static status_t build_r(private_child_create_t *this, message_t *message) build_payloads(this, message); - SIG(CHILD_UP_SUCCESS, "established CHILD_SA successfully"); + SIG(CHILD_UP_SUCCESS, "CHILD_SA '%s' established successfully", + this->child_sa->get_name(this->child_sa)); return SUCCESS; } @@ -807,7 +808,8 @@ static status_t process_i(private_child_create_t *this, message_t *message) if (select_and_install(this, no_dh) == SUCCESS) { - SIG(CHILD_UP_SUCCESS, "established CHILD_SA successfully"); + SIG(CHILD_UP_SUCCESS, "CHILD_SA '%s' established successfully", + this->child_sa->get_name(this->child_sa)); } return SUCCESS; } diff --git a/src/charon/sa/tasks/ike_auth.c b/src/charon/sa/tasks/ike_auth.c index c1c0cd5a2..a3cd6a2bc 100644 --- a/src/charon/sa/tasks/ike_auth.c +++ b/src/charon/sa/tasks/ike_auth.c @@ -157,13 +157,13 @@ static status_t build_id(private_ike_auth_t *this, message_t *message) this->ike_sa->set_my_id(this->ike_sa, me->clone(me)); } - id = id_payload_create_from_identification(this->initiator, me); + id = id_payload_create_from_identification(this->initiator ? ID_INITIATOR : ID_RESPONDER, me); message->add_payload(message, (payload_t*)id); /* as initiator, include other ID if it does not contain wildcards */ if (this->initiator && !other->contains_wildcards(other)) { - id = id_payload_create_from_identification(FALSE, other); + id = id_payload_create_from_identification(ID_RESPONDER, other); message->add_payload(message, (payload_t*)id); } return SUCCESS; @@ -320,7 +320,8 @@ static status_t build_auth_eap(private_ike_auth_t *this, message_t *message) if (!this->initiator) { this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED); - SIG(IKE_UP_SUCCESS, "IKE_SA established between %D[%H]...[%H]%D", + SIG(IKE_UP_SUCCESS, "IKE_SA '%s' established between %D[%H]...[%H]%D", + this->ike_sa->get_name(this->ike_sa), this->ike_sa->get_my_id(this->ike_sa), this->ike_sa->get_my_host(this->ike_sa), this->ike_sa->get_other_host(this->ike_sa), @@ -365,7 +366,8 @@ static status_t process_auth_eap(private_ike_auth_t *this, message_t *message) if (this->initiator) { this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED); - SIG(IKE_UP_SUCCESS, "IKE_SA established between %D[%H]...[%H]%D", + SIG(IKE_UP_SUCCESS, "IKE_SA '%s' established between %D[%H]...[%H]%D", + this->ike_sa->get_name(this->ike_sa), this->ike_sa->get_my_id(this->ike_sa), this->ike_sa->get_my_host(this->ike_sa), this->ike_sa->get_other_host(this->ike_sa), @@ -573,7 +575,8 @@ static status_t build_r(private_ike_auth_t *this, message_t *message) if (this->peer_authenticated) { this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED); - SIG(IKE_UP_SUCCESS, "IKE_SA established between %D[%H]...[%H]%D", + SIG(IKE_UP_SUCCESS, "IKE_SA '%s' established between %D[%H]...[%H]%D", + this->ike_sa->get_name(this->ike_sa), this->ike_sa->get_my_id(this->ike_sa), this->ike_sa->get_my_host(this->ike_sa), this->ike_sa->get_other_host(this->ike_sa), @@ -675,7 +678,8 @@ static status_t process_i(private_ike_auth_t *this, message_t *message) } this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED); - SIG(IKE_UP_SUCCESS, "IKE_SA established between %D[%H]...[%H]%D", + SIG(IKE_UP_SUCCESS, "IKE_SA '%s' established between %D[%H]...[%H]%D", + this->ike_sa->get_name(this->ike_sa), this->ike_sa->get_my_id(this->ike_sa), this->ike_sa->get_my_host(this->ike_sa), this->ike_sa->get_other_host(this->ike_sa), diff --git a/src/charon/sa/tasks/ike_init.c b/src/charon/sa/tasks/ike_init.c index f78b5dd66..42b47a82f 100644 --- a/src/charon/sa/tasks/ike_init.c +++ b/src/charon/sa/tasks/ike_init.c @@ -149,10 +149,18 @@ static void build_payloads(private_ike_init_t *this, message_t *message) nonce_payload = nonce_payload_create(); nonce_payload->set_nonce(nonce_payload, this->my_nonce); - message->add_payload(message, (payload_t*)nonce_payload); - ke_payload = ke_payload_create_from_diffie_hellman(this->dh); - message->add_payload(message, (payload_t*)ke_payload); + + if (this->old_sa) + { /* payload order differs if we are rekeying */ + message->add_payload(message, (payload_t*)nonce_payload); + message->add_payload(message, (payload_t*)ke_payload); + } + else + { + message->add_payload(message, (payload_t*)ke_payload); + message->add_payload(message, (payload_t*)nonce_payload); + } } /** @@ -218,7 +226,8 @@ static status_t build_i(private_ike_init_t *this, message_t *message) status_t status; this->config = this->ike_sa->get_ike_cfg(this->ike_sa); - SIG(IKE_UP_START, "initiating IKE_SA to %H", + SIG(IKE_UP_START, "initiating IKE_SA '%s' to %H", + this->ike_sa->get_name(this->ike_sa), this->config->get_other_host(this->config)); this->ike_sa->set_state(this->ike_sa, IKE_CONNECTING); diff --git a/src/charon/sa/tasks/ike_mobike.c b/src/charon/sa/tasks/ike_mobike.c index 8d4dce36c..d1fc8c695 100644 --- a/src/charon/sa/tasks/ike_mobike.c +++ b/src/charon/sa/tasks/ike_mobike.c @@ -64,7 +64,12 @@ struct private_ike_mobike_t { /** * use task to update addresses */ - bool roam; + bool update; + + /** + * do routability check + */ + bool check; /** * include address list update @@ -140,7 +145,7 @@ static void process_payloads(private_ike_mobike_t *this, message_t *message) } case UPDATE_SA_ADDRESSES: { - this->roam = TRUE; + this->update = TRUE; break; } case NO_ADDITIONAL_ADDRESSES: @@ -225,6 +230,58 @@ static void update_children(private_ike_mobike_t *this) } /** + * Implementation of ike_mobike_t.transmit + */ +static void transmit(private_ike_mobike_t *this, packet_t *packet) +{ + host_t *me, *other, *me_old, *other_old; + iterator_t *iterator; + packet_t *copy; + + if (!this->check) + { + return; + } + + me_old = this->ike_sa->get_my_host(this->ike_sa); + other_old = this->ike_sa->get_other_host(this->ike_sa); + + me = charon->kernel_interface->get_source_addr( + charon->kernel_interface, other_old); + if (me) + { + me->set_port(me, me->ip_equals(me, me_old) ? + me_old->get_port(me_old) : IKEV2_NATT_PORT); + packet->set_source(packet, me); + } + + iterator = this->ike_sa->create_additional_address_iterator(this->ike_sa); + while (iterator->iterate(iterator, (void**)&other)) + { + me = charon->kernel_interface->get_source_addr( + charon->kernel_interface, other); + if (me) + { + /* reuse port for an active address, 4500 otherwise */ + me->set_port(me, me->ip_equals(me, me_old) ? + me_old->get_port(me_old) : IKEV2_NATT_PORT); + other = other->clone(other); + other->set_port(other, other->ip_equals(other, other_old) ? + other_old->get_port(other_old) : IKEV2_NATT_PORT); + DBG1(DBG_IKE, "checking path %#H - %#H", me, other); + copy = packet->clone(packet); + copy->set_source(copy, me); + copy->set_destination(copy, other); + charon->sender->send(charon->sender, copy); + } + } + iterator->destroy(iterator); + me = packet->get_source(packet); + other = packet->get_destination(packet); + DBG1(DBG_IKE, "checking path %#H - %#H", me, other); +} + +/** * Implementation of task_t.process for initiator */ static status_t build_i(private_ike_mobike_t *this, message_t *message) @@ -235,22 +292,22 @@ static status_t build_i(private_ike_mobike_t *this, message_t *message) message->add_notify(message, FALSE, MOBIKE_SUPPORTED, chunk_empty); build_address_list(this, message); } - else + else if (message->get_exchange_type(message) == INFORMATIONAL) { - if (this->roam) + if (this->update) { message->add_notify(message, FALSE, UPDATE_SA_ADDRESSES, chunk_empty); + update_children(this); } if (this->address) { build_address_list(this, message); } - - this->natd = ike_natd_create(this->ike_sa, this->initiator); - this->natd->task.build(&this->natd->task, message); - update_children(this); + if (this->natd) + { + this->natd->task.build(&this->natd->task, message); + } } - return NEED_MORE; } @@ -267,7 +324,7 @@ static status_t process_r(private_ike_mobike_t *this, message_t *message) else if (message->get_exchange_type(message) == INFORMATIONAL) { process_payloads(this, message); - if (this->roam) + if (this->update) { host_t *me, *other; @@ -306,7 +363,7 @@ static status_t build_r(private_ike_mobike_t *this, message_t *message) { this->natd->task.build(&this->natd->task, message); } - if (this->roam) + if (this->update) { update_children(this); } @@ -324,7 +381,6 @@ static status_t process_i(private_ike_mobike_t *this, message_t *message) message->get_payload(message, SECURITY_ASSOCIATION)) { process_payloads(this, message); - return SUCCESS; } else if (message->get_exchange_type(message) == INFORMATIONAL) @@ -341,11 +397,40 @@ static status_t process_i(private_ike_mobike_t *this, message_t *message) { this->natd->task.process(&this->natd->task, message); } - if (this->roam) + if (this->update) { /* update again, as NAT state may have changed */ update_children(this); } + if (this->check) + { + host_t *me_new, *me_old, *other_new, *other_old; + + me_new = message->get_destination(message); + other_new = message->get_source(message); + me_old = this->ike_sa->get_my_host(this->ike_sa); + other_old = this->ike_sa->get_other_host(this->ike_sa); + + if (!me_new->equals(me_new, me_old)) + { + this->update = TRUE; + this->ike_sa->set_my_host(this->ike_sa, me_new->clone(me_new)); + } + if (!other_new->equals(other_new, other_old)) + { + this->update = TRUE; + this->ike_sa->set_other_host(this->ike_sa, other_new->clone(other_new)); + } + if (this->update) + { + /* start the update with the same task */ + this->check = FALSE; + this->address = FALSE; + this->natd = ike_natd_create(this->ike_sa, this->initiator); + this->ike_sa->set_pending_updates(this->ike_sa, 1); + return NEED_MORE; + } + } return SUCCESS; } return NEED_MORE; @@ -356,13 +441,21 @@ static status_t process_i(private_ike_mobike_t *this, message_t *message) */ static void roam(private_ike_mobike_t *this, bool address) { - this->roam = TRUE; + this->check = TRUE; this->address = address; this->ike_sa->set_pending_updates(this->ike_sa, this->ike_sa->get_pending_updates(this->ike_sa) + 1); } /** + * Implementation of ike_mobike_t.is_probing. + */ +static bool is_probing(private_ike_mobike_t *this) +{ + return this->check; +} + +/** * Implementation of task_t.get_type */ static task_type_t get_type(private_ike_mobike_t *this) @@ -404,6 +497,8 @@ ike_mobike_t *ike_mobike_create(ike_sa_t *ike_sa, bool initiator) private_ike_mobike_t *this = malloc_thing(private_ike_mobike_t); this->public.roam = (void(*)(ike_mobike_t*,bool))roam; + this->public.transmit = (void(*)(ike_mobike_t*,packet_t*))transmit; + this->public.is_probing = (bool(*)(ike_mobike_t*))is_probing; this->public.task.get_type = (task_type_t(*)(task_t*))get_type; this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate; this->public.task.destroy = (void(*)(task_t*))destroy; @@ -421,7 +516,8 @@ ike_mobike_t *ike_mobike_create(ike_sa_t *ike_sa, bool initiator) this->ike_sa = ike_sa; this->initiator = initiator; - this->roam = FALSE; + this->update = FALSE; + this->check = FALSE; this->address = TRUE; this->cookie2 = chunk_empty; this->natd = NULL; diff --git a/src/charon/sa/tasks/ike_mobike.h b/src/charon/sa/tasks/ike_mobike.h index db493c459..bb5150723 100644 --- a/src/charon/sa/tasks/ike_mobike.h +++ b/src/charon/sa/tasks/ike_mobike.h @@ -28,6 +28,7 @@ typedef struct ike_mobike_t ike_mobike_t; #include <library.h> #include <sa/ike_sa.h> #include <sa/tasks/task.h> +#include <network/packet.h> /** * @brief Task of type ike_mobike, detects and handles MOBIKE extension. @@ -58,6 +59,26 @@ struct ike_mobike_t { * @param address TRUE to include address list update */ void (*roam)(ike_mobike_t *this, bool address); + + /** + * @brief Transmision hook, called by task manager. + * + * The task manager calls this hook whenever it transmits a packet. It + * allows the mobike task to send the packet on multiple paths to do path + * probing. + * + * @param this calling object + * @param packet the packet to transmit + */ + void (*transmit)(ike_mobike_t *this, packet_t *packet); + + /** + * @brief Check if this task is probing for routability. + * + * @param this calling object + * @return TRUE if task is probing + */ + bool (*is_probing)(ike_mobike_t *this); }; /** diff --git a/src/charon/sa/tasks/ike_natd.c b/src/charon/sa/tasks/ike_natd.c index 84a28d024..4c64ff8ba 100644 --- a/src/charon/sa/tasks/ike_natd.c +++ b/src/charon/sa/tasks/ike_natd.c @@ -26,6 +26,7 @@ #include <string.h> #include <daemon.h> +#include <config/peer_cfg.h> #include <crypto/hashers/hasher.h> #include <encoding/payloads/notify_payload.h> @@ -90,7 +91,7 @@ static chunk_t generate_natd_hash(private_ike_natd_t *this, u_int64_t spi_i, spi_r; u_int16_t port; - /* prepare all requred chunks */ + /* prepare all required chunks */ spi_i = ike_sa_id->get_initiator_spi(ike_sa_id); spi_r = ike_sa_id->get_responder_spi(ike_sa_id); spi_i_chunk.ptr = (void*)&spi_i; @@ -113,6 +114,25 @@ static chunk_t generate_natd_hash(private_ike_natd_t *this, } /** + * build a faked NATD payload to enforce UDP encap + */ +static chunk_t generate_natd_hash_faked(private_ike_natd_t *this) +{ + randomizer_t *randomizer; + chunk_t chunk; + + randomizer = randomizer_create(); + if (randomizer->allocate_pseudo_random_bytes(randomizer, HASH_SIZE_SHA1, + &chunk) != SUCCESS) + { + DBG1(DBG_IKE, "unable to get random bytes for NATD fake"); + chunk = chunk_empty; + } + randomizer->destroy(randomizer); + return chunk; +} + +/** * Build a NAT detection notify payload. */ static notify_payload_t *build_natd_payload(private_ike_natd_t *this, @@ -120,12 +140,21 @@ static notify_payload_t *build_natd_payload(private_ike_natd_t *this, { chunk_t hash; notify_payload_t *notify; - ike_sa_id_t *ike_sa_id; + ike_sa_id_t *ike_sa_id; + ike_cfg_t *config; ike_sa_id = this->ike_sa->get_id(this->ike_sa); + config = this->ike_sa->get_ike_cfg(this->ike_sa); + if (config->force_encap(config) && type == NAT_DETECTION_SOURCE_IP) + { + hash = generate_natd_hash_faked(this); + } + else + { + hash = generate_natd_hash(this, ike_sa_id, host); + } notify = notify_payload_create(); notify->set_notify_type(notify, type); - hash = generate_natd_hash(this, ike_sa_id, host); notify->set_notification_data(notify, hash); chunk_free(&hash); @@ -143,11 +172,12 @@ static void process_payloads(private_ike_natd_t *this, message_t *message) chunk_t hash, src_hash, dst_hash; ike_sa_id_t *ike_sa_id; host_t *me, *other; + ike_cfg_t *config; /* Precompute NAT-D hashes for incoming NAT notify comparison */ ike_sa_id = message->get_ike_sa_id(message); - me = this->ike_sa->get_my_host(this->ike_sa); - other = this->ike_sa->get_other_host(this->ike_sa); + me = message->get_destination(message); + other = message->get_source(message); dst_hash = generate_natd_hash(this, ike_sa_id, me); src_hash = generate_natd_hash(this, ike_sa_id, other); @@ -208,7 +238,13 @@ static void process_payloads(private_ike_natd_t *this, message_t *message) this->ike_sa->set_condition(this->ike_sa, COND_NAT_HERE, !this->dst_matched); this->ike_sa->set_condition(this->ike_sa, COND_NAT_THERE, - !this->src_matched); + !this->src_matched); + config = this->ike_sa->get_ike_cfg(this->ike_sa); + if (this->dst_matched && this->src_matched && + config->force_encap(config)) + { + this->ike_sa->set_condition(this->ike_sa, COND_NAT_FAKE, TRUE); + } } } @@ -218,18 +254,46 @@ static void process_payloads(private_ike_natd_t *this, message_t *message) static status_t process_i(private_ike_natd_t *this, message_t *message) { process_payloads(this, message); - - /* if peer supports NAT-T, we switch to port 4500 even - * if no NAT is detected. MOBIKE requires this. */ - if (message->get_exchange_type(message) == IKE_SA_INIT && - this->ike_sa->supports_extension(this->ike_sa, EXT_NATT)) - { - host_t *me, *other; - me = this->ike_sa->get_my_host(this->ike_sa); - me->set_port(me, IKEV2_NATT_PORT); - other = this->ike_sa->get_other_host(this->ike_sa); - other->set_port(other, IKEV2_NATT_PORT); + if (message->get_exchange_type(message) == IKE_SA_INIT) + { + peer_cfg_t *peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa); + +#ifdef P2P + /* if we are on a mediated connection we have already switched to + * port 4500 and the correct destination port is already configured, + * therefore we must not switch again */ + if (peer_cfg->get_mediated_by(peer_cfg)) + { + return SUCCESS; + } +#endif /* P2P */ + + if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY) || +#ifdef P2P + /* if we are on a mediation connection we swith to port 4500 even + * if no NAT is detected. */ + peer_cfg->is_mediation(peer_cfg) || +#endif /* P2P */ + /* if peer supports NAT-T, we switch to port 4500 even + * if no NAT is detected. MOBIKE requires this. */ + (peer_cfg->use_mobike(peer_cfg) && + this->ike_sa->supports_extension(this->ike_sa, EXT_NATT))) + { + host_t *me, *other; + + /* do not switch if we have a custom port from mobike/NAT */ + me = this->ike_sa->get_my_host(this->ike_sa); + if (me->get_port(me) == IKEV2_UDP_PORT) + { + me->set_port(me, IKEV2_NATT_PORT); + } + other = this->ike_sa->get_other_host(this->ike_sa); + if (other->get_port(other) == IKEV2_UDP_PORT) + { + other->set_port(other, IKEV2_NATT_PORT); + } + } } return SUCCESS; @@ -245,7 +309,7 @@ static status_t build_i(private_ike_natd_t *this, message_t *message) host_t *host; /* destination is always set */ - host = this->ike_sa->get_other_host(this->ike_sa); + host = message->get_destination(message); notify = build_natd_payload(this, NAT_DETECTION_DESTINATION_IP, host); message->add_payload(message, (payload_t*)notify); @@ -254,7 +318,7 @@ static status_t build_i(private_ike_natd_t *this, message_t *message) * 2. We do a routing lookup in the kernel interface * 3. Include all possbile addresses */ - host = this->ike_sa->get_my_host(this->ike_sa); + host = message->get_source(message); if (!host->is_anyaddr(host)) { /* 1. */ notify = build_natd_payload(this, NAT_DETECTION_SOURCE_IP, host); @@ -305,11 +369,11 @@ static status_t build_r(private_ike_natd_t *this, message_t *message) if (this->src_seen && this->dst_seen) { /* initiator seems to support NAT detection, add response */ - me = this->ike_sa->get_my_host(this->ike_sa); + me = message->get_source(message); notify = build_natd_payload(this, NAT_DETECTION_SOURCE_IP, me); message->add_payload(message, (payload_t*)notify); - other = this->ike_sa->get_other_host(this->ike_sa); + other = message->get_destination(message); notify = build_natd_payload(this, NAT_DETECTION_DESTINATION_IP, other); message->add_payload(message, (payload_t*)notify); } diff --git a/src/charon/sa/tasks/ike_p2p.c b/src/charon/sa/tasks/ike_p2p.c new file mode 100644 index 000000000..de5a2e30e --- /dev/null +++ b/src/charon/sa/tasks/ike_p2p.c @@ -0,0 +1,851 @@ +/** + * @file ike_p2p.c + * + * @brief Implementation of the ike_p2p task. + * + */ + +/* + * Copyright (C) 2007 Tobias Brunner + * 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 "ike_p2p.h" + +#include <string.h> + +#include <daemon.h> +#include <config/peer_cfg.h> +#include <encoding/payloads/id_payload.h> +#include <encoding/payloads/notify_payload.h> +#include <encoding/payloads/endpoint_notify.h> +#include <processing/jobs/mediation_job.h> + +#define P2P_SESSIONID_LEN 8 +#define P2P_SESSIONKEY_LEN 16 + +// FIXME: proposed values +#define P2P_SESSIONID_MIN_LEN 4 +#define P2P_SESSIONID_MAX_LEN 16 +#define P2P_SESSIONKEY_MIN_LEN 8 +#define P2P_SESSIONKEY_MAX_LEN 64 + + +typedef struct private_ike_p2p_t private_ike_p2p_t; + +/** + * Private members of a ike_p2p_t task. + */ +struct private_ike_p2p_t { + + /** + * Public methods and task_t interface. + */ + ike_p2p_t public; + + /** + * Assigned IKE_SA. + */ + ike_sa_t *ike_sa; + + /** + * Are we the initiator? + */ + bool initiator; + + /** + * Is this a mediation connection? + */ + bool mediation; + + /** + * Is this the response from another peer? + */ + bool response; + + /** + * Gathered endpoints + */ + linked_list_t *local_endpoints; + + /** + * Parsed endpoints + */ + linked_list_t *remote_endpoints; + + /** + * Did the peer request a callback? + */ + bool callback; + + /** + * Did the connect fail? + */ + bool failed; + + /** + * Was there anything wrong with the payloads? + */ + bool invalid_syntax; + + /** + * The requested peer + */ + identification_t *peer_id; + /** + * Received ID used for connectivity checks + */ + chunk_t session_id; + + /** + * Received key used for connectivity checks + */ + chunk_t session_key; + + /** + * Peer config of the mediated connection + */ + peer_cfg_t *mediated_cfg; + +}; + +// ----------------------------------------------------------------------------- + +/** + * Adds a list of endpoints as notifies to a given message + */ +static void add_endpoints_to_message(message_t *message, linked_list_t *endpoints) +{ + iterator_t *iterator; + endpoint_notify_t *endpoint; + + iterator = endpoints->create_iterator(endpoints, TRUE); + while (iterator->iterate(iterator, (void**)&endpoint)) + { + message->add_payload(message, (payload_t*)endpoint->build_notify(endpoint)); + } + iterator->destroy(iterator); +} + +/** + * Gathers endpoints and adds them to the current message + */ +static void gather_and_add_endpoints(private_ike_p2p_t *this, message_t *message) +{ + iterator_t *iterator; + host_t *addr, *host; + u_int16_t port; + + // get the port that is used to communicate with the ms + host = this->ike_sa->get_my_host(this->ike_sa); + port = host->get_port(host); + + iterator = charon->kernel_interface->create_address_iterator( + charon->kernel_interface); + while (iterator->iterate(iterator, (void**)&addr)) + { + host = addr->clone(addr); + host->set_port(host, port); + + this->local_endpoints->insert_last(this->local_endpoints, + endpoint_notify_create_from_host(HOST, host, NULL)); + + host->destroy(host); + } + iterator->destroy(iterator); + + host = this->ike_sa->get_server_reflexive_host(this->ike_sa); + if (host) + { + this->local_endpoints->insert_last(this->local_endpoints, + endpoint_notify_create_from_host(SERVER_REFLEXIVE, host, + this->ike_sa->get_my_host(this->ike_sa))); + } + + add_endpoints_to_message(message, this->local_endpoints); +} + +/** + * read notifys from message and evaluate them + */ +static void process_payloads(private_ike_p2p_t *this, message_t *message) +{ + iterator_t *iterator; + payload_t *payload; + + iterator = message->get_payload_iterator(message); + while (iterator->iterate(iterator, (void**)&payload)) + { + if (payload->get_type(payload) != NOTIFY) + { + continue; + } + + notify_payload_t *notify = (notify_payload_t*)payload; + + switch (notify->get_notify_type(notify)) + { + case P2P_CONNECT_FAILED: + { + DBG2(DBG_IKE, "received P2P_CONNECT_FAILED notify"); + this->failed = TRUE; + break; + } + case P2P_MEDIATION: + { + DBG2(DBG_IKE, "received P2P_MEDIATION notify"); + this->mediation = TRUE; + break; + } + case P2P_ENDPOINT: + { + endpoint_notify_t *endpoint = endpoint_notify_create_from_payload(notify); + if (!endpoint) + { + DBG1(DBG_IKE, "received invalid P2P_ENDPOINT notify"); + break; + } + DBG2(DBG_IKE, "received P2P_ENDPOINT notify"); + + this->remote_endpoints->insert_last(this->remote_endpoints, endpoint); + break; + } + case P2P_CALLBACK: + { + DBG2(DBG_IKE, "received P2P_CALLBACK notify"); + this->callback = TRUE; + break; + } + case P2P_SESSIONID: + { + chunk_free(&this->session_id); + this->session_id = chunk_clone(notify->get_notification_data(notify)); + DBG3(DBG_IKE, "received p2p_sessionid %B", &this->session_id); + break; + } + case P2P_SESSIONKEY: + { + chunk_free(&this->session_key); + this->session_key = chunk_clone(notify->get_notification_data(notify)); + DBG4(DBG_IKE, "received p2p_sessionkey %B", &this->session_key); + break; + } + case P2P_RESPONSE: + { + DBG2(DBG_IKE, "received P2P_RESPONSE notify"); + this->response = TRUE; + break; + } + default: + break; + } + } + iterator->destroy(iterator); +} + +// ----------------------------------------------------------------------------- + +/** + * Implementation of task_t.process for initiator + */ +static status_t build_i(private_ike_p2p_t *this, message_t *message) +{ + switch(message->get_exchange_type(message)) + { + case IKE_SA_INIT: + { + peer_cfg_t *peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa); + if (peer_cfg->is_mediation(peer_cfg)) + { + DBG2(DBG_IKE, "adding P2P_MEDIATION"); + message->add_notify(message, FALSE, P2P_MEDIATION, chunk_empty); + } + else + { + return SUCCESS; + } + break; + } + case IKE_AUTH: + { + if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_HERE)) + { + endpoint_notify_t *endpoint = endpoint_notify_create_from_host(SERVER_REFLEXIVE, NULL, NULL); + message->add_payload(message, (payload_t*)endpoint->build_notify(endpoint)); + endpoint->destroy(endpoint); + } + break; + } + case P2P_CONNECT: + { + id_payload_t *id_payload; + randomizer_t *rand = randomizer_create(); + + id_payload = id_payload_create_from_identification(ID_PEER, this->peer_id); + message->add_payload(message, (payload_t*)id_payload); + + if (!this->response) + { + // only the initiator creates a session ID. the responder returns + // the session ID that it received from the initiator + if (rand->allocate_pseudo_random_bytes(rand, + P2P_SESSIONID_LEN, &this->session_id) != SUCCESS) + { + DBG1(DBG_IKE, "unable to generate session ID for P2P_CONNECT"); + rand->destroy(rand); + return FAILED; + } + } + + if (rand->allocate_pseudo_random_bytes(rand, + P2P_SESSIONKEY_LEN, &this->session_key) != SUCCESS) + { + DBG1(DBG_IKE, "unable to generate session key for P2P_CONNECT"); + rand->destroy(rand); + return FAILED; + } + + rand->destroy(rand); + + message->add_notify(message, FALSE, P2P_SESSIONID, this->session_id); + message->add_notify(message, FALSE, P2P_SESSIONKEY, this->session_key); + + if (this->response) + { + message->add_notify(message, FALSE, P2P_RESPONSE, chunk_empty); + } + else + { + // FIXME: should we make that configurable + message->add_notify(message, FALSE, P2P_CALLBACK, chunk_empty); + } + + gather_and_add_endpoints(this, message); + + break; + } + } + + return NEED_MORE; +} + +/** + * Implementation of task_t.process for responder + */ +static status_t process_r(private_ike_p2p_t *this, message_t *message) +{ + switch(message->get_exchange_type(message)) + { + case P2P_CONNECT: + { + id_payload_t *id_payload; + id_payload = (id_payload_t*)message->get_payload(message, ID_PEER); + if (!id_payload) + { + DBG1(DBG_IKE, "received P2P_CONNECT without ID_PEER payload, aborting"); + break; + } + this->peer_id = id_payload->get_identification(id_payload); + + process_payloads(this, message); + + if (this->callback) + { + DBG1(DBG_IKE, "received P2P_CALLBACK for '%D'", this->peer_id); + break; + } + + if (!this->session_id.ptr) + { + DBG1(DBG_IKE, "received P2P_CONNECT without P2P_SESSIONID notify, aborting"); + this->invalid_syntax = TRUE; + break; + } + + if (!this->session_key.ptr) + { + DBG1(DBG_IKE, "received P2P_CONNECT without P2P_SESSIONKEY notify, aborting"); + this->invalid_syntax = TRUE; + break; + } + + if (!this->remote_endpoints->get_count(this->remote_endpoints)) + { + DBG1(DBG_IKE, "received P2P_CONNECT without any P2P_ENDPOINT payloads, aborting"); + this->invalid_syntax = TRUE; + break; + } + + DBG1(DBG_IKE, "received P2P_CONNECT"); + + break; + } + } + + return NEED_MORE; +} + +/** + * Implementation of task_t.build for responder + */ +static status_t build_r(private_ike_p2p_t *this, message_t *message) +{ + switch(message->get_exchange_type(message)) + { + case P2P_CONNECT: + { + if (this->invalid_syntax) + { + message->add_notify(message, TRUE, INVALID_SYNTAX, chunk_empty); + break; + } + + if (this->callback) + { + charon->connect_manager->check_and_initiate(charon->connect_manager, + this->ike_sa->get_id(this->ike_sa), + this->ike_sa->get_my_id(this->ike_sa), this->peer_id); + return SUCCESS; + } + + if (this->response) + { + // FIXME: handle result of set_responder_data + // as initiator, upon receiving a response from another peer, + // update the checklist and start sending checks + charon->connect_manager->set_responder_data(charon->connect_manager, + this->session_id, this->session_key, this->remote_endpoints); + } + else + { + // FIXME: handle result of set_initiator_data + // as responder, create a checklist with the initiator's data + charon->connect_manager->set_initiator_data(charon->connect_manager, + this->peer_id, this->ike_sa->get_my_id(this->ike_sa), + this->session_id, this->session_key, this->remote_endpoints, + FALSE); + if (this->ike_sa->respond(this->ike_sa, this->peer_id, + this->session_id) != SUCCESS) + { + return FAILED; + } + } + + break; + } + } + return SUCCESS; +} + +/** + * Implementation of task_t.process for initiator + */ +static status_t process_i(private_ike_p2p_t *this, message_t *message) +{ + switch(message->get_exchange_type(message)) + { + case IKE_SA_INIT: + { + process_payloads(this, message); + + if (!this->mediation) + { + DBG1(DBG_IKE, "server did not return a P2P_MEDIATION, aborting"); + return FAILED; + } + + return NEED_MORE; + } + case IKE_AUTH: + { + process_payloads(this, message); + + //FIXME: we should update the server reflexive endpoint somehow, if mobike notices a change + + endpoint_notify_t *reflexive; + if (this->remote_endpoints->get_first(this->remote_endpoints, (void**)&reflexive) == SUCCESS && + reflexive->get_type(reflexive) == SERVER_REFLEXIVE) + {//FIXME: should we accept this endpoint even if we did not send a request? + host_t *endpoint = reflexive->get_host(reflexive); + DBG2(DBG_IKE, "received server reflexive endpoint %#H", endpoint); + + this->ike_sa->set_server_reflexive_host(this->ike_sa, endpoint->clone(endpoint)); + } + + // FIXME: what if it failed? e.g. AUTH failure + SIG(CHILD_UP_SUCCESS, "established mediation connection without CHILD_SA successfully"); + + break; + } + case P2P_CONNECT: + { + process_payloads(this, message); + + if (this->failed) + { + DBG1(DBG_IKE, "peer '%D' is not online", this->peer_id); + // FIXME: notify the mediated connection (job?) + // FIXME: probably delete the created checklist, at least as responder + } + else + { + if (this->response) + { + // FIXME: handle result of set_responder_data + // as responder, we update the checklist and start sending checks + charon->connect_manager->set_responder_data(charon->connect_manager, + this->session_id, this->session_key, this->local_endpoints); + } + else + { + // FIXME: handle result of set_initiator_data + // as initiator, we create a checklist and set the initiator's data + charon->connect_manager->set_initiator_data(charon->connect_manager, + this->ike_sa->get_my_id(this->ike_sa), this->peer_id, + this->session_id, this->session_key, this->local_endpoints, + TRUE); + } + } + break; + } + } + return SUCCESS; +} + +// ----------------------------------------------------------------------------- + +/** + * Implementation of task_t.process for initiator (mediation server) + */ +static status_t build_i_ms(private_ike_p2p_t *this, message_t *message) +{ + switch(message->get_exchange_type(message)) + { + case P2P_CONNECT: + { + id_payload_t *id_payload = id_payload_create_from_identification(ID_PEER, this->peer_id); + message->add_payload(message, (payload_t*)id_payload); + + if (this->callback) + { + message->add_notify(message, FALSE, P2P_CALLBACK, chunk_empty); + } + else + { + notify_payload_t *notify; + + if (this->response) + { + message->add_notify(message, FALSE, P2P_RESPONSE, chunk_empty); + } + + message->add_notify(message, FALSE, P2P_SESSIONID, this->session_id); + message->add_notify(message, FALSE, P2P_SESSIONKEY, this->session_key); + + add_endpoints_to_message(message, this->remote_endpoints); + } + + break; + } + } + + return NEED_MORE; +} + +/** + * Implementation of task_t.process for responder (mediation server) + */ +static status_t process_r_ms(private_ike_p2p_t *this, message_t *message) +{ + switch(message->get_exchange_type(message)) + { + case IKE_SA_INIT: + { + process_payloads(this, message); + return this->mediation ? NEED_MORE : SUCCESS; + } + case IKE_AUTH: + { + process_payloads(this, message); + break; + } + case P2P_CONNECT: + { + id_payload_t *id_payload; + id_payload = (id_payload_t*)message->get_payload(message, ID_PEER); + if (!id_payload) + { + DBG1(DBG_IKE, "received P2P_CONNECT without ID_PEER payload, aborting"); + this->invalid_syntax = TRUE; + break; + } + + this->peer_id = id_payload->get_identification(id_payload); + + process_payloads(this, message); + + if (!this->session_id.ptr) + { + DBG1(DBG_IKE, "received P2P_CONNECT without P2P_SESSIONID notify, aborting"); + this->invalid_syntax = TRUE; + break; + } + + if (!this->session_key.ptr) + { + DBG1(DBG_IKE, "received P2P_CONNECT without P2P_SESSIONKEY notify, aborting"); + this->invalid_syntax = TRUE; + break; + } + + if (!this->remote_endpoints->get_count(this->remote_endpoints)) + { + DBG1(DBG_IKE, "received P2P_CONNECT without any P2P_ENDPOINT payloads, aborting"); + this->invalid_syntax = TRUE; + break; + } + + break; + } + } + + return NEED_MORE; +} + +/** + * Implementation of task_t.build for responder (mediation server) + */ +static status_t build_r_ms(private_ike_p2p_t *this, message_t *message) +{ + switch(message->get_exchange_type(message)) + { + case IKE_SA_INIT: + { + message->add_notify(message, FALSE, P2P_MEDIATION, chunk_empty); + return NEED_MORE; + } + case IKE_AUTH: + { + endpoint_notify_t *endpoint; + if (this->remote_endpoints->get_first(this->remote_endpoints, (void**)&endpoint) == SUCCESS && + endpoint->get_type(endpoint) == SERVER_REFLEXIVE) + { + host_t *host = this->ike_sa->get_other_host(this->ike_sa); + + DBG2(DBG_IKE, "received request for a server reflexive endpoint " + "sending: %#H", host); + + endpoint = endpoint_notify_create_from_host(SERVER_REFLEXIVE, host, NULL); + message->add_payload(message, (payload_t*)endpoint->build_notify(endpoint)); + } + + charon->mediation_manager->update_sa_id(charon->mediation_manager, + this->ike_sa->get_other_id(this->ike_sa), + this->ike_sa->get_id(this->ike_sa)); + + SIG(CHILD_UP_SUCCESS, "established mediation connection without CHILD_SA successfully"); + + break; + } + case P2P_CONNECT: + { + if (this->invalid_syntax) + { + message->add_notify(message, TRUE, INVALID_SYNTAX, chunk_empty); + break; + } + + ike_sa_id_t *peer_sa; + if (this->callback) + { + peer_sa = charon->mediation_manager->check_and_register(charon->mediation_manager, + this->peer_id, this->ike_sa->get_other_id(this->ike_sa)); + } + else + { + peer_sa = charon->mediation_manager->check(charon->mediation_manager, + this->peer_id); + } + + if (!peer_sa) + { + // the peer is not online + message->add_notify(message, TRUE, P2P_CONNECT_FAILED, chunk_empty); + break; + } + + job_t *job = (job_t*)mediation_job_create(this->peer_id, + this->ike_sa->get_other_id(this->ike_sa), this->session_id, + this->session_key, this->remote_endpoints, this->response); + charon->processor->queue_job(charon->processor, job); + + break; + } + } + return SUCCESS; +} + +/** + * Implementation of task_t.process for initiator (mediation server) + */ +static status_t process_i_ms(private_ike_p2p_t *this, message_t *message) +{ + switch(message->get_exchange_type(message)) + { + case P2P_CONNECT: + { + break; + } + } + return SUCCESS; +} + +// ----------------------------------------------------------------------------- + +/** + * Implementation of ike_p2p.connect + */ +static void p2p_connect(private_ike_p2p_t *this, identification_t *peer_id) +{ + this->peer_id = peer_id->clone(peer_id); +} + +/** + * Implementation of ike_p2p.respond + */ +static void p2p_respond(private_ike_p2p_t *this, identification_t *peer_id, + chunk_t session_id) +{ + this->peer_id = peer_id->clone(peer_id); + this->session_id = chunk_clone(session_id); + this->response = TRUE; +} + +/** + * Implementation of ike_p2p.callback + */ +static void p2p_callback(private_ike_p2p_t *this, identification_t *peer_id) +{ + this->peer_id = peer_id->clone(peer_id); + this->callback = TRUE; +} + +/** + * Implementation of ike_p2p.relay + */ +static void relay(private_ike_p2p_t *this, identification_t *requester, chunk_t session_id, + chunk_t session_key, linked_list_t *endpoints, bool response) +{ + this->peer_id = requester->clone(requester); + this->session_id = chunk_clone(session_id); + this->session_key = chunk_clone(session_key); + this->remote_endpoints = endpoints->clone_offset(endpoints, offsetof(endpoint_notify_t, clone)); + this->response = response; +} + +/** + * Implementation of task_t.get_type + */ +static task_type_t get_type(private_ike_p2p_t *this) +{ + return IKE_P2P; +} + +/** + * Implementation of task_t.migrate + */ +static void migrate(private_ike_p2p_t *this, ike_sa_t *ike_sa) +{ + this->ike_sa = ike_sa; +} + +/** + * Implementation of task_t.destroy + */ +static void destroy(private_ike_p2p_t *this) +{ + DESTROY_IF(this->peer_id); + + chunk_free(&this->session_id); + chunk_free(&this->session_key); + + this->local_endpoints->destroy_offset(this->local_endpoints, offsetof(endpoint_notify_t, destroy)); + this->remote_endpoints->destroy_offset(this->remote_endpoints, offsetof(endpoint_notify_t, destroy)); + + DESTROY_IF(this->mediated_cfg); + free(this); +} + +/* + * Described in header. + */ +ike_p2p_t *ike_p2p_create(ike_sa_t *ike_sa, bool initiator) +{ + private_ike_p2p_t *this = malloc_thing(private_ike_p2p_t); + + this->public.task.get_type = (task_type_t(*)(task_t*))get_type; + this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate; + this->public.task.destroy = (void(*)(task_t*))destroy; + + ike_sa_id_t *id = ike_sa->get_id(ike_sa); + if (id->is_initiator(id)) + { + if (initiator) + { + this->public.task.build = (status_t(*)(task_t*,message_t*))build_i; + this->public.task.process = (status_t(*)(task_t*,message_t*))process_i; + } + else + { + this->public.task.build = (status_t(*)(task_t*,message_t*))build_r; + this->public.task.process = (status_t(*)(task_t*,message_t*))process_r; + } + } + else + { + // mediation server + if (initiator) + { + this->public.task.build = (status_t(*)(task_t*,message_t*))build_i_ms; + this->public.task.process = (status_t(*)(task_t*,message_t*))process_i_ms; + } + else + { + this->public.task.build = (status_t(*)(task_t*,message_t*))build_r_ms; + this->public.task.process = (status_t(*)(task_t*,message_t*))process_r_ms; + } + } + + this->public.connect = (void(*)(ike_p2p_t*,identification_t*))p2p_connect; + this->public.respond = (void(*)(ike_p2p_t*,identification_t*,chunk_t))p2p_respond; + this->public.callback = (void(*)(ike_p2p_t*,identification_t*))p2p_callback; + this->public.relay = (void(*)(ike_p2p_t*,identification_t*,chunk_t,chunk_t,linked_list_t*,bool))relay; + + this->ike_sa = ike_sa; + this->initiator = initiator; + + this->peer_id = NULL; + this->session_id = chunk_empty; + this->session_key = chunk_empty; + this->local_endpoints = linked_list_create(); + this->remote_endpoints = linked_list_create(); + this->mediation = FALSE; + this->response = FALSE; + this->callback = FALSE; + this->failed = FALSE; + this->invalid_syntax = FALSE; + + this->mediated_cfg = NULL; + + return &this->public; +} diff --git a/src/charon/sa/tasks/ike_p2p.h b/src/charon/sa/tasks/ike_p2p.h new file mode 100644 index 000000000..327ac49d8 --- /dev/null +++ b/src/charon/sa/tasks/ike_p2p.h @@ -0,0 +1,110 @@ +/** + * @file ike_p2p.h + * + * @brief Interface ike_p2p_t. + * + */ + +/* + * Copyright (C) 2007 Tobias Brunner + * 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 IKE_P2P_H_ +#define IKE_P2P_H_ + +typedef struct ike_p2p_t ike_p2p_t; + +#include <library.h> +#include <sa/ike_sa.h> +#include <sa/tasks/task.h> + +/** + * @brief Task of type IKE_P2P, detects and handles P2P-NAT-T extensions. + * + * This tasks handles the P2P_MEDIATION notify exchange to setup a mediation + * connection, allows to initiate mediated connections using P2P_CONNECT + * exchanges and to request reflexive addresses from the mediation server using + * P2P_ENDPOINT notifies. + * + * @note This task has to be activated before the IKE_AUTH task, because that + * task generates the IKE_SA_INIT message so that no more payloads can be added + * to it afterwards. + * + * @b Constructors: + * - ike_p2p_create() + * + * @ingroup tasks + */ +struct ike_p2p_t { + + /** + * Implements the task_t interface + */ + task_t task; + + /** + * @brief Initiates a connection with another peer (i.e. sends a P2P_CONNECT + * to the mediation server) + * + * @param this object + * @param peer_id ID of the other peer (gets cloned) + */ + void (*connect)(ike_p2p_t *this, identification_t *peer_id); + + /** + * @brief Responds to a P2P_CONNECT from another peer (i.e. sends a P2P_CONNECT + * to the mediation server) + * + * @param this object + * @param peer_id ID of the other peer (gets cloned) + * @param session_id the session ID as provided by the initiator (gets cloned) + */ + void (*respond)(ike_p2p_t *this, identification_t *peer_id, chunk_t session_id); + + /** + * @brief Sends a P2P_CALLBACK to a peer that previously requested another peer. + * + * @param this object + * @param peer_id ID of the other peer (gets cloned) + */ + void (*callback)(ike_p2p_t *this, identification_t *peer_id); + + /** + * @brief Relays data to another peer (i.e. sends a P2P_CONNECT to the peer) + * + * Data gets cloned. + * + * @param this object + * @param requester ID of the requesting peer + * @param session_id content of the P2P_SESSIONID notify + * @param session_key content of the P2P_SESSIONKEY notify + * @param endpoints endpoints + * @param response TRUE if this is a response + */ + void (*relay)(ike_p2p_t *this, identification_t *requester, chunk_t session_id, + chunk_t session_key, linked_list_t *endpoints, bool response); + +}; + +/** + * @brief Create a new ike_p2p task. + * + * @param ike_sa IKE_SA this task works for + * @param initiator TRUE if taks is initiated by us + * @return ike_p2p task to handle by the task_manager + */ +ike_p2p_t *ike_p2p_create(ike_sa_t *ike_sa, bool initiator); + + +#endif /*IKE_P2P_H_*/ diff --git a/src/charon/sa/tasks/task.c b/src/charon/sa/tasks/task.c index 713403d47..e9d0c4da1 100644 --- a/src/charon/sa/tasks/task.c +++ b/src/charon/sa/tasks/task.c @@ -6,6 +6,7 @@ */ /* + * Copyright (C) 2007 Tobias Brunner * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -33,6 +34,9 @@ ENUM(task_type_names, IKE_INIT, CHILD_REKEY, "IKE_REAUTH", "IKE_DELETE", "IKE_DPD", +#ifdef P2P + "IKE_P2P", +#endif /* P2P */ "CHILD_CREATE", "CHILD_DELETE", "CHILD_REKEY", diff --git a/src/charon/sa/tasks/task.h b/src/charon/sa/tasks/task.h index ff60ea816..dd2bb8a83 100644 --- a/src/charon/sa/tasks/task.h +++ b/src/charon/sa/tasks/task.h @@ -6,6 +6,7 @@ */ /* + * Copyright (C) 2007 Tobias Brunner * Copyright (C) 2006 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -56,6 +57,10 @@ enum task_type_t { IKE_DELETE, /** liveness check */ IKE_DPD, +#ifdef P2P + /** handle P2P-NAT-T stuff */ + IKE_P2P, +#endif /* P2P */ /** establish a CHILD_SA within an IKE_SA */ CHILD_CREATE, /** delete an established CHILD_SA */ |