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