vici: List additional information for deleted CHILD_SAs
authorTobias Brunner <tobias@strongswan.org>
Thu, 10 Oct 2019 13:33:45 +0000 (15:33 +0200)
committerTobias Brunner <tobias@strongswan.org>
Fri, 25 Oct 2019 14:15:42 +0000 (16:15 +0200)
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.

src/libcharon/plugins/vici/vici_query.c

index 0b300a3..81d692c 100644 (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)
 {
@@ -148,115 +151,143 @@ static void list_mode(vici_builder_t *b, child_sa_t *child, child_cfg_t *cfg)
 }
 
 /**
- * List details of a CHILD_SA
+ * List IPsec-related details about a CHILD_SA
  */
-static void list_child(private_vici_query_t *this, vici_builder_t *b,
-                                          child_sa_t *child, time_t now)
+static void list_child_ipsec(vici_builder_t *b, child_sa_t *child)
 {
-       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;
+       uint16_t alg, ks;
+       uint32_t if_id;
 
-       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));
-       list_mode(b, child, NULL);
-       if (child->get_state(child) == CHILD_INSTALLED ||
-               child->get_state(child) == CHILD_REKEYING ||
-               child->get_state(child) == CHILD_REKEYED)
+       b->add_kv(b, "protocol", "%N", protocol_id_names,
+                         child->get_protocol(child));
+       if (child->has_encap(child))
        {
-               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)));
+               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 (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)
                {
-                       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, "encr-alg", "%N", encryption_algorithm_names, alg);
+                       if (ks)
                        {
-                               b->add_kv(b, "dh-group", "%N", diffie_hellman_group_names, alg);
+                               b->add_kv(b, "encr-keysize", "%u", ks);
                        }
-                       if (proposal->get_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS,
-                                                                               &alg, NULL) && alg == EXT_SEQ_NUMBERS)
+               }
+               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, "esn", "1");
+                               b->add_kv(b, "integ-keysize", "%u", ks);
                        }
                }
-
-               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)
+               if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP,
+                                                                       &alg, NULL))
                {
-                       b->add_kv(b, "use-in", "%"PRIu64, (uint64_t)(now - t));
+                       b->add_kv(b, "dh-group", "%N", diffie_hellman_group_names, alg);
                }
-
-               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)
+               if (proposal->get_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS,
+                                                                       &alg, NULL) && alg == EXT_SEQ_NUMBERS)
                {
-                       b->add_kv(b, "use-out", "%"PRIu64, (uint64_t)(now - t));
+                       b->add_kv(b, "esn", "1");
                }
+       }
+}
 
-               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 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)
+{
+       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));
+       state = child->get_state(child);
+       b->add_kv(b, "state", "%N", child_sa_state_names, state);
+       list_mode(b, child, NULL);
+
+       switch (state)
+       {
+               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");