summaryrefslogtreecommitdiff
path: root/src/libcharon/config
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcharon/config')
-rw-r--r--src/libcharon/config/backend_manager.c214
-rw-r--r--src/libcharon/config/backend_manager.h15
-rw-r--r--src/libcharon/config/child_cfg.c67
-rw-r--r--src/libcharon/config/child_cfg.h35
-rw-r--r--src/libcharon/config/ike_cfg.c24
-rw-r--r--src/libcharon/config/ike_cfg.h11
-rw-r--r--src/libcharon/config/peer_cfg.c83
-rw-r--r--src/libcharon/config/peer_cfg.h24
8 files changed, 372 insertions, 101 deletions
diff --git a/src/libcharon/config/backend_manager.c b/src/libcharon/config/backend_manager.c
index 02a41a5b3..47f62d59a 100644
--- a/src/libcharon/config/backend_manager.c
+++ b/src/libcharon/config/backend_manager.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2018 Tobias Brunner
* Copyright (C) 2007-2009 Martin Willi
* HSR Hochschule fuer Technik Rapperswil
*
@@ -129,15 +130,77 @@ static ike_cfg_match_t get_ike_match(ike_cfg_t *cand, host_t *me, host_t *other,
return match;
}
-METHOD(backend_manager_t, get_ike_cfg, ike_cfg_t*,
- private_backend_manager_t *this, host_t *me, host_t *other,
- ike_version_t version)
+/**
+ * list element to help sorting
+ */
+typedef struct {
+ ike_cfg_match_t match;
+ ike_cfg_t *cfg;
+} ike_match_entry_t;
+
+CALLBACK(ike_enum_filter, bool,
+ linked_list_t *configs, enumerator_t *orig, va_list args)
+{
+ ike_match_entry_t *entry;
+ ike_cfg_t **out;
+
+ VA_ARGS_VGET(args, out);
+
+ if (orig->enumerate(orig, &entry))
+ {
+ *out = entry->cfg;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+CALLBACK(ike_match_entry_list_destroy, void,
+ linked_list_t *configs)
+{
+ ike_match_entry_t *entry;
+
+ while (configs->remove_last(configs, (void**)&entry) == SUCCESS)
+ {
+ entry->cfg->destroy(entry->cfg);
+ free(entry);
+ }
+ configs->destroy(configs);
+}
+
+/**
+ * Insert entry into match-sorted list
+ */
+static void insert_sorted_ike(ike_match_entry_t *entry, linked_list_t *list)
+{
+ enumerator_t *enumerator;
+ ike_match_entry_t *current;
+
+ enumerator = list->create_enumerator(list);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ if (entry->match > current->match)
+ {
+ break;
+ }
+ }
+ list->insert_before(list, enumerator, entry);
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * Create a sorted list of all matching IKE configs
+ */
+static linked_list_t *get_matching_ike_cfgs(private_backend_manager_t *this,
+ host_t *me, host_t *other,
+ ike_version_t version)
{
- ike_cfg_t *current, *found = NULL;
+ ike_cfg_t *current;
char *my_addr, *other_addr;
enumerator_t *enumerator;
- ike_cfg_match_t match, best = MATCH_ANY;
ike_data_t *data;
+ linked_list_t *configs;
+ ike_cfg_match_t match;
+ ike_match_entry_t *entry;
INIT(data,
.this = this,
@@ -145,44 +208,82 @@ METHOD(backend_manager_t, get_ike_cfg, ike_cfg_t*,
.other = other,
);
- DBG2(DBG_CFG, "looking for an ike config for %H...%H", me, other);
+ configs = linked_list_create();
this->lock->read_lock(this->lock);
enumerator = enumerator_create_nested(
this->backends->create_enumerator(this->backends),
(void*)ike_enum_create, data, (void*)free);
- while (enumerator->enumerate(enumerator, (void**)&current))
+
+ while (enumerator->enumerate(enumerator, &current))
{
+ my_addr = current->get_my_addr(current);
+ other_addr = current->get_other_addr(current);
match = get_ike_match(current, me, other, version);
- DBG3(DBG_CFG, "ike config match: %d (%H %H %N)",
- match, me, other, ike_version_names, version);
+ DBG3(DBG_CFG, "ike config match: %d (%s...%s %N)", match, my_addr,
+ other_addr, ike_version_names, current->get_version(current));
+
if (match)
{
- my_addr = current->get_my_addr(current);
- other_addr = current->get_other_addr(current);
DBG2(DBG_CFG, " candidate: %s...%s, prio %d",
my_addr, other_addr, match);
- if (match > best)
- {
- DESTROY_IF(found);
- found = current;
- found->get_ref(found);
- best = match;
- }
+
+ INIT(entry,
+ .match = match,
+ .cfg = current->get_ref(current),
+ );
+ insert_sorted_ike(entry, configs);
}
}
enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
- if (found)
+
+ return configs;
+}
+
+METHOD(backend_manager_t, get_ike_cfg, ike_cfg_t*,
+ private_backend_manager_t *this, host_t *me, host_t *other,
+ ike_version_t version)
+{
+ linked_list_t *configs;
+ ike_match_entry_t *entry;
+ ike_cfg_t *found = NULL;
+ char *my_addr, *other_addr;
+
+ DBG2(DBG_CFG, "looking for an %N config for %H...%H", ike_version_names,
+ version, me, other);
+
+ configs = get_matching_ike_cfgs(this, me, other, version);
+ if (configs->get_first(configs, (void**)&entry) == SUCCESS)
{
+ found = entry->cfg->get_ref(entry->cfg);
+
my_addr = found->get_my_addr(found);
other_addr = found->get_other_addr(found);
DBG2(DBG_CFG, "found matching ike config: %s...%s with prio %d",
- my_addr, other_addr, best);
+ my_addr, other_addr, entry->match);
}
+ ike_match_entry_list_destroy(configs);
+
return found;
}
+METHOD(backend_manager_t, create_ike_cfg_enumerator, enumerator_t*,
+ private_backend_manager_t *this, host_t *me, host_t *other,
+ ike_version_t version)
+{
+ linked_list_t *configs;
+
+ DBG2(DBG_CFG, "looking for %N configs for %H...%H", ike_version_names,
+ version, me, other);
+
+ configs = get_matching_ike_cfgs(this, me, other, version);
+
+ return enumerator_create_filter(configs->create_enumerator(configs),
+ ike_enum_filter, configs,
+ ike_match_entry_list_destroy);
+}
+
/**
* Get the best ID match in one of the configs auth_cfg
*/
@@ -198,7 +299,7 @@ static id_match_t get_peer_match(identification_t *id,
if (!id)
{
- DBG3(DBG_CFG, "peer config match %s: %d (%N)",
+ DBG3(DBG_CFG, " %s id match: %d (%N)",
where, ID_MATCH_ANY, id_type_names, ID_ANY);
return ID_MATCH_ANY;
}
@@ -225,7 +326,7 @@ static id_match_t get_peer_match(identification_t *id,
enumerator->destroy(enumerator);
data = id->get_encoding(id);
- DBG3(DBG_CFG, "peer config match %s: %d (%N -> %#B)",
+ DBG3(DBG_CFG, " %s id match: %d (%N: %#B)",
where, match, id_type_names, id->get_type(id), &data);
return match;
}
@@ -295,34 +396,26 @@ CALLBACK(peer_enum_filter_destroy, void,
}
/**
- * Insert entry into match-sorted list, using helper
+ * Insert entry into match-sorted list
*/
-static void insert_sorted(match_entry_t *entry, linked_list_t *list,
- linked_list_t *helper)
+static void insert_sorted(match_entry_t *entry, linked_list_t *list)
{
+ enumerator_t *enumerator;
match_entry_t *current;
- while (list->remove_first(list, (void**)&current) == SUCCESS)
- {
- helper->insert_last(helper, current);
- }
- while (helper->remove_first(helper, (void**)&current) == SUCCESS)
+ enumerator = list->create_enumerator(list);
+ while (enumerator->enumerate(enumerator, &current))
{
- if (entry && (
- (entry->match_ike > current->match_ike &&
- entry->match_peer >= current->match_peer) ||
- (entry->match_ike >= current->match_ike &&
- entry->match_peer > current->match_peer)))
+ if ((entry->match_ike > current->match_ike &&
+ entry->match_peer >= current->match_peer) ||
+ (entry->match_ike >= current->match_ike &&
+ entry->match_peer > current->match_peer))
{
- list->insert_last(list, entry);
- entry = NULL;
+ break;
}
- list->insert_last(list, current);
- }
- if (entry)
- {
- list->insert_last(list, entry);
}
+ list->insert_before(list, enumerator, entry);
+ enumerator->destroy(enumerator);
}
METHOD(backend_manager_t, create_peer_cfg_enumerator, enumerator_t*,
@@ -332,7 +425,7 @@ METHOD(backend_manager_t, create_peer_cfg_enumerator, enumerator_t*,
enumerator_t *enumerator;
peer_data_t *data;
peer_cfg_t *cfg;
- linked_list_t *configs, *helper;
+ linked_list_t *configs;
INIT(data,
.lock = this->lock,
@@ -352,35 +445,46 @@ METHOD(backend_manager_t, create_peer_cfg_enumerator, enumerator_t*,
}
configs = linked_list_create();
- /* only once allocated helper list for sorting */
- helper = linked_list_create();
while (enumerator->enumerate(enumerator, &cfg))
{
- id_match_t match_peer_me, match_peer_other;
+ ike_cfg_t *ike_cfg = cfg->get_ike_cfg(cfg);
ike_cfg_match_t match_ike;
+ id_match_t match_peer_me, match_peer_other;
match_entry_t *entry;
+ char *my_addr, *other_addr;
+
+ match_ike = get_ike_match(ike_cfg, me, other, version);
+ my_addr = ike_cfg->get_my_addr(ike_cfg);
+ other_addr = ike_cfg->get_other_addr(ike_cfg);
+ DBG3(DBG_CFG, "peer config \"%s\", ike match: %d (%s...%s %N)",
+ cfg->get_name(cfg), match_ike, my_addr, other_addr,
+ ike_version_names, ike_cfg->get_version(ike_cfg));
+
+ if (!match_ike)
+ {
+ continue;
+ }
match_peer_me = get_peer_match(my_id, cfg, TRUE);
+ if (!match_peer_me)
+ {
+ continue;
+ }
match_peer_other = get_peer_match(other_id, cfg, FALSE);
- match_ike = get_ike_match(cfg->get_ike_cfg(cfg), me, other, version);
- DBG3(DBG_CFG, "ike config match: %d (%H %H %N)",
- match_ike, me, other, ike_version_names, version);
- if (match_peer_me && match_peer_other && match_ike)
+ if (match_peer_other)
{
DBG2(DBG_CFG, " candidate \"%s\", match: %d/%d/%d (me/other/ike)",
cfg->get_name(cfg), match_peer_me, match_peer_other, match_ike);
-
INIT(entry,
.match_peer = match_peer_me + match_peer_other,
.match_ike = match_ike,
.cfg = cfg->get_ref(cfg),
);
- insert_sorted(entry, configs, helper);
+ insert_sorted(entry, configs);
}
}
enumerator->destroy(enumerator);
- helper->destroy(helper);
return enumerator_create_filter(configs->create_enumerator(configs),
peer_enum_filter, configs,
@@ -430,8 +534,7 @@ METHOD(backend_manager_t, destroy, void,
}
/*
- * Described in header-file
-
+ * Described in header
*/
backend_manager_t *backend_manager_create()
{
@@ -440,6 +543,7 @@ backend_manager_t *backend_manager_create()
INIT(this,
.public = {
.get_ike_cfg = _get_ike_cfg,
+ .create_ike_cfg_enumerator = _create_ike_cfg_enumerator,
.get_peer_cfg_by_name = _get_peer_cfg_by_name,
.create_peer_cfg_enumerator = _create_peer_cfg_enumerator,
.add_backend = _add_backend,
diff --git a/src/libcharon/config/backend_manager.h b/src/libcharon/config/backend_manager.h
index 8ec79ce28..ada295f0d 100644
--- a/src/libcharon/config/backend_manager.h
+++ b/src/libcharon/config/backend_manager.h
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2018 Tobias Brunner
* Copyright (C) 2007 Martin Willi
* HSR Hochschule fuer Technik Rapperswil
*
@@ -64,6 +65,20 @@ struct backend_manager_t {
ike_version_t version);
/**
+ * Create an enumerator over all matching IKE configs.
+ *
+ * Pass NULL as parameters to match any. The enumerator enumerates over
+ * ike_cfgs, ordered by priority (best match first).
+ *
+ * @param me local address
+ * @param other remote address
+ * @param version IKE version to get a config for
+ * @return enumerator over ike_cfg
+ */
+ enumerator_t* (*create_ike_cfg_enumerator)(backend_manager_t *this,
+ host_t *me, host_t *other, ike_version_t version);
+
+ /**
* Get a peer_config identified by it's name.
*
* @param name name of the peer_config
diff --git a/src/libcharon/config/child_cfg.c b/src/libcharon/config/child_cfg.c
index bc417f936..14148ed03 100644
--- a/src/libcharon/config/child_cfg.c
+++ b/src/libcharon/config/child_cfg.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2017 Tobias Brunner
+ * Copyright (C) 2008-2018 Tobias Brunner
* Copyright (C) 2016 Andreas Steffen
* Copyright (C) 2005-2007 Martin Willi
* Copyright (C) 2005 Jan Hutter
@@ -124,6 +124,16 @@ struct private_child_cfg_t {
mark_t mark_out;
/**
+ * Optional mark to set to packets after inbound processing
+ */
+ mark_t set_mark_in;
+
+ /**
+ * Optional mark to set to packets after outbound processing
+ */
+ mark_t set_mark_out;
+
+ /**
* Traffic Flow Confidentiality padding, if enabled
*/
uint32_t tfc;
@@ -147,6 +157,11 @@ struct private_child_cfg_t {
* HW offload mode
*/
hw_offload_t hw_offload;
+
+ /**
+ * DS header field copy mode
+ */
+ dscp_copy_t copy_dscp;
};
METHOD(child_cfg_t, get_name, char*,
@@ -254,7 +269,7 @@ METHOD(child_cfg_t, select_proposal, proposal_t*,
{
DBG2(DBG_CFG, "received proposals: %#P", proposals);
DBG2(DBG_CFG, "configured proposals: %#P", this->proposals);
- DBG2(DBG_CFG, "selected proposal: %P", selected);
+ DBG1(DBG_CFG, "selected proposal: %P", selected);
break;
}
}
@@ -289,7 +304,7 @@ 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,
- linked_list_t *hosts)
+ linked_list_t *hosts, bool log)
{
enumerator_t *e1, *e2;
traffic_selector_t *ts1, *ts2, *selected;
@@ -334,13 +349,19 @@ METHOD(child_cfg_t, get_traffic_selectors, linked_list_t*,
}
e1->destroy(e1);
- DBG2(DBG_CFG, "%s traffic selectors for %s:",
- supplied ? "selecting" : "proposing", local ? "us" : "other");
- if (supplied == NULL)
+ 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)
{
- DBG2(DBG_CFG, " %R", ts1);
+ if (log)
+ {
+ DBG2(DBG_CFG, " %R", ts1);
+ }
result->insert_last(result, ts1);
}
derived->destroy(derived);
@@ -358,11 +379,14 @@ METHOD(child_cfg_t, get_traffic_selectors, linked_list_t*,
selected = ts1->get_subset(ts1, ts2);
if (selected)
{
- DBG2(DBG_CFG, " config: %R, received: %R => match: %R",
- ts1, ts2, selected);
+ if (log)
+ {
+ DBG2(DBG_CFG, " config: %R, received: %R => match: %R",
+ ts1, ts2, selected);
+ }
result->insert_last(result, selected);
}
- else
+ else if (log)
{
DBG2(DBG_CFG, " config: %R, received: %R => no match",
ts1, ts2);
@@ -478,6 +502,12 @@ METHOD(child_cfg_t, get_hw_offload, hw_offload_t,
return this->hw_offload;
}
+METHOD(child_cfg_t, get_copy_dscp, dscp_copy_t,
+ private_child_cfg_t *this)
+{
+ return this->copy_dscp;
+}
+
METHOD(child_cfg_t, get_dpd_action, action_t,
private_child_cfg_t *this)
{
@@ -527,6 +557,12 @@ METHOD(child_cfg_t, get_mark, mark_t,
return inbound ? this->mark_in : this->mark_out;
}
+METHOD(child_cfg_t, get_set_mark, mark_t,
+ private_child_cfg_t *this, bool inbound)
+{
+ return inbound ? this->set_mark_in : this->set_mark_out;
+}
+
METHOD(child_cfg_t, get_tfc, uint32_t,
private_child_cfg_t *this)
{
@@ -600,9 +636,15 @@ METHOD(child_cfg_t, equals, bool,
this->mark_in.mask == other->mark_in.mask &&
this->mark_out.value == other->mark_out.value &&
this->mark_out.mask == other->mark_out.mask &&
+ this->set_mark_in.value == other->set_mark_in.value &&
+ this->set_mark_in.mask == other->set_mark_in.mask &&
+ this->set_mark_out.value == other->set_mark_out.value &&
+ this->set_mark_out.mask == other->set_mark_out.mask &&
this->tfc == other->tfc &&
this->manual_prio == other->manual_prio &&
this->replay_window == other->replay_window &&
+ this->hw_offload == other->hw_offload &&
+ this->copy_dscp == other->copy_dscp &&
streq(this->updown, other->updown) &&
streq(this->interface, other->interface);
}
@@ -654,6 +696,7 @@ child_cfg_t *child_cfg_create(char *name, child_cfg_create_t *data)
.get_inactivity = _get_inactivity,
.get_reqid = _get_reqid,
.get_mark = _get_mark,
+ .get_set_mark = _get_set_mark,
.get_tfc = _get_tfc,
.get_manual_prio = _get_manual_prio,
.get_interface = _get_interface,
@@ -664,6 +707,7 @@ child_cfg_t *child_cfg_create(char *name, child_cfg_create_t *data)
.get_ref = _get_ref,
.destroy = _destroy,
.get_hw_offload = _get_hw_offload,
+ .get_copy_dscp = _get_copy_dscp,
},
.name = strdup(name),
.options = data->options,
@@ -675,6 +719,8 @@ child_cfg_t *child_cfg_create(char *name, child_cfg_create_t *data)
.close_action = data->close_action,
.mark_in = data->mark_in,
.mark_out = data->mark_out,
+ .set_mark_in = data->set_mark_in,
+ .set_mark_out = data->set_mark_out,
.lifetime = data->lifetime,
.inactivity = data->inactivity,
.tfc = data->tfc,
@@ -687,6 +733,7 @@ child_cfg_t *child_cfg_create(char *name, child_cfg_create_t *data)
.replay_window = lib->settings->get_int(lib->settings,
"%s.replay_window", DEFAULT_REPLAY_WINDOW, lib->ns),
.hw_offload = data->hw_offload,
+ .copy_dscp = data->copy_dscp,
);
return &this->public;
diff --git a/src/libcharon/config/child_cfg.h b/src/libcharon/config/child_cfg.h
index d566da3ec..e3b59e656 100644
--- a/src/libcharon/config/child_cfg.h
+++ b/src/libcharon/config/child_cfg.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2017 Tobias Brunner
+ * Copyright (C) 2008-2018 Tobias Brunner
* Copyright (C) 2016 Andreas Steffen
* Copyright (C) 2005-2007 Martin Willi
* Copyright (C) 2005 Jan Hutter
@@ -135,11 +135,13 @@ struct child_cfg_t {
* @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);
+ linked_list_t *hosts, bool log);
+
/**
* Get the updown script to run for the CHILD_SA.
*
@@ -190,6 +192,13 @@ struct child_cfg_t {
hw_offload_t (*get_hw_offload) (child_cfg_t *this);
/**
+ * Get the copy mode for the DS header field to use for the CHILD_SA.
+ *
+ * @return IP header copy mode
+ */
+ dscp_copy_t (*get_copy_dscp) (child_cfg_t *this);
+
+ /**
* Action to take if CHILD_SA gets closed.
*
* @return close action
@@ -218,7 +227,7 @@ struct child_cfg_t {
uint32_t (*get_reqid)(child_cfg_t *this);
/**
- * Optional mark for CHILD_SA.
+ * Optional mark to set on policies/SAs.
*
* @param inbound TRUE for inbound, FALSE for outbound
* @return mark
@@ -226,6 +235,14 @@ struct child_cfg_t {
mark_t (*get_mark)(child_cfg_t *this, bool inbound);
/**
+ * Optional mark the SAs should apply after processing packets.
+ *
+ * @param inbound TRUE for inbound, FALSE for outbound
+ * @return mark
+ */
+ mark_t (*get_set_mark)(child_cfg_t *this, bool inbound);
+
+ /**
* Get the TFC padding value to use for CHILD_SA.
*
* @return TFC padding, 0 to disable, -1 for MTU
@@ -317,6 +334,12 @@ enum child_cfg_option_t {
/** Set mark on inbound SAs */
OPT_MARK_IN_SA = (1<<6),
+
+ /** Disable copying the DF bit to the outer IPv4 header in tunnel mode */
+ OPT_NO_COPY_DF = (1<<7),
+
+ /** Disable copying the ECN header field in tunnel mode */
+ OPT_NO_COPY_ECN = (1<<8),
};
/**
@@ -331,6 +354,10 @@ struct child_cfg_create_t {
mark_t mark_in;
/** Optional outbound mark */
mark_t mark_out;
+ /** Optional inbound mark the SA should apply to traffic */
+ mark_t set_mark_in;
+ /** Optional outbound mark the SA should apply to traffic */
+ mark_t set_mark_out;
/** Mode to propose for CHILD_SA */
ipsec_mode_t mode;
/** TFC padding size, 0 to disable, -1 to pad to PMTU */
@@ -353,6 +380,8 @@ struct child_cfg_create_t {
char *updown;
/** HW offload mode */
hw_offload_t hw_offload;
+ /** How to handle the DS header field in tunnel mode */
+ dscp_copy_t copy_dscp;
};
/**
diff --git a/src/libcharon/config/ike_cfg.c b/src/libcharon/config/ike_cfg.c
index a73a5b5e2..357c4a73b 100644
--- a/src/libcharon/config/ike_cfg.c
+++ b/src/libcharon/config/ike_cfg.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2017 Tobias Brunner
+ * Copyright (C) 2012-2018 Tobias Brunner
* Copyright (C) 2005-2007 Martin Willi
* Copyright (C) 2005 Jan Hutter
* HSR Hochschule fuer Technik Rapperswil
@@ -309,6 +309,25 @@ METHOD(ike_cfg_t, get_proposals, linked_list_t*,
return proposals;
}
+METHOD(ike_cfg_t, has_proposal, bool,
+ private_ike_cfg_t *this, proposal_t *match, bool private)
+{
+ enumerator_t *enumerator;
+ proposal_t *proposal;
+
+ enumerator = this->proposals->create_enumerator(this->proposals);
+ while (enumerator->enumerate(enumerator, &proposal))
+ {
+ if (proposal->matches(proposal, match, private))
+ {
+ enumerator->destroy(enumerator);
+ return TRUE;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return FALSE;
+}
+
METHOD(ike_cfg_t, select_proposal, proposal_t*,
private_ike_cfg_t *this, linked_list_t *proposals, bool private,
bool prefer_self)
@@ -344,7 +363,7 @@ METHOD(ike_cfg_t, select_proposal, proposal_t*,
{
DBG2(DBG_CFG, "received proposals: %#P", proposals);
DBG2(DBG_CFG, "configured proposals: %#P", this->proposals);
- DBG2(DBG_CFG, "selected proposal: %P", selected);
+ DBG1(DBG_CFG, "selected proposal: %P", selected);
break;
}
}
@@ -618,6 +637,7 @@ ike_cfg_t *ike_cfg_create(ike_version_t version, bool certreq, bool force_encap,
.add_proposal = _add_proposal,
.get_proposals = _get_proposals,
.select_proposal = _select_proposal,
+ .has_proposal = _has_proposal,
.get_dh_group = _get_dh_group,
.equals = _equals,
.get_ref = _get_ref,
diff --git a/src/libcharon/config/ike_cfg.h b/src/libcharon/config/ike_cfg.h
index ac2deef70..49690c892 100644
--- a/src/libcharon/config/ike_cfg.h
+++ b/src/libcharon/config/ike_cfg.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2017 Tobias Brunner
+ * Copyright (C) 2012-2018 Tobias Brunner
* Copyright (C) 2005-2007 Martin Willi
* Copyright (C) 2005 Jan Hutter
* HSR Hochschule fuer Technik Rapperswil
@@ -180,6 +180,15 @@ struct ike_cfg_t {
bool private, bool prefer_self);
/**
+ * Check if the config has a matching proposal.
+ *
+ * @param match proposal to check
+ * @param private accept algorithms from a private range
+ * @return TRUE if a matching proposal is contained
+ */
+ bool(*has_proposal)(ike_cfg_t *this, proposal_t *match, bool private);
+
+ /**
* Should we send a certificate request in IKE_SA_INIT?
*
* @return certificate request sending policy
diff --git a/src/libcharon/config/peer_cfg.c b/src/libcharon/config/peer_cfg.c
index 29f067858..e7dfb5f62 100644
--- a/src/libcharon/config/peer_cfg.c
+++ b/src/libcharon/config/peer_cfg.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007-2017 Tobias Brunner
+ * Copyright (C) 2007-2018 Tobias Brunner
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2005 Jan Hutter
* HSR Hochschule fuer Technik Rapperswil
@@ -126,12 +126,12 @@ struct private_peer_cfg_t {
uint32_t over_time;
/**
- * DPD check intervall
+ * DPD check interval
*/
uint32_t dpd;
/**
- * DPD timeout intervall (used for IKEv1 only)
+ * DPD timeout interval (used for IKEv1 only)
*/
uint32_t dpd_timeout;
@@ -155,6 +155,16 @@ struct private_peer_cfg_t {
*/
linked_list_t *remote_auth;
+ /**
+ * PPK ID
+ */
+ identification_t *ppk_id;
+
+ /**
+ * Whether a PPK is required
+ */
+ bool ppk_required;
+
#ifdef ME
/**
* Is this a mediation connection?
@@ -258,48 +268,44 @@ METHOD(peer_cfg_t, replace_child_cfgs, enumerator_t*,
private_peer_cfg_t *this, peer_cfg_t *other_pub)
{
private_peer_cfg_t *other = (private_peer_cfg_t*)other_pub;
- linked_list_t *removed, *added;
+ linked_list_t *new_cfgs, *removed, *added;
enumerator_t *mine, *others;
child_cfg_t *my_cfg, *other_cfg;
child_cfgs_replace_enumerator_t *enumerator;
bool found;
- removed = linked_list_create();
+ added = linked_list_create();
other->lock->read_lock(other->lock);
- added = linked_list_create_from_enumerator(
+ new_cfgs = linked_list_create_from_enumerator(
other->child_cfgs->create_enumerator(other->child_cfgs));
- added->invoke_offset(added, offsetof(child_cfg_t, get_ref));
+ new_cfgs->invoke_offset(new_cfgs, offsetof(child_cfg_t, get_ref));
other->lock->unlock(other->lock);
this->lock->write_lock(this->lock);
- others = added->create_enumerator(added);
- mine = this->child_cfgs->create_enumerator(this->child_cfgs);
- while (mine->enumerate(mine, &my_cfg))
+ removed = this->child_cfgs;
+ this->child_cfgs = new_cfgs;
+ others = new_cfgs->create_enumerator(new_cfgs);
+ mine = removed->create_enumerator(removed);
+ while (others->enumerate(others, &other_cfg))
{
found = FALSE;
- while (others->enumerate(others, &other_cfg))
+ while (mine->enumerate(mine, &my_cfg))
{
if (my_cfg->equals(my_cfg, other_cfg))
{
- added->remove_at(added, others);
- other_cfg->destroy(other_cfg);
+ removed->remove_at(removed, mine);
+ my_cfg->destroy(my_cfg);
found = TRUE;
break;
}
}
- added->reset_enumerator(added, others);
+ removed->reset_enumerator(removed, mine);
if (!found)
{
- this->child_cfgs->remove_at(this->child_cfgs, mine);
- removed->insert_last(removed, my_cfg);
+ added->insert_last(added, other_cfg->get_ref(other_cfg));
}
}
- while (others->enumerate(others, &other_cfg))
- {
- this->child_cfgs->insert_last(this->child_cfgs,
- other_cfg->get_ref(other_cfg));
- }
others->destroy(others);
mine->destroy(mine);
this->lock->unlock(this->lock);
@@ -379,7 +385,7 @@ static int get_ts_match(child_cfg_t *cfg, bool local,
int match = 0, round;
/* fetch configured TS list, narrowing dynamic TS */
- cfg_list = cfg->get_traffic_selectors(cfg, local, NULL, hosts);
+ cfg_list = cfg->get_traffic_selectors(cfg, local, NULL, hosts, TRUE);
/* use a round counter to rate leading TS with higher priority */
round = sup_list->get_count(sup_list);
@@ -581,6 +587,18 @@ METHOD(peer_cfg_t, create_auth_cfg_enumerator, enumerator_t*,
return this->remote_auth->create_enumerator(this->remote_auth);
}
+METHOD(peer_cfg_t, get_ppk_id, identification_t*,
+ private_peer_cfg_t *this)
+{
+ return this->ppk_id;
+}
+
+METHOD(peer_cfg_t, ppk_required, bool,
+ private_peer_cfg_t *this)
+{
+ return this->ppk_required;
+}
+
#ifdef ME
METHOD(peer_cfg_t, is_mediation, bool,
private_peer_cfg_t *this)
@@ -655,6 +673,14 @@ static bool auth_cfg_equal(private_peer_cfg_t *this, private_peer_cfg_t *other)
return equal;
}
+/**
+ * Check if two identities are equal, or both are not set
+ */
+static bool id_equal(identification_t *this, identification_t *other)
+{
+ return this == other || (this && other && this->equals(this, other));
+}
+
METHOD(peer_cfg_t, equals, bool,
private_peer_cfg_t *this, private_peer_cfg_t *other)
{
@@ -688,13 +714,13 @@ METHOD(peer_cfg_t, equals, bool,
this->dpd == other->dpd &&
this->aggressive == other->aggressive &&
this->pull_mode == other->pull_mode &&
- auth_cfg_equal(this, other)
+ auth_cfg_equal(this, other) &&
+ this->ppk_required == other->ppk_required &&
+ id_equal(this->ppk_id, other->ppk_id)
#ifdef ME
&& this->mediation == other->mediation &&
streq(this->mediated_by, other->mediated_by) &&
- (this->peer_id == other->peer_id ||
- (this->peer_id && other->peer_id &&
- this->peer_id->equals(this->peer_id, other->peer_id)))
+ id_equal(this->peer_id, other->peer_id)
#endif /* ME */
);
}
@@ -724,6 +750,7 @@ METHOD(peer_cfg_t, destroy, void,
DESTROY_IF(this->peer_id);
free(this->mediated_by);
#endif /* ME */
+ DESTROY_IF(this->ppk_id);
this->lock->destroy(this->lock);
free(this->name);
free(this);
@@ -778,6 +805,8 @@ peer_cfg_t *peer_cfg_create(char *name, ike_cfg_t *ike_cfg,
.create_pool_enumerator = _create_pool_enumerator,
.add_auth_cfg = _add_auth_cfg,
.create_auth_cfg_enumerator = _create_auth_cfg_enumerator,
+ .get_ppk_id = _get_ppk_id,
+ .ppk_required = _ppk_required,
.equals = (void*)_equals,
.get_ref = _get_ref,
.destroy = _destroy,
@@ -803,6 +832,8 @@ peer_cfg_t *peer_cfg_create(char *name, ike_cfg_t *ike_cfg,
.pull_mode = !data->push_mode,
.dpd = data->dpd,
.dpd_timeout = data->dpd_timeout,
+ .ppk_id = data->ppk_id,
+ .ppk_required = data->ppk_required,
.vips = linked_list_create(),
.pools = linked_list_create(),
.local_auth = linked_list_create(),
diff --git a/src/libcharon/config/peer_cfg.h b/src/libcharon/config/peer_cfg.h
index 6074a7cd4..49c4d1492 100644
--- a/src/libcharon/config/peer_cfg.h
+++ b/src/libcharon/config/peer_cfg.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007-2017 Tobias Brunner
+ * Copyright (C) 2007-2018 Tobias Brunner
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2005 Jan Hutter
* HSR Hochschule fuer Technik Rapperswil
@@ -157,11 +157,9 @@ struct peer_cfg_t {
/**
* Replace the CHILD configs with those in the given PEER config.
*
- * Configs that are equal are not replaced.
- *
* The enumerator enumerates the removed and added CHILD configs
* (child_cfg_t*, bool), where the flag is FALSE for removed configs and
- * TRUE for added configs.
+ * TRUE for added configs. Configs that are equal are not enumerated.
*
* @param other other config to get CHILD configs from
* @return an enumerator over removed/added CHILD configs
@@ -313,6 +311,20 @@ struct peer_cfg_t {
*/
enumerator_t* (*create_pool_enumerator)(peer_cfg_t *this);
+ /**
+ * Get the PPK ID to use with this peer.
+ *
+ * @return PPK id
+ */
+ identification_t *(*get_ppk_id)(peer_cfg_t *this);
+
+ /**
+ * Whether a PPK is required with this peer.
+ *
+ * @return TRUE, if a PPK is required
+ */
+ bool (*ppk_required)(peer_cfg_t *this);
+
#ifdef ME
/**
* Is this a mediation connection?
@@ -395,6 +407,10 @@ struct peer_cfg_create_t {
uint32_t dpd;
/** DPD timeout interval (IKEv1 only), if 0 default applies */
uint32_t dpd_timeout;
+ /** Postquantum Preshared Key ID (adopted) */
+ identification_t *ppk_id;
+ /** TRUE if a PPK is required, FALSE if it's optional */
+ bool ppk_required;
#ifdef ME
/** TRUE if this is a mediation connection */
bool mediation;