On Tue, May 30, 2023 at 02:10:31PM +0000, Job Snijders wrote: > On Tue, May 30, 2023 at 03:12:46PM +0200, Claudio Jeker wrote: > > On Tue, May 30, 2023 at 02:38:23PM +0200, Claudio Jeker wrote: > > > On Wed, May 24, 2023 at 04:18:30PM +0000, Job Snijders wrote: > > > > Dear all, > > > > > > > > Claudio made some suggestions to pass the desired modification times > > > > around in a different way, below is an updated patch proposal. > > > > I also added some instrumentation to also adjust GBRs and TAKs. > > > > > > > > RIPE & APNIC informally indicated some interest in this hack. > > > > > > > > > > This looks good. Some feedback below. > > How about this?
Looks good to me. OK > Index: extern.h > =================================================================== > RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v > retrieving revision 1.182 > diff -u -p -r1.182 extern.h > --- extern.h 30 May 2023 12:14:48 -0000 1.182 > +++ extern.h 30 May 2023 13:49:16 -0000 > @@ -348,6 +348,7 @@ struct gbr { > time_t notbefore; /* EE cert's Not Before */ > time_t notafter; /* Not After of the GBR EE */ > time_t expires; /* when the signature path expires */ > + int talid; /* TAL the GBR is chained up to */ > }; > > struct aspa_provider { > @@ -755,7 +756,7 @@ void proc_http(char *, int) __attribut > void proc_rrdp(int) __attribute__((noreturn)); > > /* Repository handling */ > -int filepath_add(struct filepath_tree *, char *); > +int filepath_add(struct filepath_tree *, char *, time_t); > void rrdp_clear(unsigned int); > void rrdp_save_state(unsigned int, struct rrdp_session *); > int rrdp_handle_file(unsigned int, enum publish_type, char *, > Index: filemode.c > =================================================================== > RCS file: /cvs/src/usr.sbin/rpki-client/filemode.c,v > retrieving revision 1.32 > diff -u -p -r1.32 filemode.c > --- filemode.c 30 May 2023 12:02:22 -0000 1.32 > +++ filemode.c 30 May 2023 13:49:16 -0000 > @@ -589,6 +589,7 @@ parse_file(struct entityq *q, struct msg > struct entity *entp; > struct ibuf *b; > struct tal *tal; > + time_t dummy = 0; > > while ((entp = TAILQ_FIRST(q)) != NULL) { > TAILQ_REMOVE(q, entp, entries); > @@ -615,6 +616,7 @@ parse_file(struct entityq *q, struct msg > io_simple_buffer(b, &entp->repoid, sizeof(entp->repoid)); > io_simple_buffer(b, &entp->talid, sizeof(entp->talid)); > io_str_buffer(b, entp->file); > + io_simple_buffer(b, &dummy, sizeof(dummy)); > io_close_buffer(msgq, b); > entity_free(entp); > } > Index: main.c > =================================================================== > RCS file: /cvs/src/usr.sbin/rpki-client/main.c,v > retrieving revision 1.240 > diff -u -p -r1.240 main.c > --- main.c 30 May 2023 12:14:48 -0000 1.240 > +++ main.c 30 May 2023 13:49:16 -0000 > @@ -559,6 +559,7 @@ entity_process(struct ibuf *b, struct st > struct aspa *aspa; > struct repo *rp; > char *file; > + time_t mtime; > unsigned int id; > int talid; > int c; > @@ -573,12 +574,13 @@ entity_process(struct ibuf *b, struct st > io_read_buf(b, &id, sizeof(id)); > io_read_buf(b, &talid, sizeof(talid)); > io_read_str(b, &file); > + io_read_buf(b, &mtime, sizeof(mtime)); > > /* in filemode messages can be ignored, only the accounting matters */ > if (filemode) > goto done; > > - if (filepath_add(&fpt, file) == 0) { > + if (filepath_add(&fpt, file, mtime) == 0) { > warnx("%s: File already visited", file); > goto done; > } > Index: parser.c > =================================================================== > RCS file: /cvs/src/usr.sbin/rpki-client/parser.c,v > retrieving revision 1.95 > diff -u -p -r1.95 parser.c > --- parser.c 30 May 2023 12:14:48 -0000 1.95 > +++ parser.c 30 May 2023 13:49:16 -0000 > @@ -352,7 +352,8 @@ proc_parser_mft_post(char *file, struct > * Load the most recent MFT by opening both options and comparing the two. > */ > static char * > -proc_parser_mft(struct entity *entp, struct mft **mp, char **crlfile) > +proc_parser_mft(struct entity *entp, struct mft **mp, char **crlfile, > + time_t *crlmtime) > { > struct mft *mft1 = NULL, *mft2 = NULL; > struct crl *crl, *crl1, *crl2; > @@ -360,6 +361,7 @@ proc_parser_mft(struct entity *entp, str > const char *err1, *err2; > > *mp = NULL; > + *crlmtime = 0; > > mft1 = proc_parser_mft_pre(entp, DIR_VALID, &file1, &crl1, &crl1file, > &err1); > @@ -392,6 +394,7 @@ proc_parser_mft(struct entity *entp, str > } > > if (*mp != NULL) { > + *crlmtime = crl->lastupdate; > if (!crl_insert(&crlt, crl)) { > warnx("%s: duplicate AKI %s", file, crl->aki); > crl_free(crl); > @@ -488,7 +491,7 @@ proc_parser_root_cert(char *file, const > /* > * Parse a ghostbuster record > */ > -static void > +static struct gbr * > proc_parser_gbr(char *file, const unsigned char *der, size_t len, > const char *mftaki) > { > @@ -499,17 +502,23 @@ proc_parser_gbr(char *file, const unsign > const char *errstr; > > if ((gbr = gbr_parse(&x509, file, der, len)) == NULL) > - return; > + return NULL; > > a = valid_ski_aki(file, &auths, gbr->ski, gbr->aki, mftaki); > crl = crl_get(&crlt, a); > > /* return value can be ignored since nothing happens here */ > - if (!valid_x509(file, ctx, x509, a, crl, &errstr)) > + if (!valid_x509(file, ctx, x509, a, crl, &errstr)) { > warnx("%s: %s", file, errstr); > - > + X509_free(x509); > + gbr_free(gbr); > + return NULL; > + } > X509_free(x509); > - gbr_free(gbr); > + > + gbr->talid = a->cert->talid; > + > + return gbr; > } > > /* > @@ -618,8 +627,11 @@ parse_entity(struct entityq *q, struct m > struct mft *mft; > struct roa *roa; > struct aspa *aspa; > + struct gbr *gbr; > + struct tak *tak; > struct ibuf *b; > unsigned char *f; > + time_t mtime, crlmtime; > size_t flen; > char *file, *crlfile; > int c; > @@ -642,9 +654,13 @@ parse_entity(struct entityq *q, struct m > > file = NULL; > f = NULL; > + mtime = 0; > + crlmtime = 0; > + > switch (entp->type) { > case RTYPE_TAL: > io_str_buffer(b, entp->file); > + io_simple_buffer(b, &mtime, sizeof(mtime)); > if ((tal = tal_parse(entp->file, entp->data, > entp->datasz)) == NULL) > errx(1, "%s: could not parse tal file", > @@ -663,6 +679,9 @@ parse_entity(struct entityq *q, struct m > else > cert = proc_parser_cert(file, f, flen, > entp->mftaki); > + if (cert != NULL) > + mtime = cert->notbefore; > + io_simple_buffer(b, &mtime, sizeof(mtime)); > c = (cert != NULL); > io_simple_buffer(b, &c, sizeof(int)); > if (cert != NULL) { > @@ -676,8 +695,11 @@ parse_entity(struct entityq *q, struct m > */ > break; > case RTYPE_MFT: > - file = proc_parser_mft(entp, &mft, &crlfile); > + file = proc_parser_mft(entp, &mft, &crlfile, &crlmtime); > io_str_buffer(b, file); > + if (mft != NULL) > + mtime = mft->signtime; > + io_simple_buffer(b, &mtime, sizeof(mtime)); > c = (mft != NULL); > io_simple_buffer(b, &c, sizeof(int)); > if (mft != NULL) > @@ -696,6 +718,8 @@ parse_entity(struct entityq *q, struct m > io_simple_buffer(b2, &entp->talid, > sizeof(entp->talid)); > io_str_buffer(b2, crlfile); > + io_simple_buffer(b2, &crlmtime, > + sizeof(crlmtime)); > free(crlfile); > > io_close_buffer(msgq, b2); > @@ -706,6 +730,9 @@ parse_entity(struct entityq *q, struct m > file = parse_load_file(entp, &f, &flen); > io_str_buffer(b, file); > roa = proc_parser_roa(file, f, flen, entp->mftaki); > + if (roa != NULL) > + mtime = roa->signtime; > + io_simple_buffer(b, &mtime, sizeof(mtime)); > c = (roa != NULL); > io_simple_buffer(b, &c, sizeof(int)); > if (roa != NULL) > @@ -715,12 +742,19 @@ parse_entity(struct entityq *q, struct m > case RTYPE_GBR: > file = parse_load_file(entp, &f, &flen); > io_str_buffer(b, file); > - proc_parser_gbr(file, f, flen, entp->mftaki); > + gbr = proc_parser_gbr(file, f, flen, entp->mftaki); > + if (gbr != NULL) > + mtime = gbr->signtime; > + io_simple_buffer(b, &mtime, sizeof(mtime)); > + gbr_free(gbr); > break; > case RTYPE_ASPA: > file = parse_load_file(entp, &f, &flen); > io_str_buffer(b, file); > aspa = proc_parser_aspa(file, f, flen, entp->mftaki); > + if (aspa != NULL) > + mtime = aspa->signtime; > + io_simple_buffer(b, &mtime, sizeof(mtime)); > c = (aspa != NULL); > io_simple_buffer(b, &c, sizeof(int)); > if (aspa != NULL) > @@ -730,13 +764,18 @@ parse_entity(struct entityq *q, struct m > case RTYPE_TAK: > file = parse_load_file(entp, &f, &flen); > io_str_buffer(b, file); > - proc_parser_tak(file, f, flen, entp->mftaki); > + tak = proc_parser_tak(file, f, flen, entp->mftaki); > + if (tak != NULL) > + mtime = tak->signtime; > + io_simple_buffer(b, &mtime, sizeof(mtime)); > + tak_free(tak); > break; > case RTYPE_CRL: > default: > file = parse_filepath(entp->repoid, entp->path, > entp->file, entp->location); > io_str_buffer(b, file); > + io_simple_buffer(b, &mtime, sizeof(mtime)); > warnx("%s: unhandled type %d", file, entp->type); > break; > } > Index: repo.c > =================================================================== > RCS file: /cvs/src/usr.sbin/rpki-client/repo.c,v > retrieving revision 1.46 > diff -u -p -r1.46 repo.c > --- repo.c 25 May 2023 12:49:39 -0000 1.46 > +++ repo.c 30 May 2023 13:49:16 -0000 > @@ -119,6 +119,7 @@ static void remove_contents(char *); > struct filepath { > RB_ENTRY(filepath) entry; > char *file; > + time_t mtime; > }; > > static inline int > @@ -133,12 +134,13 @@ RB_PROTOTYPE(filepath_tree, filepath, en > * Functions to lookup which files have been accessed during computation. > */ > int > -filepath_add(struct filepath_tree *tree, char *file) > +filepath_add(struct filepath_tree *tree, char *file, time_t mtime) > { > struct filepath *fp; > > if ((fp = malloc(sizeof(*fp))) == NULL) > err(1, NULL); > + fp->mtime = mtime; > if ((fp->file = strdup(file)) == NULL) > err(1, NULL); > > @@ -838,7 +840,7 @@ rrdp_handle_file(unsigned int id, enum p > > /* write new content or mark uri as deleted. */ > if (pt == PUB_DEL) { > - filepath_add(&rr->deleted, uri); > + filepath_add(&rr->deleted, uri, 0); > } else { > fp = filepath_find(&rr->deleted, uri); > if (fp != NULL) > @@ -1536,6 +1538,27 @@ repo_move_valid(struct filepath_tree *tr > base = strchr(fp->file + rrdpsz, '/'); > assert(base != NULL); > fn = base + 1; > + > + /* > + * Adjust file last modification time in order to > + * minimize RSYNC synchronization load after transport > + * failover. While serializing RRDP datastructures to > + * disk, set the last modified timestamp to the CMS > + * signing-time or the X.509 notBefore timestamp. > + */ > + if (fp->mtime != 0) { > + int ret; > + struct timespec ts[2]; > + > + ts[0].tv_nsec = UTIME_OMIT; > + ts[1].tv_sec = fp->mtime; > + ts[1].tv_nsec = 0; > + ret = utimensat(AT_FDCWD, fp->file, ts, 0); > + if (ret == -1) { > + warn("utimensat %s", fp->file); > + continue; > + } > + } > } > > if (repo_mkpath(AT_FDCWD, fn) == -1) > -- :wq Claudio