xref: /openbsd/usr.sbin/rpki-client/main.c (revision 666d181c)
1 /*	$OpenBSD: main.c,v 1.278 2025/01/03 10:14:32 job Exp $ */
2 /*
3  * Copyright (c) 2021 Claudio Jeker <claudio@openbsd.org>
4  * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/types.h>
20 #include <sys/queue.h>
21 #include <sys/resource.h>
22 #include <sys/socket.h>
23 #include <sys/statvfs.h>
24 #include <sys/time.h>
25 #include <sys/tree.h>
26 #include <sys/wait.h>
27 
28 #include <assert.h>
29 #include <dirent.h>
30 #include <err.h>
31 #include <errno.h>
32 #include <fcntl.h>
33 #include <fnmatch.h>
34 #include <limits.h>
35 #include <poll.h>
36 #include <pwd.h>
37 #include <signal.h>
38 #include <stdarg.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <syslog.h>
43 #include <time.h>
44 #include <unistd.h>
45 
46 #include <imsg.h>
47 
48 #include "extern.h"
49 #include "version.h"
50 
51 const char	*tals[TALSZ_MAX];
52 const char	*taldescs[TALSZ_MAX];
53 unsigned int	 talrepocnt[TALSZ_MAX];
54 struct repotalstats talstats[TALSZ_MAX];
55 int		 talsz;
56 
57 size_t	entity_queue;
58 int	timeout = 60*60;
59 volatile sig_atomic_t killme;
60 void	suicide(int sig);
61 
62 static struct filepath_tree	fpt = RB_INITIALIZER(&fpt);
63 static struct msgbuf		*procq, *rsyncq, *httpq, *rrdpq;
64 static int			cachefd, outdirfd;
65 
66 int	verbose;
67 int	noop;
68 int	excludeas0 = 1;
69 int	excludeaspa;
70 int	filemode;
71 int	shortlistmode;
72 int	rrdpon = 1;
73 int	repo_timeout;
74 int	experimental;
75 time_t	deadline;
76 
77 /* 9999-12-31 23:59:59 UTC */
78 #define X509_TIME_MAX 253402300799LL
79 /* 0000-01-01 00:00:00 UTC */
80 #define X509_TIME_MIN -62167219200LL
81 
82 int64_t  evaluation_time = X509_TIME_MIN;
83 
84 struct stats	 stats;
85 
86 struct fqdnlistentry {
87 	LIST_ENTRY(fqdnlistentry)	 entry;
88 	char				*fqdn;
89 };
90 LIST_HEAD(fqdns, fqdnlistentry);
91 
92 struct fqdns shortlist = LIST_HEAD_INITIALIZER(fqdns);
93 struct fqdns skiplist = LIST_HEAD_INITIALIZER(fqdns);
94 
95 /*
96  * Log a message to stderr if and only if "verbose" is non-zero.
97  * This uses the err(3) functionality.
98  */
99 void
100 logx(const char *fmt, ...)
101 {
102 	va_list		 ap;
103 
104 	if (verbose && fmt != NULL) {
105 		va_start(ap, fmt);
106 		vwarnx(fmt, ap);
107 		va_end(ap);
108 	}
109 }
110 
111 time_t
112 getmonotime(void)
113 {
114 	struct timespec ts;
115 
116 	if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0)
117 		err(1, "clock_gettime");
118 	return (ts.tv_sec);
119 }
120 
121 /*
122  * Time - Evaluation time is used as the current time if it is
123  * larger than X509_TIME_MIN, otherwise the system time is used.
124  */
125 time_t
126 get_current_time(void)
127 {
128 	if (evaluation_time > X509_TIME_MIN)
129 		return (time_t)evaluation_time;
130 	return time(NULL);
131 }
132 
133 void
134 entity_free(struct entity *ent)
135 {
136 	if (ent == NULL)
137 		return;
138 
139 	free(ent->path);
140 	free(ent->file);
141 	free(ent->mftaki);
142 	free(ent->data);
143 	free(ent);
144 }
145 
146 /*
147  * Read a queue entity from the descriptor.
148  * Matched by entity_write_req().
149  * The pointer must be passed entity_free().
150  */
151 void
152 entity_read_req(struct ibuf *b, struct entity *ent)
153 {
154 	io_read_buf(b, &ent->type, sizeof(ent->type));
155 	io_read_buf(b, &ent->location, sizeof(ent->location));
156 	io_read_buf(b, &ent->repoid, sizeof(ent->repoid));
157 	io_read_buf(b, &ent->talid, sizeof(ent->talid));
158 	io_read_buf(b, &ent->certid, sizeof(ent->certid));
159 	io_read_str(b, &ent->path);
160 	io_read_str(b, &ent->file);
161 	io_read_str(b, &ent->mftaki);
162 	io_read_buf_alloc(b, (void **)&ent->data, &ent->datasz);
163 }
164 
165 /*
166  * Write the queue entity.
167  * Matched by entity_read_req().
168  */
169 static void
170 entity_write_req(const struct entity *ent)
171 {
172 	struct ibuf *b;
173 
174 	b = io_new_buffer();
175 	io_simple_buffer(b, &ent->type, sizeof(ent->type));
176 	io_simple_buffer(b, &ent->location, sizeof(ent->location));
177 	io_simple_buffer(b, &ent->repoid, sizeof(ent->repoid));
178 	io_simple_buffer(b, &ent->talid, sizeof(ent->talid));
179 	io_simple_buffer(b, &ent->certid, sizeof(ent->certid));
180 	io_str_buffer(b, ent->path);
181 	io_str_buffer(b, ent->file);
182 	io_str_buffer(b, ent->mftaki);
183 	io_buf_buffer(b, ent->data, ent->datasz);
184 	io_close_buffer(procq, b);
185 }
186 
187 static void
188 entity_write_repo(const struct repo *rp)
189 {
190 	struct ibuf *b;
191 	enum rtype type = RTYPE_REPO;
192 	enum location loc = DIR_UNKNOWN;
193 	unsigned int repoid;
194 	char *path, *altpath;
195 	int talid = 0, certid = 0;
196 
197 	repoid = repo_id(rp);
198 	path = repo_basedir(rp, 0);
199 	altpath = repo_basedir(rp, 1);
200 	b = io_new_buffer();
201 	io_simple_buffer(b, &type, sizeof(type));
202 	io_simple_buffer(b, &loc, sizeof(loc));
203 	io_simple_buffer(b, &repoid, sizeof(repoid));
204 	io_simple_buffer(b, &talid, sizeof(talid));
205 	io_simple_buffer(b, &certid, sizeof(certid));
206 	io_str_buffer(b, path);
207 	io_str_buffer(b, altpath);
208 	io_buf_buffer(b, NULL, 0); /* ent->mftaki */
209 	io_buf_buffer(b, NULL, 0); /* ent->data */
210 	io_close_buffer(procq, b);
211 	free(path);
212 	free(altpath);
213 }
214 
215 /*
216  * Scan through all queued requests and see which ones are in the given
217  * repo, then flush those into the parser process.
218  */
219 void
220 entityq_flush(struct entityq *q, struct repo *rp)
221 {
222 	struct entity	*p, *np;
223 
224 	entity_write_repo(rp);
225 
226 	TAILQ_FOREACH_SAFE(p, q, entries, np) {
227 		entity_write_req(p);
228 		TAILQ_REMOVE(q, p, entries);
229 		entity_free(p);
230 	}
231 }
232 
233 /*
234  * Add the heap-allocated file to the queue for processing.
235  */
236 static void
237 entityq_add(char *path, char *file, enum rtype type, enum location loc,
238     struct repo *rp, unsigned char *data, size_t datasz, int talid, int certid,
239     char *mftaki)
240 {
241 	struct entity	*p;
242 
243 	if ((p = calloc(1, sizeof(struct entity))) == NULL)
244 		err(1, NULL);
245 
246 	p->type = type;
247 	p->location = loc;
248 	p->talid = talid;
249 	p->certid = certid;
250 	p->mftaki = mftaki;
251 	p->path = path;
252 	if (rp != NULL)
253 		p->repoid = repo_id(rp);
254 	p->file = file;
255 	p->data = data;
256 	p->datasz = (data != NULL) ? datasz : 0;
257 
258 	entity_queue++;
259 
260 	/*
261 	 * Write to the queue if there's no repo or the repo has already
262 	 * been loaded else enqueue it for later.
263 	 */
264 
265 	if (rp == NULL || !repo_queued(rp, p)) {
266 		entity_write_req(p);
267 		entity_free(p);
268 	}
269 }
270 
271 static void
272 rrdp_file_resp(unsigned int id, int ok)
273 {
274 	enum rrdp_msg type = RRDP_FILE;
275 	struct ibuf *b;
276 
277 	b = io_new_buffer();
278 	io_simple_buffer(b, &type, sizeof(type));
279 	io_simple_buffer(b, &id, sizeof(id));
280 	io_simple_buffer(b, &ok, sizeof(ok));
281 	io_close_buffer(rrdpq, b);
282 }
283 
284 void
285 rrdp_fetch(unsigned int id, const char *uri, const char *local,
286     struct rrdp_session *s)
287 {
288 	enum rrdp_msg type = RRDP_START;
289 	struct ibuf *b;
290 
291 	b = io_new_buffer();
292 	io_simple_buffer(b, &type, sizeof(type));
293 	io_simple_buffer(b, &id, sizeof(id));
294 	io_str_buffer(b, local);
295 	io_str_buffer(b, uri);
296 
297 	rrdp_session_buffer(b, s);
298 	io_close_buffer(rrdpq, b);
299 }
300 
301 void
302 rrdp_abort(unsigned int id)
303 {
304 	enum rrdp_msg type = RRDP_ABORT;
305 	struct ibuf *b;
306 
307 	b = io_new_buffer();
308 	io_simple_buffer(b, &type, sizeof(type));
309 	io_simple_buffer(b, &id, sizeof(id));
310 	io_close_buffer(rrdpq, b);
311 }
312 
313 /*
314  * Request a repository sync via rsync URI to directory local.
315  */
316 void
317 rsync_fetch(unsigned int id, const char *uri, const char *local,
318     const char *base)
319 {
320 	struct ibuf	*b;
321 
322 	b = io_new_buffer();
323 	io_simple_buffer(b, &id, sizeof(id));
324 	io_str_buffer(b, local);
325 	io_str_buffer(b, base);
326 	io_str_buffer(b, uri);
327 	io_close_buffer(rsyncq, b);
328 }
329 
330 void
331 rsync_abort(unsigned int id)
332 {
333 	struct ibuf	*b;
334 
335 	b = io_new_buffer();
336 	io_simple_buffer(b, &id, sizeof(id));
337 	io_str_buffer(b, NULL);
338 	io_str_buffer(b, NULL);
339 	io_str_buffer(b, NULL);
340 	io_close_buffer(rsyncq, b);
341 }
342 
343 /*
344  * Request a file from a https uri, data is written to the file descriptor fd.
345  */
346 void
347 http_fetch(unsigned int id, const char *uri, const char *last_mod, int fd)
348 {
349 	struct ibuf	*b;
350 
351 	b = io_new_buffer();
352 	io_simple_buffer(b, &id, sizeof(id));
353 	io_str_buffer(b, uri);
354 	io_str_buffer(b, last_mod);
355 	/* pass file as fd */
356 	ibuf_fd_set(b, fd);
357 	io_close_buffer(httpq, b);
358 }
359 
360 /*
361  * Request some XML file on behalf of the rrdp parser.
362  * Create a pipe and pass the pipe endpoints to the http and rrdp process.
363  */
364 static void
365 rrdp_http_fetch(unsigned int id, const char *uri, const char *last_mod)
366 {
367 	enum rrdp_msg type = RRDP_HTTP_INI;
368 	struct ibuf *b;
369 	int pi[2];
370 
371 	if (pipe2(pi, O_CLOEXEC | O_NONBLOCK) == -1)
372 		err(1, "pipe");
373 
374 	b = io_new_buffer();
375 	io_simple_buffer(b, &type, sizeof(type));
376 	io_simple_buffer(b, &id, sizeof(id));
377 	ibuf_fd_set(b, pi[0]);
378 	io_close_buffer(rrdpq, b);
379 
380 	http_fetch(id, uri, last_mod, pi[1]);
381 }
382 
383 void
384 rrdp_http_done(unsigned int id, enum http_result res, const char *last_mod)
385 {
386 	enum rrdp_msg type = RRDP_HTTP_FIN;
387 	struct ibuf *b;
388 
389 	/* RRDP request, relay response over to the rrdp process */
390 	b = io_new_buffer();
391 	io_simple_buffer(b, &type, sizeof(type));
392 	io_simple_buffer(b, &id, sizeof(id));
393 	io_simple_buffer(b, &res, sizeof(res));
394 	io_str_buffer(b, last_mod);
395 	io_close_buffer(rrdpq, b);
396 }
397 
398 /*
399  * Add a file (CER, ROA, CRL) from an MFT file, RFC 6486.
400  * These are always relative to the directory in which "mft" sits.
401  */
402 static void
403 queue_add_from_mft(const struct mft *mft)
404 {
405 	size_t			 i;
406 	struct repo		*rp;
407 	const struct mftfile	*f;
408 	char			*mftaki, *nfile, *npath = NULL;
409 
410 	rp = repo_byid(mft->repoid);
411 	for (i = 0; i < mft->filesz; i++) {
412 		f = &mft->files[i];
413 
414 		if (f->type == RTYPE_INVALID || f->type == RTYPE_CRL)
415 			continue;
416 
417 		if (mft->path != NULL)
418 			if ((npath = strdup(mft->path)) == NULL)
419 				err(1, NULL);
420 		if ((nfile = strdup(f->file)) == NULL)
421 			err(1, NULL);
422 		if ((mftaki = strdup(mft->aki)) == NULL)
423 			err(1, NULL);
424 		entityq_add(npath, nfile, f->type, f->location, rp, NULL, 0,
425 		    mft->talid, mft->certid, mftaki);
426 	}
427 }
428 
429 /*
430  * Add a local file to the queue of files to fetch.
431  */
432 static void
433 queue_add_file(const char *file, enum rtype type, int talid)
434 {
435 	unsigned char	*buf = NULL;
436 	char		*nfile;
437 	size_t		 len = 0;
438 
439 	if (!filemode || strncmp(file, RSYNC_PROTO, RSYNC_PROTO_LEN) != 0) {
440 		buf = load_file(file, &len);
441 		if (buf == NULL)
442 			err(1, "%s", file);
443 	}
444 
445 	if ((nfile = strdup(file)) == NULL)
446 		err(1, NULL);
447 	/* Not in a repository, so directly add to queue. */
448 	entityq_add(NULL, nfile, type, DIR_UNKNOWN, NULL, buf, len, talid, 0,
449 	    NULL);
450 }
451 
452 /*
453  * Add URIs (CER) from a TAL file, RFC 8630.
454  */
455 static void
456 queue_add_from_tal(struct tal *tal)
457 {
458 	struct repo	*repo;
459 	unsigned char	*data;
460 	char		*nfile;
461 
462 	assert(tal->num_uris > 0);
463 
464 	if ((taldescs[tal->id] = strdup(tal->descr)) == NULL)
465 		err(1, NULL);
466 
467 	/* figure out the TA filename, must be done before repo lookup */
468 	nfile = strrchr(tal->uri[0], '/');
469 	assert(nfile != NULL);
470 	if ((nfile = strdup(nfile + 1)) == NULL)
471 		err(1, NULL);
472 
473 	/* Look up the repository. */
474 	repo = ta_lookup(tal->id, tal);
475 	if (repo == NULL) {
476 		free(nfile);
477 		return;
478 	}
479 
480 	/* steal the pkey from the tal structure */
481 	data = tal->pkey;
482 	tal->pkey = NULL;
483 	entityq_add(NULL, nfile, RTYPE_CER, DIR_UNKNOWN, repo, data,
484 	    tal->pkeysz, tal->id, tal->id, NULL);
485 }
486 
487 /*
488  * Add a manifest (MFT) found in an X509 certificate, RFC 6487.
489  */
490 static void
491 queue_add_from_cert(const struct cert *cert)
492 {
493 	struct repo		*repo;
494 	struct fqdnlistentry	*le;
495 	char			*nfile, *npath, *host;
496 	const char		*uri, *repouri, *file;
497 	size_t			 repourisz;
498 	int			 shortlisted = 0;
499 
500 	if (strncmp(cert->repo, RSYNC_PROTO, RSYNC_PROTO_LEN) != 0)
501 		errx(1, "unexpected protocol");
502 	host = cert->repo + RSYNC_PROTO_LEN;
503 
504 	LIST_FOREACH(le, &skiplist, entry) {
505 		if (strncasecmp(host, le->fqdn, strcspn(host, "/")) == 0) {
506 			warnx("skipping %s (listed in skiplist)", cert->repo);
507 			return;
508 		}
509 	}
510 
511 	LIST_FOREACH(le, &shortlist, entry) {
512 		if (strncasecmp(host, le->fqdn, strcspn(host, "/")) == 0) {
513 			shortlisted = 1;
514 			break;
515 		}
516 	}
517 	if (shortlistmode && shortlisted == 0) {
518 		if (verbose)
519 			warnx("skipping %s (not shortlisted)", cert->repo);
520 		return;
521 	}
522 
523 	repo = repo_lookup(cert->talid, cert->repo,
524 	    rrdpon ? cert->notify : NULL);
525 	if (repo == NULL)
526 		return;
527 
528 	/*
529 	 * Figure out the cert filename and path by chopping up the
530 	 * MFT URI in the cert based on the repo base URI.
531 	 */
532 	uri = cert->mft;
533 	repouri = repo_uri(repo);
534 	repourisz = strlen(repouri);
535 	if (strncmp(repouri, cert->mft, repourisz) != 0) {
536 		warnx("%s: URI %s outside of repository", repouri, uri);
537 		return;
538 	}
539 	uri += repourisz + 1;	/* skip base and '/' */
540 	file = strrchr(uri, '/');
541 	if (file == NULL) {
542 		npath = NULL;
543 		if ((nfile = strdup(uri)) == NULL)
544 			err(1, NULL);
545 	} else {
546 		if ((npath = strndup(uri, file - uri)) == NULL)
547 			err(1, NULL);
548 		if ((nfile = strdup(file + 1)) == NULL)
549 			err(1, NULL);
550 	}
551 
552 	entityq_add(npath, nfile, RTYPE_MFT, DIR_UNKNOWN, repo, NULL, 0,
553 	    cert->talid, cert->certid, NULL);
554 }
555 
556 /*
557  * Process parsed content.
558  * For non-ROAs, we grok for more data.
559  * For ROAs, we want to extract the valid info.
560  * In all cases, we gather statistics.
561  */
562 static void
563 entity_process(struct ibuf *b, struct stats *st, struct vrp_tree *tree,
564     struct brk_tree *brktree, struct vap_tree *vaptree,
565     struct vsp_tree *vsptree)
566 {
567 	enum rtype	 type;
568 	struct tal	*tal;
569 	struct cert	*cert;
570 	struct mft	*mft;
571 	struct roa	*roa;
572 	struct aspa	*aspa;
573 	struct spl	*spl;
574 	struct repo	*rp;
575 	char		*file;
576 	time_t		 mtime;
577 	unsigned int	 id;
578 	int		 talid;
579 	int		 ok = 1;
580 
581 	/*
582 	 * For most of these, we first read whether there's any content
583 	 * at all---this means that the syntactic parse failed (X509
584 	 * certificate, for example).
585 	 * We follow that up with whether the resources didn't parse.
586 	 */
587 	io_read_buf(b, &type, sizeof(type));
588 	io_read_buf(b, &id, sizeof(id));
589 	io_read_buf(b, &talid, sizeof(talid));
590 	io_read_str(b, &file);
591 	io_read_buf(b, &mtime, sizeof(mtime));
592 
593 	/* in filemode messages can be ignored, only the accounting matters */
594 	if (filemode)
595 		goto done;
596 
597 	if (filepath_valid(&fpt, file, talid)) {
598 		warnx("%s: File already visited", file);
599 		goto done;
600 	}
601 
602 	rp = repo_byid(id);
603 	repo_stat_inc(rp, talid, type, STYPE_OK);
604 	repostats_new_files_inc(rp, file);
605 	switch (type) {
606 	case RTYPE_TAL:
607 		st->tals++;
608 		tal = tal_read(b);
609 		queue_add_from_tal(tal);
610 		tal_free(tal);
611 		break;
612 	case RTYPE_CER:
613 		io_read_buf(b, &ok, sizeof(ok));
614 		if (ok == 0) {
615 			repo_stat_inc(rp, talid, type, STYPE_FAIL);
616 			break;
617 		}
618 		cert = cert_read(b);
619 		switch (cert->purpose) {
620 		case CERT_PURPOSE_TA:
621 		case CERT_PURPOSE_CA:
622 			queue_add_from_cert(cert);
623 			break;
624 		case CERT_PURPOSE_BGPSEC_ROUTER:
625 			cert_insert_brks(brktree, cert);
626 			repo_stat_inc(rp, talid, type, STYPE_BGPSEC);
627 			break;
628 		default:
629 			errx(1, "unexpected %s", purpose2str(cert->purpose));
630 			break;
631 		}
632 		cert_free(cert);
633 		break;
634 	case RTYPE_MFT:
635 		io_read_buf(b, &ok, sizeof(ok));
636 		if (ok == 0) {
637 			repo_stat_inc(rp, talid, type, STYPE_FAIL);
638 			break;
639 		}
640 		mft = mft_read(b);
641 		if (mft->seqnum_gap)
642 			repo_stat_inc(rp, talid, type, STYPE_SEQNUM_GAP);
643 		queue_add_from_mft(mft);
644 		mft_free(mft);
645 		break;
646 	case RTYPE_CRL:
647 		/* CRLs are sent together with MFT and not accounted for */
648 		entity_queue++;
649 		break;
650 	case RTYPE_ROA:
651 		io_read_buf(b, &ok, sizeof(ok));
652 		if (ok == 0) {
653 			repo_stat_inc(rp, talid, type, STYPE_FAIL);
654 			break;
655 		}
656 		roa = roa_read(b);
657 		if (roa->valid)
658 			roa_insert_vrps(tree, roa, rp);
659 		else
660 			repo_stat_inc(rp, talid, type, STYPE_INVALID);
661 		roa_free(roa);
662 		break;
663 	case RTYPE_GBR:
664 		break;
665 	case RTYPE_ASPA:
666 		io_read_buf(b, &ok, sizeof(ok));
667 		if (ok == 0) {
668 			repo_stat_inc(rp, talid, type, STYPE_FAIL);
669 			break;
670 		}
671 		aspa = aspa_read(b);
672 		if (aspa->valid)
673 			aspa_insert_vaps(file, vaptree, aspa, rp);
674 		else
675 			repo_stat_inc(rp, talid, type, STYPE_INVALID);
676 		aspa_free(aspa);
677 		break;
678 	case RTYPE_SPL:
679 		io_read_buf(b, &ok, sizeof(ok));
680 		if (ok == 0) {
681 			if (experimental)
682 				repo_stat_inc(rp, talid, type, STYPE_FAIL);
683 			break;
684 		}
685 		spl = spl_read(b);
686 		if (spl->valid)
687 			spl_insert_vsps(vsptree, spl, rp);
688 		else
689 			repo_stat_inc(rp, talid, type, STYPE_INVALID);
690 		spl_free(spl);
691 		break;
692 	case RTYPE_TAK:
693 		break;
694 	case RTYPE_FILE:
695 		break;
696 	default:
697 		warnx("%s: unknown entity type %d", file, type);
698 		break;
699 	}
700 
701 	if (filepath_add(&fpt, file, talid, mtime, ok) == 0)
702 		errx(1, "%s: File already in tree", file);
703 
704 done:
705 	free(file);
706 	entity_queue--;
707 }
708 
709 static void
710 rrdp_process(struct ibuf *b)
711 {
712 	enum rrdp_msg type;
713 	enum publish_type pt;
714 	struct rrdp_session *s;
715 	char *uri, *last_mod, *data;
716 	char hash[SHA256_DIGEST_LENGTH];
717 	size_t dsz;
718 	unsigned int id;
719 	int ok;
720 
721 	io_read_buf(b, &type, sizeof(type));
722 	io_read_buf(b, &id, sizeof(id));
723 
724 	switch (type) {
725 	case RRDP_END:
726 		io_read_buf(b, &ok, sizeof(ok));
727 		rrdp_finish(id, ok);
728 		break;
729 	case RRDP_HTTP_REQ:
730 		io_read_str(b, &uri);
731 		io_read_str(b, &last_mod);
732 		rrdp_http_fetch(id, uri, last_mod);
733 		break;
734 	case RRDP_SESSION:
735 		s = rrdp_session_read(b);
736 		rrdp_session_save(id, s);
737 		rrdp_session_free(s);
738 		break;
739 	case RRDP_FILE:
740 		io_read_buf(b, &pt, sizeof(pt));
741 		if (pt != PUB_ADD)
742 			io_read_buf(b, &hash, sizeof(hash));
743 		io_read_str(b, &uri);
744 		io_read_buf_alloc(b, (void **)&data, &dsz);
745 
746 		ok = rrdp_handle_file(id, pt, uri, hash, sizeof(hash),
747 		    data, dsz);
748 		rrdp_file_resp(id, ok);
749 
750 		free(uri);
751 		free(data);
752 		break;
753 	case RRDP_CLEAR:
754 		rrdp_clear(id);
755 		break;
756 	default:
757 		errx(1, "unexpected rrdp response");
758 	}
759 }
760 
761 static void
762 sum_stats(const struct repo *rp, const struct repotalstats *in, void *arg)
763 {
764 	struct repotalstats *out = arg;
765 
766 	out->mfts += in->mfts;
767 	out->mfts_fail += in->mfts_fail;
768 	out->mfts_gap += in->mfts_gap;
769 	out->certs += in->certs;
770 	out->certs_fail += in->certs_fail;
771 	out->roas += in->roas;
772 	out->roas_fail += in->roas_fail;
773 	out->roas_invalid += in->roas_invalid;
774 	out->aspas += in->aspas;
775 	out->aspas_fail += in->aspas_fail;
776 	out->aspas_invalid += in->aspas_invalid;
777 	out->brks += in->brks;
778 	out->crls += in->crls;
779 	out->gbrs += in->gbrs;
780 	out->taks += in->taks;
781 	out->vrps += in->vrps;
782 	out->vrps_uniqs += in->vrps_uniqs;
783 	out->vaps += in->vaps;
784 	out->vaps_uniqs += in->vaps_uniqs;
785 	out->vaps_pas += in->vaps_pas;
786 	out->vaps_overflowed += in->vaps_overflowed;
787 	out->spls += in->spls;
788 	out->spls_fail += in->spls_fail;
789 	out->spls_invalid += in->spls_invalid;
790 	out->vsps += in->vsps;
791 	out->vsps_uniqs += in->vsps_uniqs;
792 }
793 
794 static void
795 sum_repostats(const struct repo *rp, const struct repostats *in, void *arg)
796 {
797 	struct repostats *out = arg;
798 
799 	out->del_files += in->del_files;
800 	out->extra_files += in->extra_files;
801 	out->del_extra_files += in->del_extra_files;
802 	out->del_dirs += in->del_dirs;
803 	out->new_files += in->new_files;
804 	timespecadd(&in->sync_time, &out->sync_time, &out->sync_time);
805 }
806 
807 /*
808  * Assign filenames ending in ".tal" in "/etc/rpki" into "tals",
809  * returning the number of files found and filled-in.
810  * This may be zero.
811  * Don't exceed "max" filenames.
812  */
813 static int
814 tal_load_default(void)
815 {
816 	static const char *confdir = "/etc/rpki";
817 	int s = 0;
818 	char *path;
819 	DIR *dirp;
820 	struct dirent *dp;
821 
822 	dirp = opendir(confdir);
823 	if (dirp == NULL)
824 		err(1, "open %s", confdir);
825 	while ((dp = readdir(dirp)) != NULL) {
826 		if (fnmatch("*.tal", dp->d_name, FNM_PERIOD) == FNM_NOMATCH)
827 			continue;
828 		if (s >= TALSZ_MAX)
829 			err(1, "too many tal files found in %s",
830 			    confdir);
831 		if (asprintf(&path, "%s/%s", confdir, dp->d_name) == -1)
832 			err(1, NULL);
833 		tals[s++] = path;
834 	}
835 	closedir(dirp);
836 	return s;
837 }
838 
839 /*
840  * Load the list of FQDNs from the skiplist which are to be distrusted.
841  * Return 0 on success.
842  */
843 static void
844 load_skiplist(const char *slf)
845 {
846 	struct fqdnlistentry	*le;
847 	FILE			*fp;
848 	char			*line = NULL;
849 	size_t			 linesize = 0, linelen;
850 
851 	if ((fp = fopen(slf, "r")) == NULL) {
852 		if (errno == ENOENT && strcmp(slf, DEFAULT_SKIPLIST_FILE) == 0)
853 			return;
854 		err(1, "failed to open %s", slf);
855 	}
856 
857 	while (getline(&line, &linesize, fp) != -1) {
858 		/* just eat comment lines or empty lines*/
859 		if (line[0] == '#' || line[0] == '\n')
860 			continue;
861 
862 		if (line[0] == ' ' || line[0] == '\t')
863 			errx(1, "invalid entry in skiplist: %s", line);
864 
865 		/*
866 		 * Ignore anything after comment sign, whitespaces,
867 		 * also chop off LF or CR.
868 		 */
869 		linelen = strcspn(line, " #\r\n\t");
870 		line[linelen] = '\0';
871 
872 		if (!valid_uri(line, linelen, NULL))
873 			errx(1, "invalid entry in skiplist: %s", line);
874 
875 		if ((le = malloc(sizeof(struct fqdnlistentry))) == NULL)
876 			err(1, NULL);
877 		if ((le->fqdn = strdup(line)) == NULL)
878 			err(1, NULL);
879 
880 		LIST_INSERT_HEAD(&skiplist, le, entry);
881 		stats.skiplistentries++;
882 	}
883 	if (ferror(fp))
884 		err(1, "error reading %s", slf);
885 
886 	fclose(fp);
887 	free(line);
888 }
889 
890 /*
891  * Load shortlist entries.
892  */
893 static void
894 load_shortlist(const char *fqdn)
895 {
896 	struct fqdnlistentry	*le;
897 
898 	if (!valid_uri(fqdn, strlen(fqdn), NULL))
899 		errx(1, "invalid fqdn passed to -q: %s", fqdn);
900 
901 	if ((le = malloc(sizeof(struct fqdnlistentry))) == NULL)
902 		err(1, NULL);
903 
904 	if ((le->fqdn = strdup(fqdn)) == NULL)
905 		err(1, NULL);
906 
907 	LIST_INSERT_HEAD(&shortlist, le, entry);
908 }
909 
910 static void
911 check_fs_size(int fd, const char *cachedir)
912 {
913 	struct statvfs		fs;
914 	unsigned long long	minsize = 500 * 1024 * 1024;
915 	unsigned long long	minnode = 300 * 1000;
916 
917 	if (fstatvfs(fd, &fs) == -1)
918 		err(1, "statfs %s", cachedir);
919 
920 	if (fs.f_bavail < minsize / fs.f_frsize ||
921 	    (fs.f_ffree > 0 && fs.f_favail < minnode)) {
922 		fprintf(stderr, "WARNING: rpki-client may need more than "
923 		    "the available disk space\n"
924 		    "on the file-system holding %s.\n", cachedir);
925 		fprintf(stderr, "available space: %llukB, "
926 		    "suggested minimum %llukB\n",
927 		    (unsigned long long)fs.f_bavail * fs.f_frsize / 1024,
928 		    minsize / 1024);
929 		fprintf(stderr, "available inodes: %llu, "
930 		    "suggested minimum: %llu\n\n",
931 		    (unsigned long long)fs.f_favail, minnode);
932 		fflush(stderr);
933 	}
934 }
935 
936 static pid_t
937 process_start(const char *title, int *fd)
938 {
939 	int		 fl = SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK;
940 	pid_t		 pid;
941 	int		 pair[2];
942 
943 	if (socketpair(AF_UNIX, fl, 0, pair) == -1)
944 		err(1, "socketpair");
945 	if ((pid = fork()) == -1)
946 		err(1, "fork");
947 
948 	if (pid == 0) {
949 		setproctitle("%s", title);
950 		/* change working directory to the cache directory */
951 		if (fchdir(cachefd) == -1)
952 			err(1, "fchdir");
953 		if (!filemode && timeout > 0)
954 			alarm(timeout);
955 		close(pair[1]);
956 		*fd = pair[0];
957 	} else {
958 		close(pair[0]);
959 		*fd = pair[1];
960 	}
961 	return pid;
962 }
963 
964 void
965 suicide(int sig __attribute__((unused)))
966 {
967 	killme = 1;
968 }
969 
970 #define NPFD	4
971 
972 int
973 main(int argc, char *argv[])
974 {
975 	int		 rc, c, i, st, hangup = 0;
976 	int		 procfd, rsyncfd, httpfd, rrdpfd;
977 	pid_t		 pid, procpid, rsyncpid, httppid, rrdppid;
978 	struct pollfd	 pfd[NPFD];
979 	struct msgbuf	*queues[NPFD];
980 	struct ibuf	*b;
981 	char		*rsync_prog = "openrsync";
982 	char		*bind_addr = NULL;
983 	const char	*cachedir = NULL, *outputdir = NULL;
984 	const char	*errs, *name;
985 	const char	*skiplistfile = NULL;
986 	struct vrp_tree	 vrps = RB_INITIALIZER(&vrps);
987 	struct vsp_tree	 vsps = RB_INITIALIZER(&vsps);
988 	struct brk_tree	 brks = RB_INITIALIZER(&brks);
989 	struct vap_tree	 vaps = RB_INITIALIZER(&vaps);
990 	struct rusage	 ru;
991 	struct timespec	 start_time, now_time;
992 
993 	clock_gettime(CLOCK_MONOTONIC, &start_time);
994 
995 	/* If started as root, priv-drop to _rpki-client */
996 	if (getuid() == 0) {
997 		struct passwd *pw;
998 
999 		pw = getpwnam("_rpki-client");
1000 		if (!pw)
1001 			errx(1, "no _rpki-client user to revoke to");
1002 		if (setgroups(1, &pw->pw_gid) == -1 ||
1003 		    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1 ||
1004 		    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1)
1005 			err(1, "unable to revoke privs");
1006 	}
1007 	cachedir = RPKI_PATH_BASE_DIR;
1008 	outputdir = RPKI_PATH_OUT_DIR;
1009 	repo_timeout = timeout / 4;
1010 	skiplistfile = DEFAULT_SKIPLIST_FILE;
1011 
1012 	if (pledge("stdio rpath wpath cpath inet fattr dns sendfd recvfd "
1013 	    "proc exec unveil", NULL) == -1)
1014 		err(1, "pledge");
1015 
1016 	while ((c =
1017 	    getopt(argc, argv, "0Ab:Bcd:e:fH:jmnoP:Rs:S:t:vVx")) != -1)
1018 		switch (c) {
1019 		case '0':
1020 			excludeas0 = 0;
1021 			break;
1022 		case 'A':
1023 			excludeaspa = 1;
1024 			break;
1025 		case 'b':
1026 			bind_addr = optarg;
1027 			break;
1028 		case 'B':
1029 			outformats |= FORMAT_BIRD;
1030 			break;
1031 		case 'c':
1032 			outformats |= FORMAT_CSV;
1033 			break;
1034 		case 'd':
1035 			cachedir = optarg;
1036 			break;
1037 		case 'e':
1038 			rsync_prog = optarg;
1039 			break;
1040 		case 'f':
1041 			filemode = 1;
1042 			noop = 1;
1043 			break;
1044 		case 'H':
1045 			shortlistmode = 1;
1046 			load_shortlist(optarg);
1047 			break;
1048 		case 'j':
1049 			outformats |= FORMAT_JSON;
1050 			break;
1051 		case 'm':
1052 			outformats |= FORMAT_OMETRIC;
1053 			break;
1054 		case 'n':
1055 			noop = 1;
1056 			break;
1057 		case 'o':
1058 			outformats |= FORMAT_OPENBGPD;
1059 			break;
1060 		case 'P':
1061 			evaluation_time = strtonum(optarg, X509_TIME_MIN + 1,
1062 			    X509_TIME_MAX, &errs);
1063 			if (errs)
1064 				errx(1, "-P: time in seconds %s", errs);
1065 			break;
1066 		case 'R':
1067 			rrdpon = 0;
1068 			break;
1069 		case 's':
1070 			timeout = strtonum(optarg, 0, 24*60*60, &errs);
1071 			if (errs)
1072 				errx(1, "-s: %s", errs);
1073 			if (timeout == 0)
1074 				repo_timeout = 24*60*60;
1075 			else
1076 				repo_timeout = timeout / 4;
1077 			break;
1078 		case 'S':
1079 			skiplistfile = optarg;
1080 			break;
1081 		case 't':
1082 			if (talsz >= TALSZ_MAX)
1083 				err(1, "too many tal files specified");
1084 			tals[talsz++] = optarg;
1085 			break;
1086 		case 'v':
1087 			verbose++;
1088 			break;
1089 		case 'V':
1090 			fprintf(stderr, "rpki-client %s\n", RPKI_VERSION);
1091 			return 0;
1092 		case 'x':
1093 			experimental = 1;
1094 			break;
1095 		default:
1096 			goto usage;
1097 		}
1098 
1099 	argv += optind;
1100 	argc -= optind;
1101 
1102 	if (!filemode) {
1103 		if (argc == 1)
1104 			outputdir = argv[0];
1105 		else if (argc > 1)
1106 			goto usage;
1107 
1108 		if (outputdir == NULL) {
1109 			warnx("output directory required");
1110 			goto usage;
1111 		}
1112 	} else {
1113 		if (argc == 0)
1114 			goto usage;
1115 		outputdir = NULL;
1116 	}
1117 
1118 	if (cachedir == NULL) {
1119 		warnx("cache directory required");
1120 		goto usage;
1121 	}
1122 
1123 	signal(SIGPIPE, SIG_IGN);
1124 
1125 	if ((cachefd = open(cachedir, O_RDONLY | O_DIRECTORY)) == -1)
1126 		err(1, "cache directory %s", cachedir);
1127 	if (outputdir != NULL) {
1128 		if ((outdirfd = open(outputdir, O_RDONLY | O_DIRECTORY)) == -1)
1129 			err(1, "output directory %s", outputdir);
1130 		if (outformats == 0)
1131 			outformats = FORMAT_OPENBGPD;
1132 	}
1133 
1134 	check_fs_size(cachefd, cachedir);
1135 
1136 	if (talsz == 0)
1137 		talsz = tal_load_default();
1138 	if (talsz == 0)
1139 		err(1, "no TAL files found in %s", "/etc/rpki");
1140 
1141 	/* Load optional constraint files sitting next to the TALs. */
1142 	constraints_load();
1143 
1144 	/*
1145 	 * Create the file reader as a jailed child process.
1146 	 * It will be responsible for reading all of the files (ROAs,
1147 	 * manifests, certificates, etc.) and returning contents.
1148 	 */
1149 
1150 	procpid = process_start("parser", &procfd);
1151 	if (procpid == 0) {
1152 		if (!filemode)
1153 			proc_parser(procfd);
1154 		else
1155 			proc_filemode(procfd);
1156 	}
1157 
1158 	/* Constraints are only needed in the filemode and parser processes. */
1159 	constraints_unload();
1160 
1161 	/*
1162 	 * Create a process that will do the rsync'ing.
1163 	 * This process is responsible for making sure that all the
1164 	 * repositories referenced by a certificate manifest (or the
1165 	 * TAL) exists and has been downloaded.
1166 	 */
1167 
1168 	if (!noop) {
1169 		rsyncpid = process_start("rsync", &rsyncfd);
1170 		if (rsyncpid == 0) {
1171 			close(procfd);
1172 			proc_rsync(rsync_prog, bind_addr, rsyncfd);
1173 		}
1174 	} else {
1175 		rsyncfd = -1;
1176 		rsyncpid = -1;
1177 	}
1178 
1179 	/*
1180 	 * Create a process that will fetch data via https.
1181 	 * With every request the http process receives a file descriptor
1182 	 * where the data should be written to.
1183 	 */
1184 
1185 	if (!noop && rrdpon) {
1186 		httppid = process_start("http", &httpfd);
1187 
1188 		if (httppid == 0) {
1189 			close(procfd);
1190 			close(rsyncfd);
1191 			proc_http(bind_addr, httpfd);
1192 		}
1193 	} else {
1194 		httpfd = -1;
1195 		httppid = -1;
1196 	}
1197 
1198 	/*
1199 	 * Create a process that will process RRDP.
1200 	 * The rrdp process requires the http process to fetch the various
1201 	 * XML files and does this via the main process.
1202 	 */
1203 
1204 	if (!noop && rrdpon) {
1205 		rrdppid = process_start("rrdp", &rrdpfd);
1206 		if (rrdppid == 0) {
1207 			close(procfd);
1208 			close(rsyncfd);
1209 			close(httpfd);
1210 			proc_rrdp(rrdpfd);
1211 		}
1212 	} else {
1213 		rrdpfd = -1;
1214 		rrdppid = -1;
1215 	}
1216 
1217 	if (!filemode && timeout > 0) {
1218 		/*
1219 		 * Commit suicide eventually
1220 		 * cron will normally start a new one
1221 		 */
1222 		alarm(timeout);
1223 		signal(SIGALRM, suicide);
1224 
1225 		/* give up a bit before the hard timeout and try to finish up */
1226 		if (!noop)
1227 			deadline = getmonotime() + timeout - repo_timeout / 2;
1228 	}
1229 
1230 	if (pledge("stdio rpath wpath cpath fattr sendfd unveil", NULL) == -1)
1231 		err(1, "pledge");
1232 
1233 	if ((procq = msgbuf_new_reader(sizeof(size_t), io_parse_hdr, NULL)) ==
1234 	    NULL)
1235 		err(1, NULL);
1236 	if ((rsyncq = msgbuf_new_reader(sizeof(size_t), io_parse_hdr, NULL)) ==
1237 	    NULL)
1238 		err(1, NULL);
1239 	if ((httpq = msgbuf_new_reader(sizeof(size_t), io_parse_hdr, NULL)) ==
1240 	    NULL)
1241 		err(1, NULL);
1242 	if ((rrdpq = msgbuf_new_reader(sizeof(size_t), io_parse_hdr, NULL)) ==
1243 	   NULL)
1244 		err(1, NULL);
1245 
1246 	/*
1247 	 * The main process drives the top-down scan to leaf ROAs using
1248 	 * data downloaded by the rsync process and parsed by the
1249 	 * parsing process.
1250 	 */
1251 
1252 	pfd[0].fd = procfd;
1253 	queues[0] = procq;
1254 	pfd[1].fd = rsyncfd;
1255 	queues[1] = rsyncq;
1256 	pfd[2].fd = httpfd;
1257 	queues[2] = httpq;
1258 	pfd[3].fd = rrdpfd;
1259 	queues[3] = rrdpq;
1260 
1261 	load_skiplist(skiplistfile);
1262 
1263 	/*
1264 	 * Prime the process with our TAL files.
1265 	 * These will (hopefully) contain links to manifests and we
1266 	 * can get the ball rolling.
1267 	 */
1268 
1269 	for (i = 0; i < talsz; i++)
1270 		queue_add_file(tals[i], RTYPE_TAL, i);
1271 
1272 	if (filemode) {
1273 		while (*argv != NULL)
1274 			queue_add_file(*argv++, RTYPE_FILE, 0);
1275 
1276 		if (unveil(cachedir, "r") == -1)
1277 			err(1, "unveil cachedir");
1278 	} else {
1279 		if (unveil(outputdir, "rwc") == -1)
1280 			err(1, "unveil outputdir");
1281 		if (unveil(cachedir, "rwc") == -1)
1282 			err(1, "unveil cachedir");
1283 	}
1284 	if (pledge("stdio rpath wpath cpath fattr sendfd", NULL) == -1)
1285 		err(1, "unveil");
1286 
1287 	/* change working directory to the cache directory */
1288 	if (fchdir(cachefd) == -1)
1289 		err(1, "fchdir");
1290 
1291 	while (entity_queue > 0 && !killme) {
1292 		int polltim;
1293 
1294 		polltim = repo_check_timeout(INFTIM);
1295 
1296 		for (i = 0; i < NPFD; i++) {
1297 			pfd[i].events = POLLIN;
1298 			if (msgbuf_queuelen(queues[i]) > 0)
1299 				pfd[i].events |= POLLOUT;
1300 		}
1301 
1302 		if (poll(pfd, NPFD, polltim) == -1) {
1303 			if (errno == EINTR)
1304 				continue;
1305 			err(1, "poll");
1306 		}
1307 
1308 		for (i = 0; i < NPFD; i++) {
1309 			if (pfd[i].revents & (POLLERR|POLLNVAL)) {
1310 				warnx("poll[%d]: bad fd", i);
1311 				hangup = 1;
1312 			}
1313 			if (pfd[i].revents & POLLHUP)
1314 				hangup = 1;
1315 			if (pfd[i].revents & POLLOUT) {
1316 				if (msgbuf_write(pfd[i].fd, queues[i]) == -1) {
1317 					if (errno == EPIPE)
1318 						warnx("write[%d]: "
1319 						    "connection closed", i);
1320 					else
1321 						warn("write[%d]", i);
1322 					hangup = 1;
1323 				}
1324 			}
1325 		}
1326 		if (hangup)
1327 			break;
1328 
1329 		/*
1330 		 * Check the rsync and http process.
1331 		 * This means that one of our modules has completed
1332 		 * downloading and we can flush the module requests into
1333 		 * the parser process.
1334 		 */
1335 
1336 		if ((pfd[1].revents & POLLIN)) {
1337 			switch (ibuf_read(pfd[1].fd, queues[1])) {
1338 			case -1:
1339 				err(1, "ibuf_read");
1340 			case 0:
1341 				errx(1, "ibuf_read: connection closed");
1342 			}
1343 			while ((b = io_buf_get(queues[1])) != NULL) {
1344 				unsigned int id;
1345 				int ok;
1346 
1347 				io_read_buf(b, &id, sizeof(id));
1348 				io_read_buf(b, &ok, sizeof(ok));
1349 				rsync_finish(id, ok);
1350 				ibuf_free(b);
1351 			}
1352 		}
1353 
1354 		if ((pfd[2].revents & POLLIN)) {
1355 			switch (ibuf_read(pfd[2].fd, queues[2])) {
1356 			case -1:
1357 				err(1, "ibuf_read");
1358 			case 0:
1359 				errx(1, "ibuf_read: connection closed");
1360 			}
1361 			while ((b = io_buf_get(queues[2])) != NULL) {
1362 				unsigned int id;
1363 				enum http_result res;
1364 				char *last_mod;
1365 
1366 				io_read_buf(b, &id, sizeof(id));
1367 				io_read_buf(b, &res, sizeof(res));
1368 				io_read_str(b, &last_mod);
1369 				http_finish(id, res, last_mod);
1370 				free(last_mod);
1371 				ibuf_free(b);
1372 			}
1373 		}
1374 
1375 		/*
1376 		 * Handle RRDP requests here.
1377 		 */
1378 		if ((pfd[3].revents & POLLIN)) {
1379 			switch (ibuf_read(pfd[3].fd, queues[3])) {
1380 			case -1:
1381 				abort();
1382 				err(1, "ibuf_read");
1383 			case 0:
1384 				errx(1, "ibuf_read: connection closed");
1385 			}
1386 			while ((b = io_buf_get(queues[3])) != NULL) {
1387 				rrdp_process(b);
1388 				ibuf_free(b);
1389 			}
1390 		}
1391 
1392 		/*
1393 		 * The parser has finished something for us.
1394 		 * Dequeue these one by one.
1395 		 */
1396 
1397 		if ((pfd[0].revents & POLLIN)) {
1398 			switch (ibuf_read(pfd[0].fd, queues[0])) {
1399 			case -1:
1400 				err(1, "ibuf_read");
1401 			case 0:
1402 				errx(1, "ibuf_read: connection closed");
1403 			}
1404 			while ((b = io_buf_get(queues[0])) != NULL) {
1405 				entity_process(b, &stats, &vrps, &brks, &vaps,
1406 				    &vsps);
1407 				ibuf_free(b);
1408 			}
1409 		}
1410 	}
1411 
1412 	signal(SIGALRM, SIG_DFL);
1413 	if (killme) {
1414 		syslog(LOG_CRIT|LOG_DAEMON,
1415 		    "excessive runtime (%d seconds), giving up", timeout);
1416 		errx(1, "excessive runtime (%d seconds), giving up", timeout);
1417 	}
1418 
1419 	/*
1420 	 * For clean-up, close the input for the parser and rsync
1421 	 * process.
1422 	 * This will cause them to exit, then we reap them.
1423 	 */
1424 
1425 	close(procfd);
1426 	close(rsyncfd);
1427 	close(httpfd);
1428 	close(rrdpfd);
1429 
1430 	rc = 0;
1431 	for (;;) {
1432 		pid = waitpid(WAIT_ANY, &st, 0);
1433 		if (pid == -1) {
1434 			if (errno == EINTR)
1435 				continue;
1436 			if (errno == ECHILD)
1437 				break;
1438 			err(1, "wait");
1439 		}
1440 
1441 		if (pid == procpid)
1442 			name = "parser";
1443 		else if (pid == rsyncpid)
1444 			name = "rsync";
1445 		else if (pid == httppid)
1446 			name = "http";
1447 		else if (pid == rrdppid)
1448 			name = "rrdp";
1449 		else
1450 			name = "unknown";
1451 
1452 		if (WIFSIGNALED(st)) {
1453 			warnx("%s terminated signal %d", name, WTERMSIG(st));
1454 			rc = 1;
1455 		} else if (!WIFEXITED(st) || WEXITSTATUS(st) != 0) {
1456 			warnx("%s process exited abnormally", name);
1457 			rc = 1;
1458 		}
1459 	}
1460 
1461 	/* processing did not finish because of error */
1462 	if (entity_queue != 0)
1463 		errx(1, "not all files processed, giving up");
1464 
1465 	/* if processing in filemode the process is done, no cleanup */
1466 	if (filemode)
1467 		return rc;
1468 
1469 	logx("all files parsed: generating output");
1470 
1471 	if (!noop)
1472 		repo_cleanup(&fpt, cachefd);
1473 
1474 	clock_gettime(CLOCK_MONOTONIC, &now_time);
1475 	timespecsub(&now_time, &start_time, &stats.elapsed_time);
1476 	if (getrusage(RUSAGE_SELF, &ru) == 0) {
1477 		TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &stats.user_time);
1478 		TIMEVAL_TO_TIMESPEC(&ru.ru_stime, &stats.system_time);
1479 	}
1480 	if (getrusage(RUSAGE_CHILDREN, &ru) == 0) {
1481 		struct timespec ts;
1482 
1483 		TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &ts);
1484 		timespecadd(&stats.user_time, &ts, &stats.user_time);
1485 		TIMEVAL_TO_TIMESPEC(&ru.ru_stime, &ts);
1486 		timespecadd(&stats.system_time, &ts, &stats.system_time);
1487 	}
1488 
1489 	/* change working directory to the output directory */
1490 	if (fchdir(outdirfd) == -1)
1491 		err(1, "fchdir output dir");
1492 
1493 	for (i = 0; i < talsz; i++) {
1494 		repo_tal_stats_collect(sum_stats, i, &talstats[i]);
1495 		repo_tal_stats_collect(sum_stats, i, &stats.repo_tal_stats);
1496 	}
1497 	repo_stats_collect(sum_repostats, &stats.repo_stats);
1498 
1499 	if (outputfiles(&vrps, &brks, &vaps, &vsps, &stats))
1500 		rc = 1;
1501 
1502 	printf("Processing time %lld seconds "
1503 	    "(%lld seconds user, %lld seconds system)\n",
1504 	    (long long)stats.elapsed_time.tv_sec,
1505 	    (long long)stats.user_time.tv_sec,
1506 	    (long long)stats.system_time.tv_sec);
1507 	printf("Skiplist entries: %u\n", stats.skiplistentries);
1508 	printf("Route Origin Authorizations: %u (%u failed parse, %u "
1509 	    "invalid)\n", stats.repo_tal_stats.roas,
1510 	    stats.repo_tal_stats.roas_fail,
1511 	    stats.repo_tal_stats.roas_invalid);
1512 	printf("AS Provider Attestations: %u (%u failed parse, %u "
1513 	    "invalid)\n", stats.repo_tal_stats.aspas,
1514 	    stats.repo_tal_stats.aspas_fail,
1515 	    stats.repo_tal_stats.aspas_invalid);
1516 	if (experimental) {
1517 		printf("Signed Prefix Lists: %u "
1518 		    "(%u failed parse, %u invalid)\n",
1519 		    stats.repo_tal_stats.spls, stats.repo_tal_stats.spls_fail,
1520 		    stats.repo_tal_stats.spls_invalid);
1521 	}
1522 	printf("BGPsec Router Certificates: %u\n", stats.repo_tal_stats.brks);
1523 	printf("Certificates: %u (%u invalid)\n",
1524 	    stats.repo_tal_stats.certs, stats.repo_tal_stats.certs_fail);
1525 	printf("Trust Anchor Locators: %u (%u invalid)\n",
1526 	    stats.tals, talsz - stats.tals);
1527 	printf("Manifests: %u (%u failed parse, %u seqnum gaps)\n",
1528 	    stats.repo_tal_stats.mfts, stats.repo_tal_stats.mfts_fail,
1529 	    stats.repo_tal_stats.mfts_gap);
1530 	printf("Certificate revocation lists: %u\n", stats.repo_tal_stats.crls);
1531 	printf("Ghostbuster records: %u\n", stats.repo_tal_stats.gbrs);
1532 	printf("Trust Anchor Keys: %u\n", stats.repo_tal_stats.taks);
1533 	printf("Repositories: %u\n", stats.repos);
1534 	printf("New files moved into validated cache: %u\n",
1535 	    stats.repo_stats.new_files);
1536 	printf("Cleanup: removed %u files, %u directories\n"
1537 	    "Repository cleanup: kept %u and removed %u superfluous files\n",
1538 	    stats.repo_stats.del_files, stats.repo_stats.del_dirs,
1539 	    stats.repo_stats.extra_files, stats.repo_stats.del_extra_files);
1540 	printf("VRP Entries: %u (%u unique)\n", stats.repo_tal_stats.vrps,
1541 	    stats.repo_tal_stats.vrps_uniqs);
1542 	printf("VAP Entries: %u (%u unique, %u overflowed)\n",
1543 	    stats.repo_tal_stats.vaps, stats.repo_tal_stats.vaps_uniqs,
1544 	    stats.repo_tal_stats.vaps_overflowed);
1545 	printf("VSP Entries: %u (%u unique)\n", stats.repo_tal_stats.vsps,
1546 	    stats.repo_tal_stats.vsps_uniqs);
1547 
1548 	/* Memory cleanup. */
1549 	repo_free();
1550 
1551 	return rc;
1552 
1553 usage:
1554 	fprintf(stderr,
1555 	    "usage: rpki-client [-0ABcjmnoRVvx] [-b sourceaddr] [-d cachedir]"
1556 	    " [-e rsync_prog]\n"
1557 	    "                   [-H fqdn] [-P epoch] [-S skiplist] [-s timeout]"
1558 	    " [-t tal]\n"
1559 	    "                   [outputdir]\n"
1560 	    "       rpki-client [-Vv] [-d cachedir] [-j] [-t tal] -f file ..."
1561 	    "\n");
1562 	return 1;
1563 }
1564