}
}
-METHOD(child_cfg_t, get_traffic_selectors, linked_list_t*,
- private_child_cfg_t *this, bool local, linked_list_t *supplied,
- linked_list_t *hosts, bool log)
+/**
+ * Create a copy of the traffic selectors in the given list, while resolving
+ * "dynamic" traffic selectors using the given hosts, if any. When not narrowing
+ * as initiator, we also replace TS in transport mode.
+ */
+static linked_list_t *resolve_dynamic_ts(private_child_cfg_t *this,
+ linked_list_t *list,
+ linked_list_t *hosts,
+ bool narrowing)
{
enumerator_t *e1, *e2;
- traffic_selector_t *ts1, *ts2, *selected;
- linked_list_t *result, *derived;
+ traffic_selector_t *ts1, *ts2;
+ linked_list_t *result;
host_t *host;
+ bool transport_mode;
- result = linked_list_create();
- derived = linked_list_create();
- if (local)
+ if (!hosts || !hosts->get_count(hosts))
{
- e1 = this->my_ts->create_enumerator(this->my_ts);
+ return list->clone_offset(list, offsetof(traffic_selector_t, clone));
}
- else
+ transport_mode = !narrowing && this->mode == MODE_TRANSPORT &&
+ !has_option(this, OPT_PROXY_MODE);
+
+ result = linked_list_create();
+ e1 = list->create_enumerator(list);
+ while (e1->enumerate(e1, &ts1))
{
- e1 = this->other_ts->create_enumerator(this->other_ts);
+ /* set hosts if TS is dynamic or as initiator in transport mode */
+ bool dynamic = ts1->is_dynamic(ts1);
+ if (!dynamic && !transport_mode)
+ {
+ result->insert_last(result, ts1->clone(ts1));
+ continue;
+ }
+ e2 = hosts->create_enumerator(hosts);
+ while (e2->enumerate(e2, &host))
+ {
+ if (!dynamic && !host->is_anyaddr(host) &&
+ !ts1->includes(ts1, host))
+ { /* for transport mode, we skip TS that don't match
+ * specific IPs */
+ continue;
+ }
+ ts2 = ts1->clone(ts1);
+ if (dynamic || !host->is_anyaddr(host))
+ { /* don't make regular TS larger than they were */
+ ts2->set_address(ts2, host);
+ }
+ result->insert_last(result, ts2);
+ }
+ e2->destroy(e2);
}
- /* in a first step, replace "dynamic" TS with the host list */
+ e1->destroy(e1);
+ return result;
+}
+
+/**
+ * Remove duplicate traffic selectors in the given list.
+ */
+static void remove_duplicate_ts(linked_list_t *list)
+{
+ enumerator_t *e1, *e2;
+ traffic_selector_t *ts1, *ts2;
+
+ e1 = list->create_enumerator(list);
+ e2 = list->create_enumerator(list);
while (e1->enumerate(e1, &ts1))
{
- if (hosts && hosts->get_count(hosts))
- { /* set hosts if TS is dynamic or as initiator in transport mode */
- bool dynamic = ts1->is_dynamic(ts1),
- proxy_mode = has_option(this, OPT_PROXY_MODE);
- if (dynamic || (this->mode == MODE_TRANSPORT && !proxy_mode &&
- !supplied))
+ while (e2->enumerate(e2, &ts2))
+ {
+ if (ts1 != ts2)
{
- e2 = hosts->create_enumerator(hosts);
- while (e2->enumerate(e2, &host))
+ if (ts2->is_contained_in(ts2, ts1))
{
- if (!dynamic && !host->is_anyaddr(host) &&
- !ts1->includes(ts1, host))
- { /* for transport mode, we skip TS that don't match
- * specific IPs */
- continue;
- }
- ts2 = ts1->clone(ts1);
- if (dynamic || !host->is_anyaddr(host))
- { /* don't make regular TS larger than they were */
- ts2->set_address(ts2, host);
- }
- derived->insert_last(derived, ts2);
+ list->remove_at(list, e2);
+ ts2->destroy(ts2);
+ list->reset_enumerator(list, e1);
+ break;
+ }
+ if (ts1->is_contained_in(ts1, ts2))
+ {
+ list->remove_at(list, e1);
+ ts1->destroy(ts1);
+ break;
}
- e2->destroy(e2);
- continue;
}
}
- derived->insert_last(derived, ts1->clone(ts1));
+ list->reset_enumerator(list, e2);
}
e1->destroy(e1);
+ e2->destroy(e2);
+}
+
+METHOD(child_cfg_t, get_traffic_selectors, linked_list_t*,
+ private_child_cfg_t *this, bool local, linked_list_t *hosts)
+{
+ linked_list_t *result;
+
+ result = resolve_dynamic_ts(this, local ? this->my_ts : this->other_ts,
+ hosts, FALSE);
+ remove_duplicate_ts(result);
+ return result;
+}
+
+METHOD(child_cfg_t, select_traffic_selectors, linked_list_t*,
+ 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 *resolved, *result;
+
+ result = linked_list_create();
+ resolved = resolve_dynamic_ts(this, local ? this->my_ts : this->other_ts,
+ hosts, supplied);
+
+ DBG2(DBG_CFG, "%s traffic selectors for %s:",
+ supplied ? "selecting" : "proposing", local ? "us" : "other");
- if (log)
- {
- DBG2(DBG_CFG, "%s traffic selectors for %s:",
- supplied ? "selecting" : "proposing", local ? "us" : "other");
- }
if (!supplied)
{
- while (derived->remove_first(derived, (void**)&ts1) == SUCCESS)
+ while (resolved->remove_first(resolved, (void**)&ts1) == SUCCESS)
{
- if (log)
- {
- DBG2(DBG_CFG, " %R", ts1);
- }
+ DBG2(DBG_CFG, " %R", ts1);
result->insert_last(result, ts1);
}
- derived->destroy(derived);
}
else
{
- e1 = derived->create_enumerator(derived);
+ e1 = resolved->create_enumerator(resolved);
e2 = supplied->create_enumerator(supplied);
- /* enumerate all configured/derived selectors */
+ /* enumerate all configured/resolved selectors */
while (e1->enumerate(e1, &ts1))
{
/* enumerate all supplied traffic selectors */
selected = ts1->get_subset(ts1, ts2);
if (selected)
{
- if (log)
- {
- DBG2(DBG_CFG, " config: %R, received: %R => match: %R",
- ts1, ts2, selected);
- }
+ DBG2(DBG_CFG, " config: %R, received: %R => match: %R",
+ ts1, ts2, selected);
result->insert_last(result, selected);
}
- else if (log)
+ else
{
DBG2(DBG_CFG, " config: %R, received: %R => no match",
ts1, ts2);
e2->destroy(e2);
/* check if we/peer did any narrowing, raise alert */
- e1 = derived->create_enumerator(derived);
+ e1 = resolved->create_enumerator(resolved);
e2 = result->create_enumerator(result);
while (e1->enumerate(e1, &ts1))
{
e1->destroy(e1);
e2->destroy(e2);
- derived->destroy_offset(derived, offsetof(traffic_selector_t, destroy));
- }
-
- /* remove any redundant traffic selectors in the list */
- e1 = result->create_enumerator(result);
- e2 = result->create_enumerator(result);
- while (e1->enumerate(e1, &ts1))
- {
- while (e2->enumerate(e2, &ts2))
- {
- if (ts1 != ts2)
- {
- if (ts2->is_contained_in(ts2, ts1))
- {
- result->remove_at(result, e2);
- ts2->destroy(ts2);
- result->reset_enumerator(result, e1);
- break;
- }
- if (ts1->is_contained_in(ts1, ts2))
- {
- result->remove_at(result, e1);
- ts1->destroy(ts1);
- break;
- }
- }
- }
- result->reset_enumerator(result, e2);
}
- e1->destroy(e1);
- e2->destroy(e2);
-
+ resolved->destroy_offset(resolved, offsetof(traffic_selector_t, destroy));
+ remove_duplicate_ts(result);
return result;
}
.get_name = _get_name,
.add_traffic_selector = _add_traffic_selector,
.get_traffic_selectors = _get_traffic_selectors,
+ .select_traffic_selectors = _select_traffic_selectors,
.add_proposal = _add_proposal,
.get_proposals = _get_proposals,
.select_proposal = _select_proposal,
traffic_selector_t *ts);
/**
- * Get a list of traffic selectors to use for the CHILD_SA.
+ * Get a list of configured traffic selectors to use for the CHILD_SA.
*
* The config contains two set of traffic selectors, one for the local
* side, one for the remote side.
+ *
+ * Some traffic selectors may be "dynamic", meaning they are narrowed down
+ * to a specific address (host-to-host or virtual-IP setups). Use the
+ * "hosts" parameter to narrow such traffic selectors to an address.
+ *
+ * Returned list and its traffic selectors must be destroyed after use.
+ *
+ * Note that this method does not log anything. If logging is required, use
+ * select_traffic_selectors() without passing supplied traffic selectors.
+ *
+ * @param local TRUE for TS on local side, FALSE for remote
+ * @param hosts addresses to use for narrowing "dynamic" TS', host_t
+ * @return list containing the traffic selectors
+ */
+ linked_list_t *(*get_traffic_selectors)(child_cfg_t *this, bool local,
+ linked_list_t *hosts);
+
+ /**
+ * Select a list of traffic selectors to use for the CHILD_SA.
+ *
+ * The config contains two set of traffic selectors, one for the local
+ * side, one for the remote side.
+ *
* If a list with traffic selectors is supplied, these are used to narrow
- * down the traffic selector list to the greatest common divisor.
- * Some traffic selector may be "dynamic", meaning they are narrowed down
- * to a specific address (host-to-host or virtual-IP setups). Use
- * the "host" parameter to narrow such traffic selectors to that address.
- * Resulted list and its traffic selectors must be destroyed after use.
+ * down the traffic selector list to the greatest common subset.
+ *
+ * Some traffic selectors may be "dynamic", meaning they are narrowed down
+ * to a specific address (host-to-host or virtual-IP setups). Use the
+ * "hosts" parameter to narrow such traffic selectors to an address.
+ *
+ * Returned list and its traffic selectors must be destroyed after use.
*
* @param local TRUE for TS on local side, FALSE for remote
* @param supplied list with TS to select from, or NULL
* @param hosts addresses to use for narrowing "dynamic" TS', host_t
- * @param log FALSE to avoid logging details about the selection
* @return list containing the traffic selectors
*/
- linked_list_t *(*get_traffic_selectors)(child_cfg_t *this, bool local,
- linked_list_t *supplied,
- linked_list_t *hosts, bool log);
+ linked_list_t *(*select_traffic_selectors)(child_cfg_t *this, bool local,
+ linked_list_t *supplied,
+ linked_list_t *hosts);
/**
* Get the updown script to run for the CHILD_SA.
}
/* fetch configured TS list, narrowing dynamic TS */
- cfg_list = cfg->get_traffic_selectors(cfg, local, NULL, hosts, TRUE);
+ cfg_list = cfg->select_traffic_selectors(cfg, local, NULL, hosts);
/* use a round counter to rate leading TS with higher priority */
round = sup_list->get_count(sup_list);
xmlTextWriterStartElement(writer, "childconfig");
xmlTextWriterWriteElement(writer, "name",
child_cfg->get_name(child_cfg));
- list = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL,
- NULL, FALSE);
+ list = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL);
write_networks(writer, "local", list);
list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
- list = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL,
- NULL, FALSE);
+ list = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL);
write_networks(writer, "remote", list);
list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
xmlTextWriterEndElement(writer);
children = peer_cfg->create_child_cfg_enumerator(peer_cfg);
while (children->enumerate(children, &child_cfg))
{
- my_ts = child_cfg->get_traffic_selectors(child_cfg, TRUE,
- NULL, NULL, FALSE);
+ my_ts = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL);
other_ts = child_cfg->get_traffic_selectors(child_cfg, FALSE,
- NULL, NULL, FALSE);
+ NULL);
fprintf(out, "%12s: child: %#R === %#R %N",
child_cfg->get_name(child_cfg), my_ts, other_ts,
ipsec_mode_names, child_cfg->get_mode(child_cfg));
fprintf(out, "Shunted Connections:\n");
first = FALSE;
}
- my_ts = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL,
- NULL, FALSE);
- other_ts = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL,
- NULL, FALSE);
+ my_ts = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL);
+ other_ts = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL);
fprintf(out, "%12s: %#R === %#R %N\n",
child_cfg->get_name(child_cfg), my_ts, other_ts,
ipsec_mode_names, child_cfg->get_mode(child_cfg));
received = linked_list_create();
received->insert_last(received, ts);
- selected = cfg->get_traffic_selectors(cfg, FALSE, received, NULL, FALSE);
+ selected = cfg->select_traffic_selectors(cfg, FALSE, received, NULL);
while (selected->remove_first(selected, (void**)&ts) == SUCCESS)
{
list->insert_last(list, ts);
{
ts->destroy(ts);
}
- configured = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, NULL,
- FALSE);
+ configured = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL);
while (configured->remove_first(configured, (void**)&ts) == SUCCESS)
{
enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg);
while (enumerator->enumerate(enumerator, &child_cfg))
{
- current = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, NULL,
- FALSE);
+ current = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL);
while (current->remove_first(current, (void**)&ts) == SUCCESS)
{
if (use_ts(ts))
list_label(b, NULL, cfg);
b->begin_list(b, "local-ts");
- list = cfg->get_traffic_selectors(cfg, TRUE, NULL, NULL, FALSE);
+ list = cfg->get_traffic_selectors(cfg, TRUE, NULL);
enumerator = list->create_enumerator(list);
while (enumerator->enumerate(enumerator, &ts))
{
b->end_list(b /* local-ts */);
b->begin_list(b, "remote-ts");
- list = cfg->get_traffic_selectors(cfg, FALSE, NULL, NULL, FALSE);
+ list = cfg->get_traffic_selectors(cfg, FALSE, NULL);
enumerator = list->create_enumerator(list);
while (enumerator->enumerate(enumerator, &ts))
{
child_cfg->get_close_action(child_cfg));
b->begin_list(b, "local-ts");
- list = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL,
- NULL, FALSE);
+ list = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL);
selectors = list->create_enumerator(list);
while (selectors->enumerate(selectors, &ts))
{
b->end_list(b /* local-ts */);
b->begin_list(b, "remote-ts");
- list = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL,
- NULL, FALSE);
+ list = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL);
selectors = list->create_enumerator(list);
while (selectors->enumerate(selectors, &ts))
{
traffic_selector_t *ts;
list = linked_list_create_with_items(ike, NULL);
- ts_list = config->get_traffic_selectors(config, local, NULL, list, FALSE);
+ ts_list = config->get_traffic_selectors(config, local, list);
list->destroy(list);
enumerator = ts_list->create_enumerator(ts_list);
linked_list_t *list, *hosts;
hosts = get_dynamic_hosts(this->ike_sa, local);
- list = this->config->get_traffic_selectors(this->config,
- local, supplied, hosts, TRUE);
+ list = this->config->select_traffic_selectors(this->config, local,
+ supplied, hosts);
hosts->destroy(hosts);
if (list->get_first(list, (void**)&ts) == SUCCESS)
{
this->ike_sa->has_condition(this->ike_sa, cond))
{
nat = get_transport_nat_ts(this, local, in);
- ts = this->config->get_traffic_selectors(this->config, local, nat,
- hosts, TRUE);
+ ts = this->config->select_traffic_selectors(this->config, local, nat,
+ hosts);
nat->destroy_offset(nat, offsetof(traffic_selector_t, destroy));
}
else
{
- ts = this->config->get_traffic_selectors(this->config, local, in,
- hosts, TRUE);
+ ts = this->config->select_traffic_selectors(this->config, local, in,
+ hosts);
}
hosts->destroy(hosts);
}
if (list->get_count(list))
{
- this->tsi = this->config->get_traffic_selectors(this->config,
- TRUE, NULL, list, TRUE);
+ this->tsi = this->config->select_traffic_selectors(this->config, TRUE,
+ NULL, list);
list->destroy_offset(list, offsetof(host_t, destroy));
}
else
{ /* no virtual IPs configured */
list->destroy(list);
list = ike_sa_get_dynamic_hosts(this->ike_sa, TRUE);
- this->tsi = this->config->get_traffic_selectors(this->config,
- TRUE, NULL, list, TRUE);
+ this->tsi = this->config->select_traffic_selectors(this->config, TRUE,
+ NULL, list);
list->destroy(list);
}
list = ike_sa_get_dynamic_hosts(this->ike_sa, FALSE);
- this->tsr = this->config->get_traffic_selectors(this->config,
- FALSE, NULL, list, TRUE);
+ this->tsr = this->config->select_traffic_selectors(this->config, FALSE,
+ NULL, list);
list->destroy(list);
if (this->packet_tsi)
host_any6 = host_create_any(AF_INET6);
hosts = linked_list_create_with_items(host_any, host_any6, NULL);
- my_ts_list = child->get_traffic_selectors(child, TRUE, NULL, hosts,
- FALSE);
- other_ts_list = child->get_traffic_selectors(child, FALSE, NULL, hosts,
- FALSE);
+ my_ts_list = child->get_traffic_selectors(child, TRUE, hosts);
+ other_ts_list = child->get_traffic_selectors(child, FALSE, hosts);
hosts->destroy(hosts);
manual_prio = child->get_manual_prio(child);
host_any6 = host_create_any(AF_INET6);
hosts = linked_list_create_with_items(host_any, host_any6, NULL);
- my_ts_list = child->get_traffic_selectors(child, TRUE, NULL, hosts,
- FALSE);
- other_ts_list = child->get_traffic_selectors(child, FALSE, NULL, hosts,
- FALSE);
+ my_ts_list = child->get_traffic_selectors(child, TRUE, hosts);
+ other_ts_list = child->get_traffic_selectors(child, FALSE, hosts);
hosts->destroy(hosts);
manual_prio = child->get_manual_prio(child);
traffic_selector_t *ts;
bool found = FALSE;
- other_ts = child->get_traffic_selectors(child, FALSE, NULL, NULL, FALSE);
+ other_ts = child->get_traffic_selectors(child, FALSE, NULL);
enumerator = other_ts->create_enumerator(other_ts);
while (enumerator->enumerate(enumerator, &ts))
{
child = child_sa->get_config(child_sa);
- my_ts = child->get_traffic_selectors(child, TRUE, NULL, local, FALSE);
- other_ts = child->get_traffic_selectors(child, FALSE, NULL, remote, FALSE);
+ my_ts = child->get_traffic_selectors(child, TRUE, local);
+ other_ts = child->get_traffic_selectors(child, FALSE, remote);
/* we don't know the finally negotiated protocol (ESP|AH), we install
* the SA with the protocol of the first proposal */