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