xref: /openbsd-src/usr.sbin/rpki-client/output-json.c (revision d5abdd01d7a5f24fb6f9b0aab446ef59a9e9067a)
1 /*	$OpenBSD: output-json.c,v 1.39 2023/06/05 14:19:13 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 #include "json.h"
25 
26 static void
27 outputheader_json(struct stats *st)
28 {
29 	char		 hn[NI_MAXHOST], tbuf[26];
30 	struct tm	*tp;
31 	time_t		 t;
32 	int		 i;
33 
34 	time(&t);
35 	tp = gmtime(&t);
36 	strftime(tbuf, sizeof tbuf, "%FT%TZ", tp);
37 
38 	gethostname(hn, sizeof hn);
39 
40 	json_do_object("metadata", 0);
41 
42 	json_do_string("buildmachine", hn);
43 	json_do_string("buildtime", tbuf);
44 	json_do_int("elapsedtime", st->elapsed_time.tv_sec);
45 	json_do_int("usertime", st->user_time.tv_sec);
46 	json_do_int("systemtime", st->system_time.tv_sec);
47 	json_do_int("roas", st->repo_tal_stats.roas);
48 	json_do_int("failedroas", st->repo_tal_stats.roas_fail);
49 	json_do_int("invalidroas", st->repo_tal_stats.roas_invalid);
50 	json_do_int("aspas", st->repo_tal_stats.aspas);
51 	json_do_int("failedaspas", st->repo_tal_stats.aspas_fail);
52 	json_do_int("invalidaspas", st->repo_tal_stats.aspas_invalid);
53 	json_do_int("bgpsec_pubkeys", st->repo_tal_stats.brks);
54 	json_do_int("certificates", st->repo_tal_stats.certs);
55 	json_do_int("invalidcertificates", st->repo_tal_stats.certs_fail);
56 	json_do_int("taks", st->repo_tal_stats.taks);
57 	json_do_int("tals", st->tals);
58 	json_do_int("invalidtals", talsz - st->tals);
59 
60 	json_do_array("talfiles");
61 	for (i = 0; i < talsz; i++)
62 		json_do_string("name", tals[i]);
63 	json_do_end();
64 
65 	json_do_int("manifests", st->repo_tal_stats.mfts);
66 	json_do_int("failedmanifests", st->repo_tal_stats.mfts_fail);
67 	json_do_int("stalemanifests", st->repo_tal_stats.mfts_stale);
68 	json_do_int("crls", st->repo_tal_stats.crls);
69 	json_do_int("gbrs", st->repo_tal_stats.gbrs);
70 	json_do_int("repositories", st->repos);
71 	json_do_int("vrps", st->repo_tal_stats.vrps);
72 	json_do_int("uniquevrps", st->repo_tal_stats.vrps_uniqs);
73 	json_do_int("vaps", st->repo_tal_stats.vaps);
74 	json_do_int("uniquevaps", st->repo_tal_stats.vaps_uniqs);
75 	json_do_int("cachedir_del_files", st->repo_stats.del_files);
76 	json_do_int("cachedir_del_dirs", st->repo_stats.del_dirs);
77 	json_do_int("cachedir_superfluous_files", st->repo_stats.extra_files);
78 	json_do_int("cachedir_del_superfluous_files",
79 	    st->repo_stats.del_extra_files);
80 
81 	json_do_end();
82 }
83 
84 static void
85 print_vap(struct vap *v, enum afi afi)
86 {
87 	size_t i;
88 	int found = 0;
89 
90 	json_do_object("aspa", 1);
91 	json_do_int("customer_asid", v->custasid);
92 	json_do_int("expires", v->expires);
93 
94 	json_do_array("providers");
95 	for (i = 0; i < v->providersz; i++) {
96 		if (v->providers[i].afi != 0 && v->providers[i].afi != afi)
97 			continue;
98 		found = 1;
99 		json_do_int("provider", v->providers[i].as);
100 	}
101 	if (!found)
102 		json_do_int("provider", 0);
103 	json_do_end();
104 }
105 
106 static void
107 output_aspa(struct vap_tree *vaps)
108 {
109 	struct vap	*v;
110 
111 	json_do_object("provider_authorizations", 0);
112 
113 	json_do_array("ipv4");
114 	RB_FOREACH(v, vap_tree, vaps) {
115 		print_vap(v, AFI_IPV4);
116 	}
117 	json_do_end();
118 
119 	json_do_array("ipv6");
120 	RB_FOREACH(v, vap_tree, vaps) {
121 		print_vap(v, AFI_IPV6);
122 	}
123 	json_do_end();
124 }
125 
126 int
127 output_json(FILE *out, struct vrp_tree *vrps, struct brk_tree *brks,
128     struct vap_tree *vaps, struct stats *st)
129 {
130 	char		 buf[64];
131 	struct vrp	*v;
132 	struct brk	*b;
133 
134 	json_do_start(out);
135 	outputheader_json(st);
136 
137 	json_do_array("roas");
138 	RB_FOREACH(v, vrp_tree, vrps) {
139 		ip_addr_print(&v->addr, v->afi, buf, sizeof(buf));
140 
141 		json_do_object("roa", 1);
142 		json_do_int("asn", v->asid);
143 		json_do_string("prefix", buf);
144 		json_do_int("maxLength", v->maxlength);
145 		json_do_string("ta", taldescs[v->talid]);
146 		json_do_int("expires", v->expires);
147 		json_do_end();
148 	}
149 	json_do_end();
150 
151 	json_do_array("bgpsec_keys");
152 	RB_FOREACH(b, brk_tree, brks) {
153 		json_do_object("brks", 0);
154 		json_do_int("asn", b->asid);
155 		json_do_string("ski", b->ski);
156 		json_do_string("pubkey", b->pubkey);
157 		json_do_string("ta", taldescs[b->talid]);
158 		json_do_int("expires", b->expires);
159 		json_do_end();
160 	}
161 	json_do_end();
162 
163 	if (!excludeaspa)
164 		output_aspa(vaps);
165 
166 	return json_do_finish();
167 }
168