- fixed doxygen build
[strongswan.git] / Source / charon / config / traffic_selector.c
index 22ab2a9..8127265 100644 (file)
@@ -23,8 +23,9 @@
 #include "traffic_selector.h"
 
 #include <utils/linked_list.h>
-#include <utils/allocator.h>
 #include <utils/identification.h>
+#include <arpa/inet.h>
+#include <string.h>
 
 typedef struct private_traffic_selector_t private_traffic_selector_t;
 
@@ -49,25 +50,17 @@ struct private_traffic_selector_t {
        u_int8_t protocol;
        
        /** 
-        * begin of address range 
+        * begin of address range, host order
         */
        union {
-               struct {
-                       u_int32_t from_addr_ipv4;
-               };
-               struct {
-               };
+               u_int32_t from_addr_ipv4;
        };
        
        /**
-        * end of address range 
+        * end of address range, host order
         */
        union {
-               struct {
-                       u_int32_t to_addr_ipv4;
-               };
-               struct {
-               };
+               u_int32_t to_addr_ipv4;
        };
        
        /**
@@ -82,7 +75,7 @@ struct private_traffic_selector_t {
 };
 
 /**
- * internal generic constructor 
+ * internal generic constructor
  */
 static private_traffic_selector_t *traffic_selector_create(u_int8_t protocol, ts_type_t type, u_int16_t from_port, u_int16_t to_port);
 
@@ -99,31 +92,26 @@ static traffic_selector_t *get_subset(private_traffic_selector_t *this, private_
                u_int16_t from_port, to_port;
                private_traffic_selector_t *new_ts;
                
+               /* calculate the maximum address range allowed for both */
                from_addr = max(this->from_addr_ipv4, other->from_addr_ipv4);
                to_addr = min(this->to_addr_ipv4, other->to_addr_ipv4);
-               
-               printf("FromAddr: policy: %u, request: %u, match: %u\n", this->from_addr_ipv4, other->from_addr_ipv4, from_addr);
-               printf("ToAddr  : policy: %u, request: %u, match: %u\n", this->to_addr_ipv4, other->to_addr_ipv4, to_addr);
                if (from_addr > to_addr)
                {
                        /* no match */
                        return NULL;    
                }
+               
+               /* calculate the maximum port range allowed for both */
                from_port = max(this->from_port, other->from_port);
                to_port = min(this->to_port, other->to_port);
-               
-               printf("FromPort: policy: %u, request: %u, match: %u\n", this->from_port, other->from_port, from_port);
-               printf("ToPort:   policy: %u, request: %u, match: %u\n", this->to_port, other->to_port, to_port);
                if (from_port > to_port)
                {
                        /* no match */
                        return NULL;    
                }
                
-               
-               printf("got one\n");
+               /* got a match, return it */
                new_ts = traffic_selector_create(this->protocol, this->type, from_port, to_port); 
-               
                new_ts->from_addr_ipv4 = from_addr;
                new_ts->to_addr_ipv4 = to_addr;
                new_ts->type = TS_IPV4_ADDR_RANGE;
@@ -145,7 +133,7 @@ static chunk_t get_from_address(private_traffic_selector_t *this)
                {
                        u_int32_t network;
                        from_addr.len = sizeof(network);
-                       from_addr.ptr = allocator_alloc(from_addr.len);
+                       from_addr.ptr = malloc(from_addr.len);
                        /* chunk must contain network order, convert! */
                        network = htonl(this->from_addr_ipv4);
                        memcpy(from_addr.ptr, &network, from_addr.len);
@@ -172,7 +160,7 @@ static chunk_t get_to_address(private_traffic_selector_t *this)
                {
                        u_int32_t network;
                        to_addr.len = sizeof(network);
-                       to_addr.ptr = allocator_alloc(to_addr.len);
+                       to_addr.ptr = malloc(to_addr.len);
                        /* chunk must contain network order, convert! */
                        network = htonl(this->to_addr_ipv4);
                        memcpy(to_addr.ptr, &network, to_addr.len);
@@ -203,6 +191,69 @@ static u_int16_t get_to_port(private_traffic_selector_t *this)
 }
 
 /**
+ * Implements traffic_selector_t.get_type.
+ */
+static ts_type_t get_type(private_traffic_selector_t *this)
+{
+       return this->type;
+}
+
+/**
+ * Implements traffic_selector_t.get_protocol.
+ */
+static u_int8_t get_protocol(private_traffic_selector_t *this)
+{
+       return this->protocol;
+}
+
+/**
+ * Implements traffic_selector_t.get_netmask.
+ */
+static u_int8_t get_netmask(private_traffic_selector_t *this)
+{
+       switch (this->type)
+       {
+               case TS_IPV4_ADDR_RANGE:
+               {
+                       u_int32_t from, to, bit;
+                       from = htonl(this->from_addr_ipv4);
+                       to = htonl(this->to_addr_ipv4);
+                       for (bit = 0; bit < 32; bit++)
+                       {                               
+                               if ((1<<bit & from) != (1<<bit & to))
+                               {
+                                       return bit;
+                               }
+                       }
+                       return 32;
+               }
+               case TS_IPV6_ADDR_RANGE:
+               default:
+               {
+                       return 0;
+               }
+       }
+}
+
+/**
+ * Implements traffic_selector_t.update_address_range.
+ */
+static void update_address_range(private_traffic_selector_t *this, host_t *host)
+{
+       if (host->get_family(host) == AF_INET &&
+               this->type == TS_IPV4_ADDR_RANGE)
+       {
+               if (this->from_addr_ipv4 == 0)
+               {
+                       chunk_t from = host->get_address_as_chunk(host);
+                       this->from_addr_ipv4 = ntohl(*((u_int32_t*)from.ptr));
+                       this->to_addr_ipv4 = this->from_addr_ipv4;
+                       chunk_free(&from);
+               }
+       }
+}
+
+/**
  * Implements traffic_selector_t.clone.
  */
 static traffic_selector_t *clone(private_traffic_selector_t *this)
@@ -220,7 +271,7 @@ static traffic_selector_t *clone(private_traffic_selector_t *this)
                case TS_IPV6_ADDR_RANGE:
                default:
                {
-                       allocator_free(this);
+                       free(this);
                        return NULL;    
                }
        }
@@ -231,7 +282,7 @@ static traffic_selector_t *clone(private_traffic_selector_t *this)
  */
 static void destroy(private_traffic_selector_t *this)
 {      
-       allocator_free(this);
+       free(this);
 }
 
 /*
@@ -248,7 +299,7 @@ traffic_selector_t *traffic_selector_create_from_bytes(u_int8_t protocol, ts_typ
                {
                        if (from_addr.len != 4 || to_addr.len != 4)
                        {
-                               allocator_free(this);
+                               free(this);
                                return NULL;    
                        }
                        /* chunk contains network order, convert! */
@@ -259,16 +310,53 @@ traffic_selector_t *traffic_selector_create_from_bytes(u_int8_t protocol, ts_typ
                case TS_IPV6_ADDR_RANGE:
                default:
                {
-                       allocator_free(this);
+                       free(this);
                        return NULL;    
                }
        }
        return (&this->public);
 }
 
+/*
+ * see header
+ */
+traffic_selector_t *traffic_selector_create_from_subnet(host_t *net, u_int8_t netbits)
+{
+       private_traffic_selector_t *this = traffic_selector_create(0, 0, 0, 65535);
+
+       switch (net->get_family(net))
+       {
+               case AF_INET:
+               {
+                       chunk_t from;
+                       
+                       this->type = TS_IPV4_ADDR_RANGE;
+                       from = net->get_address_as_chunk(net);
+                       this->from_addr_ipv4 = ntohl(*((u_int32_t*)from.ptr));
+                       if (this->from_addr_ipv4 == 0)
+                       {
+                               /* use /32 for 0.0.0.0 */
+                               this->to_addr_ipv4 = 0xFFFFFF;
+                       }
+                       else
+                       {
+                               this->to_addr_ipv4 = this->from_addr_ipv4 | ((1 << (32 - netbits)) - 1);
+                       }
+                       chunk_free(&from);
+                       break;  
+               }
+               case AF_INET6:
+               default:
+               {
+                       free(this);
+                       return NULL;    
+               }
+       }
+       return (&this->public);
+}
 
 /*
- * Described in header-file
+ * see header
  */
 traffic_selector_t *traffic_selector_create_from_string(u_int8_t protocol, ts_type_t type, char *from_addr, u_int16_t from_port, char *to_addr, u_int16_t to_port)
 {
@@ -285,12 +373,12 @@ traffic_selector_t *traffic_selector_create_from_string(u_int8_t protocol, ts_ty
                {
                        if (inet_aton(from_addr, (struct in_addr*)&(this->from_addr_ipv4)) == 0)
                        {
-                               allocator_free(this);
+                               free(this);
                                return NULL;
                        }
                        if (inet_aton(to_addr, (struct in_addr*)&(this->to_addr_ipv4)) == 0)
                        {
-                               allocator_free(this);
+                               free(this);
                                return NULL;
                        }
                        /* convert to host order, inet_aton has network order */
@@ -300,7 +388,7 @@ traffic_selector_t *traffic_selector_create_from_string(u_int8_t protocol, ts_ty
                }
                case TS_IPV6_ADDR_RANGE:
                {
-                       allocator_free(this);
+                       free(this);
                        return NULL;    
                }
        }
@@ -313,7 +401,7 @@ traffic_selector_t *traffic_selector_create_from_string(u_int8_t protocol, ts_ty
  */
 static private_traffic_selector_t *traffic_selector_create(u_int8_t protocol, ts_type_t type, u_int16_t from_port, u_int16_t to_port)
 {
-       private_traffic_selector_t *this = allocator_alloc_thing(private_traffic_selector_t);
+       private_traffic_selector_t *this = malloc_thing(private_traffic_selector_t);
 
        /* public functions */
        this->public.get_subset = (traffic_selector_t*(*)(traffic_selector_t*,traffic_selector_t*))get_subset;
@@ -321,6 +409,10 @@ static private_traffic_selector_t *traffic_selector_create(u_int8_t protocol, ts
        this->public.get_to_address = (chunk_t(*)(traffic_selector_t*))get_to_address;
        this->public.get_from_port = (u_int16_t(*)(traffic_selector_t*))get_from_port;
        this->public.get_to_port = (u_int16_t(*)(traffic_selector_t*))get_to_port;      
+       this->public.get_type = (ts_type_t(*)(traffic_selector_t*))get_type;    
+       this->public.get_protocol = (u_int8_t(*)(traffic_selector_t*))get_protocol;
+       this->public.get_netmask = (u_int8_t(*)(traffic_selector_t*))get_netmask;
+       this->public.update_address_range = (void(*)(traffic_selector_t*,host_t*))update_address_range;
        this->public.clone = (traffic_selector_t*(*)(traffic_selector_t*))clone;
        this->public.destroy = (void(*)(traffic_selector_t*))destroy;
        
@@ -331,4 +423,3 @@ static private_traffic_selector_t *traffic_selector_create(u_int8_t protocol, ts
        
        return this;
 }
-