summaryrefslogtreecommitdiff
path: root/usr.sbin/rpki-client/repo.c
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2023-04-26 16:32:42 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2023-04-26 16:32:42 +0000
commit268ec2e09f2c2324f9f3b77ea277b6a9285a6aa9 (patch)
treec38d925eb62e0df6aa3cf5fc41d2fbdc84396938 /usr.sbin/rpki-client/repo.c
parent443905df41cfecf772287d52742b12c7a1a13335 (diff)
Improve accounting by tracking things by repo and tal.
This fixes some wrong accounting for repositories that are referenced from more than one TAL. It changes the ometric lable output a little bit since there are repository metrics that no longer include the 'name' label. OK tb@
Diffstat (limited to 'usr.sbin/rpki-client/repo.c')
-rw-r--r--usr.sbin/rpki-client/repo.c384
1 files changed, 210 insertions, 174 deletions
diff --git a/usr.sbin/rpki-client/repo.c b/usr.sbin/rpki-client/repo.c
index 08ab2a0d206..81b06b8d4dd 100644
--- a/usr.sbin/rpki-client/repo.c
+++ b/usr.sbin/rpki-client/repo.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: repo.c,v 1.43 2023/03/30 15:29:15 claudio Exp $ */
+/* $OpenBSD: repo.c,v 1.44 2023/04/26 16:32:41 claudio Exp $ */
/*
* Copyright (c) 2021 Claudio Jeker <claudio@openbsd.org>
* Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
@@ -97,10 +97,12 @@ struct repo {
const struct rsyncrepo *rsync;
const struct tarepo *ta;
struct entityq queue; /* files waiting for repo */
- struct repostats stats;
+ struct repotalstats stats[TALSZ_MAX];
+ struct repostats repostats;
struct timespec start_time;
time_t alarm; /* sync timeout */
int talid;
+ int stats_used[TALSZ_MAX];
unsigned int id; /* identifier */
};
static SLIST_HEAD(, repo) repos = SLIST_HEAD_INITIALIZER(repos);
@@ -302,7 +304,8 @@ repo_done(const void *vp, int ok)
entityq_flush(&rp->queue, rp);
clock_gettime(CLOCK_MONOTONIC, &flush_time);
- timespecsub(&flush_time, &rp->start_time, &rp->stats.sync_time);
+ timespecsub(&flush_time, &rp->start_time,
+ &rp->repostats.sync_time);
}
}
@@ -555,16 +558,18 @@ rrdp_free(void)
* Check if a directory is an active rrdp repository.
* Returns 1 if found else 0.
*/
-static int
-rrdp_is_active(const char *dir)
+static struct repo *
+repo_rrdp_bypath(const char *dir)
{
- struct rrdprepo *rr;
-
- SLIST_FOREACH(rr, &rrdprepos, entry)
- if (strcmp(dir, rr->basedir) == 0)
- return rr->state != REPO_FAILED;
+ struct repo *rp;
- return 0;
+ SLIST_FOREACH(rp, &repos, entry) {
+ if (rp->rrdp == NULL)
+ continue;
+ if (strcmp(dir, rp->rrdp->basedir) == 0)
+ return rp;
+ }
+ return NULL;
}
/*
@@ -1322,48 +1327,49 @@ repo_check_timeout(int timeout)
* Update stats object of repository depending on rtype and subtype.
*/
void
-repo_stat_inc(struct repo *rp, enum rtype type, enum stype subtype)
+repo_stat_inc(struct repo *rp, int talid, enum rtype type, enum stype subtype)
{
if (rp == NULL)
return;
+ rp->stats_used[talid] = 1;
switch (type) {
case RTYPE_CER:
if (subtype == STYPE_OK)
- rp->stats.certs++;
+ rp->stats[talid].certs++;
if (subtype == STYPE_FAIL)
- rp->stats.certs_fail++;
+ rp->stats[talid].certs_fail++;
if (subtype == STYPE_BGPSEC) {
- rp->stats.certs--;
- rp->stats.brks++;
+ rp->stats[talid].certs--;
+ rp->stats[talid].brks++;
}
break;
case RTYPE_MFT:
if (subtype == STYPE_OK)
- rp->stats.mfts++;
+ rp->stats[talid].mfts++;
if (subtype == STYPE_FAIL)
- rp->stats.mfts_fail++;
+ rp->stats[talid].mfts_fail++;
if (subtype == STYPE_STALE)
- rp->stats.mfts_stale++;
+ rp->stats[talid].mfts_stale++;
break;
case RTYPE_ROA:
switch (subtype) {
case STYPE_OK:
- rp->stats.roas++;
+ rp->stats[talid].roas++;
break;
case STYPE_FAIL:
- rp->stats.roas_fail++;
+ rp->stats[talid].roas_fail++;
break;
case STYPE_INVALID:
- rp->stats.roas_invalid++;
+ rp->stats[talid].roas_invalid++;
break;
case STYPE_TOTAL:
- rp->stats.vrps++;
+ rp->stats[talid].vrps++;
break;
case STYPE_UNIQUE:
- rp->stats.vrps_uniqs++;
+ rp->stats[talid].vrps_uniqs++;
break;
case STYPE_DEC_UNIQUE:
- rp->stats.vrps_uniqs--;
+ rp->stats[talid].vrps_uniqs--;
break;
default:
break;
@@ -1372,41 +1378,44 @@ repo_stat_inc(struct repo *rp, enum rtype type, enum stype subtype)
case RTYPE_ASPA:
switch (subtype) {
case STYPE_OK:
- rp->stats.aspas++;
+ rp->stats[talid].aspas++;
break;
case STYPE_FAIL:
- rp->stats.aspas_fail++;
+ rp->stats[talid].aspas_fail++;
break;
case STYPE_INVALID:
- rp->stats.aspas_invalid++;
+ rp->stats[talid].aspas_invalid++;
break;
case STYPE_TOTAL:
- rp->stats.vaps++;
+ rp->stats[talid].vaps++;
break;
case STYPE_UNIQUE:
- rp->stats.vaps_uniqs++;
+ rp->stats[talid].vaps_uniqs++;
+ break;
+ case STYPE_DEC_UNIQUE:
+ rp->stats[talid].vaps_uniqs--;
break;
case STYPE_BOTH:
- rp->stats.vaps_pas++;
+ rp->stats[talid].vaps_pas++;
break;
case STYPE_ONLY_IPV4:
- rp->stats.vaps_pas4++;
+ rp->stats[talid].vaps_pas4++;
break;
case STYPE_ONLY_IPV6:
- rp->stats.vaps_pas6++;
+ rp->stats[talid].vaps_pas6++;
break;
default:
break;
}
break;
case RTYPE_CRL:
- rp->stats.crls++;
+ rp->stats[talid].crls++;
break;
case RTYPE_GBR:
- rp->stats.gbrs++;
+ rp->stats[talid].gbrs++;
break;
case RTYPE_TAK:
- rp->stats.taks++;
+ rp->stats[talid].taks++;
break;
default:
break;
@@ -1414,16 +1423,27 @@ repo_stat_inc(struct repo *rp, enum rtype type, enum stype subtype)
}
void
-repo_stats_collect(void (*cb)(const struct repo *, const struct repostats *,
- void *), void *arg)
+repo_tal_stats_collect(void (*cb)(const struct repo *,
+ const struct repotalstats *, void *), int talid, void *arg)
{
struct repo *rp;
SLIST_FOREACH(rp, &repos, entry) {
- cb(rp, &rp->stats, arg);
+ if (rp->stats_used[talid])
+ cb(rp, &rp->stats[talid], arg);
}
}
+void
+repo_stats_collect(void (*cb)(const struct repo *, const struct repostats *,
+ void *), void *arg)
+{
+ struct repo *rp;
+
+ SLIST_FOREACH(rp, &repos, entry)
+ cb(rp, &rp->repostats, arg);
+}
+
/*
* Delayed delete of files from RRDP. Since RRDP has no security built-in
* this code needs to check if this RRDP repository is actually allowed to
@@ -1432,11 +1452,15 @@ repo_stats_collect(void (*cb)(const struct repo *, const struct repostats *,
static void
repo_cleanup_rrdp(struct filepath_tree *tree)
{
+ struct repo *rp;
struct rrdprepo *rr;
struct filepath *fp, *nfp;
char *fn;
- SLIST_FOREACH(rr, &rrdprepos, entry) {
+ SLIST_FOREACH(rp, &repos, entry) {
+ if (rp->rrdp == NULL)
+ continue;
+ rr = (struct rrdprepo *)rp->rrdp;
RB_FOREACH_SAFE(fp, filepath_tree, &rr->deleted, nfp) {
if (!rrdp_uri_valid(rr, fp->file)) {
warnx("%s: external URI %s", rr->notifyuri,
@@ -1453,7 +1477,7 @@ repo_cleanup_rrdp(struct filepath_tree *tree)
} else {
if (verbose > 1)
logx("deleted %s", fn);
- stats.del_files++;
+ rp->repostats.del_files++;
}
free(fn);
@@ -1466,7 +1490,7 @@ repo_cleanup_rrdp(struct filepath_tree *tree)
} else {
if (verbose > 1)
logx("deleted %s", fn);
- stats.del_files++;
+ rp->repostats.del_files++;
}
} else
warnx("%s: referenced file supposed to be "
@@ -1524,18 +1548,16 @@ repo_move_valid(struct filepath_tree *tree)
}
}
-#define BASE_DIR (void *)0x01
-#define RSYNC_DIR (void *)0x02
-#define RRDP_DIR (void *)0x03
+struct fts_state {
+ enum { BASE_DIR, RSYNC_DIR, RRDP_DIR } type;
+ struct repo *rp;
+} fts_state;
static const struct rrdprepo *
repo_is_rrdp(struct repo *rp)
{
/* check for special pointers first these are not a repository */
- if (rp == NULL || rp == BASE_DIR || rp == RSYNC_DIR || rp == RRDP_DIR)
- return NULL;
-
- if (rp->rrdp)
+ if (rp != NULL && rp->rrdp != NULL)
return rp->rrdp->state == REPO_DONE ? rp->rrdp : NULL;
return NULL;
}
@@ -1548,152 +1570,166 @@ skip_dotslash(char *in)
return in;
}
-void
-repo_cleanup(struct filepath_tree *tree, int cachefd)
+static void
+repo_cleanup_entry(FTSENT *e, struct filepath_tree *tree, int cachefd)
{
- char *argv[2] = { ".", NULL };
- FTS *fts;
- FTSENT *e;
const struct rrdprepo *rr;
+ char *path;
- /* first move temp files which have been used to valid dir */
- repo_move_valid(tree);
- /* then delete files requested by rrdp */
- repo_cleanup_rrdp(tree);
-
- if ((fts = fts_open(argv, FTS_PHYSICAL | FTS_NOSTAT, NULL)) == NULL)
- err(1, "fts_open");
- errno = 0;
- while ((e = fts_read(fts)) != NULL) {
- char *path = skip_dotslash(e->fts_path);
- switch (e->fts_info) {
- case FTS_NSOK:
- if (filepath_exists(tree, path)) {
- e->fts_parent->fts_number++;
+ path = skip_dotslash(e->fts_path);
+ switch (e->fts_info) {
+ case FTS_NSOK:
+ if (filepath_exists(tree, path)) {
+ e->fts_parent->fts_number++;
+ break;
+ }
+ if (fts_state.type == RRDP_DIR && fts_state.rp != NULL) {
+ e->fts_parent->fts_number++;
+ /* handle rrdp .state files explicitly */
+ if (e->fts_level == 3 &&
+ strcmp(e->fts_name, ".state") == 0)
break;
+ /* can't delete these extra files */
+ fts_state.rp->repostats.extra_files++;
+ if (verbose > 1)
+ logx("superfluous %s", path);
+ break;
+ }
+ rr = repo_is_rrdp(fts_state.rp);
+ if (rr != NULL) {
+ struct stat st;
+ char *fn;
+
+ if (asprintf(&fn, "%s/%s", rr->basedir, path) == -1)
+ err(1, NULL);
+
+ /*
+ * If the file exists in the rrdp dir
+ * that file is newer and needs to be kept
+ * so unlink this file instead of moving
+ * it over the file in the rrdp dir.
+ */
+ if (fstatat(cachefd, fn, &st, 0) == 0 &&
+ S_ISREG(st.st_mode)) {
+ free(fn);
+ goto unlink;
}
- if (e->fts_parent->fts_pointer == RRDP_DIR) {
- e->fts_parent->fts_number++;
- /* handle rrdp .state files explicitly */
- if (e->fts_level == 3 &&
- strcmp(e->fts_name, ".state") == 0)
- break;
- /* can't delete these extra files */
- stats.extra_files++;
- if (verbose > 1)
- logx("superfluous %s", path);
- break;
+ if (repo_mkpath(cachefd, fn) == 0) {
+ if (renameat(AT_FDCWD, e->fts_accpath,
+ cachefd, fn) == -1)
+ warn("rename %s to %s", path, fn);
+ else if (verbose > 1)
+ logx("moved %s", path);
+ fts_state.rp->repostats.extra_files++;
}
- if (e->fts_parent->fts_pointer == RSYNC_DIR) {
+ free(fn);
+ } else {
+ unlink:
+ if (unlink(e->fts_accpath) == -1) {
+ warn("unlink %s", path);
+ } else if (fts_state.type == RSYNC_DIR) {
/* no need to keep rsync files */
if (verbose > 1)
logx("superfluous %s", path);
+ if (fts_state.rp != NULL)
+ fts_state.rp->repostats.del_extra_files++;
+ else
+ stats.repo_stats.del_extra_files++;
+ } else {
+ if (verbose > 1)
+ logx("deleted %s", path);
+ if (fts_state.rp != NULL)
+ fts_state.rp->repostats.del_files++;
+ else
+ stats.repo_stats.del_files++;
}
- rr = repo_is_rrdp(e->fts_parent->fts_pointer);
- if (rr != NULL) {
- struct stat st;
- char *fn;
-
- if (asprintf(&fn, "%s/%s", rr->basedir,
- path) == -1)
- err(1, NULL);
-
- /*
- * If the file exists in the rrdp dir
- * that file is newer and needs to be kept
- * so unlink this file instead of moving
- * it over the file in the rrdp dir.
- */
- if (fstatat(cachefd, fn, &st, 0) == 0 &&
- S_ISREG(st.st_mode)) {
- free(fn);
- goto unlink;
- }
- if (repo_mkpath(cachefd, fn) == 0) {
- if (renameat(AT_FDCWD, e->fts_accpath,
- cachefd, fn) == -1)
- warn("rename %s to %s", path,
- fn);
- else if (verbose > 1)
- logx("moved %s", path);
- stats.extra_files++;
- }
- free(fn);
+ }
+ break;
+ case FTS_D:
+ if (e->fts_level == FTS_ROOTLEVEL)
+ fts_state.type = BASE_DIR;
+ if (e->fts_level == 1) {
+ if (strcmp(".rsync", e->fts_name) == 0) {
+ fts_state.type = RSYNC_DIR;
+ fts_state.rp = NULL;
+ } else if (strcmp(".rrdp", e->fts_name) == 0) {
+ fts_state.type = RRDP_DIR;
+ fts_state.rp = NULL;
} else {
- unlink:
- if (unlink(e->fts_accpath) == -1) {
- warn("unlink %s", path);
- } else {
- if (verbose > 1)
- logx("deleted %s", path);
- stats.del_files++;
- }
+ fts_state.type = BASE_DIR;
+ fts_state.rp = repo_bypath(path);
}
- break;
- case FTS_D:
- if (e->fts_level == 1) {
- if (strcmp(".rsync", e->fts_name) == 0)
- e->fts_pointer = RSYNC_DIR;
- else if (strcmp(".rrdp", e->fts_name) == 0)
- e->fts_pointer = RRDP_DIR;
- else
- e->fts_pointer = BASE_DIR;
- } else
- e->fts_pointer = e->fts_parent->fts_pointer;
-
+ }
+ if (e->fts_level == 2) {
+ if (fts_state.type == RSYNC_DIR)
+ fts_state.rp = repo_bypath(path);
/*
* special handling for rrdp directories,
* clear them if they are not used anymore but
* only if rrdp is active.
*/
- if (e->fts_pointer == RRDP_DIR && e->fts_level == 2) {
- if (!rrdp_is_active(path))
- e->fts_pointer = NULL;
- }
- if (e->fts_pointer == BASE_DIR && e->fts_level > 1) {
- e->fts_pointer = repo_bypath(path);
- if (e->fts_pointer == NULL)
- e->fts_pointer = BASE_DIR;
- }
+ if (fts_state.type == RRDP_DIR)
+ fts_state.rp = repo_rrdp_bypath(path);
+ }
+ break;
+ case FTS_DP:
+ if (e->fts_level == FTS_ROOTLEVEL)
break;
- case FTS_DP:
- if (e->fts_level == FTS_ROOTLEVEL)
+ if (e->fts_level == 1) {
+ /* do not remove .rsync and .rrdp */
+ fts_state.rp = NULL;
+ if (fts_state.type == RRDP_DIR ||
+ fts_state.type == RSYNC_DIR)
break;
- if (e->fts_level == 1)
- /* do not remove .rsync and .rrdp */
- if (e->fts_pointer == RRDP_DIR ||
- e->fts_pointer == RSYNC_DIR)
- break;
-
- e->fts_parent->fts_number += e->fts_number;
-
- if (e->fts_number == 0) {
- if (rmdir(e->fts_accpath) == -1)
- warn("rmdir %s", path);
- else
- stats.del_dirs++;
- }
- break;
- case FTS_SL:
- case FTS_SLNONE:
- warnx("symlink %s", path);
- if (unlink(e->fts_accpath) == -1)
- warn("unlink %s", path);
- break;
- case FTS_NS:
- case FTS_ERR:
- if (e->fts_errno == ENOENT &&
- e->fts_level == FTS_ROOTLEVEL)
- continue;
- warnx("fts_read %s: %s", path,
- strerror(e->fts_errno));
- break;
- default:
- warnx("fts_read %s: unhandled[%x]", path,
- e->fts_info);
- break;
}
+ e->fts_parent->fts_number += e->fts_number;
+
+ if (e->fts_number == 0) {
+ if (rmdir(e->fts_accpath) == -1)
+ warn("rmdir %s", path);
+ if (fts_state.rp != NULL)
+ fts_state.rp->repostats.del_dirs++;
+ else
+ stats.repo_stats.del_dirs++;
+ }
+ break;
+ case FTS_SL:
+ case FTS_SLNONE:
+ warnx("symlink %s", path);
+ if (unlink(e->fts_accpath) == -1)
+ warn("unlink %s", path);
+ stats.repo_stats.del_extra_files++;
+ break;
+ case FTS_NS:
+ case FTS_ERR:
+ if (e->fts_errno == ENOENT && e->fts_level == FTS_ROOTLEVEL)
+ break;
+ warnx("fts_read %s: %s", path, strerror(e->fts_errno));
+ break;
+ default:
+ warnx("fts_read %s: unhandled[%x]", path, e->fts_info);
+ break;
+ }
+}
+
+void
+repo_cleanup(struct filepath_tree *tree, int cachefd)
+{
+ char *argv[2] = { ".", NULL };
+ FTS *fts;
+ FTSENT *e;
+
+ /* first move temp files which have been used to valid dir */
+ repo_move_valid(tree);
+ /* then delete files requested by rrdp */
+ repo_cleanup_rrdp(tree);
+
+ if ((fts = fts_open(argv, FTS_PHYSICAL | FTS_NOSTAT, NULL)) == NULL)
+ err(1, "fts_open");
+ errno = 0;
+ while ((e = fts_read(fts)) != NULL) {
+ repo_cleanup_entry(e, tree, cachefd);
errno = 0;
}
if (errno)