Index | Thread | Search

From:
Theo Buehler <tb@theobuehler.org>
Subject:
rpki-client: stats for non-functional CAs
To:
tech@openbsd.org
Date:
Thu, 3 Apr 2025 11:09:01 +0200

Download raw body.

Thread
This adds a simple counter for the non-functional CAs to the summary,
the ometrics and the json output. It tracks the number of certs per
tal in the nca tree. It appears next to wherever the invalid CAs are
listed (certs_fail).

Index: cert.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/cert.c,v
diff -u -p -r1.157 cert.c
--- cert.c	27 Mar 2025 05:03:09 -0000	1.157
+++ cert.c	3 Apr 2025 07:43:04 -0000
@@ -1395,7 +1395,7 @@ RB_GENERATE(brk_tree, brk, entry, brkcmp
  * Add each CA cert into the non-functional CA tree.
  */
 void
-cert_insert_nca(struct nca_tree *tree, const struct cert *cert)
+cert_insert_nca(struct nca_tree *tree, const struct cert *cert, struct repo *rp)
 {
 	struct nonfunc_ca *nca;
 
@@ -1414,15 +1414,17 @@ cert_insert_nca(struct nca_tree *tree, c
 
 	if (RB_INSERT(nca_tree, tree, nca) != NULL)
 		errx(1, "non-functional CA tree corrupted");
+	repo_stat_inc(rp, nca->talid, RTYPE_CER, STYPE_NONFUNC);
 }
 
 void
-cert_remove_nca(struct nca_tree *tree, int cid)
+cert_remove_nca(struct nca_tree *tree, int cid, struct repo *rp)
 {
 	struct nonfunc_ca *found, needle = { .certid = cid };
 
 	if ((found = RB_FIND(nca_tree, tree, &needle)) != NULL) {
 		RB_REMOVE(nca_tree, tree, found);
+		repo_stat_inc(rp, found->talid, RTYPE_CER, STYPE_FUNC);
 		free(found->location);
 		free(found->carepo);
 		free(found->mfturi);
Index: extern.h
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v
diff -u -p -r1.238 extern.h
--- extern.h	27 Mar 2025 05:03:09 -0000	1.238
+++ extern.h	3 Apr 2025 07:40:19 -0000
@@ -610,6 +610,8 @@ enum stype {
 	STYPE_PROVIDERS,
 	STYPE_OVERFLOW,
 	STYPE_SEQNUM_GAP,
+	STYPE_FUNC,
+	STYPE_NONFUNC,
 };
 
 struct repo;
@@ -623,6 +625,7 @@ RB_HEAD(filepath_tree, filepath);
 struct repotalstats {
 	uint32_t	 certs; /* certificates */
 	uint32_t	 certs_fail; /* invalid certificate */
+	uint32_t	 certs_nonfunc; /* non-functional CA certificates */
 	uint32_t	 mfts; /* total number of manifests */
 	uint32_t	 mfts_gap; /* manifests with sequence gaps */
 	uint32_t	 mfts_fail; /* failing syntactic parse */
@@ -709,8 +712,9 @@ struct cert	*ta_parse(const char *, stru
 		    size_t);
 struct cert	*cert_read(struct ibuf *);
 void		 cert_insert_brks(struct brk_tree *, struct cert *);
-void		 cert_insert_nca(struct nca_tree *, const struct cert *);
-void		 cert_remove_nca(struct nca_tree *, int);
+void		 cert_insert_nca(struct nca_tree *, const struct cert *,
+		    struct repo *);
+void		 cert_remove_nca(struct nca_tree *, int, struct repo *);
 
 enum rtype	 rtype_from_file_extension(const char *);
 void		 mft_buffer(struct ibuf *, const struct mft *);
Index: main.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/main.c,v
diff -u -p -r1.280 main.c
--- main.c	27 Mar 2025 05:03:09 -0000	1.280
+++ main.c	3 Apr 2025 07:39:41 -0000
@@ -549,7 +549,7 @@ queue_add_from_cert(const struct cert *c
 			err(1, NULL);
 	}
 
-	cert_insert_nca(ncas, cert);
+	cert_insert_nca(ncas, cert, repo);
 	entityq_add(npath, nfile, RTYPE_MFT, DIR_UNKNOWN, repo, NULL, 0,
 	    cert->talid, cert->certid, NULL);
 }
@@ -642,7 +642,7 @@ entity_process(struct ibuf *b, struct st
 		if (mft->seqnum_gap)
 			repo_stat_inc(rp, talid, type, STYPE_SEQNUM_GAP);
 		queue_add_from_mft(mft);
-		cert_remove_nca(ncatree, mft->certid);
+		cert_remove_nca(ncatree, mft->certid, rp);
 		mft_free(mft);
 		break;
 	case RTYPE_CRL:
@@ -770,6 +770,7 @@ sum_stats(const struct repo *rp, const s
 	out->mfts_gap += in->mfts_gap;
 	out->certs += in->certs;
 	out->certs_fail += in->certs_fail;
+	out->certs_nonfunc += in->certs_nonfunc;
 	out->roas += in->roas;
 	out->roas_fail += in->roas_fail;
 	out->roas_invalid += in->roas_invalid;
@@ -1523,8 +1524,9 @@ main(int argc, char *argv[])
 		    stats.repo_tal_stats.spls_invalid);
 	}
 	printf("BGPsec Router Certificates: %u\n", stats.repo_tal_stats.brks);
-	printf("Certificates: %u (%u invalid)\n",
-	    stats.repo_tal_stats.certs, stats.repo_tal_stats.certs_fail);
+	printf("Certificates: %u (%u invalid, %u non-functional)\n",
+	    stats.repo_tal_stats.certs, stats.repo_tal_stats.certs_fail,
+	    stats.repo_tal_stats.certs_nonfunc);
 	printf("Trust Anchor Locators: %u (%u invalid)\n",
 	    stats.tals, talsz - stats.tals);
 	printf("Manifests: %u (%u failed parse, %u seqnum gaps)\n",
Index: output-json.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/output-json.c,v
diff -u -p -r1.52 output-json.c
--- output-json.c	27 Mar 2025 05:03:09 -0000	1.52
+++ output-json.c	3 Apr 2025 07:38:55 -0000
@@ -58,6 +58,7 @@ outputheader_json(struct stats *st)
 	json_do_int("bgpsec_pubkeys", st->repo_tal_stats.brks);
 	json_do_int("certificates", st->repo_tal_stats.certs);
 	json_do_int("invalidcertificates", st->repo_tal_stats.certs_fail);
+	json_do_int("nonfunctionalcas", st->repo_tal_stats.certs_nonfunc);
 	json_do_int("taks", st->repo_tal_stats.taks);
 	json_do_int("tals", st->tals);
 	json_do_int("invalidtals", talsz - st->tals);
Index: output-ometric.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/output-ometric.c,v
diff -u -p -r1.13 output-ometric.c
--- output-ometric.c	27 Mar 2025 05:03:09 -0000	1.13
+++ output-ometric.c	3 Apr 2025 07:41:00 -0000
@@ -42,6 +42,8 @@ set_common_stats(const struct repotalsta
 	    OKV("type", "state"), OKV("cert", "valid"), ol);
 	ometric_set_int_with_labels(metric, in->certs_fail,
 	    OKV("type", "state"), OKV("cert", "failed parse"), ol);
+	ometric_set_int_with_labels(metric, in->certs_nonfunc,
+	    OKV("type", "state"), OKV("cert", "non-functional"), ol);
 
 	ometric_set_int_with_labels(metric, in->mfts,
 	    OKV("type", "state"), OKV("manifest", "valid"), ol);
Index: output.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/output.c,v
diff -u -p -r1.39 output.c
--- output.c	27 Mar 2025 05:03:09 -0000	1.39
+++ output.c	3 Apr 2025 08:10:26 -0000
@@ -259,12 +259,13 @@ outputheader(FILE *out, struct stats *st
 	    "# Processing time %lld seconds (%llds user, %llds system)\n"
 	    "# Route Origin Authorizations: %u (%u failed parse, %u invalid)\n"
 	    "# BGPsec Router Certificates: %u\n"
-	    "# Certificates: %u (%u invalid)\n",
+	    "# Certificates: %u (%u invalid, %u non-functional)\n",
 	    hn, tbuf, (long long)st->elapsed_time.tv_sec,
 	    (long long)st->user_time.tv_sec, (long long)st->system_time.tv_sec,
 	    st->repo_tal_stats.roas, st->repo_tal_stats.roas_fail,
 	    st->repo_tal_stats.roas_invalid, st->repo_tal_stats.brks,
-	    st->repo_tal_stats.certs, st->repo_tal_stats.certs_fail) < 0)
+	    st->repo_tal_stats.certs, st->repo_tal_stats.certs_fail,
+	    st->repo_tal_stats.certs_nonfunc) < 0)
 		return -1;
 
 	if (fprintf(out,
Index: repo.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/repo.c,v
diff -u -p -r1.74 repo.c
--- repo.c	31 Mar 2025 08:59:02 -0000	1.74
+++ repo.c	3 Apr 2025 07:26:45 -0000
@@ -1515,6 +1515,10 @@ repo_stat_inc(struct repo *rp, int talid
 			rp->stats[talid].certs++;
 		if (subtype == STYPE_FAIL)
 			rp->stats[talid].certs_fail++;
+		if (subtype == STYPE_NONFUNC)
+			rp->stats[talid].certs_nonfunc++;
+		if (subtype == STYPE_FUNC)
+			rp->stats[talid].certs_nonfunc--;
 		if (subtype == STYPE_BGPSEC) {
 			rp->stats[talid].certs--;
 			rp->stats[talid].brks++;