applied new changes from NATT team
authorMartin Willi <martin@strongswan.org>
Fri, 23 Jun 2006 14:02:30 +0000 (14:02 -0000)
committerMartin Willi <martin@strongswan.org>
Fri, 23 Jun 2006 14:02:30 +0000 (14:02 -0000)
DPD only done when no IPsec and IKE traffic processed
minor changes here and there

20 files changed:
src/charon/config/configuration.c
src/charon/config/configuration.h
src/charon/config/connections/connection.c
src/charon/daemon.h
src/charon/network/interfaces.c
src/charon/network/socket.c
src/charon/queues/jobs/send_dpd_job.c
src/charon/queues/jobs/send_keepalive_job.c
src/charon/sa/child_sa.c
src/charon/sa/child_sa.h
src/charon/sa/ike_sa.c
src/charon/sa/ike_sa.h
src/charon/sa/states/ike_sa_established.c
src/charon/sa/states/initiator_init.c
src/charon/sa/states/responder_init.c
src/charon/threads/kernel_interface.c
src/charon/threads/kernel_interface.h
src/libstrongswan/Makefile.am
src/pluto/Makefile.am
src/stroke/stroke_keywords.c [deleted file]

index 9e44a0e..cd20586 100755 (executable)
 #define KEEPALIVE_INTERVAL 2000000
 
 /**
- * Keepalive timeout in milliseconds.
- * Not implemented yet.
- */
-#define KEEPALIVE_TIMEOUT 30000000
-
-/**
  * DPD interval in milliseconds.
  */
 #define DPD_INTERVAL 6000000
@@ -113,14 +107,6 @@ static u_int32_t get_keepalive_interval (private_configuration_t *this)
 }
 
 /**
- * Implementation of configuration_t.get_keepalive_timeout.
- */
-static u_int32_t get_keepalive_timeout (private_configuration_t *this)
-{
-       return KEEPALIVE_TIMEOUT;
-}
-
-/**
  * Implementation of configuration_t.get_dpd_interval.
  */
 static u_int32_t get_dpd_interval (private_configuration_t *this)
@@ -148,7 +134,6 @@ configuration_t *configuration_create()
        this->public.get_retransmit_timeout = (status_t (*) (configuration_t *, u_int32_t retransmit_count, u_int32_t *timeout))get_retransmit_timeout;
        this->public.get_half_open_ike_sa_timeout = (u_int32_t (*) (configuration_t *)) get_half_open_ike_sa_timeout;
        this->public.get_keepalive_interval = (u_int32_t (*) (configuration_t *)) get_keepalive_interval;
-       this->public.get_keepalive_timeout = (u_int32_t (*) (configuration_t *)) get_keepalive_timeout;
        this->public.get_dpd_interval = (u_int32_t (*) (configuration_t *)) get_dpd_interval;
        
        return (&this->public);
index f069632..813b957 100755 (executable)
@@ -81,17 +81,6 @@ struct configuration_t {
        u_int32_t (*get_keepalive_interval) (configuration_t *this);
 
        /**
-        * @brief Returns the keepalive timeout in ms.
-        * 
-        * The keepalive timeout defines how long we should keep sending
-        * NAT keepalives after closing an IKE_SA.
-        * 
-        * @param this                          calling object
-        * @return                                      timeout in milliseconds (ms)
-        */     
-       u_int32_t (*get_keepalive_timeout) (configuration_t *this);
-
-       /**
         * @brief Returns the DPD interval in ms.
         * 
         * The DPD interval defines the time after which a
index 243c896..f3c4bdd 100644 (file)
@@ -22,7 +22,7 @@
 
 #include <string.h>
 
-#include "connection.h"
+#include <config/connections/connection.h>
 
 #include <utils/linked_list.h>
 #include <utils/logger.h>
index 2c7941f..0a5962f 100644 (file)
@@ -273,6 +273,7 @@ struct daemon_t {
         * A socket_t instance.
         */
        socket_t *socket;
+       
        /**
         * A interfaces_t instance.
         */
index a36ba4d..ce01418 100644 (file)
@@ -147,6 +147,7 @@ interfaces_t *interfaces_create(u_int16_t port)
        if (initialize(this) != SUCCESS)
        {
                destroy(this);
+               return NULL;
        }
 
        return &this->public;
index eb61c83..0d5470c 100644 (file)
@@ -395,9 +395,9 @@ static status_t initialize(private_socket_t *this)
                int type = UDP_ENCAP_ESPINUDP;
                if (setsockopt(this->natt_fd, SOL_UDP, UDP_ENCAP, &type, sizeof(type)) < 0)
                {
-                       this->logger->log(this->logger, ERROR, 
+                       this->logger->log(this->logger, ERROR,
                                                          "unable to set UDP_ENCAP on natt send socket! NAT-T may fail! error: %s",
-                                                         strerror(errno)); 
+                                                         strerror(errno));
                }
        }
 
index acbde70..3c38110 100644 (file)
@@ -66,6 +66,9 @@ static status_t execute(private_send_dpd_job_t *this)
 {
        ike_sa_t *ike_sa;
        status_t status;
+       u_int32_t dt;
+       u_int32_t interval = charon->configuration->get_dpd_interval(charon->configuration);
+       struct timeval last_msg_tv, current_tv;
 
        this->logger->log(this->logger, CONTROL|LEVEL2, "Checking out IKE SA %lld:%lld, role %s",
                        this->ike_sa_id->get_initiator_spi(this->ike_sa_id),
@@ -81,9 +84,26 @@ static status_t execute(private_send_dpd_job_t *this)
                return DESTROY_ME;
        }
 
-       ike_sa->send_dpd_request(ike_sa);
-       this->logger->log(this->logger, CONTROL|LEVEL1,
-                       "DPD request packet scheduled");
+       last_msg_tv = ike_sa->get_last_traffic_in_tv(ike_sa);
+       if (0 > gettimeofday(&current_tv, NULL) )
+       {
+               this->logger->log(this->logger, ERROR|LEVEL1,
+                               "Warning: Failed to get time of day.");
+       }
+       dt = (current_tv.tv_sec - last_msg_tv.tv_sec) * 1000
+          + (current_tv.tv_usec - last_msg_tv.tv_usec) / 1000;
+
+       if (dt >= interval)
+       {
+               ike_sa->send_dpd_request(ike_sa);
+               this->logger->log(this->logger, CONTROL|LEVEL1,
+                               "DPD request packet scheduled");
+
+       }
+       else
+       {
+               charon->event_queue->add_relative(charon->event_queue, (job_t*) this, interval - dt);
+       }
 
        this->logger->log(this->logger, CONTROL|LEVEL2,
                        "Checkin IKE SA %lld:%lld, role %s",
index 4fc7f3d..f17296a 100644 (file)
@@ -68,7 +68,6 @@ static status_t execute(private_send_keepalive_job_t *this)
        status_t status;
        u_int32_t dt;
        u_int32_t interval = charon->configuration->get_keepalive_interval(charon->configuration);
-       u_int32_t timeout = charon->configuration->get_keepalive_timeout(charon->configuration);
        struct timeval last_msg_tv, current_tv;
        packet_t *packet;
        host_t *host;
@@ -89,7 +88,7 @@ static status_t execute(private_send_keepalive_job_t *this)
                return DESTROY_ME;
        }
 
-       last_msg_tv = ike_sa->get_last_msg_tv(ike_sa);
+       last_msg_tv = ike_sa->get_last_traffic_out_tv(ike_sa);
        if (0 > gettimeofday(&current_tv, NULL) )
        {
                this->logger->log(this->logger, ERROR|LEVEL1,
@@ -114,8 +113,7 @@ static status_t execute(private_send_keepalive_job_t *this)
                this->logger->log(this->logger, CONTROL|LEVEL1,
                                "NAT keepalive packet scheduled");
        }
-       charon->event_queue->add_relative(charon->event_queue,
-                                         (job_t*) this, interval - dt);
+       charon->event_queue->add_relative(charon->event_queue, (job_t*) this, interval - dt);
 
        this->logger->log(this->logger, CONTROL|LEVEL2,
                        "Checkin IKE SA %lld:%lld, role %s",
index 554078c..b7b4492 100644 (file)
@@ -327,7 +327,6 @@ static status_t install(private_child_sa_t *this, proposal_t *proposal, prf_plus
 
 static status_t add(private_child_sa_t *this, proposal_t *proposal, prf_plus_t *prf_plus)
 {
-       linked_list_t *list;
        u_int32_t outbound_spi, inbound_spi;
        
        /* backup outbound spi, as alloc overwrites it */
@@ -540,6 +539,94 @@ static void log_status(private_child_sa_t *this, logger_t *logger, char* name)
 }
 
 /**
+ * Implementation of child_sa_t.get_use_time
+ */
+static status_t get_use_time(private_child_sa_t *this, bool inbound, time_t *use_time)
+{
+       iterator_t *iterator;
+       sa_policy_t *policy;
+       struct protoent *proto;
+       char proto_buf[8] = "";
+       char *proto_name = proto_buf;
+       status_t status;
+       
+       *use_time = UNDEFINED_TIME;
+
+       iterator = this->policies->create_iterator(this->policies, TRUE);
+       while (iterator->iterate(iterator, (void**)&policy))
+       {
+               time_t ut;
+
+               if (policy->upper_proto)
+               {
+                       proto = getprotobynumber(policy->upper_proto);
+                       if (proto)
+                       {
+                               proto_name = proto->p_name;
+                       }
+                       else
+                       {
+                               snprintf(proto_buf, sizeof(proto_buf), "<%d>", policy->upper_proto);
+                       }
+               }
+               
+               this->logger->log(this->logger, CONTROL|LEVEL1,
+                                       "quering policy:     %s/%d==%s==%s/%d",
+                                       policy->me.net->get_address(policy->me.net), policy->me.net_mask,
+                                       proto_name,
+                                       policy->other.net->get_address(policy->other.net), policy->other.net_mask);
+
+               if (inbound) 
+               {
+                       status = charon->kernel_interface->query_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,
+                                               &ut);
+       
+                       /* also check forward policy in tunnel mode */
+                       if (status == SUCCESS /*&& mode == TUNNEL XXX */)
+                       {
+                               time_t fwd;
+
+                               status = charon->kernel_interface->query_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,
+                                                       &fwd);
+                       
+                               if (status == SUCCESS)
+                               {
+                                       ut = max(ut, fwd);
+                               }
+                       }
+               }
+               else 
+               {
+                       status = charon->kernel_interface->query_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,
+                                               &ut);
+               }
+               
+               if (status != SUCCESS)
+               {
+                       iterator->destroy(iterator);
+                       return FAILED;
+               }
+
+               *use_time = max(*use_time, ut);
+       }
+       iterator->destroy(iterator);
+       
+       return SUCCESS;
+}
+
+/**
  * Update the host adress/port of a SA
  */
 static status_t update_sa_hosts(private_child_sa_t *this, host_t *new_me, host_t *new_other, 
@@ -772,6 +859,7 @@ child_sa_t * child_sa_create(u_int32_t rekey, host_t *me, host_t* other,
        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.add_policies = (status_t (*)(child_sa_t*, linked_list_t*,linked_list_t*))add_policies;
+       this->public.get_use_time = (status_t (*)(child_sa_t*,bool,time_t*))get_use_time;
        this->public.set_rekeyed = (void (*)(child_sa_t*))set_rekeyed;
        this->public.log_status = (void (*)(child_sa_t*, logger_t*, char*))log_status;
        this->public.destroy = (void(*)(child_sa_t*))destroy;
index a93d81e..6c1ca01 100644 (file)
@@ -158,6 +158,16 @@ struct child_sa_t {
        status_t (*add_policies) (child_sa_t *this, linked_list_t *my_ts_list, linked_list_t *other_ts_list);
        
        /**
+        * @brief Get the time of this child_sa_t's last use (i.e. last use of any of its policies)
+        * 
+        * @param this          calling object
+        * @param inbound       query for in- or outbound usage
+        * @param use_time      the time
+        * @return                      SUCCESS or FAILED
+        */     
+       status_t (*get_use_time) (child_sa_t *this, bool inbound, time_t *use_time);
+       
+       /**
         * @brief Mark this child_sa as rekeyed.
         *
         * Since an SA which rekeys a old SA shares the same policy,
index 84c7514..2ba9c74 100644 (file)
@@ -68,6 +68,16 @@ struct private_ike_sa_t {
        protected_ike_sa_t protected;
        
        /**
+        * Update a timestamp on ike traffic
+        */
+       void (*update_timestamp)(private_ike_sa_t *this, bool in);
+       
+       /**
+        * Returns the time since last traffic on kernel policies
+        */
+       struct timeval (*get_last_esp_traffic_tv)(private_ike_sa_t * this, bool inbound);
+
+       /**
         * Identifier for the current IKE_SA.
         */
        ike_sa_id_t *ike_sa_id;
@@ -194,9 +204,14 @@ struct private_ike_sa_t {
        bool nat_there;
 
        /**
-        * Timestamp of last IKE message sent or received on this SA
+        * Timestamp of last IKE message received on this SA
         */
-       struct timeval last_msg_tv;
+       struct timeval last_msg_in_tv;
+
+       /**
+        * Timestamp of last IKE message sent on this SA
+        */
+       struct timeval last_msg_out_tv;
 
        /*
         * Message ID of last DPD message
@@ -330,7 +345,7 @@ static host_t* get_my_host(private_ike_sa_t *this)
  */
 static host_t* get_other_host(private_ike_sa_t *this)
 {
-       return this->connection->get_other_host(this->connection);;
+       return this->connection->get_other_host(this->connection);
 }
 
 /**
@@ -338,7 +353,7 @@ static host_t* get_other_host(private_ike_sa_t *this)
  */
 static identification_t* get_my_id(private_ike_sa_t *this)
 {
-       return this->policy->get_my_id(this->policy);;
+       return this->policy->get_my_id(this->policy);
 }
 
 /**
@@ -346,7 +361,7 @@ static identification_t* get_my_id(private_ike_sa_t *this)
  */
 static identification_t* get_other_id(private_ike_sa_t *this)
 {
-       return this->policy->get_other_id(this->policy);;
+       return this->policy->get_other_id(this->policy);
 }
 
 /**
@@ -375,7 +390,7 @@ static status_t retransmit_request(private_ike_sa_t *this, u_int32_t message_id)
        this->logger->log(this->logger, CONTROL | LEVEL1, "Going to retransmit message with id %d",message_id);
        packet = this->last_requested_message->get_packet(this->last_requested_message);
        charon->send_queue->add(charon->send_queue, packet);
-       
+       this->update_timestamp(this, FALSE);
        return SUCCESS;
 }
 
@@ -607,6 +622,20 @@ static signer_t *get_signer_responder(private_ike_sa_t *this)
 }
 
 /**
+ * Implementation of protected_ike_sa_t.update_timestamp
+ */
+static void update_timestamp(private_ike_sa_t *this, bool in)
+{
+       /* bump last message sent timestamp */
+       struct timeval *tv = in ? &this->last_msg_in_tv : &this->last_msg_out_tv;
+       if (0 > gettimeofday(tv, NULL))
+       {
+               this->logger->log(this->logger, ERROR|LEVEL1,
+                                                 "Warning: Failed to get time of day.");
+       }
+}
+
+/**
  * Implementation of protected_ike_sa_t.send_request.
  */
 static status_t send_request(private_ike_sa_t *this, message_t *message)
@@ -678,11 +707,7 @@ static status_t send_request(private_ike_sa_t *this, message_t *message)
                                          this->message_id_out);
        this->message_id_out++;
 
-       /* bump last message sent timestamp */
-       if (gettimeofday(&this->last_msg_tv, NULL) < 0)
-       {
-               this->logger->log(this->logger, ERROR|LEVEL1, "failed to get time of day");
-       }
+       this->update_timestamp(this, FALSE);
        return SUCCESS; 
 }
 
@@ -740,6 +765,8 @@ static status_t send_response(private_ike_sa_t *this, message_t *message)
        this->logger->log(this->logger, CONTROL|LEVEL3, "Increase message counter for incoming messages");
        this->message_id_in++;
 
+       this->update_timestamp(this, FALSE);
+
        return SUCCESS;
 }
 
@@ -780,6 +807,8 @@ static void send_notify(private_ike_sa_t *this, exchange_type_t exchange_type, n
        charon->send_queue->add(charon->send_queue, packet);
        this->logger->log(this->logger, CONTROL|LEVEL2, "Destroy message");
        response->destroy(response);
+
+       this->update_timestamp(this, FALSE);
 }
 
 /**
@@ -842,6 +871,7 @@ static status_t process_message(private_ike_sa_t *this, message_t *message)
                        packet_t *packet = this->last_responded_message->get_packet(this->last_responded_message);
                        this->logger->log(this->logger, CONTROL|LEVEL1, "Resent request detected. Send stored reply.");
                        charon->send_queue->add(charon->send_queue, packet);
+                       this->update_timestamp(this, FALSE);
                        return SUCCESS;
                }
                else
@@ -875,6 +905,8 @@ static status_t process_message(private_ike_sa_t *this, message_t *message)
                }
        }
        
+       this->update_timestamp(this, TRUE);
+       
        /* now the message is processed by the current state object.
         * The specific state object is responsible to check if a message can be received in 
         * the state it represents.
@@ -1412,14 +1444,50 @@ static void set_other_host_behind_nat (private_ike_sa_t *this, bool nat)
 }
 
 /**
- * Implementation of ike_sa_t.get_last_msg_tv.
+ * Implementation of private_ike_sa_t.get_last_esp_traffic_tv
  */
-static struct timeval get_last_msg_tv (private_ike_sa_t *this)
+static struct timeval get_last_esp_traffic_tv(private_ike_sa_t * this, bool inbound)
 {
-       /*
-        * XXX: query kernel for last activity time
-        */
-       return this->last_msg_tv;
+       iterator_t *iterator;
+       child_sa_t *child_sa;
+       bool ret = TRUE; 
+       time_t use_time = 0;
+       struct timeval tv = {0, 0};
+
+       iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
+       while (iterator->iterate(iterator, (void**)&child_sa))
+       {
+               if (child_sa->get_use_time(child_sa, inbound, &use_time) == SUCCESS
+                               && use_time != 0)
+               {
+                       tv.tv_sec = max(tv.tv_sec, use_time);
+               }
+       }
+       iterator->destroy(iterator);
+       
+       return tv;
+}
+
+/**
+ * Implementation of ike_sa_t.get_last_traffic_in_tv.
+ */
+static struct timeval get_last_traffic_in_tv (private_ike_sa_t *this)
+{
+       struct timeval esp_tv  = this->get_last_esp_traffic_tv(this, TRUE);
+       return this->last_msg_in_tv.tv_sec > esp_tv.tv_sec ? this->last_msg_in_tv
+            : this->last_msg_in_tv.tv_sec < esp_tv.tv_sec ? esp_tv
+            : this->last_msg_in_tv.tv_usec > esp_tv.tv_usec ? this->last_msg_in_tv : esp_tv;
+}
+
+/**
+ * Implementation of ike_sa_t.get_last_traffic_out_tv.
+ */
+static struct timeval get_last_traffic_out_tv (private_ike_sa_t *this)
+{
+       struct timeval esp_tv  = this->get_last_esp_traffic_tv(this, FALSE);
+       return this->last_msg_out_tv.tv_sec > esp_tv.tv_sec ? this->last_msg_out_tv
+            : this->last_msg_out_tv.tv_sec < esp_tv.tv_sec ? esp_tv
+            : this->last_msg_out_tv.tv_usec > esp_tv.tv_usec ? this->last_msg_out_tv : esp_tv; 
 }
 
 /**
@@ -1543,7 +1611,8 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
        this->protected.public.is_my_host_behind_nat = (bool(*)(ike_sa_t*)) is_my_host_behind_nat;
        this->protected.public.is_other_host_behind_nat = (bool(*)(ike_sa_t*)) is_other_host_behind_nat;
        this->protected.public.is_any_host_behind_nat = (bool(*)(ike_sa_t*)) is_any_host_behind_nat;
-       this->protected.public.get_last_msg_tv = (struct timeval (*)(ike_sa_t*)) get_last_msg_tv;
+       this->protected.public.get_last_traffic_in_tv = (struct timeval (*)(ike_sa_t*)) get_last_traffic_in_tv;
+       this->protected.public.get_last_traffic_out_tv = (struct timeval (*)(ike_sa_t*)) get_last_traffic_out_tv;
        this->protected.public.send_dpd_request = (status_t (*)(ike_sa_t*)) send_dpd_request;
        
        /* protected functions */
@@ -1579,6 +1648,10 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
        this->protected.get_last_dpd_message_id = (u_int32_t (*) (protected_ike_sa_t*)) get_last_dpd_message_id;
        this->protected.update_connection_hosts = (status_t (*) (protected_ike_sa_t *, host_t*, host_t*)) update_connection_hosts;
        
+       /* private functions */
+       this->update_timestamp = (void (*) (private_ike_sa_t*,bool))update_timestamp;
+       this->get_last_esp_traffic_tv = (struct timeval (*) (private_ike_sa_t *,bool))get_last_esp_traffic_tv;
+
        /* initialize private fields */
        this->logger = logger_manager->get_logger(logger_manager, IKE_SA);
        
@@ -1604,8 +1677,10 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
        this->nat_hasher = hasher_create(HASH_SHA1);
        this->nat_here = FALSE;
        this->nat_there = FALSE;
-       this->last_msg_tv.tv_sec = 0;
-       this->last_msg_tv.tv_usec = 0;
+       this->last_msg_in_tv.tv_sec = 0;
+       this->last_msg_in_tv.tv_usec = 0;
+       this->last_msg_out_tv.tv_sec = 0;
+       this->last_msg_out_tv.tv_usec = 0;
        this->last_dpd_message_id = 0;
 
        /* at creation time, IKE_SA is in a initiator state */
index aed8ff3..719aa94 100644 (file)
@@ -236,12 +236,20 @@ struct ike_sa_t {
        bool (*is_any_host_behind_nat) (ike_sa_t *this);
 
        /**
-        * @brief Query timeval of last message sent.
+        * @brief Query timeval of last inbound IKE or ESP traffic.
         *
-        * @param this                  calling object
-        * @return                              time when the last message was sent
+        * @param this                  calling object
+        * @return                              time when the last traffic was seen
+        */
+       struct timeval (*get_last_traffic_in_tv) (ike_sa_t *this);
+
+       /**
+        * @brief Query timeval of last outbound IKE or ESP traffic.
+        *
+        * @param this                  calling object
+        * @return                              time when the last traffic was seen
         */
-       struct timeval (*get_last_msg_tv) (ike_sa_t *this);
+       struct timeval (*get_last_traffic_out_tv) (ike_sa_t *this);
 
        /**
         * @brief Get the state of type of associated state object.
index c97254e..8003806 100644 (file)
@@ -554,14 +554,6 @@ static status_t process_message(private_ike_sa_established_t *this, message_t *m
        signer_t *signer;
        status_t status;
        
-       /* only requests are allowed, responses are handled in other state */
-       if (!message->get_request(message))
-       {
-               this->logger->log(this->logger, ERROR|LEVEL1,
-                                                 "Response not handled in state ike_sa_established");
-               return FAILED;
-       }
-       
        /* get signer for verification and crypter for decryption */
        ike_sa_id = this->ike_sa->public.get_id(&this->ike_sa->public);
        if (!ike_sa_id->is_initiator(ike_sa_id))
@@ -590,6 +582,28 @@ static status_t process_message(private_ike_sa_established_t *this, message_t *m
        {
                return status;
        }
+
+       /* process responses */
+       if (!message->get_request(message))
+       {
+               switch (message->get_exchange_type(message))
+               {
+                       case INFORMATIONAL:
+                               status = process_informational_response(this, message);
+                               break;
+                       default:
+                               this->logger->log(this->logger, ERROR | LEVEL1, 
+                                                 "Only INFORMATIONAL responses are handled in state ike_sa_established");
+                               status = FAILED;
+                               break;
+               }
+
+               /* we don't really reply to this message but the retransmit mechanism relies on this */
+               this->ike_sa->set_last_replied_message_id(this->ike_sa, message->get_message_id(message));
+
+               /* return here */
+               return status;
+       }
        
        /* prepare a reply of the same type */
        this->ike_sa->build_message(this->ike_sa, message->get_exchange_type(message), FALSE, &response);
@@ -609,6 +623,7 @@ static status_t process_message(private_ike_sa_established_t *this, message_t *m
                                                          mapping_find(exchange_type_m, message->get_exchange_type(message)));
                        status = NOT_SUPPORTED;
        }
+       
        return status;
 }
 
index b120918..503bfef 100644 (file)
@@ -94,6 +94,7 @@ struct private_initiator_init_t {
         * @param request       message_t object to add the NONCE payload
         */
        status_t (*build_nonce_payload) (private_initiator_init_t *this,message_t *request);    
+
        /**
         * Builds the NAT-T Notify(NAT_DETECTION_SOURCE_IP) and
         * Notify(NAT_DETECTION_DESTINATION_IP) payloads for this state.
index 3e85ea5..5dad9e7 100644 (file)
@@ -388,6 +388,7 @@ static status_t process_message(private_responder_init_t *this, message_t *messa
                response->destroy(response);
                return status;
        }       
+
        /* build Notify(NAT-D) payloads */
        this->build_natd_payloads(this, response);
 
@@ -616,6 +617,7 @@ static status_t process_notify_payload(private_responder_init_t *this, notify_pa
        
        this->logger->log(this->logger, CONTROL|LEVEL1, "process notify type %s",
                                                  mapping_find(notify_message_type_m, notify_message_type));
+
        switch (notify_message_type)
        {
                case NAT_DETECTION_DESTINATION_IP:
index 5e44803..4338889 100644 (file)
@@ -673,6 +673,75 @@ static status_t add_policy(private_kernel_interface_t *this,
        return status;
 }
 
+static status_t query_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,
+                                       int direction, int upper_proto,
+                                       time_t *use_time)
+{
+       unsigned char request[BUFFER_SIZE];
+       struct nlmsghdr *response;
+       
+       memset(&request, 0, sizeof(request));
+       status_t status = SUCCESS;
+       
+       this->logger->log(this->logger, CONTROL|LEVEL2, "querying policy");
+
+       struct nlmsghdr *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));
+
+       struct xfrm_userpolicy_id *policy_id = (struct xfrm_userpolicy_id*)NLMSG_DATA(hdr);
+       policy_id->sel.sport = htons(src->get_port(src));
+       policy_id->sel.sport_mask = (policy_id->sel.sport) ? ~0 : 0;
+       policy_id->sel.saddr = src->get_xfrm_addr(src);
+       policy_id->sel.prefixlen_s = src_hostbits;
+       
+       policy_id->sel.dport = htons(dst->get_port(dst));
+       policy_id->sel.dport_mask = (policy_id->sel.dport) ? ~0 : 0;
+       policy_id->sel.daddr = dst->get_xfrm_addr(dst);
+       policy_id->sel.prefixlen_d = dst_hostbits;
+       
+       policy_id->sel.proto = upper_proto;
+       policy_id->sel.family = src->get_family(src);
+       
+       policy_id->dir = direction;
+
+       if (this->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;
+       }
+
+       struct xfrm_userpolicy_info *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.
  */
@@ -923,6 +992,7 @@ kernel_interface_t *kernel_interface_create()
        this->public.add_policy = (status_t(*)(kernel_interface_t*,host_t*, host_t*,host_t*,host_t*,u_int8_t,u_int8_t,int,int,protocol_id_t,u_int32_t))add_policy;
        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.del_sa = (status_t(*)(kernel_interface_t*,host_t*,u_int32_t,protocol_id_t))del_sa;
+       this->public.query_policy = (status_t(*)(kernel_interface_t*,host_t*,host_t*,host_t*,host_t*,u_int8_t,u_int8_t,int,int,time_t*))query_policy;
        this->public.del_policy = (status_t(*)(kernel_interface_t*,host_t*,host_t*,host_t*,host_t*,u_int8_t,u_int8_t,int,int))del_policy;
        
        this->public.destroy = (void(*)(kernel_interface_t*)) destroy;
index 9aa2d94..c427e2a 100644 (file)
@@ -118,6 +118,7 @@ struct kernel_interface_t {
                                prf_plus_t *prf_plus,
                                natt_conf_t *natt,
                                bool replace);
+       
        /**
         * @brief Update the hosts on an installed SA. Encapsulation ports are also updated.
         *
@@ -190,6 +191,29 @@ struct kernel_interface_t {
                                int direction, int upper_proto, 
                                protocol_id_t protocol,
                                u_int32_t reqid);
+       /**
+        * @brief Query the use time of a policy
+        * 
+        * @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 use_time              the time of this policy's last use
+        * @return
+        *                                              - SUCCESS
+        *                                              - FAILED if kernel comm failed
+        */
+       status_t (*query_policy) (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,
+                               int direction, int upper_proto,
+                               time_t *use_time);
        
        /**
         * @brief Remove a policy from the SPD.
index 5f495a5..968342d 100644 (file)
@@ -38,6 +38,7 @@ libstrongswan_la_LIBADD = -lgmp -lpthread
 
 INCLUDES = -I$(top_srcdir)/src/libstrongswan
 EXTRA_DIST = asn1/oid.txt asn1/oid.pl
+BUILT_SOURCES = asn1/oid.c asn1/oid.h
 MAINTAINERCLEANFILES = asn1/oid.c asn1/oid.h
 
 if USE_LEAK_DETECTIVE
index 9787f49..fb07bb8 100644 (file)
@@ -30,6 +30,7 @@ pluto_LDADD = $(top_srcdir)/src/libfreeswan/libfreeswan.a $(top_srcdir)/src/libc
 _pluto_adns_LDADD = -lresolv $(top_srcdir)/src/libfreeswan/libfreeswan.a
 dist_man_MANS = pluto.8 ipsec.secrets.5
 EXTRA_DIST = oid.pl oid.txt
+BUILT_SOURCES = oid.c oid.h
 MAINTAINERCLEANFILES = oid.c oid.h
 
 oid.c: oid.txt oid.pl
diff --git a/src/stroke/stroke_keywords.c b/src/stroke/stroke_keywords.c
deleted file mode 100644 (file)
index f622d2d..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-/* C code produced by gperf version 3.0.1 */
-/* Command-line: /usr/bin/gperf -C -G -t  */
-/* Computed positions: -k'2' */
-
-#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
-      && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
-      && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
-      && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
-      && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
-      && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
-      && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
-      && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
-      && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
-      && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
-      && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
-      && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
-      && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
-      && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
-      && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
-      && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
-      && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
-      && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
-      && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
-      && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
-      && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
-      && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
-      && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
-/* The character set is not based on ISO-646.  */
-error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>."
-#endif
-
-
-/* stroke keywords
- * Copyright (C) 2006 Andreas Steffen
- * Hochschule fuer Technik Rapperswil, Switzerland
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- *
- * RCSID $Id: keywords.txt,v 1.6 2006/04/17 10:30:27 as Exp $
- */
-
-#include <string.h>
-
-#include "stroke_keywords.h"
-
-struct stroke_token {
-    char *name;
-    stroke_keyword_t kw;
-};
-
-#define TOTAL_KEYWORDS 17
-#define MIN_WORD_LENGTH 2
-#define MAX_WORD_LENGTH 13
-#define MIN_HASH_VALUE 2
-#define MAX_HASH_VALUE 23
-/* maximum key range = 22, duplicates = 0 */
-
-#ifdef __GNUC__
-__inline
-#else
-#ifdef __cplusplus
-inline
-#endif
-#endif
-static unsigned int
-hash (str, len)
-     register const char *str;
-     register unsigned int len;
-{
-  static const unsigned char asso_values[] =
-    {
-      24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-      24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-      24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-      24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-      24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-      24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-      24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-      24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-      24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-      24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-      20,  0, 24, 24, 24, 10, 24, 24, 24, 24,
-      24,  0,  0, 24, 24, 24,  5, 24, 24, 24,
-      24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-      24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-      24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-      24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-      24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-      24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-      24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-      24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-      24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-      24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-      24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-      24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-      24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-      24, 24, 24, 24, 24, 24
-    };
-  return len + asso_values[(unsigned char)str[1]];
-}
-
-static const struct stroke_token wordlist[] =
-  {
-    {""}, {""},
-    {"up",            STROKE_UP},
-    {"del",           STROKE_DEL},
-    {"down",          STROKE_DOWN},
-    {"route",         STROKE_ROUTE},
-    {"delete",        STROKE_DELETE},
-    {"logtype",       STROKE_LOGTYPE},
-    {"loglevel",      STROKE_LOGLEVEL},
-    {"rereadall",     STROKE_REREAD_ALL},
-    {"rereadcrls",    STROKE_REREAD_CRLS,},
-    {"status",        STROKE_STATUS},
-    {""},
-    {"rereadcacerts", STROKE_REREAD_CACERTS,},
-    {"statusall",     STROKE_STATUSALL},
-    {""}, {""},
-    {"listall",       STROKE_LIST_ALL,},
-    {"listcrls",      STROKE_LIST_CRLS},
-    {"listcerts",     STROKE_LIST_CERTS},
-    {""},
-    {"listcacerts",   STROKE_LIST_CACERTS},
-    {""},
-    {"add",           STROKE_ADD}
-  };
-
-#ifdef __GNUC__
-__inline
-#endif
-const struct stroke_token *
-in_word_set (str, len)
-     register const char *str;
-     register unsigned int len;
-{
-  if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
-    {
-      register int key = hash (str, len);
-
-      if (key <= MAX_HASH_VALUE && key >= 0)
-        {
-          register const char *s = wordlist[key].name;
-
-          if (*str == *s && !strcmp (str + 1, s + 1))
-            return &wordlist[key];
-        }
-    }
-  return 0;
-}