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