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