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