ns_print.c revision 1.12 1 1.12 rillig /* $NetBSD: ns_print.c,v 1.12 2022/04/19 20:32:15 rillig Exp $ */
2 1.1 christos
3 1.1 christos /*
4 1.1 christos * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
5 1.1 christos * Copyright (c) 1996-1999 by Internet Software Consortium.
6 1.1 christos *
7 1.1 christos * Permission to use, copy, modify, and distribute this software for any
8 1.1 christos * purpose with or without fee is hereby granted, provided that the above
9 1.1 christos * copyright notice and this permission notice appear in all copies.
10 1.1 christos *
11 1.1 christos * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
12 1.1 christos * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 1.1 christos * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
14 1.1 christos * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 1.1 christos * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 1.1 christos * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
17 1.1 christos * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 1.1 christos */
19 1.1 christos
20 1.2 christos #include <sys/cdefs.h>
21 1.1 christos #ifndef lint
22 1.2 christos #ifdef notdef
23 1.9 christos static const char rcsid[] = "Id: ns_print.c,v 1.12 2009/03/03 05:29:58 each Exp";
24 1.2 christos #else
25 1.12 rillig __RCSID("$NetBSD: ns_print.c,v 1.12 2022/04/19 20:32:15 rillig Exp $");
26 1.2 christos #endif
27 1.1 christos #endif
28 1.1 christos
29 1.1 christos /* Import. */
30 1.1 christos
31 1.1 christos #include "port_before.h"
32 1.1 christos
33 1.1 christos #include <sys/types.h>
34 1.1 christos #include <sys/socket.h>
35 1.1 christos
36 1.1 christos #include <netinet/in.h>
37 1.1 christos #include <arpa/nameser.h>
38 1.1 christos #include <arpa/inet.h>
39 1.1 christos
40 1.1 christos #include <isc/assertions.h>
41 1.1 christos #include <isc/dst.h>
42 1.11 christos #include <assert.h>
43 1.1 christos #include <errno.h>
44 1.1 christos #include <resolv.h>
45 1.11 christos #include <stddef.h>
46 1.1 christos #include <string.h>
47 1.1 christos #include <ctype.h>
48 1.1 christos
49 1.1 christos #include "port_after.h"
50 1.1 christos
51 1.1 christos #ifdef SPRINTF_CHAR
52 1.11 christos # define SPRINTF(x) ((int)strlen(sprintf/**/x))
53 1.1 christos #else
54 1.11 christos # define SPRINTF(x) (sprintf x)
55 1.1 christos #endif
56 1.1 christos
57 1.1 christos /* Forward. */
58 1.1 christos
59 1.1 christos static size_t prune_origin(const char *name, const char *origin);
60 1.1 christos static int charstr(const u_char *rdata, const u_char *edata,
61 1.1 christos char **buf, size_t *buflen);
62 1.1 christos static int addname(const u_char *msg, size_t msglen,
63 1.1 christos const u_char **p, const char *origin,
64 1.1 christos char **buf, size_t *buflen);
65 1.1 christos static void addlen(size_t len, char **buf, size_t *buflen);
66 1.1 christos static int addstr(const char *src, size_t len,
67 1.1 christos char **buf, size_t *buflen);
68 1.1 christos static int addtab(size_t len, size_t target, int spaced,
69 1.1 christos char **buf, size_t *buflen);
70 1.1 christos
71 1.1 christos /* Macros. */
72 1.1 christos
73 1.1 christos #define T(x) \
74 1.1 christos do { \
75 1.1 christos if ((x) < 0) \
76 1.1 christos return (-1); \
77 1.12 rillig } while (0)
78 1.1 christos
79 1.9 christos static const char base32hex[] =
80 1.9 christos "0123456789ABCDEFGHIJKLMNOPQRSTUV=0123456789abcdefghijklmnopqrstuv";
81 1.9 christos
82 1.1 christos /* Public. */
83 1.1 christos
84 1.6 christos /*%
85 1.1 christos * Convert an RR to presentation format.
86 1.6 christos *
87 1.1 christos * return:
88 1.6 christos *\li Number of characters written to buf, or -1 (check errno).
89 1.1 christos */
90 1.1 christos int
91 1.1 christos ns_sprintrr(const ns_msg *handle, const ns_rr *rr,
92 1.1 christos const char *name_ctx, const char *origin,
93 1.1 christos char *buf, size_t buflen)
94 1.1 christos {
95 1.1 christos int n;
96 1.1 christos
97 1.1 christos n = ns_sprintrrf(ns_msg_base(*handle), ns_msg_size(*handle),
98 1.1 christos ns_rr_name(*rr), ns_rr_class(*rr), ns_rr_type(*rr),
99 1.1 christos ns_rr_ttl(*rr), ns_rr_rdata(*rr), ns_rr_rdlen(*rr),
100 1.1 christos name_ctx, origin, buf, buflen);
101 1.1 christos return (n);
102 1.1 christos }
103 1.1 christos
104 1.6 christos /*%
105 1.1 christos * Convert the fields of an RR into presentation format.
106 1.6 christos *
107 1.1 christos * return:
108 1.6 christos *\li Number of characters written to buf, or -1 (check errno).
109 1.1 christos */
110 1.1 christos int
111 1.1 christos ns_sprintrrf(const u_char *msg, size_t msglen,
112 1.1 christos const char *name, ns_class class, ns_type type,
113 1.1 christos u_long ttl, const u_char *rdata, size_t rdlen,
114 1.1 christos const char *name_ctx, const char *origin,
115 1.1 christos char *buf, size_t buflen)
116 1.1 christos {
117 1.1 christos const char *obuf = buf;
118 1.1 christos const u_char *edata = rdata + rdlen;
119 1.1 christos int spaced = 0;
120 1.1 christos
121 1.1 christos const char *comment;
122 1.1 christos char tmp[100];
123 1.1 christos int len, x;
124 1.1 christos
125 1.1 christos /*
126 1.1 christos * Owner.
127 1.1 christos */
128 1.1 christos if (name_ctx != NULL && ns_samename(name_ctx, name) == 1) {
129 1.2 christos T(addstr("\t\t\t", (size_t)3, &buf, &buflen));
130 1.1 christos } else {
131 1.11 christos len = (int)prune_origin(name, origin);
132 1.1 christos if (*name == '\0') {
133 1.1 christos goto root;
134 1.1 christos } else if (len == 0) {
135 1.2 christos T(addstr("@\t\t\t", (size_t)4, &buf, &buflen));
136 1.1 christos } else {
137 1.2 christos T(addstr(name, (size_t)len, &buf, &buflen));
138 1.1 christos /* Origin not used or not root, and no trailing dot? */
139 1.1 christos if (((origin == NULL || origin[0] == '\0') ||
140 1.1 christos (origin[0] != '.' && origin[1] != '\0' &&
141 1.1 christos name[len] == '\0')) && name[len - 1] != '.') {
142 1.1 christos root:
143 1.2 christos T(addstr(".", (size_t)1, &buf, &buflen));
144 1.1 christos len++;
145 1.1 christos }
146 1.2 christos T(spaced = addtab((size_t)len, 24, spaced, &buf, &buflen));
147 1.1 christos }
148 1.1 christos }
149 1.1 christos
150 1.1 christos /*
151 1.1 christos * TTL, Class, Type.
152 1.1 christos */
153 1.1 christos T(x = ns_format_ttl(ttl, buf, buflen));
154 1.2 christos addlen((size_t)x, &buf, &buflen);
155 1.1 christos len = SPRINTF((tmp, " %s %s", p_class(class), p_type(type)));
156 1.2 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
157 1.2 christos T(spaced = addtab((size_t)(x + len), (size_t)16, spaced, &buf, &buflen));
158 1.1 christos
159 1.1 christos /*
160 1.1 christos * RData.
161 1.1 christos */
162 1.1 christos switch (type) {
163 1.1 christos case ns_t_a:
164 1.1 christos if (rdlen != (size_t)NS_INADDRSZ)
165 1.1 christos goto formerr;
166 1.11 christos (void) inet_ntop(AF_INET, rdata, buf, (socklen_t)buflen);
167 1.1 christos addlen(strlen(buf), &buf, &buflen);
168 1.1 christos break;
169 1.1 christos
170 1.1 christos case ns_t_cname:
171 1.1 christos case ns_t_mb:
172 1.1 christos case ns_t_mg:
173 1.1 christos case ns_t_mr:
174 1.1 christos case ns_t_ns:
175 1.1 christos case ns_t_ptr:
176 1.1 christos case ns_t_dname:
177 1.1 christos T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
178 1.1 christos break;
179 1.1 christos
180 1.1 christos case ns_t_hinfo:
181 1.1 christos case ns_t_isdn:
182 1.1 christos /* First word. */
183 1.1 christos T(len = charstr(rdata, edata, &buf, &buflen));
184 1.1 christos if (len == 0)
185 1.1 christos goto formerr;
186 1.1 christos rdata += len;
187 1.2 christos T(addstr(" ", (size_t)1, &buf, &buflen));
188 1.1 christos
189 1.1 christos
190 1.1 christos /* Second word, optional in ISDN records. */
191 1.1 christos if (type == ns_t_isdn && rdata == edata)
192 1.1 christos break;
193 1.1 christos
194 1.1 christos T(len = charstr(rdata, edata, &buf, &buflen));
195 1.1 christos if (len == 0)
196 1.1 christos goto formerr;
197 1.1 christos rdata += len;
198 1.1 christos break;
199 1.1 christos
200 1.1 christos case ns_t_soa: {
201 1.1 christos u_long t;
202 1.1 christos
203 1.1 christos /* Server name. */
204 1.1 christos T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
205 1.2 christos T(addstr(" ", (size_t)1, &buf, &buflen));
206 1.1 christos
207 1.1 christos /* Administrator name. */
208 1.1 christos T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
209 1.2 christos T(addstr(" (\n", (size_t)3, &buf, &buflen));
210 1.1 christos spaced = 0;
211 1.1 christos
212 1.1 christos if ((edata - rdata) != 5*NS_INT32SZ)
213 1.1 christos goto formerr;
214 1.1 christos
215 1.1 christos /* Serial number. */
216 1.1 christos t = ns_get32(rdata); rdata += NS_INT32SZ;
217 1.2 christos T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen));
218 1.1 christos len = SPRINTF((tmp, "%lu", t));
219 1.2 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
220 1.2 christos T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen));
221 1.2 christos T(addstr("; serial\n", (size_t)9, &buf, &buflen));
222 1.1 christos spaced = 0;
223 1.1 christos
224 1.1 christos /* Refresh interval. */
225 1.1 christos t = ns_get32(rdata); rdata += NS_INT32SZ;
226 1.2 christos T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen));
227 1.1 christos T(len = ns_format_ttl(t, buf, buflen));
228 1.2 christos addlen((size_t)len, &buf, &buflen);
229 1.2 christos T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen));
230 1.2 christos T(addstr("; refresh\n", (size_t)10, &buf, &buflen));
231 1.1 christos spaced = 0;
232 1.1 christos
233 1.1 christos /* Retry interval. */
234 1.1 christos t = ns_get32(rdata); rdata += NS_INT32SZ;
235 1.2 christos T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen));
236 1.1 christos T(len = ns_format_ttl(t, buf, buflen));
237 1.2 christos addlen((size_t)len, &buf, &buflen);
238 1.2 christos T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen));
239 1.2 christos T(addstr("; retry\n", (size_t)8, &buf, &buflen));
240 1.1 christos spaced = 0;
241 1.1 christos
242 1.1 christos /* Expiry. */
243 1.1 christos t = ns_get32(rdata); rdata += NS_INT32SZ;
244 1.2 christos T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen));
245 1.1 christos T(len = ns_format_ttl(t, buf, buflen));
246 1.2 christos addlen((size_t)len, &buf, &buflen);
247 1.2 christos T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen));
248 1.2 christos T(addstr("; expiry\n", (size_t)9, &buf, &buflen));
249 1.1 christos spaced = 0;
250 1.1 christos
251 1.1 christos /* Minimum TTL. */
252 1.1 christos t = ns_get32(rdata); rdata += NS_INT32SZ;
253 1.2 christos T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen));
254 1.1 christos T(len = ns_format_ttl(t, buf, buflen));
255 1.2 christos addlen((size_t)len, &buf, &buflen);
256 1.2 christos T(addstr(" )", (size_t)2, &buf, &buflen));
257 1.2 christos T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen));
258 1.2 christos T(addstr("; minimum\n", (size_t)10, &buf, &buflen));
259 1.1 christos
260 1.1 christos break;
261 1.1 christos }
262 1.1 christos
263 1.1 christos case ns_t_mx:
264 1.1 christos case ns_t_afsdb:
265 1.9 christos case ns_t_rt:
266 1.9 christos case ns_t_kx: {
267 1.1 christos u_int t;
268 1.1 christos
269 1.1 christos if (rdlen < (size_t)NS_INT16SZ)
270 1.1 christos goto formerr;
271 1.1 christos
272 1.1 christos /* Priority. */
273 1.1 christos t = ns_get16(rdata);
274 1.1 christos rdata += NS_INT16SZ;
275 1.1 christos len = SPRINTF((tmp, "%u ", t));
276 1.2 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
277 1.1 christos
278 1.1 christos /* Target. */
279 1.1 christos T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
280 1.1 christos
281 1.1 christos break;
282 1.1 christos }
283 1.1 christos
284 1.1 christos case ns_t_px: {
285 1.1 christos u_int t;
286 1.1 christos
287 1.1 christos if (rdlen < (size_t)NS_INT16SZ)
288 1.1 christos goto formerr;
289 1.1 christos
290 1.1 christos /* Priority. */
291 1.1 christos t = ns_get16(rdata);
292 1.1 christos rdata += NS_INT16SZ;
293 1.1 christos len = SPRINTF((tmp, "%u ", t));
294 1.2 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
295 1.1 christos
296 1.1 christos /* Name1. */
297 1.1 christos T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
298 1.2 christos T(addstr(" ", (size_t)1, &buf, &buflen));
299 1.1 christos
300 1.1 christos /* Name2. */
301 1.1 christos T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
302 1.1 christos
303 1.1 christos break;
304 1.1 christos }
305 1.1 christos
306 1.1 christos case ns_t_x25:
307 1.1 christos T(len = charstr(rdata, edata, &buf, &buflen));
308 1.1 christos if (len == 0)
309 1.1 christos goto formerr;
310 1.1 christos rdata += len;
311 1.1 christos break;
312 1.1 christos
313 1.1 christos case ns_t_txt:
314 1.9 christos case ns_t_spf:
315 1.1 christos while (rdata < edata) {
316 1.1 christos T(len = charstr(rdata, edata, &buf, &buflen));
317 1.1 christos if (len == 0)
318 1.1 christos goto formerr;
319 1.1 christos rdata += len;
320 1.1 christos if (rdata < edata)
321 1.2 christos T(addstr(" ", (size_t)1, &buf, &buflen));
322 1.1 christos }
323 1.1 christos break;
324 1.1 christos
325 1.1 christos case ns_t_nsap: {
326 1.1 christos char t[2+255*3];
327 1.1 christos
328 1.2 christos (void) inet_nsap_ntoa((int)rdlen, rdata, t);
329 1.1 christos T(addstr(t, strlen(t), &buf, &buflen));
330 1.1 christos break;
331 1.1 christos }
332 1.1 christos
333 1.1 christos case ns_t_aaaa:
334 1.1 christos if (rdlen != (size_t)NS_IN6ADDRSZ)
335 1.1 christos goto formerr;
336 1.11 christos (void) inet_ntop(AF_INET6, rdata, buf, (socklen_t)buflen);
337 1.1 christos addlen(strlen(buf), &buf, &buflen);
338 1.1 christos break;
339 1.1 christos
340 1.1 christos case ns_t_loc: {
341 1.1 christos char t[255];
342 1.1 christos
343 1.1 christos /* XXX protocol format checking? */
344 1.1 christos (void) loc_ntoa(rdata, t);
345 1.1 christos T(addstr(t, strlen(t), &buf, &buflen));
346 1.1 christos break;
347 1.1 christos }
348 1.1 christos
349 1.1 christos case ns_t_naptr: {
350 1.1 christos u_int order, preference;
351 1.1 christos char t[50];
352 1.1 christos
353 1.1 christos if (rdlen < 2U*NS_INT16SZ)
354 1.1 christos goto formerr;
355 1.1 christos
356 1.1 christos /* Order, Precedence. */
357 1.1 christos order = ns_get16(rdata); rdata += NS_INT16SZ;
358 1.1 christos preference = ns_get16(rdata); rdata += NS_INT16SZ;
359 1.1 christos len = SPRINTF((t, "%u %u ", order, preference));
360 1.2 christos T(addstr(t, (size_t)len, &buf, &buflen));
361 1.1 christos
362 1.1 christos /* Flags. */
363 1.1 christos T(len = charstr(rdata, edata, &buf, &buflen));
364 1.1 christos if (len == 0)
365 1.1 christos goto formerr;
366 1.1 christos rdata += len;
367 1.2 christos T(addstr(" ", (size_t)1, &buf, &buflen));
368 1.1 christos
369 1.1 christos /* Service. */
370 1.1 christos T(len = charstr(rdata, edata, &buf, &buflen));
371 1.1 christos if (len == 0)
372 1.1 christos goto formerr;
373 1.1 christos rdata += len;
374 1.2 christos T(addstr(" ", (size_t)1, &buf, &buflen));
375 1.1 christos
376 1.1 christos /* Regexp. */
377 1.1 christos T(len = charstr(rdata, edata, &buf, &buflen));
378 1.1 christos if (len < 0)
379 1.1 christos return (-1);
380 1.1 christos if (len == 0)
381 1.1 christos goto formerr;
382 1.1 christos rdata += len;
383 1.2 christos T(addstr(" ", (size_t)1, &buf, &buflen));
384 1.1 christos
385 1.1 christos /* Server. */
386 1.1 christos T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
387 1.1 christos break;
388 1.1 christos }
389 1.1 christos
390 1.1 christos case ns_t_srv: {
391 1.1 christos u_int priority, weight, port;
392 1.1 christos char t[50];
393 1.1 christos
394 1.1 christos if (rdlen < 3U*NS_INT16SZ)
395 1.1 christos goto formerr;
396 1.1 christos
397 1.1 christos /* Priority, Weight, Port. */
398 1.1 christos priority = ns_get16(rdata); rdata += NS_INT16SZ;
399 1.1 christos weight = ns_get16(rdata); rdata += NS_INT16SZ;
400 1.1 christos port = ns_get16(rdata); rdata += NS_INT16SZ;
401 1.1 christos len = SPRINTF((t, "%u %u %u ", priority, weight, port));
402 1.2 christos T(addstr(t, (size_t)len, &buf, &buflen));
403 1.1 christos
404 1.1 christos /* Server. */
405 1.1 christos T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
406 1.1 christos break;
407 1.1 christos }
408 1.1 christos
409 1.1 christos case ns_t_minfo:
410 1.1 christos case ns_t_rp:
411 1.1 christos /* Name1. */
412 1.1 christos T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
413 1.2 christos T(addstr(" ", (size_t)1, &buf, &buflen));
414 1.1 christos
415 1.1 christos /* Name2. */
416 1.1 christos T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
417 1.1 christos
418 1.1 christos break;
419 1.1 christos
420 1.1 christos case ns_t_wks: {
421 1.1 christos int n, lcnt;
422 1.1 christos
423 1.1 christos if (rdlen < 1U + NS_INT32SZ)
424 1.1 christos goto formerr;
425 1.1 christos
426 1.1 christos /* Address. */
427 1.11 christos (void) inet_ntop(AF_INET, rdata, buf, (socklen_t)buflen);
428 1.1 christos addlen(strlen(buf), &buf, &buflen);
429 1.1 christos rdata += NS_INADDRSZ;
430 1.1 christos
431 1.1 christos /* Protocol. */
432 1.1 christos len = SPRINTF((tmp, " %u ( ", *rdata));
433 1.2 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
434 1.1 christos rdata += NS_INT8SZ;
435 1.1 christos
436 1.1 christos /* Bit map. */
437 1.1 christos n = 0;
438 1.1 christos lcnt = 0;
439 1.1 christos while (rdata < edata) {
440 1.1 christos u_int c = *rdata++;
441 1.1 christos do {
442 1.1 christos if (c & 0200) {
443 1.1 christos if (lcnt == 0) {
444 1.2 christos T(addstr("\n\t\t\t\t", (size_t)5,
445 1.1 christos &buf, &buflen));
446 1.1 christos lcnt = 10;
447 1.1 christos spaced = 0;
448 1.1 christos }
449 1.1 christos len = SPRINTF((tmp, "%d ", n));
450 1.2 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
451 1.1 christos lcnt--;
452 1.1 christos }
453 1.1 christos c <<= 1;
454 1.1 christos } while (++n & 07);
455 1.1 christos }
456 1.2 christos T(addstr(")", (size_t)1, &buf, &buflen));
457 1.1 christos
458 1.1 christos break;
459 1.1 christos }
460 1.1 christos
461 1.9 christos case ns_t_key:
462 1.9 christos case ns_t_dnskey: {
463 1.1 christos char base64_key[NS_MD5RSA_MAX_BASE64];
464 1.1 christos u_int keyflags, protocol, algorithm, key_id;
465 1.1 christos const char *leader;
466 1.1 christos int n;
467 1.1 christos
468 1.1 christos if (rdlen < 0U + NS_INT16SZ + NS_INT8SZ + NS_INT8SZ)
469 1.1 christos goto formerr;
470 1.1 christos
471 1.1 christos /* Key flags, Protocol, Algorithm. */
472 1.3 christos #ifndef _LIBC
473 1.1 christos key_id = dst_s_dns_key_id(rdata, edata-rdata);
474 1.3 christos #else
475 1.3 christos key_id = 0;
476 1.3 christos #endif
477 1.1 christos keyflags = ns_get16(rdata); rdata += NS_INT16SZ;
478 1.1 christos protocol = *rdata++;
479 1.1 christos algorithm = *rdata++;
480 1.1 christos len = SPRINTF((tmp, "0x%04x %u %u",
481 1.1 christos keyflags, protocol, algorithm));
482 1.2 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
483 1.1 christos
484 1.1 christos /* Public key data. */
485 1.2 christos len = b64_ntop(rdata, (size_t)(edata - rdata),
486 1.1 christos base64_key, sizeof base64_key);
487 1.1 christos if (len < 0)
488 1.1 christos goto formerr;
489 1.1 christos if (len > 15) {
490 1.2 christos T(addstr(" (", (size_t)2, &buf, &buflen));
491 1.1 christos leader = "\n\t\t";
492 1.1 christos spaced = 0;
493 1.1 christos } else
494 1.1 christos leader = " ";
495 1.1 christos for (n = 0; n < len; n += 48) {
496 1.1 christos T(addstr(leader, strlen(leader), &buf, &buflen));
497 1.2 christos T(addstr(base64_key + n, (size_t)MIN(len - n, 48),
498 1.1 christos &buf, &buflen));
499 1.1 christos }
500 1.1 christos if (len > 15)
501 1.2 christos T(addstr(" )", (size_t)2, &buf, &buflen));
502 1.1 christos n = SPRINTF((tmp, " ; key_tag= %u", key_id));
503 1.2 christos T(addstr(tmp, (size_t)n, &buf, &buflen));
504 1.1 christos
505 1.1 christos break;
506 1.1 christos }
507 1.1 christos
508 1.9 christos case ns_t_sig:
509 1.9 christos case ns_t_rrsig: {
510 1.1 christos char base64_key[NS_MD5RSA_MAX_BASE64];
511 1.2 christos u_int typ, algorithm, labels, footprint;
512 1.1 christos const char *leader;
513 1.1 christos u_long t;
514 1.1 christos int n;
515 1.1 christos
516 1.1 christos if (rdlen < 22U)
517 1.1 christos goto formerr;
518 1.1 christos
519 1.1 christos /* Type covered, Algorithm, Label count, Original TTL. */
520 1.2 christos typ = ns_get16(rdata); rdata += NS_INT16SZ;
521 1.1 christos algorithm = *rdata++;
522 1.1 christos labels = *rdata++;
523 1.1 christos t = ns_get32(rdata); rdata += NS_INT32SZ;
524 1.1 christos len = SPRINTF((tmp, "%s %d %d %lu ",
525 1.2 christos p_type((int)typ), algorithm, labels, t));
526 1.2 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
527 1.1 christos if (labels > (u_int)dn_count_labels(name))
528 1.1 christos goto formerr;
529 1.1 christos
530 1.1 christos /* Signature expiry. */
531 1.1 christos t = ns_get32(rdata); rdata += NS_INT32SZ;
532 1.1 christos len = SPRINTF((tmp, "%s ", p_secstodate(t)));
533 1.2 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
534 1.1 christos
535 1.1 christos /* Time signed. */
536 1.1 christos t = ns_get32(rdata); rdata += NS_INT32SZ;
537 1.1 christos len = SPRINTF((tmp, "%s ", p_secstodate(t)));
538 1.2 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
539 1.1 christos
540 1.1 christos /* Signature Footprint. */
541 1.1 christos footprint = ns_get16(rdata); rdata += NS_INT16SZ;
542 1.1 christos len = SPRINTF((tmp, "%u ", footprint));
543 1.2 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
544 1.1 christos
545 1.1 christos /* Signer's name. */
546 1.1 christos T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
547 1.1 christos
548 1.1 christos /* Signature. */
549 1.2 christos len = b64_ntop(rdata, (size_t)(edata - rdata),
550 1.1 christos base64_key, sizeof base64_key);
551 1.1 christos if (len > 15) {
552 1.2 christos T(addstr(" (", (size_t)2, &buf, &buflen));
553 1.1 christos leader = "\n\t\t";
554 1.1 christos spaced = 0;
555 1.1 christos } else
556 1.1 christos leader = " ";
557 1.1 christos if (len < 0)
558 1.1 christos goto formerr;
559 1.1 christos for (n = 0; n < len; n += 48) {
560 1.1 christos T(addstr(leader, strlen(leader), &buf, &buflen));
561 1.2 christos T(addstr(base64_key + n, (size_t)MIN(len - n, 48),
562 1.1 christos &buf, &buflen));
563 1.1 christos }
564 1.1 christos if (len > 15)
565 1.2 christos T(addstr(" )", (size_t)2, &buf, &buflen));
566 1.1 christos break;
567 1.1 christos }
568 1.1 christos
569 1.1 christos case ns_t_nxt: {
570 1.11 christos ptrdiff_t n, c;
571 1.1 christos
572 1.1 christos /* Next domain name. */
573 1.1 christos T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
574 1.1 christos
575 1.1 christos /* Type bit map. */
576 1.1 christos n = edata - rdata;
577 1.1 christos for (c = 0; c < n*8; c++)
578 1.1 christos if (NS_NXT_BIT_ISSET(c, rdata)) {
579 1.11 christos len = SPRINTF((tmp, " %s", p_type((int)c)));
580 1.2 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
581 1.1 christos }
582 1.1 christos break;
583 1.1 christos }
584 1.1 christos
585 1.1 christos case ns_t_cert: {
586 1.1 christos u_int c_type, key_tag, alg;
587 1.1 christos int n;
588 1.11 christos size_t siz;
589 1.2 christos char base64_cert[8192], tmp1[40];
590 1.1 christos const char *leader;
591 1.1 christos
592 1.1 christos c_type = ns_get16(rdata); rdata += NS_INT16SZ;
593 1.1 christos key_tag = ns_get16(rdata); rdata += NS_INT16SZ;
594 1.1 christos alg = (u_int) *rdata++;
595 1.1 christos
596 1.2 christos len = SPRINTF((tmp1, "%d %d %d ", c_type, key_tag, alg));
597 1.2 christos T(addstr(tmp1, (size_t)len, &buf, &buflen));
598 1.1 christos siz = (edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */
599 1.1 christos if (siz > sizeof(base64_cert) * 3/4) {
600 1.1 christos const char *str = "record too long to print";
601 1.1 christos T(addstr(str, strlen(str), &buf, &buflen));
602 1.1 christos }
603 1.1 christos else {
604 1.2 christos len = b64_ntop(rdata, (size_t)(edata-rdata),
605 1.2 christos base64_cert, siz);
606 1.1 christos
607 1.1 christos if (len < 0)
608 1.1 christos goto formerr;
609 1.1 christos else if (len > 15) {
610 1.2 christos T(addstr(" (", (size_t)2, &buf, &buflen));
611 1.1 christos leader = "\n\t\t";
612 1.1 christos spaced = 0;
613 1.1 christos }
614 1.1 christos else
615 1.1 christos leader = " ";
616 1.1 christos
617 1.1 christos for (n = 0; n < len; n += 48) {
618 1.1 christos T(addstr(leader, strlen(leader),
619 1.1 christos &buf, &buflen));
620 1.2 christos T(addstr(base64_cert + n, (size_t)MIN(len - n, 48),
621 1.1 christos &buf, &buflen));
622 1.1 christos }
623 1.1 christos if (len > 15)
624 1.2 christos T(addstr(" )", (size_t)2, &buf, &buflen));
625 1.1 christos }
626 1.1 christos break;
627 1.1 christos }
628 1.1 christos
629 1.1 christos case ns_t_tkey: {
630 1.1 christos /* KJD - need to complete this */
631 1.1 christos u_long t;
632 1.1 christos int mode, err, keysize;
633 1.1 christos
634 1.1 christos /* Algorithm name. */
635 1.1 christos T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
636 1.2 christos T(addstr(" ", (size_t)1, &buf, &buflen));
637 1.1 christos
638 1.1 christos /* Inception. */
639 1.1 christos t = ns_get32(rdata); rdata += NS_INT32SZ;
640 1.1 christos len = SPRINTF((tmp, "%s ", p_secstodate(t)));
641 1.2 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
642 1.1 christos
643 1.1 christos /* Experation. */
644 1.1 christos t = ns_get32(rdata); rdata += NS_INT32SZ;
645 1.1 christos len = SPRINTF((tmp, "%s ", p_secstodate(t)));
646 1.2 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
647 1.1 christos
648 1.1 christos /* Mode , Error, Key Size. */
649 1.1 christos /* Priority, Weight, Port. */
650 1.1 christos mode = ns_get16(rdata); rdata += NS_INT16SZ;
651 1.1 christos err = ns_get16(rdata); rdata += NS_INT16SZ;
652 1.1 christos keysize = ns_get16(rdata); rdata += NS_INT16SZ;
653 1.1 christos len = SPRINTF((tmp, "%u %u %u ", mode, err, keysize));
654 1.2 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
655 1.1 christos
656 1.1 christos /* XXX need to dump key, print otherdata length & other data */
657 1.1 christos break;
658 1.1 christos }
659 1.1 christos
660 1.1 christos case ns_t_tsig: {
661 1.1 christos /* BEW - need to complete this */
662 1.1 christos int n;
663 1.1 christos
664 1.1 christos T(len = addname(msg, msglen, &rdata, origin, &buf, &buflen));
665 1.2 christos T(addstr(" ", (size_t)1, &buf, &buflen));
666 1.6 christos rdata += 8; /*%< time */
667 1.1 christos n = ns_get16(rdata); rdata += INT16SZ;
668 1.6 christos rdata += n; /*%< sig */
669 1.6 christos n = ns_get16(rdata); rdata += INT16SZ; /*%< original id */
670 1.1 christos sprintf(buf, "%d", ns_get16(rdata));
671 1.1 christos rdata += INT16SZ;
672 1.1 christos addlen(strlen(buf), &buf, &buflen);
673 1.1 christos break;
674 1.1 christos }
675 1.1 christos
676 1.1 christos case ns_t_a6: {
677 1.1 christos struct in6_addr a;
678 1.1 christos int pbyte, pbit;
679 1.1 christos
680 1.1 christos /* prefix length */
681 1.1 christos if (rdlen == 0U) goto formerr;
682 1.1 christos len = SPRINTF((tmp, "%d ", *rdata));
683 1.2 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
684 1.1 christos pbit = *rdata;
685 1.1 christos if (pbit > 128) goto formerr;
686 1.1 christos pbyte = (pbit & ~7) / 8;
687 1.1 christos rdata++;
688 1.1 christos
689 1.1 christos /* address suffix: provided only when prefix len != 128 */
690 1.1 christos if (pbit < 128) {
691 1.1 christos if (rdata + pbyte >= edata) goto formerr;
692 1.1 christos memset(&a, 0, sizeof(a));
693 1.1 christos memcpy(&a.s6_addr[pbyte], rdata, sizeof(a) - pbyte);
694 1.11 christos (void) inet_ntop(AF_INET6, &a, buf, (socklen_t)buflen);
695 1.1 christos addlen(strlen(buf), &buf, &buflen);
696 1.1 christos rdata += sizeof(a) - pbyte;
697 1.1 christos }
698 1.1 christos
699 1.1 christos /* prefix name: provided only when prefix len > 0 */
700 1.1 christos if (pbit == 0)
701 1.1 christos break;
702 1.1 christos if (rdata >= edata) goto formerr;
703 1.2 christos T(addstr(" ", (size_t)1, &buf, &buflen));
704 1.1 christos T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
705 1.1 christos
706 1.1 christos break;
707 1.1 christos }
708 1.1 christos
709 1.1 christos case ns_t_opt: {
710 1.1 christos len = SPRINTF((tmp, "%u bytes", class));
711 1.2 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
712 1.1 christos break;
713 1.1 christos }
714 1.1 christos
715 1.9 christos case ns_t_ds:
716 1.9 christos case ns_t_dlv:
717 1.9 christos case ns_t_sshfp: {
718 1.9 christos u_int t;
719 1.9 christos
720 1.9 christos if (type == ns_t_ds || type == ns_t_dlv) {
721 1.9 christos if (rdlen < 4U) goto formerr;
722 1.9 christos t = ns_get16(rdata);
723 1.9 christos rdata += NS_INT16SZ;
724 1.9 christos len = SPRINTF((tmp, "%u ", t));
725 1.10 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
726 1.9 christos } else
727 1.9 christos if (rdlen < 2U) goto formerr;
728 1.9 christos
729 1.9 christos len = SPRINTF((tmp, "%u ", *rdata));
730 1.10 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
731 1.9 christos rdata++;
732 1.9 christos
733 1.9 christos len = SPRINTF((tmp, "%u ", *rdata));
734 1.10 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
735 1.9 christos rdata++;
736 1.9 christos
737 1.9 christos while (rdata < edata) {
738 1.9 christos len = SPRINTF((tmp, "%02X", *rdata));
739 1.10 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
740 1.9 christos rdata++;
741 1.9 christos }
742 1.9 christos break;
743 1.9 christos }
744 1.9 christos
745 1.9 christos case ns_t_nsec3:
746 1.9 christos case ns_t_nsec3param: {
747 1.9 christos u_int t, w, l, j, k, c;
748 1.9 christos
749 1.9 christos len = SPRINTF((tmp, "%u ", *rdata));
750 1.10 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
751 1.9 christos rdata++;
752 1.9 christos
753 1.9 christos len = SPRINTF((tmp, "%u ", *rdata));
754 1.10 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
755 1.9 christos rdata++;
756 1.9 christos
757 1.9 christos t = ns_get16(rdata);
758 1.9 christos rdata += NS_INT16SZ;
759 1.9 christos len = SPRINTF((tmp, "%u ", t));
760 1.10 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
761 1.9 christos
762 1.9 christos t = *rdata++;
763 1.9 christos if (t == 0) {
764 1.9 christos T(addstr("-", 1, &buf, &buflen));
765 1.9 christos } else {
766 1.9 christos while (t-- > 0) {
767 1.9 christos len = SPRINTF((tmp, "%02X", *rdata));
768 1.10 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
769 1.9 christos rdata++;
770 1.9 christos }
771 1.9 christos }
772 1.9 christos if (type == ns_t_nsec3param)
773 1.9 christos break;
774 1.9 christos T(addstr(" ", 1, &buf, &buflen));
775 1.9 christos
776 1.9 christos t = *rdata++;
777 1.9 christos while (t > 0) {
778 1.9 christos switch (t) {
779 1.9 christos case 1:
780 1.10 christos tmp[0] = base32hex[(((uint32_t)rdata[0]>>3)&0x1f)];
781 1.10 christos tmp[1] = base32hex[(((uint32_t)rdata[0]<<2)&0x1c)];
782 1.9 christos tmp[2] = tmp[3] = tmp[4] = '=';
783 1.9 christos tmp[5] = tmp[6] = tmp[7] = '=';
784 1.9 christos break;
785 1.9 christos case 2:
786 1.10 christos tmp[0] = base32hex[(((uint32_t)rdata[0]>>3)&0x1f)];
787 1.10 christos tmp[1] = base32hex[(((uint32_t)rdata[0]<<2)&0x1c)|
788 1.10 christos (((uint32_t)rdata[1]>>6)&0x03)];
789 1.10 christos tmp[2] = base32hex[(((uint32_t)rdata[1]>>1)&0x1f)];
790 1.10 christos tmp[3] = base32hex[(((uint32_t)rdata[1]<<4)&0x10)];
791 1.9 christos tmp[4] = tmp[5] = tmp[6] = tmp[7] = '=';
792 1.9 christos break;
793 1.9 christos case 3:
794 1.10 christos tmp[0] = base32hex[(((uint32_t)rdata[0]>>3)&0x1f)];
795 1.10 christos tmp[1] = base32hex[(((uint32_t)rdata[0]<<2)&0x1c)|
796 1.10 christos (((uint32_t)rdata[1]>>6)&0x03)];
797 1.10 christos tmp[2] = base32hex[(((uint32_t)rdata[1]>>1)&0x1f)];
798 1.10 christos tmp[3] = base32hex[(((uint32_t)rdata[1]<<4)&0x10)|
799 1.10 christos (((uint32_t)rdata[2]>>4)&0x0f)];
800 1.10 christos tmp[4] = base32hex[(((uint32_t)rdata[2]<<1)&0x1e)];
801 1.9 christos tmp[5] = tmp[6] = tmp[7] = '=';
802 1.9 christos break;
803 1.9 christos case 4:
804 1.10 christos tmp[0] = base32hex[(((uint32_t)rdata[0]>>3)&0x1f)];
805 1.10 christos tmp[1] = base32hex[(((uint32_t)rdata[0]<<2)&0x1c)|
806 1.10 christos (((uint32_t)rdata[1]>>6)&0x03)];
807 1.10 christos tmp[2] = base32hex[(((uint32_t)rdata[1]>>1)&0x1f)];
808 1.10 christos tmp[3] = base32hex[(((uint32_t)rdata[1]<<4)&0x10)|
809 1.10 christos (((uint32_t)rdata[2]>>4)&0x0f)];
810 1.10 christos tmp[4] = base32hex[(((uint32_t)rdata[2]<<1)&0x1e)|
811 1.10 christos (((uint32_t)rdata[3]>>7)&0x01)];
812 1.10 christos tmp[5] = base32hex[(((uint32_t)rdata[3]>>2)&0x1f)];
813 1.10 christos tmp[6] = base32hex[((uint32_t)rdata[3]<<3)&0x18];
814 1.9 christos tmp[7] = '=';
815 1.9 christos break;
816 1.9 christos default:
817 1.10 christos tmp[0] = base32hex[(((uint32_t)rdata[0]>>3)&0x1f)];
818 1.10 christos tmp[1] = base32hex[(((uint32_t)rdata[0]<<2)&0x1c)|
819 1.10 christos (((uint32_t)rdata[1]>>6)&0x03)];
820 1.10 christos tmp[2] = base32hex[(((uint32_t)rdata[1]>>1)&0x1f)];
821 1.10 christos tmp[3] = base32hex[(((uint32_t)rdata[1]<<4)&0x10)|
822 1.10 christos (((uint32_t)rdata[2]>>4)&0x0f)];
823 1.10 christos tmp[4] = base32hex[(((uint32_t)rdata[2]<<1)&0x1e)|
824 1.10 christos (((uint32_t)rdata[3]>>7)&0x01)];
825 1.10 christos tmp[5] = base32hex[(((uint32_t)rdata[3]>>2)&0x1f)];
826 1.10 christos tmp[6] = base32hex[(((uint32_t)rdata[3]<<3)&0x18)|
827 1.10 christos (((uint32_t)rdata[4]>>5)&0x07)];
828 1.9 christos tmp[7] = base32hex[(rdata[4]&0x1f)];
829 1.9 christos break;
830 1.9 christos }
831 1.9 christos T(addstr(tmp, 8, &buf, &buflen));
832 1.9 christos if (t >= 5) {
833 1.9 christos rdata += 5;
834 1.9 christos t -= 5;
835 1.9 christos } else {
836 1.9 christos rdata += t;
837 1.9 christos t -= t;
838 1.9 christos }
839 1.9 christos }
840 1.9 christos
841 1.9 christos while (rdata < edata) {
842 1.9 christos w = *rdata++;
843 1.9 christos l = *rdata++;
844 1.9 christos for (j = 0; j < l; j++) {
845 1.9 christos if (rdata[j] == 0)
846 1.9 christos continue;
847 1.9 christos for (k = 0; k < 8; k++) {
848 1.9 christos if ((rdata[j] & (0x80 >> k)) == 0)
849 1.9 christos continue;
850 1.9 christos c = w * 256 + j * 8 + k;
851 1.10 christos len = SPRINTF((tmp, " %s", p_type((ns_type)c)));
852 1.10 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
853 1.9 christos }
854 1.9 christos }
855 1.9 christos rdata += l;
856 1.9 christos }
857 1.9 christos break;
858 1.9 christos }
859 1.9 christos
860 1.9 christos case ns_t_nsec: {
861 1.9 christos u_int w, l, j, k, c;
862 1.9 christos
863 1.9 christos T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
864 1.9 christos
865 1.9 christos while (rdata < edata) {
866 1.9 christos w = *rdata++;
867 1.9 christos l = *rdata++;
868 1.9 christos for (j = 0; j < l; j++) {
869 1.9 christos if (rdata[j] == 0)
870 1.9 christos continue;
871 1.9 christos for (k = 0; k < 8; k++) {
872 1.9 christos if ((rdata[j] & (0x80 >> k)) == 0)
873 1.9 christos continue;
874 1.9 christos c = w * 256 + j * 8 + k;
875 1.10 christos len = SPRINTF((tmp, " %s", p_type((ns_type)c)));
876 1.10 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
877 1.9 christos }
878 1.9 christos }
879 1.9 christos rdata += l;
880 1.9 christos }
881 1.9 christos break;
882 1.9 christos }
883 1.9 christos
884 1.9 christos case ns_t_dhcid: {
885 1.9 christos int n;
886 1.9 christos unsigned int siz;
887 1.9 christos char base64_dhcid[8192];
888 1.9 christos const char *leader;
889 1.9 christos
890 1.11 christos siz = (int)(edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */
891 1.9 christos if (siz > sizeof(base64_dhcid) * 3/4) {
892 1.9 christos const char *str = "record too long to print";
893 1.9 christos T(addstr(str, strlen(str), &buf, &buflen));
894 1.9 christos } else {
895 1.10 christos len = b64_ntop(rdata, (size_t)(edata-rdata),
896 1.10 christos base64_dhcid, siz);
897 1.9 christos
898 1.9 christos if (len < 0)
899 1.9 christos goto formerr;
900 1.9 christos
901 1.9 christos else if (len > 15) {
902 1.9 christos T(addstr(" (", 2, &buf, &buflen));
903 1.9 christos leader = "\n\t\t";
904 1.9 christos spaced = 0;
905 1.9 christos }
906 1.9 christos else
907 1.9 christos leader = " ";
908 1.9 christos
909 1.9 christos for (n = 0; n < len; n += 48) {
910 1.9 christos T(addstr(leader, strlen(leader),
911 1.9 christos &buf, &buflen));
912 1.10 christos T(addstr(base64_dhcid + n,
913 1.10 christos (size_t)MIN(len - n, 48), &buf, &buflen));
914 1.9 christos }
915 1.9 christos if (len > 15)
916 1.9 christos T(addstr(" )", 2, &buf, &buflen));
917 1.9 christos }
918 1.10 christos break;
919 1.9 christos }
920 1.9 christos
921 1.9 christos case ns_t_ipseckey: {
922 1.9 christos int n;
923 1.9 christos unsigned int siz;
924 1.9 christos char base64_key[8192];
925 1.9 christos const char *leader;
926 1.9 christos
927 1.9 christos if (rdlen < 2)
928 1.9 christos goto formerr;
929 1.9 christos
930 1.9 christos switch (rdata[1]) {
931 1.9 christos case 0:
932 1.9 christos case 3:
933 1.9 christos if (rdlen < 3)
934 1.9 christos goto formerr;
935 1.9 christos break;
936 1.9 christos case 1:
937 1.9 christos if (rdlen < 7)
938 1.9 christos goto formerr;
939 1.9 christos break;
940 1.9 christos case 2:
941 1.9 christos if (rdlen < 19)
942 1.9 christos goto formerr;
943 1.9 christos break;
944 1.9 christos default:
945 1.9 christos comment = "unknown IPSECKEY gateway type";
946 1.9 christos goto hexify;
947 1.9 christos }
948 1.9 christos
949 1.9 christos len = SPRINTF((tmp, "%u ", *rdata));
950 1.10 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
951 1.9 christos rdata++;
952 1.9 christos
953 1.9 christos len = SPRINTF((tmp, "%u ", *rdata));
954 1.10 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
955 1.9 christos rdata++;
956 1.9 christos
957 1.9 christos len = SPRINTF((tmp, "%u ", *rdata));
958 1.10 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
959 1.9 christos rdata++;
960 1.9 christos
961 1.9 christos switch (rdata[-2]) {
962 1.9 christos case 0:
963 1.9 christos T(addstr(".", 1, &buf, &buflen));
964 1.9 christos break;
965 1.9 christos case 1:
966 1.11 christos (void) inet_ntop(AF_INET, rdata, buf, (socklen_t)buflen);
967 1.9 christos addlen(strlen(buf), &buf, &buflen);
968 1.9 christos rdata += 4;
969 1.9 christos break;
970 1.9 christos case 2:
971 1.11 christos (void) inet_ntop(AF_INET6, rdata, buf, (socklen_t)buflen);
972 1.9 christos addlen(strlen(buf), &buf, &buflen);
973 1.9 christos rdata += 16;
974 1.9 christos break;
975 1.9 christos case 3:
976 1.9 christos T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
977 1.9 christos break;
978 1.9 christos }
979 1.9 christos
980 1.9 christos if (rdata >= edata)
981 1.9 christos break;
982 1.9 christos
983 1.11 christos siz = (int)(edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */
984 1.9 christos if (siz > sizeof(base64_key) * 3/4) {
985 1.9 christos const char *str = "record too long to print";
986 1.9 christos T(addstr(str, strlen(str), &buf, &buflen));
987 1.9 christos } else {
988 1.10 christos len = b64_ntop(rdata, (size_t)(edata-rdata),
989 1.10 christos base64_key, siz);
990 1.9 christos
991 1.9 christos if (len < 0)
992 1.9 christos goto formerr;
993 1.9 christos
994 1.9 christos else if (len > 15) {
995 1.9 christos T(addstr(" (", 2, &buf, &buflen));
996 1.9 christos leader = "\n\t\t";
997 1.9 christos spaced = 0;
998 1.9 christos }
999 1.9 christos else
1000 1.9 christos leader = " ";
1001 1.9 christos
1002 1.9 christos for (n = 0; n < len; n += 48) {
1003 1.9 christos T(addstr(leader, strlen(leader),
1004 1.9 christos &buf, &buflen));
1005 1.10 christos T(addstr(base64_key + n,
1006 1.10 christos (size_t)MIN(len - n, 48), &buf, &buflen));
1007 1.9 christos }
1008 1.9 christos if (len > 15)
1009 1.9 christos T(addstr(" )", 2, &buf, &buflen));
1010 1.9 christos }
1011 1.10 christos break;
1012 1.9 christos }
1013 1.9 christos
1014 1.9 christos case ns_t_hip: {
1015 1.9 christos unsigned int i, hip_len, algorithm, key_len;
1016 1.9 christos char base64_key[NS_MD5RSA_MAX_BASE64];
1017 1.9 christos unsigned int siz;
1018 1.9 christos const char *leader = "\n\t\t\t\t\t";
1019 1.9 christos
1020 1.9 christos hip_len = *rdata++;
1021 1.9 christos algorithm = *rdata++;
1022 1.9 christos key_len = ns_get16(rdata);
1023 1.9 christos rdata += NS_INT16SZ;
1024 1.9 christos
1025 1.9 christos siz = key_len*4/3 + 4; /* "+4" accounts for trailing \0 */
1026 1.9 christos if (siz > sizeof(base64_key) * 3/4) {
1027 1.9 christos const char *str = "record too long to print";
1028 1.9 christos T(addstr(str, strlen(str), &buf, &buflen));
1029 1.9 christos } else {
1030 1.9 christos len = sprintf(tmp, "( %u ", algorithm);
1031 1.10 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
1032 1.9 christos
1033 1.9 christos for (i = 0; i < hip_len; i++) {
1034 1.9 christos len = sprintf(tmp, "%02X", *rdata);
1035 1.10 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
1036 1.9 christos rdata++;
1037 1.9 christos }
1038 1.9 christos T(addstr(leader, strlen(leader), &buf, &buflen));
1039 1.9 christos
1040 1.9 christos len = b64_ntop(rdata, key_len, base64_key, siz);
1041 1.9 christos if (len < 0)
1042 1.9 christos goto formerr;
1043 1.9 christos
1044 1.10 christos T(addstr(base64_key, (size_t)len, &buf, &buflen));
1045 1.9 christos
1046 1.9 christos rdata += key_len;
1047 1.9 christos while (rdata < edata) {
1048 1.9 christos T(addstr(leader, strlen(leader), &buf, &buflen));
1049 1.9 christos T(addname(msg, msglen, &rdata, origin,
1050 1.9 christos &buf, &buflen));
1051 1.9 christos }
1052 1.9 christos T(addstr(" )", 2, &buf, &buflen));
1053 1.9 christos }
1054 1.9 christos break;
1055 1.9 christos }
1056 1.9 christos
1057 1.1 christos default:
1058 1.1 christos comment = "unknown RR type";
1059 1.1 christos goto hexify;
1060 1.1 christos }
1061 1.11 christos _DIAGASSERT(__type_fit(int, buf - obuf));
1062 1.11 christos return (int)(buf - obuf);
1063 1.1 christos formerr:
1064 1.1 christos comment = "RR format error";
1065 1.1 christos hexify: {
1066 1.1 christos int n, m;
1067 1.1 christos char *p;
1068 1.1 christos
1069 1.6 christos len = SPRINTF((tmp, "\\# %u%s\t; %s", (unsigned)(edata - rdata),
1070 1.6 christos rdlen != 0U ? " (" : "", comment));
1071 1.2 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
1072 1.1 christos while (rdata < edata) {
1073 1.1 christos p = tmp;
1074 1.1 christos p += SPRINTF((p, "\n\t"));
1075 1.1 christos spaced = 0;
1076 1.11 christos n = MIN(16, (int)(edata - rdata));
1077 1.1 christos for (m = 0; m < n; m++)
1078 1.1 christos p += SPRINTF((p, "%02x ", rdata[m]));
1079 1.2 christos T(addstr(tmp, (size_t)(p - tmp), &buf, &buflen));
1080 1.1 christos if (n < 16) {
1081 1.2 christos T(addstr(")", (size_t)1, &buf, &buflen));
1082 1.2 christos T(addtab((size_t)(p - tmp + 1), (size_t)48, spaced, &buf, &buflen));
1083 1.1 christos }
1084 1.1 christos p = tmp;
1085 1.1 christos p += SPRINTF((p, "; "));
1086 1.1 christos for (m = 0; m < n; m++)
1087 1.1 christos *p++ = (isascii(rdata[m]) && isprint(rdata[m]))
1088 1.1 christos ? rdata[m]
1089 1.1 christos : '.';
1090 1.2 christos T(addstr(tmp, (size_t)(p - tmp), &buf, &buflen));
1091 1.1 christos rdata += n;
1092 1.1 christos }
1093 1.11 christos _DIAGASSERT(__type_fit(int, buf - obuf));
1094 1.11 christos return (int)(buf - obuf);
1095 1.1 christos }
1096 1.1 christos }
1097 1.1 christos
1098 1.1 christos /* Private. */
1099 1.1 christos
1100 1.6 christos /*%
1101 1.1 christos * size_t
1102 1.1 christos * prune_origin(name, origin)
1103 1.1 christos * Find out if the name is at or under the current origin.
1104 1.1 christos * return:
1105 1.1 christos * Number of characters in name before start of origin,
1106 1.1 christos * or length of name if origin does not match.
1107 1.1 christos * notes:
1108 1.1 christos * This function should share code with samedomain().
1109 1.1 christos */
1110 1.1 christos static size_t
1111 1.1 christos prune_origin(const char *name, const char *origin) {
1112 1.1 christos const char *oname = name;
1113 1.1 christos
1114 1.1 christos while (*name != '\0') {
1115 1.1 christos if (origin != NULL && ns_samename(name, origin) == 1)
1116 1.1 christos return (name - oname - (name > oname));
1117 1.1 christos while (*name != '\0') {
1118 1.1 christos if (*name == '\\') {
1119 1.1 christos name++;
1120 1.1 christos /* XXX need to handle \nnn form. */
1121 1.1 christos if (*name == '\0')
1122 1.1 christos break;
1123 1.1 christos } else if (*name == '.') {
1124 1.1 christos name++;
1125 1.1 christos break;
1126 1.1 christos }
1127 1.1 christos name++;
1128 1.1 christos }
1129 1.1 christos }
1130 1.1 christos return (name - oname);
1131 1.1 christos }
1132 1.1 christos
1133 1.6 christos /*%
1134 1.1 christos * int
1135 1.1 christos * charstr(rdata, edata, buf, buflen)
1136 1.1 christos * Format a <character-string> into the presentation buffer.
1137 1.1 christos * return:
1138 1.1 christos * Number of rdata octets consumed
1139 1.1 christos * 0 for protocol format error
1140 1.1 christos * -1 for output buffer error
1141 1.1 christos * side effects:
1142 1.1 christos * buffer is advanced on success.
1143 1.1 christos */
1144 1.1 christos static int
1145 1.1 christos charstr(const u_char *rdata, const u_char *edata, char **buf, size_t *buflen) {
1146 1.1 christos const u_char *odata = rdata;
1147 1.1 christos size_t save_buflen = *buflen;
1148 1.1 christos char *save_buf = *buf;
1149 1.1 christos
1150 1.2 christos if (addstr("\"", (size_t)1, buf, buflen) < 0)
1151 1.1 christos goto enospc;
1152 1.1 christos if (rdata < edata) {
1153 1.1 christos int n = *rdata;
1154 1.1 christos
1155 1.1 christos if (rdata + 1 + n <= edata) {
1156 1.1 christos rdata++;
1157 1.1 christos while (n-- > 0) {
1158 1.1 christos if (strchr("\n\"\\", *rdata) != NULL)
1159 1.2 christos if (addstr("\\", (size_t)1, buf, buflen) < 0)
1160 1.1 christos goto enospc;
1161 1.2 christos if (addstr((const char *)rdata, (size_t)1,
1162 1.1 christos buf, buflen) < 0)
1163 1.1 christos goto enospc;
1164 1.1 christos rdata++;
1165 1.1 christos }
1166 1.1 christos }
1167 1.1 christos }
1168 1.2 christos if (addstr("\"", (size_t)1, buf, buflen) < 0)
1169 1.1 christos goto enospc;
1170 1.11 christos _DIAGASSERT(__type_fit(int, rdata - odata));
1171 1.11 christos return (int)(rdata - odata);
1172 1.1 christos enospc:
1173 1.1 christos errno = ENOSPC;
1174 1.1 christos *buf = save_buf;
1175 1.1 christos *buflen = save_buflen;
1176 1.1 christos return (-1);
1177 1.1 christos }
1178 1.1 christos
1179 1.1 christos static int
1180 1.1 christos addname(const u_char *msg, size_t msglen,
1181 1.1 christos const u_char **pp, const char *origin,
1182 1.1 christos char **buf, size_t *buflen)
1183 1.1 christos {
1184 1.1 christos size_t newlen, save_buflen = *buflen;
1185 1.1 christos char *save_buf = *buf;
1186 1.1 christos int n;
1187 1.1 christos
1188 1.2 christos n = dn_expand(msg, msg + msglen, *pp, *buf, (int)*buflen);
1189 1.1 christos if (n < 0)
1190 1.6 christos goto enospc; /*%< Guess. */
1191 1.1 christos newlen = prune_origin(*buf, origin);
1192 1.1 christos if (**buf == '\0') {
1193 1.1 christos goto root;
1194 1.1 christos } else if (newlen == 0U) {
1195 1.1 christos /* Use "@" instead of name. */
1196 1.1 christos if (newlen + 2 > *buflen)
1197 1.1 christos goto enospc; /* No room for "@\0". */
1198 1.1 christos (*buf)[newlen++] = '@';
1199 1.1 christos (*buf)[newlen] = '\0';
1200 1.1 christos } else {
1201 1.1 christos if (((origin == NULL || origin[0] == '\0') ||
1202 1.1 christos (origin[0] != '.' && origin[1] != '\0' &&
1203 1.1 christos (*buf)[newlen] == '\0')) && (*buf)[newlen - 1] != '.') {
1204 1.1 christos /* No trailing dot. */
1205 1.1 christos root:
1206 1.1 christos if (newlen + 2 > *buflen)
1207 1.1 christos goto enospc; /* No room for ".\0". */
1208 1.1 christos (*buf)[newlen++] = '.';
1209 1.1 christos (*buf)[newlen] = '\0';
1210 1.1 christos }
1211 1.1 christos }
1212 1.1 christos *pp += n;
1213 1.1 christos addlen(newlen, buf, buflen);
1214 1.1 christos **buf = '\0';
1215 1.11 christos _DIAGASSERT(__type_fit(int, newlen));
1216 1.11 christos return (int)newlen;
1217 1.1 christos enospc:
1218 1.1 christos errno = ENOSPC;
1219 1.1 christos *buf = save_buf;
1220 1.1 christos *buflen = save_buflen;
1221 1.1 christos return (-1);
1222 1.1 christos }
1223 1.1 christos
1224 1.1 christos static void
1225 1.1 christos addlen(size_t len, char **buf, size_t *buflen) {
1226 1.1 christos INSIST(len <= *buflen);
1227 1.1 christos *buf += len;
1228 1.1 christos *buflen -= len;
1229 1.1 christos }
1230 1.1 christos
1231 1.1 christos static int
1232 1.1 christos addstr(const char *src, size_t len, char **buf, size_t *buflen) {
1233 1.1 christos if (len >= *buflen) {
1234 1.1 christos errno = ENOSPC;
1235 1.1 christos return (-1);
1236 1.1 christos }
1237 1.1 christos memcpy(*buf, src, len);
1238 1.1 christos addlen(len, buf, buflen);
1239 1.1 christos **buf = '\0';
1240 1.1 christos return (0);
1241 1.1 christos }
1242 1.1 christos
1243 1.1 christos static int
1244 1.1 christos addtab(size_t len, size_t target, int spaced, char **buf, size_t *buflen) {
1245 1.1 christos size_t save_buflen = *buflen;
1246 1.1 christos char *save_buf = *buf;
1247 1.11 christos ptrdiff_t t;
1248 1.1 christos
1249 1.1 christos if (spaced || len >= target - 1) {
1250 1.2 christos T(addstr(" ", (size_t)2, buf, buflen));
1251 1.1 christos spaced = 1;
1252 1.1 christos } else {
1253 1.1 christos for (t = (target - len - 1) / 8; t >= 0; t--)
1254 1.2 christos if (addstr("\t", (size_t)1, buf, buflen) < 0) {
1255 1.1 christos *buflen = save_buflen;
1256 1.1 christos *buf = save_buf;
1257 1.1 christos return (-1);
1258 1.1 christos }
1259 1.1 christos spaced = 0;
1260 1.1 christos }
1261 1.1 christos return (spaced);
1262 1.1 christos }
1263 1.6 christos
1264 1.6 christos /*! \file */
1265