Claudio Jeker([email protected]) on 2022.09.02 19:55:28 +0200:
> We want to be able to abort RRDP syncs. Now the problem is that depending
> on the state the abort request is more or less complex. What needs to be
> avoided is that a message received after the corresponding RRDP session
> was removed. This is mainly the RRDP_FILE and RRDP_HTTP_FIN messages that
> cause this.
>
> So once a RRDP_HTTP_INI message was received the abort code goes through
> most states, it just aborts the internal XML parser and closes the input
> fd.
ok.
> --
> :wq Claudio
>
> Index: extern.h
> ===================================================================
> RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v
> retrieving revision 1.151
> diff -u -p -r1.151 extern.h
> --- extern.h 30 Aug 2022 18:56:49 -0000 1.151
> +++ extern.h 2 Sep 2022 17:41:07 -0000
> @@ -408,6 +408,7 @@ enum rrdp_msg {
> RRDP_HTTP_REQ,
> RRDP_HTTP_INI,
> RRDP_HTTP_FIN,
> + RRDP_ABORT,
> };
>
> /*
> Index: rrdp.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/rpki-client/rrdp.c,v
> retrieving revision 1.24
> diff -u -p -r1.24 rrdp.c
> --- rrdp.c 15 May 2022 16:43:35 -0000 1.24
> +++ rrdp.c 2 Sep 2022 17:54:58 -0000
> @@ -57,6 +57,7 @@ struct rrdp {
> struct pollfd *pfd;
> int infd;
> int state;
> + int aborted;
> unsigned int file_pending;
> unsigned int file_failed;
> enum http_result res;
> @@ -73,7 +74,7 @@ struct rrdp {
> struct delta_xml *dxml;
> };
>
> -TAILQ_HEAD(, rrdp) states = TAILQ_HEAD_INITIALIZER(states);
> +static TAILQ_HEAD(, rrdp) states = TAILQ_HEAD_INITIALIZER(states);
>
> char *
> xstrdup(const char *s)
> @@ -256,7 +257,7 @@ rrdp_failed(struct rrdp *s)
> /* reset file state before retrying */
> s->file_failed = 0;
>
> - if (s->task == DELTA) {
> + if (s->task == DELTA && !s->aborted) {
> /* fallback to a snapshot as per RFC8182 */
> free_delta_xml(s->dxml);
> s->dxml = NULL;
> @@ -289,7 +290,7 @@ rrdp_finished(struct rrdp *s)
> if (s->file_pending > 0)
> return;
>
> - if (s->state & RRDP_STATE_PARSE_ERROR) {
> + if (s->state & RRDP_STATE_PARSE_ERROR || s->aborted) {
> rrdp_failed(s);
> return;
> }
> @@ -372,6 +373,34 @@ rrdp_finished(struct rrdp *s)
> }
>
> static void
> +rrdp_abort_req(struct rrdp *s)
> +{
> + unsigned int id = s->id;
> +
> + s->aborted = 1;
> + if (s->state == RRDP_STATE_REQ) {
> + /* nothing is pending, just abort */
> + rrdp_free(s);
> + rrdp_done(id, 1);
> + return;
> + }
> + if (s->state == RRDP_STATE_WAIT)
> + /* wait for HTTP_INI which will progress the state */
> + return;
> +
> + /*
> + * RRDP_STATE_PARSE or later, close infd, abort parser but
> + * wait for HTTP_FIN and file_pending to drop to 0.
> + */
> + if (s->infd != -1) {
> + close(s->infd);
> + s->infd = -1;
> + s->state |= RRDP_STATE_PARSE_DONE | RRDP_STATE_PARSE_ERROR;
> + }
> + rrdp_finished(s);
> +}
> +
> +static void
> rrdp_input_handler(int fd)
> {
> static struct ibuf *inbuf;
> @@ -408,12 +437,15 @@ rrdp_input_handler(int fd)
> errx(1, "expected fd not received");
> s = rrdp_get(id);
> if (s == NULL)
> - errx(1, "rrdp session %u does not exist", id);
> + errx(1, "http ini, rrdp session %u does not exist", id);
> if (s->state != RRDP_STATE_WAIT)
> errx(1, "%s: bad internal state", s->local);
> -
> s->infd = b->fd;
> s->state = RRDP_STATE_PARSE;
> + if (s->aborted) {
> + rrdp_abort_req(s);
> + break;
> + }
> break;
> case RRDP_HTTP_FIN:
> io_read_buf(b, &res, sizeof(res));
> @@ -423,20 +455,19 @@ rrdp_input_handler(int fd)
>
> s = rrdp_get(id);
> if (s == NULL)
> - errx(1, "rrdp session %u does not exist", id);
> + errx(1, "http fin, rrdp session %u does not exist", id);
> if (!(s->state & RRDP_STATE_PARSE))
> errx(1, "%s: bad internal state", s->local);
> -
> + s->state |= RRDP_STATE_HTTP_DONE;
> s->res = res;
> free(s->last_mod);
> s->last_mod = last_mod;
> - s->state |= RRDP_STATE_HTTP_DONE;
> rrdp_finished(s);
> break;
> case RRDP_FILE:
> s = rrdp_get(id);
> if (s == NULL)
> - errx(1, "rrdp session %u does not exist", id);
> + errx(1, "file, rrdp session %u does not exist", id);;
> if (b->fd != -1)
> errx(1, "received unexpected fd");
> io_read_buf(b, &ok, sizeof(ok));
> @@ -445,6 +476,13 @@ rrdp_input_handler(int fd)
> s->file_pending--;
> if (s->file_pending == 0)
> rrdp_finished(s);
> + break;
> + case RRDP_ABORT:
> + if (b->fd != -1)
> + errx(1, "received unexpected fd");
> + s = rrdp_get(id);
> + if (s != NULL)
> + rrdp_abort_req(s);
> break;
> default:
> errx(1, "unexpected message %d", type);
>