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