diff options
Diffstat (limited to 'src/libcharon/config/child_cfg.c')
-rw-r--r-- | src/libcharon/config/child_cfg.c | 96 |
1 files changed, 60 insertions, 36 deletions
diff --git a/src/libcharon/config/child_cfg.c b/src/libcharon/config/child_cfg.c index 74949be3c..6fe7d44b8 100644 --- a/src/libcharon/config/child_cfg.c +++ b/src/libcharon/config/child_cfg.c @@ -165,12 +165,14 @@ METHOD(child_cfg_t, get_proposals, linked_list_t*, current = current->clone(current); if (strip_dh) { - current->strip_dh(current); + current->strip_dh(current, MODP_NONE); } proposals->insert_last(proposals, current); } enumerator->destroy(enumerator); + DBG2(DBG_CFG, "configured proposals: %#P", proposals); + return proposals; } @@ -192,7 +194,7 @@ METHOD(child_cfg_t, select_proposal, proposal_t*, { if (strip_dh) { - stored->strip_dh(stored); + stored->strip_dh(stored, MODP_NONE); } selected = stored->select(stored, supplied, private); if (selected) @@ -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,41 +255,47 @@ 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); } - e1->destroy(e1); + 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); + } + derived->destroy(derived); } else { - DBG2(DBG_CFG, "selecting traffic selectors for %s:", - local ? "us" : "other"); + e1 = derived->create_enumerator(derived); e2 = supplied->create_enumerator(supplied); - /* iterate over all stored selectors */ + /* enumerate all configured/derived selectors */ while (e1->enumerate(e1, &ts1)) { - /* 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 */ + /* enumerate all supplied traffic selectors */ while (e2->enumerate(e2, &ts2)) { selected = ts1->get_subset(ts1, ts2); @@ -299,12 +311,27 @@ METHOD(child_cfg_t, get_traffic_selectors, linked_list_t*, ts1, ts2); } } - e2->destroy(e2); - e2 = supplied->create_enumerator(supplied); - ts1->destroy(ts1); + supplied->reset_enumerator(supplied, e2); } e1->destroy(e1); e2->destroy(e2); + + /* check if we/peer did any narrowing, raise alert */ + e1 = derived->create_enumerator(derived); + e2 = result->create_enumerator(result); + while (e1->enumerate(e1, &ts1)) + { + if (!e2->enumerate(e2, &ts2) || !ts1->equals(ts1, ts2)) + { + charon->bus->alert(charon->bus, ALERT_TS_NARROWED, + local, result, this); + break; + } + } + e1->destroy(e1); + e2->destroy(e2); + + derived->destroy_offset(derived, offsetof(traffic_selector_t, destroy)); } /* remove any redundant traffic selectors in the list */ @@ -320,16 +347,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; } } @@ -566,4 +591,3 @@ child_cfg_t *child_cfg_create(char *name, lifetime_cfg_t *lifetime, return &this->public; } - |