1 /* $OpenBSD: output-json.c,v 1.22 2021/11/04 11:32:55 claudio Exp $ */ 2 /* 3 * Copyright (c) 2019 Claudio Jeker <claudio@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <stdlib.h> 19 #include <unistd.h> 20 #include <time.h> 21 #include <netdb.h> 22 23 #include "extern.h" 24 25 static int 26 outputheader_json(FILE *out, struct stats *st) 27 { 28 char hn[NI_MAXHOST], tbuf[26]; 29 struct tm *tp; 30 time_t t; 31 size_t i; 32 33 time(&t); 34 setenv("TZ", "UTC", 1); 35 tp = localtime(&t); 36 strftime(tbuf, sizeof tbuf, "%FT%TZ", tp); 37 38 gethostname(hn, sizeof hn); 39 40 if (fprintf(out, 41 "{\n\t\"metadata\": {\n" 42 "\t\t\"buildmachine\": \"%s\",\n" 43 "\t\t\"buildtime\": \"%s\",\n" 44 "\t\t\"elapsedtime\": \"%lld\",\n" 45 "\t\t\"usertime\": \"%lld\",\n" 46 "\t\t\"systemtime\": \"%lld\",\n" 47 "\t\t\"roas\": %zu,\n" 48 "\t\t\"failedroas\": %zu,\n" 49 "\t\t\"invalidroas\": %zu,\n" 50 "\t\t\"bgpsec_pubkeys\": %zu,\n" 51 "\t\t\"certificates\": %zu,\n" 52 "\t\t\"invalidcertificates\": %zu,\n" 53 "\t\t\"tals\": %zu,\n" 54 "\t\t\"invalidtals\": %zu,\n" 55 "\t\t\"talfiles\": [\n", 56 hn, tbuf, (long long)st->elapsed_time.tv_sec, 57 (long long)st->user_time.tv_sec, (long long)st->system_time.tv_sec, 58 st->roas, st->roas_fail, st->roas_invalid, 59 st->brks, st->certs, st->certs_fail, 60 st->tals, talsz - st->tals) < 0) 61 return -1; 62 63 for (i = 0; i < talsz; i++) { 64 if (fprintf(out, 65 "\t\t\t\"%s\"%s\n", 66 tals[i], i == talsz - 1 ? "" : ",") < 0) 67 return -1; 68 } 69 70 if (fprintf(out, 71 "\t\t],\n" 72 "\t\t\"manifests\": %zu,\n" 73 "\t\t\"failedmanifests\": %zu,\n" 74 "\t\t\"stalemanifests\": %zu,\n" 75 "\t\t\"crls\": %zu,\n" 76 "\t\t\"gbrs\": %zu,\n" 77 "\t\t\"repositories\": %zu,\n" 78 "\t\t\"vrps\": %zu,\n" 79 "\t\t\"uniquevrps\": %zu,\n" 80 "\t\t\"cachedir_del_files\": %zu,\n" 81 "\t\t\"cachedir_del_dirs\": %zu\n" 82 "\t},\n\n", 83 st->mfts, st->mfts_fail, st->mfts_stale, 84 st->crls, 85 st->gbrs, 86 st->repos, 87 st->vrps, st->uniqs, 88 st->del_files, st->del_dirs) < 0) 89 return -1; 90 return 0; 91 } 92 93 int 94 output_json(FILE *out, struct vrp_tree *vrps, struct brk_tree *brks, 95 struct stats *st) 96 { 97 char buf[64]; 98 struct vrp *v; 99 struct brk *b; 100 int first = 1; 101 102 if (outputheader_json(out, st) < 0) 103 return -1; 104 105 if (fprintf(out, "\t\"roas\": [\n") < 0) 106 return -1; 107 108 RB_FOREACH(v, vrp_tree, vrps) { 109 if (!first) { 110 if (fprintf(out, ",\n") < 0) 111 return -1; 112 } 113 first = 0; 114 115 ip_addr_print(&v->addr, v->afi, buf, sizeof(buf)); 116 117 if (fprintf(out, "\t\t{ \"asn\": %u, \"prefix\": \"%s\", " 118 "\"maxLength\": %u, \"ta\": \"%s\", \"expires\": %lld }", 119 v->asid, buf, v->maxlength, taldescs[v->talid], 120 (long long)v->expires) 121 < 0) 122 return -1; 123 } 124 125 if (fprintf(out, "\n\t],\n\n\t\"bgpsec_keys\": [\n") < 0) 126 return -1; 127 128 first = 1; 129 RB_FOREACH(b, brk_tree, brks) { 130 if (!first) { 131 if (fprintf(out, ",\n") < 0) 132 return -1; 133 } 134 first = 0; 135 136 if (fprintf(out, "\t\t{ \"asn\": %u, \"ski\": \"%s\", " 137 "\"pubkey\": \"%s\", \"ta\": \"%s\", \"expires\": %lld }", 138 b->asid, b->ski, b->pubkey, taldescs[b->talid], 139 (long long)b->expires) < 0) 140 return -1; 141 } 142 143 if (fprintf(out, "\n\t]\n}\n") < 0) 144 return -1; 145 return 0; 146 } 147