Merge branch 'vici-proposals'

Adds IKE and IPsec proposals to the `list-conn` VICI event.  Currently
not printed in `swanctl --list-conns` to keep the output compact (`--raw`
can be used to see the proposals).

Closes strongswan/strongswan#3067
This commit is contained in:
Tobias Brunner
2026-05-28 16:27:37 +02:00
12 changed files with 125 additions and 18 deletions
+5 -3
View File
@@ -216,7 +216,7 @@ CALLBACK(match_proposal, bool,
}
METHOD(child_cfg_t, get_proposals, linked_list_t*,
private_child_cfg_t *this, bool strip_ke)
private_child_cfg_t *this, bool strip_ke, bool log)
{
enumerator_t *enumerator;
proposal_t *current;
@@ -241,8 +241,10 @@ METHOD(child_cfg_t, get_proposals, linked_list_t*,
}
enumerator->destroy(enumerator);
DBG2(DBG_CFG, "configured proposals: %#P", proposals);
if (log)
{
DBG2(DBG_CFG, "configured proposals: %#P", proposals);
}
return proposals;
}
+2 -1
View File
@@ -91,9 +91,10 @@ struct child_cfg_t {
* Resulting list and all of its proposals must be freed after use.
*
* @param strip_ke TRUE strip out key exchange methods
* @param log whether to log the configured proposals
* @return list of proposals
*/
linked_list_t* (*get_proposals)(child_cfg_t *this, bool strip_ke);
linked_list_t* (*get_proposals)(child_cfg_t *this, bool strip_ke, bool log);
/**
* Select a proposal from a supplied list.
+5 -3
View File
@@ -318,7 +318,7 @@ METHOD(ike_cfg_t, add_proposal, void,
}
METHOD(ike_cfg_t, get_proposals, linked_list_t*,
private_ike_cfg_t *this)
private_ike_cfg_t *this, bool log)
{
enumerator_t *enumerator;
proposal_t *current;
@@ -333,8 +333,10 @@ METHOD(ike_cfg_t, get_proposals, linked_list_t*,
}
enumerator->destroy(enumerator);
DBG2(DBG_CFG, "configured proposals: %#P", proposals);
if (log)
{
DBG2(DBG_CFG, "configured proposals: %#P", proposals);
}
return proposals;
}
+2 -1
View File
@@ -178,9 +178,10 @@ struct ike_cfg_t {
*
* Returned list and its proposals must be destroyed after use.
*
* @param log whether to log the configured proposals
* @return list containing all the proposals
*/
linked_list_t* (*get_proposals) (ike_cfg_t *this);
linked_list_t *(*get_proposals)(ike_cfg_t *this, bool log);
/**
* Select a proposal from a list of supplied proposals.
+18 -1
View File
@@ -893,7 +893,18 @@ _list-conns_ command.
version = <IKE version as string, IKEv1|IKEv2 or 0 for any>
reauth_time = <IKE_SA reauthentication interval in seconds>
rekey_time = <IKE_SA rekeying interval in seconds>
proposals = { # numbered (zero-based) sub-sections for IKE proposal
<num> = { # lists with NAME[_KEYSIZE] for each transform type in proposal
encr = [ <list of encryption algorithms> ]
integ = [ <list of integrity algorithms> ]
prf = [ <list of pseudo random functions> ]
ke = [ <list of key exchange methods> ]
ake1 = [ <list of first additional key exchange methods> ]
...
ake7 = [ <list fo seventh additional key exchange methods> ]
sn = [ <list of sequence number transforms> ]
}
}
local*, remote* = { # multiple local and remote auth sections
class = <authentication type>
eap-type = <EAP type to authenticate if when using EAP>
@@ -921,6 +932,12 @@ _list-conns_ command.
rekey_time = <CHILD_SA rekeying interval in seconds>
rekey_bytes = <CHILD_SA rekeying interval in bytes>
rekey_packets = <CHILD_SA rekeying interval in packets>
esp_proposals = {
<sub-sections for ESP proposals, see above for details>
}
ah_proposals = {
<sub-sections for AH proposals, see above for details>
}
local-ts = [
<list of local traffic selectors>
]
+84
View File
@@ -208,6 +208,81 @@ static void list_label(vici_builder_t *b, child_sa_t *child, child_cfg_t *cfg)
}
}
/**
* Print all algorithms of the given type
*/
static void list_transforms(vici_builder_t *b, proposal_t *proposal, char *name,
transform_type_t type)
{
enumerator_t *enumerator;
enum_name_t *names;
char buf[BUF_LEN];
uint16_t alg, ks;
bool first = TRUE;
names = transform_get_enum_names(type);
enumerator = proposal->create_enumerator(proposal, type);
while (enumerator->enumerate(enumerator, &alg, &ks))
{
if (first)
{
b->begin_list(b, name);
first = FALSE;
}
buf[0] = '\0';
if (ks)
{
snprintf(buf, sizeof(buf), "_%u", ks);
}
b->add_li(b, "%N%s", names, alg, buf);
}
enumerator->destroy(enumerator);
if (!first)
{
b->end_list(b);
}
}
/**
* List proposals for a config
*/
static void list_proposals(vici_builder_t *b, linked_list_t *proposals,
char *label, protocol_id_t protocol)
{
enumerator_t *enumerator;
proposal_t *proposal;
char buf[BUF_LEN];
u_int num = 0;
b->begin_section(b, label);
enumerator = proposals->create_enumerator(proposals);
while (enumerator->enumerate(enumerator, &proposal))
{
if (proposal->get_protocol(proposal) == protocol)
{
snprintf(buf, sizeof(buf), "%u", num++);
b->begin_section(b, buf);
list_transforms(b, proposal, "encr", ENCRYPTION_ALGORITHM);
list_transforms(b, proposal, "integ", INTEGRITY_ALGORITHM);
list_transforms(b, proposal, "prf", PSEUDO_RANDOM_FUNCTION);
list_transforms(b, proposal, "ke", KEY_EXCHANGE_METHOD);
list_transforms(b, proposal, "ake1", ADDITIONAL_KEY_EXCHANGE_1);
list_transforms(b, proposal, "ake2", ADDITIONAL_KEY_EXCHANGE_2);
list_transforms(b, proposal, "ake3", ADDITIONAL_KEY_EXCHANGE_3);
list_transforms(b, proposal, "ake4", ADDITIONAL_KEY_EXCHANGE_4);
list_transforms(b, proposal, "ake5", ADDITIONAL_KEY_EXCHANGE_5);
list_transforms(b, proposal, "ake6", ADDITIONAL_KEY_EXCHANGE_6);
list_transforms(b, proposal, "ake7", ADDITIONAL_KEY_EXCHANGE_7);
list_transforms(b, proposal, "sn", EXTENDED_SEQUENCE_NUMBERS);
b->end_section(b);
}
}
enumerator->destroy(enumerator);
b->end_section(b);
}
/**
* List additional key exchanges
*/
@@ -1006,6 +1081,10 @@ CALLBACK(list_conns, vici_message_t*,
b->add_kv(b, "unique", "%N", unique_policy_names,
peer_cfg->get_unique_policy(peer_cfg));
list = ike_cfg->get_proposals(ike_cfg, FALSE);
list_proposals(b, list, "proposals", PROTO_IKE);
list->destroy_offset(list, offsetof(proposal_t, destroy));
dpd_delay = peer_cfg->get_dpd(peer_cfg);
if (dpd_delay)
{
@@ -1052,6 +1131,11 @@ CALLBACK(list_conns, vici_message_t*,
b->add_kv(b, "close_action", "%N", action_names,
child_cfg->get_close_action(child_cfg));
list = child_cfg->get_proposals(child_cfg, FALSE, FALSE);
list_proposals(b, list, "esp_proposals", PROTO_ESP);
list_proposals(b, list, "ah_proposals", PROTO_AH);
list->destroy_offset(list, offsetof(proposal_t, destroy));
b->begin_list(b, "local-ts");
list = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL);
selectors = list->create_enumerator(list);
@@ -240,7 +240,7 @@ METHOD(task_t, build_i, status_t,
FALSE);
}
this->lifetime += this->peer_cfg->get_over_time(this->peer_cfg);
proposals = ike_cfg->get_proposals(ike_cfg);
proposals = ike_cfg->get_proposals(ike_cfg, TRUE);
sa_payload = sa_payload_create_from_proposals_v1(proposals,
this->lifetime, 0, this->method, MODE_NONE,
ENCAP_NONE, 0);
+1 -1
View File
@@ -271,7 +271,7 @@ METHOD(task_t, build_i, status_t,
FALSE);
}
this->lifetime += this->peer_cfg->get_over_time(this->peer_cfg);
proposals = ike_cfg->get_proposals(ike_cfg);
proposals = ike_cfg->get_proposals(ike_cfg, TRUE);
sa_payload = sa_payload_create_from_proposals_v1(proposals,
this->lifetime, 0, this->method, MODE_NONE,
ENCAP_NONE, 0);
+2 -2
View File
@@ -802,7 +802,7 @@ static linked_list_t *get_proposals(private_quick_mode_t *this,
proposal_t *proposal;
enumerator_t *enumerator;
list = this->config->get_proposals(this->config, FALSE);
list = this->config->get_proposals(this->config, FALSE, TRUE);
enumerator = list->create_enumerator(list);
while (enumerator->enumerate(enumerator, &proposal))
{
@@ -864,7 +864,7 @@ METHOD(task_t, build_i, status_t,
}
}
list = this->config->get_proposals(this->config, FALSE);
list = this->config->get_proposals(this->config, FALSE, TRUE);
if (list->get_first(list, (void**)&proposal) == SUCCESS)
{
this->proto = proposal->get_protocol(proposal);
+2 -2
View File
@@ -1768,7 +1768,7 @@ METHOD(task_t, build_i, status_t,
OPT_PER_CPU_SAS);
}
this->proposals = this->config->get_proposals(this->config, no_ke);
this->proposals = this->config->get_proposals(this->config, no_ke, TRUE);
this->mode = this->config->get_mode(this->config);
this->child.if_id_in_def = this->ike_sa->get_if_id(this->ike_sa, TRUE);
@@ -2486,7 +2486,7 @@ static void raise_alerts(private_child_create_t *this, notify_type_t type)
switch (type)
{
case NO_PROPOSAL_CHOSEN:
list = this->config->get_proposals(this->config, FALSE);
list = this->config->get_proposals(this->config, FALSE, FALSE);
charon->bus->alert(charon->bus, ALERT_PROPOSAL_MISMATCH_CHILD, list);
list->destroy_offset(list, offsetof(proposal_t, destroy));
break;
+2 -2
View File
@@ -367,7 +367,7 @@ static bool build_payloads(private_ike_init_t *this, message_t *message)
if (this->initiator)
{
proposal_list = ike_cfg->get_proposals(ike_cfg);
proposal_list = ike_cfg->get_proposals(ike_cfg, TRUE);
other_ke_methods = linked_list_create();
enumerator = proposal_list->create_enumerator(proposal_list);
while (enumerator->enumerate(enumerator, (void**)&proposal))
@@ -1216,7 +1216,7 @@ static void raise_alerts(private_ike_init_t *this, notify_type_t type)
{
case NO_PROPOSAL_CHOSEN:
ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
list = ike_cfg->get_proposals(ike_cfg);
list = ike_cfg->get_proposals(ike_cfg, FALSE);
charon->bus->alert(charon->bus, ALERT_PROPOSAL_MISMATCH_IKE, list);
list->destroy_offset(list, offsetof(proposal_t, destroy));
break;
+1 -1
View File
@@ -219,7 +219,7 @@ static status_t install_trap(child_sa_t *child_sa, linked_list_t *local,
/* we don't know the finally negotiated protocol (ESP|AH), we install
* the SA with the protocol of the first proposal */
proposals = child->get_proposals(child, TRUE);
proposals = child->get_proposals(child, TRUE, FALSE);
if (proposals->get_first(proposals, (void**)&proposal) == SUCCESS)
{
proto = proposal->get_protocol(proposal);