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