removed %M printf handler, five more to go
[strongswan.git] / src / charon / encoding / message.c
index d8f5efe..077b767 100644 (file)
 
 #include <stdlib.h>
 #include <string.h>
-#include <printf.h>
 
 #include "message.h"
 
-#include <types.h>
+#include <library.h>
 #include <daemon.h>
 #include <sa/ike_sa_id.h>
 #include <encoding/generator.h>
@@ -125,6 +124,7 @@ static payload_rule_t ike_sa_init_i_payload_rules[] = {
        {SECURITY_ASSOCIATION,1,1,FALSE,FALSE},
        {KEY_EXCHANGE,1,1,FALSE,FALSE},
        {NONCE,1,1,FALSE,FALSE},
+       {VENDOR_ID,0,10,FALSE,FALSE},
 };
 
 /**
@@ -135,6 +135,7 @@ static payload_rule_t ike_sa_init_r_payload_rules[] = {
        {SECURITY_ASSOCIATION,1,1,FALSE,FALSE},
        {KEY_EXCHANGE,1,1,FALSE,FALSE},
        {NONCE,1,1,FALSE,FALSE},
+       {VENDOR_ID,0,10,FALSE,FALSE},
 };
 
 /**
@@ -142,15 +143,17 @@ static payload_rule_t ike_sa_init_r_payload_rules[] = {
  */
 static payload_rule_t ike_auth_i_payload_rules[] = {
        {NOTIFY,0,MAX_NOTIFY_PAYLOADS,TRUE,FALSE},
+       {EXTENSIBLE_AUTHENTICATION,0,1,TRUE,TRUE},
+       {AUTHENTICATION,0,1,TRUE,TRUE},
        {ID_INITIATOR,1,1,TRUE,FALSE},
        {CERTIFICATE,0,1,TRUE,FALSE},
        {CERTIFICATE_REQUEST,0,1,TRUE,FALSE},
        {ID_RESPONDER,0,1,TRUE,FALSE},
-       {AUTHENTICATION,1,1,TRUE,FALSE},
        {SECURITY_ASSOCIATION,1,1,TRUE,FALSE},
        {TRAFFIC_SELECTOR_INITIATOR,1,1,TRUE,FALSE},
        {TRAFFIC_SELECTOR_RESPONDER,1,1,TRUE,FALSE},
        {CONFIGURATION,0,1,TRUE,FALSE},
+       {VENDOR_ID,0,10,TRUE,FALSE},
 };
 
 /**
@@ -158,13 +161,15 @@ static payload_rule_t ike_auth_i_payload_rules[] = {
  */
 static payload_rule_t ike_auth_r_payload_rules[] = {
        {NOTIFY,0,MAX_NOTIFY_PAYLOADS,TRUE,TRUE},
+       {EXTENSIBLE_AUTHENTICATION,0,1,TRUE,TRUE},
        {CERTIFICATE,0,1,TRUE,FALSE},
-       {ID_RESPONDER,1,1,TRUE,FALSE},
-       {AUTHENTICATION,1,1,TRUE,FALSE},
-       {SECURITY_ASSOCIATION,1,1,TRUE,FALSE},
-       {TRAFFIC_SELECTOR_INITIATOR,1,1,TRUE,FALSE},
-       {TRAFFIC_SELECTOR_RESPONDER,1,1,TRUE,FALSE},
+       {ID_RESPONDER,0,1,TRUE,FALSE},
+       {AUTHENTICATION,0,1,TRUE,FALSE},
+       {SECURITY_ASSOCIATION,0,1,TRUE,FALSE},
+       {TRAFFIC_SELECTOR_INITIATOR,0,1,TRUE,FALSE},
+       {TRAFFIC_SELECTOR_RESPONDER,0,1,TRUE,FALSE},
        {CONFIGURATION,0,1,TRUE,FALSE},
+       {VENDOR_ID,0,10,TRUE,FALSE},
 };
 
 
@@ -175,6 +180,7 @@ static payload_rule_t informational_i_payload_rules[] = {
        {NOTIFY,0,MAX_NOTIFY_PAYLOADS,TRUE,FALSE},
        {CONFIGURATION,0,1,TRUE,FALSE},
        {DELETE,0,1,TRUE,FALSE},
+       {VENDOR_ID,0,10,TRUE,FALSE},
        
 };
 
@@ -185,6 +191,7 @@ static payload_rule_t informational_r_payload_rules[] = {
        {NOTIFY,0,MAX_NOTIFY_PAYLOADS,TRUE,FALSE},
        {CONFIGURATION,0,1,TRUE,FALSE},
        {DELETE,0,1,TRUE,FALSE},
+       {VENDOR_ID,0,10,TRUE,FALSE},
 };
 
 /**
@@ -198,6 +205,7 @@ static payload_rule_t create_child_sa_i_payload_rules[] = {
        {TRAFFIC_SELECTOR_INITIATOR,0,1,TRUE,FALSE},
        {TRAFFIC_SELECTOR_RESPONDER,0,1,TRUE,FALSE},
        {CONFIGURATION,0,1,TRUE,FALSE},
+       {VENDOR_ID,0,10,TRUE,FALSE},
 };
 
 /**
@@ -211,6 +219,7 @@ static payload_rule_t create_child_sa_r_payload_rules[] = {
        {TRAFFIC_SELECTOR_INITIATOR,0,1,TRUE,FALSE},
        {TRAFFIC_SELECTOR_RESPONDER,0,1,TRUE,FALSE},
        {CONFIGURATION,0,1,TRUE,FALSE},
+       {VENDOR_ID,0,10,TRUE,FALSE},
 };
 
 
@@ -343,6 +352,7 @@ static status_t get_payload_rule(private_message_t *this, payload_type_t payload
  */
 static void set_ike_sa_id (private_message_t *this,ike_sa_id_t *ike_sa_id)
 {
+       DESTROY_IF(this->ike_sa_id);
        this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
 }
 
@@ -470,24 +480,67 @@ static bool is_encoded(private_message_t *this)
  */
 static void add_payload(private_message_t *this, payload_t *payload)
 {
-       payload_t *last_payload;
-       if (this->payloads->get_count(this->payloads) > 0)
+       payload_t *last_payload, *first_payload;
+       
+       if ((this->is_request && payload->get_type(payload) == ID_INITIATOR) ||
+               (!this->is_request && payload->get_type(payload) == ID_RESPONDER))
        {
-               this->payloads->get_last(this->payloads,(void **) &last_payload);
-               last_payload->set_next_type(last_payload, payload->get_type(payload));
+               /* HOTD: insert ID payload in the beginning to respect RFC */
+               if (this->payloads->get_first(this->payloads,
+                                                                         (void **)&first_payload) == SUCCESS)
+               {
+                       payload->set_next_type(payload, first_payload->get_type(first_payload));
+               }
+               else
+               {
+                       payload->set_next_type(payload, NO_PAYLOAD);
+               }
+               this->first_payload = payload->get_type(payload);
+               this->payloads->insert_first(this->payloads, payload);
        }
        else
        {
-               this->first_payload = payload->get_type(payload);
+               if (this->payloads->get_count(this->payloads) > 0)
+               {
+                       this->payloads->get_last(this->payloads,(void **) &last_payload);
+                       last_payload->set_next_type(last_payload, payload->get_type(payload));
+               }
+               else
+               {
+                       this->first_payload = payload->get_type(payload);
+               }
+               payload->set_next_type(payload, NO_PAYLOAD);
+               this->payloads->insert_last(this->payloads, payload);
        }
-       payload->set_next_type(payload, NO_PAYLOAD);
-       this->payloads->insert_last(this->payloads, (void*)payload);
 
        DBG2(DBG_ENC ,"added payload of type %N to message",
                 payload_type_names, payload->get_type(payload));
 }
 
 /**
+ * Implementation of message_t.add_notify.
+ */
+static void add_notify(private_message_t *this, bool flush, notify_type_t type, 
+                                          chunk_t data)
+{
+       notify_payload_t *notify;
+       payload_t *payload;
+       
+       if (flush)
+       {
+               while (this->payloads->remove_last(this->payloads, 
+                                                                                               (void**)&payload) == SUCCESS)
+               {
+                       payload->destroy(payload);
+               }
+       }
+       notify = notify_payload_create();
+       notify->set_notify_type(notify, type);
+       notify->set_notification_data(notify, data);
+       add_payload(this, (payload_t*)notify);
+}
+
+/**
  * Implementation of message_t.set_source.
  */
 static void set_source(private_message_t *this, host_t *host)
@@ -520,7 +573,7 @@ static host_t * get_destination(private_message_t *this)
 }
 
 /**
- * Implementation of message_t.get_destination.
+ * Implementation of message_t.get_payload_iterator.
  */
 static iterator_t *get_payload_iterator(private_message_t *this)
 {
@@ -528,84 +581,63 @@ static iterator_t *get_payload_iterator(private_message_t *this)
 }
 
 /**
- * output handler in printf()
+ * Implementation of message_t.get_payload.
  */
-static int print(FILE *stream, const struct printf_info *info,
-                                const void *const *args)
+static payload_t *get_payload(private_message_t *this, payload_type_t type)
 {
-       private_message_t *this = *((private_message_t**)(args[0]));
+       payload_t *current, *found = NULL;
        iterator_t *iterator;
-       payload_t *payload;
-       bool first = TRUE;
-       size_t total_written = 0;
-       size_t written;
-       
-       if (this == NULL)
-       {
-               return fprintf(stream, "(null)");
-       }
-       
-       written = fprintf(stream, "%N %s [", 
-                                         exchange_type_names, this->exchange_type,
-                                         this->is_request ? "request" : "response");
-       if (written < 0)
-       {
-               return written;
-       }
-       total_written += written;
        
        iterator = this->payloads->create_iterator(this->payloads, TRUE);
-       while (iterator->iterate(iterator, (void**)&payload))
+       while (iterator->iterate(iterator, (void**)&current))
        {
-               if (!first)
-               {
-                       written = fprintf(stream, " ");
-                       if (written < 0)
-                       {
-                               return written;
-                       }
-                       total_written += written;
-               }
-               else
-               {
-                       first = FALSE;
-               }
-               written = fprintf(stream, "%N", payload_type_short_names,
-                                                 payload->get_type(payload));
-               if (written < 0)
+               if (current->get_type(current) == type)
                {
-                       return written;
+                       found = current;
+                       break;
                }
-               total_written += written;
        }
        iterator->destroy(iterator);
-       written = fprintf(stream, "]");
-       if (written < 0)
-       {
-               return written;
-       }
-       total_written += written;
-       return total_written;
+       return found;
 }
 
 /**
- * arginfo handler in printf()
+ * get a string representation of the message
  */
-static int print_arginfo(const struct printf_info *info, size_t n, int *argtypes)
+static void get_string(private_message_t *this, char *buf, int len)
 {
-       if (n > 0)
+       iterator_t *iterator;
+       payload_t *payload;
+       int written;
+       
+       written = snprintf(buf, len, "%N %s [", 
+                                          exchange_type_names, this->exchange_type,
+                                          this->is_request ? "request" : "response");
+       if (written >= len || written < 0)
        {
-               argtypes[0] = PA_POINTER;
+               return;
        }
-       return 1;
-}
-
-/**
- * register printf() handlers
- */
-static void __attribute__ ((constructor))print_register()
-{
-       register_printf_function(MESSAGE_PRINTF_SPEC, print, print_arginfo);
+       buf += written;
+       len -= written;
+       
+       iterator = this->payloads->create_iterator(this->payloads, TRUE);
+       while (iterator->iterate(iterator, (void**)&payload))
+       {
+               written = snprintf(buf, len, "%N ", payload_type_short_names,
+                                                  payload->get_type(payload));
+               if (written >= len || written < 0)
+               {
+                       return;
+               }
+               buf += written;
+               len -= written;
+       }
+       iterator->destroy(iterator);
+       
+       /* remove last space */
+       len++;
+       buf--;
+       snprintf(buf, len, "]");
 }
 
 /**
@@ -694,6 +726,7 @@ static status_t generate(private_message_t *this, crypter_t *crypter, signer_t*
        iterator_t *iterator;
        status_t status;
        chunk_t packet_data;
+       char str[128];
        
        if (is_encoded(this))
        {
@@ -702,7 +735,8 @@ static status_t generate(private_message_t *this, crypter_t *crypter, signer_t*
                return SUCCESS;
        }
        
-       DBG1(DBG_ENC, "generating %M", this);
+       get_string(this, str, sizeof(str));
+       DBG1(DBG_ENC, "generating %s", str);
        
        if (this->exchange_type == EXCHANGE_TYPE_UNDEFINED)
        {
@@ -796,6 +830,10 @@ static status_t generate(private_message_t *this, crypter_t *crypter, signer_t*
  */
 static packet_t *get_packet (private_message_t *this)
 {
+       if (this->packet == NULL)
+       {
+               return NULL;
+       }
        return this->packet->clone(this->packet);
 }
 
@@ -804,6 +842,10 @@ static packet_t *get_packet (private_message_t *this)
  */
 static chunk_t get_packet_data (private_message_t *this)
 {
+       if (this->packet == NULL)
+       {
+               return chunk_empty;
+       }
        return chunk_clone(this->packet->get_data(this->packet));
 }
 
@@ -1091,6 +1133,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 str[128];
                
        current_payload_type = this->first_payload;     
                
@@ -1157,11 +1200,11 @@ static status_t parse_body(private_message_t *this, crypter_t *crypter, signer_t
        status = verify(this);
        if (status != SUCCESS)
        {
-               DBG1(DBG_ENC, "verification of message failed");
                return status;
        }
        
-       DBG1(DBG_ENC, "parsed %M", this);
+       get_string(this, str, sizeof(str));
+       DBG1(DBG_ENC, "parsed %s", str);
        
        return SUCCESS;
 }
@@ -1201,12 +1244,14 @@ message_t *message_create_from_packet(packet_t *packet)
        this->public.set_request = (void(*)(message_t*, bool))set_request;
        this->public.get_request = (bool(*)(message_t*))get_request;
        this->public.add_payload = (void(*)(message_t*,payload_t*))add_payload;
+       this->public.add_notify = (void(*)(message_t*,bool,notify_type_t,chunk_t))add_notify;
        this->public.generate = (status_t (*) (message_t *,crypter_t*,signer_t*,packet_t**)) generate;
        this->public.set_source = (void (*) (message_t*,host_t*)) set_source;
        this->public.get_source = (host_t * (*) (message_t*)) get_source;
        this->public.set_destination = (void (*) (message_t*,host_t*)) set_destination;
        this->public.get_destination = (host_t * (*) (message_t*)) get_destination;
        this->public.get_payload_iterator = (iterator_t * (*) (message_t *)) get_payload_iterator;
+       this->public.get_payload = (payload_t * (*) (message_t *, payload_type_t)) get_payload;
        this->public.parse_header = (status_t (*) (message_t *)) parse_header;
        this->public.parse_body = (status_t (*) (message_t *,crypter_t*,signer_t*)) parse_body;
        this->public.get_packet = (packet_t * (*) (message_t*)) get_packet;