fixed CHILD_SA rekeying/delete bug on 64bit machines
[strongswan.git] / src / charon / encoding / payloads / delete_payload.c
index 28e7880..1d42a3a 100644 (file)
@@ -6,7 +6,8 @@
  */
 
 /*
- * Copyright (C) 2005 Jan Hutter, Martin Willi
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
  * Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -71,6 +72,11 @@ struct private_delete_payload_t {
         * The contained SPI's.
         */
        chunk_t spis;
+       
+       /**
+        * List containing u_int32_t spis 
+        */
+       linked_list_t *spi_list;
 };
 
 /**
@@ -121,23 +127,30 @@ encoding_rule_t delete_payload_encodings[] = {
  */
 static status_t verify(private_delete_payload_t *this)
 {
-       if ((this->protocol_id == 0) ||
-               (this->protocol_id > 3))
+       switch (this->protocol_id)
        {
-               /* reserved IDs */
-               return FAILED;
+               case PROTO_AH:
+               case PROTO_ESP:
+                       if (this->spi_size != 4)
+                       {
+                               return FAILED;
+                       }
+                       break;
+               case PROTO_IKE:
+               case 0:
+                       /* IKE deletion has no spi assigned! */
+                       if (this->spi_size != 0)
+                       {
+                               return FAILED;
+                       }
+                       break;
+               default:
+                       return FAILED;
        }
        if (this->spis.len != (this->spi_count * this->spi_size))
        {
                return FAILED;
        }
-       if ((this->protocol_id == PROTO_IKE) && (this->spis.len != 0))
-       {
-               /* IKE deletion has no spi assigned! */
-               return FAILED;
-       }
-       
-       
        return SUCCESS;
 }
 
@@ -183,14 +196,6 @@ static size_t get_length(private_delete_payload_t *this)
 }
 
 /**
- * Implementation of delete_payload_t.set_protocol_id.
- */
-static void set_protocol_id (private_delete_payload_t *this, protocol_id_t protocol_id)
-{
-       this->protocol_id = protocol_id;
-}
-
-/**
  * Implementation of delete_payload_t.get_protocol_id.
  */
 static protocol_id_t get_protocol_id (private_delete_payload_t *this)
@@ -199,73 +204,47 @@ static protocol_id_t get_protocol_id (private_delete_payload_t *this)
 }
 
 /**
- * Implementation of delete_payload_t.set_spi_size.
- */
-static void set_spi_size (private_delete_payload_t *this, u_int8_t spi_size)
-{
-       this->spi_size = spi_size;
-}
-
-/**
- * Implementation of delete_payload_t.get_spi_size.
+ * Implementation of delete_payload_t.add_spi.
  */
-static u_int8_t get_spi_size (private_delete_payload_t *this)
+static void add_spi(private_delete_payload_t *this, u_int32_t spi)
 {
-       return (this->spi_size);
-}
-
-/**
- * Implementation of delete_payload_t.set_spi_count.
- */
-static void set_spi_count (private_delete_payload_t *this, u_int16_t spi_count)
-{
-       this->spi_count = spi_count;
-}
-
-/**
- * Implementation of delete_payload_t.get_spi_count.
- */
-static u_int16_t get_spi_count (private_delete_payload_t *this)
-{
-       return (this->spi_count);
-}
-
-
-/**
- * Implementation of delete_payload_t.set_spis.
- */
-static void set_spis (private_delete_payload_t *this, chunk_t spis)
-{
-       if (this->spis.ptr != NULL)
+       /* only add SPIs if AH|ESP, ignore others */
+       if (this->protocol_id == PROTO_AH || this->protocol_id == PROTO_ESP)
        {
-               chunk_free(&(this->spis));
+               this->spi_count += 1;
+               this->spis.len += this->spi_size;
+               this->spis.ptr = realloc(this->spis.ptr, this->spis.len);
+               *(u_int32_t*)(this->spis.ptr + (this->spis.len / this->spi_size - 1)) = spi;
+               if (this->spi_list)
+               {
+                       /* reset SPI iterator list */
+                       this->spi_list->destroy(this->spi_list);
+                       this->spi_list = NULL;
+               }
        }
-       this->spis.ptr = clalloc(spis.ptr,spis.len);
-       this->spis.len = spis.len;
-       this->payload_length = DELETE_PAYLOAD_HEADER_LENGTH + this->spis.len;
-}
-
-/**
- * Implementation of delete_payload_t.get_spis.
- */
-static chunk_t get_spis (private_delete_payload_t *this)
-{
-       return (this->spis);
 }
 
 /**
- * Implementation of delete_payload_t.get_spis_clone.
+ * Implementation of delete_payload_t.create_spi_iterator.
  */
-static chunk_t get_spis_clone (private_delete_payload_t *this)
+static iterator_t* create_spi_iterator(private_delete_payload_t *this)
 {
-       chunk_t cloned_spis;
-       if (this->spis.ptr == NULL)
+       int i;
+       
+       if (this->spi_list == NULL)
        {
-               return (this->spis);
+               this->spi_list = linked_list_create();
+               /* only parse SPIs if AH|ESP */
+               if (this->protocol_id == PROTO_AH || this->protocol_id == PROTO_ESP)
+               {
+                       for (i = 0; i < this->spi_count; i++)
+                       {
+                               this->spi_list->insert_last(this->spi_list, this->spis.ptr + i *
+                                                                                                                       this->spi_size);
+                       }
+               }
        }
-       cloned_spis.ptr = clalloc(this->spis.ptr,this->spis.len);
-       cloned_spis.len = this->spis.len;
-       return cloned_spis;
+       return this->spi_list->create_iterator(this->spi_list, TRUE);
 }
 
 /**
@@ -275,16 +254,19 @@ static void destroy(private_delete_payload_t *this)
 {
        if (this->spis.ptr != NULL)
        {
-               chunk_free(&(this->spis));
+               chunk_free(&this->spis);
+       }
+       if (this->spi_list)
+       {
+               this->spi_list->destroy(this->spi_list);
        }
-       
        free(this);     
 }
 
 /*
  * Described in header
  */
-delete_payload_t *delete_payload_create()
+delete_payload_t *delete_payload_create(protocol_id_t protocol_id)
 {
        private_delete_payload_t *this = malloc_thing(private_delete_payload_t);
 
@@ -299,24 +281,19 @@ delete_payload_t *delete_payload_create()
        
        /* public functions */
        this->public.destroy = (void (*) (delete_payload_t *)) destroy;
-       this->public.set_protocol_id = (void (*) (delete_payload_t *,protocol_id_t)) set_protocol_id;
        this->public.get_protocol_id = (protocol_id_t (*) (delete_payload_t *)) get_protocol_id;
-       this->public.set_spi_size = (void (*) (delete_payload_t *,u_int8_t)) set_spi_size;
-       this->public.get_spi_size = (u_int8_t (*) (delete_payload_t *)) get_spi_size;
-       this->public.set_spi_count = (void (*) (delete_payload_t *,u_int16_t)) set_spi_count;
-       this->public.get_spi_count = (u_int16_t (*) (delete_payload_t *)) get_spi_count;
-       this->public.set_spis = (void (*) (delete_payload_t *,chunk_t)) set_spis;
-       this->public.get_spis_clone = (chunk_t (*) (delete_payload_t *)) get_spis_clone;
-       this->public.get_spis = (chunk_t (*) (delete_payload_t *)) get_spis;
+       this->public.add_spi = (void (*) (delete_payload_t *,u_int32_t))add_spi;
+       this->public.create_spi_iterator = (iterator_t* (*) (delete_payload_t *)) create_spi_iterator;
        
        /* private variables */
        this->critical = FALSE;
        this->next_payload = NO_PAYLOAD;
-       this->payload_length =DELETE_PAYLOAD_HEADER_LENGTH;
-       this->protocol_id = PROTO_NONE;
-       this->spi_size = 0;
+       this->payload_length = DELETE_PAYLOAD_HEADER_LENGTH;
+       this->protocol_id = protocol_id;
+       this->spi_size = protocol_id == PROTO_AH || protocol_id == PROTO_ESP ? 4 : 0;
        this->spi_count = 0;
-       this->spis = CHUNK_INITIALIZER;
+       this->spis = chunk_empty;
+       this->spi_list = NULL;
 
-       return (&(this->public));
+       return (&this->public);
 }