cleanups in kernel interface code
authorMartin Willi <martin@strongswan.org>
Tue, 18 Jul 2006 12:53:54 +0000 (12:53 -0000)
committerMartin Willi <martin@strongswan.org>
Tue, 18 Jul 2006 12:53:54 +0000 (12:53 -0000)
added proper traffic selector to string conversion
some cleanups here & there

23 files changed:
configure.in
src/charon/Makefile.am
src/charon/config/connections/local_connection_store.c
src/charon/config/policies/policy.c
src/charon/config/traffic_selector.c
src/charon/config/traffic_selector.h
src/charon/doc/Todo-list.txt
src/charon/encoding/payloads/traffic_selector_substructure.c
src/charon/network/interfaces.c
src/charon/network/socket.c
src/charon/queues/jobs/incoming_packet_job.c
src/charon/queues/send_queue.c
src/charon/sa/child_sa.c
src/charon/sa/child_sa.h
src/charon/sa/ike_sa.c
src/charon/sa/transactions/ike_auth.c
src/charon/sa/transactions/ike_sa_init.c
src/charon/threads/kernel_interface.c
src/charon/threads/kernel_interface.h
src/charon/threads/stroke_interface.c
src/libstrongswan/utils/host.c
src/libstrongswan/utils/host.h
src/libstrongswan/utils/leak_detective.c

index 8dfbc40..5099c45 100644 (file)
@@ -141,7 +141,7 @@ AC_OUTPUT(
        src/pluto/Makefile
        src/whack/Makefile
        src/charon/Makefile
-       src/charon/testing/Makefile
+dnl    src/charon/testing/Makefile
        src/stroke/Makefile
        src/ipsec/Makefile
        src/starter/Makefile
index b22c12e..a0f8541 100644 (file)
@@ -1,4 +1,4 @@
-SUBDIRS = . testing
+SUBDIRS = . testing
 
 ipsec_PROGRAMS = charon
 
index 31d466e..c6e982e 100644 (file)
@@ -75,7 +75,7 @@ static connection_t *get_connection_by_hosts(private_local_connection_store_t *t
        connection_t *found = NULL;
        
        this->logger->log(this->logger, CONTROL|LEVEL1, "looking for connection for host pair %s...%s",
-                                         my_host->get_address(my_host), other_host->get_address(other_host));
+                                         my_host->get_string(my_host), other_host->get_string(other_host));
        
        pthread_mutex_lock(&(this->mutex));
        iterator = this->connections->create_iterator(this->connections, TRUE);
@@ -108,8 +108,8 @@ static connection_t *get_connection_by_hosts(private_local_connection_store_t *t
                        this->logger->log(this->logger, CONTROL|LEVEL2,
                                                         "candidate connection \"%s\": %s...%s (prio=%d)",
                                                          candidate->get_name(candidate),
-                                                         candidate_my_host->get_address(candidate_my_host),
-                                                         candidate_other_host->get_address(candidate_other_host),
+                                                         candidate_my_host->get_string(candidate_my_host),
+                                                         candidate_other_host->get_string(candidate_other_host),
                                                          prio);
 
                        if (prio > best_prio)
@@ -129,8 +129,8 @@ static connection_t *get_connection_by_hosts(private_local_connection_store_t *t
                this->logger->log(this->logger, CONTROL,
                                                 "found matching connection \"%s\": %s...%s (prio=%d)",
                                                  found->get_name(found),
-                                                 found_my_host->get_address(found_my_host),
-                                                 found_other_host->get_address(found_other_host),
+                                                 found_my_host->get_string(found_my_host),
+                                                 found_other_host->get_string(found_other_host),
                                                  best_prio);
 
                found = found->clone(found);
@@ -243,8 +243,8 @@ void log_connections(private_local_connection_store_t *this, logger_t *logger, c
 
                        logger->log(logger, CONTROL, "  \"%s\": %s...%s",
                                                current->get_name(current),
-                                               my_host->get_address(my_host),
-                                               other_host->get_address(other_host));
+                                               my_host->get_string(my_host),
+                                               other_host->get_string(other_host));
                }
        }
        iterator->destroy(iterator);
index 561c28f..152c157 100644 (file)
@@ -29,7 +29,7 @@
 
 #include <utils/linked_list.h>
 #include <utils/identification.h>
-#include <utils/logger.h>
+#include <utils/logger_manager.h>
 
 typedef struct private_policy_t private_policy_t;
 
@@ -105,9 +105,9 @@ struct private_policy_t {
        u_int32_t jitter;
        
        /**
-        * select_traffic_selectors for both
+        * logger
         */
-       linked_list_t *(*select_traffic_selectors) (private_policy_t *,linked_list_t*,linked_list_t*);
+       logger_t *logger;
 };
 
 /**
@@ -202,21 +202,6 @@ static linked_list_t *get_other_traffic_selectors(private_policy_t *this, traffi
 }
 
 /**
- * Implementation of private_policy_t.select_my_traffic_selectors
- */
-static linked_list_t *select_my_traffic_selectors(private_policy_t *this, linked_list_t *supplied)
-{
-       return this->select_traffic_selectors(this, this->my_ts, supplied);
-}
-
-/**
- * Implementation of private_policy_t.select_other_traffic_selectors
- */
-static linked_list_t *select_other_traffic_selectors(private_policy_t *this, linked_list_t *supplied)
-{
-       return this->select_traffic_selectors(this, this->other_ts, supplied);
-}
-/**
  * Implementation of private_policy_t.select_traffic_selectors
  */
 static linked_list_t *select_traffic_selectors(private_policy_t *this, linked_list_t *stored, linked_list_t *supplied)
@@ -225,6 +210,9 @@ static linked_list_t *select_traffic_selectors(private_policy_t *this, linked_li
        traffic_selector_t *supplied_ts, *stored_ts, *selected_ts;
        linked_list_t *selected = linked_list_create();
        
+       this->logger->log(this->logger, CONTROL|LEVEL1,
+                                         "selecting traffic selectors for %s host",
+                                         stored == this->my_ts ? "local" : "remote");
        
        stored_iter = stored->create_iterator(stored, TRUE);
        supplied_iter = supplied->create_iterator(supplied, TRUE);
@@ -240,11 +228,19 @@ static linked_list_t *select_traffic_selectors(private_policy_t *this, linked_li
                {
                        supplied_iter->current(supplied_iter, (void**)&supplied_ts);
                        
+                       this->logger->log(this->logger, CONTROL|LEVEL2,
+                                                         "  stored %s <=> %s received",
+                                                         stored_ts->get_string(stored_ts), 
+                                                         supplied_ts->get_string(supplied_ts));
+                       
                        selected_ts = stored_ts->get_subset(stored_ts, supplied_ts);
                        if (selected_ts)
                        {
                                /* got a match, add to list */
                                selected->insert_last(selected, (void*)selected_ts);
+                               
+                               this->logger->log(this->logger, CONTROL|LEVEL1, "    got a match: %s",
+                                                                 selected_ts->get_string(selected_ts));
                        }
                }
        }
@@ -255,6 +251,22 @@ static linked_list_t *select_traffic_selectors(private_policy_t *this, linked_li
 }
 
 /**
+ * Implementation of private_policy_t.select_my_traffic_selectors
+ */
+static linked_list_t *select_my_traffic_selectors(private_policy_t *this, linked_list_t *supplied)
+{
+       return select_traffic_selectors(this, this->my_ts, supplied);
+}
+
+/**
+ * Implementation of private_policy_t.select_other_traffic_selectors
+ */
+static linked_list_t *select_other_traffic_selectors(private_policy_t *this, linked_list_t *supplied)
+{
+       return select_traffic_selectors(this, this->other_ts, supplied);
+}
+
+/**
  * Implementation of policy_t.get_proposal_iterator
  */
 static linked_list_t *get_proposals(private_policy_t *this)
@@ -365,7 +377,7 @@ static u_int32_t get_hard_lifetime(private_policy_t *this)
 /**
  * Implements policy_t.clone.
  */
-static policy_t *clone(private_policy_t *this)
+static policy_t *clone_(private_policy_t *this)
 {
        private_policy_t *clone = (private_policy_t*)policy_create(this->name,
                                                                                                                           this->my_id->clone(this->my_id),
@@ -507,7 +519,7 @@ policy_t *policy_create(char *name, identification_t *my_id, identification_t *o
        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;
+       this->public.clone = (policy_t*(*)(policy_t*))clone_;
        this->public.destroy = (void(*)(policy_t*))destroy;
        
        /* apply init values */
@@ -521,10 +533,10 @@ policy_t *policy_create(char *name, identification_t *my_id, identification_t *o
        /* initialize private members*/
        this->my_ca = NULL;
        this->other_ca = NULL;
-       this->select_traffic_selectors = select_traffic_selectors;
        this->proposals = linked_list_create();
        this->my_ts = linked_list_create();
        this->other_ts = linked_list_create();
+       this->logger = logger_manager->get_logger(logger_manager, CONFIG);
 
        return (&this->public);
 }
index 203efe2..b0b0a13 100644 (file)
  * for more details.
  */
 
+#include <arpa/inet.h>
+#include <string.h>
+#include <netdb.h>
+
 #include "traffic_selector.h"
 
 #include <utils/linked_list.h>
 #include <utils/identification.h>
-#include <utils/logger_manager.h>
-#include <arpa/inet.h>
-#include <string.h>
 
 typedef struct private_traffic_selector_t private_traffic_selector_t;
 
@@ -76,9 +77,9 @@ struct private_traffic_selector_t {
        u_int16_t to_port;
        
        /**
-        * Logger reference
+        * string representation of this traffic selector
         */
-       logger_t *logger;
+       char *string;
 };
 
 /**
@@ -87,6 +88,122 @@ struct private_traffic_selector_t {
 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);
 
 /**
+ * update the string representation of this traffic selector
+ */
+static void update_string(private_traffic_selector_t *this)
+{
+       char buf[256];
+       struct protoent *proto;
+       struct servent *serv;
+       char *serv_proto = NULL;
+       char proto_str[8] = "";
+       char addr_str[INET6_ADDRSTRLEN];
+       char port_str[16] = "";
+       char mask_str[8] = "";
+       char proto_port_str[32] = "";
+       bool has_proto = FALSE, has_port = FALSE;
+       
+       if (this->type == TS_IPV4_ADDR_RANGE)
+       {
+               u_int32_t from_no, to_no, bit;
+               u_int8_t mask = 32;
+               
+               /* build address string */
+               from_no = htonl(this->from_addr_ipv4);
+               to_no = htonl(this->to_addr_ipv4);
+               inet_ntop(AF_INET, &from_no, addr_str, sizeof(addr_str));
+               
+               /* build network mask string */
+               for (bit = 0; bit < 32; bit++)
+               {
+                       if ((1<<bit & from_no) != (1<<bit & to_no))
+                       {
+                               mask = bit;
+                               break;
+                       }
+               }
+               if (mask != 32)
+               {
+                       snprintf(mask_str, sizeof(mask_str), "/%d", mask);
+               }
+       }
+       else
+       {
+               /* TODO: be a little bit more verbose ;-) */
+               snprintf(addr_str, sizeof(addr_str), "(IPv6 address range)");
+       }
+       
+       /* build protocol string */
+       if (this->protocol)
+       {
+               proto = getprotobynumber(this->protocol);
+               if (proto)
+               {
+                       snprintf(proto_str, sizeof(proto_str), "%s", proto->p_name);
+                       serv_proto = proto->p_name;
+               }
+               else
+               {
+                       snprintf(proto_str, sizeof(proto_str), "%d", this->protocol);
+               }
+               has_proto = TRUE;
+       }
+       
+       /* build port string */
+       if (this->from_port == this->to_port)
+       {
+               serv = getservbyport(htons(this->from_port), serv_proto);
+               if (serv)
+               {
+                       snprintf(port_str, sizeof(port_str), "%s", serv->s_name);
+               }
+               else
+               {
+                       snprintf(port_str, sizeof(port_str), "%d", this->from_port);
+               }
+               has_port = TRUE;
+       }
+       else if (!(this->from_port == 0 && this->to_port == 0xFFFF))
+       {
+               snprintf(port_str, sizeof(port_str), "%d-%d",
+                                this->from_port, this->to_port);
+               has_port = TRUE;
+       }
+       
+       /* concatenate port & proto string */
+       if (has_proto && has_port)
+       {
+               snprintf(proto_port_str, sizeof(proto_port_str), "[%s/%s]", 
+                                proto_str, port_str);
+       }
+       else if (has_proto)
+       {
+               snprintf(proto_port_str, sizeof(proto_port_str), "[%s]", proto_str);
+       }
+       else if (has_port)
+       {
+               snprintf(proto_port_str, sizeof(proto_port_str), "[%s]", port_str);
+       }
+       
+       /* concatenate it all */
+       snprintf(buf, sizeof(buf), "%s%s%s", addr_str, mask_str, proto_port_str);
+
+       if (this->string)
+       {
+               free(this->string);
+       }
+       this->string = strdup(buf);
+}
+
+/**
+ * implements traffic_selector_t.get_string
+ */
+static char *get_string(private_traffic_selector_t *this)
+{
+       return this->string;
+}
+
+/**
  * implements traffic_selector_t.get_subset
  */
 static traffic_selector_t *get_subset(private_traffic_selector_t *this, private_traffic_selector_t *other)
@@ -99,19 +216,12 @@ static traffic_selector_t *get_subset(private_traffic_selector_t *this, private_
                u_int8_t protocol;
                private_traffic_selector_t *new_ts;
                
-               /* TODO: make output more human readable */
-               this->logger->log(this->logger, CONTROL|LEVEL2,
-                                                 "matching traffic selector ranges %x:%d-%x:%d <=> %x:%d-%x:%d",
-                                                 this->from_addr_ipv4, this->from_port, this->to_addr_ipv4, this->to_port,
-                                                 other->from_addr_ipv4, other->from_port, other->to_addr_ipv4, other->to_port);
                /* 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);
                if (from_addr > to_addr)
                {
-                       this->logger->log(this->logger, CONTROL|LEVEL2,
-                                                         "no match in address range");
-                       return NULL;    
+                       return NULL;
                }
                
                /* calculate the maximum port range allowed for both */
@@ -119,9 +229,7 @@ static traffic_selector_t *get_subset(private_traffic_selector_t *this, private_
                to_port = min(this->to_port, other->to_port);
                if (from_port > to_port)
                {
-                       this->logger->log(this->logger, CONTROL|LEVEL2,
-                                                         "no match in port range");
-                       return NULL;    
+                       return NULL;
                }
                
                /* select protocol, which is not zero */
@@ -132,10 +240,8 @@ static traffic_selector_t *get_subset(private_traffic_selector_t *this, private_
                new_ts->from_addr_ipv4 = from_addr;
                new_ts->to_addr_ipv4 = to_addr;
                new_ts->type = TS_IPV4_ADDR_RANGE;
+               update_string(new_ts);
                
-               this->logger->log(this->logger, CONTROL|LEVEL2,
-                                                 "got a match: %x:%d-%x:%d",
-                                                 new_ts->from_addr_ipv4, new_ts->from_port, new_ts->to_addr_ipv4, new_ts->to_port);
                return &(new_ts->public);
        }
        return NULL;
@@ -228,35 +334,6 @@ static u_int8_t get_protocol(private_traffic_selector_t *this)
 }
 
 /**
- * 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)
@@ -266,12 +343,12 @@ static void update_address_range(private_traffic_selector_t *this, host_t *host)
        {
                if (this->from_addr_ipv4 == 0)
                {
-                       chunk_t from = host->get_address_as_chunk(host);
+                       chunk_t from = host->get_address(host);
                        this->from_addr_ipv4 = ntohl(*((u_int32_t*)from.ptr));
                        this->to_addr_ipv4 = this->from_addr_ipv4;
-                       chunk_free(&from);
                }
        }
+       update_string(this);
 }
 
 /**
@@ -281,6 +358,7 @@ static traffic_selector_t *clone_(private_traffic_selector_t *this)
 {
        private_traffic_selector_t *clone = traffic_selector_create(this->protocol, this->type, this->from_port, this->to_port);
        clone->type = this->type;
+       clone->string = strdup(this->string);
        switch (clone->type)
        {
                case TS_IPV4_ADDR_RANGE:
@@ -302,14 +380,15 @@ static traffic_selector_t *clone_(private_traffic_selector_t *this)
  * Implements traffic_selector_t.destroy.
  */
 static void destroy(private_traffic_selector_t *this)
-{      
+{
+       free(this->string);
        free(this);
 }
 
 /*
  * see header
  */
-traffic_selector_t *traffic_selector_create_from_bytes(u_int8_t protocol, ts_type_t type, chunk_t from_addr, int16_t from_port, chunk_t to_addr, u_int16_t to_port)
+traffic_selector_t *traffic_selector_create_from_bytes(u_int8_t protocol, ts_type_t type, chunk_t from_addr, u_int16_t from_port, chunk_t to_addr, u_int16_t to_port)
 {
        private_traffic_selector_t *this = traffic_selector_create(protocol, type, from_port, to_port);
 
@@ -335,6 +414,9 @@ traffic_selector_t *traffic_selector_create_from_bytes(u_int8_t protocol, ts_typ
                        return NULL;    
                }
        }
+       
+       update_string(this);
+       
        return (&this->public);
 }
 
@@ -352,7 +434,7 @@ traffic_selector_t *traffic_selector_create_from_subnet(host_t *net, u_int8_t ne
                        chunk_t from;
                        
                        this->type = TS_IPV4_ADDR_RANGE;
-                       from = net->get_address_as_chunk(net);
+                       from = net->get_address(net);
                        this->from_addr_ipv4 = ntohl(*((u_int32_t*)from.ptr));
                        if (this->from_addr_ipv4 == 0)
                        {
@@ -363,7 +445,6 @@ traffic_selector_t *traffic_selector_create_from_subnet(host_t *net, u_int8_t ne
                        {
                                this->to_addr_ipv4 = this->from_addr_ipv4 | ((1 << (32 - netbits)) - 1);
                        }
-                       chunk_free(&from);
                        break;  
                }
                case AF_INET6:
@@ -379,6 +460,8 @@ traffic_selector_t *traffic_selector_create_from_subnet(host_t *net, u_int8_t ne
                this->to_port = port;
        }
        
+       update_string(this);
+       
        return (&this->public);
 }
 
@@ -419,7 +502,9 @@ traffic_selector_t *traffic_selector_create_from_string(u_int8_t protocol, ts_ty
                        return NULL;    
                }
        }
-
+       
+       update_string(this);
+       
        return (&this->public);
 }
 
@@ -432,13 +517,13 @@ static private_traffic_selector_t *traffic_selector_create(u_int8_t protocol, ts
 
        /* public functions */
        this->public.get_subset = (traffic_selector_t*(*)(traffic_selector_t*,traffic_selector_t*))get_subset;
+       this->public.get_string = (char*(*)(traffic_selector_t*))get_string;
        this->public.get_from_address = (chunk_t(*)(traffic_selector_t*))get_from_address;
        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;
@@ -447,7 +532,7 @@ static private_traffic_selector_t *traffic_selector_create(u_int8_t protocol, ts
        this->to_port = to_port;
        this->protocol = protocol;
        this->type = type;
-       this->logger = logger_manager->get_logger(logger_manager, CONFIG);
+       this->string = NULL;
        
        return this;
 }
index ef07114..420f97d 100644 (file)
@@ -82,20 +82,21 @@ struct traffic_selector_t {
        /**
         * @brief Compare two traffic selectors, and create a new one
         * which is the largest subset of both (subnet & port).
-        * 
+        *
         * Resulting traffic_selector is newly created and must be destroyed.
-        * 
+        *
         * @param this          first to compare
         * @param other         second to compare
         * @return
         *                                      - created subset of them
         *                                      - or NULL if no match between this and other
         */
-       traffic_selector_t *(*get_subset) (traffic_selector_t *this, traffic_selector_t *other);
+       traffic_selector_t *(*get_subset)  (traffic_selector_t *this, 
+                                                                               traffic_selector_t *other);
        
        /**
         * @brief Clone a traffic selector.
-        *  
+        *
         * @param this          traffic selector to clone
         * @return                      clone of it
         */
@@ -103,12 +104,9 @@ struct traffic_selector_t {
        
        /**
         * @brief Get starting address of this ts as a chunk.
-        * 
-        * Data is in network order and represents the address.
-        * Size depends on protocol.
-        * 
-        * Resulting chunk data is allocated and must be freed!
-        *  
+        *
+        * Chunk is in network order gets allocated.
+        *
         * @param this          calling object
         * @return                      chunk containing the address
         */
@@ -116,12 +114,9 @@ struct traffic_selector_t {
        
        /**
         * @brief Get ending address of this ts as a chunk.
-        * 
-        * Data is in network order and represents the address.
-        * Size depends on protocol.
-        * 
-        * Resulting chunk data is allocated and must be freed!
-        *  
+        *
+        * Chunk is in network order gets allocated.
+        *
         * @param this          calling object
         * @return                      chunk containing the address
         */
@@ -140,10 +135,10 @@ struct traffic_selector_t {
        
        /**
         * @brief Get ending port of this ts.
-        * 
+        *
         * Port is in host order, since the parser converts it.
         * Size depends on protocol.
-        *  
+        *
         * @param this          calling object
         * @return                      port
         */
@@ -151,51 +146,47 @@ struct traffic_selector_t {
        
        /**
         * @brief Get the type of the traffic selector.
-        * 
+        *
         * @param this          calling obect
         * @return                      ts_type_t specifying the type
         */
        ts_type_t (*get_type) (traffic_selector_t *this);
-               
+       
        /**
         * @brief Get the protocol id of this ts.
-        * 
+        *
         * @param this          calling obect
         * @return                      protocol id
         */
        u_int8_t (*get_protocol) (traffic_selector_t *this);
-               
-       /**
-        * @brief Get the netmask of the address range.
-        * 
-        * Returns the number of bits associated to the subnet.
-        * (As the "24" in "192.168.0.0/24"). This is approximated
-        * if the address range is not a complete subnet! Since Linux
-        * does not support full IP address ranges (yet), we can't do this
-        * (much) better.
-        * 
-        * @param this          calling obect
-        * @return                      netmask as "bits for subnet"
-        */
-       u_int8_t (*get_netmask) (traffic_selector_t *this);
-               
+       
        /**
         * @brief Update the address of a traffic selector.
-        * 
+        *
         * Update the address range of a traffic selector, 
         * if the current address is 0.0.0.0. The new address range
         * starts from the supplied address and also ends there 
         * (which means it is a one-host-address-range ;-).
-        * 
+        *
         * @param this          calling obect
         * @param host          host_t specifying the address range
         */
        void (*update_address_range) (traffic_selector_t *this, host_t* host);
        
        /**
-        * @brief Destroys the ts object
+        * @brief Get a string representation of the traffic selector.
+        *
+        * String points to internal data, do not free/modify.
         * 
         * @param this          calling object
+        * @return                      pointer to a string.
+        */
+       char* (*get_string) (traffic_selector_t *this);
+       
+       /**
+        * @brief Destroys the ts object
+        *
+        * @param this          calling object
         */
        void (*destroy) (traffic_selector_t *this);
 };
@@ -215,7 +206,10 @@ struct traffic_selector_t {
  * 
  * @ingroup config
  */
-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);
+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);
 
 /**
  * @brief Create a new traffic selector using data read from the net.
@@ -236,7 +230,10 @@ traffic_selector_t *traffic_selector_create_from_string(u_int8_t protocol, ts_ty
  *
  * @ingroup config
  */
-traffic_selector_t *traffic_selector_create_from_bytes(u_int8_t protocol, ts_type_t type, chunk_t from_address, int16_t from_port, chunk_t to_address, u_int16_t to_port);
+traffic_selector_t *traffic_selector_create_from_bytes(
+                                                               u_int8_t protocol, ts_type_t type,
+                                                               chunk_t from_address, u_int16_t from_port,
+                                                               chunk_t to_address, u_int16_t to_port);
 
 /**
  * @brief Create a new traffic selector defining a whole subnet.
@@ -256,6 +253,8 @@ traffic_selector_t *traffic_selector_create_from_bytes(u_int8_t protocol, ts_typ
  *
  * @ingroup config
  */
-traffic_selector_t *traffic_selector_create_from_subnet(host_t *net, u_int8_t netbits, u_int8_t protocol, u_int16_t port);
+traffic_selector_t *traffic_selector_create_from_subnet(
+                                                                       host_t *net, u_int8_t netbits, 
+                                                                       u_int8_t protocol, u_int16_t port);
 
 #endif /* TRAFFIC_SELECTOR_H_ */
index 8ae08fb..b0835cd 100644 (file)
@@ -32,7 +32,7 @@
 + doxygen cleanup (charon/lib)
 + new build environment (autotools?)
 
-/ useable certificate support
++ useable certificate support
   + more id types (use atodn from pluto)
   + rewrite certificate storage the clean way
   + further subjectAltName support
index 6abae04..2ac7464 100644 (file)
@@ -56,7 +56,7 @@ struct private_traffic_selector_substructure_t {
        /**
         * IP Protocol ID.
         */
-       u_int8_t  ip_protocol_id;
+       u_int8_t ip_protocol_id;
 
        /**
         * Length of this payload.
@@ -82,11 +82,6 @@ struct private_traffic_selector_substructure_t {
         * Ending address.
         */
        chunk_t ending_address;
-       
-       /**
-        * update length
-        */
-       void (*compute_length) (private_traffic_selector_substructure_t *this);
 };
 
 /**
@@ -137,7 +132,6 @@ encoding_rule_t traffic_selector_substructure_encodings[] = {
  */
 static status_t verify(private_traffic_selector_substructure_t *this)
 {
-       
        if (this->start_port > this->end_port)
        {
                return FAILED;
@@ -161,7 +155,6 @@ static status_t verify(private_traffic_selector_substructure_t *this)
                        return FAILED;
                }
        }
-
        
        return SUCCESS;
 }
@@ -196,6 +189,7 @@ static payload_type_t get_next_type(private_traffic_selector_substructure_t *thi
  */
 static void set_next_type(private_traffic_selector_substructure_t *this,payload_type_t type)
 {
+       
 }
 
 /**
@@ -207,82 +201,6 @@ static size_t get_length(private_traffic_selector_substructure_t *this)
 }
 
 /**
- * Implementation of traffic_selector_substructure_t.get_ts_type.
- */
-static ts_type_t get_ts_type (private_traffic_selector_substructure_t *this)
-{
-       return this->ts_type;
-}
-
-/**
- * Implementation of traffic_selector_substructure_t.set_ts_type.
- */
-static void set_ts_type (private_traffic_selector_substructure_t *this,ts_type_t ts_type)
-{
-       this->ts_type = ts_type;
-}
-
-/**
- * Implementation of traffic_selector_substructure_t.get_protocol_id.
- */
-static u_int8_t get_protocol_id (private_traffic_selector_substructure_t *this)
-{
-       return this->ip_protocol_id;
-}
-
-/**
- * Implementation of traffic_selector_substructure_t.set_protocol_id.
- */    
-static void set_protocol_id (private_traffic_selector_substructure_t *this,u_int8_t protocol_id)
-{
-       this->ip_protocol_id = protocol_id;
-}
-
-/**
- * Implementation of traffic_selector_substructure_t.get_start_host.
- */
-static host_t * get_start_host (private_traffic_selector_substructure_t *this)
-{
-       return (host_create_from_chunk(AF_INET,this->starting_address, this->start_port));
-}
-
-/**
- * Implementation of traffic_selector_substructure_t.set_start_host.
- */
-static void set_start_host (private_traffic_selector_substructure_t *this,host_t *start_host)
-{
-       this->start_port = start_host->get_port(start_host);
-       if (this->starting_address.ptr != NULL)
-       {
-               chunk_free(&(this->starting_address));
-       }
-       this->starting_address = start_host->get_address_as_chunk(start_host);
-       this->compute_length(this);
-}
-
-/**
- * Implementation of traffic_selector_substructure_t.get_end_host.
- */
-static host_t *get_end_host (private_traffic_selector_substructure_t *this)
-{
-       return (host_create_from_chunk(AF_INET,this->ending_address, this->end_port));
-}
-
-/**
- * Implementation of traffic_selector_substructure_t.set_end_host.
- */
-static void set_end_host (private_traffic_selector_substructure_t *this,host_t *end_host)
-{
-       this->end_port = end_host->get_port(end_host);
-       if (this->ending_address.ptr != NULL)
-       {
-               chunk_free(&(this->ending_address));
-       }
-       this->ending_address = end_host->get_address_as_chunk(end_host);
-       this->compute_length(this);
-}
-
-/**
  * Implementation of traffic_selector_substructure_t.get_traffic_selector.
  */
 static traffic_selector_t *get_traffic_selector(private_traffic_selector_substructure_t *this)
@@ -295,11 +213,12 @@ static traffic_selector_t *get_traffic_selector(private_traffic_selector_substru
 }
 
 /**
- * Implementation of private_ts_payload_t.compute_length 
+ * recompute length field of the payload
  */
 void compute_length(private_traffic_selector_substructure_t *this)
 {
-       this->payload_length = TRAFFIC_SELECTOR_HEADER_LENGTH + this->ending_address.len + this->starting_address.len;
+       this->payload_length = TRAFFIC_SELECTOR_HEADER_LENGTH +
+                       this->ending_address.len + this->starting_address.len;
 }
 
 /**
@@ -329,19 +248,8 @@ traffic_selector_substructure_t *traffic_selector_substructure_create()
        this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
        
        /* public functions */
-       this->public.destroy = (void (*) (traffic_selector_substructure_t *)) destroy;
-       this->public.get_ts_type = (ts_type_t (*) (traffic_selector_substructure_t *)) get_ts_type;
-       this->public.set_ts_type = (void (*) (traffic_selector_substructure_t *,ts_type_t)) set_ts_type;
-       this->public.get_protocol_id = (u_int8_t (*) (traffic_selector_substructure_t *)) get_protocol_id;
-       this->public.set_protocol_id = (void (*) (traffic_selector_substructure_t *,u_int8_t)) set_protocol_id;
-       this->public.get_start_host = (host_t * (*) (traffic_selector_substructure_t *))get_start_host;
-       this->public.set_start_host = (void (*) (traffic_selector_substructure_t *, host_t *))set_start_host;
-       this->public.get_end_host = (host_t * (*) (traffic_selector_substructure_t *))get_end_host;
-       this->public.set_end_host = (void (*) (traffic_selector_substructure_t *, host_t *))set_end_host;
        this->public.get_traffic_selector = (traffic_selector_t* (*)(traffic_selector_substructure_t*))get_traffic_selector;
-       
-       /* private functions */
-       this->compute_length = compute_length;
+       this->public.destroy = (void (*) (traffic_selector_substructure_t *)) destroy;
        
        /* private variables */
        this->payload_length = TRAFFIC_SELECTOR_HEADER_LENGTH;
@@ -368,8 +276,8 @@ traffic_selector_substructure_t *traffic_selector_substructure_create_from_traff
        this->end_port = traffic_selector->get_to_port(traffic_selector);
        this->starting_address = traffic_selector->get_from_address(traffic_selector);
        this->ending_address = traffic_selector->get_to_address(traffic_selector);
-               
-       this->compute_length(this);
+       
+       compute_length(this);
        
        return &(this->public);
 }
index 7578d57..b1244c9 100644 (file)
@@ -74,7 +74,7 @@ static bool is_local_address(private_interfaces_t *this, host_t *host)
        while (iterator->iterate(iterator, (void**)&lhost))
        {
                if (host->get_family(host) == lhost->get_family(lhost) && 
-                       streq(host->get_address(host), lhost->get_address(lhost)))
+                       streq(host->get_string(host), lhost->get_string(lhost)))
                {
                        iterator->destroy(iterator);
                        return TRUE;
index 4dff479..c0c53ff 100644 (file)
@@ -162,8 +162,8 @@ static status_t receiver(private_socket_t *this, packet_t **packet)
        pkt->set_destination(pkt, dest);
 
        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));
+                                         source->get_string(source), source->get_port(source),
+                                         dest->get_string(dest), dest->get_port(dest));
 
        data_offset = IP_LEN + UDP_LEN;
 
@@ -200,8 +200,8 @@ status_t sender(private_socket_t *this, packet_t *packet)
        data = packet->get_data(packet);
 
        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));
+                                         src->get_string(src), src->get_port(src),
+                                         dst->get_string(dst), dst->get_port(dst));
        
        /* send data */
        sport = src->get_port(src);
@@ -404,7 +404,7 @@ static status_t initialize(private_socket_t *this)
        if (setsockopt(this->natt_fd, SOL_UDP, UDP_ENCAP, &type, sizeof(type)) < 0)
        {
                this->logger->log(this->logger, ERROR,
-                                                 "unable to set UDP_ENCAP on raw socket! NAT-T may fail! error: %s",
+                                                 "unable to set UDP_ENCAP on NAT-T socket: %s; NAT-T may fail",
                                                  strerror(errno));
        }
        
index 541d4c1..e24f625 100644 (file)
@@ -113,8 +113,8 @@ static status_t execute(private_incoming_packet_job_t *this)
        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));
+                                         src->get_string(src), src->get_port(src),
+                                         dst->get_string(dst), dst->get_port(dst));
        
        status = message->parse_header(message);
        if (status != SUCCESS)
index e92f630..a24308b 100644 (file)
@@ -112,8 +112,8 @@ static void add(private_send_queue_t *this, packet_t *packet)
        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));
+                                         src->get_string(src), src->get_port(src),
+                                         dst->get_string(dst), dst->get_port(dst));
        
        pthread_mutex_lock(&this->mutex);
        this->list->insert_last(this->list, packet);
index 5bffc25..c9c6794 100644 (file)
@@ -22,8 +22,6 @@
  * for more details.
  */
 
-#include <netdb.h>
-
 #include "child_sa.h"
 
 #include <daemon.h>
@@ -48,18 +46,15 @@ typedef struct sa_policy_t sa_policy_t;
  * for deleting a policy...
  */
 struct sa_policy_t {
-       
-       struct {
-               /** subnet address behind peer peer */
-               host_t *net;
-               /** netmask used for net */
-               u_int8_t net_mask;
-       } me, other;
+       /**
+        * Traffic selector for us
+        */
+       traffic_selector_t *my_ts;
        
        /**
-        * Protocol for this policy, such as TCP/UDP/ICMP...
+        * Traffic selector for other
         */
-       int upper_proto;
+       traffic_selector_t *other_ts;
 };
 
 typedef struct private_child_sa_t private_child_sa_t;
@@ -343,7 +338,7 @@ static status_t install(private_child_sa_t *this, proposal_t *proposal, prf_plus
        /* send SA down to the kernel */
        this->logger->log(this->logger, CONTROL|LEVEL2,
                                                "  SPI 0x%.8x, src %s dst %s",
-                                               ntohl(spi), src->get_address(src), dst->get_address(dst));
+                                               ntohl(spi), src->get_string(src), dst->get_string(dst));
        status = charon->kernel_interface->add_sa(charon->kernel_interface,
                                                                                          src, dst,
                                                                                          spi, this->protocol,
@@ -432,79 +427,52 @@ static status_t add_policies(private_child_sa_t *this, linked_list_t *my_ts_list
                while (other_iter->has_next(other_iter))
                {
                        /* set up policies for every entry in my_ts_list to every entry in other_ts_list */
-                       int family;
-                       chunk_t from_addr;
-                       u_int16_t from_port, to_port;
-                       sa_policy_t *policy;
                        status_t status;
+                       sa_policy_t *policy;
                        
                        other_iter->current(other_iter, (void**)&other_ts);
                        
+                       if (my_ts->get_type(my_ts) != other_ts->get_type(other_ts))
+                       {
+                               this->logger->log(this->logger, CONTROL|LEVEL1, 
+                                                                 "CHILD_SA policy uses two different IP families, ignored");
+                               continue;
+                       }
+                       
                        /* only set up policies if protocol matches, or if one is zero (any) */
                        if (my_ts->get_protocol(my_ts) != other_ts->get_protocol(other_ts) &&
                                my_ts->get_protocol(my_ts) && other_ts->get_protocol(other_ts))
                        {
-                               this->logger->log(this->logger, ERROR
+                               this->logger->log(this->logger, CONTROL|LEVEL1
                                                                  "CHILD_SA policy uses two different protocols, ignored");
                                continue;
                        }
-                       policy = malloc_thing(sa_policy_t);
-                       policy->upper_proto = max(my_ts->get_protocol(my_ts), other_ts->get_protocol(other_ts));
-               
-                       /* calculate net and ports for local side */
-                       family = my_ts->get_type(my_ts) == TS_IPV4_ADDR_RANGE ? AF_INET : AF_INET6;
-                       from_addr = my_ts->get_from_address(my_ts);
-                       from_port = my_ts->get_from_port(my_ts);
-                       to_port = my_ts->get_to_port(my_ts);
-                       from_port = (from_port != to_port) ? 0 : from_port;
-                       policy->me.net = host_create_from_chunk(family, from_addr, from_port);
-                       policy->me.net_mask = my_ts->get_netmask(my_ts);
-                       chunk_free(&from_addr);
                        
-                       /* calculate net and ports for remote side */
-                       family = other_ts->get_type(other_ts) == TS_IPV4_ADDR_RANGE ? AF_INET : AF_INET6;
-                       from_addr = other_ts->get_from_address(other_ts);
-                       from_port = other_ts->get_from_port(other_ts);
-                       to_port = other_ts->get_to_port(other_ts);
-                       from_port = (from_port != to_port) ? 0 : from_port;
-                       policy->other.net = host_create_from_chunk(family, from_addr, from_port);
-                       policy->other.net_mask = other_ts->get_netmask(other_ts);
-                       chunk_free(&from_addr);
-       
                        /* install 3 policies: out, in and forward */
                        status = charon->kernel_interface->add_policy(charon->kernel_interface,
-                                       this->me.addr, this->other.addr,
-                                       policy->me.net, policy->other.net,
-                                       policy->me.net_mask, policy->other.net_mask,
-                                       XFRM_POLICY_OUT, policy->upper_proto,
-                                       this->protocol, this->reqid, FALSE);
-       
+                                       this->me.addr, this->other.addr, my_ts, other_ts, 
+                                       POLICY_OUT, this->protocol, this->reqid, FALSE);
+                       
                        status |= charon->kernel_interface->add_policy(charon->kernel_interface,
-                                       this->other.addr, this->me.addr,
-                                       policy->other.net, policy->me.net,
-                                       policy->other.net_mask, policy->me.net_mask,
-                                       XFRM_POLICY_IN, policy->upper_proto,
-                                       this->protocol, this->reqid, FALSE);
-       
+                                       this->other.addr, this->me.addr, other_ts, my_ts,
+                                       POLICY_IN, this->protocol, this->reqid, FALSE);
+                       
                        status |= charon->kernel_interface->add_policy(charon->kernel_interface,
-                                       this->other.addr, this->me.addr,
-                                       policy->other.net, policy->me.net,
-                                       policy->other.net_mask, policy->me.net_mask,
-                                       XFRM_POLICY_FWD, policy->upper_proto,
-                                       this->protocol, this->reqid, FALSE);
+                                       this->other.addr, this->me.addr, other_ts, my_ts,
+                                       POLICY_FWD, this->protocol, this->reqid, FALSE);
                        
                        if (status != SUCCESS)
                        {
                                my_iter->destroy(my_iter);
                                other_iter->destroy(other_iter);
-                               policy->me.net->destroy(policy->me.net);
-                               policy->other.net->destroy(policy->other.net);
-                               free(policy);
                                return status;
                        }
                        
-                       /* add it to the policy list, since we want to know which policies we own */
-                       this->policies->insert_last(this->policies, policy);
+                       /* store policy to delete/update them later */
+                       policy = malloc_thing(sa_policy_t);
+                       policy->my_ts = my_ts->clone(my_ts);
+                       policy->other_ts = other_ts->clone(other_ts);
+                       this->policies->insert_last(this->policies, (void*)policy);
                }
        }
        my_iter->destroy(my_iter);
@@ -533,22 +501,38 @@ static void* get_rekeying_transaction(private_child_sa_t *this)
  */
 static status_t get_use_time(private_child_sa_t *this, bool inbound, time_t *use_time)
 {
+       iterator_t *iterator;
+       sa_policy_t *policy;
        status_t status;
        
        *use_time = UNDEFINED_TIME;
-       
-       if (inbound)
-       {
-               status = charon->kernel_interface->query_sa(charon->kernel_interface,
-                               this->me.addr, this->me.spi,
-                               this->protocol, use_time);
-       }
-       else
+
+       iterator = this->policies->create_iterator(this->policies, TRUE);
+       while (iterator->iterate(iterator, (void**)&policy))
        {
-               status = charon->kernel_interface->query_sa(charon->kernel_interface,
-                               this->other.addr, this->other.spi,
-                               this->protocol, use_time);
+               if (inbound) 
+               {
+                       time_t in = UNDEFINED_TIME, fwd = UNDEFINED_TIME;
+                       
+                       status = charon->kernel_interface->query_policy(
+                                                                       charon->kernel_interface,
+                                                                       policy->other_ts, policy->my_ts,
+                                                                       POLICY_IN, (u_int32_t*)&in);
+                       status |= charon->kernel_interface->query_policy(
+                                                                       charon->kernel_interface,
+                                                                       policy->other_ts, policy->my_ts,
+                                                                       POLICY_FWD, (u_int32_t*)&fwd);
+                       *use_time = max(in, fwd);
+               }
+               else
+               {
+                       status = charon->kernel_interface->query_policy(
+                                                                       charon->kernel_interface,
+                                                                       policy->my_ts, policy->other_ts, 
+                                                                       POLICY_OUT, (u_int32_t*)use_time);
+               }
        }
+       iterator->destroy(iterator);
        return status;
 }
 
@@ -561,38 +545,44 @@ static void log_status(private_child_sa_t *this, logger_t *logger, char* name)
        char use_in_str[12] = "unused";
        char use_out_str[12] = "unused";
        char rekey_str[12] = "disabled";
-       time_t use_in, use_out, now, rekeying;
+       u_int32_t use_in, use_out, use_fwd, now, rekeying;
+       status_t status;
        
        if (logger == NULL)
        {
                logger = this->logger;
        }
-       now = time(NULL);
-       get_use_time(this, TRUE, &use_in);
-       if (use_in)
+       now = (u_int32_t)time(NULL);
+       
+       /* query SA times */
+       status = charon->kernel_interface->query_sa(charon->kernel_interface,
+                                       this->me.addr, this->me.spi, this->protocol, &use_in);
+       if (status == SUCCESS && use_in)
        {
-               snprintf(use_in_str, sizeof(use_in_str), "%ds", (int)(now - use_in));
+               snprintf(use_in_str, sizeof(use_in_str), "%ds", now - use_in);
        }
-       get_use_time(this, FALSE, &use_out);
-       if (use_out)
+       status = charon->kernel_interface->query_sa(charon->kernel_interface,
+                                       this->other.addr, this->other.spi, this->protocol, &use_out);
+       if (status == SUCCESS && use_out)
        {
-               snprintf(use_out_str, sizeof(use_out_str), "%ds", (int)(now - use_out));
+               snprintf(use_out_str, sizeof(use_out_str), "%ds", now - use_out);
        }
+       
+       /* calculate rekey times */
        if (this->soft_lifetime)
        {
                rekeying = this->soft_lifetime - (now - this->install_time);
                snprintf(rekey_str, sizeof(rekey_str), "%ds", (int)rekeying);
        }
        
-       logger->log(logger, CONTROL|LEVEL1, 
+       logger->log(logger, CONTROL|LEVEL1,
                                "  \"%s\":   using %s, SPIs (in/out): 0x%x/0x%x, reqid: %d",
                                name,
                                this->protocol == PROTO_ESP ? "ESP" : "AH",
                                htonl(this->me.spi), htonl(this->other.spi),
                                this->reqid);
-       
-       logger->log(logger, CONTROL|LEVEL1, 
-                               "  \"%s\":   state: %s, rekeying: %s, last traffic (in/out): %s/%s",
+       logger->log(logger, CONTROL|LEVEL1,
+                               "  \"%s\":   state: %s, rekeying: %s, key age (in/out): %s/%s",
                                name, mapping_find(child_sa_state_m, this->state),
                                rekey_str, use_in_str, use_out_str);
        
@@ -600,55 +590,40 @@ static void log_status(private_child_sa_t *this, logger_t *logger, char* name)
        while (iterator->has_next(iterator))
        {
                sa_policy_t *policy;
-               struct protoent *proto;
-               char proto_str[8] = "";
-               char *proto_name = proto_str;
-               char my_net_str[8] = "";
-               char other_net_str[8] = "";
-               char my_port_str[8] = "";
-               char other_port_str[8] = "";
-               u_int16_t my_port, other_port;
+               char *my_str;
+               char *other_str;
+               char pol_in_str[12] = "unused";
+               char pol_out_str[12] = "unused";
+               char pol_fwd_str[12] = "unused";
                
+               /* get ts strings */
                iterator->current(iterator, (void**)&policy);
+               my_str = policy->my_ts->get_string(policy->my_ts);
+               other_str = policy->other_ts->get_string(policy->other_ts);
                
-               if (policy->upper_proto)
-               {
-                       proto = getprotobynumber(policy->upper_proto);
-                       if (proto)
-                       {
-                               proto_name = proto->p_name;
-                       }
-                       else
-                       {
-                               snprintf(proto_str, sizeof(proto_str), "%d", policy->upper_proto);
-                       }
-               }
-               if (policy->me.net_mask != 32)
-               {
-                       snprintf(my_net_str, sizeof(my_net_str), "/%d", policy->me.net_mask);
-               }
-               if (policy->other.net_mask != 32)
+               /* query policy times */
+               status = charon->kernel_interface->query_policy(charon->kernel_interface,
+                                               policy->other_ts, policy->my_ts, POLICY_IN, &use_in);
+               if (status == SUCCESS && use_in)
                {
-                       snprintf(other_net_str, sizeof(other_net_str), "/%d", policy->other.net_mask);
+                       snprintf(pol_in_str, sizeof(pol_in_str), "%ds", now - use_in);
                }
-               my_port = policy->me.net->get_port(policy->me.net);
-               other_port = policy->other.net->get_port(policy->other.net);
-               if (my_port)
+               status = charon->kernel_interface->query_policy(charon->kernel_interface,
+                                               policy->my_ts, policy->other_ts, POLICY_OUT, &use_out);
+               if (status == SUCCESS && use_out)
                {
-                       snprintf(my_port_str, sizeof(my_port_str), ":%d", my_port);
+                       snprintf(pol_out_str, sizeof(pol_out_str), "%ds", now - use_out);
                }
-               if (other_port)
+               status = charon->kernel_interface->query_policy(charon->kernel_interface,
+                                               policy->other_ts, policy->my_ts, POLICY_FWD, &use_fwd);
+               if (status == SUCCESS && use_fwd)
                {
-                       snprintf(other_port_str, sizeof(other_port_str), ":%d", other_port);
+                       snprintf(pol_fwd_str, sizeof(pol_fwd_str), "%ds", now - use_fwd);
                }
                
-               logger->log(logger, CONTROL, "  \"%s\":     %s%s%s==%s==%s%s%s",
-                                       name,
-                                       policy->me.net->get_address(policy->me.net), 
-                                       my_port_str, my_net_str,
-                                       proto_name,
-                                       policy->other.net->get_address(policy->other.net), 
-                                       other_port_str, other_net_str);
+               logger->log(logger, CONTROL, 
+                                       "  \"%s\":     %s====%s, last use (in/out/fwd): %s/%s/%s",
+                                       name, my_str, other_str, pol_in_str, pol_out_str, pol_fwd_str);
        }
        iterator->destroy(iterator);
 }
@@ -688,16 +663,15 @@ static status_t update_sa_hosts(private_child_sa_t *this, host_t *new_me, host_t
        this->logger->log(this->logger, CONTROL|LEVEL1,
                                          "updating %s SA 0x%x, from %s:%d..%s:%d to %s:%d..%s:%d",
                                          mapping_find(protocol_id_m, this->protocol), ntohl(spi),
-                                         src->get_address(src), src->get_port(src),
-                                         dst->get_address(dst), dst->get_port(dst),
-                                         new_src->get_address(new_src), new_src->get_port(new_src),
-                                         new_dst->get_address(new_dst), new_dst->get_port(new_dst));
+                                         src->get_string(src), src->get_port(src),
+                                         dst->get_string(dst), dst->get_port(dst),
+                                         new_src->get_string(new_src), new_src->get_port(new_src),
+                                         new_dst->get_string(new_dst), new_dst->get_port(new_dst));
        
-       status = charon->kernel_interface->update_sa_hosts(
-                                               charon->kernel_interface,
-                                               src, dst, new_src, new_dst, 
-                                               src_changes, dst_changes,
-                                               spi, this->protocol);
+       status = charon->kernel_interface->update_sa(charon->kernel_interface,
+                                                                                                dst, spi, this->protocol, 
+                                                                                                new_src, new_dst, 
+                                                                                                src_changes, dst_changes);
        
        if (status != SUCCESS)
        {
@@ -721,26 +695,20 @@ static status_t update_policy_hosts(private_child_sa_t *this, host_t *new_me, ho
                status = charon->kernel_interface->add_policy(
                                charon->kernel_interface,
                                new_me, new_other,
-                               policy->me.net, policy->other.net,
-                               policy->me.net_mask, policy->other.net_mask,
-                               XFRM_POLICY_OUT, policy->upper_proto,
-                               this->protocol, this->reqid, TRUE);
+                               policy->my_ts, policy->other_ts,
+                               POLICY_OUT, this->protocol, this->reqid, TRUE);
                
                status |= charon->kernel_interface->add_policy(
                                charon->kernel_interface,
                                new_other, new_me,
-                               policy->other.net, policy->me.net,
-                               policy->other.net_mask, policy->me.net_mask,
-                               XFRM_POLICY_IN, policy->upper_proto,
-                               this->protocol, this->reqid, TRUE);
+                               policy->other_ts, policy->my_ts,
+                               POLICY_IN, this->protocol, this->reqid, TRUE);
                
                status |= charon->kernel_interface->add_policy(
                                charon->kernel_interface,
                                new_other, new_me,
-                               policy->other.net, policy->me.net,
-                               policy->other.net_mask, policy->me.net_mask,
-                               XFRM_POLICY_FWD, policy->upper_proto,
-                               this->protocol, this->reqid, TRUE);
+                               policy->other_ts, policy->my_ts,
+                               POLICY_FWD, this->protocol, this->reqid, TRUE);
                
                if (status != SUCCESS)
                {
@@ -749,7 +717,7 @@ static status_t update_policy_hosts(private_child_sa_t *this, host_t *new_me, ho
                }
        }
        iterator->destroy(iterator);
-
+       
        return SUCCESS;
 }
 
@@ -757,7 +725,7 @@ static status_t update_policy_hosts(private_child_sa_t *this, host_t *new_me, ho
  * Implementation of child_sa_t.update_hosts.
  */
 static status_t update_hosts(private_child_sa_t *this, host_t *new_me, host_t *new_other, 
-                                                        int my_changes, int other_changes) 
+                                                        host_diff_t my_changes, host_diff_t other_changes) 
 {
        if (!my_changes && !other_changes)
        {
@@ -835,21 +803,18 @@ static void destroy(private_child_sa_t *this)
        {
                /* let rekeyed policies, as they are used by another child_sa */
                charon->kernel_interface->del_policy(charon->kernel_interface,
-                                                                                       policy->me.net, policy->other.net,
-                                                                                       policy->me.net_mask, policy->other.net_mask,
-                                                                                       XFRM_POLICY_OUT, policy->upper_proto);
+                                                                                        policy->my_ts, policy->other_ts,
+                                                                                        POLICY_OUT);
                
                charon->kernel_interface->del_policy(charon->kernel_interface,
-                                                                                       policy->other.net, policy->me.net,
-                                                                                       policy->other.net_mask, policy->me.net_mask,
-                                                                                       XFRM_POLICY_IN, policy->upper_proto);
+                                                                                        policy->other_ts, policy->my_ts,
+                                                                                        POLICY_IN);
                
                charon->kernel_interface->del_policy(charon->kernel_interface,
-                                                                                       policy->other.net, policy->me.net,
-                                                                                       policy->other.net_mask, policy->me.net_mask,
-                                                                                       XFRM_POLICY_FWD, policy->upper_proto);
-               policy->me.net->destroy(policy->me.net);
-               policy->other.net->destroy(policy->other.net);
+                                                                                        policy->other_ts, policy->my_ts,
+                                                                                        POLICY_FWD);
+               policy->my_ts->destroy(policy->my_ts);
+               policy->other_ts->destroy(policy->other_ts);
                free(policy);
        }
        this->policies->destroy(this->policies);
@@ -876,7 +841,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.update_hosts = (status_t (*)(child_sa_t*,host_t*,host_t*,host_diff_t,host_diff_t))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_rekeying_transaction = (void (*)(child_sa_t*,void*))set_rekeying_transaction;
index 01f51c1..33d06a7 100644 (file)
@@ -169,13 +169,15 @@ struct child_sa_t {
         *
         * @warning only call this after update() has been called.
         *
-        * @param this          calling object
-        * @param new_me        the new local host
-        * @param new_other     the new remote host
-        * @return                      SUCCESS or FAILED
+        * @param this                  calling object
+        * @param new_me                the new local host
+        * @param new_other             the new remote host
+        * @param my_diff               differences to apply for me
+        * @param other_diff    differences to apply for other
+        * @return                              SUCCESS or FAILED
         */
        status_t (*update_hosts) (child_sa_t *this, host_t *new_me, host_t *new_other, 
-                                                         int my_changes, int other_changes);
+                                                         host_diff_t my_diff, host_diff_t other_diff);
        
        /**
         * @brief Install the policies using some traffic selectors.
index fc176fa..c233afc 100644 (file)
@@ -366,6 +366,8 @@ static status_t transmit_request(private_ike_sa_t *this)
                status = request->generate(request, this->crypter_out, this->signer_out, &packet);
                if (status != SUCCESS)
                {
+                       this->logger->log(this->logger, ERROR,
+                                                         "request generation failed. transaction discarded");
                        return FAILED;
                }
        }
@@ -848,9 +850,9 @@ static void set_state(private_ike_sa_t *this, ike_sa_state_t state)
                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_host->get_string(my_host),
                                                  my_id->get_string(my_id),
-                                                 other_host->get_address(other_host),
+                                                 other_host->get_string(other_host),
                                                  other_id->get_string(other_id));
                
                send_dpd(this);
@@ -1236,9 +1238,9 @@ static void log_status(private_ike_sa_t *this, logger_t *logger, char *name)
                                this->ike_sa_id->get_responder_spi(this->ike_sa_id));
        logger->log(logger, CONTROL, "  \"%s\": %s[%s]...%s[%s]",
                                name,
-                               my_host->get_address(my_host),
+                               my_host->get_string(my_host),
                                my_id ? my_id->get_string(my_id) : "(unknown)",
-                               other_host->get_address(other_host),
+                               other_host->get_string(other_host),
                                other_id ? other_id->get_string(other_id) : "(unknown)");
        
        iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
@@ -1391,9 +1393,9 @@ static void destroy(private_ike_sa_t *this)
                }
                
                this->logger->log(this->logger, AUDIT, "IKE_SA deleted between %s[%s]...%s[%s]", 
-                                                 my_host->get_address(my_host),
+                                                 my_host->get_string(my_host),
                                                  my_id ? my_id->get_string(my_id) : "(unknown)",
-                                                 other_host->get_address(other_host),
+                                                 other_host->get_string(other_host),
                                                  other_id ? other_id->get_string(other_id) : "(unknown)");
                this->connection->destroy(this->connection);
        }
index a16379c..53ba620 100644 (file)
@@ -391,7 +391,7 @@ static void import_certificate(private_ike_auth_t *this, cert_payload_t *cert_pa
        encoding = cert_payload->get_cert_encoding(cert_payload);
        if (encoding != CERT_X509_SIGNATURE)
        {
-               this->logger->log(this->logger, CONTROL, 
+               this->logger->log(this->logger, ERROR,
                                                  "certificate payload %s not supported, ignored",
                                                  enum_name(&cert_encoding_names, encoding));
                return;
@@ -401,7 +401,7 @@ static void import_certificate(private_ike_auth_t *this, cert_payload_t *cert_pa
        if (charon->credentials->verify(charon->credentials, cert, &found))
        {
                this->logger->log(this->logger, CONTROL|LEVEL1, 
-                                                 "end entity certificate is trusted");
+                                                 "received end entity certificate is trusted, added to store");
                if (found)
                {
                        cert->destroy(cert);
@@ -413,8 +413,8 @@ static void import_certificate(private_ike_auth_t *this, cert_payload_t *cert_pa
        }
        else
        {
-               this->logger->log(this->logger, ERROR
-                                                 "end entity certificate is not trusted");
+               this->logger->log(this->logger, CONTROL
+                                                 "received end entity certificate is not trusted, discarded");
        }
 }
 
index 987a5bc..d66ba84 100644 (file)
@@ -219,7 +219,7 @@ static chunk_t generate_natd_hash(private_ike_sa_init_t *this,
        this->nat_hasher->allocate_hash(this->nat_hasher, natd_string, &natd_hash);
        
        sprintf(buf, "natd_hash(%016llx %016llx %s:%d) == SHA1(", spi_i, spi_r,
-                       host->get_address(host), host->get_port(host));
+                       host->get_string(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);
@@ -520,7 +520,7 @@ static status_t get_response(private_ike_sa_init_t *this,
                
                this->logger->log(this->logger, AUDIT,
                                                  "no connection for hosts %s...%s found, deleting IKE_SA",
-                                                 me->get_address(me), other->get_address(other));
+                                                 me->get_string(me), other->get_string(other));
                return DESTROY_ME;
        }
        this->ike_sa->set_connection(this->ike_sa, this->connection);
index c4966f4..4bb9a6c 100644 (file)
@@ -29,6 +29,7 @@
 #include <sys/socket.h>
 #include <linux/netlink.h>
 #include <linux/rtnetlink.h>
+#include <linux/xfrm.h>
 #include <linux/udp.h>
 #include <pthread.h>
 #include <unistd.h>
@@ -389,8 +390,8 @@ static void receive_messages(private_kernel_interface_t *this)
                * list these responses for the sender
                */
                else if (hdr->nlmsg_type == NLMSG_ERROR ||
-                                          hdr->nlmsg_type == XFRM_MSG_NEWSA ||
-                                          hdr->nlmsg_type == XFRM_MSG_NEWPOLICY)
+                                hdr->nlmsg_type == XFRM_MSG_NEWSA ||
+                                hdr->nlmsg_type == XFRM_MSG_NEWPOLICY)
                {
                        /* add response to queue */
                        listed_response = malloc(hdr->nlmsg_len);
@@ -409,10 +410,19 @@ static void receive_messages(private_kernel_interface_t *this)
 }
 
 /**
+ * convert a host_t to a struct xfrm_address
+ */
+static void host2xfrm(host_t *host, xfrm_address_t *xfrm)
+{
+       chunk_t chunk = host->get_address(host);
+       memcpy(xfrm, chunk.ptr, max(chunk.len, sizeof(xfrm_address_t)));        
+}
+
+/**
  * Implementation of kernel_interface_t.get_spi.
  */
 static status_t get_spi(private_kernel_interface_t *this, 
-                                               host_t *src, host_t *dest, 
+                                               host_t *src, host_t *dst, 
                                                protocol_id_t protocol, u_int32_t reqid,
                                                u_int32_t *spi)
 {
@@ -432,8 +442,8 @@ static status_t get_spi(private_kernel_interface_t *this,
        hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_userspi_info));
 
        userspi = (struct xfrm_userspi_info*)NLMSG_DATA(hdr);
-       userspi->info.saddr = src->get_xfrm_addr(src);
-       userspi->info.id.daddr = dest->get_xfrm_addr(dest);
+       host2xfrm(src, &userspi->info.saddr);
+       host2xfrm(dst, &userspi->info.id.daddr);
        userspi->info.id.proto = (protocol == PROTO_ESP) ? KERNEL_ESP : KERNEL_AH;
        userspi->info.mode = TRUE; /* tunnel mode */
        userspi->info.reqid = reqid;
@@ -476,9 +486,8 @@ static status_t get_spi(private_kernel_interface_t *this,
  * Implementation of kernel_interface_t.add_sa.
  */
 static status_t add_sa(private_kernel_interface_t *this,
-                                          host_t *me, host_t *other,
-                                          u_int32_t spi, protocol_id_t protocol,
-                                          u_int32_t reqid,
+                                          host_t *src, host_t *dst, u_int32_t spi,
+                                          protocol_id_t protocol, u_int32_t reqid,
                                           u_int64_t expire_soft, u_int64_t expire_hard,
                                           algorithm_t *enc_alg, algorithm_t *int_alg,
                                           prf_plus_t *prf_plus, natt_conf_t *natt,
@@ -502,12 +511,11 @@ static status_t add_sa(private_kernel_interface_t *this,
        hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_info));
        
        sa = (struct xfrm_usersa_info*)NLMSG_DATA(hdr);
-       sa->saddr = me->get_xfrm_addr(me);
-       sa->id.daddr = other->get_xfrm_addr(other);
-       
+       host2xfrm(src, &sa->saddr);
+       host2xfrm(dst, &sa->id.daddr);
        sa->id.spi = spi;
        sa->id.proto = (protocol == PROTO_ESP) ? KERNEL_ESP : KERNEL_AH;
-       sa->family = me->get_family(me);
+       sa->family = src->get_family(src);
        sa->mode = TRUE; /* tunnel mode */
        sa->replay_window = 32;
        sa->reqid = reqid;
@@ -595,8 +603,8 @@ static status_t add_sa(private_kernel_interface_t *this,
 
                struct xfrm_encap_tmpl* encap = (struct xfrm_encap_tmpl*)RTA_DATA(rthdr);
                encap->encap_type = UDP_ENCAP_ESPINUDP;
-               encap->encap_sport = ntohs(natt->sport);
-               encap->encap_dport = ntohs(natt->dport);
+               encap->encap_sport = htons(natt->sport);
+               encap->encap_dport = htons(natt->dport);
                memset(&encap->encap_oa, 0, sizeof (xfrm_address_t));
                /* encap_oa could probably be derived from the 
                 * traffic selectors [rfc4306, p39]. In the netlink kernel implementation 
@@ -633,13 +641,13 @@ static status_t add_sa(private_kernel_interface_t *this,
 }
 
 /**
- * Implementation of kernel_interface_t.update_sa_hosts.
+ * Implementation of kernel_interface_t.update_sa.
  */
-static status_t update_sa_hosts(
+static status_t update_sa(
                private_kernel_interface_t *this,
                host_t *src, host_t *dst,
                host_t *new_src, host_t *new_dst, 
-               int src_changes, int dst_changes,
+               host_diff_t src_changes, host_diff_t dst_changes,
                u_int32_t spi, protocol_id_t protocol)
 {
        unsigned char request[BUFFER_SIZE];
@@ -658,11 +666,11 @@ static status_t update_sa_hosts(
        hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_id));
 
        sa_id = (struct xfrm_usersa_id*)NLMSG_DATA(hdr);
-       sa_id->daddr = dst->get_xfrm_addr(dst);
+       host2xfrm(dst, &sa_id->daddr);
        sa_id->spi = spi;
        sa_id->proto = (protocol == PROTO_ESP) ? KERNEL_ESP : KERNEL_AH;
        sa_id->family = dst->get_family(dst);
-
+       POS;
        if (send_message(this, hdr, &update) != SUCCESS)
        {
                this->logger->log(this->logger, ERROR, "netlink communication failed");
@@ -687,6 +695,7 @@ static status_t update_sa_hosts(
                free(update);
                return FAILED;
        }
+       POS;
        
        this->logger->log(this->logger, CONTROL|LEVEL2, "updating SA");
        update->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;        
@@ -695,7 +704,7 @@ static status_t update_sa_hosts(
        struct xfrm_usersa_info *sa = (struct xfrm_usersa_info*)NLMSG_DATA(update);
        if (src_changes & HOST_DIFF_ADDR)
        {
-               sa->saddr = new_src->get_xfrm_addr(new_src);
+               host2xfrm(new_src, &sa->saddr);
        }
 
        if (dst_changes & HOST_DIFF_ADDR)
@@ -703,7 +712,7 @@ static status_t update_sa_hosts(
                this->logger->log(this->logger, CONTROL|LEVEL2, "destination address changed! replacing SA");   
                
                update->nlmsg_type = XFRM_MSG_NEWSA;
-               sa->id.daddr = new_dst->get_xfrm_addr(new_dst);         
+               host2xfrm(new_dst, &sa->id.daddr);
        }
        
        if (src_changes & HOST_DIFF_PORT || dst_changes & HOST_DIFF_PORT)
@@ -722,7 +731,7 @@ static status_t update_sa_hosts(
                        rthdr = RTA_NEXT(rthdr, rtsize);
                }
        }
-       
+       POS;
        if (send_message(this, update, &response) != SUCCESS)
        {
                this->logger->log(this->logger, ERROR, "netlink communication failed");
@@ -745,6 +754,7 @@ static status_t update_sa_hosts(
                this->logger->log(this->logger, CONTROL|LEVEL2, "deleting old SA");
                status = this->public.del_sa(&this->public, dst, spi, protocol);
        }
+       POS;
 
        free(update);
        free(response);
@@ -755,7 +765,7 @@ static status_t update_sa_hosts(
  * Implementation of kernel_interface_t.query_sa.
  */
 static status_t query_sa(private_kernel_interface_t *this, host_t *dst,
-                                                u_int32_t spi, protocol_id_t protocol, time_t *use_time)
+                                                u_int32_t spi, protocol_id_t protocol, u_int32_t *use_time)
 {
        unsigned char request[BUFFER_SIZE];
        struct nlmsghdr *response;
@@ -772,7 +782,7 @@ static status_t query_sa(private_kernel_interface_t *this, host_t *dst,
        hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_info));
 
        sa_id = (struct xfrm_usersa_id*)NLMSG_DATA(hdr);
-       sa_id->daddr = dst->get_xfrm_addr(dst);
+       host2xfrm(dst, &sa_id->daddr);
        sa_id->spi = spi;
        sa_id->proto = (protocol == PROTO_ESP) ? KERNEL_ESP : KERNEL_AH;
        sa_id->family = dst->get_family(dst);
@@ -796,7 +806,7 @@ static status_t query_sa(private_kernel_interface_t *this, host_t *dst,
        }
        
        sa_info = (struct xfrm_usersa_info*)NLMSG_DATA(response);
-       *use_time = (time_t)sa_info->curlft.use_time;
+       *use_time = sa_info->curlft.use_time;
        
        free(response);
        return SUCCESS;
@@ -824,7 +834,7 @@ static status_t del_sa(private_kernel_interface_t *this, host_t *dst,
        hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_id));
        
        sa_id = (struct xfrm_usersa_id*)NLMSG_DATA(hdr);
-       sa_id->daddr = dst->get_xfrm_addr(dst);
+       host2xfrm(dst, &sa_id->daddr);
        sa_id->spi = spi;
        sa_id->proto = (protocol == PROTO_ESP) ? KERNEL_ESP : KERNEL_AH;
        sa_id->family = dst->get_family(dst);
@@ -851,15 +861,110 @@ static status_t del_sa(private_kernel_interface_t *this, host_t *dst,
 }
 
 /**
+ * convert a traffic selector address range to subnet and its mask.
+ */
+static void ts2subnet(traffic_selector_t* ts, 
+                                         xfrm_address_t *net, u_int8_t *mask)
+{
+       /* there is no way to do this cleanly, as the address range may
+        * be anything else but a subnet. We use from_addr as subnet 
+        * and try to calculate a usable subnet mask.
+        */
+       chunk_t chunk;
+       
+       chunk = ts->get_from_address(ts);
+       memcpy(net, chunk.ptr, chunk.len);
+       
+       switch (ts->get_type(ts))
+       {
+               case TS_IPV4_ADDR_RANGE:
+               {
+                       u_int32_t from, to, bit;
+                       
+                       from = *(u_int32_t*)chunk.ptr;
+                       chunk_free(&chunk);
+                       chunk = ts->get_to_address(ts);
+                       to = *(u_int32_t*)chunk.ptr;
+                       chunk_free(&chunk);
+                       for (bit = 0; bit < 32; bit++)
+                       {
+                               if ((1<<bit & from) != (1<<bit & to))
+                               {
+                                       *mask = bit;
+                                       return;
+                               }
+                       }
+                       *mask = 32;
+                       return;
+               }
+               case TS_IPV6_ADDR_RANGE:
+               default:
+               {
+                       /* TODO: IPV6 support */
+                       *mask = 0;
+                       return;
+               }
+       }
+}
+
+/**
+ * convert a traffic selector port range to port/portmask
+ */
+static void ts2ports(traffic_selector_t* ts, 
+                                        u_int16_t *port, u_int16_t *mask)
+{
+       /* linux does not seem to accept complex portmasks. Only
+        * any or a specific port is allowed. We set to any, if we have
+        * a port range, or to a specific, if we have one port only.
+        */
+       u_int16_t from, to;
+       
+       from = ts->get_from_port(ts);
+       to = ts->get_to_port(ts);
+       
+       if (from == to)
+       {
+               *port = htons(from);
+               *mask = ~0;
+       }
+       else
+       {
+               *port = 0;
+               *mask = 0;
+       }
+}
+
+/**
+ * convert a pair of traffic_selectors to a xfrm_selector
+ */
+static struct xfrm_selector ts2selector(traffic_selector_t *src, 
+                                                                               traffic_selector_t *dst)
+{
+       struct xfrm_selector sel;
+
+       memset(&sel, 0, sizeof(sel));
+       sel.family = src->get_type(src) == TS_IPV4_ADDR_RANGE ? AF_INET : AF_INET6;
+       /* src or dest proto may be "any" (0), use more restrictive one */
+       sel.proto = max(src->get_protocol(src), dst->get_protocol(dst));
+       ts2subnet(dst, &sel.daddr, &sel.prefixlen_d);
+       ts2subnet(src, &sel.saddr, &sel.prefixlen_s);
+       ts2ports(dst, &sel.dport, &sel.dport_mask);
+       ts2ports(src, &sel.sport, &sel.sport_mask);
+       sel.ifindex = 0;
+       sel.user = 0;
+       
+       return sel;
+}
+
+/**
  * Implementation of kernel_interface_t.add_policy.
  */
 static status_t add_policy(private_kernel_interface_t *this, 
-                                                 host_t *me, host_t *other, 
-                                                 host_t *src, host_t *dst,
-                                                 u_int8_t src_hostbits, u_int8_t dst_hostbits,
-                                                 u_int8_t direction, u_int8_t upper_proto,
-                                                 protocol_id_t protocol,
-                                                 u_int32_t reqid, bool update)
+                                                  host_t *src, host_t *dst,
+                                                  traffic_selector_t *src_ts,
+                                                  traffic_selector_t *dst_ts,
+                                                  policy_dir_t direction, protocol_id_t protocol,
+                                                  u_int32_t reqid, bool update)
 {
        iterator_t *iterator;
        kernel_policy_t *current, *policy;
@@ -873,16 +978,7 @@ static status_t add_policy(private_kernel_interface_t *this,
        /* create a policy */
        policy = malloc_thing(kernel_policy_t);
        memset(policy, 0, sizeof(kernel_policy_t));
-       policy->sel.saddr = src->get_xfrm_addr(src);
-       policy->sel.prefixlen_s = src_hostbits;
-       policy->sel.sport = htons(src->get_port(src));
-       policy->sel.sport_mask = (policy->sel.sport) ? ~0 : 0;
-       policy->sel.daddr = dst->get_xfrm_addr(dst);
-       policy->sel.prefixlen_d = dst_hostbits;
-       policy->sel.dport = htons(dst->get_port(dst));
-       policy->sel.dport_mask = (policy->sel.dport) ? ~0 : 0;
-       policy->sel.proto = upper_proto;
-       policy->sel.family = src->get_family(src);
+       policy->sel = ts2selector(src_ts, dst_ts);
        policy->direction = direction;
        
        /* find the policy, which matches EXACTLY */
@@ -893,12 +989,17 @@ static status_t add_policy(private_kernel_interface_t *this,
                if (memcmp(current, policy, sizeof(struct xfrm_selector)) == 0 &&
                        policy->direction == current->direction)
                {
+                       free(policy);
                        /* use existing policy */
                        if (!update)
                        {
                                current->refcount++;
+                               iterator->destroy(iterator);
+                               pthread_mutex_unlock(&this->pol_mutex);
+                               this->logger->log(this->logger, CONTROL|LEVEL1, 
+                                                                 "policy already exists, increasing refcount");
+                               return SUCCESS;
                        }
-                       free(policy);
                        policy = current;
                        found = TRUE;
                        break;
@@ -921,7 +1022,7 @@ static status_t add_policy(private_kernel_interface_t *this,
 
        policy_info = (struct xfrm_userpolicy_info*)NLMSG_DATA(hdr);
        policy_info->sel = policy->sel;
-       policy_info->dir = direction;
+       policy_info->dir = policy->direction;
        policy_info->priority = SPD_PRIORITY;
        policy_info->action = XFRM_POLICY_ALLOW;
        policy_info->share = XFRM_SHARE_ANY;
@@ -955,8 +1056,8 @@ static status_t add_policy(private_kernel_interface_t *this,
        tmpl->aalgos = tmpl->ealgos = tmpl->calgos = ~0;
        tmpl->mode = TRUE;
        
-       tmpl->saddr = me->get_xfrm_addr(me);
-       tmpl->id.daddr = other->get_xfrm_addr(other);
+       host2xfrm(src, &tmpl->saddr);
+       host2xfrm(dst, &tmpl->id.daddr);
        
        if (send_message(this, hdr, &response) != SUCCESS)
        {
@@ -982,12 +1083,73 @@ static status_t add_policy(private_kernel_interface_t *this,
 }
 
 /**
+ * Implementation of kernel_interface_t.query_policy.
+ */
+static status_t query_policy(private_kernel_interface_t *this,
+                                                        traffic_selector_t *src_ts, 
+                                                        traffic_selector_t *dst_ts,
+                                                        policy_dir_t direction, u_int32_t *use_time)
+{
+       unsigned char request[BUFFER_SIZE];
+       struct nlmsghdr *response;
+       struct nlmsghdr *hdr;
+       struct xfrm_userpolicy_id *policy_id;
+       struct xfrm_userpolicy_info *policy;
+       
+       memset(&request, 0, sizeof(request));
+       status_t status = SUCCESS;
+       
+       this->logger->log(this->logger, CONTROL|LEVEL2, "querying policy");
+
+       hdr = (struct nlmsghdr*)request;
+       hdr->nlmsg_flags = NLM_F_REQUEST;
+       hdr->nlmsg_type = XFRM_MSG_GETPOLICY;
+       hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_userpolicy_id));
+
+       policy_id = (struct xfrm_userpolicy_id*)NLMSG_DATA(hdr);
+       policy_id->sel = ts2selector(src_ts, dst_ts);
+       policy_id->dir = direction;
+
+       if (send_message(this, hdr, &response) != SUCCESS)
+       {
+               this->logger->log(this->logger, ERROR, "netlink communication failed");
+               return FAILED;
+       }
+       else if (response->nlmsg_type == NLMSG_ERROR)
+       {
+               this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_GETPOLICY got an error: %s",
+                                                 strerror(-((struct nlmsgerr*)NLMSG_DATA(response))->error));
+               free(response);
+               return FAILED;
+       }
+       else if (response->nlmsg_type != XFRM_MSG_NEWPOLICY)
+       {
+               this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_GETPOLICY got an unknown reply");
+               free(response);
+               return FAILED;
+       }
+       else if (response->nlmsg_len < NLMSG_LENGTH(sizeof(struct xfrm_userpolicy_info)))
+       {
+               this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_GETPOLICY got an invalid reply");
+               free(response);
+               return FAILED;
+       }
+
+       policy = (struct xfrm_userpolicy_info*)NLMSG_DATA(response);
+
+       *use_time = (time_t)policy->curlft.use_time;
+       
+       free(response);
+       return status;
+}
+
+/**
  * Implementation of kernel_interface_t.del_policy.
  */
 static status_t del_policy(private_kernel_interface_t *this,
-                                                  host_t *src, host_t *dst
-                                                  u_int8_t src_hostbits, u_int8_t dst_hostbits,
-                                                  u_int8_t direction, u_int8_t upper_proto)
+                                                  traffic_selector_t *src_ts
+                                                  traffic_selector_t *dst_ts,
+                                                  policy_dir_t direction)
 {
        kernel_policy_t *current, policy, *to_delete = NULL;
        unsigned char request[BUFFER_SIZE];
@@ -1001,16 +1163,7 @@ static status_t del_policy(private_kernel_interface_t *this,
        
        /* create a policy */
        memset(&policy, 0, sizeof(kernel_policy_t));
-       policy.sel.saddr = src->get_xfrm_addr(src);
-       policy.sel.prefixlen_s = src_hostbits;
-       policy.sel.sport = htons(src->get_port(src));
-       policy.sel.sport_mask = (policy.sel.sport) ? ~0 : 0;
-       policy.sel.daddr = dst->get_xfrm_addr(dst);
-       policy.sel.prefixlen_d = dst_hostbits;
-       policy.sel.dport = htons(dst->get_port(dst));
-       policy.sel.dport_mask = (policy.sel.dport) ? ~0 : 0;
-       policy.sel.proto = upper_proto;
-       policy.sel.family = src->get_family(src);
+       policy.sel = ts2selector(src_ts, dst_ts);
        policy.direction = direction;
        
        /* find the policy */
@@ -1025,7 +1178,7 @@ static status_t del_policy(private_kernel_interface_t *this,
                        if (--to_delete->refcount > 0)
                        {
                                /* is used by more SAs, keep in kernel */
-                               this->logger->log(this->logger, CONTROL|LEVEL2
+                               this->logger->log(this->logger, CONTROL|LEVEL1
                                                                  "is used by other SAs, not removed");
                                iterator->destroy(iterator);
                                pthread_mutex_unlock(&this->pol_mutex);
@@ -1103,11 +1256,12 @@ kernel_interface_t *kernel_interface_create()
        /* public functions */
        this->public.get_spi = (status_t(*)(kernel_interface_t*,host_t*,host_t*,protocol_id_t,u_int32_t,u_int32_t*))get_spi;
        this->public.add_sa  = (status_t(*)(kernel_interface_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,u_int64_t,u_int64_t,algorithm_t*,algorithm_t*,prf_plus_t*,natt_conf_t*,bool))add_sa;
-       this->public.update_sa_hosts = (status_t(*)(kernel_interface_t*,host_t*,host_t*,host_t*,host_t*,int,int,u_int32_t,protocol_id_t))update_sa_hosts;
-       this->public.query_sa = (status_t(*)(kernel_interface_t*,host_t*,u_int32_t,protocol_id_t,time_t*))query_sa;
+       this->public.update_sa = (status_t(*)(kernel_interface_t*,host_t*,u_int32_t,protocol_id_t,host_t*,host_t*,host_diff_t,host_diff_t))update_sa;
+       this->public.query_sa = (status_t(*)(kernel_interface_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t*))query_sa;
        this->public.del_sa = (status_t(*)(kernel_interface_t*,host_t*,u_int32_t,protocol_id_t))del_sa;
-       this->public.add_policy = (status_t(*)(kernel_interface_t*,host_t*,host_t*,host_t*,host_t*,u_int8_t,u_int8_t,u_int8_t,u_int8_t,protocol_id_t,u_int32_t,bool))add_policy;
-       this->public.del_policy = (status_t(*)(kernel_interface_t*,host_t*,host_t*,u_int8_t,u_int8_t,u_int8_t,u_int8_t))del_policy;
+       this->public.add_policy = (status_t(*)(kernel_interface_t*,host_t*,host_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,protocol_id_t,u_int32_t,bool))add_policy;
+       this->public.query_policy = (status_t(*)(kernel_interface_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,u_int32_t*))query_policy;
+       this->public.del_policy = (status_t(*)(kernel_interface_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t))del_policy;
        this->public.destroy = (void(*)(kernel_interface_t*)) destroy;
 
        /* private members */
index 5d385ca..bafb1a6 100644 (file)
@@ -25,8 +25,6 @@
 #ifndef KERNEL_INTERFACE_H_
 #define KERNEL_INTERFACE_H_
 
-#include <linux/xfrm.h>
-
 #include <utils/host.h>
 #include <crypto/prf_plus.h>
 #include <encoding/payloads/proposal_substructure.h>
 typedef struct natt_conf_t natt_conf_t;
 
 /**
- * @brief Configuration for NAT-T
+ * Configuration for NAT-T
  */
 struct natt_conf_t {
-       u_int16_t sport, dport;
+       /** source port to use for UDP-encapsulated packets */
+       u_int16_t sport;
+       /** dest port to use for UDP-encapsulated packets */
+       u_int16_t dport;
+};
+
+typedef enum policy_dir_t policy_dir_t;
+
+/**
+ * Direction of a policy. These are equal to those
+ * defined in xfrm.h, but we want to stay implementation
+ * neutral here.
+ */
+enum policy_dir_t {
+       /** Policy for inbound traffic */
+       POLICY_IN = 0,
+       /** Policy for outbound traffic */
+       POLICY_OUT = 1,
+       /** Policy for forwarded traffic */
+       POLICY_FWD = 2,
 };
 
 typedef struct kernel_interface_t kernel_interface_t;
@@ -52,10 +69,10 @@ typedef struct kernel_interface_t kernel_interface_t;
  * reference counting. The Linux kernel does not allow the same policy
  * installed twice, but we need this as CHILD_SA exist multiple times
  * when rekeying. Thats why we do reference counting of policies.
- * 
+ *
  * @b Constructors:
  *  - kernel_interface_create()
- * 
+ *
  * @ingroup threads
  */
 struct kernel_interface_t {
@@ -101,8 +118,8 @@ struct kernel_interface_t {
         * @param expire_hard   lieftime in seconds before delete
         * @param enc_alg               Algorithm to use for encryption (ESP only)
         * @param int_alg               Algorithm to use for integrity protection
-        * @param prf_plus              PRF to derive keys
-        * @param natt                  NAT-T Configuration
+        * @param prf_plus              PRF to derive keys from
+        * @param natt                  NAT-T Configuration, or NULL of no NAT-T used
         * @param replace               Should an already installed SA be updated?
         * @return
         *                                              - SUCCESS
@@ -113,35 +130,38 @@ struct kernel_interface_t {
                                                protocol_id_t protocol, u_int32_t reqid,
                                                u_int64_t expire_soft, u_int64_t expire_hard,
                                                algorithm_t *enc_alg, algorithm_t *int_alg,
-                                               prf_plus_t *prf_plus, natt_conf_t *natt, bool replace);
+                                               prf_plus_t *prf_plus, natt_conf_t *natt, bool update);
        
        /**
-        * @brief Update the hosts on an installed SA. Encapsulation ports are also updated.
+        * @brief Update the hosts on an installed SA.
         *
-        * @note We cannot directly update the destination address as the kernel requires the spi,
-        * the protocol AND the destination address (and family) to identify SAs. Therefore if the 
-        * destination address changed we create a new SA and delete the old one.
+        * We cannot directly update the destination address as the kernel
+        * requires the spi, the protocol AND the destination address (and family)
+        * to identify SAs. Therefore if the destination address changed we
+        * create a new SA and delete the old one.
         *
         * @param this                  calling object
-        * @param src                   source address for this SA
         * @param dst                   destination address for this SA
+        * @param spi                   SPI of the SA
+        * @param protocol              protocol for this SA (ESP/AH)
         * @param new_src               new source address for this SA
         * @param new_dst               new destination address for this SA
         * @param src_changes   changes in src
         * @param dst_changes   changes in dst
-        * @param spi                   SPI allocated by us or remote peer
-        * @param protocol              protocol for this SA (ESP/AH)
         * @return
         *                                              - SUCCESS
         *                                              - FAILED if kernel comm failed
         */
-       status_t (*update_sa_hosts)(kernel_interface_t *this,
-                               host_t *src, host_t *dst,
-                               host_t *new_src, host_t *new_dst,
-                               int src_changes, int dst_changes,
-                               u_int32_t spi, protocol_id_t protocol);
+       status_t (*update_sa)(kernel_interface_t *this, host_t *dst, u_int32_t spi,
+                                                 protocol_id_t protocol,
+                                                 host_t *new_src, host_t *new_dst,
+                                                 host_diff_t src_changes, host_diff_t dst_changes);
+       
        /**
         * @brief Query the use time of an SA.
+        *
+        * The use time of an SA is not the time of the last usage, but 
+        * the time of the first usage of the SA.
         * 
         * @param this                  calling object
         * @param dst                   destination address for this SA
@@ -153,7 +173,7 @@ struct kernel_interface_t {
         *                                              - FAILED if kernel comm failed
         */
        status_t (*query_sa) (kernel_interface_t *this, host_t *dst, u_int32_t spi, 
-                                                 protocol_id_t protocol, time_t *use_time);
+                                                 protocol_id_t protocol, u_int32_t *use_time);
        
        /**
         * @brief Delete a previusly installed SA from the SAD.
@@ -172,20 +192,19 @@ struct kernel_interface_t {
        /**
         * @brief Add a policy to the SPD.
         * 
-        * A policy is always associated to an SA, so
-        * traffic applied to a policy. Traffic which
-        * matches a policy is handled by the SA with the same
-        * reqid.
+        * A policy is always associated to an SA. Traffic which matches a
+        * policy is handled by the SA with the same reqid.
+        * If the update flag is set, the policy is updated with the new
+        * src/dst addresses.
+        * If the update flag is not set, but a such policy is already in the
+        * kernel, the reference count to this policy is increased.
         * 
         * @param this                  calling object
-        * @param me                    address of local peer
-        * @param other                 address of remote peer
-        * @param src                   src address of traffic this policy applies
-        * @param dst                   dest address of traffic this policy applies
-        * @param src_hostbits  subnetmask to use for src address
-        * @param dst_hostbits  subnetmask to use for dst address
-        * @param direction             direction of traffic, XFRM_POLICY_OUT, XFRM_POLICY_IN, XFRM_POLICY_FWD
-        * @param upper_proto   upper layer protocol of traffic for this policy (TCP, UDP, ICMP, ...)
+        * @param src                   source address of SA
+        * @param dst                   dest address of SA
+        * @param src_ts                traffic selector to match traffic source
+        * @param dst_ts                traffic selector to match traffic dest
+        * @param direction             direction of traffic, POLICY_IN, POLICY_OUT, POLICY_FWD
         * @param protocol              protocol to use to protect traffic (AH/ESP)
         * @param reqid                 uniqe ID of an SA to use to enforce policy
         * @param update                update an existing policy, if TRUE
@@ -193,32 +212,53 @@ struct kernel_interface_t {
         *                                              - SUCCESS
         *                                              - FAILED if kernel comm failed
         */
-       status_t (*add_policy) (kernel_interface_t *this, 
-                                                       host_t *me, host_t *other, 
+       status_t (*add_policy) (kernel_interface_t *this,
                                                        host_t *src, host_t *dst,
-                                                       u_int8_t src_hostbits, u_int8_t dst_hostbits,
-                                                       u_int8_t direction, u_int8_t upper_proto, 
-                                                       protocol_id_t protocol,
+                                                       traffic_selector_t *src_ts,
+                                                       traffic_selector_t *dst_ts,
+                                                       policy_dir_t direction, protocol_id_t protocol,
                                                        u_int32_t reqid, bool update);
        
        /**
+        * @brief Query the use time of a policy.
+        *
+        * The use time of a policy is the time the policy was used
+        * for the last time.
+        * 
+        * @param this                  calling object
+        * @param src_ts                traffic selector to match traffic source
+        * @param dst_ts                traffic selector to match traffic dest
+        * @param direction             direction of traffic, POLICY_IN, POLICY_OUT, POLICY_FWD
+        * @param[out] use_time the time of this SA's last use
+        * @return
+        *                                              - SUCCESS
+        *                                              - FAILED if kernel comm failed
+        */
+       status_t (*query_policy) (kernel_interface_t *this,
+                                                         traffic_selector_t *src_ts, 
+                                                         traffic_selector_t *dst_ts,
+                                                         policy_dir_t direction, u_int32_t *use_time);
+       
+       /**
         * @brief Remove a policy from the SPD.
         *
+        * The kernel interface implements reference counting for policies.
+        * If the same policy is installed multiple times (in the case of rekeying),
+        * the reference counter is increased. del_policy() decreases the ref counter
+        * and removes the policy only when no more references are available.
+        *
         * @param this                  calling object
-        * @param src                   src address of traffic this policy applies
-        * @param dst                   dest address of traffic this policy applies
-        * @param src_hostbits  subnetmask to use for src address
-        * @param dst_hostbits  subnetmask to use for dst address
-        * @param direction             direction of traffic, XFRM_POLICY_OUT, XFRM_POLICY_IN, XFRM_POLICY_FWD
-        * @param upper_proto   upper layer protocol of traffic for this policy (TCP, UDP, ICMP, ...)
+        * @param src_ts                traffic selector to match traffic source
+        * @param dst_ts                traffic selector to match traffic dest
+        * @param direction             direction of traffic, POLICY_IN, POLICY_OUT, POLICY_FWD
         * @return
         *                                              - SUCCESS
         *                                              - FAILED if kernel comm failed
         */
        status_t (*del_policy) (kernel_interface_t *this,
-                                                       host_t *src, host_t *dst,
-                                                       u_int8_t src_hostbits, u_int8_t dst_hostbits,
-                                                       u_int8_t direction, u_int8_t upper_proto);
+                                                       traffic_selector_t *src_ts, 
+                                                       traffic_selector_t *dst_ts,
+                                                       policy_dir_t direction);
        
        /**
         * @brief Destroys a kernel_interface object.
index ae03766..f4d7acc 100755 (executable)
@@ -428,9 +428,9 @@ static void stroke_add_conn(private_stroke_t *this, stroke_msg_t *msg)
        charon->connections->add_connection(charon->connections, connection);
        this->logger->log(this->logger, CONTROL, "added connection \"%s\": %s[%s]...%s[%s]",
                                          msg->add_conn.name,
-                                         my_host->get_address(my_host),
+                                         my_host->get_string(my_host),
                                          my_id->get_string(my_id),
-                                         other_host->get_address(other_host),
+                                         other_host->get_string(other_host),
                                          other_id->get_string(other_id));
        /* add to global policy list */
        charon->policies->add_policy(charon->policies, policy);
index 1f928f5..763358e 100644 (file)
@@ -100,9 +100,9 @@ static bool is_anyaddr(private_host_t *this)
 }
 
 /**
- * implements host_t.get_address
+ * implements host_t.get_string
  */
-static char *get_address(private_host_t *this)
+static char *get_string(private_host_t *this)
 {
        switch (this->family) 
        {
@@ -128,9 +128,9 @@ static char *get_address(private_host_t *this)
 }
 
 /**
- * Implementation of host_t.get_address_as_chunk.
+ * Implementation of host_t.get_address.
  */
-static chunk_t get_address_as_chunk(private_host_t *this)
+static chunk_t get_address(private_host_t *this)
 {
        chunk_t address = CHUNK_INITIALIZER;
        
@@ -139,9 +139,8 @@ static chunk_t get_address_as_chunk(private_host_t *this)
                case AF_INET: 
                {
                        /* allocate 4 bytes for IPv4 address*/
-                       address.ptr = malloc(4);
+                       address.ptr = (char*)&(this->address4.sin_addr.s_addr);
                        address.len = 4;
-                       memcpy(address.ptr,&(this->address4.sin_addr.s_addr),4);
                }
                default:
                {
@@ -151,22 +150,9 @@ static chunk_t get_address_as_chunk(private_host_t *this)
        }
 }
 
-static xfrm_address_t get_xfrm_addr(private_host_t *this)
-{
-       switch (this->family) 
-       {
-               case AF_INET: 
-               {
-                       return (xfrm_address_t)(this->address4.sin_addr.s_addr);
-               }
-               default:
-               {
-                       /* todo */
-                       return (xfrm_address_t)(this->address4.sin_addr.s_addr);
-               }
-       }
-}
-
+/**
+ * implements host_t.get_family
+ */
 static int get_family(private_host_t *this)
 {
        return this->family;    
@@ -203,12 +189,11 @@ static void set_port(private_host_t *this, u_int16_t port)
                }
                default:
                {
-                       /**/
+                       /*TODO*/
                }
        }
 }
 
-
 /**
  * Implements host_t.clone.
  */
@@ -249,9 +234,9 @@ static bool ip_equals(private_host_t *this, private_host_t *other)
 /**
  * Implements host_t.get_differences
  */
-static int get_differences(private_host_t *this, private_host_t *other)
+static host_diff_t get_differences(private_host_t *this, private_host_t *other)
 {
-       int ret = HOST_DIFF_NONE;
+       host_diff_t ret = HOST_DIFF_NONE;
        
        if (!this->public.ip_equals(&this->public, &other->public))
        {
@@ -307,12 +292,11 @@ static private_host_t *host_create_empty(void)
        this->public.get_sockaddr_len = (socklen_t*(*) (host_t*))get_sockaddr_len;
        this->public.clone = (host_t* (*) (host_t*))clone;
        this->public.get_family = (int (*) (host_t*))get_family;
-       this->public.get_xfrm_addr = (xfrm_address_t (*) (host_t *))get_xfrm_addr;
-       this->public.get_address = (char* (*) (host_t *))get_address;
-       this->public.get_address_as_chunk = (chunk_t (*) (host_t *)) get_address_as_chunk;
+       this->public.get_string = (char* (*) (host_t *))get_string;
+       this->public.get_address = (chunk_t (*) (host_t *)) get_address;
        this->public.get_port = (u_int16_t (*) (host_t *))get_port;
        this->public.set_port = (void (*) (host_t *,u_int16_t))set_port;
-       this->public.get_differences = (int (*) (host_t *,host_t *)) get_differences;
+       this->public.get_differences = (host_diff_t (*) (host_t *,host_t *)) get_differences;
        this->public.ip_equals = (bool (*) (host_t *,host_t *)) ip_equals;
        this->public.equals = (bool (*) (host_t *,host_t *)) equals;
        this->public.is_anyaddr = (bool (*) (host_t *)) is_anyaddr;
index 6a72f52..54f3b55 100644 (file)
 
 #include <types.h>
 
+typedef enum host_diff_t host_diff_t;
 
-#define HOST_DIFF_NONE 0
-#define HOST_DIFF_ADDR 1
-#define HOST_DIFF_PORT 2
+/**
+ * Differences between two hosts. They differ in
+ * address, port, or both.
+ */
+enum host_diff_t {
+       HOST_DIFF_NONE = 0,
+       HOST_DIFF_ADDR = 1,
+       HOST_DIFF_PORT = 2,
+};
 
 typedef struct host_t host_t;
 
@@ -80,7 +87,7 @@ struct host_t {
        /** 
         * @brief Get the length of the sockaddr struct.
         * 
-        * Sepending on the family, the length of the sockaddr struct
+        * Depending on the family, the length of the sockaddr struct
         * is different. Use this function to get the length of the sockaddr
         * struct returned by get_sock_addr.
         * 
@@ -92,20 +99,6 @@ struct host_t {
        socklen_t *(*get_sockaddr_len) (host_t *this);
        
        /**
-        * @brief Gets the address as xfrm_address_t.
-        * 
-        * This function allows the conversion to an
-        * xfrm_address_t, used for netlink communication
-        * with the kernel.
-        * 
-        * @see kernel_interface_t.
-        * 
-        * @param this                  calling object
-        * @return                              address in xfrm_address_t format
-        */
-       xfrm_address_t (*get_xfrm_addr) (host_t *this);
-       
-       /**
         * @brief Gets the family of the address
         * 
         * @param this                  calling object
@@ -114,15 +107,15 @@ struct host_t {
        int (*get_family) (host_t *this);
        
        /** 
-        * @brief get the address of this host
+        * @brief Get the address of this host as a string
         * 
-        * Mostly used for debugging purposes. 
-        * @warning string must NOT be freed
+        * Mostly used for debugging purposes. String
+        * points to internal data.
         * 
         * @param this                  object
         * @return                              address string, 
         */
-       char* (*get_address) (host_t *this);
+       char* (*get_string) (host_t *this);
        
        /** 
         * @brief Checks if the ip address of host is set to default route.
@@ -137,12 +130,12 @@ struct host_t {
        /** 
         * @brief get the address of this host as chunk_t
         * 
-        * @warning returned chunk has to get destroyed by caller.
+        * Returned chunk points to internal data.
         * 
         * @param this                  object
         * @return                              address string, 
         */
-       chunk_t (*get_address_as_chunk) (host_t *this);
+       chunk_t (*get_address) (host_t *this);
                
        /** 
         * @brief get the port of this host
@@ -183,10 +176,9 @@ struct host_t {
         *
         * @param this                  object to compare
         * @param other                 the other to compare
-        * @return                              a combination of HOST_DIFF_NONE,
-        *                                              HOST_DIFF_ADDR and HOST_DIFF_PORT
+        * @return                              differences in a combination of host_diff_t's
         */
-       int (*get_differences) (host_t *this, host_t *other);
+       host_diff_t (*get_differences) (host_t *this, host_t *other);
        
        /** 
         * @brief Destroy this host object
index 3a5f48f..fbcd7d9 100644 (file)
@@ -174,6 +174,7 @@ whitelist_t whitelist[] = {
        {inet_ntoa, 0xFF},
        {strerror, 0xFF},
        {getprotobynumber, 0xFF},
+       {getservbyport, 0xFF},
 };
 
 /**