1*30a08502Stb /* $OpenBSD: output-json.c,v 1.51 2024/11/13 12:51:04 tb Exp $ */ 2a382efa2Sclaudio /* 3a382efa2Sclaudio * Copyright (c) 2019 Claudio Jeker <claudio@openbsd.org> 4a382efa2Sclaudio * 5a382efa2Sclaudio * Permission to use, copy, modify, and distribute this software for any 6a382efa2Sclaudio * purpose with or without fee is hereby granted, provided that the above 7a382efa2Sclaudio * copyright notice and this permission notice appear in all copies. 8a382efa2Sclaudio * 9a382efa2Sclaudio * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10a382efa2Sclaudio * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11a382efa2Sclaudio * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12a382efa2Sclaudio * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13a382efa2Sclaudio * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14a382efa2Sclaudio * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15a382efa2Sclaudio * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16a382efa2Sclaudio */ 17a382efa2Sclaudio 18a382efa2Sclaudio #include <stdlib.h> 190ee5ab88Sderaadt #include <unistd.h> 209962cf41Sderaadt #include <time.h> 210ee5ab88Sderaadt #include <netdb.h> 22a382efa2Sclaudio 23a382efa2Sclaudio #include "extern.h" 2415797777Sclaudio #include "json.h" 25a382efa2Sclaudio 2615797777Sclaudio static void 2715797777Sclaudio outputheader_json(struct stats *st) 280ee5ab88Sderaadt { 290ee5ab88Sderaadt char hn[NI_MAXHOST], tbuf[26]; 309962cf41Sderaadt struct tm *tp; 310ee5ab88Sderaadt time_t t; 32389eb209Sclaudio int i; 330ee5ab88Sderaadt 340ee5ab88Sderaadt time(&t); 3565c2098bStb tp = gmtime(&t); 369962cf41Sderaadt strftime(tbuf, sizeof tbuf, "%FT%TZ", tp); 370ee5ab88Sderaadt 380ee5ab88Sderaadt gethostname(hn, sizeof hn); 390ee5ab88Sderaadt 40a09a3191Sclaudio json_do_object("metadata", 0); 41dc508150Sclaudio 42b1f57218Sclaudio json_do_string("buildmachine", hn); 43b1f57218Sclaudio json_do_string("buildtime", tbuf); 4415797777Sclaudio json_do_int("elapsedtime", st->elapsed_time.tv_sec); 4515797777Sclaudio json_do_int("usertime", st->user_time.tv_sec); 4615797777Sclaudio json_do_int("systemtime", st->system_time.tv_sec); 4715797777Sclaudio json_do_int("roas", st->repo_tal_stats.roas); 4815797777Sclaudio json_do_int("failedroas", st->repo_tal_stats.roas_fail); 4915797777Sclaudio json_do_int("invalidroas", st->repo_tal_stats.roas_invalid); 5020c31060Sjob if (experimental) { 51d4be4cdeSjob json_do_int("spls", st->repo_tal_stats.spls); 52d4be4cdeSjob json_do_int("failedspls", st->repo_tal_stats.spls_fail); 53d4be4cdeSjob json_do_int("invalidspls", st->repo_tal_stats.spls_invalid); 5420c31060Sjob } 5515797777Sclaudio json_do_int("aspas", st->repo_tal_stats.aspas); 5615797777Sclaudio json_do_int("failedaspas", st->repo_tal_stats.aspas_fail); 5715797777Sclaudio json_do_int("invalidaspas", st->repo_tal_stats.aspas_invalid); 5815797777Sclaudio json_do_int("bgpsec_pubkeys", st->repo_tal_stats.brks); 5915797777Sclaudio json_do_int("certificates", st->repo_tal_stats.certs); 6015797777Sclaudio json_do_int("invalidcertificates", st->repo_tal_stats.certs_fail); 6115797777Sclaudio json_do_int("taks", st->repo_tal_stats.taks); 6215797777Sclaudio json_do_int("tals", st->tals); 6315797777Sclaudio json_do_int("invalidtals", talsz - st->tals); 6415797777Sclaudio 6515797777Sclaudio json_do_array("talfiles"); 6615797777Sclaudio for (i = 0; i < talsz; i++) 67b1f57218Sclaudio json_do_string("name", tals[i]); 6815797777Sclaudio json_do_end(); 6915797777Sclaudio 7015797777Sclaudio json_do_int("manifests", st->repo_tal_stats.mfts); 7115797777Sclaudio json_do_int("failedmanifests", st->repo_tal_stats.mfts_fail); 7215797777Sclaudio json_do_int("crls", st->repo_tal_stats.crls); 7315797777Sclaudio json_do_int("gbrs", st->repo_tal_stats.gbrs); 7415797777Sclaudio json_do_int("repositories", st->repos); 7515797777Sclaudio json_do_int("vrps", st->repo_tal_stats.vrps); 7615797777Sclaudio json_do_int("uniquevrps", st->repo_tal_stats.vrps_uniqs); 77d4be4cdeSjob json_do_int("vsps", st->repo_tal_stats.vsps); 78d4be4cdeSjob json_do_int("uniquevsps", st->repo_tal_stats.vsps_uniqs); 7915797777Sclaudio json_do_int("vaps", st->repo_tal_stats.vaps); 8015797777Sclaudio json_do_int("uniquevaps", st->repo_tal_stats.vaps_uniqs); 81a5f50487Sjob json_do_int("cachedir_new_files", st->repo_stats.new_files); 8215797777Sclaudio json_do_int("cachedir_del_files", st->repo_stats.del_files); 8315797777Sclaudio json_do_int("cachedir_del_dirs", st->repo_stats.del_dirs); 841438586aSclaudio json_do_int("cachedir_superfluous_files", st->repo_stats.extra_files); 851438586aSclaudio json_do_int("cachedir_del_superfluous_files", 861438586aSclaudio st->repo_stats.del_extra_files); 8715797777Sclaudio 8815797777Sclaudio json_do_end(); 89dc508150Sclaudio } 90dc508150Sclaudio 9115797777Sclaudio static void 924b5fc138Sjob print_vap(struct vap *v) 93a29ddfd5Sjob { 9415797777Sclaudio size_t i; 95a29ddfd5Sjob 967e284d50Stb if (v->overflowed) 97cd55b6bdSjob return; 98cd55b6bdSjob 99a09a3191Sclaudio json_do_object("aspa", 1); 10015797777Sclaudio json_do_int("customer_asid", v->custasid); 10115797777Sclaudio json_do_int("expires", v->expires); 10238f92035Sjob 10315797777Sclaudio json_do_array("providers"); 104*30a08502Stb for (i = 0; i < v->num_providers; i++) 1054b5fc138Sjob json_do_int("provider", v->providers[i]); 1064b5fc138Sjob 10715797777Sclaudio json_do_end(); 108a29ddfd5Sjob } 10914b6717bSjob 11015797777Sclaudio static void 11115797777Sclaudio output_aspa(struct vap_tree *vaps) 112a29ddfd5Sjob { 113a29ddfd5Sjob struct vap *v; 114a29ddfd5Sjob 1154b5fc138Sjob json_do_array("aspas"); 1164b5fc138Sjob RB_FOREACH(v, vap_tree, vaps) 1174b5fc138Sjob print_vap(v); 11815797777Sclaudio json_do_end(); 119a29ddfd5Sjob } 120a29ddfd5Sjob 121ad406917Stb static void 122ad406917Stb output_spl(struct vsp_tree *vsps) 123ad406917Stb { 124ad406917Stb struct vsp *vsp; 125ad406917Stb char buf[64]; 126ad406917Stb size_t i; 127ad406917Stb 128ad406917Stb json_do_array("signedprefixlists"); 129ad406917Stb RB_FOREACH(vsp, vsp_tree, vsps) { 130ad406917Stb json_do_object("vsp", 1); 131ad406917Stb json_do_int("origin_as", vsp->asid); 132ad406917Stb json_do_array("prefixes"); 133*30a08502Stb for (i = 0; i < vsp->num_prefixes; i++) { 134ad406917Stb ip_addr_print(&vsp->prefixes[i].prefix, 135ad406917Stb vsp->prefixes[i].afi, buf, sizeof(buf)); 136ad406917Stb json_do_string("prefix", buf); 137ad406917Stb } 138ad406917Stb json_do_end(); 139ad406917Stb json_do_int("expires", vsp->expires); 140ad406917Stb json_do_string("ta", taldescs[vsp->talid]); 141ad406917Stb json_do_end(); 142ad406917Stb } 143ad406917Stb json_do_end(); 144ad406917Stb } 145ad406917Stb 1461f9a8b94Sderaadt int 1476b83d8e3Sjob output_json(FILE *out, struct vrp_tree *vrps, struct brk_tree *brks, 148d4be4cdeSjob struct vap_tree *vaps, struct vsp_tree *vsps, struct stats *st) 149a382efa2Sclaudio { 150a382efa2Sclaudio char buf[64]; 151a382efa2Sclaudio struct vrp *v; 1526b83d8e3Sjob struct brk *b; 153ed26e04bSderaadt 15415797777Sclaudio json_do_start(out); 15515797777Sclaudio outputheader_json(st); 1560ee5ab88Sderaadt 15715797777Sclaudio json_do_array("roas"); 158a382efa2Sclaudio RB_FOREACH(v, vrp_tree, vrps) { 159a382efa2Sclaudio ip_addr_print(&v->addr, v->afi, buf, sizeof(buf)); 160a382efa2Sclaudio 161a09a3191Sclaudio json_do_object("roa", 1); 16215797777Sclaudio json_do_int("asn", v->asid); 163b1f57218Sclaudio json_do_string("prefix", buf); 16415797777Sclaudio json_do_int("maxLength", v->maxlength); 165b1f57218Sclaudio json_do_string("ta", taldescs[v->talid]); 16615797777Sclaudio json_do_int("expires", v->expires); 16715797777Sclaudio json_do_end(); 168a382efa2Sclaudio } 16915797777Sclaudio json_do_end(); 170a382efa2Sclaudio 17115797777Sclaudio json_do_array("bgpsec_keys"); 1726b83d8e3Sjob RB_FOREACH(b, brk_tree, brks) { 173a09a3191Sclaudio json_do_object("brks", 0); 17415797777Sclaudio json_do_int("asn", b->asid); 175b1f57218Sclaudio json_do_string("ski", b->ski); 176b1f57218Sclaudio json_do_string("pubkey", b->pubkey); 177b1f57218Sclaudio json_do_string("ta", taldescs[b->talid]); 17815797777Sclaudio json_do_int("expires", b->expires); 17915797777Sclaudio json_do_end(); 1806b83d8e3Sjob } 18115797777Sclaudio json_do_end(); 1826b83d8e3Sjob 18315797777Sclaudio if (!excludeaspa) 18415797777Sclaudio output_aspa(vaps); 1856b83d8e3Sjob 1869463abd5Stb if (experimental) 187ad406917Stb output_spl(vsps); 188d4be4cdeSjob 18915797777Sclaudio return json_do_finish(); 190a382efa2Sclaudio } 191