vici: List additional information for deleted CHILD_SAs

If a CHILD_SA is terminated, the updown event is triggered after the
CHILD_SA is set to state CHILD_DELETED, so no usage stats or detail
information like SPIs were reported.  However, when an IKEv2 SA is
terminated, the updown event for its children is triggered without
changing the state first, that is, they usually remain in state
INSTALLED and detailed data was reported in the event.  IKEv1
CHILD_SAs are always terminated individually, i.e. with state
change and no extra data so far.

With this change usage stats are also returned for individually deleted
CHILD_SAs as long as the SA has not yet expired.

Fixes #3198.
This commit is contained in:
Tobias Brunner
2019-10-25 16:15:42 +02:00
parent 62e7c68b61
commit 08d0342ca6
+127 -96
View File
@@ -111,6 +111,9 @@ struct private_vici_query_t {
time_t uptime;
};
/**
* Add the given mark/mask to the message using the provided labels
*/
static void add_mark(vici_builder_t *b, mark_t mark,
char *label, char *mask_label)
{
@@ -147,116 +150,144 @@ static void list_mode(vici_builder_t *b, child_sa_t *child, child_cfg_t *cfg)
}
}
/**
* List IPsec-related details about a CHILD_SA
*/
static void list_child_ipsec(vici_builder_t *b, child_sa_t *child)
{
proposal_t *proposal;
uint16_t alg, ks;
uint32_t if_id;
b->add_kv(b, "protocol", "%N", protocol_id_names,
child->get_protocol(child));
if (child->has_encap(child))
{
b->add_kv(b, "encap", "yes");
}
b->add_kv(b, "spi-in", "%.8x", ntohl(child->get_spi(child, TRUE)));
b->add_kv(b, "spi-out", "%.8x", ntohl(child->get_spi(child, FALSE)));
if (child->get_ipcomp(child) != IPCOMP_NONE)
{
b->add_kv(b, "cpi-in", "%.4x", ntohs(child->get_cpi(child, TRUE)));
b->add_kv(b, "cpi-out", "%.4x", ntohs(child->get_cpi(child, FALSE)));
}
add_mark(b, child->get_mark(child, TRUE), "mark-in", "mark-mask-in");
add_mark(b, child->get_mark(child, FALSE), "mark-out", "mark-mask-out");
if_id = child->get_if_id(child, TRUE);
if (if_id)
{
b->add_kv(b, "if-id-in", "%.8x", if_id);
}
if_id = child->get_if_id(child, FALSE);
if (if_id)
{
b->add_kv(b, "if-id-out", "%.8x", if_id);
}
proposal = child->get_proposal(child);
if (proposal)
{
if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM,
&alg, &ks) && alg != ENCR_UNDEFINED)
{
b->add_kv(b, "encr-alg", "%N", encryption_algorithm_names, alg);
if (ks)
{
b->add_kv(b, "encr-keysize", "%u", ks);
}
}
if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM,
&alg, &ks) && alg != AUTH_UNDEFINED)
{
b->add_kv(b, "integ-alg", "%N", integrity_algorithm_names, alg);
if (ks)
{
b->add_kv(b, "integ-keysize", "%u", ks);
}
}
if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP,
&alg, NULL))
{
b->add_kv(b, "dh-group", "%N", diffie_hellman_group_names, alg);
}
if (proposal->get_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS,
&alg, NULL) && alg == EXT_SEQ_NUMBERS)
{
b->add_kv(b, "esn", "1");
}
}
}
/**
* List usage and lifetime stats of a CHILD_SA
*/
static void list_child_stats(vici_builder_t *b, child_sa_t *child, time_t now)
{
uint64_t bytes, packets;
time_t t;
child->get_usestats(child, TRUE, &t, &bytes, &packets);
b->add_kv(b, "bytes-in", "%" PRIu64, bytes);
b->add_kv(b, "packets-in", "%" PRIu64, packets);
if (t)
{
b->add_kv(b, "use-in", "%"PRIu64, (uint64_t)(now - t));
}
child->get_usestats(child, FALSE, &t, &bytes, &packets);
b->add_kv(b, "bytes-out", "%"PRIu64, bytes);
b->add_kv(b, "packets-out", "%"PRIu64, packets);
if (t)
{
b->add_kv(b, "use-out", "%"PRIu64, (uint64_t)(now - t));
}
t = child->get_lifetime(child, FALSE);
if (t)
{
b->add_kv(b, "rekey-time", "%"PRId64, (int64_t)(t - now));
}
t = child->get_lifetime(child, TRUE);
if (t)
{
b->add_kv(b, "life-time", "%"PRId64, (int64_t)(t - now));
}
t = child->get_installtime(child);
b->add_kv(b, "install-time", "%"PRId64, (int64_t)(now - t));
}
/**
* List details of a CHILD_SA
*/
static void list_child(private_vici_query_t *this, vici_builder_t *b,
child_sa_t *child, time_t now)
{
time_t t;
uint64_t bytes, packets;
uint32_t if_id;
uint16_t alg, ks;
proposal_t *proposal;
enumerator_t *enumerator;
traffic_selector_t *ts;
child_sa_state_t state;
b->add_kv(b, "name", "%s", child->get_name(child));
b->add_kv(b, "uniqueid", "%u", child->get_unique_id(child));
b->add_kv(b, "reqid", "%u", child->get_reqid(child));
b->add_kv(b, "state", "%N", child_sa_state_names, child->get_state(child));
state = child->get_state(child);
b->add_kv(b, "state", "%N", child_sa_state_names, state);
list_mode(b, child, NULL);
if (child->get_state(child) == CHILD_INSTALLED ||
child->get_state(child) == CHILD_REKEYING ||
child->get_state(child) == CHILD_REKEYED)
switch (state)
{
b->add_kv(b, "protocol", "%N", protocol_id_names,
child->get_protocol(child));
if (child->has_encap(child))
{
b->add_kv(b, "encap", "yes");
}
b->add_kv(b, "spi-in", "%.8x", ntohl(child->get_spi(child, TRUE)));
b->add_kv(b, "spi-out", "%.8x", ntohl(child->get_spi(child, FALSE)));
if (child->get_ipcomp(child) != IPCOMP_NONE)
{
b->add_kv(b, "cpi-in", "%.4x", ntohs(child->get_cpi(child, TRUE)));
b->add_kv(b, "cpi-out", "%.4x", ntohs(child->get_cpi(child, FALSE)));
}
add_mark(b, child->get_mark(child, TRUE), "mark-in", "mark-mask-in");
add_mark(b, child->get_mark(child, FALSE), "mark-out", "mark-mask-out");
if_id = child->get_if_id(child, TRUE);
if (if_id)
{
b->add_kv(b, "if-id-in", "%.8x", if_id);
}
if_id = child->get_if_id(child, FALSE);
if (if_id)
{
b->add_kv(b, "if-id-out", "%.8x", if_id);
}
proposal = child->get_proposal(child);
if (proposal)
{
if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM,
&alg, &ks) && alg != ENCR_UNDEFINED)
{
b->add_kv(b, "encr-alg", "%N", encryption_algorithm_names, alg);
if (ks)
{
b->add_kv(b, "encr-keysize", "%u", ks);
}
}
if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM,
&alg, &ks) && alg != AUTH_UNDEFINED)
{
b->add_kv(b, "integ-alg", "%N", integrity_algorithm_names, alg);
if (ks)
{
b->add_kv(b, "integ-keysize", "%u", ks);
}
}
if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP,
&alg, NULL))
{
b->add_kv(b, "dh-group", "%N", diffie_hellman_group_names, alg);
}
if (proposal->get_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS,
&alg, NULL) && alg == EXT_SEQ_NUMBERS)
{
b->add_kv(b, "esn", "1");
}
}
child->get_usestats(child, TRUE, &t, &bytes, &packets);
b->add_kv(b, "bytes-in", "%" PRIu64, bytes);
b->add_kv(b, "packets-in", "%" PRIu64, packets);
if (t)
{
b->add_kv(b, "use-in", "%"PRIu64, (uint64_t)(now - t));
}
child->get_usestats(child, FALSE, &t, &bytes, &packets);
b->add_kv(b, "bytes-out", "%"PRIu64, bytes);
b->add_kv(b, "packets-out", "%"PRIu64, packets);
if (t)
{
b->add_kv(b, "use-out", "%"PRIu64, (uint64_t)(now - t));
}
t = child->get_lifetime(child, FALSE);
if (t)
{
b->add_kv(b, "rekey-time", "%"PRId64, (int64_t)(t - now));
}
t = child->get_lifetime(child, TRUE);
if (t)
{
b->add_kv(b, "life-time", "%"PRId64, (int64_t)(t - now));
}
t = child->get_installtime(child);
b->add_kv(b, "install-time", "%"PRId64, (int64_t)(now - t));
case CHILD_INSTALLED:
case CHILD_REKEYING:
case CHILD_REKEYED:
case CHILD_DELETING:
case CHILD_DELETED:
list_child_ipsec(b, child);
list_child_stats(b, child, now);
break;
default:
break;
}
b->begin_list(b, "local-ts");