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?

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)

Reply via email to