redesigned IKE_SA using a transaction mechanism:
authorMartin Willi <martin@strongswan.org>
Wed, 5 Jul 2006 10:53:20 +0000 (10:53 -0000)
committerMartin Willi <martin@strongswan.org>
Wed, 5 Jul 2006 10:53:20 +0000 (10:53 -0000)
  removed old state machine
  reimplemented IKE_SA setup and delete
  implemented dead peer detection
  implemented keep-alives
  a lot of fixes
  no rekeying yet

71 files changed:
src/charon/Makefile.am
src/charon/config/configuration.c
src/charon/config/configuration.h
src/charon/config/connections/connection.c
src/charon/config/policies/policy.c
src/charon/config/proposal.c
src/charon/daemon.c
src/charon/doc/Todo-list.txt
src/charon/encoding/message.c
src/charon/encoding/message.h
src/charon/encoding/payloads/cert_payload.c
src/charon/encoding/payloads/ke_payload.c
src/charon/encoding/payloads/ke_payload.h
src/charon/encoding/payloads/nonce_payload.h
src/charon/encoding/payloads/notify_payload.c
src/charon/encoding/payloads/notify_payload.h
src/charon/encoding/payloads/payload.c
src/charon/encoding/payloads/payload.h
src/charon/encoding/payloads/proposal_substructure.c
src/charon/encoding/payloads/sa_payload.c
src/charon/network/interfaces.c
src/charon/network/interfaces.h
src/charon/network/socket.c
src/charon/queues/jobs/delete_half_open_ike_sa_job.c
src/charon/queues/jobs/delete_half_open_ike_sa_job.h
src/charon/queues/jobs/incoming_packet_job.c
src/charon/queues/jobs/initiate_ike_sa_job.c
src/charon/queues/jobs/retransmit_request_job.c
src/charon/queues/jobs/send_dpd_job.c
src/charon/queues/jobs/send_keepalive_job.c
src/charon/queues/send_queue.c
src/charon/sa/authenticator.c
src/charon/sa/authenticator.h
src/charon/sa/child_sa.c
src/charon/sa/ike_sa.c
src/charon/sa/ike_sa.h
src/charon/sa/ike_sa_id.c
src/charon/sa/ike_sa_manager.c
src/charon/sa/states/create_child_sa_requested.c [deleted file]
src/charon/sa/states/create_child_sa_requested.h [deleted file]
src/charon/sa/states/delete_child_sa_requested.c [deleted file]
src/charon/sa/states/delete_child_sa_requested.h [deleted file]
src/charon/sa/states/delete_ike_sa_requested.c [deleted file]
src/charon/sa/states/delete_ike_sa_requested.h [deleted file]
src/charon/sa/states/ike_auth_requested.c [deleted file]
src/charon/sa/states/ike_auth_requested.h [deleted file]
src/charon/sa/states/ike_sa_established.c [deleted file]
src/charon/sa/states/ike_sa_established.h [deleted file]
src/charon/sa/states/ike_sa_init_requested.c [deleted file]
src/charon/sa/states/ike_sa_init_requested.h [deleted file]
src/charon/sa/states/ike_sa_init_responded.c [deleted file]
src/charon/sa/states/ike_sa_init_responded.h [deleted file]
src/charon/sa/states/initiator_init.c [deleted file]
src/charon/sa/states/initiator_init.h [deleted file]
src/charon/sa/states/responder_init.c [deleted file]
src/charon/sa/states/responder_init.h [deleted file]
src/charon/sa/states/state.c [deleted file]
src/charon/sa/states/state.h [deleted file]
src/charon/sa/transactions/dead_peer_detection.c [new file with mode: 0644]
src/charon/sa/transactions/dead_peer_detection.h [new file with mode: 0644]
src/charon/sa/transactions/delete_ike_sa.c [new file with mode: 0644]
src/charon/sa/transactions/delete_ike_sa.h [new file with mode: 0644]
src/charon/sa/transactions/ike_auth.c [new file with mode: 0644]
src/charon/sa/transactions/ike_auth.h [new file with mode: 0644]
src/charon/sa/transactions/ike_sa_init.c [new file with mode: 0644]
src/charon/sa/transactions/ike_sa_init.h [new file with mode: 0644]
src/charon/sa/transactions/transaction.c [new file with mode: 0644]
src/charon/sa/transactions/transaction.h [new file with mode: 0644]
src/charon/testing/generator_test.c
src/charon/testing/parser_test.c
src/charon/threads/stroke_interface.c

index 54028b0..09eab46 100644 (file)
@@ -1,4 +1,3 @@
-SUBDIRS = . testing
 ipsec_PROGRAMS = charon
 
 charon_SOURCES = \
@@ -9,13 +8,11 @@ config/policies/local_policy_store.c config/policies/policy_store.h config/polic
 config/credentials/local_credential_store.c config/credentials/local_credential_store.h \
 config/credentials/credential_store.h config/traffic_selector.c config/traffic_selector.h \
 config/proposal.c config/proposal.h config/configuration.c config/configuration.h \
-sa/states/state.c sa/states/state.h sa/states/ike_sa_init_requested.c sa/states/ike_sa_init_requested.h \
-sa/states/ike_sa_init_responded.c sa/states/ike_sa_established.c sa/states/ike_sa_established.h \
-sa/states/responder_init.c sa/states/responder_init.h sa/states/initiator_init.c sa/states/initiator_init.h \
-sa/states/ike_sa_init_responded.h sa/states/ike_auth_requested.c sa/states/ike_auth_requested.h \
-sa/states/delete_ike_sa_requested.h sa/states/delete_ike_sa_requested.c \
-sa/states/delete_child_sa_requested.h sa/states/delete_child_sa_requested.c \
-sa/states/create_child_sa_requested.c sa/states/create_child_sa_requested.h \
+sa/transactions/transaction.h sa/transactions/transaction.c \
+sa/transactions/ike_sa_init.h sa/transactions/ike_sa_init.c \
+sa/transactions/ike_auth.h sa/transactions/ike_auth.c \
+sa/transactions/dead_peer_detection.h sa/transactions/dead_peer_detection.c \
+sa/transactions/delete_ike_sa.h sa/transactions/delete_ike_sa.c \
 sa/child_sa.c sa/child_sa.h sa/ike_sa.c sa/ike_sa.h sa/ike_sa_manager.c sa/ike_sa_manager.h \
 sa/ike_sa_id.c sa/ike_sa_id.h sa/authenticator.c sa/authenticator.h encoding/payloads/encryption_payload.c \
 encoding/payloads/cert_payload.c encoding/payloads/payload.h encoding/payloads/traffic_selector_substructure.c \
index cd20586..2dcf0bb 100755 (executable)
@@ -29,6 +29,7 @@
 
 /**
  * Timeout in milliseconds after that a half open IKE_SA gets deleted.
+ * Set to zero to disable
  */
 #define HALF_OPEN_IKE_SA_TIMEOUT 30000
 
 #define MAX_RETRANSMIT_COUNT 6
 
 /**
- * Keepalive interval in milliseconds.
+ * Keepalive interval in seconds.
  */
-#define KEEPALIVE_INTERVAL 2000000
+#define KEEPALIVE_INTERVAL 20
 
 /**
- * DPD interval in milliseconds.
+ * DPD interval in seconds.
  */
-#define DPD_INTERVAL 6000000
+#define DPD_INTERVAL 60
 
 
 typedef struct private_configuration_t private_configuration_t;
@@ -78,16 +79,13 @@ struct private_configuration_t {
 /**
  * Implementation of configuration_t.get_retransmit_timeout.
  */
-static status_t get_retransmit_timeout (private_configuration_t *this, u_int32_t retransmit_count, u_int32_t *timeout)
+static u_int32_t get_retransmit_timeout (private_configuration_t *this, u_int32_t retransmit_count)
 {
        if (retransmit_count > MAX_RETRANSMIT_COUNT && MAX_RETRANSMIT_COUNT != 0)
        {
-               return FAILED;
+               return 0;
        }
-       
-       *timeout = (u_int32_t)(RETRANSMIT_TIMEOUT * pow(RETRANSMIT_BASE, retransmit_count));
-
-       return SUCCESS;
+       return (u_int32_t)(RETRANSMIT_TIMEOUT * pow(RETRANSMIT_BASE, retransmit_count));
 }
 
 /**
@@ -131,7 +129,7 @@ configuration_t *configuration_create()
        
        /* public functions */
        this->public.destroy = (void(*)(configuration_t*))destroy;
-       this->public.get_retransmit_timeout = (status_t (*) (configuration_t *, u_int32_t retransmit_count, u_int32_t *timeout))get_retransmit_timeout;
+       this->public.get_retransmit_timeout = (u_int32_t (*) (configuration_t *, u_int32_t retransmit_count))get_retransmit_timeout;
        this->public.get_half_open_ike_sa_timeout = (u_int32_t (*) (configuration_t *)) get_half_open_ike_sa_timeout;
        this->public.get_keepalive_interval = (u_int32_t (*) (configuration_t *)) get_keepalive_interval;
        this->public.get_dpd_interval = (u_int32_t (*) (configuration_t *)) get_dpd_interval;
index 813b957..553a01e 100755 (executable)
@@ -41,18 +41,15 @@ struct configuration_t {
        /**
         * @brief Returns the retransmit timeout.
         *
+        * A return value of zero means the request should not retransmitted again.
         * The timeout values are managed by the configuration, so 
         * another backoff algorithm may be implemented here.
         *
         * @param this                          calling object
         * @param retransmit_count      number of times a message was retransmitted so far
-        * @param[out] timeout          the new retransmit timeout in milliseconds
-        * 
-        * @return              
-        *                                                      - FAILED, if the message should not be retransmitted
-        *                                                      - SUCCESS
+        * @return                                      time in milliseconds, when to schedule next retransmit
         */
-       status_t (*get_retransmit_timeout) (configuration_t *this, u_int32_t retransmit_count, u_int32_t *timeout);
+       u_int32_t (*get_retransmit_timeout) (configuration_t *this, u_int32_t retransmit_count);
        
        /**
         * @brief Returns the timeout for an half open IKE_SA in ms.
@@ -76,7 +73,7 @@ struct configuration_t {
         * NAT keepalive packet should be sent.
         * 
         * @param this                          calling object
-        * @return                                      interval in milliseconds (ms)
+        * @return                                      interval in seconds
         */     
        u_int32_t (*get_keepalive_interval) (configuration_t *this);
 
@@ -87,7 +84,7 @@ struct configuration_t {
         * DPD request packet should be sent.
         * 
         * @param this                          calling object
-        * @return                                      interval in milliseconds (ms)
+        * @return                                      interval in seconds
         */     
        u_int32_t (*get_dpd_interval) (configuration_t *this);
 
index ce1f0f3..e314660 100644 (file)
@@ -280,9 +280,9 @@ static bool check_dh_group(private_connection_t *this, diffie_hellman_group_t dh
                                return TRUE;
                        }
                }
+               alg_iter->destroy(alg_iter);
        }
        prop_iter->destroy(prop_iter);
-       alg_iter->destroy(alg_iter);
        return FALSE;
 }
 
index 9e163f9..0e2d148 100644 (file)
@@ -503,7 +503,7 @@ policy_t *policy_create(char *name, identification_t *my_id, identification_t *o
        this->public.add_other_traffic_selector = (void(*)(policy_t*,traffic_selector_t*))add_other_traffic_selector;
        this->public.add_proposal = (void(*)(policy_t*,proposal_t*))add_proposal;
        this->public.add_authorities = (void(*)(policy_t*,identification_t*, identification_t*))add_authorities;
-       this->public.add_updown = (void(*)(policy_t*,identification_t*,char*))add_updown;
+       this->public.add_updown = (void(*)(policy_t*,char*))add_updown;
        this->public.get_soft_lifetime = (u_int32_t (*) (policy_t *))get_soft_lifetime;
        this->public.get_hard_lifetime = (u_int32_t (*) (policy_t *))get_hard_lifetime;
        this->public.clone = (policy_t*(*)(policy_t*))clone;
index 3eb0815..503b4c1 100644 (file)
@@ -572,6 +572,8 @@ proposal_t *proposal_create_default(protocol_id_t protocol)
                        add_algorithm(this, INTEGRITY_ALGORITHM,    AUTH_HMAC_SHA1_96, 0);
                        add_algorithm(this, INTEGRITY_ALGORITHM,    AUTH_HMAC_MD5_96,  0);
                        break;
+               default:
+                       break;
        }
        
        return &this->public;
index 73d131c..d9ce83e 100644 (file)
@@ -34,7 +34,7 @@
 #include "daemon.h" 
 
 #include <types.h>
-#include <config/credentials/credential_store.h>
+#include <config/credentials/local_credential_store.h>
 #include <config/connections/local_connection_store.h>
 #include <config/policies/local_policy_store.h>
 
index 8508d24..7fb33e5 100644 (file)
@@ -35,9 +35,9 @@
 / useable certificate support
   + more id types (use atodn from pluto)
   + rewrite certificate storage the clean way
-  - further subjectAltName support
-  - certificate validation/chaining
-  - certificate exchange
+  + further subjectAltName support
+  + certificate validation/chaining
+  + certificate exchange
 
 + Apply -W's from Makefile.program to charon
 + do ipsec status via starter
@@ -45,7 +45,7 @@
 
 + stroke status should show configured connections
 + stroke loglevel update
-- stroke argument parsing via getopts/gperf?
++ stroke argument parsing via getopts/gperf?
 
 - implement 3DES to load encrypted pem files
 + ipsec.secrets parsing
@@ -60,3 +60,4 @@
 - add a crl fetch mechanism which synchronizes equal fetches
 
 - replace state machine with something more transaction oriented
+- find existing IKE_SA on CHILD_SA initiation
index 4f5f3b8..4593d33 100644 (file)
@@ -22,6 +22,7 @@
  */
 
 #include <stdlib.h>
+#include <string.h>
 
 #include "message.h"
 
@@ -413,14 +414,9 @@ static void set_ike_sa_id (private_message_t *this,ike_sa_id_t *ike_sa_id)
 /**
  * Implementation of message_t.get_ike_sa_id.
  */
-static status_t get_ike_sa_id (private_message_t *this,ike_sa_id_t **ike_sa_id)
+static ike_sa_id_t* get_ike_sa_id (private_message_t *this)
 {
-       if (this->ike_sa_id == NULL)
-       {
-               return FAILED;
-       }
-       *ike_sa_id = this->ike_sa_id->clone(this->ike_sa_id);
-       return SUCCESS;
+       return this->ike_sa_id;
 }
 
 /**
@@ -521,6 +517,20 @@ static exchange_type_t get_request (private_message_t *this)
 }
 
 /**
+ * Is this message in an encoded form?
+ */
+static bool is_encoded(private_message_t *this)
+{
+       chunk_t data = this->packet->get_data(this->packet);
+       
+       if (data.ptr == NULL)
+       {
+               return FALSE;
+       }
+       return TRUE;
+}
+
+/**
  * Implementation of message_t.add_payload.
  */
 static void add_payload(private_message_t *this, payload_t *payload)
@@ -583,6 +593,48 @@ static iterator_t *get_payload_iterator(private_message_t *this)
        return this->payloads->create_iterator(this->payloads, TRUE);
 }
 
+/**
+ * Build a string containing short names for all payload in this message
+ */
+static void build_payload_string(private_message_t *this, char* buffer, size_t size)
+{
+       iterator_t *iterator;
+       payload_t *payload;
+       bool first = TRUE;
+       
+       *buffer = '\0';
+       size--;
+       
+       iterator = this->payloads->create_iterator(this->payloads, TRUE);
+       while (iterator->iterate(iterator, (void**)&payload))
+       {
+               payload_type_t type = payload->get_type(payload);
+               char *name = mapping_find(payload_type_short_m, type);
+               size_t name_len = strlen(name);
+               if (!first)
+               {
+                       strncat(buffer, " ", size);
+                       if (size)
+                       {
+                               size--;
+                       }
+               }
+               else
+               {
+                       first = FALSE;
+               }
+               strncat(buffer, name, size);
+               if (name_len > size)
+               {
+                       size = 0;
+               }
+               else
+               {
+                       size -= name_len;
+               }
+       }
+       iterator->destroy(iterator);
+}
 
 /**
  * Implementation of message_t.generate.
@@ -595,11 +647,20 @@ static status_t generate(private_message_t *this, crypter_t *crypter, signer_t*
        iterator_t *iterator;
        status_t status;
        chunk_t packet_data;
+       char payload_names[128];
+       
+       if (is_encoded(this))
+       {
+               /* already generated, return a new packet clone */
+               *packet = this->packet->clone(this->packet);
+               return SUCCESS;
+       }
        
-       this->logger->log(this->logger, CONTROL, "generating %s %s, contains %d payloads",
+       build_payload_string(this, payload_names, sizeof(payload_names));
+       this->logger->log(this->logger, CONTROL, "generating %s %s [%s]",
                                          mapping_find(exchange_type_m,this->exchange_type),
                                          this->is_request ? "request" : "response",
-                                         this->payloads->get_count(this->payloads));
+                                         payload_names);
        
        if (this->exchange_type == EXCHANGE_TYPE_UNDEFINED)
        {
@@ -711,20 +772,6 @@ static chunk_t get_packet_data (private_message_t *this)
 }
 
 /**
- * Implementation of message_t.is_encoded.
- */
-static bool is_encoded(private_message_t *this)
-{
-       chunk_t data = this->packet->get_data(this->packet);
-       
-       if (data.ptr == NULL)
-       {
-               return FALSE;
-       }
-       return TRUE;
-}
-
-/**
  * Implementation of message_t.parse_header.
  */
 static status_t parse_header(private_message_t *this)
@@ -794,6 +841,7 @@ static status_t parse_body(private_message_t *this, crypter_t *crypter, signer_t
 {
        status_t status = SUCCESS;
        payload_type_t current_payload_type;
+       char payload_names[128];
                
        current_payload_type = this->first_payload;     
                
@@ -815,7 +863,7 @@ static status_t parse_body(private_message_t *this, crypter_t *crypter, signer_t
                {
                        this->logger->log(this->logger, ERROR, "payload type %s could not be parsed",
                                                                mapping_find(payload_type_m,current_payload_type));
-                       return status;
+                       return PARSE_ERROR;
                }
 
                this->logger->log(this->logger, CONTROL|LEVEL2, "verify payload of type %s", 
@@ -828,8 +876,7 @@ static status_t parse_body(private_message_t *this, crypter_t *crypter, signer_t
                        this->logger->log(this->logger, ERROR, "%s payload verification failed",
                                                                mapping_find(payload_type_m,current_payload_type));
                        current_payload->destroy(current_payload);
-                       status = VERIFY_ERROR;
-                       return status;
+                       return VERIFY_ERROR;
                }
                
                this->logger->log(this->logger, CONTROL|LEVEL2, "%s payload verified. Adding to payload list", 
@@ -862,14 +909,16 @@ static status_t parse_body(private_message_t *this, crypter_t *crypter, signer_t
        if (status != SUCCESS)
        {
                this->logger->log(this->logger, ERROR, "verification of message failed");
+               return status;
        }
        
-       this->logger->log(this->logger, CONTROL, "parsed %s %s, contains %d payloads", 
+       build_payload_string(this, payload_names, sizeof(payload_names));
+       this->logger->log(this->logger, CONTROL, "parsed %s %s [%s]", 
                                        mapping_find(exchange_type_m, this->exchange_type),
                                        this->is_request ? "request" : "response",
-                                       this->payloads->get_count(this->payloads));
+                                       payload_names);
        
-       return status;
+       return SUCCESS;
 }
 
 /**
@@ -926,7 +975,7 @@ static status_t verify(private_message_t *this)
                                                                          mapping_find(payload_type_m, current_payload_type),
                                                                          this->message_rule->payload_rules[i].max_occurence, found_payloads);
                                        iterator->destroy(iterator);
-                                       return FAILED;                                  
+                                       return VERIFY_ERROR;
                                }
                        }
                }
@@ -937,7 +986,7 @@ static status_t verify(private_message_t *this)
                                                          mapping_find(payload_type_m, this->message_rule->payload_rules[i].payload_type),
                                                          this->message_rule->payload_rules[i].min_occurence, found_payloads);
                        iterator->destroy(iterator);
-                       return FAILED;
+                       return VERIFY_ERROR;
                }
                if ((this->message_rule->payload_rules[i].sufficient) && (this->payloads->get_count(this->payloads) == total_found_payloads))
                {
@@ -993,7 +1042,7 @@ static status_t decrypt_payloads(private_message_t *this,crypter_t *crypter, sig
                                /* encrypted payload is not last one */
                                this->logger->log(this->logger, ERROR, "encrypted payload is not last payload");
                                iterator->destroy(iterator);
-                               return FAILED;
+                               return VERIFY_ERROR;
                        }
                        /* decrypt */
                        encryption_payload->set_transforms(encryption_payload, crypter, signer);
@@ -1003,7 +1052,7 @@ static status_t decrypt_payloads(private_message_t *this,crypter_t *crypter, sig
                        {
                                this->logger->log(this->logger, ERROR, "encryption payload signature invalid");
                                iterator->destroy(iterator);
-                               return status;
+                               return FAILED;
                        }
                        this->logger->log(this->logger, CONTROL | LEVEL2, "decrypt content of encryption payload");
                        status = encryption_payload->decrypt(encryption_payload);
@@ -1013,7 +1062,7 @@ static status_t decrypt_payloads(private_message_t *this,crypter_t *crypter, sig
                                                                  "encrypted payload could not be decrypted and parsed: %s", 
                                                                  mapping_find(status_m, status));
                                iterator->destroy(iterator);
-                               return status;
+                               return PARSE_ERROR;
                        }
                        
                        /* needed later to find out if a payload was encrypted */
@@ -1073,7 +1122,7 @@ static status_t decrypt_payloads(private_message_t *this,crypter_t *crypter, sig
                                this->logger->log(this->logger, ERROR, "payload type %s not allowed",
                                                                  mapping_find(payload_type_m,current_payload_type));
                                iterator->destroy(iterator);
-                               return status;
+                               return VERIFY_ERROR;
                        }
                        
                        /* check if the payload was encrypted, and if it should been have encrypted */
@@ -1084,7 +1133,7 @@ static status_t decrypt_payloads(private_message_t *this,crypter_t *crypter, sig
                                                                        mapping_find(payload_type_m,current_payload_type),
                                                                        (payload_rule->encrypted) ? "encrypted" : "not encrypted");
                                iterator->destroy(iterator);
-                               return FAILED;
+                               return VERIFY_ERROR;
                        }
                }
                /* advance to the next payload */
@@ -1188,8 +1237,6 @@ static void destroy (private_message_t *this)
 {
        iterator_t *iterator;
        
-       this->logger->log(this->logger, CONTROL|LEVEL3, "going to destroy message_t object");
-       
        this->packet->destroy(this->packet);
 
        if (this->ike_sa_id != NULL)
@@ -1202,8 +1249,6 @@ static void destroy (private_message_t *this)
        {
                payload_t *payload;
                iterator->current(iterator, (void**)&payload);  
-               this->logger->log(this->logger, CONTROL|LEVEL3, "destroying payload of type %s", 
-                                                       mapping_find(payload_type_m, payload->get_type(payload)));
                payload->destroy(payload);
        }
        iterator->destroy(iterator);
@@ -1230,7 +1275,7 @@ message_t *message_create_from_packet(packet_t *packet)
        this->public.get_initiator_spi = (u_int64_t(*)(message_t*))get_initiator_spi;
        this->public.get_responder_spi = (u_int64_t(*)(message_t*))get_responder_spi;
        this->public.set_ike_sa_id = (void(*)(message_t*, ike_sa_id_t *))set_ike_sa_id;
-       this->public.get_ike_sa_id = (status_t(*)(message_t*, ike_sa_id_t **))get_ike_sa_id;
+       this->public.get_ike_sa_id = (ike_sa_id_t*(*)(message_t*))get_ike_sa_id;
        this->public.set_exchange_type = (void(*)(message_t*, exchange_type_t))set_exchange_type;
        this->public.get_exchange_type = (exchange_type_t(*)(message_t*))get_exchange_type;
        this->public.set_request = (void(*)(message_t*, bool))set_request;
@@ -1246,7 +1291,6 @@ message_t *message_create_from_packet(packet_t *packet)
        this->public.parse_body = (status_t (*) (message_t *,crypter_t*,signer_t*)) parse_body;
        this->public.get_packet = (packet_t * (*) (message_t*)) get_packet;
        this->public.get_packet_data = (chunk_t (*) (message_t *this)) get_packet_data;
-       this->public.is_encoded = (bool (*) (message_t *this)) is_encoded;
        this->public.destroy = (void(*)(message_t*))destroy;
                
        /* private values */
index 8c105e5..41edd4c 100644 (file)
@@ -120,27 +120,22 @@ struct message_t {
        /**
         * @brief Sets the IKE_SA ID of the message.
         * 
-        * @warning ike_sa_id gets cloned  internaly and 
-        * so can be destroyed afterwards.
+        * ike_sa_id gets cloned.
         *
         * @param this                  message_t object
         * @param ike_sa_id             ike_sa_id to set
         */
-       void (*set_ike_sa_id) (message_t *this,ike_sa_id_t * ike_sa_id);
+       void (*set_ike_sa_id) (message_t *this, ike_sa_id_t * ike_sa_id);
 
        /**
         * @brief Gets the IKE_SA ID of the message.
-        * 
-        * @warning The returned ike_sa_id is a clone of the internal one.
-        * So it has to be destroyed by the caller.
+        *
+        * The ike_sa_id points to the message internal id, do not modify.
         *
         * @param this                  message_t object
-        * @param ike_sa_id             pointer to ike_sa_id pointer which will be set
-        * @return                              
-        *                                              - SUCCESS
-        *                                              - FAILED if no ike_sa_id is set
+        * @return                              ike_sa_id of message
         */
-       status_t (*get_ike_sa_id) (message_t *this,ike_sa_id_t **ike_sa_id);
+       ike_sa_id_t *(*get_ike_sa_id) (message_t *this);
 
        /**
         * @brief Sets the exchange type of the message.
@@ -219,11 +214,12 @@ struct message_t {
         * @param crypter       crypter to decrypt encryption payloads
         * @param signer        signer to verifiy a message with an encryption payload
         * @return
-        *                                      - SUCCESS if header could be parsed
+        *                                      - SUCCESS if parsing successful
         *                                      - NOT_SUPPORTED if ciritcal unknown payloads found
-        *                                      - FAILED if message type is not suppported!
-        *                                      - PARSE_ERROR if corrupted/invalid data found
-        *                                      - VERIFY_ERROR if verification of some payload failed
+        *                                      - NOT_SUPPORTED if message type is not supported!
+        *                                      - PARSE_ERROR if message parsing failed
+        *                                      - VERIFY_ERROR if message verification failed (bad syntax)
+        *                                      - FAILED if integrity check failed
         *                                      - INVALID_STATE if crypter/signer not supplied, but needed
         */
        status_t (*parse_body) (message_t *this, crypter_t *crypter, signer_t *signer);
@@ -238,10 +234,12 @@ struct message_t {
         * message.
         * Crypter/signer can be omitted (by passing NULL) when no encryption 
         * payload is expected.
+        * Generation is only done once, multiple calls will just return a packet copy.
         *
         * @param this          message_t object
         * @param crypter       crypter to use when a payload must be encrypted
         * @param signer        signer to build a mac
+        * @param packet        copy of generated packet
         * @return
         *                                      - SUCCESS if packet could be generated
         *                                      - INVALID_STATE if exchange type is currently not set
@@ -322,19 +320,6 @@ struct message_t {
        chunk_t (*get_packet_data) (message_t *this);
        
        /**
-        * @brief Check if a message is encoded.
-        *
-        * Check if the packet is in a generated (and encrypted) form available
-        * and can be passed down to the socket. If not, it has to be generated
-        * first.
-        *
-        * @param this          message_t object
-        * @return                      TRUE if encoded, FALSE if not
-        */     
-       bool (*is_encoded) (message_t *this);
-       
-       
-       /**
         * @brief Destroys a message and all including objects.
         *
         * @param this          message_t object
index 18bf24d..1df30e1 100644 (file)
@@ -291,4 +291,4 @@ cert_payload_t *cert_payload_create_from_x509(x509_t *cert)
        this->set_cert_encoding(this, CERT_X509_SIGNATURE);
        this->set_data(this, cert->get_certificate(cert));
        return this;
-}
\ No newline at end of file
+}
index 0c92e03..02af601 100644 (file)
@@ -216,9 +216,7 @@ static void set_key_exchange_data(private_ke_payload_t *this, chunk_t key_exchan
                
        }
        
-       this->key_exchange_data.ptr = clalloc(key_exchange_data.ptr,key_exchange_data.len);
-
-       this->key_exchange_data.len = key_exchange_data.len;
+       this->key_exchange_data = chunk_clone(key_exchange_data);
        this->compute_length(this);
 }
 
@@ -268,9 +266,22 @@ ke_payload_t *ke_payload_create()
        this->critical = FALSE;
        this->next_payload = NO_PAYLOAD;
        this->payload_length = KE_PAYLOAD_HEADER_LENGTH;
-       this->key_exchange_data.ptr = NULL;
-       this->key_exchange_data.len = 0;
-       this->dh_group_number = 0;
+       this->key_exchange_data = CHUNK_INITIALIZER;
+       this->dh_group_number = MODP_NONE;
+
+       return &this->public;
+}
 
-       return (&(this->public));
+/*
+ * Described in header
+ */
+ke_payload_t *ke_payload_create_from_diffie_hellman(diffie_hellman_t *dh)
+{
+       private_ke_payload_t *this = (private_ke_payload_t*)ke_payload_create();
+       
+       dh->get_my_public_value(dh, &this->key_exchange_data);
+       this->dh_group_number = dh->get_dh_group(dh);
+       this->compute_length(this);
+       
+       return &this->public;
 }
index 9490bef..43a55fd 100644 (file)
@@ -27,6 +27,8 @@
 #include <encoding/payloads/payload.h>
 #include <encoding/payloads/transform_substructure.h>
 #include <utils/linked_list.h>
+#include <crypto/diffie_hellman.h>
+
 /**
  * KE payload length in bytes without any key exchange data.
  * 
@@ -106,5 +108,14 @@ struct ke_payload_t {
  */
 ke_payload_t *ke_payload_create(void);
 
+/**
+ * @brief Creates a ke_payload_t from a diffie_hellman_t
+ * 
+ * @param diffie_hellman       diffie hellman object containing group and key
+ * @return                                     ke_payload_t object
+ * 
+ * @ingroup payloads
+ */
+ke_payload_t *ke_payload_create_from_diffie_hellman(diffie_hellman_t *diffie_hellman);
 
-#endif /*KE_PAYLOAD_H_*/
+#endif /* KE_PAYLOAD_H_ */
index e875fb2..9365bb5 100644 (file)
 #include <encoding/payloads/payload.h>
 
 /**
+ * Nonce size in bytes for nonces sending to other peer.
+ * 
+ * @warning Nonce size MUST be between 16 and 256 bytes.
+ * 
+ * @ingroup payloads
+ */
+#define NONCE_SIZE 16
+
+/**
  * Length of a nonce payload without a nonce in bytes.
  * 
  * @ingroup payloads
index 4242b4c..7d032ec 100644 (file)
 #include <daemon.h>
 #include <encoding/payloads/encodings.h>
 
+#define SHA1_HASH_SIZE 20
+
 /** 
- * String mappings for notify_message_type_t.
+ * String mappings for notify_type_t.
  */
-mapping_t notify_message_type_m[] = {
+mapping_t notify_type_m[] = {
        {UNSUPPORTED_CRITICAL_PAYLOAD, "UNSUPPORTED_CRITICAL_PAYLOAD"},
        {INVALID_IKE_SPI, "INVALID_IKE_SPI"},
        {INVALID_MAJOR_VERSION, "INVALID_MAJOR_VERSION"},
@@ -94,7 +96,7 @@ struct private_notify_payload_t {
        /**
         * Notify message type.
         */
-       u_int16_t notify_message_type;
+       u_int16_t notify_type;
        
        /**
         * Security parameter index (spi).
@@ -146,7 +148,7 @@ encoding_rule_t notify_payload_encodings[] = {
        /* SPI Size as 8 bit field*/
        { SPI_SIZE,                     offsetof(private_notify_payload_t, spi_size)                    },
        /* Notify message type as 16 bit field*/
-       { U_INT_16,                     offsetof(private_notify_payload_t, notify_message_type) },
+       { U_INT_16,                     offsetof(private_notify_payload_t, notify_type) },
        /* SPI as variable length field*/
        { SPI,                          offsetof(private_notify_payload_t, spi)                                 },
        /* Key Exchange Data is from variable size */
@@ -195,31 +197,60 @@ static status_t verify(private_notify_payload_t *this)
                        return FAILED;
        }
        
-       /* TODO: Check all kinds of notify */
-       if (this->notify_message_type == INVALID_KE_PAYLOAD)
+       switch (this->notify_type)
        {
-               /* check notification data */
-               diffie_hellman_group_t dh_group;
-               if (this->notification_data.len != 2)
+               case INVALID_KE_PAYLOAD:
                {
-                       return FAILED;
+                       /* check notification data */
+                       diffie_hellman_group_t dh_group;
+                       if (this->notification_data.len != 2)
+                       {
+                               return FAILED;
+                       }
+                       dh_group = ntohs(*((u_int16_t*)this->notification_data.ptr));
+                       switch (dh_group)
+                       {
+                               case MODP_768_BIT:
+                               case MODP_1024_BIT:
+                               case MODP_1536_BIT:
+                               case MODP_2048_BIT:
+                               case MODP_3072_BIT:
+                               case MODP_4096_BIT:
+                               case MODP_6144_BIT:
+                               case MODP_8192_BIT:
+                                       break;
+                               default:
+                                       this->logger->log(this->logger, ERROR, "Bad DH group (%d)", dh_group);
+                                       return FAILED;
+                       }
+                       break;
                }
-               dh_group = ntohs(*((u_int16_t*)this->notification_data.ptr));
-               switch (dh_group)
+               case NAT_DETECTION_SOURCE_IP:
+               case NAT_DETECTION_DESTINATION_IP:
                {
-                       case MODP_768_BIT:
-                       case MODP_1024_BIT:
-                       case MODP_1536_BIT:
-                       case MODP_2048_BIT:
-                       case MODP_3072_BIT:
-                       case MODP_4096_BIT:
-                       case MODP_6144_BIT:
-                       case MODP_8192_BIT:
-                               break;
-                       default:
-                               this->logger->log(this->logger, ERROR, "Bad DH group (%d)", dh_group);
+                       if (this->notification_data.len != SHA1_HASH_SIZE)
+                       {
+                               this->logger->log(this->logger, ERROR, "invalid %s notify length",
+                                                                 mapping_find(notify_type_m, this->notify_type));
+                               return FAILED;
+                       }
+                       break;
+               }
+               case INVALID_SYNTAX:
+               case INVALID_MAJOR_VERSION:
+               case NO_PROPOSAL_CHOSEN:
+               {
+                       if (this->notification_data.len != 0)
+                       {
+                               this->logger->log(this->logger, ERROR, "invalid %s notify",
+                                                                 mapping_find(notify_type_m, this->notify_type));
                                return FAILED;
+                       }
+                       break;
                }
+               default:
+                       /* TODO: verify */
+                       break;
        }
        return SUCCESS;
 }
@@ -300,19 +331,19 @@ static void set_protocol_id(private_notify_payload_t *this, u_int8_t protocol_id
 }
 
 /**
- * Implementation of notify_payload_t.get_notify_message_type.
+ * Implementation of notify_payload_t.get_notify_type.
  */
-static notify_message_type_t get_notify_message_type(private_notify_payload_t *this)
+static notify_type_t get_notify_type(private_notify_payload_t *this)
 {
-       return this->notify_message_type;
+       return this->notify_type;
 }
 
 /**
- * Implementation of notify_payload_t.set_notify_message_type.
+ * Implementation of notify_payload_t.set_notify_type.
  */
-static void set_notify_message_type(private_notify_payload_t *this, u_int16_t notify_message_type)
+static void set_notify_type(private_notify_payload_t *this, u_int16_t notify_type)
 {
-       this->notify_message_type = notify_message_type;
+       this->notify_type = notify_type;
 }
 
 /**
@@ -363,20 +394,9 @@ static chunk_t get_notification_data(private_notify_payload_t *this)
  */
 static status_t set_notification_data(private_notify_payload_t *this, chunk_t notification_data)
 {
-       /* destroy existing data first */
-       if (this->notification_data.ptr != NULL)
-       {
-               /* free existing value */
-               free(this->notification_data.ptr);
-               this->notification_data.ptr = NULL;
-               this->notification_data.len = 0;
-               
-       }
-       
-       this->notification_data.ptr = clalloc(notification_data.ptr,notification_data.len);
-       this->notification_data.len = notification_data.len;
+       chunk_free(&this->notification_data);
+       this->notification_data = chunk_clone(notification_data);
        this->compute_length(this);
-       
        return SUCCESS;
 }
 
@@ -385,14 +405,8 @@ static status_t set_notification_data(private_notify_payload_t *this, chunk_t no
  */
 static status_t destroy(private_notify_payload_t *this)
 {
-       if (this->notification_data.ptr != NULL)
-       {
-               free(this->notification_data.ptr);
-       }
-       if (this->spi.ptr != NULL)
-       {
-               free(this->spi.ptr);
-       }
+       chunk_free(&this->notification_data);
+       chunk_free(&this->spi);
        free(this);
        return SUCCESS;
 }
@@ -416,8 +430,8 @@ notify_payload_t *notify_payload_create()
        /* public functions */
        this->public.get_protocol_id = (u_int8_t (*) (notify_payload_t *)) get_protocol_id;
        this->public.set_protocol_id  = (void (*) (notify_payload_t *,u_int8_t)) set_protocol_id;
-       this->public.get_notify_message_type = (notify_message_type_t (*) (notify_payload_t *)) get_notify_message_type;
-       this->public.set_notify_message_type = (void (*) (notify_payload_t *,notify_message_type_t)) set_notify_message_type;
+       this->public.get_notify_type = (notify_type_t (*) (notify_payload_t *)) get_notify_type;
+       this->public.set_notify_type = (void (*) (notify_payload_t *,notify_type_t)) set_notify_type;
        this->public.get_spi = (u_int32_t (*) (notify_payload_t *)) get_spi;
        this->public.set_spi = (void (*) (notify_payload_t *,u_int32_t)) set_spi;
        this->public.get_notification_data = (chunk_t (*) (notify_payload_t *)) get_notification_data;
@@ -432,7 +446,7 @@ notify_payload_t *notify_payload_create()
        this->next_payload = NO_PAYLOAD;
        this->payload_length = NOTIFY_PAYLOAD_HEADER_LENGTH;
        this->protocol_id = 0;
-       this->notify_message_type = 0;
+       this->notify_type = 0;
        this->spi.ptr = NULL;
        this->spi.len = 0;
        this->spi_size = 0;
@@ -440,17 +454,17 @@ notify_payload_t *notify_payload_create()
        this->notification_data.len = 0;
        this->logger = logger_manager->get_logger(logger_manager, PAYLOAD);
 
-       return (&(this->public));
+       return &this->public;
 }
 
 /*
  * Described in header.
  */
-notify_payload_t *notify_payload_create_from_protocol_and_type(protocol_id_t protocol_id, notify_message_type_t notify_message_type)
+notify_payload_t *notify_payload_create_from_protocol_and_type(protocol_id_t protocol_id, notify_type_t notify_type)
 {
        notify_payload_t *notify = notify_payload_create();
 
-       notify->set_notify_message_type(notify,notify_message_type);
+       notify->set_notify_type(notify,notify_type);
        notify->set_protocol_id(notify,protocol_id);
        
        return notify;
index 2d2e4ba..660fdcb 100644 (file)
@@ -37,7 +37,7 @@
  */
 #define NOTIFY_PAYLOAD_HEADER_LENGTH 8
 
-typedef enum notify_message_type_t notify_message_type_t;
+typedef enum notify_type_t notify_type_t;
 
 
 /** 
@@ -47,7 +47,7 @@ typedef enum notify_message_type_t notify_message_type_t;
  * 
  * @ingroup payloads
  */
-enum notify_message_type_t {
+enum notify_type_t {
        UNSUPPORTED_CRITICAL_PAYLOAD = 1,
        INVALID_IKE_SPI = 4,
        INVALID_MAJOR_VERSION = 5,
@@ -72,11 +72,11 @@ enum notify_message_type_t {
 };
 
 /** 
- * String mappings for notify_message_type_t.
+ * String mappings for notify_type_t.
  * 
  * @ingroup payloads
  */
-extern mapping_t notify_message_type_m[];
+extern mapping_t notify_type_m[];
 
 
 typedef struct notify_payload_t notify_payload_t;
@@ -122,7 +122,7 @@ struct notify_payload_t {
         * @param this          calling notify_payload_t object
         * @return                      notify message type of this payload
         */
-       notify_message_type_t (*get_notify_message_type) (notify_payload_t *this);
+       notify_type_t (*get_notify_type) (notify_payload_t *this);
 
        /**
         * @brief Sets notify message type of this payload.
@@ -130,7 +130,7 @@ struct notify_payload_t {
         * @param this          calling notify_payload_t object
         * @param type          notify message type to set
         */
-       void (*set_notify_message_type) (notify_payload_t *this, notify_message_type_t type);
+       void (*set_notify_type) (notify_payload_t *this, notify_type_t type);
 
        /**
         * @brief Returns the currently set spi of this payload.
@@ -193,12 +193,12 @@ notify_payload_t *notify_payload_create(void);
  * @brief Creates an notify_payload_t object of specific type for specific protocol id.
  * 
  * @param protocol_id                  protocol id (IKE, AH or ESP)
- * @param notify_message_type  notify type (see notify_message_type_t)
+ * @param type                                 notify type (see notify_type_t)
  * @return                                             notify_payload_t object
  * 
  * @ingroup payloads
  */
-notify_payload_t *notify_payload_create_from_protocol_and_type(protocol_id_t protocol_id, notify_message_type_t notify_message_type);
+notify_payload_t *notify_payload_create_from_protocol_and_type(protocol_id_t protocol_id, notify_type_t type);
 
 
 #endif /*NOTIFY_PAYLOAD_H_*/
index be58adf..13e7515 100644 (file)
@@ -74,6 +74,37 @@ mapping_t payload_type_m[] = {
 };
 
 /*
+ * build the short mappings for payload_type_t
+ */
+mapping_t payload_type_short_m[] = {
+       {NO_PAYLOAD, "--"},
+       {SECURITY_ASSOCIATION, "SA"},
+       {KEY_EXCHANGE, "KE"},
+       {ID_INITIATOR, "IDi"},
+       {ID_RESPONDER, "IDr"},
+       {CERTIFICATE, "CERT"},
+       {CERTIFICATE_REQUEST, "CERTREQ"},
+       {AUTHENTICATION, "AUTH"},
+       {NONCE, "No"},
+       {NOTIFY, "N"},
+       {DELETE, "D"},
+       {VENDOR_ID, "V"},
+       {TRAFFIC_SELECTOR_INITIATOR, "TSi"},
+       {TRAFFIC_SELECTOR_RESPONDER, "TSr"},
+       {ENCRYPTED, "E"},
+       {CONFIGURATION, "CP"},
+       {EXTENSIBLE_AUTHENTICATION, "EAP"},
+       {HEADER, "HDR"},
+       {PROPOSAL_SUBSTRUCTURE, "PROP"},
+       {TRANSFORM_SUBSTRUCTURE, "TRANS"},
+       {TRANSFORM_ATTRIBUTE, "TRANSATTR"},
+       {TRAFFIC_SELECTOR_SUBSTRUCTURE, "TSSUB"},
+       {CONFIGURATION_ATTRIBUTE, "CPATTR"},
+       {UNKNOWN_PAYLOAD, "??"},
+       {MAPPING_END, NULL}
+};
+
+/*
  * see header
  */
 payload_t *payload_create(payload_type_t type)
index bc593f6..68e22b3 100644 (file)
@@ -188,6 +188,11 @@ enum payload_type_t{
  */
 extern mapping_t payload_type_m[];
 
+/**
+ * Special string mappings for payload_type_t in a short form.
+ */
+extern mapping_t payload_type_short_m[];
+
 
 typedef struct payload_t payload_t;
 
index f72fbb1..e7a4058 100644 (file)
@@ -632,15 +632,11 @@ proposal_substructure_t *proposal_substructure_create_from_proposal(proposal_t *
        iterator->destroy(iterator);
        
        /* take over general infos */
-       this->spi_size = proposal->get_protocol(proposal) == PROTO_IKE ? 8 : 4;
+       this->spi_size = proposal->get_protocol(proposal) == PROTO_IKE ? 0 : 4;
        this->spi.len = this->spi_size;
-       this->spi.ptr = malloc(this->spi_size);
-       if (this->spi_size == 8)
-       {
-               *((u_int64_t*)this->spi.ptr) = proposal->get_spi(proposal);
-       }
-       else
+       if (this->spi_size == 4)
        {
+               this->spi.ptr = malloc(this->spi_size);
                *((u_int32_t*)this->spi.ptr) = proposal->get_spi(proposal);
        }
        this->proposal_number = 0;
index 0c752b8..8e5022d 100644 (file)
@@ -303,7 +303,7 @@ static linked_list_t *get_proposals(private_sa_payload_t *this)
                        if (ignore_struct_number < struct_number)
                        {
                                /* remova an already added, if first of series */
-                               proposal_list->remove_last(proposal_list, (void**)proposal);
+                               proposal_list->remove_last(proposal_list, (void**)&proposal);
                                proposal->destroy(proposal);
                                ignore_struct_number = struct_number;
                        }
index ce01418..7578d57 100644 (file)
@@ -50,11 +50,11 @@ struct private_interfaces_t {
 };
 
 /**
- * Implements interfaces_t.get_addresses
+ * Implements interfaces_t.create_address_iterator
  */
-static linked_list_t* get_addresses(private_interfaces_t *this)
+static iterator_t* create_address_iterator(private_interfaces_t *this)
 {
-       return this->addresses;
+       return this->addresses->create_iterator(this->addresses, TRUE);
 }
        
 /**
@@ -138,7 +138,7 @@ interfaces_t *interfaces_create(u_int16_t port)
 
        this->port = port;
        
-       this->public.get_addresses = (linked_list_t* (*) (interfaces_t*)) get_addresses;
+       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;
 
index 6500460..33143e0 100644 (file)
@@ -41,12 +41,12 @@ typedef struct interfaces_t interfaces_t;
 struct interfaces_t {
 
        /**
-        * @brief Get addresses of local interfaces
+        * @brief Get an iterator over addresses of local interfaces
         *
         * @param this          calling object
-        * @return                      linked_list_t of host_t objects
+        * @return                      iterator over host_t objects
         */
-       linked_list_t* (*get_addresses) (interfaces_t *ifaces);
+       iterator_t* (*create_address_iterator) (interfaces_t *this);
        
        /**
         * @brief Check if address is associated with a local interface
@@ -55,7 +55,7 @@ struct interfaces_t {
         * @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 *ifaces, host_t *host);
+       bool (*is_local_address) (interfaces_t *this, host_t *host);
        
        /**
         * @brief Destroy the object, freeing contained data.
@@ -77,4 +77,4 @@ struct interfaces_t {
 interfaces_t *interfaces_create(u_int16_t port);
 
 
-#endif /*INTERFACES_H_*/
+#endif /* INTERFACES_H_ */
index 0d5470c..78c793e 100644 (file)
@@ -164,7 +164,7 @@ static status_t receiver(private_socket_t *this, packet_t **packet)
        pkt->set_source(pkt, source);
        pkt->set_destination(pkt, dest);
 
-       this->logger->log(this->logger, CONTROL, "received packet: from %s:%d to %s:%d",
+       this->logger->log(this->logger, CONTROL|LEVEL1, "received packet: from %s:%d to %s:%d",
                                          source->get_address(source), source->get_port(source),
                                          dest->get_address(dest), dest->get_port(dest));
 
@@ -202,7 +202,7 @@ status_t sender(private_socket_t *this, packet_t *packet)
        dst = packet->get_destination(packet);
        data = packet->get_data(packet);
 
-       this->logger->log(this->logger, CONTROL, "sending packet: from %s:%d to %s:%d",
+       this->logger->log(this->logger, CONTROL|LEVEL1, "sending packet: from %s:%d to %s:%d",
                                          src->get_address(src), src->get_port(src),
                                          dst->get_address(dst), dst->get_port(dst));
        
index c817834..864711b 100644 (file)
@@ -60,40 +60,27 @@ static job_type_t get_type(private_delete_half_open_ike_sa_job_t *this)
 static status_t execute(private_delete_half_open_ike_sa_job_t *this)
 {
        ike_sa_t *ike_sa;
-       status_t status;
        
-       status = charon->ike_sa_manager->checkout(charon->ike_sa_manager, this->ike_sa_id, &ike_sa);
-       if ((status != SUCCESS) && (status != CREATED))
+       if (charon->ike_sa_manager->checkout(charon->ike_sa_manager, this->ike_sa_id, 
+                                                                                &ike_sa) != SUCCESS)
        {
-               this->logger->log(this->logger, CONTROL | LEVEL3, "IKE SA seems to be already deleted");
                return DESTROY_ME;
        }
        
        switch (ike_sa->get_state(ike_sa))
        {
-               case INITIATOR_INIT:
-               case RESPONDER_INIT:
-               case IKE_SA_INIT_REQUESTED:
-               case IKE_SA_INIT_RESPONDED:
-               case IKE_AUTH_REQUESTED:
-               case DELETE_IKE_SA_REQUESTED:
+               case SA_ESTABLISHED:
                {
-                       /* IKE_SA is half open and gets deleted! */
-                       status = charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa);
-                       if (status != SUCCESS)
-                       {
-                               this->logger->log(this->logger, ERROR, "Could not checkin and delete checked out IKE_SA!");
-                       }
+                       /* IKE_SA is established and so is not getting destroyed */
+                       charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
                        return DESTROY_ME;
                }
                default:
                {
-                       /* IKE_SA is established and so is not getting deleted! */
-                       status = charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
-                       if (status != SUCCESS)
-                       {
-                               this->logger->log(this->logger, ERROR, "Could not checkin a checked out IKE_SA!");
-                       }
+                       /* IKE_SA is half open and gets destroyed */
+                       this->logger->log(this->logger, AUDIT,
+                                                         "deleting half open IKE_SA after timeout");
+                       charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa);
                        return DESTROY_ME;
                }
        }
index b26750c..ff4f522 100644 (file)
@@ -34,7 +34,7 @@ typedef struct delete_half_open_ike_sa_job_t delete_half_open_ike_sa_job_t;
  * @brief Class representing an DELETE_HALF_OPEN_IKE_SA Job.
  * 
  * This job is responsible for deleting of half open IKE_SAs. A half 
- * open IKE_SA is every IKE_SA which hasn't reache the ike_sa_established
+ * open IKE_SA is every IKE_SA which hasn't reache the SA_ESTABLISHED
  * state.
  * 
  * @b Constructors:
@@ -43,6 +43,7 @@ typedef struct delete_half_open_ike_sa_job_t delete_half_open_ike_sa_job_t;
  * @ingroup jobs
  */
 struct delete_half_open_ike_sa_job_t {
+       
        /**
         * The job_t interface.
         */
@@ -59,4 +60,4 @@ struct delete_half_open_ike_sa_job_t {
  */
 delete_half_open_ike_sa_job_t *delete_half_open_ike_sa_job_create(ike_sa_id_t *ike_sa_id);
 
-#endif /*DELETE_HALF_OPEN_IKE_SA_JOB_H_*/
+#endif /* DELETE_HALF_OPEN_IKE_SA_JOB_H_ */
index fbd52b7..fa6eb33 100644 (file)
@@ -57,6 +57,47 @@ static job_type_t get_type(private_incoming_packet_job_t *this)
 }
 
 /**
+ * send a notify back to the sender
+ */
+static void send_notify_response(private_incoming_packet_job_t *this,
+                                                                message_t *request,
+                                                                notify_type_t type)
+{
+       notify_payload_t *notify;
+       message_t *response;
+       host_t *src, *dst;
+       packet_t *packet;
+       ike_sa_id_t *ike_sa_id;
+       
+       ike_sa_id = request->get_ike_sa_id(request);
+       ike_sa_id = ike_sa_id->clone(ike_sa_id);
+       ike_sa_id->switch_initiator(ike_sa_id);
+       
+       response = message_create();
+       dst = request->get_source(request);
+       src = request->get_destination(request);
+       response->set_source(response, src->clone(src));
+       response->set_destination(response, dst->clone(dst));
+       response->set_exchange_type(response, IKE_SA_INIT);
+       response->set_request(response, FALSE);
+       response->set_message_id(response, 0);
+       response->set_ike_sa_id(response, ike_sa_id);
+       notify = notify_payload_create_from_protocol_and_type(PROTO_NONE, type);
+       response->add_payload(response, (payload_t *)notify);
+       if (response->generate(response, NULL, NULL, &packet) != SUCCESS)
+       {
+               response->destroy(response);
+               return;
+       }
+       this->logger->log(this->logger, CONTROL, "sending %s notify",
+                                         mapping_find(notify_type_m, type)); 
+       charon->send_queue->add(charon->send_queue, packet);
+       response->destroy(response);
+       ike_sa_id->destroy(ike_sa_id);
+       return;
+}
+
+/**
  * Implementation of job_t.execute.
  */
 static status_t execute(private_incoming_packet_job_t *this)
@@ -65,104 +106,55 @@ static status_t execute(private_incoming_packet_job_t *this)
        ike_sa_t *ike_sa;
        ike_sa_id_t *ike_sa_id;
        status_t status;
-       packet_t *packet;
+       host_t *src, *dst;
        
        message = message_create_from_packet(this->packet->clone(this->packet));
+       src = message->get_source(message);
+       dst = message->get_destination(message);
+       this->logger->log(this->logger, CONTROL, "received packet: from %s:%d to %s:%d",
+                                         src->get_address(src), src->get_port(src),
+                                         dst->get_address(dst), dst->get_port(dst));
+       
        status = message->parse_header(message);
        if (status != SUCCESS)
        {
-               this->logger->log(this->logger, ERROR, "Message header could not be verified!");
+               this->logger->log(this->logger, ERROR, "received message with invalid IKE header, ignored");
                message->destroy(message);
                return DESTROY_ME;
        }
        
-       this->logger->log(this->logger, CONTROL|LEVEL2, "Message is a %s %s", 
-                                         mapping_find(exchange_type_m, message->get_exchange_type(message)),
-                                         message->get_request(message) ? "request" : "reply");
-       
        if ((message->get_major_version(message) != IKE_MAJOR_VERSION) ||
                (message->get_minor_version(message) != IKE_MINOR_VERSION))
        {
-               this->logger->log(this->logger, ERROR | LEVEL2,
-                                                 "IKE version %d.%d not supported",
+               this->logger->log(this->logger, ERROR,
+                                                 "received a packet with IKE version %d.%d, not supported",
                                                  message->get_major_version(message),
                                                  message->get_minor_version(message));
                if ((message->get_exchange_type(message) == IKE_SA_INIT) && (message->get_request(message)))
                {
-                       notify_payload_t *notify;
-                       message_t *response;
-                       host_t *src, *dst;
-                       
-                       message->get_ike_sa_id(message, &ike_sa_id);
-                       ike_sa_id->switch_initiator(ike_sa_id);
-                       
-                       response = message_create();
-                       src = message->get_source(message);
-                       dst = message->get_destination(message);
-                       response->set_source(response, src->clone(src));
-                       response->set_destination(response, dst->clone(dst));
-                       response->set_exchange_type(response, IKE_SA_INIT);
-                       response->set_request(response, FALSE);
-                       response->set_message_id(response, 0);
-                       response->set_ike_sa_id(response, ike_sa_id);
-                       
-                       notify = notify_payload_create_from_protocol_and_type(PROTO_NONE, INVALID_MAJOR_VERSION);
-                       response->add_payload(response, (payload_t *)notify);
-                       
-                       status = response->generate(response, NULL, NULL, &packet);
-                       if (status != SUCCESS)
-                       {
-                               this->logger->log(this->logger, ERROR, "Could not generate packet from message");
-                               response->destroy(response);
-                               return DESTROY_ME;
-                       }
-                       this->logger->log(this->logger, ERROR, "Send notify reply of type INVALID_MAJOR_VERSION"); 
-                       charon->send_queue->add(charon->send_queue, packet);
-                       response->destroy(response);
-                       return DESTROY_ME;
+                       send_notify_response(this, message, INVALID_MAJOR_VERSION);
                }
                message->destroy(message);
                return DESTROY_ME;
        }
        
-       message->get_ike_sa_id(message, &ike_sa_id);
+       ike_sa_id = message->get_ike_sa_id(message);
+       ike_sa_id = ike_sa_id->clone(ike_sa_id);
        ike_sa_id->switch_initiator(ike_sa_id);
-       this->logger->log(this->logger, CONTROL|LEVEL3, "Checking out IKE SA %lld:%lld, role %s", 
-                                         ike_sa_id->get_initiator_spi(ike_sa_id),
-                                         ike_sa_id->get_responder_spi(ike_sa_id),
-                                         ike_sa_id->is_initiator(ike_sa_id) ? "initiator" : "responder");
-       
        status = charon->ike_sa_manager->checkout(charon->ike_sa_manager, ike_sa_id, &ike_sa);
-       if ((status != SUCCESS) && (status != CREATED))
+       if (status != SUCCESS)
        {
-               this->logger->log(this->logger, ERROR, "IKE SA could not be checked out");
+               this->logger->log(this->logger, ERROR,
+                                                 "received packet with SPIs %llx:%llx, but no such IKE_SA",
+                                                 ike_sa_id->get_initiator_spi(ike_sa_id),
+                                                 ike_sa_id->get_responder_spi(ike_sa_id));
+               send_notify_response(this, message, INVALID_IKE_SPI);
                ike_sa_id->destroy(ike_sa_id);  
                message->destroy(message);
-               
-               /* TODO: send notify reply of type INVALID_IKE_SPI if SPI could not be found ? */
                return DESTROY_ME;
        }
-
-       if (status == CREATED)
-       {
-               job_t *delete_job;
-               this->logger->log(this->logger, CONTROL|LEVEL3, 
-                                                 "Create Job to delete half open IKE_SA.");
-               
-               delete_job = (job_t *) delete_half_open_ike_sa_job_create(ike_sa_id);
-               charon->event_queue->add_relative(charon->event_queue, delete_job, 
-                                                                                 charon->configuration->get_half_open_ike_sa_timeout(charon->configuration));
-       }
        
        status = ike_sa->process_message(ike_sa, message);
-       
-       this->logger->log(this->logger, CONTROL|LEVEL3, "%s IKE SA %lld:%lld, role %s", 
-                                         status == DESTROY_ME ? "Checkin and delete" : "Checkin",
-                                         ike_sa_id->get_initiator_spi(ike_sa_id),
-                                         ike_sa_id->get_responder_spi(ike_sa_id),
-                                         ike_sa_id->is_initiator(ike_sa_id) ? "initiator" : "responder");
-       ike_sa_id->destroy(ike_sa_id);
-       
        if (status == DESTROY_ME)
        {
                status = charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa);
@@ -171,11 +163,7 @@ static status_t execute(private_incoming_packet_job_t *this)
        {
                status = charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
        }
-       
-       if (status != SUCCESS)
-       {
-               this->logger->log(this->logger, ERROR, "Checkin of IKE SA failed!");
-       }
+       ike_sa_id->destroy(ike_sa_id);
        message->destroy(message);
        return DESTROY_ME;
 }
index 16e4407..6c1d7bf 100644 (file)
@@ -63,41 +63,28 @@ static job_type_t get_type(private_initiate_ike_sa_job_t *this)
  */
 static status_t execute(private_initiate_ike_sa_job_t *this)
 {
-       /*
-       * Initiatie an IKE_SA:
-       * - is defined by a name of a configuration
-       * - create an empty IKE_SA via manager
-       * - call initiate_connection on this sa
-       */
+       /* Initiatie an IKE_SA:
+        * - is defined by a connection
+        * - create an empty IKE_SA via manager
+        * - call initiate() on this IKE_SA
+        */
        ike_sa_t *ike_sa;
        status_t status;
-       job_t *delete_job;
        
        this->logger->log(this->logger, CONTROL|LEVEL2, "Creating and checking out IKE SA");
        charon->ike_sa_manager->create_and_checkout(charon->ike_sa_manager, &ike_sa);
        
-       status = ike_sa->initiate_connection(ike_sa, this->connection->clone(this->connection));
+       status = ike_sa->initiate(ike_sa, this->connection->clone(this->connection));
        if (status != SUCCESS)
        {
-               this->logger->log(this->logger, ERROR, "Initiation returned %s, going to delete IKE_SA.", 
-                                                                mapping_find(status_m, status));
+               this->logger->log(this->logger, ERROR,
+                                                 "initiation returned %s, going to delete IKE_SA.",
+                                                 mapping_find(status_m, status));
                charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa);
                return DESTROY_ME;
        }
        
-       this->logger->log(this->logger, CONTROL|LEVEL3, "Create Job to delete half open IKE_SA.");
-       
-       delete_job = (job_t *) delete_half_open_ike_sa_job_create(ike_sa->get_id(ike_sa));
-       charon->event_queue->add_relative(charon->event_queue, delete_job, 
-                       charon->configuration->get_half_open_ike_sa_timeout(charon->configuration));
-
-       this->logger->log(this->logger, CONTROL|LEVEL2, "Checking in IKE SA");
-       status = charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
-       if (status != SUCCESS)
-       {
-               this->logger->log(this->logger, ERROR, "Could not checkin IKE_SA (%s)", 
-                                                                mapping_find(status_m, status));
-       }
+       charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
        return DESTROY_ME;
 }
 
index 40f2ffd..7c2d742 100644 (file)
@@ -46,11 +46,6 @@ struct private_retransmit_request_job_t {
        ike_sa_id_t *ike_sa_id;
        
        /**
-        * Number of times a request was retransmitted
-        */
-       u_int32_t retransmit_count;
-       
-       /**
         * Logger reference
         */
        logger_t *logger;
@@ -69,79 +64,27 @@ static job_type_t get_type(private_retransmit_request_job_t *this)
  */
 static status_t execute(private_retransmit_request_job_t *this)
 {
-       bool stop_retransmitting = FALSE, timed_out = FALSE;
-       u_int32_t timeout;
        ike_sa_t *ike_sa;
        status_t status;
-       
-       this->logger->log(this->logger, CONTROL|LEVEL2, "Checking out IKE SA %lld:%lld, role %s", 
-                                         this->ike_sa_id->get_initiator_spi(this->ike_sa_id),
-                                         this->ike_sa_id->get_responder_spi(this->ike_sa_id),
-                                         this->ike_sa_id->is_initiator(this->ike_sa_id) ? "initiator" : "responder");
                                
        status = charon->ike_sa_manager->checkout(charon->ike_sa_manager, this->ike_sa_id, &ike_sa);
-       if ((status != SUCCESS) && (status != CREATED))
+       if (status != SUCCESS)
        {
                this->logger->log(this->logger, ERROR|LEVEL1, 
                                                  "IKE SA could not be checked out. Already deleted?");
                return DESTROY_ME;
        }
        
-       this->retransmit_count++;
-       status = charon->configuration->get_retransmit_timeout(charon->configuration,
-                       this->retransmit_count, &timeout);
-       timed_out = (status != SUCCESS);
-       
-       if (ike_sa->retransmit_possible(ike_sa, this->message_id))
+       if (ike_sa->retransmit_request(ike_sa, this->message_id) == DESTROY_ME)
        {
-               if (!timed_out)
-               {
-                       status = ike_sa->retransmit_request(ike_sa, this->message_id);
-                       if (status != SUCCESS)
-                       {
-                               this->logger->log(this->logger, CONTROL|LEVEL3, 
-                                                                                "Message doesn't have to be retransmitted");
-                               stop_retransmitting = TRUE;
-                       }
-               }
+               /* retransmission hopeless, kill SA */
+               charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa);
        }
        else
        {
-               stop_retransmitting = TRUE;
-       }
-
-       this->logger->log(this->logger, CONTROL|LEVEL2, "Checkin IKE SA %lld:%lld, role %s", 
-                                         this->ike_sa_id->get_initiator_spi(this->ike_sa_id),
-                                         this->ike_sa_id->get_responder_spi(this->ike_sa_id),
-                                         this->ike_sa_id->is_initiator(this->ike_sa_id) ? "initiator" : "responder");
-
-       status = charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
-       if (status != SUCCESS)
-       {
-               this->logger->log(this->logger, ERROR, "Checkin of IKE SA failed!");
-       }
-
-       if (timed_out)
-       {
-               /*
-                * XXX: We should act depending on DPD policy here, or not act at all.
-                */
-               this->logger->log(this->logger, CONTROL|LEVEL2, "Timeout: Deleting SA!");
-               status = charon->ike_sa_manager->delete(charon->ike_sa_manager, this->ike_sa_id);
-               if (status != SUCCESS)
-               {
-                       this->logger->log(this->logger, ERROR|LEVEL1, "Cannot delete SA!");
-               }
-               return DESTROY_ME;
-       }
-       
-       if (stop_retransmitting)
-       {
-               return DESTROY_ME;
+               charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
        }
-       
-       charon->event_queue->add_relative(charon->event_queue, (job_t *)this, timeout);
-       return SUCCESS;
+       return DESTROY_ME;
 }
 
 /**
@@ -167,7 +110,6 @@ retransmit_request_job_t *retransmit_request_job_create(u_int32_t message_id,ike
 
        /* private variables */
        this->message_id = message_id;
-       this->retransmit_count = 0;
        this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
        this->logger = logger_manager->get_logger(logger_manager, WORKER);
        
index 3c38110..56b1fac 100644 (file)
@@ -66,58 +66,23 @@ static status_t execute(private_send_dpd_job_t *this)
 {
        ike_sa_t *ike_sa;
        status_t status;
-       u_int32_t dt;
-       u_int32_t interval = charon->configuration->get_dpd_interval(charon->configuration);
-       struct timeval last_msg_tv, current_tv;
-
-       this->logger->log(this->logger, CONTROL|LEVEL2, "Checking out IKE SA %lld:%lld, role %s",
-                       this->ike_sa_id->get_initiator_spi(this->ike_sa_id),
-                       this->ike_sa_id->get_responder_spi(this->ike_sa_id),
-                       this->ike_sa_id->is_initiator(this->ike_sa_id) ? "initiator" : "responder");
        
        status = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
-                       this->ike_sa_id, &ike_sa);
+                                                                                         this->ike_sa_id, &ike_sa);
        if (status != SUCCESS)
        {
-               this->logger->log(this->logger, ERROR|LEVEL1,
-                               "IKE SA could not be checked out. Already deleted?");
                return DESTROY_ME;
        }
-
-       last_msg_tv = ike_sa->get_last_traffic_in_tv(ike_sa);
-       if (0 > gettimeofday(&current_tv, NULL) )
-       {
-               this->logger->log(this->logger, ERROR|LEVEL1,
-                               "Warning: Failed to get time of day.");
-       }
-       dt = (current_tv.tv_sec - last_msg_tv.tv_sec) * 1000
-          + (current_tv.tv_usec - last_msg_tv.tv_usec) / 1000;
-
-       if (dt >= interval)
+       status = ike_sa->send_dpd(ike_sa);
+       if (status == DESTROY_ME)
        {
-               ike_sa->send_dpd_request(ike_sa);
-               this->logger->log(this->logger, CONTROL|LEVEL1,
-                               "DPD request packet scheduled");
-
+               charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa);
        }
        else
        {
-               charon->event_queue->add_relative(charon->event_queue, (job_t*) this, interval - dt);
+               charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
        }
-
-       this->logger->log(this->logger, CONTROL|LEVEL2,
-                       "Checkin IKE SA %lld:%lld, role %s",
-                       this->ike_sa_id->get_initiator_spi(this->ike_sa_id),
-                       this->ike_sa_id->get_responder_spi(this->ike_sa_id),
-                       this->ike_sa_id->is_initiator(this->ike_sa_id) ? "initiator" : "responder");
-
-       status = charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
-       if (status != SUCCESS)
-       {
-               this->logger->log(this->logger, ERROR, "Checkin of IKE SA failed!");
-       }
-
-       return SUCCESS;
+       return DESTROY_ME;
 }
 
 /**
index f17296a..6c7dceb 100644 (file)
@@ -60,74 +60,22 @@ static job_type_t get_type(private_send_keepalive_job_t *this)
 }
 
 /**
- * Implementation of job_t.execute. 
+ * Implementation of job_t.execute.
  */ 
 static status_t execute(private_send_keepalive_job_t *this)
 {
        ike_sa_t *ike_sa;
        status_t status;
-       u_int32_t dt;
-       u_int32_t interval = charon->configuration->get_keepalive_interval(charon->configuration);
-       struct timeval last_msg_tv, current_tv;
-       packet_t *packet;
-       host_t *host;
-       connection_t *connection;
-       chunk_t data;
-
-       this->logger->log(this->logger, CONTROL|LEVEL2, "Checking out IKE SA %lld:%lld, role %s",
-                       this->ike_sa_id->get_initiator_spi(this->ike_sa_id),
-                       this->ike_sa_id->get_responder_spi(this->ike_sa_id),
-                       this->ike_sa_id->is_initiator(this->ike_sa_id) ? "initiator" : "responder");
        
        status = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
-                       this->ike_sa_id, &ike_sa);
+                                                                                         this->ike_sa_id, &ike_sa);
        if (status != SUCCESS)
        {
-               this->logger->log(this->logger, ERROR|LEVEL1,
-                               "IKE SA could not be checked out. Already deleted?");
                return DESTROY_ME;
        }
-
-       last_msg_tv = ike_sa->get_last_traffic_out_tv(ike_sa);
-       if (0 > gettimeofday(&current_tv, NULL) )
-       {
-               this->logger->log(this->logger, ERROR|LEVEL1,
-                               "Warning: Failed to get time of day.");
-       }
-       dt = (current_tv.tv_sec - last_msg_tv.tv_sec) * 1000
-          + (current_tv.tv_usec - last_msg_tv.tv_usec) / 1000;
-
-       if (dt >= interval)
-       {
-               packet = packet_create();
-               connection = ike_sa->get_connection(ike_sa);
-               host = connection->get_my_host(connection);
-               packet->set_source(packet, host->clone(host));
-               host = connection->get_other_host(connection);
-               packet->set_destination(packet, host->clone(host));
-               data = chunk_alloc(1);
-               data.ptr[0] = 0xFF;
-               packet->set_data(packet, data);
-               charon->send_queue->add(charon->send_queue, packet);
-               dt = 0;
-               this->logger->log(this->logger, CONTROL|LEVEL1,
-                               "NAT keepalive packet scheduled");
-       }
-       charon->event_queue->add_relative(charon->event_queue, (job_t*) this, interval - dt);
-
-       this->logger->log(this->logger, CONTROL|LEVEL2,
-                       "Checkin IKE SA %lld:%lld, role %s",
-                       this->ike_sa_id->get_initiator_spi(this->ike_sa_id),
-                       this->ike_sa_id->get_responder_spi(this->ike_sa_id),
-                       this->ike_sa_id->is_initiator(this->ike_sa_id) ? "initiator" : "responder");
-
-       status = charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
-       if (status != SUCCESS)
-       {
-               this->logger->log(this->logger, ERROR, "Checkin of IKE SA failed!");
-       }
-
-       return SUCCESS;
+       ike_sa->send_keepalive(ike_sa);
+       charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+       return DESTROY_ME;
 }
 
 /**
index 6a55d96..f3a6b0f 100644 (file)
@@ -25,6 +25,7 @@
 #include "send_queue.h"
 
 #include <utils/linked_list.h>
+#include <utils/logger_manager.h>
 
 
 typedef struct private_send_queue_t private_send_queue_t;
@@ -54,8 +55,12 @@ struct private_send_queue_t {
         * This condvar is used to wake up such a thread
         */
        pthread_cond_t condvar;
-};
 
+       /**
+        * Logger reference
+        */
+       logger_t *logger;
+};
 
 /**
  * implements send_queue_t.get_count
@@ -100,6 +105,14 @@ static packet_t *get(private_send_queue_t *this)
  */
 static void add(private_send_queue_t *this, packet_t *packet)
 {
+       host_t *src, *dst;
+       
+       src = packet->get_source(packet);
+       dst = packet->get_destination(packet);
+       this->logger->log(this->logger, CONTROL, "sending packet: from %s:%d to %s:%d",
+                                         src->get_address(src), src->get_port(src),
+                                         dst->get_address(dst), dst->get_port(dst));
+       
        pthread_mutex_lock(&(this->mutex));
        this->list->insert_last(this->list,packet);
        pthread_cond_signal( &(this->condvar));
@@ -148,6 +161,7 @@ send_queue_t *send_queue_create(void)
        this->list = linked_list_create();
        pthread_mutex_init(&(this->mutex), NULL);
        pthread_cond_init(&(this->condvar), NULL);
+       this->logger = logger_manager->get_logger(logger_manager, SOCKET);
 
        return (&this->public);
 }
index aefd1e9..029dd8e 100644 (file)
@@ -47,7 +47,7 @@ struct private_authenticator_t {
        /**
         * Assigned IKE_SA. Needed to get objects of type prf_t and logger_t.
         */
-       protected_ike_sa_t *ike_sa;
+       ike_sa_t *ike_sa;
        
        /**
         * PRF taken from the IKE_SA.
@@ -404,7 +404,7 @@ static void destroy (private_authenticator_t *this)
 /*
  * Described in header.
  */
-authenticator_t *authenticator_create(protected_ike_sa_t *ike_sa)
+authenticator_t *authenticator_create(ike_sa_t *ike_sa)
 {
        private_authenticator_t *this = malloc_thing(private_authenticator_t);
 
index b6bc317..143cdb6 100644 (file)
@@ -120,19 +120,12 @@ struct authenticator_t {
 /**
  * @brief Creates an authenticator object.
  * 
- * @warning: The following functions of the assigned protected_ike_sa_t object 
- * must return a valid value:
- *  - protected_ike_sa_t.get_policy
- *  - protected_ike_sa_t.get_prf
- *  - protected_ike_sa_t.get_logger
- * This preconditions are not given in IKE_SA states INITIATOR_INIT or RESPONDER_INIT!
- * 
- * @param ike_sa               object of type protected_ike_sa_t
+ * @param ike_sa               associated ike_sa
  * 
  * @return                             authenticator_t object
  * 
  * @ingroup sa
  */
-authenticator_t *authenticator_create(protected_ike_sa_t *ike_sa);
+authenticator_t *authenticator_create(ike_sa_t *ike_sa);
 
 #endif /* AUTHENTICATOR_H_ */
index 895c967..5ff67be 100644 (file)
@@ -858,6 +858,7 @@ child_sa_t * child_sa_create(u_int32_t rekey, host_t *me, host_t* other,
        this->public.alloc = (status_t(*)(child_sa_t*,linked_list_t*))alloc;
        this->public.add = (status_t(*)(child_sa_t*,proposal_t*,prf_plus_t*))add;
        this->public.update = (status_t(*)(child_sa_t*,proposal_t*,prf_plus_t*))update;
+       this->public.update_hosts = (status_t (*)(child_sa_t*,host_t*,host_t*,int,int))update_hosts;
        this->public.add_policies = (status_t (*)(child_sa_t*, linked_list_t*,linked_list_t*))add_policies;
        this->public.get_use_time = (status_t (*)(child_sa_t*,bool,time_t*))get_use_time;
        this->public.set_rekeyed = (void (*)(child_sa_t*))set_rekeyed;
index 4bff808..863a329 100644 (file)
@@ -31,7 +31,6 @@
 #include <definitions.h>
 #include <utils/linked_list.h>
 #include <utils/logger_manager.h>
-#include <utils/randomizer.h>
 #include <crypto/diffie_hellman.h>
 #include <crypto/prf_plus.h>
 #include <crypto/crypters/crypter.h>
 #include <encoding/payloads/transform_substructure.h>
 #include <encoding/payloads/transform_attribute.h>
 #include <encoding/payloads/ts_payload.h>
-#include <sa/states/initiator_init.h>
-#include <sa/states/responder_init.h>
-#include <sa/states/create_child_sa_requested.h>
-#include <sa/states/delete_child_sa_requested.h>
-#include <sa/states/delete_ike_sa_requested.h>
+#include <sa/transactions/transaction.h>
+#include <sa/transactions/ike_sa_init.h>
+#include <sa/transactions/delete_ike_sa.h>
+#include <sa/transactions/dead_peer_detection.h>
 #include <queues/jobs/retransmit_request_job.h>
 #include <queues/jobs/delete_established_ike_sa_job.h>
 #include <queues/jobs/delete_half_open_ike_sa_job.h>
+#include <queues/jobs/send_dpd_job.h>
+#include <queues/jobs/send_keepalive_job.h>
 
 
+/**
+ * String mappings for ike_sa_state_t.
+ */
+mapping_t ike_sa_state_m[] = {
+       {SA_CREATED, "CREATED"},
+       {SA_CONNECTING, "CONNECTING"},
+       {SA_ESTABLISHED, "ESTABLISHED"},
+       {SA_DELETING, "DELETING"},
+       {MAPPING_END, NULL}
+};
 
 
 typedef struct private_ike_sa_t private_ike_sa_t;
@@ -63,19 +73,9 @@ typedef struct private_ike_sa_t private_ike_sa_t;
 struct private_ike_sa_t {
 
        /**
-        * Protected part of a ike_sa_t object.
-        */
-       protected_ike_sa_t protected;
-       
-       /**
-        * Update a timestamp on ike traffic
-        */
-       void (*update_timestamp)(private_ike_sa_t *this, bool in);
-       
-       /**
-        * Returns the time since last traffic on kernel policies
+        * Public members
         */
-       struct timeval (*get_last_esp_traffic_tv)(private_ike_sa_t * this, bool inbound);
+       ike_sa_t public;
 
        /**
         * Identifier for the current IKE_SA.
@@ -88,18 +88,9 @@ struct private_ike_sa_t {
        linked_list_t *child_sas;
        
        /**
-        * Current state of the IKE_SA represented as state_t object.
-        * 
-        * A state object representates one of the following states and is processing 
-        * messages in the specific state:
-        *  - INITIATOR_INIT
-        *  - RESPONDER_INIT
-        *  - IKE_SA_INIT_REQUESTED
-        *  - IKE_SA_INIT_RESPONDED
-        *  - IKE_AUTH_REQUESTED
-        *   -IKE_SA_ESTABLISHED
+        * Current state of the IKE_SA
         */
-       state_t *current_state;
+       ike_sa_state_t state;
        
        /**
         * Connection definition used for this IKE_SA
@@ -112,41 +103,24 @@ struct private_ike_sa_t {
        policy_t *policy;
        
        /**
-        * This SA's source for random data.
-        * 
-        * Is available in every state.
-        */
-       randomizer_t *randomizer;
-       
-       /**
-        * The last responded message.
-        */
-       message_t *last_responded_message;
-
-       /**
-        * The ast requested message.
-        */
-       message_t *last_requested_message;
-       
-       /**
-        * Crypter object for initiator.
+        * crypter for inbound traffic
         */
-       crypter_t *crypter_initiator;
+       crypter_t *crypter_in;
        
        /**
-        * Crypter object for responder.
+        * crypter for outbound traffic
         */
-       crypter_t *crypter_responder;
+       crypter_t *crypter_out;
        
        /**
-        * Signer object for initiator.
+        * Signer for inbound traffic
         */
-       signer_t *signer_initiator;
+       signer_t *signer_in;
        
        /**
-        * Signer object for responder.
+        * Signer for outbound traffic
         */
-       signer_t *signer_responder;
+       signer_t *signer_out;
        
        /**
         * Multi purpose prf, set key, use it, forget it
@@ -167,21 +141,6 @@ struct private_ike_sa_t {
         * PRF, with key set to pr_key, used for authentication
         */
        prf_t *prf_auth_r;
-
-       /**
-        * Next message id to receive.
-        */
-       u_int32_t message_id_in;
-       
-       /**
-        * Next message id to send.
-        */
-       u_int32_t message_id_out;
-       
-       /**
-        * Last reply id which was successfully received.
-        */
-       int32_t last_replied_message_id;
        
        /**
         * A logger for this IKE_SA.
@@ -202,948 +161,994 @@ struct private_ike_sa_t {
         * NAT status of remote host.
         */
        bool nat_there;
+       
+       /**
+        * message ID for next outgoung request
+        */
+       u_int32_t message_id_out;
 
        /**
         * Timestamp of last IKE message received on this SA
         */
-       struct timeval last_msg_in_tv;
+       time_t time_inbound;
 
        /**
         * Timestamp of last IKE message sent on this SA
         */
-       struct timeval last_msg_out_tv;
-
-       /*
-        * Message ID of last DPD message
+       time_t time_outbound;
+       
+       /**
+        * List of queued transactions to process
+        */
+       linked_list_t *transaction_queue;
+       
+       /**
+        * Transaction currently initiated
+        * (only one supported yet, window size = 1)
+        */
+       transaction_t *transaction_out;
+       
+       /**
+        * last transaction initiated by peer processed.
+        * (only one supported yet, window size = 1)
+        * Stored for retransmission.
         */
-       u_int32_t last_dpd_message_id;
+       transaction_t *transaction_in;
+       
+       /**
+        * Next incoming transaction expected. Used to
+        * do multi transaction operations.
+        */
+       transaction_t *transaction_in_next;
 };
 
 /**
- * Implementation of protected_ike_sa_t.build_message.
+ * get the time of the latest traffic processed by the kernel
  */
-static void build_message(private_ike_sa_t *this, exchange_type_t type, bool request, message_t **message)
+static time_t get_esp_time(private_ike_sa_t* this, bool inbound)
 {
-       message_t *new_message;
-       host_t *me, *other;
+       iterator_t *iterator;
+       child_sa_t *child_sa;
+       time_t latest = 0, use_time;
        
-       me = this->connection->get_my_host(this->connection);
-       other = this->connection->get_other_host(this->connection);
-
-       this->logger->log(this->logger, CONTROL|LEVEL2, "build empty message");
-       new_message = message_create();
-       new_message->set_source(new_message, me->clone(me));
-       new_message->set_destination(new_message, other->clone(other));
-       new_message->set_exchange_type(new_message, type);
-       new_message->set_request(new_message, request);
-       new_message->set_message_id(new_message, (request) ? this->message_id_out : this->message_id_in);
-       new_message->set_ike_sa_id(new_message, this->ike_sa_id);
-
-       *message = new_message;
-}
-
-/**
- * Implementation of ike_sa_t.get_state.
- */
-static ike_sa_state_t get_state(private_ike_sa_t *this)
-{
-       return this->current_state->get_state(this->current_state);
-}
+       iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
+       while (iterator->iterate(iterator, (void**)&child_sa))
+       {
+               if (child_sa->get_use_time(child_sa, inbound, &use_time) == SUCCESS)
+               {
+                       latest = max(latest, use_time);
+               }
+       }
+       iterator->destroy(iterator);
        
-/**
- * Implementation of protected_ike_sa_t.set_new_state.
- */
-static void set_new_state(private_ike_sa_t *this, state_t *state)
-{
-       this->logger->log(this->logger, CONTROL, "state change: %s => %s",
-                                         mapping_find(ike_sa_state_m, get_state(this)),
-                                         mapping_find(ike_sa_state_m, state->get_state(state)));
-       this->current_state = state;
-}
-
-/**
- * Implementation of protected_ike_sa_t.get_connection.
- */
-static connection_t *get_connection(private_ike_sa_t *this)
-{
-       return this->connection;
-}
-
-/**
- * Implementation of protected_ike_sa_t.set_connection.
- */
-static void set_connection(private_ike_sa_t *this,connection_t * connection)
-{
-       this->connection = connection;
-}
-
-/**
- * Implementation of protected_ike_sa_t.get_policy.
- */
-static policy_t *get_policy(private_ike_sa_t *this)
-{
-       return this->policy;
+       return latest;
 }
 
 /**
- * Implementation of protected_ike_sa_t.set_policy.
+ * get the time of the latest received traffice
  */
-static void set_policy(private_ike_sa_t *this,policy_t * policy)
+static time_t get_time_inbound(private_ike_sa_t *this)
 {
-       this->policy = policy;
+       return max(this->time_inbound, get_esp_time(this, TRUE));
 }
 
 /**
- * Implementation of protected_ike_sa_t.get_prf.
+ * get the time of the latest sent traffic
  */
-static prf_t *get_prf(private_ike_sa_t *this)
+static time_t get_time_outbound(private_ike_sa_t *this)
 {
-       return this->prf;
+       return max(this->time_outbound, get_esp_time(this, FALSE));
 }
 
-/**
- * Implementation of protected_ike_sa_t.get_prf.
- */
-static prf_t *get_child_prf(private_ike_sa_t *this)
-{
-       return this->child_prf;
-}
 
 /**
- * Implementation of protected_ike_sa_t.get_prf_auth_i.
+ * Update connection host, as addresses may change (NAT)
  */
-static prf_t *get_prf_auth_i(private_ike_sa_t *this)
+static void update_hosts(private_ike_sa_t *this, host_t *me, host_t *other)
 {
-       return this->prf_auth_i;
-}
+       /*
+        * Quoting RFC 4306:
+        *
+        * 2.11.  Address and Port Agility
+        * 
+        *    IKE runs over UDP ports 500 and 4500, and implicitly sets up ESP and
+        *    AH associations for the same IP addresses it runs over.  The IP
+        *    addresses and ports in the outer header are, however, not themselves
+        *    cryptographically protected, and IKE is designed to work even through
+        *    Network Address Translation (NAT) boxes.  An implementation MUST
+        *    accept incoming requests even if the source port is not 500 or 4500,
+        *    and MUST respond to the address and port from which the request was
+        *    received.  It MUST specify the address and port at which the request
+        *    was received as the source address and port in the response.  IKE
+        *    functions identically over IPv4 or IPv6.
+        *
+        *    [...]
+        *
+        *    There are cases where a NAT box decides to remove mappings that
+        *    are still alive (for example, the keepalive interval is too long,
+        *    or the NAT box is rebooted).  To recover in these cases, hosts
+        *    that are not behind a NAT SHOULD send all packets (including
+        *    retransmission packets) to the IP address and port from the last
+        *    valid authenticated packet from the other end (i.e., dynamically
+        *    update the address).  A host behind a NAT SHOULD NOT do this
+        *    because it opens a DoS attack possibility.  Any authenticated IKE
+        *    packet or any authenticated UDP-encapsulated ESP packet can be
+        *    used to detect that the IP address or the port has changed.
+        */
+       host_t *old_other = NULL;
+       iterator_t *iterator = NULL;
+       child_sa_t *child_sa = NULL;
+       int my_changes, other_changes;
 
-/**
- * Implementation of protected_ike_sa_t.get_prf_auth_r.
- */
-static prf_t *get_prf_auth_r(private_ike_sa_t *this)
-{
-       return this->prf_auth_r;
-}
-/**
- * Implementation of ike_sa_t.get_id.
- */
-static ike_sa_id_t* get_id(private_ike_sa_t *this)
-{
-       return this->ike_sa_id;
-}
+       my_changes = me->get_differences(me, this->connection->get_my_host(this->connection));
 
-/**
- * Implementation of ike_sa_t.get_my_host.
- */
-static host_t* get_my_host(private_ike_sa_t *this)
-{
-       return this->connection->get_my_host(this->connection);;
-}
+       old_other = this->connection->get_other_host(this->connection);
+       other_changes = other->get_differences(other, old_other);
 
-/**
- * Implementation of ike_sa_t.get_other_host.
- */
-static host_t* get_other_host(private_ike_sa_t *this)
-{
-       return this->connection->get_other_host(this->connection);
+       if (!my_changes && !other_changes) 
+       {
+               return;
+       }
+       
+       if (my_changes)
+       {
+               this->connection->update_my_host(this->connection, me->clone(me));
+       }
+       
+       if (!this->nat_here)
+       {
+               /* update without restrictions if we are not NATted */
+               if (other_changes)
+               {
+                       this->connection->update_other_host(this->connection, other->clone(other));
+               }
+       }
+       else
+       {
+               /* if we are natted, only port may change */
+               if (other_changes & HOST_DIFF_ADDR)
+               {
+                       return;
+               }
+               else if (other_changes & HOST_DIFF_PORT)
+               {
+                       old_other->set_port(old_other, other->get_port(other));
+               }
+       }
+       iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
+       while (iterator->iterate(iterator, (void**)&child_sa))
+       {
+               child_sa->update_hosts(child_sa,
+                                                          this->connection->get_my_host(this->connection),
+                                                          this->connection->get_other_host(this->connection),
+                                                          my_changes, other_changes);
+               /* TODO: what to do if update fails? Delete CHILD_SA? */
+       }
+       iterator->destroy(iterator);
 }
 
 /**
- * Implementation of ike_sa_t.get_my_id.
+ * send a request and schedule retransmission
  */
-static identification_t* get_my_id(private_ike_sa_t *this)
+static status_t transmit_request(private_ike_sa_t *this)
 {
-       return this->policy->get_my_id(this->policy);
+       message_t *request;
+       packet_t *packet;
+       status_t status;
+       retransmit_request_job_t *job;
+       u_int32_t transmitted;
+       u_int32_t timeout;
+       transaction_t *transaction = this->transaction_out;
+       u_int32_t message_id = transaction->get_message_id(transaction);
+       
+       transmitted = transaction->requested(transaction);
+       timeout = charon->configuration->get_retransmit_timeout(charon->configuration,
+                                                                                                                       transmitted);
+       if (timeout == 0)
+       {
+               this->logger->log(this->logger, ERROR,
+                                                 "giving up after %d retransmits, deleting IKE_SA",
+                                                 transmitted - 1);
+               return DESTROY_ME;
+       }
+       
+       status = transaction->get_request(transaction, &request);
+       if (status != SUCCESS)
+       {
+               return status;
+       }
+       /* if we retransmit, the request is already generated */
+       if (transmitted == 0)
+       {
+               status = request->generate(request, this->crypter_out, this->signer_out, &packet);
+               if (status != SUCCESS)
+               {
+                       return FAILED;
+               }
+       }
+       else
+       {
+               this->logger->log(this->logger, CONTROL, 
+                                                 "sending retransmit %d for %s request with message ID %d",
+                                                 transmitted,
+                                                 mapping_find(exchange_type_m, request->get_exchange_type(request)),
+                                                 message_id);
+               packet = request->get_packet(request);
+       }
+       /* finally send */
+       charon->send_queue->add(charon->send_queue, packet);
+       this->time_outbound = time(NULL);
+       
+       /* schedule retransmission job */
+       job = retransmit_request_job_create(message_id, this->ike_sa_id);
+       charon->event_queue->add_relative(charon->event_queue, (job_t*)job, timeout);
+       return SUCCESS;
 }
 
 /**
- * Implementation of ike_sa_t.get_other_id.
+ * Implementation of ike_sa.retransmit_request.
  */
-static identification_t* get_other_id(private_ike_sa_t *this)
+static status_t retransmit_request(private_ike_sa_t *this, u_int32_t message_id)
 {
-       return this->policy->get_other_id(this->policy);
+       if (this->transaction_out == NULL ||
+               this->transaction_out->get_message_id(this->transaction_out) != message_id)
+       {
+               /* no retransmit necessary, transaction did already complete */
+               return SUCCESS;
+       }
+       return transmit_request(this);
 }
 
 /**
- * Implementation of ike_sa_t.retransmit_possible.
+ * Check for transactions in the queue and initiate the first transaction found.
  */
-static bool retransmit_possible(private_ike_sa_t *this, u_int32_t message_id)
+static status_t process_transaction_queue(private_ike_sa_t *this)
 {
-       return ((this->last_requested_message)
-            && (message_id != this->last_replied_message_id)
-            && (message_id == this->last_requested_message->get_message_id(
-                                               this->last_requested_message)));
+       if (this->transaction_out)
+       {
+               /* already a transaction in progress */
+               return SUCCESS;
+       }
+       
+       while (TRUE)
+       {
+               if (this->transaction_queue->remove_first(this->transaction_queue,
+                       (void**)&this->transaction_out) != SUCCESS)
+               {
+                       /* transaction queue empty */
+                       return SUCCESS;
+               }
+               switch (transmit_request(this))
+               {
+                       case SUCCESS:
+                               return SUCCESS;
+                       case DESTROY_ME:
+                               /* critical, IKE_SA unusable, destroy immediately */
+                               this->logger->log(this->logger, ERROR, 
+                                                                 "transaction initiaton failed, deleting IKE_SA");
+                               return DESTROY_ME;
+                       default:
+                               /* discard transaction, process next one */
+                               this->logger->log(this->logger, ERROR, 
+                                                                 "transaction initiation failed, discarded");
+                               this->transaction_out->destroy(this->transaction_out);
+                               this->transaction_out = NULL;
+                               /* handle next transaction */
+                               continue;
+               }
+       }
 }
 
 /**
- * Implementation of ike_sa_t.retransmit_request.
+ * Queue a new transaction and execute the next outstanding transaction
  */
-static status_t retransmit_request(private_ike_sa_t *this, u_int32_t message_id)
+static status_t queue_transaction(private_ike_sa_t *this, transaction_t *transaction, bool prefer)
 {
-       packet_t *packet;
-       
-       if (!this->protected.public.retransmit_possible(&this->protected.public, message_id))
+       /* inject next transaction */
+       if (transaction)
        {
-               return NOT_FOUND;
+               if (prefer)
+               {
+                       this->transaction_queue->insert_first(this->transaction_queue, transaction);
+               }
+               else
+               {
+                       this->transaction_queue->insert_last(this->transaction_queue, transaction);
+               }
        }
-       
-       this->logger->log(this->logger, CONTROL | LEVEL1, "going to retransmit message with id %d",message_id);
-       packet = this->last_requested_message->get_packet(this->last_requested_message);
-       charon->send_queue->add(charon->send_queue, packet);
-       this->update_timestamp(this, FALSE);
-       return SUCCESS;
+       /* process a transaction */
+       return process_transaction_queue(this);
 }
 
 /**
- * Implementation of protected_ike_sa_t.build_transforms.
+ * process an incoming request.
  */
-static status_t build_transforms(private_ike_sa_t *this, proposal_t *proposal, diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r)
+static status_t process_request(private_ike_sa_t *this, message_t *request)
 {
-       chunk_t nonces, nonces_spis, skeyseed, key, secret;
-       u_int64_t spi_i, spi_r;
-       prf_plus_t *prf_plus;
-       algorithm_t *algo;
-       size_t key_size;
+       transaction_t *last, *current = NULL;
+       message_t *response;
+       packet_t *packet;
+       u_int32_t request_mid;
+       status_t status;
        
-       /*
-       * Build the PRF+ instance for deriving keys
-       */
-       if (this->prf != NULL)
+       request_mid = request->get_message_id(request);
+       last = this->transaction_in;
+       
+       /* check if message ID is correct */
+       if (last)
        {
-               this->prf->destroy(this->prf);
+               u_int32_t last_mid = last->get_message_id(last);
+               
+               if (last_mid == request_mid)
+               {
+                       /* retransmit detected */
+                       this->logger->log(this->logger, ERROR,
+                                                         "received retransmitted request for message ID %d, retransmitting response",
+                                                         request_mid);
+                       last->get_response(last, request, &response, &this->transaction_in_next);
+                       packet = response->get_packet(response);
+                       charon->send_queue->add(charon->send_queue, packet);
+                       this->time_outbound = time(NULL);
+                       return SUCCESS;
+               }
+               
+               if (last_mid > request_mid)
+               {
+                       /* something seriously wrong here, message id may not decrease */
+                       this->logger->log(this->logger, ERROR,
+                                                         "received request with message ID %d, excepted %d, ingored",
+                                                         request_mid, last_mid + 1);
+                       return FAILED;
+               }
+               /* we allow jumps in message IDs, as long as they are incremental */
+               if (last_mid + 1 < request_mid)
+               {
+                       this->logger->log(this->logger, ERROR,
+                                                         "received request with message ID %d, excepted %d",
+                                                         request_mid, last_mid + 1);
+               }
        }
-       if (!proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &algo))
+       else
        {
-               this->logger->log(this->logger, ERROR|LEVEL2, "no PRF algoithm selected!?");
-               return FAILED;
+               if (request_mid != 0)
+               {
+                       /* warn, but allow it */
+                       this->logger->log(this->logger, CONTROL,
+                                                         "first received request has message ID %d, excepted 0", 
+                                                         request_mid);
+               }
        }
-       this->prf = prf_create(algo->algorithm);
-       if (this->prf == NULL)
-       {
-               this->logger->log(this->logger, ERROR|LEVEL1, 
-                                                 "PSEUDO_RANDOM_FUNCTION %s not supported!",
-                                                 mapping_find(pseudo_random_function_m, algo->algorithm));
-               return FAILED;
-       }
-       
-       /* concatenate nonces =  nonce_i | nonce_r */
-       nonces = chunk_alloc(nonce_i.len + nonce_r.len);
-       memcpy(nonces.ptr, nonce_i.ptr, nonce_i.len);
-       memcpy(nonces.ptr + nonce_i.len, nonce_r.ptr, nonce_r.len);
-
-       /* concatenate prf_seed = nonce_i | nonce_r | spi_i | spi_r */
-       nonces_spis = chunk_alloc(nonces.len + 16);
-       memcpy(nonces_spis.ptr, nonces.ptr, nonces.len);
-       spi_i = this->ike_sa_id->get_initiator_spi(this->ike_sa_id);
-       spi_r = this->ike_sa_id->get_responder_spi(this->ike_sa_id);
-       memcpy(nonces_spis.ptr + nonces.len, &spi_i, 8);
-       memcpy(nonces_spis.ptr + nonces.len + 8, &spi_r, 8);
        
-       /* SKEYSEED = prf(Ni | Nr, g^ir) */
-       dh->get_shared_secret(dh, &secret);
-       this->logger->log_chunk(this->logger, PRIVATE, "shared Diffie-Hellman secret", secret);
-       this->prf->set_key(this->prf, nonces);
-       this->prf->allocate_bytes(this->prf, secret, &skeyseed);
-       this->logger->log_chunk(this->logger, PRIVATE | LEVEL1, "SKEYSEED", skeyseed);
-       chunk_free(&secret);
-
-       /* prf+ (SKEYSEED, Ni | Nr | SPIi | SPIr )
-       * = SK_d | SK_ai | SK_ar | SK_ei | SK_er | SK_pi | SK_pr
-       *
-       * we use the prf directly for prf+ 
-       */
-       this->prf->set_key(this->prf, skeyseed);
-       prf_plus = prf_plus_create(this->prf, nonces_spis);
-       
-       /* clean up unused stuff */
-       chunk_free(&nonces);
-       chunk_free(&nonces_spis);
-       chunk_free(&skeyseed);
-       
-       
-       /*
-       * We now can derive all of our key. We build the transforms 
-       * directly.
-       */
-       
-       
-       /* SK_d used for prf+ to derive keys for child SAs */
-       this->child_prf = prf_create(algo->algorithm);
-       key_size = this->child_prf->get_key_size(this->child_prf);
-       prf_plus->allocate_bytes(prf_plus, key_size, &key);
-       this->logger->log_chunk(this->logger, PRIVATE, "Sk_d secret", key);
-       this->child_prf->set_key(this->child_prf, key);
-       chunk_free(&key);
-       
-       
-       /* SK_ai/SK_ar used for integrity protection */
-       if (!proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &algo))
-       {
-               this->logger->log(this->logger, ERROR, "no integrity algoithm selected?!");
-               return FAILED;
-       }
-       if (this->signer_initiator != NULL)
+       /* check if we already have a pre-created transaction for this request */
+       if (this->transaction_in_next)
        {
-               this->signer_initiator->destroy(this->signer_initiator);
+               u_int32_t trans_mid = this->transaction_in_next->get_message_id(this->transaction_in_next);
+               
+               /* check message id consistency */
+               if (trans_mid == request_mid)
+               {
+                       /* use it */
+                       current = this->transaction_in_next;
+               }
+               else
+               {
+                       /* discard queued transaction */
+                       this->transaction_in_next->destroy(this->transaction_in_next);
+               }
+               this->transaction_in_next = NULL;
        }
-       if (this->signer_responder != NULL)
+       /* create new transaction if "next" unusable */
+       if (current == NULL)
        {
-               this->signer_responder->destroy(this->signer_responder);
+               current = transaction_create(&this->public, request);
+               if (current == NULL)
+               {
+                       this->logger->log(this->logger, ERROR, 
+                                                         "no idea how to handle received message (%d), ignored",
+                                                         request->get_exchange_type(request));
+                       return FAILED;
+               }
        }
        
-       this->signer_initiator = signer_create(algo->algorithm);
-       this->signer_responder = signer_create(algo->algorithm);
-       if (this->signer_initiator == NULL || this->signer_responder == NULL)
+       /* send message. get_request() always gives a valid response */
+       status = current->get_response(current, request, &response, &this->transaction_in_next);
+       if (response->generate(response, this->crypter_out, this->signer_out, &packet) != SUCCESS)
        {
                this->logger->log(this->logger, ERROR, 
-                                                 "INTEGRITY_ALGORITHM %s not supported!",
-                                                 mapping_find(integrity_algorithm_m,algo->algorithm));
+                                                 "response generation failed, discarding transaction");
+               current->destroy(current);
                return FAILED;
        }
-       key_size = this->signer_initiator->get_key_size(this->signer_initiator);
        
-       prf_plus->allocate_bytes(prf_plus, key_size, &key);
-       this->logger->log_chunk(this->logger, CONTROL|LEVEL1, "Sk_ai secret", key);
-       this->signer_initiator->set_key(this->signer_initiator, key);
-       chunk_free(&key);
+       charon->send_queue->add(charon->send_queue, packet);
+       this->time_outbound = time(NULL);
+       /* act depending on transaction result */
+       switch (status)
+       {
+               case DESTROY_ME:
+                       /* transactions says we should destroy the IKE_SA, so do it */
+                       current->destroy(current);
+                       return DESTROY_ME;
+               default:
+                       /* store for retransmission, destroy old transaction */
+                       this->transaction_in = current;
+                       if (last)
+                       {
+                               last->destroy(last);
+                       }
+                       return SUCCESS;
+       }
+}
 
-       prf_plus->allocate_bytes(prf_plus, key_size, &key);
-       this->logger->log_chunk(this->logger, CONTROL|LEVEL1, "Sk_ar secret", key);
-       this->signer_responder->set_key(this->signer_responder, key);
-       chunk_free(&key);
-       
+/**
+ * process an incoming response
+ */
+static status_t process_response(private_ike_sa_t *this, message_t *response)
+{
+       transaction_t *current, *new = NULL;
        
-       /* SK_ei/SK_er used for encryption */
-       if (!proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &algo))
+       current = this->transaction_out;
+       /* check if message ID is that of our currently active transaction */
+       if (current == NULL ||
+               current->get_message_id(current) !=
+                  response->get_message_id(response))
        {
-               this->logger->log(this->logger, ERROR, "no encryption algoithm selected!?");
+               this->logger->log(this->logger, ERROR, 
+                                                 "received response with message ID %d not requested, ignored");
                return FAILED;
        }
-       if (this->crypter_initiator != NULL)
-       {
-               this->crypter_initiator->destroy(this->crypter_initiator);
-       }
-       if (this->crypter_responder != NULL)
+       
+       switch (current->conclude(current, response, &new))
        {
-               this->crypter_responder->destroy(this->crypter_responder);
+               case DESTROY_ME:
+                       /* state requested to destroy IKE_SA */
+                       return DESTROY_ME;
+               default:
+                       /* discard transaction, process next one */
+                       break;
        }
+       /* transaction comleted, remove */
+       current->destroy(current);
+       this->transaction_out = NULL;
        
-       this->crypter_initiator = crypter_create(algo->algorithm, algo->key_size / 8);
-       this->crypter_responder = crypter_create(algo->algorithm, algo->key_size / 8);
-       if (this->crypter_initiator == NULL || this->crypter_responder == NULL)
+       /* queue new transaction */
+       return queue_transaction(this, new, TRUE);
+}
+
+/**
+ * send a notify back to the sender
+ */
+static void send_notify_response(private_ike_sa_t *this,
+                                                                message_t *request,
+                                                                notify_type_t type)
+{
+       notify_payload_t *notify;
+       message_t *response;
+       host_t *src, *dst;
+       packet_t *packet;
+       
+       response = message_create();
+       dst = request->get_source(request);
+       src = request->get_destination(request);
+       response->set_source(response, src->clone(src));
+       response->set_destination(response, dst->clone(dst));
+       response->set_exchange_type(response, request->get_exchange_type(request));
+       response->set_request(response, FALSE);
+       response->set_message_id(response, request->get_message_id(request));
+       response->set_ike_sa_id(response, this->ike_sa_id);
+       notify = notify_payload_create_from_protocol_and_type(PROTO_NONE, type);
+       response->add_payload(response, (payload_t *)notify);
+       if (response->generate(response, this->crypter_out, this->signer_out, &packet) != SUCCESS)
        {
-               this->logger->log(this->logger, ERROR, 
-                                                 "ENCRYPTION_ALGORITHM %s (key size %d) not supported!",
-                                                 mapping_find(encryption_algorithm_m, algo->algorithm),
-                                                 algo->key_size);
-               return FAILED;
+               response->destroy(response);
+               return;
        }
-       key_size = this->crypter_initiator->get_key_size(this->crypter_initiator);
-       
-       prf_plus->allocate_bytes(prf_plus, key_size, &key);
-       this->logger->log_chunk(this->logger, PRIVATE, "Sk_ei secret", key);
-       this->crypter_initiator->set_key(this->crypter_initiator, key);
-       chunk_free(&key);
+       charon->send_queue->add(charon->send_queue, packet);
+       this->time_outbound = time(NULL);
+       response->destroy(response);
+       return;
+}
+
+
+/**
+ * Implementation of ike_sa_t.process_message.
+ */
+static status_t process_message(private_ike_sa_t *this, message_t *message)
+{
+       status_t status;
+       bool is_request;
        
-       prf_plus->allocate_bytes(prf_plus, key_size, &key);
-       this->logger->log_chunk(this->logger, PRIVATE, "Sk_er secret", key);
-       this->crypter_responder->set_key(this->crypter_responder, key);
-       chunk_free(&key);
+       is_request = message->get_request(message);
        
-       /* SK_pi/SK_pr used for authentication */
-       if (this->prf_auth_i != NULL)
+       status = message->parse_body(message, this->crypter_in, this->signer_in);
+       if (status != SUCCESS)
        {
-               this->prf_auth_i->destroy(this->prf_auth_i);
+               switch (status)
+               {
+                       case NOT_SUPPORTED:
+                               this->logger->log(this->logger, ERROR,
+                                                                 "ciritcal unknown payloads found");
+                               if (is_request)
+                               {
+                                       send_notify_response(this, message, UNSUPPORTED_CRITICAL_PAYLOAD);
+                               }
+                               break;
+                       case PARSE_ERROR:
+                               this->logger->log(this->logger, ERROR,
+                                                                 "message parsing failed");
+                               if (is_request)
+                               {
+                                       send_notify_response(this, message, INVALID_SYNTAX);
+                               }
+                               break;
+                       case VERIFY_ERROR:
+                               this->logger->log(this->logger, ERROR,
+                                                                 "message verification failed");
+                               if (is_request)
+                               {
+                                       send_notify_response(this, message, INVALID_SYNTAX);
+                               }
+                               break;
+                       case FAILED:
+                               this->logger->log(this->logger, ERROR,
+                                                                 "integrity check failed");
+                               /* ignored */
+                               break;
+                       case INVALID_STATE:
+                               this->logger->log(this->logger, ERROR,
+                                                                 "found encrypted message, but no keys available");
+                               if (is_request)
+                               {
+                                       send_notify_response(this, message, INVALID_SYNTAX);
+                               }
+                       default:
+                               break;
+               }
+               this->logger->log(this->logger, ERROR,
+                                                 "%s %s with message ID %d processing failed",
+                                                 mapping_find(exchange_type_m, message->get_exchange_type(message)),
+                                                 message->get_request(message) ? "request" : "response",
+                                                 message->get_message_id(message));
        }
-       if (this->prf_auth_r != NULL)
+       else
        {
-               this->prf_auth_r->destroy(this->prf_auth_r);
+               /* check if message is trustworthy, and update connection information */
+               if ((this->state == SA_CREATED && this->connection) ||
+                       message->get_exchange_type(message) != IKE_SA_INIT)
+               {
+                       update_hosts(this, message->get_destination(message),
+                                                          message->get_source(message));
+                       this->time_inbound = time(NULL);
+               }
+               if (is_request)
+               {
+                       status = process_request(this, message);
+               }
+               else
+               {
+                       status = process_response(this, message);
+               }
        }
-       
-       proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &algo);
-       this->prf_auth_i = prf_create(algo->algorithm);
-       this->prf_auth_r = prf_create(algo->algorithm);
-       
-       key_size = this->prf_auth_i->get_key_size(this->prf_auth_i);
-       prf_plus->allocate_bytes(prf_plus, key_size, &key);
-       this->logger->log_chunk(this->logger, PRIVATE, "Sk_pi secret", key);
-       this->prf_auth_i->set_key(this->prf_auth_i, key);
-       chunk_free(&key);
-       
-       prf_plus->allocate_bytes(prf_plus, key_size, &key);
-       this->logger->log_chunk(this->logger, PRIVATE, "Sk_pr secret", key);
-       this->prf_auth_r->set_key(this->prf_auth_r, key);
-       chunk_free(&key);
-       
-       /* all done, prf_plus not needed anymore */
-       prf_plus->destroy(prf_plus);
-       
-       return SUCCESS;
+       return status;
 }
 
 /**
- * Implementation of protected_ike_sa_t.get_randomizer.
+ * Implementation of ike_sa_t.initiate.
  */
-static randomizer_t *get_randomizer(private_ike_sa_t *this)
+static status_t initiate(private_ike_sa_t *this, connection_t *connection)
 {
-       return this->randomizer;
+       ike_sa_init_t *ike_sa_init;
+       
+       /* set connection and policy */
+       this->connection = connection;
+       this->policy = charon->policies->get_policy_by_name(charon->policies,
+                       this->connection->get_name(this->connection));
+       if (this->policy == NULL)
+       {
+               this->logger->log(this->logger, ERROR,
+                                                 "no policy found for connection %s, aborting",
+                                                 connection->get_name(connection));
+               return DESTROY_ME;
+       }
+       ike_sa_init = ike_sa_init_create(&this->public, 0);
+       this->message_id_out = 2;
+       return queue_transaction(this, (transaction_t*)ike_sa_init, TRUE);
 }
 
 /**
- * Implementation of protected_ike_sa_t.get_crypter_initiator.
+ * Implementation of ike_sa_t.send_dpd
  */
-static crypter_t *get_crypter_initiator(private_ike_sa_t *this)
+static status_t send_dpd(private_ike_sa_t *this)
 {
-       return this->crypter_initiator;
+       send_dpd_job_t *job;
+       time_t diff, interval;
+       status_t status = SUCCESS;
+       
+       interval = charon->configuration->get_dpd_interval(charon->configuration);
+       
+       if (this->transaction_out)
+       {
+               /* there is a transaction in progress. Come back later */
+               diff = 0;
+       }
+       else
+       {
+               /* check if there was any inbound traffic */
+               time_t last_in, now;
+               last_in = get_time_inbound(this);
+               now = time(NULL);
+               diff = now - last_in;
+               if (diff >= interval)
+               {
+                       /* to long ago, initiate dead peer detection */
+                       dead_peer_detection_t *dpd;
+                       this->logger->log(this->logger, CONTROL, "sending DPD request");
+                       dpd = dead_peer_detection_create(&this->public, this->message_id_out++);
+                       status = queue_transaction(this, (transaction_t*)dpd, FALSE);
+                       diff = 0;
+               }
+       }
+       /* recheck in "interval" seconds */
+       job = send_dpd_job_create(this->ike_sa_id);
+       charon->event_queue->add_relative(charon->event_queue, (job_t*)job,
+                                                                         (interval - diff) * 1000);
+       return SUCCESS;
 }
 
 /**
- * Implementation of protected_ike_sa_t.get_signer_initiator.
+ * Implementation of ike_sa_t.send_keepalive
  */
-static signer_t *get_signer_initiator(private_ike_sa_t *this)
+static void send_keepalive(private_ike_sa_t *this)
 {
-       return this->signer_initiator;
+       send_keepalive_job_t *job;
+       time_t last_out, now, diff, interval;
+       
+       last_out = get_time_outbound(this);
+       now = time(NULL);
+       
+       diff = now - last_out;
+       interval = charon->configuration->get_keepalive_interval(charon->configuration);
+       
+       if (diff >= interval)
+       {
+               host_t *me, *other;
+               packet_t *packet;
+               chunk_t data;
+               
+               packet = packet_create();
+               me = this->connection->get_my_host(this->connection);
+               other = this->connection->get_other_host(this->connection);
+               packet->set_source(packet, me->clone(me));
+               packet->set_destination(packet, other->clone(other));
+               data.ptr = malloc(1);
+               data.ptr[0] = 0xFF;
+               data.len = 1;
+               packet->set_data(packet, data);
+               charon->send_queue->add(charon->send_queue, packet);
+               this->logger->log(this->logger, CONTROL, "sending keep alive");
+               diff = 0;
+       }
+       job = send_keepalive_job_create(this->ike_sa_id);
+       charon->event_queue->add_relative(charon->event_queue, (job_t*)job,
+                                                                         (interval - diff) * 1000);
 }
 
 /**
- * Implementation of protected_ike_sa_t.get_crypter_responder.
+ * Implementation of ike_sa_t.get_state.
  */
-static crypter_t *get_crypter_responder(private_ike_sa_t *this)
+static ike_sa_state_t get_state(private_ike_sa_t *this)
 {
-       return this->crypter_responder;
+       return this->state;
 }
 
 /**
- * Implementation of protected_ike_sa_t.get_signer_responder.
+ * Implementation of ike_sa_t.set_state.
  */
-static signer_t *get_signer_responder(private_ike_sa_t *this)
+static void set_state(private_ike_sa_t *this, ike_sa_state_t state)
 {
-       return this->signer_responder;
+       this->logger->log(this->logger, CONTROL, "state change: %s => %s",
+                                         mapping_find(ike_sa_state_m, this->state),
+                                         mapping_find(ike_sa_state_m, state));
+       if (state == SA_ESTABLISHED)
+       {
+               host_t *my_host, *other_host;
+               identification_t *my_id, *other_id;
+               my_host = this->connection->get_my_host(this->connection);
+               other_host = this->connection->get_other_host(this->connection);
+               my_id = this->policy->get_my_id(this->policy);
+               other_id = this->policy->get_other_id(this->policy);
+               this->logger->log(this->logger, AUDIT, "IKE_SA established: %s[%s]...%s[%s]",
+                                                 my_host->get_address(my_host),
+                                                 my_id->get_string(my_id),
+                                                 other_host->get_address(other_host),
+                                                 other_id->get_string(other_id));
+               
+               send_dpd(this);
+       }
+       this->state = state;
 }
 
 /**
- * Implementation of protected_ike_sa_t.update_timestamp
+ * Implementation of protected_ike_sa_t.get_connection.
  */
-static void update_timestamp(private_ike_sa_t *this, bool in)
+static connection_t *get_connection(private_ike_sa_t *this)
 {
-       /* bump last message sent timestamp */
-       struct timeval *tv = in ? &this->last_msg_in_tv : &this->last_msg_out_tv;
-       if (0 > gettimeofday(tv, NULL))
-       {
-               this->logger->log(this->logger, ERROR|LEVEL1,
-                                                 "warning: failed to get time of day.");
-       }
+       return this->connection;
 }
 
 /**
- * Implementation of protected_ike_sa_t.send_request.
+ * Implementation of protected_ike_sa_t.set_connection.
  */
-static status_t send_request(private_ike_sa_t *this, message_t *message)
+static void set_connection(private_ike_sa_t *this,connection_t * connection)
 {
-       retransmit_request_job_t *retransmit_job;
-       u_int32_t timeout;
-       crypter_t *crypter;
-       signer_t *signer;
-       packet_t *packet;
-       status_t status;
-       
-       if (message->get_message_id(message) != this->message_id_out)
-       {
-               this->logger->log(this->logger, ERROR, "message could not be sent cause id (%d) was not as expected (%d)",
-                                                 message->get_message_id(message),this->message_id_out);
-               return FAILED;
-       }
-
-       /* generate packet */   
-       this->logger->log(this->logger, CONTROL|LEVEL2, "generate packet from message");
-
-       if (this->ike_sa_id->is_initiator(this->ike_sa_id))
-       {
-               crypter = this->crypter_initiator;
-               signer = this->signer_initiator;
-       }
-       else
-       {
-               crypter = this->crypter_responder;
-               signer =this->signer_responder;
-       }
-       
-       status = message->generate(message, crypter,signer, &packet);
-       if (status != SUCCESS)
-       {
-               this->logger->log(this->logger, ERROR, "could not generate packet from message");
-               return FAILED;
-       }
-       
-       this->logger->log(this->logger, CONTROL|LEVEL3,
-                                         "add request packet with message id %d to global send queue",
-                                         this->message_id_out);
-       charon->send_queue->add(charon->send_queue, packet);
-       
-       /* replace last message for retransmit with current */
-       if (this->last_requested_message != NULL)
-       {
-               this->last_requested_message->destroy(this->last_requested_message);
-       }
-       this->logger->log(this->logger, CONTROL|LEVEL3, "replace last requested message with new one");
-       this->last_requested_message = message;
-       
-       /* schedule a job for retransmission */
-       status = charon->configuration->get_retransmit_timeout(charon->configuration, 0, &timeout);
-       if (status != SUCCESS)
-       {
-               this->logger->log(this->logger, CONTROL|LEVEL2, "no retransmit job for message created!");
-       }
-       else
-       {
-               this->logger->log(this->logger, CONTROL|LEVEL2, "request will be retransmitted in %d ms.", timeout);
-               retransmit_job = retransmit_request_job_create(this->message_id_out, this->ike_sa_id);
-               charon->event_queue->add_relative(charon->event_queue, (job_t *)retransmit_job, timeout);
-       }
-       
-       /* message counter can now be increased */
-       this->logger->log(this->logger, CONTROL|LEVEL3,
-                                         "increase message counter for outgoing messages from %d",
-                                         this->message_id_out);
-       this->message_id_out++;
-
-       this->update_timestamp(this, FALSE);
-       return SUCCESS; 
+       this->connection = connection;
 }
 
 /**
- * Implementation of protected_ike_sa_t.send_response.
+ * Implementation of protected_ike_sa_t.get_policy.
  */
-static status_t send_response(private_ike_sa_t *this, message_t *message)
+static policy_t *get_policy(private_ike_sa_t *this)
 {
-       crypter_t *crypter;
-       signer_t *signer;
-       packet_t *packet;
-       status_t status;
-       
-       if (message->get_message_id(message) != this->message_id_in)
-       {
-       
-               this->logger->log(this->logger, ERROR, "message could not be sent cause id (%d) was not as expected (%d)",
-                                                 message->get_message_id(message),this->message_id_in);
-               return FAILED;  
-       }
-       
-       if (this->ike_sa_id->is_initiator(this->ike_sa_id))
-       {
-               crypter = this->crypter_initiator;
-               signer = this->signer_initiator;
-       }
-       else
-       {
-               crypter = this->crypter_responder;
-               signer =this->signer_responder;
-       }
-       
-       status = message->generate(message, crypter,signer, &packet);
-       if (status != SUCCESS)
-       {
-               this->logger->log(this->logger, ERROR, "could not generate packet from message");
-               return FAILED;
-       }
-       
-       this->logger->log(this->logger, CONTROL|LEVEL3,
-                                         "add response packet with message id %d to global send queue",
-                                         this->message_id_in);
-       charon->send_queue->add(charon->send_queue, packet);
-       
-       if (this->last_responded_message != NULL)
-       {
-               /* destroy message */
-               this->last_responded_message->destroy(this->last_responded_message);
-       }
-       
-       this->logger->log(this->logger, CONTROL|LEVEL3, "replace last responded message with new one");
-       this->last_responded_message = message;
-
-       /* message counter can now be increased */
-       this->logger->log(this->logger, CONTROL|LEVEL3, "increase message counter for incoming messages");
-       this->message_id_in++;
-
-       this->update_timestamp(this, FALSE);
-
-       return SUCCESS;
+       return this->policy;
 }
 
 /**
- * Implementation of of private_responder_init_t.send_notify_reply.
+ * Implementation of protected_ike_sa_t.set_policy.
  */
-static void send_notify(private_ike_sa_t *this, exchange_type_t exchange_type, notify_message_type_t type, chunk_t data)
+static void set_policy(private_ike_sa_t *this,policy_t * policy)
 {
-       notify_payload_t *payload;
-       message_t *response;
-       packet_t *packet;
-       status_t status;
-       
-       this->logger->log(this->logger, CONTROL|LEVEL2, "going to build message with notify payload");
-       /* set up the reply */
-       build_message(this, exchange_type, FALSE, &response);
-       payload = notify_payload_create_from_protocol_and_type(PROTO_NONE, type);
-       if ((data.ptr != NULL) && (data.len > 0))
-       {
-               this->logger->log(this->logger, CONTROL|LEVEL2, "add Data to notify payload");
-               payload->set_notification_data(payload,data);
-       }
-       
-       this->logger->log(this->logger, CONTROL|LEVEL2, "add Notify payload to message");
-       response->add_payload(response,(payload_t *) payload);
-       
-       /* generate packet */   
-       this->logger->log(this->logger, CONTROL|LEVEL2, "generate packet from message");
-       status = response->generate(response, this->crypter_responder, this->signer_responder, &packet);
-       if (status != SUCCESS)
-       {
-               this->logger->log(this->logger, ERROR|LEVEL1, "could not generate notify message");
-               response->destroy(response);
-               return;
-       }
-       
-       this->logger->log(this->logger, CONTROL|LEVEL2, "add packet to global send queue");
-       charon->send_queue->add(charon->send_queue, packet);
-       this->logger->log(this->logger, CONTROL|LEVEL2, "destroy message");
-       response->destroy(response);
-
-       this->update_timestamp(this, FALSE);
+       this->policy = policy;
 }
 
 /**
- * Implementation of protected_ike_sa_t.set_last_replied_message_id.
+ * Implementation of protected_ike_sa_t.get_prf.
  */
-static void set_last_replied_message_id (private_ike_sa_t *this,u_int32_t message_id)
+static prf_t *get_prf(private_ike_sa_t *this)
 {
-       this->last_replied_message_id = message_id;
+       return this->prf;
 }
 
 /**
- * Implementation of protected_ike_sa_t.get_last_responded_message.
+ * Implementation of protected_ike_sa_t.get_prf.
  */
-static message_t *get_last_responded_message (private_ike_sa_t *this)
+static prf_t *get_child_prf(private_ike_sa_t *this)
 {
-       return this->last_responded_message;
+       return this->child_prf;
 }
 
 /**
- * Implementation of protected_ike_sa_t.get_last_requested_message.
+ * Implementation of protected_ike_sa_t.get_prf_auth_i.
  */
-static message_t *get_last_requested_message(private_ike_sa_t *this)
+static prf_t *get_prf_auth_i(private_ike_sa_t *this)
 {
-       return this->last_requested_message;
+       return this->prf_auth_i;
 }
 
 /**
- * Implementation of protected_ike_sa_t.add_child_sa.
+ * Implementation of protected_ike_sa_t.get_prf_auth_r.
  */
-static void add_child_sa(private_ike_sa_t *this, child_sa_t *child_sa)
+static prf_t *get_prf_auth_r(private_ike_sa_t *this)
 {
-       this->child_sas->insert_last(this->child_sas, child_sa);
+       return this->prf_auth_r;
+}
+/**
+ * Implementation of ike_sa_t.get_id.
+ */
+static ike_sa_id_t* get_id(private_ike_sa_t *this)
+{
+       return this->ike_sa_id;
 }
 
 /**
- * Implementation of ike_sa_t.process_message.
+ * Implementation of protected_ike_sa_t.build_transforms.
  */
-static status_t process_message(private_ike_sa_t *this, message_t *message)
+static status_t build_transforms(private_ike_sa_t *this, proposal_t *proposal, 
+                                                                diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r,
+                                                                bool initiator)
 {
-       u_int32_t message_id;
-       exchange_type_t exchange_type;
-       bool is_request;
-       
-       /* Find out type of message (request or response) */
-       is_request = message->get_request(message);
-       exchange_type = message->get_exchange_type(message);
-       
-       this->logger->log(this->logger, CONTROL|LEVEL1, "process %s of exchange type %s",
-                                         (is_request) ? "request" : "response",
-                                         mapping_find(exchange_type_m, exchange_type));
-       
-       message_id = message->get_message_id(message);
-       
-       /* check if message already received, and retransmit its reply */
-       if (is_request && (message_id == (this->message_id_in - 1)))
-       {
-               /* resend last message, if any */
-               if (this->last_responded_message)
-               {
-                       packet_t *packet = this->last_responded_message->get_packet(this->last_responded_message);
-                       this->logger->log(this->logger, CONTROL|LEVEL1, "resent request detected. Send stored reply.");
-                       charon->send_queue->add(charon->send_queue, packet);
-                       this->update_timestamp(this, FALSE);
-                       return SUCCESS;
-               }
-               else
-               {
-                       /* somebody does something nasty here... */
-                       return FAILED;
-               }
-       }
+       chunk_t nonces, nonces_spis, skeyseed, key, secret;
+       u_int64_t spi_i, spi_r;
+       prf_plus_t *prf_plus;
+       algorithm_t *algo;
+       size_t key_size;
+       crypter_t *crypter_i, *crypter_r;
+       signer_t *signer_i, *signer_r;
        
-       /* Now, the message id is checked for request AND reply */
-       if (is_request)
+       /* Build the PRF+ instance for deriving keys */
+       if (!proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &algo))
        {
-               /* In a request, the message has to be this->message_id_in (other case is already handled) */
-               if (message_id != this->message_id_in)
-               {
-                       this->logger->log(this->logger, ERROR | LEVEL1,
-                                                               "message request with message id %d received, but %d expected",
-                                                               message_id,this->message_id_in);
-                       return FAILED;
-               }
+               this->logger->log(this->logger, ERROR, "no PSEUDO_RANDOM_FUNCTION selected!");
+               return FAILED;
        }
-       else
+       this->prf = prf_create(algo->algorithm);
+       if (this->prf == NULL)
        {
-               /* In a reply, the message has to be this->message_id_out -1 cause it is the reply to the last sent message*/
-               if (message_id != (this->message_id_out - 1))
-               {
-                       this->logger->log(this->logger, ERROR | LEVEL1,
-                                                               "message reply with message id %d received, but %d expected",
-                                                               message_id,this->message_id_in);
-                       return FAILED;
-               }
+               this->logger->log(this->logger, ERROR, "PSEUDO_RANDOM_FUNCTION %s not supported!",
+                                                 mapping_find(pseudo_random_function_m, algo->algorithm));
+               return FAILED;
        }
        
-       this->update_timestamp(this, TRUE);
-       
-       /* now the message is processed by the current state object.
-        * The specific state object is responsible to check if a message can be received in 
-        * the state it represents.
-        * The current state is also responsible to change the state object to the next state 
-        * by calling protected_ike_sa_t.set_new_state
-        */
-       return this->current_state->process_message(this->current_state, message);
-}
+       /* nonces =  nonce_i | nonce_r */
+       nonces = chunk_alloc(nonce_i.len + nonce_r.len);
+       memcpy(nonces.ptr, nonce_i.ptr, nonce_i.len);
+       memcpy(nonces.ptr + nonce_i.len, nonce_r.ptr, nonce_r.len);
 
-/**
- * Implementation of protected_ike_sa_t.initiate_connection.
- */
-static status_t initiate_connection(private_ike_sa_t *this, connection_t *connection)
-{
-       initiator_init_t *current_state;
+       /* prf_seed = nonce_i | nonce_r | spi_i | spi_r */
+       nonces_spis = chunk_alloc(nonces.len + 16);
+       memcpy(nonces_spis.ptr, nonces.ptr, nonces.len);
+       spi_i = this->ike_sa_id->get_initiator_spi(this->ike_sa_id);
+       spi_r = this->ike_sa_id->get_responder_spi(this->ike_sa_id);
+       memcpy(nonces_spis.ptr + nonces.len, &spi_i, 8);
+       memcpy(nonces_spis.ptr + nonces.len + 8, &spi_r, 8);
+       
+       /* SKEYSEED = prf(Ni | Nr, g^ir) */
+       dh->get_shared_secret(dh, &secret);
+       this->logger->log_chunk(this->logger, PRIVATE, "shared Diffie Hellman secret", secret);
+       this->prf->set_key(this->prf, nonces);
+       this->prf->allocate_bytes(this->prf, secret, &skeyseed);
+       this->logger->log_chunk(this->logger, PRIVATE|LEVEL1, "SKEYSEED", skeyseed);
+       chunk_free(&secret);
 
-       /* Work is done in state object of type INITIATOR_INIT. All other states are not 
-        * initial states and so don't have a initiate_connection function */
+       /* prf+ (SKEYSEED, Ni | Nr | SPIi | SPIr )
+        *     = SK_d | SK_ai | SK_ar | SK_ei | SK_er | SK_pi | SK_pr
+        */
+       this->prf->set_key(this->prf, skeyseed);
+       prf_plus = prf_plus_create(this->prf, nonces_spis);
        
-       if (this->current_state->get_state(this->current_state) != INITIATOR_INIT)
+       /* clean up unused stuff */
+       chunk_free(&nonces);
+       chunk_free(&nonces_spis);
+       chunk_free(&skeyseed);
+       
+       /* SK_d used for prf+ to derive keys for child SAs */
+       this->child_prf = prf_create(algo->algorithm);
+       key_size = this->child_prf->get_key_size(this->child_prf);
+       prf_plus->allocate_bytes(prf_plus, key_size, &key);
+       this->logger->log_chunk(this->logger, PRIVATE, "Sk_d secret", key);
+       this->child_prf->set_key(this->child_prf, key);
+       chunk_free(&key);
+       
+       /* SK_ai/SK_ar used for integrity protection */
+       if (!proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &algo))
        {
+               this->logger->log(this->logger, ERROR, "no INTEGRITY_ALGORITHM selected?!");
                return FAILED;
        }
        
-       current_state = (initiator_init_t *) this->current_state;
-       
-       return current_state->initiate_connection(current_state, connection);
-}
-
-/**
- * Implementation of protected_ike_sa_t.update_connection_hosts.
- *
- * Quoting RFC 4306:
- *
- * 2.11.  Address and Port Agility
- * 
- *    IKE runs over UDP ports 500 and 4500, and implicitly sets up ESP and
- *    AH associations for the same IP addresses it runs over.  The IP
- *    addresses and ports in the outer header are, however, not themselves
- *    cryptographically protected, and IKE is designed to work even through
- *    Network Address Translation (NAT) boxes.  An implementation MUST
- *    accept incoming requests even if the source port is not 500 or 4500,
- *    and MUST respond to the address and port from which the request was
- *    received.  It MUST specify the address and port at which the request
- *    was received as the source address and port in the response.  IKE
- *    functions identically over IPv4 or IPv6.
- * 
- * [...]
- * 
- *    There are cases where a NAT box decides to remove mappings that
- *    are still alive (for example, the keepalive interval is too long,
- *    or the NAT box is rebooted).  To recover in these cases, hosts
- *    that are not behind a NAT SHOULD send all packets (including
- *    retransmission packets) to the IP address and port from the last
- *    valid authenticated packet from the other end (i.e., dynamically
- *    update the address).  A host behind a NAT SHOULD NOT do this
- *    because it opens a DoS attack possibility.  Any authenticated IKE
- *    packet or any authenticated UDP-encapsulated ESP packet can be
- *    used to detect that the IP address or the port has changed.
- */
-static status_t update_connection_hosts(private_ike_sa_t *this, host_t *me, host_t *other)
-{
-       host_t *old_other = NULL;
-       iterator_t *iterator = NULL;
-       child_sa_t *child_sa = NULL;
-       int my_changes, other_changes;
-       ike_sa_state_t s;
-
-       my_changes = me->get_differences(me, this->connection->get_my_host(this->connection));
-
-       old_other = this->connection->get_other_host(this->connection);
-       other_changes = other->get_differences(other, old_other);
-
-       if (!my_changes && !other_changes) {
-               return SUCCESS;
-       }
-       
-       if (my_changes)
+       signer_i = signer_create(algo->algorithm);
+       signer_r = signer_create(algo->algorithm);
+       if (signer_i == NULL || signer_r == NULL)
        {
-               this->connection->update_my_host(this->connection, me->clone(me));
+               this->logger->log(this->logger, ERROR, "INTEGRITY_ALGORITHM %s not supported!",
+                                                 mapping_find(integrity_algorithm_m,algo->algorithm));
+               return FAILED;
        }
+       key_size = signer_i->get_key_size(signer_i);
+       
+       prf_plus->allocate_bytes(prf_plus, key_size, &key);
+       this->logger->log_chunk(this->logger, CONTROL|LEVEL1, "Sk_ai secret", key);
+       signer_i->set_key(signer_i, key);
+       chunk_free(&key);
 
-       s = this->protected.public.get_state(&this->protected.public);
+       prf_plus->allocate_bytes(prf_plus, key_size, &key);
+       this->logger->log_chunk(this->logger, CONTROL|LEVEL1, "Sk_ar secret", key);
+       signer_r->set_key(signer_r, key);
+       chunk_free(&key);
        
-       if (s == RESPONDER_INIT || s == IKE_SA_INIT_REQUESTED || !this->nat_here)
+       if (initiator)
        {
-               if (other_changes)
-               {
-                       this->connection->update_other_host(this->connection, other->clone(other));
-               }
+               this->signer_in = signer_i;
+               this->signer_out = signer_r;
        }
        else
        {
-               if (other_changes & HOST_DIFF_ADDR)
-               {
-                       this->logger->log(this->logger, ERROR|LEVEL1,
-                                                         "destination ip changed from %s to %s. As we are NATed this is not allowed!",
-                                                         old_other->get_address(old_other), other->get_address(other));
-                       return DESTROY_ME;
-               }
-               else if (other_changes & HOST_DIFF_PORT)
-               {
-                       old_other->set_port(old_other, other->get_port(other));
-               }
+               this->signer_in = signer_r;
+               this->signer_out = signer_i;
        }
-
-       iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
-       while (iterator->iterate(iterator, (void**)&child_sa))
+       
+       /* SK_ei/SK_er used for encryption */
+       if (!proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &algo))
        {
-               child_sa->update_hosts(child_sa,
-                                                          this->connection->get_my_host(this->connection),
-                                                          this->connection->get_other_host(this->connection),
-                                                          my_changes, other_changes);
-               /* XXX error handling */
+               this->logger->log(this->logger, ERROR, "no ENCRYPTION_ALGORITHM selected!");
+               return FAILED;
+       }       
+       crypter_i = crypter_create(algo->algorithm, algo->key_size / 8);
+       crypter_r = crypter_create(algo->algorithm, algo->key_size / 8);
+       if (crypter_i == NULL || crypter_r == NULL)
+       {
+               this->logger->log(this->logger, ERROR, 
+                                                 "ENCRYPTION_ALGORITHM %s (key size %d) not supported!",
+                                                 mapping_find(encryption_algorithm_m, algo->algorithm),
+                                                 algo->key_size);
+               return FAILED;
        }
-       iterator->destroy(iterator);
+       key_size = crypter_i->get_key_size(crypter_i);
        
-       return SUCCESS;
-}
-
-/**
- * Implementation of protected_ike_sa_t.build_transforms.
- * TODO: IPv6 support.
- */
-static chunk_t generate_natd_hash(private_ike_sa_t *this, u_int64_t spi_i, u_int64_t spi_r, host_t *host)
-{
-       chunk_t natd_string;
-       chunk_t natd_hash;
-       void *p;
-       struct sockaddr_in* sai;
-       char buf[512];
-
-       natd_hash = chunk_alloc(this->nat_hasher->get_hash_size(this->nat_hasher));
-       natd_string = chunk_alloc(8 + 8 + 4 + 2);
-
-       sai = (struct sockaddr_in*)host->get_sockaddr(host);
-       p = natd_string.ptr;
-       *(u_int64_t*)p = spi_i;                p += sizeof(spi_i);
-       *(u_int64_t*)p = spi_r;                p += sizeof(spi_r);
-       *(u_int32_t*)p = sai->sin_addr.s_addr; p += sizeof(sai->sin_addr.s_addr);
-       *(u_int16_t*)p = sai->sin_port;        p += sizeof(sai->sin_port);
-
-       this->nat_hasher->get_hash(this->nat_hasher, natd_string, natd_hash.ptr);
-       this->nat_hasher->reset(this->nat_hasher);
-
-       sprintf(buf, "natd_hash(%016llx %016llx %s:%d)\n == SHA1(", spi_i, spi_r,
-                       host->get_address(host), host->get_port(host));
-       chunk_to_hex(buf + strlen(buf), sizeof(buf) - strlen(buf), natd_string);
-       strcat(buf, ") == ");
-       chunk_to_hex(buf + strlen(buf), sizeof(buf) - strlen(buf), natd_hash);
-       this->logger->log(this->logger, CONTROL|LEVEL3, buf);
-
-       chunk_free(&natd_string);
-       return natd_hash;
-}
-
-/**
- * Implementation of ike_sa_t.send_dpd_request.
- */
-static status_t send_dpd_request(private_ike_sa_t *this)
-{
-       message_t *dpd_msg;
-       status_t status;
-       this->protected.build_message(&this->protected, INFORMATIONAL, TRUE, &dpd_msg);
-       status = this->protected.send_request(&this->protected, dpd_msg);
-       if (status != SUCCESS)
+       prf_plus->allocate_bytes(prf_plus, key_size, &key);
+       this->logger->log_chunk(this->logger, PRIVATE, "Sk_ei secret", key);
+       crypter_i->set_key(crypter_i, key);
+       chunk_free(&key);
+       
+       prf_plus->allocate_bytes(prf_plus, key_size, &key);
+       this->logger->log_chunk(this->logger, PRIVATE, "Sk_er secret", key);
+       crypter_r->set_key(crypter_r, key);
+       chunk_free(&key);
+       
+       if (initiator)
        {
-               dpd_msg->destroy(dpd_msg);
+               this->crypter_in = crypter_i;
+               this->crypter_out = crypter_r;
        }
-       this->last_dpd_message_id = dpd_msg->get_message_id(dpd_msg);
-       return status;
-}
-
-/**
- * Implementation of ike_sa_t.get_last_dpd_message_id
- */
-static u_int32_t get_last_dpd_message_id(private_ike_sa_t *this)
-{
-       return this->last_dpd_message_id;
+       else
+       {
+               this->crypter_in = crypter_r;
+               this->crypter_out = crypter_i;
+       }
+       
+       /* SK_pi/SK_pr used for authentication */       
+       proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &algo);
+       this->prf_auth_i = prf_create(algo->algorithm);
+       this->prf_auth_r = prf_create(algo->algorithm);
+       
+       key_size = this->prf_auth_i->get_key_size(this->prf_auth_i);
+       prf_plus->allocate_bytes(prf_plus, key_size, &key);
+       this->logger->log_chunk(this->logger, PRIVATE, "Sk_pi secret", key);
+       this->prf_auth_i->set_key(this->prf_auth_i, key);
+       chunk_free(&key);
+       
+       prf_plus->allocate_bytes(prf_plus, key_size, &key);
+       this->logger->log_chunk(this->logger, PRIVATE, "Sk_pr secret", key);
+       this->prf_auth_r->set_key(this->prf_auth_r, key);
+       chunk_free(&key);
+       
+       /* all done, prf_plus not needed anymore */
+       prf_plus->destroy(prf_plus);
+       
+       return SUCCESS;
 }
 
 /**
- * Implementation of ike_sa_t.get_child_sa.
+ * Implementation of protected_ike_sa_t.add_child_sa.
  */
-static child_sa_t *get_child_sa(private_ike_sa_t *this, u_int32_t reqid)
+static void add_child_sa(private_ike_sa_t *this, child_sa_t *child_sa)
 {
-       iterator_t *iterator;
-       child_sa_t *current, *found = NULL;
-       
-       iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
-       while (iterator->has_next(iterator))
-       {
-               iterator->current(iterator, (void**)&current);
-               if (current->get_reqid(current) == reqid)
-               {
-                       found = current;
-                       break;
-               }
-       }
-       iterator->destroy(iterator);
-       return found;
+       this->child_sas->insert_last(this->child_sas, child_sa);
 }
 
 /**
  * Implementation of ike_sa_t.delete_child_sa.
  */
-static status_t delete_child_sa(private_ike_sa_t *this, u_int32_t reqid)
+static status_t delete_child_sa(private_ike_sa_t *this, u_int32_t spi)
 {
-       message_t *request;
-       child_sa_t *child_sa;
-       delete_payload_t *delete_payload;
-       state_t *old_state;
-       
-       if (this->current_state->get_state(this->current_state) != IKE_SA_ESTABLISHED)
-       {
-               this->logger->log(this->logger, ERROR|LEVEL1,
-                                                 "delete of a CHILD_SA whose IKE_SA not in state IKE_SA_ESTABLISHED, aborting");
-               return FAILED;
-       }
-       
-       child_sa = get_child_sa(this, reqid);
-       if (child_sa == NULL)
-       {
-               this->logger->log(this->logger, ERROR|LEVEL1, 
-                                                 "IKE_SA does not contain a CHILD_SA with reqid %d", reqid);
-               return FAILED;
-       }
-       build_message(this, INFORMATIONAL, TRUE, &request);
-       delete_payload = delete_payload_create(child_sa->get_protocol(child_sa));
-       delete_payload->add_spi(delete_payload, child_sa->get_spi(child_sa, TRUE));
-       request->add_payload(request, (payload_t*)delete_payload);
-       
-       send_request(this, request);
-       
-       old_state = this->current_state;
-       set_new_state(this, (state_t*)delete_child_sa_requested_create(&this->protected));
-       old_state->destroy(old_state);
+       /* TODO: Reimplement */
+//     message_t *request;
+//     child_sa_t *child_sa;
+//     delete_payload_t *delete_payload;
+// 
+//     if (this->current_state->get_state(this->current_state) != IKE_SA_ESTABLISHED)
+//     {
+//             this->logger->log(this->logger, ERROR|LEVEL1,
+//                                               "Delete of a CHILD_SA whose IKE_SA not in state IKE_SA_ESTABLISHED, aborting");
+//             return FAILED;
+//     }
+//     
+//     child_sa = get_child_sa(this, reqid);
+//     if (child_sa == NULL)
+//     {
+//             this->logger->log(this->logger, ERROR|LEVEL1, 
+//                                               "IKE_SA does not contain a CHILD_SA with reqid %d", reqid);
+//             return FAILED;
+//     }
+//     build_message(this, INFORMATIONAL, TRUE, &request);
+//     delete_payload = delete_payload_create(child_sa->get_protocol(child_sa));
+//     delete_payload->add_spi(delete_payload, child_sa->get_spi(child_sa, TRUE));
+//     request->add_payload(request, (payload_t*)delete_payload);
+//     
+//     send_request(this, request);
+//     
+//     old_state = this->current_state;
+//     set_new_state(this, (state_t*)delete_child_sa_requested_create(&this->protected));
+//     old_state->destroy(old_state);
        return SUCCESS;
 }
 
@@ -1185,7 +1190,7 @@ static u_int32_t destroy_child_sa(private_ike_sa_t *this, u_int32_t spi)
 /**
  * Implementation of protected_ike_sa_t.get_child_sa.
  */
-static child_sa_t* get_child_sa_by_spi(private_ike_sa_t *this, u_int32_t spi)
+static child_sa_t* get_child_sa(private_ike_sa_t *this, u_int32_t spi)
 {
        iterator_t *iterator;
        child_sa_t *current, *found = NULL;
@@ -1206,8 +1211,9 @@ static child_sa_t* get_child_sa_by_spi(private_ike_sa_t *this, u_int32_t spi)
 /**
  * Implementation of ike_sa_t.rekey_child_sa.
  */
-static status_t rekey_child_sa(private_ike_sa_t *this, u_int32_t reqid)
+static status_t rekey_child_sa(private_ike_sa_t *this, u_int32_t spi)
 {
+/*     TODO reimplement 
        message_t *request;
        child_sa_t *child_sa;
        notify_payload_t *notify;
@@ -1217,7 +1223,6 @@ static status_t rekey_child_sa(private_ike_sa_t *this, u_int32_t reqid)
        linked_list_t *proposals;
        chunk_t nonce;
        linked_list_t *my_ts, *other_ts;
-       state_t *old_state;
        
        if (this->current_state->get_state(this->current_state) != IKE_SA_ESTABLISHED)
        {
@@ -1272,58 +1277,11 @@ static status_t rekey_child_sa(private_ike_sa_t *this, u_int32_t reqid)
        
        old_state = this->current_state;
        set_new_state(this, (state_t*)create_child_sa_requested_create(&this->protected, child_sa, nonce, reqid));
-       old_state->destroy(old_state);
+       old_state->destroy(old_state);*/
        
        return SUCCESS;
 }
 
-/**
- * Implementation of protected_ike_sa_t.establish.
- */
-static void establish(private_ike_sa_t *this)
-{
-       protected_ike_sa_t *ike_sa = (protected_ike_sa_t *)this;
-
-       connection_t *connection = ike_sa->get_connection(ike_sa);
-       host_t *my_host = connection->get_my_host(connection);
-       host_t *other_host = connection->get_other_host(connection);
-       policy_t *policy = ike_sa->get_policy(ike_sa);
-       identification_t *my_id = policy->get_my_id(policy);
-       identification_t *other_id = policy->get_other_id(policy);
-
-       ike_sa->set_new_state(ike_sa, (state_t*)ike_sa_established_create(ike_sa));
-
-       this->logger->log(this->logger, AUDIT, "IKE_SA established %s[%s]...%s[%s]",
-                                         my_host->get_address(my_host),
-                                         my_id->get_string(my_id),
-                                         other_host->get_address(other_host),
-                                         other_id->get_string(other_id));
-}
-
-/**
- * Implementation of protected_ike_sa_t.reset_message_buffers.
- */
-static void reset_message_buffers(private_ike_sa_t *this)
-{
-       this->logger->log(this->logger, CONTROL|LEVEL2, "reset message counters and destroy stored messages");
-       /* destroy stored requested message */
-       if (this->last_requested_message != NULL)
-       {
-               this->last_requested_message->destroy(this->last_requested_message);
-               this->last_requested_message = NULL;
-       }
-       
-       /* destroy stored responded messages */
-       if (this->last_responded_message != NULL)
-       {
-               this->last_responded_message->destroy(this->last_responded_message);
-               this->last_responded_message = NULL;
-       }
-       
-       this->message_id_out = 0;
-       this->message_id_in = 0;
-       this->last_replied_message_id = -1;
-}
 
 /**
  * Implementation of protected_ike_sa_t.log_status.
@@ -1364,7 +1322,7 @@ static void log_status(private_ike_sa_t *this, logger_t *logger, char *name)
        }
        logger->log(logger, CONTROL|LEVEL1, "  \"%s\": IKE_SA in state %s, SPIs: 0x%.16llx 0x%.16llx",
                                name,
-                               mapping_find(ike_sa_state_m, this->current_state->get_state(this->current_state)),
+                               mapping_find(ike_sa_state_m, this->state),
                                this->ike_sa_id->get_initiator_spi(this->ike_sa_id),
                                this->ike_sa_id->get_responder_spi(this->ike_sa_id));
        logger->log(logger, CONTROL, "  \"%s\": %s[%s]...%s[%s]",
@@ -1388,129 +1346,38 @@ static void log_status(private_ike_sa_t *this, logger_t *logger, char *name)
  */
 static status_t delete_(private_ike_sa_t *this)
 {
-       message_t *informational_request;
-       delete_payload_t *delete_payload;
-       u_int32_t timeout;
-       delete_half_open_ike_sa_job_t *job;
-       state_t *old_state;
-       
-       if (get_state(this) != IKE_SA_ESTABLISHED)
-       {
-               return INVALID_STATE;
-       }
-       
-       build_message(this, INFORMATIONAL, TRUE, &informational_request);
-       /* delete for the full IKE_SA, this deletes all child_sa's implicit */  
-       delete_payload = delete_payload_create(PROTO_IKE);
-       
-       informational_request->add_payload(informational_request, (payload_t*)delete_payload);
-       
-       if (send_request(this, informational_request) != SUCCESS)
-       {
-               /* send failed, but we ignore this, SA will get deleted anyway later */
-               informational_request->destroy(informational_request);
-       }
-       
-       /* transit to state delete_ike_sa_requested */
-       old_state = this->current_state;
-       set_new_state(this, (state_t*)delete_ike_sa_requested_create(&this->protected));
-       old_state->destroy(old_state);
+       delete_ike_sa_t *delete_ike_sa;
+       delete_ike_sa = delete_ike_sa_create(&this->public, this->message_id_out++);
        
-       /* there is no guarantee that the other peer will acknowledge the delete,
-        * so we have to set a timeout where we destroy the SA... This is done with
-        * the delete_half_open_ike_sa_job as used in IKE SA setup.
-        */
-       timeout = charon->configuration->get_half_open_ike_sa_timeout(charon->configuration);
-       job = delete_half_open_ike_sa_job_create(this->ike_sa_id);
-       charon->event_queue->add_relative(charon->event_queue, (job_t*)job, timeout);
-       return SUCCESS;
-}
-
-/**
- * Implementation of ike_sa_t.is_my_host_behind_nat.
- */
-static bool is_my_host_behind_nat (private_ike_sa_t *this)
-{
-       return this->nat_here;
-}
-
-/**
- * Implementation of ike_sa_t.is_other_host_behind_nat.
- */
-static bool is_other_host_behind_nat (private_ike_sa_t *this)
-{
-       return this->nat_there;
+       return queue_transaction(this, (transaction_t*)delete_ike_sa, FALSE);
 }
 
 /**
- * Implementation of ike_sa_t.is_any_host_behind_nat.
+ * Implementation of ike_sa_t.is_natt_enabled.
  */
-static bool is_any_host_behind_nat (private_ike_sa_t *this)
+static bool is_natt_enabled (private_ike_sa_t *this)
 {
        return this->nat_here || this->nat_there;
 }
 
 /**
- * Implementation of protected_ike_sa_t.set_my_host_behind_nat.
- */
-static void set_my_host_behind_nat (private_ike_sa_t *this, bool nat)
-{
-       this->nat_here = nat;
-}
-
-/**
- * Implementation of protected_ike_sa_t.set_other_host_behind_nat.
- */
-static void set_other_host_behind_nat (private_ike_sa_t *this, bool nat)
-{
-       this->nat_there = nat;
-}
-
-/**
- * Implementation of private_ike_sa_t.get_last_esp_traffic_tv
+ * Implementation of protected_ike_sa_t.enable_natt.
  */
-static struct timeval get_last_esp_traffic_tv(private_ike_sa_t * this, bool inbound)
+static void enable_natt (private_ike_sa_t *this, bool local)
 {
-       iterator_t *iterator;
-       child_sa_t *child_sa;
-       bool ret = TRUE; 
-       time_t use_time = 0;
-       struct timeval tv = {0, 0};
-
-       iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
-       while (iterator->iterate(iterator, (void**)&child_sa))
+       if (local)
        {
-               if (child_sa->get_use_time(child_sa, inbound, &use_time) == SUCCESS
-                               && use_time != 0)
-               {
-                       tv.tv_sec = max(tv.tv_sec, use_time);
-               }
+               this->logger->log(this->logger, CONTROL,
+                                                 "local host is behind NAT, using NAT-T, scheduled keep alives");
+               this->nat_here = TRUE;
+               send_keepalive(this);
+       }
+       else
+       {
+               this->logger->log(this->logger, CONTROL, 
+                                                 "remote host is behind NAT, using NAT-T");
+               this->nat_there = TRUE;
        }
-       iterator->destroy(iterator);
-       
-       return tv;
-}
-
-/**
- * Implementation of ike_sa_t.get_last_traffic_in_tv.
- */
-static struct timeval get_last_traffic_in_tv (private_ike_sa_t *this)
-{
-       struct timeval esp_tv  = this->get_last_esp_traffic_tv(this, TRUE);
-       return this->last_msg_in_tv.tv_sec > esp_tv.tv_sec ? this->last_msg_in_tv
-            : this->last_msg_in_tv.tv_sec < esp_tv.tv_sec ? esp_tv
-            : this->last_msg_in_tv.tv_usec > esp_tv.tv_usec ? this->last_msg_in_tv : esp_tv;
-}
-
-/**
- * Implementation of ike_sa_t.get_last_traffic_out_tv.
- */
-static struct timeval get_last_traffic_out_tv (private_ike_sa_t *this)
-{
-       struct timeval esp_tv  = this->get_last_esp_traffic_tv(this, FALSE);
-       return this->last_msg_out_tv.tv_sec > esp_tv.tv_sec ? this->last_msg_out_tv
-            : this->last_msg_out_tv.tv_sec < esp_tv.tv_sec ? esp_tv
-            : this->last_msg_out_tv.tv_usec > esp_tv.tv_usec ? this->last_msg_out_tv : esp_tv; 
 }
 
 /**
@@ -1519,15 +1386,17 @@ static struct timeval get_last_traffic_out_tv (private_ike_sa_t *this)
 static void destroy(private_ike_sa_t *this)
 {
        child_sa_t *child_sa;
+       transaction_t *transaction;
        
        this->logger->log(this->logger, CONTROL|LEVEL2, "going to destroy IKE SA %llu:%llu, role %s", 
                                          this->ike_sa_id->get_initiator_spi(this->ike_sa_id),
                                          this->ike_sa_id->get_responder_spi(this->ike_sa_id),
                                          this->ike_sa_id->is_initiator(this->ike_sa_id) ? "initiator" : "responder");
        
-       if (get_state(this) == IKE_SA_ESTABLISHED)
+       if (this->state == SA_ESTABLISHED)
        {
-               this->logger->log(this->logger, ERROR, "destroying an established IKE SA without knowledge from remote peer!");
+               this->logger->log(this->logger, ERROR, 
+                                                 "destroying an established IKE SA without knowledge from remote peer!");
        }
 
        while (this->child_sas->remove_last(this->child_sas, (void**)&child_sa) == SUCCESS)
@@ -1536,21 +1405,38 @@ static void destroy(private_ike_sa_t *this)
        }
        this->child_sas->destroy(this->child_sas);
        
-       if (this->crypter_initiator)
+       while (this->transaction_queue->remove_last(this->transaction_queue, (void**)&transaction) == SUCCESS)
+       {
+               transaction->destroy(transaction);
+       }
+       this->transaction_queue->destroy(this->transaction_queue);
+       if (this->transaction_in)
+       {
+               this->transaction_in->destroy(this->transaction_in);
+       }
+       if (this->transaction_in_next)
+       {
+               this->transaction_in_next->destroy(this->transaction_in_next);
+       }
+       if (this->transaction_out)
+       {
+               this->transaction_out->destroy(this->transaction_out);
+       }
+       if (this->crypter_in)
        {
-               this->crypter_initiator->destroy(this->crypter_initiator);
+               this->crypter_in->destroy(this->crypter_in);
        }
-       if (this->crypter_responder)
+       if (this->crypter_out)
        {
-               this->crypter_responder->destroy(this->crypter_responder);
+               this->crypter_out->destroy(this->crypter_out);
        }
-       if (this->signer_initiator)
+       if (this->signer_in)
        {
-               this->signer_initiator->destroy(this->signer_initiator);
+               this->signer_in->destroy(this->signer_in);
        }
-       if (this->signer_responder)
+       if (this->signer_out)
        {
-               this->signer_responder->destroy(this->signer_responder);
+               this->signer_out->destroy(this->signer_out);
        }
        if (this->prf)
        {
@@ -1591,18 +1477,7 @@ static void destroy(private_ike_sa_t *this)
        {
                this->policy->destroy(this->policy);
        }
-       if (this->last_requested_message)
-       {
-               this->last_requested_message->destroy(this->last_requested_message);
-       }
-       if (this->last_responded_message)
-       {
-               this->last_responded_message->destroy(this->last_responded_message);
-       }
-       this->nat_hasher->destroy(this->nat_hasher);
        this->ike_sa_id->destroy(this->ike_sa_id);
-       this->randomizer->destroy(this->randomizer);
-       this->current_state->destroy(this->current_state);
        free(this);
 }
 
@@ -1614,109 +1489,59 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
        private_ike_sa_t *this = malloc_thing(private_ike_sa_t);
        
        /* Public functions */
-       this->protected.public.process_message = (status_t (*) (ike_sa_t*,message_t*)) process_message;
-       this->protected.public.initiate_connection = (status_t (*) (ike_sa_t*,connection_t*)) initiate_connection;
-       this->protected.public.delete_child_sa = (status_t (*) (ike_sa_t*,u_int32_t)) delete_child_sa;
-       this->protected.public.rekey_child_sa = (status_t (*) (ike_sa_t*,u_int32_t)) rekey_child_sa;
-       this->protected.public.get_child_sa = (child_sa_t* (*) (ike_sa_t*,u_int32_t))get_child_sa;
-       this->protected.public.get_id = (ike_sa_id_t* (*) (ike_sa_t*)) get_id;
-       this->protected.public.get_my_host = (host_t* (*) (ike_sa_t*)) get_my_host;
-       this->protected.public.get_other_host = (host_t* (*) (ike_sa_t*)) get_other_host;
-       this->protected.public.get_my_id = (identification_t* (*) (ike_sa_t*)) get_my_id;
-       this->protected.public.get_other_id = (identification_t* (*) (ike_sa_t*)) get_other_id;
-       this->protected.public.get_connection = (connection_t* (*) (ike_sa_t*)) get_connection;
-       this->protected.public.retransmit_possible = (bool (*) (ike_sa_t*,u_int32_t)) retransmit_possible;
-       this->protected.public.retransmit_request = (status_t (*) (ike_sa_t*,u_int32_t)) retransmit_request;
-       this->protected.public.get_state = (ike_sa_state_t (*) (ike_sa_t*)) get_state;
-       this->protected.public.log_status = (void (*) (ike_sa_t*,logger_t*,char*))log_status;
-       this->protected.public.delete = (status_t (*) (ike_sa_t*))delete_;
-       this->protected.public.destroy = (void (*) (ike_sa_t*))destroy;
-       this->protected.public.is_my_host_behind_nat = (bool (*) (ike_sa_t*)) is_my_host_behind_nat;
-       this->protected.public.is_other_host_behind_nat = (bool (*) (ike_sa_t*)) is_other_host_behind_nat;
-       this->protected.public.is_any_host_behind_nat = (bool (*) (ike_sa_t*)) is_any_host_behind_nat;
-       this->protected.public.get_last_traffic_in_tv = (struct timeval (*) (ike_sa_t*)) get_last_traffic_in_tv;
-       this->protected.public.get_last_traffic_out_tv = (struct timeval (*) (ike_sa_t*)) get_last_traffic_out_tv;
-       this->protected.public.send_dpd_request = (status_t (*) (ike_sa_t*)) send_dpd_request;
-       
-       /* protected functions */
-       this->protected.build_message = (void (*) (protected_ike_sa_t*,exchange_type_t,bool,message_t**)) build_message;
-       this->protected.get_prf = (prf_t *(*) (protected_ike_sa_t*)) get_prf;   
-       this->protected.get_child_prf = (prf_t* (*) (protected_ike_sa_t*)) get_child_prf;
-       this->protected.get_prf_auth_i = (prf_t* (*) (protected_ike_sa_t*)) get_prf_auth_i;
-       this->protected.get_prf_auth_r = (prf_t* (*) (protected_ike_sa_t*)) get_prf_auth_r;
-       this->protected.add_child_sa = (void (*) (protected_ike_sa_t*,child_sa_t*)) add_child_sa;
-       this->protected.establish = (void (*) (protected_ike_sa_t*)) establish;
-       this->protected.set_connection = (void (*) (protected_ike_sa_t*,connection_t*)) set_connection;
-       this->protected.get_connection = (connection_t* (*) (protected_ike_sa_t*)) get_connection;
-       this->protected.set_policy = (void (*) (protected_ike_sa_t *,policy_t*)) set_policy;
-       this->protected.get_policy = (policy_t* (*) (protected_ike_sa_t*)) get_policy;
-       this->protected.get_randomizer = (randomizer_t* (*) (protected_ike_sa_t*)) get_randomizer;
-       this->protected.send_request = (status_t (*) (protected_ike_sa_t*,message_t*)) send_request;
-       this->protected.send_response = (status_t (*) (protected_ike_sa_t*,message_t*)) send_response;
-       this->protected.send_notify = (void (*) (protected_ike_sa_t*,exchange_type_t,notify_message_type_t,chunk_t)) send_notify;
-       this->protected.build_transforms = (status_t (*) (protected_ike_sa_t*,proposal_t*,diffie_hellman_t*,chunk_t,chunk_t)) build_transforms;
-       this->protected.set_new_state = (void (*) (protected_ike_sa_t*,state_t*)) set_new_state;
-       this->protected.get_crypter_initiator = (crypter_t* (*) (protected_ike_sa_t*)) get_crypter_initiator;
-       this->protected.get_signer_initiator = (signer_t* (*) (protected_ike_sa_t*)) get_signer_initiator;
-       this->protected.get_crypter_responder = (crypter_t* (*) (protected_ike_sa_t*)) get_crypter_responder;
-       this->protected.get_signer_responder = (signer_t* (*) (protected_ike_sa_t*)) get_signer_responder;
-       this->protected.reset_message_buffers = (void (*) (protected_ike_sa_t*)) reset_message_buffers;
-       this->protected.get_last_responded_message = (message_t* (*) (protected_ike_sa_t*)) get_last_responded_message;
-       this->protected.get_last_requested_message = (message_t* (*) (protected_ike_sa_t*)) get_last_requested_message;
-       this->protected.set_last_replied_message_id = (void (*) (protected_ike_sa_t*,u_int32_t)) set_last_replied_message_id;
-       this->protected.destroy_child_sa = (u_int32_t (*) (protected_ike_sa_t*,u_int32_t))destroy_child_sa;
-       this->protected.get_child_sa = (child_sa_t* (*) (protected_ike_sa_t*,u_int32_t))get_child_sa_by_spi;
-       this->protected.set_my_host_behind_nat = (void (*) (protected_ike_sa_t*,bool)) set_my_host_behind_nat;
-       this->protected.set_other_host_behind_nat = (void (*) (protected_ike_sa_t*,bool)) set_other_host_behind_nat;
-       this->protected.generate_natd_hash = (chunk_t (*) (protected_ike_sa_t*,u_int64_t, u_int64_t, host_t*)) generate_natd_hash;
-       this->protected.get_last_dpd_message_id = (u_int32_t (*) (protected_ike_sa_t*)) get_last_dpd_message_id;
-       this->protected.update_connection_hosts = (status_t (*) (protected_ike_sa_t*,host_t*,host_t*)) update_connection_hosts;
-       
-       /* private functions */
-       this->update_timestamp = (void (*) (private_ike_sa_t*,bool))update_timestamp;
-       this->get_last_esp_traffic_tv = (struct timeval (*) (private_ike_sa_t*,bool))get_last_esp_traffic_tv;
-
+       this->public.get_state = (ike_sa_state_t(*)(ike_sa_t*)) get_state;
+       this->public.set_state = (void(*)(ike_sa_t*,ike_sa_state_t)) set_state;
+       this->public.process_message = (status_t(*)(ike_sa_t*, message_t*)) process_message;
+       this->public.initiate = (status_t(*)(ike_sa_t*,connection_t*)) initiate;
+       this->public.get_id = (ike_sa_id_t*(*)(ike_sa_t*)) get_id;
+       this->public.get_connection = (connection_t*(*)(ike_sa_t*)) get_connection;
+       this->public.retransmit_request = (status_t (*) (ike_sa_t *, u_int32_t)) retransmit_request;
+       this->public.log_status = (void (*) (ike_sa_t*,logger_t*,char*))log_status;
+       this->public.delete = (status_t(*)(ike_sa_t*))delete_;
+       this->public.destroy = (void(*)(ike_sa_t*))destroy;
+       this->public.send_dpd = (status_t (*)(ike_sa_t*)) send_dpd;
+       this->public.send_keepalive = (void (*)(ike_sa_t*)) send_keepalive;
+       this->public.get_prf = (prf_t *(*) (ike_sa_t *)) get_prf;
+       this->public.get_child_prf = (prf_t *(*) (ike_sa_t *)) get_child_prf;
+       this->public.get_prf_auth_i = (prf_t *(*) (ike_sa_t *)) get_prf_auth_i;
+       this->public.get_prf_auth_r = (prf_t *(*) (ike_sa_t *)) get_prf_auth_r;
+       this->public.add_child_sa = (void (*) (ike_sa_t*,child_sa_t*)) add_child_sa;
+       this->public.set_connection = (void (*) (ike_sa_t *,connection_t *)) set_connection;
+       this->public.get_connection = (connection_t *(*) (ike_sa_t *)) get_connection;
+       this->public.set_policy = (void (*) (ike_sa_t *,policy_t *)) set_policy;
+       this->public.get_policy = (policy_t *(*) (ike_sa_t *)) get_policy;
+       this->public.build_transforms = (status_t (*) (ike_sa_t *,proposal_t*,diffie_hellman_t*,chunk_t,chunk_t,bool)) build_transforms;
+       this->public.destroy_child_sa = (u_int32_t (*)(ike_sa_t*,u_int32_t))destroy_child_sa;
+       this->public.get_child_sa = (child_sa_t* (*)(ike_sa_t*,u_int32_t)) get_child_sa;
+       this->public.delete_child_sa = (status_t(*)(ike_sa_t*,u_int32_t)) delete_child_sa;
+       this->public.rekey_child_sa = (status_t(*)(ike_sa_t*,u_int32_t)) rekey_child_sa;
+       this->public.enable_natt = (void(*)(ike_sa_t*, bool)) enable_natt;
+       this->public.is_natt_enabled = (bool(*)(ike_sa_t*)) is_natt_enabled;
+       
        /* initialize private fields */
        this->logger = logger_manager->get_logger(logger_manager, IKE_SA);
-       
        this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
        this->child_sas = linked_list_create();
-       this->randomizer = randomizer_create();
-       
-       this->last_requested_message = NULL;
-       this->last_responded_message = NULL;
-       this->message_id_out = 0;
-       this->message_id_in = 0;
-       this->last_replied_message_id = -1;
-       this->crypter_initiator = NULL;
-       this->crypter_responder = NULL;
-       this->signer_initiator = NULL;
-       this->signer_responder = NULL;
+       this->crypter_in = NULL;
+       this->crypter_out = NULL;
+       this->signer_in = NULL;
+       this->signer_out = NULL;
        this->prf = NULL;
        this->prf_auth_i = NULL;
        this->prf_auth_r = NULL;
        this->child_prf = NULL;
        this->connection = NULL;
        this->policy = NULL;
-       this->nat_hasher = hasher_create(HASH_SHA1);
        this->nat_here = FALSE;
        this->nat_there = FALSE;
-       this->last_msg_in_tv.tv_sec = 0;
-       this->last_msg_in_tv.tv_usec = 0;
-       this->last_msg_out_tv.tv_sec = 0;
-       this->last_msg_out_tv.tv_usec = 0;
-       this->last_dpd_message_id = 0;
-
-       /* at creation time, IKE_SA is in a initiator state */
-       if (ike_sa_id->is_initiator(ike_sa_id))
-       {
-               this->logger->log(this->logger, CONTROL | LEVEL2, "create first state_t object of type INITIATOR_INIT");
-               this->current_state = (state_t *) initiator_init_create(&(this->protected));
-       }
-       else
-       {
-               this->logger->log(this->logger, CONTROL | LEVEL2, "create first state_t object of type RESPONDER_INIT");
-               this->current_state = (state_t *) responder_init_create(&(this->protected));
-       }
-       return &(this->protected.public);
+       this->transaction_queue = linked_list_create();
+       this->transaction_in = NULL;
+       this->transaction_in_next = NULL;
+       this->transaction_out = NULL;
+       this->state = SA_CREATED;
+       this->message_id_out = 0;
+       this->time_inbound = 0;
+       this->time_outbound = 0;
+       
+       return &this->public;
 }
index 06a5930..8632719 100644 (file)
@@ -29,7 +29,6 @@
 #include <encoding/payloads/proposal_substructure.h>
 #include <sa/ike_sa_id.h>
 #include <sa/child_sa.h>
-#include <sa/states/state.h>
 #include <config/configuration.h>
 #include <utils/logger.h>
 #include <utils/randomizer.h>
 #include <config/policies/policy.h>
 #include <utils/logger.h>
 
+
+typedef enum ike_sa_state_t ike_sa_state_t;
+
 /**
- * Nonce size in bytes for nonces sending to other peer.
- * 
- * @warning Nonce size MUST be between 16 and 256 bytes.
+ * @brief State of an IKE_SA.
  * 
  * @ingroup sa
  */
-#define NONCE_SIZE 16
+enum ike_sa_state_t {
+       
+       /**
+        * IKE_SA just got created, but is not initiating nor responding yet.
+        */
+       SA_CREATED,
+       
+       /**
+        * IKE_SA gets initiated actively or passively
+        */
+       SA_CONNECTING,
+       
+       /**
+        * IKE_SA is fully established
+        */
+       SA_ESTABLISHED,
+       
+       /**
+        * IKE_SA is in progress of deletion
+        */
+       SA_DELETING,
+};
+
+/**
+ * String mappings for ike_sa_state_t.
+ */
+extern mapping_t ike_sa_state_m[];
 
 
 typedef struct ike_sa_t ike_sa_t;
 
 /**
- * @brief Class ike_sa_t representing an IKE_SA. 
- * 
- * An object of this type is managed by an ike_sa_manager_t object 
- * and represents an IKE_SA. Message processing is split up in different states. 
- * They will handle all related things for the state they represent.
- * 
+ * @brief Class ike_sa_t representing an IKE_SA.
+ *
+ * An IKE_SA contains crypto information related to a connection
+ * with a peer. It contains multiple IPsec CHILD_SA, for which
+ * it is responsible. All traffic is handled by an IKE_SA, using
+ * transactions.
+ *
  * @b Constructors:
  * - ike_sa_create()
  * 
@@ -67,20 +94,34 @@ typedef struct ike_sa_t ike_sa_t;
 struct ike_sa_t {
 
        /**
-        * @brief Processes a incoming IKEv2-Message of type message_t.
+        * @brief Get the id of the SA.
+        * 
+        * Returned ike_sa_id_t object is not getting cloned!
         *
-        * @param this ike_sa_t object object
-        * @param[in] message message_t object to process
-        * @return                              
-        *                                              - SUCCESS
-        *                                              - FAILED
-        *                                              - DESTROY_ME if this IKE_SA MUST be deleted
+        * @param this                  calling object
+        * @return                              ike_sa's ike_sa_id_t
         */
-       status_t (*process_message) (ike_sa_t *this,message_t *message);
+       ike_sa_id_t* (*get_id) (ike_sa_t *this);
+       
+       /**
+        * @brief Get the state of the IKE_SA.
+        *
+        * @param this                  calling object
+        * @return                              state of the IKE_SA
+        */
+       ike_sa_state_t (*get_state) (ike_sa_t *this);
+       
+       /**
+        * @brief Set the state of the IKE_SA.
+        *
+        * @param this                  calling object
+        * @param state                 state to set for the IKE_SA
+        */
+       void (*set_state) (ike_sa_t *this, ike_sa_state_t ike_sa);
 
        /**
-        * @brief Initiate a new connection with given connection_t object.
-        * 
+        * @brief Initiate a new connection.
+        *
         * The connection_t object is owned by the IKE_SA after the call, so
         * do not modify or destroy it.
         * 
@@ -91,19 +132,24 @@ struct ike_sa_t {
         *                                              - FAILED if in wrong state
         *                                              - DESTROY_ME if initialization failed and IKE_SA MUST be deleted
         */
-       status_t (*initiate_connection) (ike_sa_t *this, connection_t *connection);
+       status_t (*initiate) (ike_sa_t *this, connection_t *connection);
        
        /**
-        * @brief Checks whether retransmission is possible.
+        * @brief Initiates the deletion of an IKE_SA.
+        * 
+        * Sends a delete message to the remote peer and waits for
+        * its response. If the response comes in, or a timeout occurs,
+        * the IKE SA gets deleted.
         * 
         * @param this                  calling object
-        * @param message_id    ID of the request to retransmit
         * @return
-        *                                              - TRUE if retransmit is possible
-        *                                              - FALSE if not
+        *                                              - SUCCESS if deletion is initialized
+        *                                              - INVALID_STATE, if the IKE_SA is not in 
+        *                                                an established state and can not be
+        *                                                delete (but destroyed).
         */
-       bool (*retransmit_possible) (ike_sa_t *this, u_int32_t message_id);
-
+       status_t (*delete) (ike_sa_t *this);
+       
        /**
         * @brief Retransmits a request.
         * 
@@ -114,157 +160,71 @@ struct ike_sa_t {
         *                                              - NOT_FOUND if request doesn't have to be retransmited
         */
        status_t (*retransmit_request) (ike_sa_t *this, u_int32_t message_id);
-
-       /**
-        * @brief Get the id of the SA.
-        * 
-        * Returned ike_sa_id_t object is not getting cloned!
-        *
-        * @param this                  calling object
-        * @return                              ike_sa's ike_sa_id_t
-        */
-       ike_sa_id_t* (*get_id) (ike_sa_t *this);
-
-       /**
-        * @brief Get the CHILD_SA with the specified reqid.
-        *
-        * The reqid is a unique ID for a child SA, which is 
-        * generated on child SA creation.
-        * Returned child_sa_t object is not cloned!
-        *
-        * @param this                  calling object
-        * @param reqid                 reqid of the child SA, as used in the kernel
-        * @return                              child_sa, or NULL if not found
-        */
-       child_sa_t* (*get_child_sa) (ike_sa_t *this, u_int32_t reqid);
-
-       /**
-        * @brief Close the CHILD SA with the specified reqid.
-        *
-        * Looks for a CHILD SA owned by this IKE_SA, deletes it and
-        * notify's the remote peer about the delete. The associated
-        * states and policies in the kernel get deleted, if they exist.
-        *
-        * @param this                  calling object
-        * @param reqid                 reqid of the child SA, as used in the kernel
-        * @return
-        *                                              - NOT_FOUND, if IKE_SA has no such CHILD_SA
-        *                                              - SUCCESS, if deleted and delete message sent
-        */
-       status_t (*delete_child_sa) (ike_sa_t *this, u_int32_t reqid);
-
-       /**
-        * @brief Rekey the CHILD SA with the specified reqid.
-        *
-        * Looks for a CHILD SA owned by this IKE_SA, and start the rekeing.
-        *
-        * @param this                  calling object
-        * @param spi                   security parameter index identifying the SA to rekey
-        * @return
-        *                                              - NOT_FOUND, if IKE_SA has no such CHILD_SA
-        *                                              - SUCCESS, if rekeying initiated
-        */
-       status_t (*rekey_child_sa) (ike_sa_t *this, u_int32_t reqid);
-
-       /**
-        * @brief Get local peer address of the IKE_SA.
-        *
-        * @param this                  calling object
-        * @return                              local host_t
-        */
-       host_t* (*get_my_host) (ike_sa_t *this);
-
-       /**
-        * @brief Get remote peer address of the IKE_SA.
-        *
-        * @param this                  calling object
-        * @return                              remote host_t
-        */
-       host_t* (*get_other_host) (ike_sa_t *this);
-
-       /**
-        * @brief Get own ID of the IKE_SA.
-        *
-        * @param this                  calling object
-        * @return                              local identification_t
-        */
-       identification_t* (*get_my_id) (ike_sa_t *this);
-
+       
        /**
-        * @brief Get remote ID the IKE_SA.
+        * @brief Processes a incoming IKEv2-Message.
         *
-        * @param this                  calling object
-        * @return                              remote identification_t
-        */
-       identification_t* (*get_other_id) (ike_sa_t *this);
-
-       /**
-        * @brief Get the connection of the IKE_SA.
+        * Message processing may fail. If a critical failure occurs, 
+        * process_message() return DESTROY_ME. Then the caller must 
+        * destroy the IKE_SA immediatly, as it is unusable.
         * 
-        * The internal used connection specification 
-        * can be queried to get some data of an IKE_SA.
-        * The connection is still owned to the IKE_SA
-        * and must not be manipulated.
-        *
         * @param this                  calling object
-        * @return                              connection_t
+        * @param[in] message   message to process
+        * @return                              
+        *                                              - SUCCESS
+        *                                              - FAILED
+        *                                              - DESTROY_ME if this IKE_SA MUST be deleted
         */
-       connection_t* (*get_connection) (ike_sa_t *this);
+       status_t (*process_message) (ike_sa_t *this,message_t *message);
        
        /**
-        * @brief Query NAT detection status for local host.
+        * @brief Check if NAT traversal is enabled for this IKE_SA.
         *
         * @param this                  calling object
-        * @return                              TRUE if this host is behind NAT
+        * @return                              TRUE if NAT traversal enabled
         */
-       bool (*is_my_host_behind_nat) (ike_sa_t *this);
+       bool (*is_natt_enabled) (ike_sa_t *this);
 
        /**
-        * @brief Query NAT detection status for remote host.
+        * @brief Enable NAT detection for this IKE_SA.
         *
-        * @param this                  calling object
-        * @return                              TRUE if other host is behind NAT
-        */
-       bool (*is_other_host_behind_nat) (ike_sa_t *this);
-
-       /**
-        * @brief Query NAT detection status for any host.
+        * If a Network address translation is detected with
+        * NAT_DETECTION notifys, a SA must switch to ports
+        * 4500. To enable this behavior, call enable_natt().
+        * It is relevant which peer is NATted, this is specified
+        * with the "local" parameter. Call it twice when both
+        * are NATted.
         *
         * @param this                  calling object
-        * @return                              TRUE if this or other host is behind NAT
+        * @param local                 TRUE, if we are NATted, FALSE if other
         */
-       bool (*is_any_host_behind_nat) (ike_sa_t *this);
+       void (*enable_natt) (ike_sa_t *this, bool local);
 
        /**
-        * @brief Query timeval of last inbound IKE or ESP traffic.
+        * @brief Sends a DPD request to the peer.
         *
+        * To check if a peer is still alive, periodic
+        * empty INFORMATIONAL messages are sent if no
+        * other traffic was received.
+        * 
         * @param this                  calling object
-        * @return                              time when the last traffic was seen
+        * @return
+        *                                              - SUCCESS
+        *                                              - DESTROY_ME, if peer did not respond
         */
-       struct timeval (*get_last_traffic_in_tv) (ike_sa_t *this);
-
+       status_t (*send_dpd) (ike_sa_t *this);
+       
        /**
-        * @brief Query timeval of last outbound IKE or ESP traffic.
+        * @brief Sends a keep alive packet.
         *
-        * @param this                  calling object
-        * @return                              time when the last traffic was seen
-        */
-       struct timeval (*get_last_traffic_out_tv) (ike_sa_t *this);
-
-       /**
-        * @brief Get the state of type of associated state object.
+        * To refresh NAT tables in a NAT router
+        * between the peers, periodic empty
+        * UDP packets are sent if no other traffic
+        * was sent.
         *
-        * @param this                  calling object
-        * @return                              state of IKE_SA
-        */
-       ike_sa_state_t (*get_state) (ike_sa_t *this);
-       
-       /**
-        * @brief Sends a DPD request to the peer.
-        * 
         * @param this                          calling object
         */
-       status_t (*send_dpd_request) (ike_sa_t *this);
+       void (*send_keepalive) (ike_sa_t *this);
        
        /**
         * @brief Log the status of a the ike sa to a logger.
@@ -279,71 +239,14 @@ struct ike_sa_t {
         * @param name          name of the connection
         */     
        void (*log_status) (ike_sa_t *this, logger_t *logger, char *name);
-       
-       /**
-        * @brief Initiates the deletion of an IKE_SA.
-        * 
-        * Sends a delete message to the remote peer and waits for
-        * its response. If the response comes in, or a timeout occurs,
-        * the IKE SA gets deleted.
-        * 
-        * @param this                  calling object
-        * @return
-        *                                              - SUCCESS if deletion is initialized
-        *                                              - INVALID_STATE, if the IKE_SA is not in 
-        *                                                an established state and can not be
-        *                                                delete (but destroyed).
-        */
-       status_t (*delete) (ike_sa_t *this);
-
-       /**
-        * @brief Destroys a ike_sa_t object.
-        *
-        * @param this                  calling object
-        */
-       void (*destroy) (ike_sa_t *this);
-};
-
-
-typedef struct protected_ike_sa_t protected_ike_sa_t;
-
-/**
- * @brief Protected functions of an ike_sa_t object.
- * 
- * This members are only accessed out from 
- * the various state_t implementations.
- * 
- * @ingroup sa
- */
-struct protected_ike_sa_t {
-
-       /**
-        * Public interface of an ike_sa_t object.
-        */
-       ike_sa_t public;
-       
-       /**
-        * @brief Build an empty IKEv2-Message and fills in default informations.
-        * 
-        * Depending on the type of message (request or response), the message id is 
-        * either message_id_out or message_id_in.
-        * 
-        * Used in state_t Implementation to build an empty IKEv2-Message.
-        * 
-        * @param this                          calling object
-        * @param type                          exchange type of new message
-        * @param request                       TRUE, if message has to be a request
-        * @param message                       new message is stored at this location
-        */
-       void (*build_message) (protected_ike_sa_t *this, exchange_type_t type, bool request, message_t **message);
-       
+               
        /**
         * @brief Get the internal stored connection_t object.
         * 
         * @param this                          calling object
         * @return                                      pointer to the internal stored connection_t object
         */
-       connection_t *(*get_connection) (protected_ike_sa_t *this);
+       connection_t *(*get_connection) (ike_sa_t *this);
        
        /**
         * @brief Set the internal connection object.
@@ -351,7 +254,7 @@ struct protected_ike_sa_t {
         * @param this                          calling object
         * @param connection            object of type connection_t
         */
-       void (*set_connection) (protected_ike_sa_t *this, connection_t *connection);
+       void (*set_connection) (ike_sa_t *this, connection_t *connection);
        
        /**
         * @brief Get the internal stored policy object.
@@ -359,7 +262,7 @@ struct protected_ike_sa_t {
         * @param this                          calling object
         * @return                                      pointer to the internal stored policy_t object
         */
-       policy_t *(*get_policy) (protected_ike_sa_t *this);
+       policy_t *(*get_policy) (ike_sa_t *this);
        
        /**
         * @brief Set the internal policy_t object.
@@ -367,274 +270,135 @@ struct protected_ike_sa_t {
         * @param this                          calling object
         * @param policy                        object of type policy_t
         */
-       void (*set_policy) (protected_ike_sa_t *this,policy_t *policy);
-       
+       void (*set_policy) (ike_sa_t *this, policy_t *policy);
+
        /**
         * @brief Derive all keys and create the transforms for IKE communication.
         * 
         * Keys are derived using the diffie hellman secret, nonces and internal
-        * stored SPIs. 
+        * stored SPIs.
         * Already existing objects get destroyed.
         * 
-        * @param this                          calling object
-        * @param proposal                      proposal which contains algorithms to use
-        * @param dh                            diffie hellman object with shared secret
-        * @param nonce_i                       initiators nonce
-        * @param nonce_r                       responders nonce
-        */
-       status_t (*build_transforms) (protected_ike_sa_t *this, proposal_t* proposal,
-                                                                diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r);
-       
-       /**
-        * @brief Send the next request message.
-        * 
-        * Also the first retransmit job is created.
-        * 
-        * Last stored requested message gets destroyed. Object gets not cloned!
-        * 
-        * @param this                          calling object
-        * @param message                       pointer to the message which should be sent
-        * @return
-        *                                                      - SUCCESS
-        *                                                      - FAILED if message id is not next expected one
-        */
-       status_t (*send_request) (protected_ike_sa_t *this,message_t * message);
-
-       /**
-        * @brief Send the next response message.
-        * 
-        * Last stored responded message gets destroyed. Object gets not cloned!
-        * 
-        * @param this                          calling object
-        * @param message                       pointer to the message which should be sent
-        * return                                       
-        *                                                      - SUCCESS
-        *                                                      - FAILED if message id is not next expected one
-        */
-       status_t (*send_response) (protected_ike_sa_t *this,message_t * message);
-
-       /**
-        * @brief Send a notify reply message.
-        * 
-        * @param this                          calling object
-        * @param exchange_type         type of exchange in which the notify should be wrapped
-        * @param type                          type of the notify message to send
-        * @param data                          notification data
-        */
-       void (*send_notify) (protected_ike_sa_t *this, exchange_type_t exchange_type, notify_message_type_t type, chunk_t data);
-       
-       /**
-        * @brief Get the internal stored randomizer_t object.
-        * 
-        * @param this                          calling object
-        * @return                                      pointer to the internal randomizer_t object
-        */
-       randomizer_t *(*get_randomizer) (protected_ike_sa_t *this);
-       
-       /**
-        * @brief Set the new state_t object of the IKE_SA object.
-        * 
-        * The old state_t object gets not destroyed. It's the callers duty to 
-        * make sure old state is destroyed (Normally the old state is the caller).
-        * 
-        * @param this                          calling object
-        * @param state                         pointer to the new state_t object
-        */
-       void (*set_new_state) (protected_ike_sa_t *this,state_t *state);
-       
-       /**
-        * @brief Set the last replied message id.
-        * 
-        * @param this                          calling object
-        * @param message_id            message id
-        */
-       void (*set_last_replied_message_id) (protected_ike_sa_t *this,u_int32_t message_id);
-       
-       /**
-        * @brief Get the internal stored initiator crypter_t object.
-        * 
-        * @param this                          calling object
-        * @return                                      pointer to crypter_t object
-        */
-       crypter_t *(*get_crypter_initiator) (protected_ike_sa_t *this);
-       
-       /**
-        * @brief Get the internal stored initiator signer_t object.
-        * 
-        * @param this                          calling object
-        * @return                                      pointer to signer_t object
-        */
-       signer_t *(*get_signer_initiator) (protected_ike_sa_t *this);
-       
-       /**
-        * @brief Get the internal stored responder crypter_t object.
-        * 
-        * @param this                          calling object
-        * @return                                      pointer to crypter_t object
-        */
-       crypter_t *(*get_crypter_responder) (protected_ike_sa_t *this);
-       
-       /**
-        * @brief Get the internal stored responder signer object.
-        * 
-        * @param this                          calling object
-        * @return                                      pointer to signer_t object
-        */
-       signer_t *(*get_signer_responder) (protected_ike_sa_t *this);
+        * @param this                  calling object
+        * @param proposal              proposal which contains algorithms to use
+        * @param dh                    diffie hellman object with shared secret
+        * @param nonce_i               initiators nonce
+        * @param nonce_r               responders nonce
+        * @param initiator             role of this IKE SA (TRUE = originial initiator)
+        */
+       status_t (*build_transforms) (ike_sa_t *this, proposal_t* proposal,
+                                                                 diffie_hellman_t *dh,
+                                                                 chunk_t nonce_i, chunk_t nonce_r,
+                                                                 bool initiator);
        
        /**
         * @brief Get the multi purpose prf.
         * 
-        * @param this                          calling object
-        * @return                                      pointer to prf_t object
+        * @param this                  calling object
+        * @return                              pointer to prf_t object
         */
-       prf_t *(*get_prf) (protected_ike_sa_t *this);
+       prf_t *(*get_prf) (ike_sa_t *this);
        
        /**
         * @brief Get the prf-object, which is used to derive keys for child SAs.
         * 
-        * @param this                          calling object
-        * @return                                      pointer to prf_t object
+        * @param this                  calling object
+        * @return                              pointer to prf_t object
         */
-       prf_t *(*get_child_prf) (protected_ike_sa_t *this);
+       prf_t *(*get_child_prf) (ike_sa_t *this);
        
        /**
         * @brief Get the prf used for authentication of initiator.
         * 
-        * @param this                          calling object
-        * @return                                      pointer to prf_t object
+        * @param this                  calling object
+        * @return                              pointer to prf_t object
         */
-       prf_t *(*get_prf_auth_i) (protected_ike_sa_t *this);
+       prf_t *(*get_prf_auth_i) (ike_sa_t *this);
        
        /**
         * @brief Get the prf used for authentication of responder.
         * 
-        * @param this                          calling object
-        * @return                                      pointer to prf_t object
-        */
-       prf_t *(*get_prf_auth_r) (protected_ike_sa_t *this);
-       
-       /**
-        * @brief Associates a child SA to this IKE SA
-        * 
-        * @param this                          calling object
-        * @param child_sa                      child_sa to add
-        */
-       void (*add_child_sa) (protected_ike_sa_t *this, child_sa_t *child_sa);
-       
-       /**
-        * @brief Destroys a CHILD_SA upon request from the other peer.
-        * 
-        * @param this                          calling object
-        * @param spi                           inbound spi of the CHILD_SA to destroy
-        * @return                                      outbound spi of the destroyed CHILD_SA
+        * @param this                  calling object
+        * @return                              pointer to prf_t object
         */
-       u_int32_t (*destroy_child_sa) (protected_ike_sa_t *this, u_int32_t spi);
+       prf_t *(*get_prf_auth_r) (ike_sa_t *this);
        
        /**
         * @brief Get a CHILD_SA upon request from the other peer.
         * 
-        * @param this                          calling object
-        * @param spi                           spi of the CHILD_SA
-        * @return                                      child_sa, or NULL if none found
+        * @param this                  calling object
+        * @param spi                   spi of the CHILD_SA
+        * @return                              child_sa, or NULL if none found
         */
-       child_sa_t* (*get_child_sa) (protected_ike_sa_t *this, u_int32_t spi);
+       child_sa_t* (*get_child_sa) (ike_sa_t *this, u_int32_t spi);
 
        /**
-        * @brief establish the IKE SA
+        * @brief Close the CHILD SA with the specified reqid.
+        *
+        * Looks for a CHILD SA owned by this IKE_SA, deletes it and
+        * notify's the remote peer about the delete. The associated
+        * states and policies in the kernel get deleted, if they exist.
         *
         * @param this                  calling object
-        */
-       void (*establish) (protected_ike_sa_t *this);
-
-       /**
-        * @brief Get the last responded message.
-        *  
-        * @param this                          calling object
-        * @return                                      
-        *                                                      - last received as message_t object 
-        *                                                      - NULL if no last request available
-        */
-       message_t *(*get_last_responded_message) (protected_ike_sa_t *this);
-       
-       /**
-        * @brief Get the last requested message.
-        *  
-        * @param this                          calling object
-        * @return                                      
-        *                                                      - last sent as message_t object 
-        *                                                      - NULL if no last request available
-        */
-       message_t *(*get_last_requested_message) (protected_ike_sa_t *this);
-
-       /**
-        * @brief Resets message counters and does destroy stored received and sent messages.
+        * @param reqid                 reqid of the child SA, as used in the kernel
+        * @return
+        *                                              - NOT_FOUND, if IKE_SA has no such CHILD_SA
+        *                                              - SUCCESS, if deleted and delete message sent
         * 
-        * @param this                          calling object
-        */     
-       void (*reset_message_buffers) (protected_ike_sa_t *this);
+        * @TODO use spi, not reqid
+        */
+       status_t (*delete_child_sa) (ike_sa_t *this, u_int32_t reqid);
        
        /**
-        * @brief Set NAT detection status for local host.
+        * @brief Rekey the CHILD SA with the specified reqid.
         *
-        * @param this                          calling object
-        * @param nat                           if TRUE, local host is behing NAT
-        */
-       void (*set_my_host_behind_nat) (protected_ike_sa_t *this, bool nat);
-
-       /**
-        * @brief Set NAT detection status for remote host.
+        * Looks for a CHILD SA owned by this IKE_SA, and start the rekeing.
         *
-        * @param this                          calling object
-        * @param nat                           if TRUE, remote host is behing NAT
+        * @param this                  calling object
+        * @param spi                   security parameter index identifying the SA to rekey
+        * @return
+        *                                              - NOT_FOUND, if IKE_SA has no such CHILD_SA
+        *                                              - SUCCESS, if rekeying initiated
+        * 
+        * @TODO use spi, not reqid
         */
-       void (*set_other_host_behind_nat) (protected_ike_sa_t *this, bool nat);
-
+       status_t (*rekey_child_sa) (ike_sa_t *this, u_int32_t reqid);
+       
        /**
-        * @brief Generate NAT-D payload hash.
-        *
-        * @param this                          calling object
-        * @param spi_i                         IKE SPI of initiator
-        * @param spi_r                         IKE SPI of responder
-        * @param host                          address and port of the host/interface
-        * @return                                      chunk containing calculated NAT-D hash
+        * @brief Associates a child SA to this IKE SA
+        * 
+        * @param this                  calling object
+        * @param child_sa              child_sa to add
         */
-       chunk_t (*generate_natd_hash) (protected_ike_sa_t *this, u_int64_t spi_i, u_int64_t spi_r, host_t *host);
-
+       void (*add_child_sa) (ike_sa_t *this, child_sa_t *child_sa);
+       
        /**
-        * @brief Dynamically update hosts on the associated connection.
-        *
-        * Warning: me and other host are cloned.
-        *
-        * @param this                          calling object
-        * @param me                            local address and port
-        * @param other                         remote address and port
+        * @brief Destroys a CHILD_SA upon request from the other peer.
+        * 
+        * @param this                  calling object
+        * @param spi                   inbound spi of the CHILD_SA to destroy
+        * @return                              outbound spi of the destroyed CHILD_SA
         */
-       status_t (*update_connection_hosts) (protected_ike_sa_t *this, host_t *me, host_t *other);
-
+       u_int32_t (*destroy_child_sa) (ike_sa_t *this, u_int32_t spi);
+       
        /**
-        * @brief Return the message id of the last DPD message
+        * @brief Destroys a ike_sa_t object.
         *
-        * @param this                          calling object
-        * @return                              the messages id
+        * @param this                  calling object
         */
-       u_int32_t (*get_last_dpd_message_id) (protected_ike_sa_t *this);
+       void (*destroy) (ike_sa_t *this);
 };
 
-
 /**
  * @brief Creates an ike_sa_t object with a specific ID.
- * 
- * @warning the Content of internal ike_sa_id_t object can change over time
- *                     e.g. when a IKE_SA_INIT has been finished.
  *
- * @param[in] ike_sa_id        ike_sa_id_t object to associate with new IKE_SA.
- *                                                     The object is internal getting cloned
- *                                                     and so has to be destroyed by the caller.
+ * The ID gets cloned internally.
+ *
+ * @param[in] ike_sa_id        ike_sa_id_t object to associate with new IKE_SA
  * @return                                     ike_sa_t object
  * 
  * @ingroup sa
  */
-ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id);
+ike_sa_t *ike_sa_create(ike_sa_id_t *ike_sa_id);
 
 #endif /*IKE_SA_H_*/
index bf3a05d..4f1f33b 100644 (file)
@@ -181,5 +181,5 @@ ike_sa_id_t * ike_sa_id_create(u_int64_t initiator_spi, u_int64_t responder_spi,
        this->responder_spi = responder_spi;
        this->is_initiator_flag = is_initiator_flag;
 
-       return (&this->public);
+       return &this->public;
 }
index 82f5d22..1aad1b3 100644 (file)
@@ -175,7 +175,7 @@ struct private_ike_sa_manager_t {
         status_t (*get_entry_by_sa) (private_ike_sa_manager_t *this, ike_sa_t *ike_sa, ike_sa_entry_t **entry);
         
         /**
-         * @brief Felete an entry from the linked list.
+         * @brief Delete an entry from the linked list.
          *
          * @param this                 calling object
          * @param entry                entry to delete
@@ -229,10 +229,13 @@ static status_t get_entry_by_id(private_ike_sa_manager_t *this, ike_sa_id_t *ike
                if (current->ike_sa_id->get_responder_spi(current->ike_sa_id) == 0)
                {
                        /* seems to be a half ready ike_sa */
-                       if ((current->ike_sa_id->get_initiator_spi(current->ike_sa_id) == ike_sa_id->get_initiator_spi(ike_sa_id))
-                               && (ike_sa_id->is_initiator(ike_sa_id) == current->ike_sa_id->is_initiator(current->ike_sa_id)))
+                       if ((current->ike_sa_id->get_initiator_spi(current->ike_sa_id) ==
+                                                 ike_sa_id->get_initiator_spi(ike_sa_id)) &&
+                               (ike_sa_id->is_initiator(ike_sa_id) == 
+                                                 current->ike_sa_id->is_initiator(current->ike_sa_id)))
                        {
-                               this->logger->log(this->logger, CONTROL|LEVEL2, "found entry by initiator spi %d",
+                               this->logger->log(this->logger, CONTROL|LEVEL2, 
+                                                                 "found entry by initiator spi %d",
                                                                  ike_sa_id->get_initiator_spi(ike_sa_id));
                                *entry = current;
                                status = SUCCESS;
@@ -241,8 +244,10 @@ static status_t get_entry_by_id(private_ike_sa_manager_t *this, ike_sa_id_t *ike
                }
                else if (ike_sa_id->get_responder_spi(ike_sa_id) == 0)
                {
-                       if ((current->ike_sa_id->get_initiator_spi(current->ike_sa_id) == ike_sa_id->get_initiator_spi(ike_sa_id))
-                               && (ike_sa_id->is_initiator(ike_sa_id) == current->ike_sa_id->is_initiator(current->ike_sa_id)))
+                       if ((current->ike_sa_id->get_initiator_spi(current->ike_sa_id) == 
+                                                 ike_sa_id->get_initiator_spi(ike_sa_id)) &&
+                               (ike_sa_id->is_initiator(ike_sa_id) == 
+                                                 current->ike_sa_id->is_initiator(current->ike_sa_id)))
                        {
                                this->logger->log(this->logger, CONTROL|LEVEL2, "found entry by initiator spi %d",
                                                                  ike_sa_id->get_initiator_spi(ike_sa_id));
@@ -315,7 +320,8 @@ static status_t delete_entry(private_ike_sa_manager_t *this, ike_sa_entry_t *ent
                iterator->current(iterator, (void**)&current);
                if (current == entry) 
                {
-                       this->logger->log(this->logger, CONTROL|LEVEL2, "found entry by pointer. Going to delete it.");
+                       this->logger->log(this->logger, CONTROL|LEVEL2, 
+                                                         "found entry by pointer. Going to delete it");
                        iterator->remove(iterator);
                        entry->destroy(entry);
                        status = SUCCESS;
@@ -355,6 +361,11 @@ static void create_and_checkout(private_ike_sa_manager_t *this,ike_sa_t **ike_sa
        /* create entry */
        new_ike_sa_entry = ike_sa_entry_create(new_ike_sa_id);
        new_ike_sa_id->destroy(new_ike_sa_id);
+       this->logger->log(this->logger, CONTROL|LEVEL2,
+                                         "created IKE_SA %llx:%llx, role %s",
+                                         new_ike_sa_id->get_initiator_spi(new_ike_sa_id),
+                                         new_ike_sa_id->get_responder_spi(new_ike_sa_id),
+                                         new_ike_sa_id->is_initiator(new_ike_sa_id) ? "initiator" : "responder");
 
        /* each access is locked */
        pthread_mutex_lock(&(this->mutex));
@@ -362,7 +373,8 @@ static void create_and_checkout(private_ike_sa_manager_t *this,ike_sa_t **ike_sa
        this->ike_sa_list->insert_last(this->ike_sa_list, new_ike_sa_entry);
 
        /* check ike_sa out */
-       this->logger->log(this->logger, CONTROL|LEVEL1, "new IKE_SA created and added to list of known IKE_SA's");
+       this->logger->log(this->logger, CONTROL|LEVEL1, 
+                                         "new IKE_SA created and added to list of known IKE_SA's");
        new_ike_sa_entry->checked_out = TRUE;
        *ike_sa = new_ike_sa_entry->ike_sa;
 
@@ -379,6 +391,15 @@ static status_t checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id,
        bool original_initiator;
        status_t retval;
        
+       this->logger->log(this->logger, CONTROL|LEVEL2,
+                                         "checkout IKE_SA %llx:%llx, role %s",
+                                         ike_sa_id->get_initiator_spi(ike_sa_id),
+                                         ike_sa_id->get_responder_spi(ike_sa_id),
+                                         ike_sa_id->is_initiator(ike_sa_id) ? "initiator" : "responder");
+       
+       this->logger->log(this->logger, CONTROL|LEVEL2, "%d IKE_SAs in manager",
+                                         this->ike_sa_list->get_count(this->ike_sa_list));
+       
        /* each access is locked */
        pthread_mutex_lock(&(this->mutex));
        
@@ -399,7 +420,8 @@ static status_t checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id,
                        /* can we give this ike_sa out to new requesters?*/
                        if (entry->driveout_new_threads)
                        {
-                               this->logger->log(this->logger, CONTROL|LEVEL1, "drive out new thread for existing IKE_SA");
+                               this->logger->log(this->logger, CONTROL|LEVEL1, 
+                                                                 "drive out new thread for existing IKE_SA");
                                /* no we can't */
                                retval = NOT_FOUND;
                        }
@@ -422,12 +444,14 @@ static status_t checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id,
                                {
                                        /* we must signal here, others are interested that we leave */
                                        pthread_cond_signal(&(entry->condvar));
-                                       this->logger->log(this->logger, CONTROL|LEVEL1, "drive out waiting thread for existing IKE_SA");
+                                       this->logger->log(this->logger, CONTROL|LEVEL1, 
+                                                                         "drive out waiting thread for existing IKE_SA");
                                        retval = NOT_FOUND;
                                }
                                else
                                {
-                                       this->logger->log(this->logger, CONTROL|LEVEL2, "IKE SA successfully checked out");
+                                       this->logger->log(this->logger, CONTROL|LEVEL2, 
+                                                                         "IKE SA successfully checked out");
                                        /* ok, this IKE_SA is finally ours */
                                        entry->checked_out = TRUE;
                                        *ike_sa = entry->ike_sa;
@@ -438,7 +462,8 @@ static status_t checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id,
                }
                else
                {
-                       this->logger->log(this->logger, ERROR|LEVEL1, "IKE SA not stored in known IKE_SA list");
+                       this->logger->log(this->logger, ERROR|LEVEL1, 
+                                                         "IKE SA not stored in known IKE_SA list");
                        /* looks like there is no such IKE_SA, better luck next time... */
                        /* DON'T use return, we must unlock the mutex! */
                        retval = NOT_FOUND;
@@ -469,11 +494,12 @@ static status_t checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id,
                this->ike_sa_list->insert_last(this->ike_sa_list, new_ike_sa_entry);
                
                /* check ike_sa out */
-               this->logger->log(this->logger, CONTROL|LEVEL1 ,"IKE_SA added to list of known IKE_SA's");
+               this->logger->log(this->logger, CONTROL|LEVEL1,
+                                                 "IKE_SA added to list of known IKE_SA's");
                new_ike_sa_entry->checked_out = TRUE;
                *ike_sa = new_ike_sa_entry->ike_sa;
                
-               retval = CREATED;
+               retval = SUCCESS;
        }
        else
        {
@@ -482,7 +508,7 @@ static status_t checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id,
                /* DON'T use return, we must unlock the mutex! */
                retval = INVALID_ARG;
        }
-
+       
        pthread_mutex_unlock(&(this->mutex));
        /* OK, unlocked... */
        return retval;
@@ -491,7 +517,8 @@ static status_t checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id,
 /**
  * Implementation of of ike_sa_manager.checkout_by_reqid.
  */
-static status_t checkout_by_reqid(private_ike_sa_manager_t *this, u_int32_t reqid, ike_sa_t **ike_sa)
+static status_t checkout_by_reqid(private_ike_sa_manager_t *this, 
+                                                                 u_int32_t reqid, ike_sa_t **ike_sa)
 {
        iterator_t *iterator;
        status_t status = NOT_FOUND;
@@ -600,15 +627,16 @@ linked_list_t *get_ike_sa_list_by_name(private_ike_sa_manager_t* this, const cha
 static void log_status(private_ike_sa_manager_t* this, logger_t* logger, char* name)
 {
        iterator_t *iterator;
+       u_int instances;
        
        pthread_mutex_lock(&(this->mutex));
        
-       iterator = this->ike_sa_list->create_iterator(this->ike_sa_list, TRUE);
-
-       if (iterator->get_count(iterator))
+       instances = this->ike_sa_list->get_count(this->ike_sa_list);
+       if (instances)
        {
-               logger->log(logger, CONTROL, "Instances:");
+               logger->log(logger, CONTROL, "Instances (%d):", instances);
        }
+       iterator = this->ike_sa_list->create_iterator(this->ike_sa_list, TRUE);
        while (iterator->has_next(iterator))
        {
                ike_sa_entry_t *entry;
@@ -633,6 +661,15 @@ static status_t checkin(private_ike_sa_manager_t *this, ike_sa_t *ike_sa)
         */
        status_t retval;
        ike_sa_entry_t *entry;
+       ike_sa_id_t *ike_sa_id;
+       
+       ike_sa_id = ike_sa->get_id(ike_sa);
+       
+       this->logger->log(this->logger, CONTROL|LEVEL2,
+                                          "checkin IKE_SA %llx:%llx, role %s",
+                                         ike_sa_id->get_initiator_spi(ike_sa_id),
+                                         ike_sa_id->get_responder_spi(ike_sa_id),
+                                         ike_sa_id->is_initiator(ike_sa_id) ? "initiator" : "responder");
        
        pthread_mutex_lock(&(this->mutex));
 
@@ -649,10 +686,14 @@ static status_t checkin(private_ike_sa_manager_t *this, ike_sa_t *ike_sa)
        }
        else
        {
-               this->logger->log(this->logger, ERROR, "tried to check in nonexisting IKE_SA");
+               this->logger->log(this->logger, ERROR, 
+                                                 "tried to check in nonexisting IKE_SA");
                /* this SA is no more, this REALLY should not happen */
                retval = NOT_FOUND;
        }
+       
+       this->logger->log(this->logger, CONTROL|LEVEL2, "%d IKE_SAs in manager now",
+                               this->ike_sa_list->get_count(this->ike_sa_list));
        pthread_mutex_unlock(&(this->mutex));
        return retval;
 }
@@ -670,6 +711,14 @@ static status_t checkin_and_destroy(private_ike_sa_manager_t *this, ike_sa_t *ik
         */
        ike_sa_entry_t *entry;
        status_t retval;
+       ike_sa_id_t *ike_sa_id;
+       
+       ike_sa_id = ike_sa->get_id(ike_sa);
+       this->logger->log(this->logger, CONTROL|LEVEL2,
+                                         "checkin and destroy IKE_SA %llx:%llx, role %s",
+                                         ike_sa_id->get_initiator_spi(ike_sa_id),
+                                         ike_sa_id->get_responder_spi(ike_sa_id),
+                                         ike_sa_id->is_initiator(ike_sa_id) ? "initiator" : "responder");
 
        pthread_mutex_lock(&(this->mutex));
 
@@ -690,12 +739,14 @@ static status_t checkin_and_destroy(private_ike_sa_manager_t *this, ike_sa_t *ik
                }
                /* ok, we are alone now, no threads waiting in the entry's condvar */
                this->delete_entry(this, entry);
-               this->logger->log(this->logger, CONTROL|LEVEL1, "check-in and destroy of IKE_SA successful");
+               this->logger->log(this->logger, CONTROL|LEVEL1, 
+                                                 "check-in and destroy of IKE_SA successful");
                retval = SUCCESS;
        }
        else
        {
-               this->logger->log(this->logger,ERROR, "tried to check-in and delete nonexisting IKE_SA");
+               this->logger->log(this->logger,ERROR, 
+                                                 "tried to check-in and delete nonexisting IKE_SA");
                retval = NOT_FOUND;
        }
        
@@ -715,9 +766,15 @@ static status_t delete_(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id)
         */
        ike_sa_entry_t *entry;
        status_t retval;
-
+       
+       this->logger->log(this->logger, CONTROL|LEVEL2,
+                                         "delete IKE_SA %llx:%llx, role %s",
+                                         ike_sa_id->get_initiator_spi(ike_sa_id),
+                                         ike_sa_id->get_responder_spi(ike_sa_id),
+                                         ike_sa_id->is_initiator(ike_sa_id) ? "initiator" : "responder");
+       
        pthread_mutex_lock(&(this->mutex));
-
+       
        if (this->get_entry_by_id(this, ike_sa_id, &entry) == SUCCESS)
        {
                /* we try a delete. If it succeeds, our job is done here. The
@@ -725,11 +782,13 @@ static status_t delete_(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id)
                 */
                if (entry->ike_sa->delete(entry->ike_sa) == SUCCESS)
                {
-                       this->logger->log(this->logger, CONTROL|LEVEL1, "initiated delete for IKE_SA");
+                       this->logger->log(this->logger, CONTROL|LEVEL1,
+                                                         "initiated delete for IKE_SA");
                }
-               /* but if the IKE SA is not in a state where the deletion is negotiated with
-                * the other peer, we can destroy the IKE SA on our own. For this, we must
-                * be sure that really NO other threads are waiting for this SA...
+               /* but if the IKE SA is not in a state where the deletion is 
+                * negotiated with the other peer, we can destroy the IKE SA on our own. 
+                * For this, we must be sure that really NO other threads are 
+                * waiting for this SA...
                 */
                else
                {
@@ -740,7 +799,8 @@ static status_t delete_(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id)
                        {
                                /* wake up all */
                                pthread_cond_broadcast(&(entry->condvar));
-                               /* and the nice thing, they will wake us again when their work is done */
+                               /* and the nice thing, they will wake us again when their work
+                                * is done */
                                pthread_cond_wait(&(entry->condvar), &(this->mutex));
                        }
                        /* ok, we are alone now, no threads waiting in the entry's condvar */
@@ -751,7 +811,8 @@ static status_t delete_(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id)
        }
        else
        {
-               this->logger->log(this->logger,ERROR, "tried to delete nonexisting IKE_SA");
+               this->logger->log(this->logger,ERROR, 
+                                                 "tried to delete nonexisting IKE_SA");
                retval = NOT_FOUND;
        }
 
@@ -770,13 +831,12 @@ static void destroy(private_ike_sa_manager_t *this)
        ike_sa_entry_t *entry;
        
        pthread_mutex_lock(&(this->mutex));
-       
-       this->logger->log(this->logger, CONTROL|LEVEL1, "going to destroy IKE_SA manager and all managed IKE_SA's");
-       
+       this->logger->log(this->logger, CONTROL|LEVEL1, 
+                                         "going to destroy IKE_SA manager and all managed IKE_SA's");
        /* Step 1: drive out all waiting threads  */
+       this->logger->log(this->logger, CONTROL|LEVEL2, 
+                                         "set driveout flags for all stored IKE_SA's");
        iterator = list->create_iterator(list, TRUE);
-
-       this->logger->log(this->logger, CONTROL|LEVEL2, "set driveout flags for all stored IKE_SA's");
        while (iterator->has_next(iterator))
        {
                iterator->current(iterator, (void**)&entry);
@@ -784,8 +844,8 @@ static void destroy(private_ike_sa_manager_t *this)
                entry->driveout_new_threads = TRUE;
                entry->driveout_waiting_threads = TRUE; 
        }
-
-       this->logger->log(this->logger, CONTROL|LEVEL2, "wait for all threads to leave IKE_SA's");
+       this->logger->log(this->logger, CONTROL|LEVEL2, 
+                                         "wait for all threads to leave IKE_SA's");
        /* Step 2: wait until all are gone */
        iterator->reset(iterator);
        while (iterator->has_next(iterator))
diff --git a/src/charon/sa/states/create_child_sa_requested.c b/src/charon/sa/states/create_child_sa_requested.c
deleted file mode 100644 (file)
index 3e7abe1..0000000
+++ /dev/null
@@ -1,435 +0,0 @@
-/**
- * @file create_child_sa_requested.c
- * 
- * @brief State after a CREATE_CHILD_SA request was sent.
- * 
- */
-
-/*
- * Copyright (C) 2006 Martin Willi
- * 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 <string.h>
-
-#include "create_child_sa_requested.h"
-
-#include <sa/child_sa.h>
-#include <sa/states/delete_ike_sa_requested.h>
-#include <sa/states/ike_sa_established.h>
-#include <encoding/payloads/ts_payload.h>
-#include <encoding/payloads/sa_payload.h>
-#include <encoding/payloads/nonce_payload.h>
-#include <encoding/payloads/notify_payload.h>
-#include <utils/logger_manager.h>
-
-
-typedef struct private_create_child_sa_requested_t private_create_child_sa_requested_t;
-
-/**
- * Private data of a create_child_sa_requested_t object.
- */
-struct private_create_child_sa_requested_t {
-       /**
-        * Public interface of create_child_sa_requested_t.
-        */
-       create_child_sa_requested_t public;
-       
-       /**
-        * Assigned IKE_SA.
-        */
-       protected_ike_sa_t *ike_sa;
-       
-       /**
-        * nonce chosen by initiator
-        */
-       chunk_t nonce_i;
-       
-       /**
-        * nonce chosen by the responder
-        */
-       chunk_t nonce_r;
-       
-       /**
-        * Policy to use for new child_sa
-        */
-       policy_t *policy;
-       
-       /**
-        * Proposal negotiated
-        */
-       proposal_t *proposal;
-       
-       /**
-        * Negotiated list of traffic selectors for local site
-        */
-       linked_list_t *my_ts;
-       
-       /**
-        * Negotiated list of traffic selectors for remote site
-        */
-       linked_list_t *other_ts;
-       
-       /**
-        * Child SA to create
-        */
-       child_sa_t *child_sa;
-       
-       /**
-        * Reqid of the old CHILD_SA, when rekeying
-        */
-       u_int32_t reqid;
-       
-       /**
-        * Assigned logger.
-        * 
-        * Is logger of ike_sa!
-        */
-       logger_t *logger;
-};
-
-/**
- * Implementation of private_create_child_sa_requested_t.process_sa_payload.
- */
-static status_t process_sa_payload(private_create_child_sa_requested_t *this, sa_payload_t *sa_payload)
-{
-       proposal_t *proposal, *proposal_tmp;
-       linked_list_t *proposal_list;
-       
-       /* get his selected proposal */
-       proposal_list = sa_payload->get_proposals(sa_payload);
-       /* check count of proposals */
-       if (proposal_list->get_count(proposal_list) == 0)
-       {
-               /* no proposal? we accept this, but no child sa is built */
-               this->logger->log(this->logger, AUDIT, "CREATE_CHILD_SA reply contained no proposals. CHILD_SA not created");
-               proposal_list->destroy(proposal_list);
-               return FAILED;
-       }
-       if (proposal_list->get_count(proposal_list) > 1)
-       {
-               this->logger->log(this->logger, AUDIT, "CREATE_CHILD_SA reply contained %d proposals. Aborting",
-                                                 proposal_list->get_count(proposal_list));
-               while (proposal_list->remove_last(proposal_list, (void**)&proposal) == SUCCESS)
-               {
-                       proposal->destroy(proposal);
-               }
-               proposal_list->destroy(proposal_list);
-               return FAILED;
-       }
-       
-       /* we have to re-check here if other's selection is valid */
-       proposal = this->policy->select_proposal(this->policy, proposal_list);
-       /* list not needed anymore */
-       while (proposal_list->remove_last(proposal_list, (void**)&proposal_tmp) == SUCCESS)
-       {
-               proposal_tmp->destroy(proposal_tmp);
-       }
-       proposal_list->destroy(proposal_list);
-       /* got a match? */
-       if (proposal == NULL)
-       {
-               this->logger->log(this->logger, AUDIT, "CREATE_CHILD_SA reply contained a not offered proposal. Aborting");
-               return FAILED;
-       }
-       
-       /* apply proposal */
-       this->proposal = proposal;
-       
-       return SUCCESS;
-}
-
-/**
- * Implementation of private_create_child_sa_requested_t.process_ts_payload.
- */
-static status_t process_ts_payload(private_create_child_sa_requested_t *this, bool ts_initiator, ts_payload_t *ts_payload)
-{
-       linked_list_t *ts_received, *ts_selected;
-       traffic_selector_t *ts;
-       
-       /* get ts form payload */
-       ts_received = ts_payload->get_traffic_selectors(ts_payload);
-       /* select ts depending on payload type */
-       if (ts_initiator)
-       {
-               ts_selected = this->policy->select_my_traffic_selectors(this->policy, ts_received);
-               this->my_ts = ts_selected;
-       }
-       else
-       {
-               ts_selected = this->policy->select_other_traffic_selectors(this->policy, ts_received);
-               this->other_ts = ts_selected;
-       }
-       /* check if the responder selected valid proposals */
-       if (ts_selected->get_count(ts_selected) != ts_received->get_count(ts_received))
-       {
-               this->logger->log(this->logger, AUDIT, "IKE_AUTH reply contained not offered traffic selectors.");
-       }
-       
-       /* cleanup */
-       while (ts_received->remove_last(ts_received, (void**)&ts) == SUCCESS)
-       {
-               ts->destroy(ts);
-       }
-       ts_received->destroy(ts_received);
-
-       return SUCCESS;
-}
-
-/**
- * Implementation of private_create_child_sa_requested_t.process_nonce_payload.
- */
-static status_t process_nonce_payload(private_create_child_sa_requested_t *this, nonce_payload_t *nonce_request)
-{      
-       this->nonce_r = nonce_request->get_nonce(nonce_request);
-       return SUCCESS;
-}
-
-/**
- * Process a CREATE_CHILD_SA response
- */
-static status_t process_message(private_create_child_sa_requested_t *this, message_t *response)
-{
-       ts_payload_t *tsi_request = NULL, *tsr_request = NULL;
-       sa_payload_t *sa_request = NULL;
-       nonce_payload_t *nonce_request = NULL;
-       ike_sa_id_t *ike_sa_id;
-       iterator_t *payloads;
-       crypter_t *crypter;
-       signer_t *signer;
-       status_t status;
-       chunk_t seed;
-       prf_plus_t *prf_plus;
-       child_sa_t *old_child_sa;
-       
-       this->policy = this->ike_sa->get_policy(this->ike_sa);
-       if (response->get_exchange_type(response) != CREATE_CHILD_SA)
-       {
-               this->logger->log(this->logger, ERROR | LEVEL1, "Message of type %s not supported in state create_child_sa_requested",
-                                                 mapping_find(exchange_type_m, response->get_exchange_type(response)));
-               return FAILED;
-       }
-       
-       if (response->get_request(response))
-       {
-               this->logger->log(this->logger, ERROR | LEVEL1, "CREATE_CHILD_SA requests not allowed state create_child_sa_requested");
-               /* TODO: our state implementation currently can not handle incoming requests cleanly here.
-                * If a request comes in before an outstanding reply, we can not handle it the correct way.
-                * Currently, we create a ESTABLISHED state and let it process the message... But we
-                * need changes in the whole state mechanism.
-                */
-               state_t *state = (state_t*)ike_sa_established_create(this->ike_sa);
-               state->process_message(state, response);
-               state->destroy(state);
-               return SUCCESS;
-       }
-       
-       /* get signer for verification and crypter for decryption */
-       ike_sa_id = this->ike_sa->public.get_id(&this->ike_sa->public);
-       if (!ike_sa_id->is_initiator(ike_sa_id))
-       {
-               crypter = this->ike_sa->get_crypter_initiator(this->ike_sa);
-               signer = this->ike_sa->get_signer_initiator(this->ike_sa);
-       }
-       else
-       {
-               crypter = this->ike_sa->get_crypter_responder(this->ike_sa);
-               signer = this->ike_sa->get_signer_responder(this->ike_sa);
-       }
-       
-       /* parse incoming message */
-       status = response->parse_body(response, crypter, signer);
-       if (status != SUCCESS)
-       {
-               this->logger->log(this->logger, AUDIT, "CREATE_CHILD_SA r decryption failed. Ignoring message");
-               return status;
-       }
-       
-       /* iterate over incoming payloads. Message is verified, we can be sure there are the required payloads */
-       payloads = response->get_payload_iterator(response);
-       while (payloads->has_next(payloads))
-       {
-               payload_t *payload;
-               payloads->current(payloads, (void**)&payload);
-               
-               switch (payload->get_type(payload))
-               {
-                       case SECURITY_ASSOCIATION:
-                       {
-                               sa_request = (sa_payload_t*)payload;
-                               break;
-                       }
-                       case TRAFFIC_SELECTOR_INITIATOR:
-                       {
-                               tsi_request = (ts_payload_t*)payload;
-                               break;  
-                       }
-                       case TRAFFIC_SELECTOR_RESPONDER:
-                       {
-                               tsr_request = (ts_payload_t*)payload;
-                               break;  
-                       }
-                       case NONCE:
-                       {
-                               nonce_request = (nonce_payload_t*)payload;
-                               break;  
-                       }
-                       case NOTIFY:
-                       {
-                               /* TODO: handle notifys */
-                               break;
-                       }
-                       default:
-                       {
-                               this->logger->log(this->logger, ERROR|LEVEL1, "Ignoring payload %s (%d)", 
-                                                                 mapping_find(payload_type_m, payload->get_type(payload)), payload->get_type(payload));
-                               break;
-                       }
-               }
-       }
-       /* iterator can be destroyed */
-       payloads->destroy(payloads);
-       
-       /* check if we have all payloads */
-       if (!(sa_request && nonce_request && tsi_request && tsr_request))
-       {
-               this->logger->log(this->logger, AUDIT, "CREATE_CHILD_SA request did not contain all required payloads. Ignored");
-               return FAILED;
-       }
-       
-       /* add payloads to it */
-       status = process_nonce_payload(this, nonce_request);
-       if (status != SUCCESS)
-       {
-               response->destroy(response);
-               return status;
-       }
-       status = process_sa_payload(this, sa_request);
-       if (status != SUCCESS)
-       {
-               response->destroy(response);
-               return status;
-       }
-       status = process_ts_payload(this, TRUE, tsi_request);
-       if (status != SUCCESS)
-       {
-               response->destroy(response);
-               return status;
-       }
-       status = process_ts_payload(this, FALSE, tsr_request);
-       if (status != SUCCESS)
-       {
-               response->destroy(response);
-               return status;
-       }
-       
-       /* install child SAs for AH and esp */
-       if (!this->proposal)
-       {
-               this->logger->log(this->logger, CONTROL, "Proposal negotiation failed, no CHILD_SA built");
-               this->child_sa->destroy(this->child_sa);
-               this->child_sa = NULL;
-       }
-       else if (this->my_ts->get_count(this->my_ts) == 0 || this->other_ts->get_count(this->other_ts) == 0)
-       {
-               this->logger->log(this->logger, CONTROL, "Traffic selector negotiation failed, no CHILD_SA built");
-               this->child_sa->destroy(this->child_sa);
-               this->child_sa = NULL;
-       }
-       else
-       {
-               seed = chunk_alloc(this->nonce_i.len + this->nonce_r.len);
-               memcpy(seed.ptr, this->nonce_i.ptr, this->nonce_i.len);
-               memcpy(seed.ptr + this->nonce_i.len, this->nonce_r.ptr, this->nonce_r.len);
-               prf_plus = prf_plus_create(this->ike_sa->get_child_prf(this->ike_sa), seed);
-               
-               this->logger->log_chunk(this->logger, RAW|LEVEL2, "Rekey seed", seed);
-               chunk_free(&seed);
-               
-               status = this->child_sa->update(this->child_sa, this->proposal, prf_plus);
-               prf_plus->destroy(prf_plus);
-               if (status != SUCCESS)
-               {
-                       this->logger->log(this->logger, AUDIT, "Could not install CHILD_SA! Deleting IKE_SA");
-                       return DESTROY_ME;
-               }
-               status = this->child_sa->add_policies(this->child_sa, this->my_ts, this->other_ts);
-               if (status != SUCCESS)
-               {
-                       this->logger->log(this->logger, AUDIT, "Could not install CHILD_SA policy! Deleting IKE_SA");
-                       return DESTROY_ME;
-               }
-               this->ike_sa->add_child_sa(this->ike_sa, this->child_sa);
-       }
-       
-       this->ike_sa->set_last_replied_message_id(this->ike_sa, response->get_message_id(response));
-       
-       /* create new state */
-       this->ike_sa->set_new_state(this->ike_sa, (state_t*)ike_sa_established_create(this->ike_sa));
-       
-       /* if we are rekeying, inform the old child SA that it has been superseeded and
-        * start its delete */
-       if (this->reqid)
-       {
-               old_child_sa = this->ike_sa->public.get_child_sa(&this->ike_sa->public, this->reqid);
-               if (old_child_sa)
-               {
-                       old_child_sa->set_rekeyed(old_child_sa);
-               }
-               
-               this->ike_sa->public.delete_child_sa(&this->ike_sa->public, this->reqid);
-       }
-       this->public.state_interface.destroy(&this->public.state_interface);
-       return SUCCESS;
-}
-
-/**
- * Implements state_t.get_state
- */
-static ike_sa_state_t get_state(private_create_child_sa_requested_t *this)
-{
-       return CREATE_CHILD_SA_REQUESTED;
-}
-
-/**
- * Implementation of state_t.destroy.
- */
-static void destroy(private_create_child_sa_requested_t *this)
-{
-       chunk_free(&this->nonce_i);
-       chunk_free(&this->nonce_r);
-       free(this);
-}
-
-/*
- * Described in header.
- */
-create_child_sa_requested_t *create_child_sa_requested_create(protected_ike_sa_t *ike_sa, child_sa_t *child_sa, chunk_t nonce_i, u_int32_t reqid)
-{
-       private_create_child_sa_requested_t *this = malloc_thing(private_create_child_sa_requested_t);
-       
-       /* interface functions */
-       this->public.state_interface.process_message = (status_t (*) (state_t *,message_t *)) process_message;
-       this->public.state_interface.get_state = (ike_sa_state_t (*) (state_t *)) get_state;
-       this->public.state_interface.destroy  = (void (*) (state_t *)) destroy;
-       
-       /* private data */
-       this->ike_sa = ike_sa;
-       this->child_sa = child_sa;
-       this->nonce_i = nonce_i;
-       this->nonce_r = CHUNK_INITIALIZER;
-       this->reqid = reqid;
-       this->logger = logger_manager->get_logger(logger_manager, IKE_SA);
-       
-       return &(this->public);
-}
diff --git a/src/charon/sa/states/create_child_sa_requested.h b/src/charon/sa/states/create_child_sa_requested.h
deleted file mode 100644 (file)
index 20c17b6..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/**
- * @file create_child_sa_requested.h
- * 
- * @brief Interface of create_child_sa_requested_t.
- * 
- */
-
-/*
- * Copyright (C) 2006 Martin Willi
- * 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 CREATE_CHILD_SA_REQEUSTED_H_
-#define CREATE_CHILD_SA_REQEUSTED_H_
-
-#include <sa/states/state.h>
-#include <sa/ike_sa.h>
-#include <sa/child_sa.h>
-
-typedef struct create_child_sa_requested_t create_child_sa_requested_t;
-
-/**
- * @brief State after a CREATE_CHILD_SA request was sent.
- * 
- * @b Constructors:
- * - create_child_sa_requested_create()
- * 
- * @ingroup states
- */
-struct create_child_sa_requested_t {
-       /**
-        * methods of the state_t interface
-        */
-       state_t state_interface;
-};
-
-/**
- * @brief Constructor of class create_child_sa_requested_t
- * 
- * If this CREATE_CHILD_SA message is to rekey a CHILD_SA, 
- * the child_sa with the specified reqid gets deleted after a new
- * one is set up.
- * 
- * @param ike_sa       assigned ike_sa
- * @param child_sa     newly created child sa to complete
- * @param nonce                nonce sent at initialization
- * @param reqid                reqid, when rekeying a child SA.
- * @return                     created create_child_sa_requested_t object
- * 
- * @ingroup states
- */
-create_child_sa_requested_t *create_child_sa_requested_create(protected_ike_sa_t *ike_sa, child_sa_t *child_sa, chunk_t nonce_i, u_int32_t reqid);
-
-#endif /*CREATE_CHILD_SA_REQEUSTED_H_*/
diff --git a/src/charon/sa/states/delete_child_sa_requested.c b/src/charon/sa/states/delete_child_sa_requested.c
deleted file mode 100644 (file)
index 8cad93d..0000000
+++ /dev/null
@@ -1,185 +0,0 @@
-/**
- * @file delete_child_sa_requested.c
- * 
- * @brief State after a CREATE_CHILD_SA request was sent.
- * 
- */
-
-/*
- * Copyright (C) 2006 Martin Willi
- * 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 <string.h>
-
-#include "delete_child_sa_requested.h"
-
-#include <sa/child_sa.h>
-#include <sa/states/delete_ike_sa_requested.h>
-#include <sa/states/ike_sa_established.h>
-#include <encoding/payloads/notify_payload.h>
-#include <encoding/payloads/delete_payload.h>
-#include <utils/logger_manager.h>
-
-
-typedef struct private_delete_child_sa_requested_t private_delete_child_sa_requested_t;
-
-/**
- * Private data of a delete_child_sa_requested_t object.
- */
-struct private_delete_child_sa_requested_t {
-       /**
-        * Public interface of delete_child_sa_requested_t.
-        */
-       delete_child_sa_requested_t public;
-       
-       /**
-        * Assigned IKE_SA.
-        */
-       protected_ike_sa_t *ike_sa;
-       
-       /**
-        * Assigned logger.
-        * 
-        * Is logger of ike_sa!
-        */
-       logger_t *logger;
-};
-
-
-/**
- * Process the response
- */
-static status_t process_message(private_delete_child_sa_requested_t *this, message_t *response)
-{
-       ike_sa_id_t *ike_sa_id;
-       crypter_t *crypter;
-       signer_t *signer;
-       status_t status;
-       iterator_t *iterator;
-       payload_t *payload;
-       delete_payload_t *delete_response;
-       
-       if (response->get_exchange_type(response) != INFORMATIONAL)
-       {
-               this->logger->log(this->logger, ERROR | LEVEL1, "Message of type %s not supported in state delete_child_sa_requested",
-                                                 mapping_find(exchange_type_m, response->get_exchange_type(response)));
-               return FAILED;
-       }
-       
-       if (response->get_request(response))
-       {
-               this->logger->log(this->logger, ERROR | LEVEL1, "INFORMATIONAL requests not allowed state delete_child_sa_requested");
-               /* TODO: our state implementation currently can not handle incoming requests cleanly here.
-                * If a request comes in before an outstanding reply, we can not handle it cleanly.
-                * Currently, we create a ESTABLISHED state and let it process the message... But we
-                * need changes in the whole state mechanism.
-                */
-               state_t *state = (state_t*)ike_sa_established_create(this->ike_sa);
-               state->process_message(state, response);
-               state->destroy(state);
-               return SUCCESS;
-       }
-       
-       /* get signer for verification and crypter for decryption */
-       ike_sa_id = this->ike_sa->public.get_id(&this->ike_sa->public);
-       if (!ike_sa_id->is_initiator(ike_sa_id))
-       {
-               crypter = this->ike_sa->get_crypter_initiator(this->ike_sa);
-               signer = this->ike_sa->get_signer_initiator(this->ike_sa);
-       }
-       else
-       {
-               crypter = this->ike_sa->get_crypter_responder(this->ike_sa);
-               signer = this->ike_sa->get_signer_responder(this->ike_sa);
-       }
-       
-       /* parse incoming message */
-       status = response->parse_body(response, crypter, signer);
-       if (status != SUCCESS)
-       {
-               this->logger->log(this->logger, AUDIT, "INFORMATIONAL response decryption failed. Ignoring message");
-               return status;
-       }
-       
-       iterator = response->get_payload_iterator(response);
-       while (iterator->has_next(iterator)) {
-               iterator->current(iterator, (void**)&payload);
-               switch (payload->get_type(payload))
-               {
-                       case DELETE:
-                               delete_response = (delete_payload_t*)payload;
-                               break;
-                       default:
-                               break;
-               }
-               
-       }
-       iterator->destroy(iterator);
-       
-       if (delete_response)
-       {
-               iterator = delete_response->create_spi_iterator(delete_response);
-               while (iterator->has_next(iterator))
-               {       
-                       u_int32_t spi;
-                       iterator->current(iterator, (void**)&spi);
-                       this->logger->log(this->logger, CONTROL, "DELETE request for CHILD_SA with SPI 0x%x received", spi);
-                       this->ike_sa->destroy_child_sa(this->ike_sa, spi);
-               }
-               iterator->destroy(iterator);
-       }
-       
-       this->ike_sa->set_last_replied_message_id(this->ike_sa, response->get_message_id(response));
-       
-       /* create new state */
-       this->ike_sa->set_new_state(this->ike_sa, (state_t*)ike_sa_established_create(this->ike_sa));
-       this->public.state_interface.destroy(&this->public.state_interface);
-       
-       return SUCCESS;
-}
-
-/**
- * Implements state_t.get_state
- */
-static ike_sa_state_t get_state(private_delete_child_sa_requested_t *this)
-{
-       return DELETE_CHILD_SA_REQUESTED;
-}
-
-/**
- * Implementation of state_t.destroy.
- */
-static void destroy(private_delete_child_sa_requested_t *this)
-{
-       free(this);
-}
-
-/*
- * Described in header.
- */
-delete_child_sa_requested_t *delete_child_sa_requested_create(protected_ike_sa_t *ike_sa)
-{
-       private_delete_child_sa_requested_t *this = malloc_thing(private_delete_child_sa_requested_t);
-       
-       /* interface functions */
-       this->public.state_interface.process_message = (status_t (*) (state_t *,message_t *)) process_message;
-       this->public.state_interface.get_state = (ike_sa_state_t (*) (state_t *)) get_state;
-       this->public.state_interface.destroy  = (void (*) (state_t *)) destroy;
-       
-       /* private data */
-       this->ike_sa = ike_sa;
-       this->logger = logger_manager->get_logger(logger_manager, IKE_SA);
-       
-       return &(this->public);
-}
diff --git a/src/charon/sa/states/delete_child_sa_requested.h b/src/charon/sa/states/delete_child_sa_requested.h
deleted file mode 100644 (file)
index e70ff18..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/**
- * @file delete_child_sa_requested.h
- * 
- * @brief Interface of delete_child_sa_requested_t.
- * 
- */
-
-/*
- * Copyright (C) 2006 Martin Willi
- * 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 DELETE_CHILD_SA_REQEUSTED_H_
-#define DELETE_CHILD_SA_REQEUSTED_H_
-
-#include <sa/states/state.h>
-#include <sa/ike_sa.h>
-#include <sa/child_sa.h>
-
-typedef struct delete_child_sa_requested_t delete_child_sa_requested_t;
-
-/**
- * @brief State after a CREATE_CHILD_SA request was sent.
- * 
- * @b Constructors:
- * - delete_child_sa_requested_create()
- * 
- * @ingroup states
- */
-struct delete_child_sa_requested_t {
-       /**
-        * methods of the state_t interface
-        */
-       state_t state_interface;
-};
-
-/**
- * @brief Constructor of class delete_child_sa_requested_t
- * 
- * @param ike_sa       assigned ike_sa
- * @return                     created delete_child_sa_requested_t object
- * 
- * @ingroup states
- */
-delete_child_sa_requested_t *delete_child_sa_requested_create(protected_ike_sa_t *ike_sa);
-
-#endif /*DELETE_CHILD_SA_REQEUSTED_H_*/
diff --git a/src/charon/sa/states/delete_ike_sa_requested.c b/src/charon/sa/states/delete_ike_sa_requested.c
deleted file mode 100644 (file)
index 36e9c2f..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-/**
- * @file delete_ike_sa_requested.c
- *
- * @brief Implementation of delete_ike_sa_requested_t.
- *
- */
-
-/*
- * Copyright (C) 2006 Martin Willi
- * 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 "delete_ike_sa_requested.h"
-
-#include <daemon.h>
-
-
-typedef struct private_delete_ike_sa_requested_t private_delete_ike_sa_requested_t;
-
-/**
- * Private data of a delete_ike_sa_requested_t object.
- */
-struct private_delete_ike_sa_requested_t {
-       
-       /**
-        * methods of the state_t interface
-        */
-       delete_ike_sa_requested_t public;
-       
-       /** 
-        * Assigned IKE_SA.
-        */
-       protected_ike_sa_t *ike_sa;
-       
-       /** 
-        * Assigned logger. Use logger of IKE_SA.
-        */
-       logger_t *logger;
-};
-
-/**
- * Implements state_t.get_state
- */
-static status_t process_message(private_delete_ike_sa_requested_t *this, message_t *message)
-{
-       ike_sa_id_t *ike_sa_id;
-       crypter_t *crypter;
-       signer_t *signer;
-       status_t status;
-       
-       /* Notation as follows:
-        * Mx{D} means: Message, with message ID "x", containing a Delete payload
-        *
-        * The clarifcation Document says in 5.8, that a IKE_SA delete should not
-        * be acknowledged with the same delete. This only makes sense for CHILD_SAs,
-        * as they are paired. IKE_SAs are not, there is only one for both ends.
-        *
-        * Normal case:
-        * ----------------
-        * Mx{D}  -->
-        *       <--      Mx{}
-        * Delete request is sent, and we wait for the acknowledge.
-        *
-        * Special case 1:
-        * ---------------
-        * Mx{D}  -->
-        *       <--      My{D}
-        * My{}   -->
-        *       <--      Mx{}
-        * Both initate a delete at the same time. We ack the delete, but wait for
-        * our delete to be acknowledged.
-        */
-       
-       if (message->get_exchange_type(message) != INFORMATIONAL)
-       {
-               /* anything other than information is ignored. We can an will not handle
-                * messages such as CREATE_CHILD_SA */
-               this->logger->log(this->logger, ERROR | LEVEL1, 
-                                                 "%s messages not supported in state delete_ike_sa_requested. Ignored",
-                                                 mapping_find(exchange_type_m, message->get_exchange_type(message)));
-               return FAILED;
-       }
-       
-       if (message->get_request(message))
-       {
-               /* if it is a request, not a reply to our delete request, we 
-                * just acknowledge this. We stay in our state, as the other peer
-                * has to ACK our request.
-                */
-               message_t *acknowledge;
-               this->ike_sa->build_message(this->ike_sa, INFORMATIONAL, FALSE, &acknowledge);
-               return this->ike_sa->send_response(this->ike_sa, acknowledge);
-       }
-       
-       /* get signer for verification and crypter for decryption */
-       ike_sa_id = this->ike_sa->public.get_id(&(this->ike_sa->public));
-       if (!ike_sa_id->is_initiator(ike_sa_id))
-       {
-               crypter = this->ike_sa->get_crypter_initiator(this->ike_sa);
-               signer = this->ike_sa->get_signer_initiator(this->ike_sa);
-       }
-       else
-       {
-               crypter = this->ike_sa->get_crypter_responder(this->ike_sa);
-               signer = this->ike_sa->get_signer_responder(this->ike_sa);
-       }
-       
-       /* parse incoming message, check if it's proper signed */
-       status = message->parse_body(message, crypter, signer);
-       if (status != SUCCESS)
-       {
-               this->logger->log(this->logger, AUDIT, "INFORMATIONAL message decryption failed. Ignoring message");
-               return status;
-       }
-       
-       /* ok, he knows about the deletion, destroy this IKE SA */
-       return DESTROY_ME;
-}
-
-/**
- * Implementation of state_t.get_state.
- */
-static ike_sa_state_t get_state(private_delete_ike_sa_requested_t *this)
-{
-       return DELETE_IKE_SA_REQUESTED;
-}
-
-/**
- * Implementation of state_t.get_state
- */
-static void destroy(private_delete_ike_sa_requested_t *this)
-{
-       free(this);
-}
-
-/* 
- * Described in header.
- */
-delete_ike_sa_requested_t *delete_ike_sa_requested_create(protected_ike_sa_t *ike_sa)
-{
-       private_delete_ike_sa_requested_t *this = malloc_thing(private_delete_ike_sa_requested_t);
-
-       /* interface functions */
-       this->public.state_interface.process_message = (status_t (*) (state_t *,message_t *)) process_message;
-       this->public.state_interface.get_state = (ike_sa_state_t (*) (state_t *)) get_state;
-       this->public.state_interface.destroy  = (void (*) (state_t *)) destroy;
-       
-       /* private data */
-       this->ike_sa = ike_sa;
-       this->logger = logger_manager->get_logger(logger_manager, IKE_SA);
-       
-       return &(this->public);
-}
diff --git a/src/charon/sa/states/delete_ike_sa_requested.h b/src/charon/sa/states/delete_ike_sa_requested.h
deleted file mode 100644 (file)
index a010a0f..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/**
- * @file delete_ike_sa_requested.h
- * 
- * @brief Interface of delete_ike_sa_requested_t.
- * 
- */
-
-/*
- * Copyright (C) 2006 Martin Willi
- * 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 DELETE_IKE_SA_REQUESTED_H_
-#define DELETE_IKE_SA_REQUESTED_H_
-
-#include <sa/states/state.h>
-#include <sa/ike_sa.h>
-
-typedef struct delete_ike_sa_requested_t delete_ike_sa_requested_t;
-
-/**
- * @brief This class represents an the state of a half closed IKE_SA.
- * 
- * @b Constructors:
- * - delete_ike_sa_requested_create()
- * 
- * @ingroup states
- */
-struct delete_ike_sa_requested_t {
-       /**
-        * methods of the state_t interface
-        */
-       state_t state_interface;
-
-};
-
-/**
- * @brief Constructor of class delete_ike_sa_requested_t
- * 
- * @param ike_sa       assigned ike_sa
- * @return                     created delete_ike_sa_requested_t object
- * 
- * @ingroup states
- */
-delete_ike_sa_requested_t *delete_ike_sa_requested_create(protected_ike_sa_t *ike_sa);
-
-#endif /*DELETE_IKE_SA_REQUESTED_H_*/
diff --git a/src/charon/sa/states/ike_auth_requested.c b/src/charon/sa/states/ike_auth_requested.c
deleted file mode 100644 (file)
index b2d42fd..0000000
+++ /dev/null
@@ -1,719 +0,0 @@
-/**
- * @file ike_auth_requested.c
- * 
- * @brief Implementation of ike_auth_requested_t.
- * 
- */
-
-/*
- * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger
- * Copyright (C) 2005 Jan Hutter, Martin Willi
- * 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 <string.h>
-
-#include "ike_auth_requested.h"
-
-#include <daemon.h>
-#include <encoding/payloads/ts_payload.h>
-#include <encoding/payloads/sa_payload.h>
-#include <encoding/payloads/id_payload.h>
-#include <encoding/payloads/cert_payload.h>
-#include <encoding/payloads/auth_payload.h>
-#include <encoding/payloads/notify_payload.h>
-#include <crypto/signers/signer.h>
-#include <crypto/crypters/crypter.h>
-#include <sa/states/ike_sa_established.h>
-#include <sa/authenticator.h>
-#include <sa/child_sa.h>
-
-typedef struct private_ike_auth_requested_t private_ike_auth_requested_t;
-
-/**
- * Private data of a ike_auth_requested_t object.
- *
- */
-struct private_ike_auth_requested_t {
-       /**
-        * Public interface of ike_auth_requested_t.
-        */
-       ike_auth_requested_t public;
-       
-       /**
-        * Assigned IKE_SA.
-        */
-        protected_ike_sa_t *ike_sa;
-        
-       /**
-        * SA config, just a copy of the one stored in the ike_sa.
-        */
-       policy_t *policy; 
-       
-       /**
-        * Received nonce from responder.
-        */
-       chunk_t received_nonce;
-       
-       /**
-        * Sent nonce in IKE_SA_INIT request.
-        */
-       chunk_t sent_nonce;
-       
-       /**
-        * IKE_SA_INIT-Request in binary form.
-        */
-       chunk_t ike_sa_init_reply_data;
-       
-       /**
-        * Proposal to setup CHILD_SA
-        */
-       proposal_t *proposal;
-       
-       /**
-        * Traffic selectors applicable at our site
-        */
-       linked_list_t *my_ts;
-       
-       /**
-        * Traffic selectors applicable at remote site
-        */
-       linked_list_t *other_ts;
-       
-       /**
-        * Child sa created in ike_sa_init_requested
-        */
-       child_sa_t *child_sa;
-        
-       /**
-        * Assigned Logger.
-        * 
-        * Is logger of ike_sa!
-        */
-       logger_t *logger;
-       
-       /**
-        * Process the IDr payload (check if other id is valid)
-        * 
-        * @param this                  calling object
-        * @param idr_payload   ID payload of responder
-        * @return                              
-        *                                              - SUCCESS
-        *                                              - DESTROY_ME
-        */
-       status_t (*process_idr_payload) (private_ike_auth_requested_t *this, id_payload_t *idr_payload);
-       
-       /**
-        * Process received CERT payload
-        * 
-        * @param this                  calling object
-        * @param cert_payload  payload to process
-        * @return
-        *                                              - DESTROY_ME if IKE_SA should be deleted
-        *                                              - SUCCSS if processed successful
-        */
-       status_t (*process_cert_payload) (private_ike_auth_requested_t *this, cert_payload_t *cert_payload);
-       
-       /**
-        * Process the SA payload (check if selected proposals are valid, setup child sa)
-        * 
-        * @param this                  calling object
-        * @param sa_payload    SA payload of responder
-        *
-        *                                              - SUCCESS
-        *                                              - DESTROY_ME
-        */
-       status_t (*process_sa_payload) (private_ike_auth_requested_t *this, sa_payload_t *sa_payload);
-       
-       /**
-        * Process the AUTH payload (check authenticity of message)
-        * 
-        * @param this                          calling object
-        * @param auth_payload          AUTH payload of responder
-        * @param other_id_payload      ID payload of responder
-        *
-        *                                              - SUCCESS
-        *                                              - DESTROY_ME
-        */
-       status_t (*process_auth_payload) (private_ike_auth_requested_t *this, auth_payload_t *auth_payload, id_payload_t *other_id_payload);
-       
-       /**
-        * Process the TS payload (check if selected traffic selectors are valid)
-        * 
-        * @param this                  calling object
-        * @param ts_initiator  TRUE if TS payload is TSi, FALSE for TSr
-        * @param ts_payload    TS payload of responder
-        *
-        *                                              - SUCCESS
-        *                                              - DESTROY_ME
-        */
-       status_t (*process_ts_payload) (private_ike_auth_requested_t *this, bool ts_initiator, ts_payload_t *ts_payload);
-       
-       /**
-        * Process a notify payload
-        * 
-        * @param this                          calling object
-        * @param notify_payload        notify payload
-        *
-        *                   &n