main.c revision 1.161
1/*	$OpenBSD: main.c,v 1.161 2021/11/04 11:32:55 claudio 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/socket.h>
22#include <sys/resource.h>
23#include <sys/statvfs.h>
24#include <sys/tree.h>
25#include <sys/wait.h>
26
27#include <assert.h>
28#include <err.h>
29#include <errno.h>
30#include <dirent.h>
31#include <fcntl.h>
32#include <fnmatch.h>
33#include <poll.h>
34#include <pwd.h>
35#include <stdio.h>
36#include <stdlib.h>
37#include <signal.h>
38#include <string.h>
39#include <limits.h>
40#include <syslog.h>
41#include <unistd.h>
42#include <imsg.h>
43
44#include "extern.h"
45#include "version.h"
46
47/*
48 * Maximum number of TAL files we'll load.
49 */
50#define	TALSZ_MAX	8
51
52const char	*tals[TALSZ_MAX];
53const char	*taldescs[TALSZ_MAX];
54size_t		 talsz;
55
56size_t	entity_queue;
57int	timeout = 60*60;
58volatile sig_atomic_t killme;
59void	suicide(int sig);
60
61static struct filepath_tree	fpt = RB_INITIALIZER(&fpt);
62static struct msgbuf		procq, rsyncq, httpq, rrdpq;
63static int			cachefd, outdirfd;
64
65const char	*bird_tablename = "ROAS";
66
67int	verbose;
68int	noop;
69int	rrdpon = 1;
70
71struct stats	 stats;
72
73/*
74 * Log a message to stderr if and only if "verbose" is non-zero.
75 * This uses the err(3) functionality.
76 */
77void
78logx(const char *fmt, ...)
79{
80	va_list		 ap;
81
82	if (verbose && fmt != NULL) {
83		va_start(ap, fmt);
84		vwarnx(fmt, ap);
85		va_end(ap);
86	}
87}
88
89void
90entity_free(struct entity *ent)
91{
92	if (ent == NULL)
93		return;
94
95	free(ent->data);
96	free(ent->file);
97	free(ent);
98}
99
100/*
101 * Read a queue entity from the descriptor.
102 * Matched by entity_buffer_req().
103 * The pointer must be passed entity_free().
104 */
105void
106entity_read_req(struct ibuf *b, struct entity *ent)
107{
108	io_read_buf(b, &ent->type, sizeof(ent->type));
109	io_read_buf(b, &ent->talid, sizeof(ent->talid));
110	io_read_str(b, &ent->file);
111	io_read_buf(b, &ent->has_data, sizeof(ent->has_data));
112	if (ent->has_data)
113		io_read_buf_alloc(b, (void **)&ent->data, &ent->datasz);
114}
115
116/*
117 * Write the queue entity.
118 * Matched by entity_read_req().
119 */
120static void
121entity_write_req(const struct entity *ent)
122{
123	struct ibuf *b;
124
125	if (filepath_add(&fpt, ent->file) == 0) {
126		warnx("%s: File already visited", ent->file);
127		entity_queue--;
128		return;
129	}
130
131	b = io_new_buffer();
132	io_simple_buffer(b, &ent->type, sizeof(ent->type));
133	io_simple_buffer(b, &ent->talid, sizeof(ent->talid));
134	io_str_buffer(b, ent->file);
135	io_simple_buffer(b, &ent->has_data, sizeof(int));
136	if (ent->has_data)
137		io_buf_buffer(b, ent->data, ent->datasz);
138	io_close_buffer(&procq, b);
139}
140
141/*
142 * Scan through all queued requests and see which ones are in the given
143 * repo, then flush those into the parser process.
144 */
145void
146entityq_flush(struct entityq *q, struct repo *rp)
147{
148	struct entity	*p, *np;
149
150	TAILQ_FOREACH_SAFE(p, q, entries, np) {
151		char *file = p->file;
152
153		/*
154		 * XXX fixup path here since the repo may change
155		 * during load because of fallback. In that case
156		 * the file path changes as well since RRDP and RSYNC
157		 * can not share a common repo.
158		 */
159		p->file = repo_filename(rp, file);
160		if (p->file == NULL)
161			err(1, "can't construct repo filename");
162		free(file);
163
164		entity_write_req(p);
165		TAILQ_REMOVE(q, p, entries);
166		entity_free(p);
167	}
168}
169
170/*
171 * Add the heap-allocated file to the queue for processing.
172 */
173static void
174entityq_add(char *file, enum rtype type, struct repo *rp,
175    unsigned char *data, size_t datasz, int talid)
176{
177	struct entity	*p;
178
179	if ((p = calloc(1, sizeof(struct entity))) == NULL)
180		err(1, NULL);
181
182	p->type = type;
183	p->talid = talid;
184	p->file = file;
185	p->has_data = data != NULL;
186	if (p->has_data) {
187		p->data = data;
188		p->datasz = datasz;
189	}
190
191	entity_queue++;
192
193	/*
194	 * Write to the queue if there's no repo or the repo has already
195	 * been loaded else enqueue it for later.
196	 */
197
198	if (rp == NULL || !repo_queued(rp, p)) {
199		/*
200		 * XXX fixup path here since for repo path the
201		 * file path has not yet been fixed here.
202		 * This is a quick way to make this work but in
203		 * the long run repos need to be passed to the parser.
204		 */
205		if (rp != NULL) {
206			file = p->file;
207			p->file = repo_filename(rp, file);
208			if (p->file == NULL)
209				err(1, "can't construct repo filename from %s",
210				    file);
211			free(file);
212		}
213		entity_write_req(p);
214		entity_free(p);
215	}
216}
217
218static void
219rrdp_file_resp(size_t id, int ok)
220{
221	enum rrdp_msg type = RRDP_FILE;
222	struct ibuf *b;
223
224	b = io_new_buffer();
225	io_simple_buffer(b, &type, sizeof(type));
226	io_simple_buffer(b, &id, sizeof(id));
227	io_simple_buffer(b, &ok, sizeof(ok));
228	io_close_buffer(&rrdpq, b);
229}
230
231void
232rrdp_fetch(size_t id, const char *uri, const char *local,
233    struct rrdp_session *s)
234{
235	enum rrdp_msg type = RRDP_START;
236	struct ibuf *b;
237
238	b = io_new_buffer();
239	io_simple_buffer(b, &type, sizeof(type));
240	io_simple_buffer(b, &id, sizeof(id));
241	io_str_buffer(b, local);
242	io_str_buffer(b, uri);
243	io_str_buffer(b, s->session_id);
244	io_simple_buffer(b, &s->serial, sizeof(s->serial));
245	io_str_buffer(b, s->last_mod);
246	io_close_buffer(&rrdpq, b);
247}
248
249/*
250 * Request a repository sync via rsync URI to directory local.
251 */
252void
253rsync_fetch(size_t id, const char *uri, const char *local)
254{
255	struct ibuf	*b;
256
257	b = io_new_buffer();
258	io_simple_buffer(b, &id, sizeof(id));
259	io_str_buffer(b, local);
260	io_str_buffer(b, uri);
261	io_close_buffer(&rsyncq, b);
262}
263
264/*
265 * Request a file from a https uri, data is written to the file descriptor fd.
266 */
267void
268http_fetch(size_t id, const char *uri, const char *last_mod, int fd)
269{
270	struct ibuf	*b;
271
272	b = io_new_buffer();
273	io_simple_buffer(b, &id, sizeof(id));
274	io_str_buffer(b, uri);
275	io_str_buffer(b, last_mod);
276	/* pass file as fd */
277	b->fd = fd;
278	io_close_buffer(&httpq, b);
279}
280
281/*
282 * Request some XML file on behalf of the rrdp parser.
283 * Create a pipe and pass the pipe endpoints to the http and rrdp process.
284 */
285static void
286rrdp_http_fetch(size_t id, const char *uri, const char *last_mod)
287{
288	enum rrdp_msg type = RRDP_HTTP_INI;
289	struct ibuf *b;
290	int pi[2];
291
292	if (pipe2(pi, O_CLOEXEC | O_NONBLOCK) == -1)
293		err(1, "pipe");
294
295	b = io_new_buffer();
296	io_simple_buffer(b, &type, sizeof(type));
297	io_simple_buffer(b, &id, sizeof(id));
298	b->fd = pi[0];
299	io_close_buffer(&rrdpq, b);
300
301	http_fetch(id, uri, last_mod, pi[1]);
302}
303
304void
305rrdp_http_done(size_t id, enum http_result res, const char *last_mod)
306{
307	enum rrdp_msg type = RRDP_HTTP_FIN;
308	struct ibuf *b;
309
310	/* RRDP request, relay response over to the rrdp process */
311	b = io_new_buffer();
312	io_simple_buffer(b, &type, sizeof(type));
313	io_simple_buffer(b, &id, sizeof(id));
314	io_simple_buffer(b, &res, sizeof(res));
315	io_str_buffer(b, last_mod);
316	io_close_buffer(&rrdpq, b);
317}
318
319/*
320 * Add a file (CER, ROA, CRL) from an MFT file, RFC 6486.
321 * These are always relative to the directory in which "mft" sits.
322 */
323static void
324queue_add_from_mft(const char *mft, const struct mftfile *file, enum rtype type)
325{
326	char		*cp, *nfile;
327
328	/* Construct local path from filename. */
329	cp = strrchr(mft, '/');
330	assert(cp != NULL);
331	assert(cp - mft < INT_MAX);
332	if (asprintf(&nfile, "%.*s/%s", (int)(cp - mft), mft, file->file) == -1)
333		err(1, NULL);
334
335	/*
336	 * Since we're from the same directory as the MFT file, we know
337	 * that the repository has already been loaded.
338	 */
339
340	entityq_add(nfile, type, NULL, NULL, 0, -1);
341}
342
343/*
344 * Loops over queue_add_from_mft() for all files.
345 * The order here is important: we want to parse the revocation
346 * list *before* we parse anything else.
347 * FIXME: set the type of file in the mftfile so that we don't need to
348 * keep doing the check (this should be done in the parser, where we
349 * check the suffix anyway).
350 */
351static void
352queue_add_from_mft_set(const struct mft *mft)
353{
354	size_t			 i, sz;
355	const struct mftfile	*f;
356
357	for (i = 0; i < mft->filesz; i++) {
358		f = &mft->files[i];
359		sz = strlen(f->file);
360		assert(sz > 4);
361		if (strcasecmp(f->file + sz - 4, ".crl") != 0)
362			continue;
363		queue_add_from_mft(mft->file, f, RTYPE_CRL);
364	}
365
366	for (i = 0; i < mft->filesz; i++) {
367		f = &mft->files[i];
368		sz = strlen(f->file);
369		assert(sz > 4);
370		if (strcasecmp(f->file + sz - 4, ".crl") == 0)
371			continue;
372		else if (strcasecmp(f->file + sz - 4, ".cer") == 0)
373			queue_add_from_mft(mft->file, f, RTYPE_CER);
374		else if (strcasecmp(f->file + sz - 4, ".roa") == 0)
375			queue_add_from_mft(mft->file, f, RTYPE_ROA);
376		else if (strcasecmp(f->file + sz - 4, ".gbr") == 0)
377			queue_add_from_mft(mft->file, f, RTYPE_GBR);
378		else
379			logx("%s: unsupported file type: %s", mft->file,
380			    f->file);
381	}
382}
383
384/*
385 * Add a local TAL file (RFC 7730) to the queue of files to fetch.
386 */
387static void
388queue_add_tal(const char *file, int id)
389{
390	unsigned char	*buf;
391	char		*nfile;
392	size_t		 len;
393
394	if ((nfile = strdup(file)) == NULL)
395		err(1, NULL);
396	buf = load_file(file, &len);
397	if (buf == NULL) {
398		warn("%s", file);
399		return;
400	}
401
402	/* Not in a repository, so directly add to queue. */
403	entityq_add(nfile, RTYPE_TAL, NULL, buf, len, id);
404}
405
406/*
407 * Add URIs (CER) from a TAL file, RFC 8630.
408 */
409static void
410queue_add_from_tal(struct tal *tal)
411{
412	struct repo	*repo;
413	unsigned char	*data;
414
415	assert(tal->urisz);
416
417	if ((taldescs[tal->id] = strdup(tal->descr)) == NULL)
418		err(1, NULL);
419
420	/* Look up the repository. */
421	repo = ta_lookup(tal);
422
423	/* steal the pkey from the tal structure */
424	data = tal->pkey;
425	tal->pkey = NULL;
426	entityq_add(NULL, RTYPE_CER, repo, data,
427	    tal->pkeysz, tal->id);
428}
429
430/*
431 * Add a manifest (MFT) found in an X509 certificate, RFC 6487.
432 */
433static void
434queue_add_from_cert(const struct cert *cert)
435{
436	struct repo	*repo;
437	char		*nfile;
438
439	repo = repo_lookup(cert->repo, rrdpon ? cert->notify : NULL);
440	if (repo == NULL) {
441		warnx("%s: repository lookup failed", cert->repo);
442		return;
443	}
444
445	if ((nfile = strdup(cert->mft)) == NULL)
446		err(1, NULL);
447	entityq_add(nfile, RTYPE_MFT, repo, NULL, 0, -1);
448}
449
450/*
451 * Process parsed content.
452 * For non-ROAs, we grok for more data.
453 * For ROAs, we want to extract the valid info.
454 * In all cases, we gather statistics.
455 */
456static void
457entity_process(struct ibuf *b, struct stats *st, struct vrp_tree *tree,
458    struct brk_tree *brktree)
459{
460	enum rtype	 type;
461	struct tal	*tal;
462	struct cert	*cert;
463	struct mft	*mft;
464	struct roa	*roa;
465	int		 c;
466
467	/*
468	 * For most of these, we first read whether there's any content
469	 * at all---this means that the syntactic parse failed (X509
470	 * certificate, for example).
471	 * We follow that up with whether the resources didn't parse.
472	 */
473	io_read_buf(b, &type, sizeof(type));
474
475	switch (type) {
476	case RTYPE_TAL:
477		st->tals++;
478		tal = tal_read(b);
479		queue_add_from_tal(tal);
480		tal_free(tal);
481		break;
482	case RTYPE_CER:
483		st->certs++;
484		io_read_buf(b, &c, sizeof(c));
485		if (c == 0) {
486			st->certs_fail++;
487			break;
488		}
489		cert = cert_read(b);
490		if (cert->purpose == CERT_PURPOSE_CA) {
491			/*
492			 * Process the revocation list from the
493			 * certificate *first*, since it might mark that
494			 * we're revoked and then we don't want to
495			 * process the MFT.
496			 */
497			queue_add_from_cert(cert);
498		} else if (cert->purpose == CERT_PURPOSE_BGPSEC_ROUTER) {
499			cert_insert_brks(brktree, cert);
500			st->brks++;
501		} else
502			st->certs_fail++;
503		cert_free(cert);
504		break;
505	case RTYPE_MFT:
506		st->mfts++;
507		io_read_buf(b, &c, sizeof(c));
508		if (c == 0) {
509			st->mfts_fail++;
510			break;
511		}
512		mft = mft_read(b);
513		if (mft->stale)
514			st->mfts_stale++;
515		queue_add_from_mft_set(mft);
516		mft_free(mft);
517		break;
518	case RTYPE_CRL:
519		st->crls++;
520		break;
521	case RTYPE_ROA:
522		st->roas++;
523		io_read_buf(b, &c, sizeof(c));
524		if (c == 0) {
525			st->roas_fail++;
526			break;
527		}
528		roa = roa_read(b);
529		if (roa->valid)
530			roa_insert_vrps(tree, roa, &st->vrps, &st->uniqs);
531		else
532			st->roas_invalid++;
533		roa_free(roa);
534		break;
535	case RTYPE_GBR:
536		st->gbrs++;
537		break;
538	default:
539		errx(1, "unknown entity type %d", type);
540	}
541
542	entity_queue--;
543}
544
545static void
546rrdp_process(struct ibuf *b)
547{
548	enum rrdp_msg type;
549	enum publish_type pt;
550	struct rrdp_session s;
551	char *uri, *last_mod, *data;
552	char hash[SHA256_DIGEST_LENGTH];
553	size_t dsz, id;
554	int ok;
555
556	io_read_buf(b, &type, sizeof(type));
557	io_read_buf(b, &id, sizeof(id));
558
559	switch (type) {
560	case RRDP_END:
561		io_read_buf(b, &ok, sizeof(ok));
562		rrdp_finish(id, ok);
563		break;
564	case RRDP_HTTP_REQ:
565		io_read_str(b, &uri);
566		io_read_str(b, &last_mod);
567		rrdp_http_fetch(id, uri, last_mod);
568		break;
569	case RRDP_SESSION:
570		io_read_str(b, &s.session_id);
571		io_read_buf(b, &s.serial, sizeof(s.serial));
572		io_read_str(b, &s.last_mod);
573		rrdp_save_state(id, &s);
574		free(s.session_id);
575		free(s.last_mod);
576		break;
577	case RRDP_FILE:
578		io_read_buf(b, &pt, sizeof(pt));
579		if (pt != PUB_ADD)
580			io_read_buf(b, &hash, sizeof(hash));
581		io_read_str(b, &uri);
582		io_read_buf_alloc(b, (void **)&data, &dsz);
583
584		ok = rrdp_handle_file(id, pt, uri, hash, sizeof(hash),
585		    data, dsz);
586		rrdp_file_resp(id, ok);
587
588		free(uri);
589		free(data);
590		break;
591	default:
592		errx(1, "unexpected rrdp response");
593	}
594}
595
596/*
597 * Assign filenames ending in ".tal" in "/etc/rpki" into "tals",
598 * returning the number of files found and filled-in.
599 * This may be zero.
600 * Don't exceded "max" filenames.
601 */
602static size_t
603tal_load_default(void)
604{
605	static const char *confdir = "/etc/rpki";
606	size_t s = 0;
607	char *path;
608	DIR *dirp;
609	struct dirent *dp;
610
611	dirp = opendir(confdir);
612	if (dirp == NULL)
613		err(1, "open %s", confdir);
614	while ((dp = readdir(dirp)) != NULL) {
615		if (fnmatch("*.tal", dp->d_name, FNM_PERIOD) == FNM_NOMATCH)
616			continue;
617		if (s >= TALSZ_MAX)
618			err(1, "too many tal files found in %s",
619			    confdir);
620		if (asprintf(&path, "%s/%s", confdir, dp->d_name) == -1)
621			err(1, NULL);
622		tals[s++] = path;
623	}
624	closedir(dirp);
625	return s;
626}
627
628static void
629check_fs_size(int fd, const char *cachedir)
630{
631	struct statvfs	fs;
632	const long long minsize = 500 * 1024 * 1024;
633	const long long minnode = 300 * 1000;
634
635	if (fstatvfs(fd, &fs) == -1)
636		err(1, "statfs %s", cachedir);
637
638	if (fs.f_bavail < minsize / fs.f_frsize || fs.f_favail < minnode) {
639		fprintf(stderr, "WARNING: rpki-client may need more than "
640		    "the availabe disk space\n"
641		    "on the file-system holding %s.\n", cachedir);
642		fprintf(stderr, "available space: %lldkB, "
643		    "suggested minimum %lldkB\n",
644		    (long long)fs.f_bavail * fs.f_frsize / 1024,
645		    minsize / 1024);
646		fprintf(stderr, "available inodes %lld, "
647		    "suggested minimum %lld\n\n",
648		    (long long)fs.f_favail, minnode);
649		fflush(stderr);
650	}
651}
652
653void
654suicide(int sig __attribute__((unused)))
655{
656	killme = 1;
657}
658
659#define NPFD	4
660
661int
662main(int argc, char *argv[])
663{
664	int		 rc, c, st, proc, rsync, http, rrdp, ok, hangup = 0;
665	int		 fl = SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK;
666	size_t		 i, id;
667	pid_t		 pid, procpid, rsyncpid, httppid, rrdppid;
668	int		 fd[2];
669	struct pollfd	 pfd[NPFD];
670	struct msgbuf	*queues[NPFD];
671	struct ibuf	*b, *httpbuf = NULL, *procbuf = NULL;
672	struct ibuf	*rrdpbuf = NULL, *rsyncbuf = NULL;
673	char		*rsync_prog = "openrsync";
674	char		*bind_addr = NULL;
675	const char	*cachedir = NULL, *outputdir = NULL;
676	const char	*errs, *name;
677	const char	*file = NULL;
678	struct vrp_tree	 vrps = RB_INITIALIZER(&vrps);
679	struct brk_tree  brks = RB_INITIALIZER(&brks);
680	struct rusage	ru;
681	struct timeval	start_time, now_time;
682
683	gettimeofday(&start_time, NULL);
684
685	/* If started as root, priv-drop to _rpki-client */
686	if (getuid() == 0) {
687		struct passwd *pw;
688
689		pw = getpwnam("_rpki-client");
690		if (!pw)
691			errx(1, "no _rpki-client user to revoke to");
692		if (setgroups(1, &pw->pw_gid) == -1 ||
693		    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1 ||
694		    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1)
695			err(1, "unable to revoke privs");
696	}
697	cachedir = RPKI_PATH_BASE_DIR;
698	outputdir = RPKI_PATH_OUT_DIR;
699
700	if (pledge("stdio rpath wpath cpath inet fattr dns sendfd recvfd "
701	    "proc exec unveil", NULL) == -1)
702		err(1, "pledge");
703
704	while ((c = getopt(argc, argv, "b:Bcd:e:f:jnorRs:t:T:vV")) != -1)
705		switch (c) {
706		case 'b':
707			bind_addr = optarg;
708			break;
709		case 'B':
710			outformats |= FORMAT_BIRD;
711			break;
712		case 'c':
713			outformats |= FORMAT_CSV;
714			break;
715		case 'd':
716			cachedir = optarg;
717			break;
718		case 'e':
719			rsync_prog = optarg;
720			break;
721		case 'f':
722			file = optarg;
723			noop = 1;
724			break;
725		case 'j':
726			outformats |= FORMAT_JSON;
727			break;
728		case 'n':
729			noop = 1;
730			break;
731		case 'o':
732			outformats |= FORMAT_OPENBGPD;
733			break;
734		case 'R':
735			rrdpon = 0;
736			break;
737		case 'r':
738			rrdpon = 1;
739			break;
740		case 's':
741			timeout = strtonum(optarg, 0, 24*60*60, &errs);
742			if (errs)
743				errx(1, "-s: %s", errs);
744			break;
745		case 't':
746			if (talsz >= TALSZ_MAX)
747				err(1,
748				    "too many tal files specified");
749			tals[talsz++] = optarg;
750			break;
751		case 'T':
752			bird_tablename = optarg;
753			break;
754		case 'v':
755			verbose++;
756			break;
757		case 'V':
758			fprintf(stderr, "rpki-client %s\n", RPKI_VERSION);
759			return 0;
760		default:
761			goto usage;
762		}
763
764	argv += optind;
765	argc -= optind;
766	if (argc == 1)
767		outputdir = argv[0];
768	else if (argc > 1)
769		goto usage;
770
771	signal(SIGPIPE, SIG_IGN);
772
773	if (cachedir == NULL) {
774		warnx("cache directory required");
775		goto usage;
776	}
777	if (outputdir == NULL) {
778		warnx("output directory required");
779		goto usage;
780	}
781
782	if ((cachefd = open(cachedir, O_RDONLY | O_DIRECTORY)) == -1)
783		err(1, "cache directory %s", cachedir);
784	if ((outdirfd = open(outputdir, O_RDONLY | O_DIRECTORY)) == -1)
785		err(1, "output directory %s", outputdir);
786
787	check_fs_size(cachefd, cachedir);
788
789	if (outformats == 0)
790		outformats = FORMAT_OPENBGPD;
791
792	if (talsz == 0)
793		talsz = tal_load_default();
794	if (talsz == 0)
795		err(1, "no TAL files found in %s", "/etc/rpki");
796
797	/*
798	 * Create the file reader as a jailed child process.
799	 * It will be responsible for reading all of the files (ROAs,
800	 * manifests, certificates, etc.) and returning contents.
801	 */
802
803	if (socketpair(AF_UNIX, fl, 0, fd) == -1)
804		err(1, "socketpair");
805	if ((procpid = fork()) == -1)
806		err(1, "fork");
807
808	if (procpid == 0) {
809		close(fd[1]);
810
811		setproctitle("parser");
812		/* change working directory to the cache directory */
813		if (fchdir(cachefd) == -1)
814			err(1, "fchdir");
815
816		if (timeout)
817			alarm(timeout);
818
819		/* Only allow access to the cache directory. */
820		if (unveil(".", "r") == -1)
821			err(1, "%s: unveil", cachedir);
822		if (pledge("stdio rpath", NULL) == -1)
823			err(1, "pledge");
824		proc_parser(fd[0]);
825		errx(1, "parser process returned");
826	}
827
828	close(fd[0]);
829	proc = fd[1];
830
831	/*
832	 * Create a process that will do the rsync'ing.
833	 * This process is responsible for making sure that all the
834	 * repositories referenced by a certificate manifest (or the
835	 * TAL) exists and has been downloaded.
836	 */
837
838	if (!noop) {
839		if (socketpair(AF_UNIX, fl, 0, fd) == -1)
840			err(1, "socketpair");
841		if ((rsyncpid = fork()) == -1)
842			err(1, "fork");
843
844		if (rsyncpid == 0) {
845			close(proc);
846			close(fd[1]);
847
848			setproctitle("rsync");
849			/* change working directory to the cache directory */
850			if (fchdir(cachefd) == -1)
851				err(1, "fchdir");
852
853			if (timeout)
854				alarm(timeout);
855
856			if (pledge("stdio rpath proc exec unveil", NULL) == -1)
857				err(1, "pledge");
858
859			proc_rsync(rsync_prog, bind_addr, fd[0]);
860			errx(1, "rsync process returned");
861		}
862
863		close(fd[0]);
864		rsync = fd[1];
865	} else {
866		rsync = -1;
867		rsyncpid = -1;
868	}
869
870	/*
871	 * Create a process that will fetch data via https.
872	 * With every request the http process receives a file descriptor
873	 * where the data should be written to.
874	 */
875
876	if (!noop) {
877		if (socketpair(AF_UNIX, fl, 0, fd) == -1)
878			err(1, "socketpair");
879		if ((httppid = fork()) == -1)
880			err(1, "fork");
881
882		if (httppid == 0) {
883			close(proc);
884			close(rsync);
885			close(fd[1]);
886
887			setproctitle("http");
888			/* change working directory to the cache directory */
889			if (fchdir(cachefd) == -1)
890				err(1, "fchdir");
891
892			if (timeout)
893				alarm(timeout);
894
895			if (pledge("stdio rpath inet dns recvfd", NULL) == -1)
896				err(1, "pledge");
897
898			proc_http(bind_addr, fd[0]);
899			errx(1, "http process returned");
900		}
901
902		close(fd[0]);
903		http = fd[1];
904	} else {
905		http = -1;
906		httppid = -1;
907	}
908
909	/*
910	 * Create a process that will process RRDP.
911	 * The rrdp process requires the http process to fetch the various
912	 * XML files and does this via the main process.
913	 */
914
915	if (!noop && rrdpon) {
916		if (socketpair(AF_UNIX, fl, 0, fd) == -1)
917			err(1, "socketpair");
918		if ((rrdppid = fork()) == -1)
919			err(1, "fork");
920
921		if (rrdppid == 0) {
922			close(proc);
923			close(rsync);
924			close(http);
925			close(fd[1]);
926
927			setproctitle("rrdp");
928			/* change working directory to the cache directory */
929			if (fchdir(cachefd) == -1)
930				err(1, "fchdir");
931
932			if (timeout)
933				alarm(timeout);
934
935			if (pledge("stdio recvfd", NULL) == -1)
936				err(1, "pledge");
937
938			proc_rrdp(fd[0]);
939			/* NOTREACHED */
940		}
941
942		close(fd[0]);
943		rrdp = fd[1];
944	} else {
945		rrdp = -1;
946		rrdppid = -1;
947	}
948
949	if (timeout) {
950		/*
951		 * Commit suicide eventually
952		 * cron will normally start a new one
953		 */
954		alarm(timeout);
955		signal(SIGALRM, suicide);
956	}
957
958	/* TODO unveil cachedir and outputdir, no other access allowed */
959	if (pledge("stdio rpath wpath cpath fattr sendfd", NULL) == -1)
960		err(1, "pledge");
961
962	msgbuf_init(&procq);
963	msgbuf_init(&rsyncq);
964	msgbuf_init(&httpq);
965	msgbuf_init(&rrdpq);
966	procq.fd = proc;
967	rsyncq.fd = rsync;
968	httpq.fd = http;
969	rrdpq.fd = rrdp;
970
971	/*
972	 * The main process drives the top-down scan to leaf ROAs using
973	 * data downloaded by the rsync process and parsed by the
974	 * parsing process.
975	 */
976
977	pfd[0].fd = proc;
978	queues[0] = &procq;
979	pfd[1].fd = rsync;
980	queues[1] = &rsyncq;
981	pfd[2].fd = http;
982	queues[2] = &httpq;
983	pfd[3].fd = rrdp;
984	queues[3] = &rrdpq;
985
986	/*
987	 * Prime the process with our TAL file.
988	 * This will contain (hopefully) links to our manifest and we
989	 * can get the ball rolling.
990	 */
991
992	for (i = 0; i < talsz; i++)
993		queue_add_tal(tals[i], i);
994
995	/* change working directory to the cache directory */
996	if (fchdir(cachefd) == -1)
997		err(1, "fchdir");
998
999	while (entity_queue > 0 && !killme) {
1000		for (i = 0; i < NPFD; i++) {
1001			pfd[i].events = POLLIN;
1002			if (queues[i]->queued)
1003				pfd[i].events |= POLLOUT;
1004		}
1005
1006		if ((c = poll(pfd, NPFD, INFTIM)) == -1) {
1007			if (errno == EINTR)
1008				continue;
1009			err(1, "poll");
1010		}
1011
1012		for (i = 0; i < NPFD; i++) {
1013			if (pfd[i].revents & (POLLERR|POLLNVAL))
1014				errx(1, "poll[%zu]: bad fd", i);
1015			if (pfd[i].revents & POLLHUP) {
1016				warnx("poll[%zu]: hangup", i);
1017				hangup = 1;
1018			}
1019			if (pfd[i].revents & POLLOUT) {
1020				switch (msgbuf_write(queues[i])) {
1021				case 0:
1022					errx(1, "write[%zu]: "
1023					    "connection closed", i);
1024				case -1:
1025					err(1, "write[%zu]", i);
1026				}
1027			}
1028		}
1029		if (hangup)
1030			break;
1031
1032		/*
1033		 * Check the rsync and http process.
1034		 * This means that one of our modules has completed
1035		 * downloading and we can flush the module requests into
1036		 * the parser process.
1037		 */
1038
1039		if ((pfd[1].revents & POLLIN)) {
1040			b = io_buf_read(rsync, &rsyncbuf);
1041			if (b != NULL) {
1042				io_read_buf(b, &id, sizeof(id));
1043				io_read_buf(b, &ok, sizeof(ok));
1044				rsync_finish(id, ok);
1045				ibuf_free(b);
1046			}
1047		}
1048
1049		if ((pfd[2].revents & POLLIN)) {
1050			b = io_buf_read(http, &httpbuf);
1051			if (b != NULL) {
1052				enum http_result res;
1053				char *last_mod;
1054
1055				io_read_buf(b, &id, sizeof(id));
1056				io_read_buf(b, &res, sizeof(res));
1057				io_read_str(b, &last_mod);
1058				http_finish(id, res, last_mod);
1059				free(last_mod);
1060				ibuf_free(b);
1061			}
1062		}
1063
1064		/*
1065		 * Handle RRDP requests here.
1066		 */
1067		if ((pfd[3].revents & POLLIN)) {
1068			b = io_buf_read(rrdp, &rrdpbuf);
1069			if (b != NULL) {
1070				rrdp_process(b);
1071				ibuf_free(b);
1072			}
1073		}
1074
1075		/*
1076		 * The parser has finished something for us.
1077		 * Dequeue these one by one.
1078		 */
1079
1080		if ((pfd[0].revents & POLLIN)) {
1081			b = io_buf_read(proc, &procbuf);
1082			if (b != NULL) {
1083				entity_process(b, &stats, &vrps, &brks);
1084				ibuf_free(b);
1085			}
1086		}
1087	}
1088
1089	signal(SIGALRM, SIG_DFL);
1090	if (killme) {
1091		syslog(LOG_CRIT|LOG_DAEMON,
1092		    "excessive runtime (%d seconds), giving up", timeout);
1093		errx(1, "excessive runtime (%d seconds), giving up", timeout);
1094	}
1095
1096	/*
1097	 * For clean-up, close the input for the parser and rsync
1098	 * process.
1099	 * This will cause them to exit, then we reap them.
1100	 */
1101
1102	close(proc);
1103	close(rsync);
1104	close(http);
1105	close(rrdp);
1106
1107	rc = 0;
1108	for (;;) {
1109		pid = waitpid(WAIT_ANY, &st, 0);
1110		if (pid == -1) {
1111			if (errno == EINTR)
1112				continue;
1113			if (errno == ECHILD)
1114				break;
1115			err(1, "wait");
1116		}
1117
1118		if (pid == procpid)
1119			name = "parser";
1120		else if (pid == rsyncpid)
1121			name = "rsync";
1122		else if (pid == httppid)
1123			name = "http";
1124		else if (pid == rrdppid)
1125			name = "rrdp";
1126		else
1127			name = "unknown";
1128
1129		if (WIFSIGNALED(st)) {
1130			warnx("%s terminated signal %d", name, WTERMSIG(st));
1131			rc = 1;
1132		} else if (!WIFEXITED(st) || WEXITSTATUS(st) != 0) {
1133			warnx("%s process exited abnormally", name);
1134			rc = 1;
1135		}
1136	}
1137
1138	/* processing did not finish because of error */
1139	if (entity_queue != 0)
1140		return 1;
1141
1142	logx("all files parsed: generating output");
1143
1144	repo_cleanup(&fpt);
1145
1146	gettimeofday(&now_time, NULL);
1147	timersub(&now_time, &start_time, &stats.elapsed_time);
1148	if (getrusage(RUSAGE_SELF, &ru) == 0) {
1149		stats.user_time = ru.ru_utime;
1150		stats.system_time = ru.ru_stime;
1151	}
1152	if (getrusage(RUSAGE_CHILDREN, &ru) == 0) {
1153		timeradd(&stats.user_time, &ru.ru_utime, &stats.user_time);
1154		timeradd(&stats.system_time, &ru.ru_stime, &stats.system_time);
1155	}
1156
1157	/* change working directory to the output directory */
1158	if (fchdir(outdirfd) == -1)
1159		err(1, "fchdir output dir");
1160
1161	if (outputfiles(&vrps, &brks, &stats))
1162		rc = 1;
1163
1164	logx("Processing time %lld seconds "
1165	    "(%lld seconds user, %lld seconds system)",
1166	    (long long)stats.elapsed_time.tv_sec,
1167	    (long long)stats.user_time.tv_sec,
1168	    (long long)stats.system_time.tv_sec);
1169	logx("Route Origin Authorizations: %zu (%zu failed parse, %zu invalid)",
1170	    stats.roas, stats.roas_fail, stats.roas_invalid);
1171	logx("BGPsec Router Certificates: %zu", stats.brks);
1172	logx("Certificates: %zu (%zu invalid)",
1173	    stats.certs, stats.certs_fail);
1174	logx("Trust Anchor Locators: %zu (%zu invalid)",
1175	    stats.tals, talsz - stats.tals);
1176	logx("Manifests: %zu (%zu failed parse, %zu stale)",
1177	    stats.mfts, stats.mfts_fail, stats.mfts_stale);
1178	logx("Certificate revocation lists: %zu", stats.crls);
1179	logx("Ghostbuster records: %zu", stats.gbrs);
1180	logx("Repositories: %zu", stats.repos);
1181	logx("Cleanup: removed %zu files, %zu directories",
1182	    stats.del_files, stats.del_dirs);
1183	logx("VRP Entries: %zu (%zu unique)", stats.vrps, stats.uniqs);
1184
1185	/* Memory cleanup. */
1186	repo_free();
1187
1188	return rc;
1189
1190usage:
1191	fprintf(stderr,
1192	    "usage: rpki-client [-BcjnoRrVv] [-b sourceaddr] [-d cachedir]"
1193	    " [-e rsync_prog]\n"
1194	    "                   [-s timeout] [-T table] [-t tal]"
1195	    " [outputdir]\n");
1196	return 1;
1197}
1198