fixed a bug introduced in [3973]
[strongswan.git] / src / charon / config / child_cfg.c
index 2f53767..33dd73c 100644 (file)
@@ -1,11 +1,5 @@
-/**
- * @file child_cfg.c
- * 
- * @brief Implementation of child_cfg_t.
- * 
- */
-
 /*
 /*
+ * Copyright (C) 2008 Tobias Brunner
  * Copyright (C) 2005-2007 Martin Willi
  * Copyright (C) 2005 Jan Hutter
  * Hochschule fuer Technik Rapperswil
  * Copyright (C) 2005-2007 Martin Willi
  * Copyright (C) 2005 Jan Hutter
  * Hochschule fuer Technik Rapperswil
  * 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.
  * 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.
+ *
+ * $Id$
  */
 
  */
 
-
 #include "child_cfg.h"
 
 #include <daemon.h>
 #include "child_cfg.h"
 
 #include <daemon.h>
@@ -34,6 +29,21 @@ ENUM(mode_names, MODE_TRANSPORT, MODE_BEET,
        "BEET",
 );
 
        "BEET",
 );
 
+ENUM(action_names, ACTION_NONE, ACTION_RESTART,
+       "ACTION_NONE",
+       "ACTION_ROUTE",
+       "ACTION_RESTART",
+);
+
+ENUM_BEGIN(ipcomp_transform_names, IPCOMP_NONE, IPCOMP_NONE, 
+       "IPCOMP_NONE");
+ENUM_NEXT(ipcomp_transform_names, IPCOMP_OUI, IPCOMP_LZJH, IPCOMP_NONE,
+       "IPCOMP_OUI",
+       "IPCOMP_DEFLATE",
+       "IPCOMP_LZS",
+       "IPCOMP_LZJH");
+ENUM_END(ipcomp_transform_names, IPCOMP_LZJH);
+
 typedef struct private_child_cfg_t private_child_cfg_t;
 
 /**
 typedef struct private_child_cfg_t private_child_cfg_t;
 
 /**
@@ -87,6 +97,16 @@ struct private_child_cfg_t {
        mode_t mode;
        
        /**
        mode_t mode;
        
        /**
+        * action to take on DPD
+        */
+       action_t dpd_action;
+       
+       /**
+        * action to take on CHILD_SA close
+        */
+       action_t close_action;
+       
+       /**
         * Time before an SA gets invalid
         */
        u_int32_t lifetime;
         * Time before an SA gets invalid
         */
        u_int32_t lifetime;
@@ -101,6 +121,11 @@ struct private_child_cfg_t {
         * substracted from rekeytime.
         */
        u_int32_t jitter;
         * substracted from rekeytime.
         */
        u_int32_t jitter;
+       
+       /**
+        * enable IPComp
+        */
+       bool use_ipcomp;
 };
 
 /**
 };
 
 /**
@@ -122,19 +147,23 @@ static void add_proposal(private_child_cfg_t *this, proposal_t *proposal)
 /**
  * Implementation of child_cfg_t.get_proposals
  */
 /**
  * Implementation of child_cfg_t.get_proposals
  */
-static linked_list_t* get_proposals(private_child_cfg_t *this)
+static linked_list_t* get_proposals(private_child_cfg_t *this, bool strip_dh)
 {
 {
-       iterator_t *iterator;
+       enumerator_t *enumerator;
        proposal_t *current;
        linked_list_t *proposals = linked_list_create();
        
        proposal_t *current;
        linked_list_t *proposals = linked_list_create();
        
-       iterator = this->proposals->create_iterator(this->proposals, TRUE);
-       while (iterator->iterate(iterator, (void**)&current))
+       enumerator = this->proposals->create_enumerator(this->proposals);
+       while (enumerator->enumerate(enumerator, &current))
        {
                current = current->clone(current);
        {
                current = current->clone(current);
+               if (strip_dh)
+               {
+                       current->strip_dh(current);
+               }
                proposals->insert_last(proposals, current);
        }
                proposals->insert_last(proposals, current);
        }
-       iterator->destroy(iterator);
+       enumerator->destroy(enumerator);
        
        return proposals;
 }
        
        return proposals;
 }
@@ -142,33 +171,41 @@ static linked_list_t* get_proposals(private_child_cfg_t *this)
 /**
  * Implementation of child_cfg_t.get_name
  */
 /**
  * Implementation of child_cfg_t.get_name
  */
-static proposal_t* select_proposal(private_child_cfg_t*this, linked_list_t *proposals)
+static proposal_t* select_proposal(private_child_cfg_t*this,
+                                                                  linked_list_t *proposals, bool strip_dh)
 {
 {
-       iterator_t *stored_iter, *supplied_iter;
+       enumerator_t *stored_enum, *supplied_enum;
        proposal_t *stored, *supplied, *selected = NULL;
        
        proposal_t *stored, *supplied, *selected = NULL;
        
-       stored_iter = this->proposals->create_iterator(this->proposals, TRUE);
-       supplied_iter = proposals->create_iterator(proposals, TRUE);
+       stored_enum = this->proposals->create_enumerator(this->proposals);
+       supplied_enum = proposals->create_enumerator(proposals);
        
        /* compare all stored proposals with all supplied. Stored ones are preferred. */
        
        /* compare all stored proposals with all supplied. Stored ones are preferred. */
-       while (stored_iter->iterate(stored_iter, (void**)&stored))
+       while (stored_enum->enumerate(stored_enum, &stored))
        {
        {
-               supplied_iter->reset(supplied_iter);
-               while (supplied_iter->iterate(supplied_iter, (void**)&supplied))
+               stored = stored->clone(stored);
+               while (supplied_enum->enumerate(supplied_enum, &supplied))
                {
                {
+                       if (strip_dh)
+                       {
+                               stored->strip_dh(stored);
+                       }
                        selected = stored->select(stored, supplied);
                        if (selected)
                        {
                                break;
                        }
                }
                        selected = stored->select(stored, supplied);
                        if (selected)
                        {
                                break;
                        }
                }
+               stored->destroy(stored);
                if (selected)
                {
                        break;
                }
                if (selected)
                {
                        break;
                }
+               supplied_enum->destroy(supplied_enum);
+               supplied_enum = proposals->create_enumerator(proposals);        
        }
        }
-       stored_iter->destroy(stored_iter);
-       supplied_iter->destroy(supplied_iter);
+       stored_enum->destroy(stored_enum);
+       supplied_enum->destroy(supplied_enum);
        return selected;
 }
 
        return selected;
 }
 
@@ -195,40 +232,44 @@ static linked_list_t* get_traffic_selectors(private_child_cfg_t *this, bool loca
                                                                                        linked_list_t *supplied,
                                                                                        host_t *host)
 {
                                                                                        linked_list_t *supplied,
                                                                                        host_t *host)
 {
-       iterator_t *i1, *i2;
+       enumerator_t *e1, *e2;
        traffic_selector_t *ts1, *ts2, *selected;
        linked_list_t *result = linked_list_create();
        
        if (local)
        {
        traffic_selector_t *ts1, *ts2, *selected;
        linked_list_t *result = linked_list_create();
        
        if (local)
        {
-               i1 = this->my_ts->create_iterator(this->my_ts, TRUE);
+               e1 = this->my_ts->create_enumerator(this->my_ts);
        }
        else
        {
        }
        else
        {
-               i1 = this->other_ts->create_iterator(this->other_ts, FALSE);
+               e1 = this->other_ts->create_enumerator(this->other_ts);
        }
        
        /* no list supplied, just fetch the stored traffic selectors */
        if (supplied == NULL)
        {
        }
        
        /* no list supplied, just fetch the stored traffic selectors */
        if (supplied == NULL)
        {
-               while (i1->iterate(i1, (void**)&ts1))
+               DBG2(DBG_CFG, "proposing traffic selectors for %s:", 
+                        local ? "us" : "other");
+               while (e1->enumerate(e1, &ts1))
                {
                        /* we make a copy of the TS, this allows us to update dynamic TS' */
                {
                        /* we make a copy of the TS, this allows us to update dynamic TS' */
-                       ts1 = ts1->clone(ts1);
+                       selected = ts1->clone(ts1);
                        if (host)
                        {
                        if (host)
                        {
-                               ts1->set_address(ts1, host);
+                               selected->set_address(selected, host);
                        }
                        }
-                       result->insert_last(result, ts1);
+                       DBG2(DBG_CFG, " %R (derived from %R)", selected, ts1);
+                       result->insert_last(result, selected);
                }
                }
-               i1->destroy(i1);
+               e1->destroy(e1);
        }
        else
        {
        }
        else
        {
-               DBG2(DBG_CFG, "selecting traffic selectors");
-               i2 = supplied->create_iterator(supplied, TRUE);
+               DBG2(DBG_CFG, "selecting traffic selectors for %s:", 
+                        local ? "us" : "other");
+               e2 = supplied->create_enumerator(supplied);
                /* iterate over all stored selectors */
                /* iterate over all stored selectors */
-               while (i1->iterate(i1, (void**)&ts1))
+               while (e1->enumerate(e1, &ts1))
                {
                        /* we make a copy of the TS, as we have to update dynamic TS' */
                        ts1 = ts1->clone(ts1);
                {
                        /* we make a copy of the TS, as we have to update dynamic TS' */
                        ts1 = ts1->clone(ts1);
@@ -237,53 +278,60 @@ static linked_list_t* get_traffic_selectors(private_child_cfg_t *this, bool loca
                                ts1->set_address(ts1, host);
                        }
                        
                                ts1->set_address(ts1, host);
                        }
                        
-                       i2->reset(i2);
                        /* iterate over all supplied traffic selectors */
                        /* iterate over all supplied traffic selectors */
-                       while (i2->iterate(i2, (void**)&ts2))
+                       while (e2->enumerate(e2, &ts2))
                        {
                        {
-                               DBG2(DBG_CFG, "stored %R <=> %R received", ts1, ts2);
                                selected = ts1->get_subset(ts1, ts2);
                                if (selected)
                                {
                                selected = ts1->get_subset(ts1, ts2);
                                if (selected)
                                {
+                                       DBG2(DBG_CFG, " config: %R, received: %R => match: %R",
+                                                ts1, ts2, selected);
                                        result->insert_last(result, selected);
                                        result->insert_last(result, selected);
-                                       DBG2(DBG_CFG, "found traffic selector for %s: %R", 
-                                                local ? "us" : "other", selected);
+                               }
+                               else
+                               {
+                                       DBG2(DBG_CFG, " config: %R, received: %R => no match",
+                                                ts1, ts2, selected);
                                }
                        }
                                }
                        }
+                       e2->destroy(e2);
+                       e2 = supplied->create_enumerator(supplied);
                        ts1->destroy(ts1);
                }
                        ts1->destroy(ts1);
                }
-               i1->destroy(i1);
-               i2->destroy(i2);
+               e1->destroy(e1);
+               e2->destroy(e2);
        }
        
        /* remove any redundant traffic selectors in the list */
        }
        
        /* remove any redundant traffic selectors in the list */
-       i1 = result->create_iterator(result, TRUE);
-       i2 = result->create_iterator(result, TRUE);
-       while (i1->iterate(i1, (void**)&ts1))
+       e1 = result->create_enumerator(result);
+       e2 = result->create_enumerator(result);
+       while (e1->enumerate(e1, &ts1))
        {
        {
-               while (i2->iterate(i2, (void**)&ts2))
+               while (e2->enumerate(e2, &ts2))
                {
                        if (ts1 != ts2)
                        {
                                if (ts2->is_contained_in(ts2, ts1))
                                {
                {
                        if (ts1 != ts2)
                        {
                                if (ts2->is_contained_in(ts2, ts1))
                                {
-                                       i2->remove(i2);
+                                       result->remove_at(result, e2);
                                        ts2->destroy(ts2);
                                        ts2->destroy(ts2);
-                                       i1->reset(i1);
+                                       e1->destroy(e1);
+                                       e1 = result->create_enumerator(result);
                                        break;
                                }
                                if (ts1->is_contained_in(ts1, ts2))
                                {
                                        break;
                                }
                                if (ts1->is_contained_in(ts1, ts2))
                                {
-                                       i1->remove(i1);
+                                       result->remove_at(result, e1);
                                        ts1->destroy(ts1);
                                        ts1->destroy(ts1);
-                                       i2->reset(i2);
+                                       e2->destroy(e2);
+                                       e2 = result->create_enumerator(result);
                                        break;
                                }
                        }
                }
        }
                                        break;
                                }
                        }
                }
        }
-       i1->destroy(i1);
-       i2->destroy(i2);
+       e1->destroy(e1);
+       e2->destroy(e2);
        
        return result;
 }
        
        return result;
 }
@@ -321,7 +369,7 @@ static u_int32_t get_lifetime(private_child_cfg_t *this, bool rekey)
 }
 
 /**
 }
 
 /**
- * Implementation of child_cfg_t.get_name
+ * Implementation of child_cfg_t.get_mode
  */
 static mode_t get_mode(private_child_cfg_t *this)
 {
  */
 static mode_t get_mode(private_child_cfg_t *this)
 {
@@ -329,11 +377,57 @@ static mode_t get_mode(private_child_cfg_t *this)
 }
 
 /**
 }
 
 /**
+ * Implementation of child_cfg_t.get_dpd_action
+ */
+static action_t get_dpd_action(private_child_cfg_t *this)
+{
+       return this->dpd_action;
+}
+
+/**
+ * Implementation of child_cfg_t.get_close_action
+ */
+static action_t get_close_action(private_child_cfg_t *this)
+{
+       return this->close_action;
+}
+
+/**
+ * Implementation of child_cfg_t.get_dh_group.
+ */
+static diffie_hellman_group_t get_dh_group(private_child_cfg_t *this)
+{
+       enumerator_t *enumerator;
+       proposal_t *proposal;
+       u_int16_t dh_group = MODP_NONE;
+       
+       enumerator = this->proposals->create_enumerator(this->proposals);
+       while (enumerator->enumerate(enumerator, &proposal))
+       {
+               if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &dh_group, NULL))
+               {
+                       break;
+               }
+       }
+       enumerator->destroy(enumerator);
+       return dh_group;
+}
+
+/**
+ * Implementation of child_cfg_t.use_ipcomp.
+ */
+static bool use_ipcomp(private_child_cfg_t *this)
+{
+       return this->use_ipcomp;
+}
+
+/**
  * Implementation of child_cfg_t.get_name
  */
  * Implementation of child_cfg_t.get_name
  */
-static void get_ref(private_child_cfg_t *this)
+static child_cfg_t* get_ref(private_child_cfg_t *this)
 {
        ref_get(&this->refcount);
 {
        ref_get(&this->refcount);
+       return &this->public;
 }
 
 /**
 }
 
 /**
@@ -360,25 +454,28 @@ static void destroy(private_child_cfg_t *this)
  */
 child_cfg_t *child_cfg_create(char *name, u_int32_t lifetime,
                                                          u_int32_t rekeytime, u_int32_t jitter,
  */
 child_cfg_t *child_cfg_create(char *name, u_int32_t lifetime,
                                                          u_int32_t rekeytime, u_int32_t jitter,
-                                                         char *updown, bool hostaccess, mode_t mode)
+                                                         char *updown, bool hostaccess, mode_t mode,
+                                                         action_t dpd_action, action_t close_action, bool ipcomp)
 {
        private_child_cfg_t *this = malloc_thing(private_child_cfg_t);
 
 {
        private_child_cfg_t *this = malloc_thing(private_child_cfg_t);
 
-       /* public functions */
        this->public.get_name = (char* (*) (child_cfg_t*))get_name;
        this->public.add_traffic_selector = (void (*)(child_cfg_t*,bool,traffic_selector_t*))add_traffic_selector;
        this->public.get_traffic_selectors = (linked_list_t*(*)(child_cfg_t*,bool,linked_list_t*,host_t*))get_traffic_selectors;
        this->public.add_proposal = (void (*) (child_cfg_t*,proposal_t*))add_proposal;
        this->public.get_name = (char* (*) (child_cfg_t*))get_name;
        this->public.add_traffic_selector = (void (*)(child_cfg_t*,bool,traffic_selector_t*))add_traffic_selector;
        this->public.get_traffic_selectors = (linked_list_t*(*)(child_cfg_t*,bool,linked_list_t*,host_t*))get_traffic_selectors;
        this->public.add_proposal = (void (*) (child_cfg_t*,proposal_t*))add_proposal;
-       this->public.get_proposals = (linked_list_t* (*) (child_cfg_t*))get_proposals;
-       this->public.select_proposal = (proposal_t* (*) (child_cfg_t*,linked_list_t*))select_proposal;
+       this->public.get_proposals = (linked_list_t* (*) (child_cfg_t*,bool))get_proposals;
+       this->public.select_proposal = (proposal_t* (*) (child_cfg_t*,linked_list_t*,bool))select_proposal;
        this->public.get_updown = (char* (*) (child_cfg_t*))get_updown;
        this->public.get_hostaccess = (bool (*) (child_cfg_t*))get_hostaccess;
        this->public.get_mode = (mode_t (*) (child_cfg_t *))get_mode;
        this->public.get_updown = (char* (*) (child_cfg_t*))get_updown;
        this->public.get_hostaccess = (bool (*) (child_cfg_t*))get_hostaccess;
        this->public.get_mode = (mode_t (*) (child_cfg_t *))get_mode;
+       this->public.get_dpd_action = (action_t (*) (child_cfg_t *))get_dpd_action;
+       this->public.get_close_action = (action_t (*) (child_cfg_t *))get_close_action;
        this->public.get_lifetime = (u_int32_t (*) (child_cfg_t *,bool))get_lifetime;
        this->public.get_lifetime = (u_int32_t (*) (child_cfg_t *,bool))get_lifetime;
-       this->public.get_ref = (void (*) (child_cfg_t*))get_ref;
+       this->public.get_dh_group = (diffie_hellman_group_t(*)(child_cfg_t*)) get_dh_group;
+       this->public.use_ipcomp = (bool (*) (child_cfg_t *))use_ipcomp;
+       this->public.get_ref = (child_cfg_t* (*) (child_cfg_t*))get_ref;
        this->public.destroy = (void (*) (child_cfg_t*))destroy;
        
        this->public.destroy = (void (*) (child_cfg_t*))destroy;
        
-       /* apply init values */
        this->name = strdup(name);
        this->lifetime = lifetime;
        this->rekeytime = rekeytime;
        this->name = strdup(name);
        this->lifetime = lifetime;
        this->rekeytime = rekeytime;
@@ -386,8 +483,9 @@ child_cfg_t *child_cfg_create(char *name, u_int32_t lifetime,
        this->updown = updown ? strdup(updown) : NULL;
        this->hostaccess = hostaccess;
        this->mode = mode;
        this->updown = updown ? strdup(updown) : NULL;
        this->hostaccess = hostaccess;
        this->mode = mode;
-       
-       /* initialize private members*/
+       this->dpd_action = dpd_action;
+       this->close_action = close_action;
+       this->use_ipcomp = ipcomp; 
        this->refcount = 1;
        this->proposals = linked_list_create();
        this->my_ts = linked_list_create();
        this->refcount = 1;
        this->proposals = linked_list_create();
        this->my_ts = linked_list_create();
@@ -395,3 +493,4 @@ child_cfg_t *child_cfg_create(char *name, u_int32_t lifetime,
 
        return &this->public;
 }
 
        return &this->public;
 }
+