summaryrefslogtreecommitdiff
path: root/src/libcharon/config/child_cfg.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcharon/config/child_cfg.c')
-rw-r--r--src/libcharon/config/child_cfg.c79
1 files changed, 43 insertions, 36 deletions
diff --git a/src/libcharon/config/child_cfg.c b/src/libcharon/config/child_cfg.c
index 74949be3c..b675c908f 100644
--- a/src/libcharon/config/child_cfg.c
+++ b/src/libcharon/config/child_cfg.c
@@ -171,6 +171,8 @@ METHOD(child_cfg_t, get_proposals, linked_list_t*,
}
enumerator->destroy(enumerator);
+ DBG2(DBG_CFG, "configured proposals: %#P", proposals);
+
return proposals;
}
@@ -235,12 +237,16 @@ METHOD(child_cfg_t, add_traffic_selector, void,
}
METHOD(child_cfg_t, get_traffic_selectors, linked_list_t*,
- private_child_cfg_t *this, bool local, linked_list_t *supplied, host_t *host)
+ private_child_cfg_t *this, bool local, linked_list_t *supplied,
+ linked_list_t *hosts)
{
enumerator_t *e1, *e2;
traffic_selector_t *ts1, *ts2, *selected;
- linked_list_t *result = linked_list_create();
+ linked_list_t *result, *derived;
+ host_t *host;
+ result = linked_list_create();
+ derived = linked_list_create();
if (local)
{
e1 = this->my_ts->create_enumerator(this->my_ts);
@@ -249,42 +255,46 @@ METHOD(child_cfg_t, get_traffic_selectors, linked_list_t*,
{
e1 = this->other_ts->create_enumerator(this->other_ts);
}
-
- /* no list supplied, just fetch the stored traffic selectors */
- if (supplied == NULL)
+ /* In a first step, replace "dynamic" TS with the host list */
+ while (e1->enumerate(e1, &ts1))
{
- DBG2(DBG_CFG, "proposing traffic selectors for %s:",
- local ? "us" : "other");
- while (e1->enumerate(e1, &ts1))
+ if (hosts && hosts->get_count(hosts) &&
+ ts1->is_dynamic(ts1))
{
- /* we make a copy of the TS, this allows us to update dynamic TS' */
- selected = ts1->clone(ts1);
- if (host)
+ e2 = hosts->create_enumerator(hosts);
+ while (e2->enumerate(e2, &host))
{
- selected->set_address(selected, host);
+ ts2 = ts1->clone(ts1);
+ ts2->set_address(ts2, host);
+ derived->insert_last(derived, ts2);
}
- DBG2(DBG_CFG, " %R (derived from %R)", selected, ts1);
- result->insert_last(result, selected);
+ e2->destroy(e2);
+ }
+ else
+ {
+ derived->insert_last(derived, ts1->clone(ts1));
+ }
+ }
+ e1->destroy(e1);
+
+ DBG2(DBG_CFG, "%s traffic selectors for %s:",
+ supplied ? "selecting" : "proposing", local ? "us" : "other");
+ if (supplied == NULL)
+ {
+ while (derived->remove_first(derived, (void**)&ts1) == SUCCESS)
+ {
+ DBG2(DBG_CFG, " %R", ts1);
+ result->insert_last(result, ts1);
}
- e1->destroy(e1);
}
else
{
- DBG2(DBG_CFG, "selecting traffic selectors for %s:",
- local ? "us" : "other");
- e2 = supplied->create_enumerator(supplied);
- /* iterate over all stored selectors */
- while (e1->enumerate(e1, &ts1))
+ e1 = supplied->create_enumerator(supplied);
+ /* enumerate all configured/derived selectors */
+ while (derived->remove_first(derived, (void**)&ts1) == SUCCESS)
{
- /* we make a copy of the TS, as we have to update dynamic TS' */
- ts1 = ts1->clone(ts1);
- if (host)
- {
- ts1->set_address(ts1, host);
- }
-
- /* iterate over all supplied traffic selectors */
- while (e2->enumerate(e2, &ts2))
+ /* enumerate all supplied traffic selectors */
+ while (e1->enumerate(e1, &ts2))
{
selected = ts1->get_subset(ts1, ts2);
if (selected)
@@ -299,13 +309,12 @@ METHOD(child_cfg_t, get_traffic_selectors, linked_list_t*,
ts1, ts2);
}
}
- e2->destroy(e2);
- e2 = supplied->create_enumerator(supplied);
+ supplied->reset_enumerator(supplied, e1);
ts1->destroy(ts1);
}
e1->destroy(e1);
- e2->destroy(e2);
}
+ derived->destroy(derived);
/* remove any redundant traffic selectors in the list */
e1 = result->create_enumerator(result);
@@ -320,16 +329,14 @@ METHOD(child_cfg_t, get_traffic_selectors, linked_list_t*,
{
result->remove_at(result, e2);
ts2->destroy(ts2);
- e1->destroy(e1);
- e1 = result->create_enumerator(result);
+ result->reset_enumerator(result, e1);
break;
}
if (ts1->is_contained_in(ts1, ts2))
{
result->remove_at(result, e1);
ts1->destroy(ts1);
- e2->destroy(e2);
- e2 = result->create_enumerator(result);
+ result->reset_enumerator(result, e2);
break;
}
}