Annotation of src/lib/libc/nameser/ns_print.c, Revision 1.8
1.8 ! christos 1: /* $NetBSD: ns_print.c,v 1.7 2007/03/30 20:23:03 ghen Exp $ */
1.1 christos 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:
1.2 christos 20: #include <sys/cdefs.h>
1.1 christos 21: #ifndef lint
1.2 christos 22: #ifdef notdef
1.8 ! christos 23: static const char rcsid[] = "Id: ns_print.c,v 1.10 2005/04/27 04:56:40 sra Exp";
1.2 christos 24: #else
1.8 ! christos 25: __RCSID("$NetBSD: ns_print.c,v 1.7 2007/03/30 20:23:03 ghen Exp $");
1.2 christos 26: #endif
1.1 christos 27: #endif
28:
29: /* Import. */
30:
31: #include "port_before.h"
32:
33: #include <sys/types.h>
34: #include <sys/socket.h>
35:
36: #include <netinet/in.h>
37: #include <arpa/nameser.h>
38: #include <arpa/inet.h>
39:
40: #include <isc/assertions.h>
41: #include <isc/dst.h>
42: #include <errno.h>
43: #include <resolv.h>
44: #include <string.h>
45: #include <ctype.h>
46:
47: #include "port_after.h"
48:
49: #ifdef SPRINTF_CHAR
50: # define SPRINTF(x) strlen(sprintf/**/x)
51: #else
52: # define SPRINTF(x) ((size_t)sprintf x)
53: #endif
54:
55: /* Forward. */
56:
57: static size_t prune_origin(const char *name, const char *origin);
58: static int charstr(const u_char *rdata, const u_char *edata,
59: char **buf, size_t *buflen);
60: static int addname(const u_char *msg, size_t msglen,
61: const u_char **p, const char *origin,
62: char **buf, size_t *buflen);
63: static void addlen(size_t len, char **buf, size_t *buflen);
64: static int addstr(const char *src, size_t len,
65: char **buf, size_t *buflen);
66: static int addtab(size_t len, size_t target, int spaced,
67: char **buf, size_t *buflen);
68:
69: /* Macros. */
70:
71: #define T(x) \
72: do { \
73: if ((x) < 0) \
74: return (-1); \
1.2 christos 75: } while (/*CONSTCOND*/0)
1.1 christos 76:
77: /* Public. */
78:
1.6 christos 79: /*%
1.1 christos 80: * Convert an RR to presentation format.
1.6 christos 81: *
1.1 christos 82: * return:
1.6 christos 83: *\li Number of characters written to buf, or -1 (check errno).
1.1 christos 84: */
85: int
86: ns_sprintrr(const ns_msg *handle, const ns_rr *rr,
87: const char *name_ctx, const char *origin,
88: char *buf, size_t buflen)
89: {
90: int n;
91:
92: n = ns_sprintrrf(ns_msg_base(*handle), ns_msg_size(*handle),
93: ns_rr_name(*rr), ns_rr_class(*rr), ns_rr_type(*rr),
94: ns_rr_ttl(*rr), ns_rr_rdata(*rr), ns_rr_rdlen(*rr),
95: name_ctx, origin, buf, buflen);
96: return (n);
97: }
98:
1.6 christos 99: /*%
1.1 christos 100: * Convert the fields of an RR into presentation format.
1.6 christos 101: *
1.1 christos 102: * return:
1.6 christos 103: *\li Number of characters written to buf, or -1 (check errno).
1.1 christos 104: */
105: int
106: ns_sprintrrf(const u_char *msg, size_t msglen,
107: const char *name, ns_class class, ns_type type,
108: u_long ttl, const u_char *rdata, size_t rdlen,
109: const char *name_ctx, const char *origin,
110: char *buf, size_t buflen)
111: {
112: const char *obuf = buf;
113: const u_char *edata = rdata + rdlen;
114: int spaced = 0;
115:
116: const char *comment;
117: char tmp[100];
118: int len, x;
119:
120: /*
121: * Owner.
122: */
123: if (name_ctx != NULL && ns_samename(name_ctx, name) == 1) {
1.2 christos 124: T(addstr("\t\t\t", (size_t)3, &buf, &buflen));
1.1 christos 125: } else {
126: len = prune_origin(name, origin);
127: if (*name == '\0') {
128: goto root;
129: } else if (len == 0) {
1.2 christos 130: T(addstr("@\t\t\t", (size_t)4, &buf, &buflen));
1.1 christos 131: } else {
1.2 christos 132: T(addstr(name, (size_t)len, &buf, &buflen));
1.1 christos 133: /* Origin not used or not root, and no trailing dot? */
134: if (((origin == NULL || origin[0] == '\0') ||
135: (origin[0] != '.' && origin[1] != '\0' &&
136: name[len] == '\0')) && name[len - 1] != '.') {
137: root:
1.2 christos 138: T(addstr(".", (size_t)1, &buf, &buflen));
1.1 christos 139: len++;
140: }
1.2 christos 141: T(spaced = addtab((size_t)len, 24, spaced, &buf, &buflen));
1.1 christos 142: }
143: }
144:
145: /*
146: * TTL, Class, Type.
147: */
148: T(x = ns_format_ttl(ttl, buf, buflen));
1.2 christos 149: addlen((size_t)x, &buf, &buflen);
1.1 christos 150: len = SPRINTF((tmp, " %s %s", p_class(class), p_type(type)));
1.2 christos 151: T(addstr(tmp, (size_t)len, &buf, &buflen));
152: T(spaced = addtab((size_t)(x + len), (size_t)16, spaced, &buf, &buflen));
1.1 christos 153:
154: /*
155: * RData.
156: */
157: switch (type) {
158: case ns_t_a:
159: if (rdlen != (size_t)NS_INADDRSZ)
160: goto formerr;
161: (void) inet_ntop(AF_INET, rdata, buf, buflen);
162: addlen(strlen(buf), &buf, &buflen);
163: break;
164:
165: case ns_t_cname:
166: case ns_t_mb:
167: case ns_t_mg:
168: case ns_t_mr:
169: case ns_t_ns:
170: case ns_t_ptr:
171: case ns_t_dname:
172: T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
173: break;
174:
175: case ns_t_hinfo:
176: case ns_t_isdn:
177: /* First word. */
178: T(len = charstr(rdata, edata, &buf, &buflen));
179: if (len == 0)
180: goto formerr;
181: rdata += len;
1.2 christos 182: T(addstr(" ", (size_t)1, &buf, &buflen));
1.1 christos 183:
184:
185: /* Second word, optional in ISDN records. */
186: if (type == ns_t_isdn && rdata == edata)
187: break;
188:
189: T(len = charstr(rdata, edata, &buf, &buflen));
190: if (len == 0)
191: goto formerr;
192: rdata += len;
193: break;
194:
195: case ns_t_soa: {
196: u_long t;
197:
198: /* Server name. */
199: T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
1.2 christos 200: T(addstr(" ", (size_t)1, &buf, &buflen));
1.1 christos 201:
202: /* Administrator name. */
203: T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
1.2 christos 204: T(addstr(" (\n", (size_t)3, &buf, &buflen));
1.1 christos 205: spaced = 0;
206:
207: if ((edata - rdata) != 5*NS_INT32SZ)
208: goto formerr;
209:
210: /* Serial number. */
211: t = ns_get32(rdata); rdata += NS_INT32SZ;
1.2 christos 212: T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen));
1.1 christos 213: len = SPRINTF((tmp, "%lu", t));
1.2 christos 214: T(addstr(tmp, (size_t)len, &buf, &buflen));
215: T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen));
216: T(addstr("; serial\n", (size_t)9, &buf, &buflen));
1.1 christos 217: spaced = 0;
218:
219: /* Refresh interval. */
220: t = ns_get32(rdata); rdata += NS_INT32SZ;
1.2 christos 221: T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen));
1.1 christos 222: T(len = ns_format_ttl(t, buf, buflen));
1.2 christos 223: addlen((size_t)len, &buf, &buflen);
224: T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen));
225: T(addstr("; refresh\n", (size_t)10, &buf, &buflen));
1.1 christos 226: spaced = 0;
227:
228: /* Retry interval. */
229: t = ns_get32(rdata); rdata += NS_INT32SZ;
1.2 christos 230: T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen));
1.1 christos 231: T(len = ns_format_ttl(t, buf, buflen));
1.2 christos 232: addlen((size_t)len, &buf, &buflen);
233: T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen));
234: T(addstr("; retry\n", (size_t)8, &buf, &buflen));
1.1 christos 235: spaced = 0;
236:
237: /* Expiry. */
238: t = ns_get32(rdata); rdata += NS_INT32SZ;
1.2 christos 239: T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen));
1.1 christos 240: T(len = ns_format_ttl(t, buf, buflen));
1.2 christos 241: addlen((size_t)len, &buf, &buflen);
242: T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen));
243: T(addstr("; expiry\n", (size_t)9, &buf, &buflen));
1.1 christos 244: spaced = 0;
245:
246: /* Minimum TTL. */
247: t = ns_get32(rdata); rdata += NS_INT32SZ;
1.2 christos 248: T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen));
1.1 christos 249: T(len = ns_format_ttl(t, buf, buflen));
1.2 christos 250: addlen((size_t)len, &buf, &buflen);
251: T(addstr(" )", (size_t)2, &buf, &buflen));
252: T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen));
253: T(addstr("; minimum\n", (size_t)10, &buf, &buflen));
1.1 christos 254:
255: break;
256: }
257:
258: case ns_t_mx:
259: case ns_t_afsdb:
260: case ns_t_rt: {
261: u_int t;
262:
263: if (rdlen < (size_t)NS_INT16SZ)
264: goto formerr;
265:
266: /* Priority. */
267: t = ns_get16(rdata);
268: rdata += NS_INT16SZ;
269: len = SPRINTF((tmp, "%u ", t));
1.2 christos 270: T(addstr(tmp, (size_t)len, &buf, &buflen));
1.1 christos 271:
272: /* Target. */
273: T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
274:
275: break;
276: }
277:
278: case ns_t_px: {
279: u_int t;
280:
281: if (rdlen < (size_t)NS_INT16SZ)
282: goto formerr;
283:
284: /* Priority. */
285: t = ns_get16(rdata);
286: rdata += NS_INT16SZ;
287: len = SPRINTF((tmp, "%u ", t));
1.2 christos 288: T(addstr(tmp, (size_t)len, &buf, &buflen));
1.1 christos 289:
290: /* Name1. */
291: T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
1.2 christos 292: T(addstr(" ", (size_t)1, &buf, &buflen));
1.1 christos 293:
294: /* Name2. */
295: T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
296:
297: break;
298: }
299:
300: case ns_t_x25:
301: T(len = charstr(rdata, edata, &buf, &buflen));
302: if (len == 0)
303: goto formerr;
304: rdata += len;
305: break;
306:
307: case ns_t_txt:
308: while (rdata < edata) {
309: T(len = charstr(rdata, edata, &buf, &buflen));
310: if (len == 0)
311: goto formerr;
312: rdata += len;
313: if (rdata < edata)
1.2 christos 314: T(addstr(" ", (size_t)1, &buf, &buflen));
1.1 christos 315: }
316: break;
317:
318: case ns_t_nsap: {
319: char t[2+255*3];
320:
1.2 christos 321: (void) inet_nsap_ntoa((int)rdlen, rdata, t);
1.1 christos 322: T(addstr(t, strlen(t), &buf, &buflen));
323: break;
324: }
325:
326: case ns_t_aaaa:
327: if (rdlen != (size_t)NS_IN6ADDRSZ)
328: goto formerr;
329: (void) inet_ntop(AF_INET6, rdata, buf, buflen);
330: addlen(strlen(buf), &buf, &buflen);
331: break;
332:
333: case ns_t_loc: {
334: char t[255];
335:
336: /* XXX protocol format checking? */
337: (void) loc_ntoa(rdata, t);
338: T(addstr(t, strlen(t), &buf, &buflen));
339: break;
340: }
341:
342: case ns_t_naptr: {
343: u_int order, preference;
344: char t[50];
345:
346: if (rdlen < 2U*NS_INT16SZ)
347: goto formerr;
348:
349: /* Order, Precedence. */
350: order = ns_get16(rdata); rdata += NS_INT16SZ;
351: preference = ns_get16(rdata); rdata += NS_INT16SZ;
352: len = SPRINTF((t, "%u %u ", order, preference));
1.2 christos 353: T(addstr(t, (size_t)len, &buf, &buflen));
1.1 christos 354:
355: /* Flags. */
356: T(len = charstr(rdata, edata, &buf, &buflen));
357: if (len == 0)
358: goto formerr;
359: rdata += len;
1.2 christos 360: T(addstr(" ", (size_t)1, &buf, &buflen));
1.1 christos 361:
362: /* Service. */
363: T(len = charstr(rdata, edata, &buf, &buflen));
364: if (len == 0)
365: goto formerr;
366: rdata += len;
1.2 christos 367: T(addstr(" ", (size_t)1, &buf, &buflen));
1.1 christos 368:
369: /* Regexp. */
370: T(len = charstr(rdata, edata, &buf, &buflen));
371: if (len < 0)
372: return (-1);
373: if (len == 0)
374: goto formerr;
375: rdata += len;
1.2 christos 376: T(addstr(" ", (size_t)1, &buf, &buflen));
1.1 christos 377:
378: /* Server. */
379: T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
380: break;
381: }
382:
383: case ns_t_srv: {
384: u_int priority, weight, port;
385: char t[50];
386:
387: if (rdlen < 3U*NS_INT16SZ)
388: goto formerr;
389:
390: /* Priority, Weight, Port. */
391: priority = ns_get16(rdata); rdata += NS_INT16SZ;
392: weight = ns_get16(rdata); rdata += NS_INT16SZ;
393: port = ns_get16(rdata); rdata += NS_INT16SZ;
394: len = SPRINTF((t, "%u %u %u ", priority, weight, port));
1.2 christos 395: T(addstr(t, (size_t)len, &buf, &buflen));
1.1 christos 396:
397: /* Server. */
398: T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
399: break;
400: }
401:
402: case ns_t_minfo:
403: case ns_t_rp:
404: /* Name1. */
405: T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
1.2 christos 406: T(addstr(" ", (size_t)1, &buf, &buflen));
1.1 christos 407:
408: /* Name2. */
409: T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
410:
411: break;
412:
413: case ns_t_wks: {
414: int n, lcnt;
415:
416: if (rdlen < 1U + NS_INT32SZ)
417: goto formerr;
418:
419: /* Address. */
420: (void) inet_ntop(AF_INET, rdata, buf, buflen);
421: addlen(strlen(buf), &buf, &buflen);
422: rdata += NS_INADDRSZ;
423:
424: /* Protocol. */
425: len = SPRINTF((tmp, " %u ( ", *rdata));
1.2 christos 426: T(addstr(tmp, (size_t)len, &buf, &buflen));
1.1 christos 427: rdata += NS_INT8SZ;
428:
429: /* Bit map. */
430: n = 0;
431: lcnt = 0;
432: while (rdata < edata) {
433: u_int c = *rdata++;
434: do {
435: if (c & 0200) {
436: if (lcnt == 0) {
1.2 christos 437: T(addstr("\n\t\t\t\t", (size_t)5,
1.1 christos 438: &buf, &buflen));
439: lcnt = 10;
440: spaced = 0;
441: }
442: len = SPRINTF((tmp, "%d ", n));
1.2 christos 443: T(addstr(tmp, (size_t)len, &buf, &buflen));
1.1 christos 444: lcnt--;
445: }
446: c <<= 1;
447: } while (++n & 07);
448: }
1.2 christos 449: T(addstr(")", (size_t)1, &buf, &buflen));
1.1 christos 450:
451: break;
452: }
453:
454: case ns_t_key: {
455: char base64_key[NS_MD5RSA_MAX_BASE64];
456: u_int keyflags, protocol, algorithm, key_id;
457: const char *leader;
458: int n;
459:
460: if (rdlen < 0U + NS_INT16SZ + NS_INT8SZ + NS_INT8SZ)
461: goto formerr;
462:
463: /* Key flags, Protocol, Algorithm. */
1.3 christos 464: #ifndef _LIBC
1.1 christos 465: key_id = dst_s_dns_key_id(rdata, edata-rdata);
1.3 christos 466: #else
467: key_id = 0;
468: #endif
1.1 christos 469: keyflags = ns_get16(rdata); rdata += NS_INT16SZ;
470: protocol = *rdata++;
471: algorithm = *rdata++;
472: len = SPRINTF((tmp, "0x%04x %u %u",
473: keyflags, protocol, algorithm));
1.2 christos 474: T(addstr(tmp, (size_t)len, &buf, &buflen));
1.1 christos 475:
476: /* Public key data. */
1.2 christos 477: len = b64_ntop(rdata, (size_t)(edata - rdata),
1.1 christos 478: base64_key, sizeof base64_key);
479: if (len < 0)
480: goto formerr;
481: if (len > 15) {
1.2 christos 482: T(addstr(" (", (size_t)2, &buf, &buflen));
1.1 christos 483: leader = "\n\t\t";
484: spaced = 0;
485: } else
486: leader = " ";
487: for (n = 0; n < len; n += 48) {
488: T(addstr(leader, strlen(leader), &buf, &buflen));
1.2 christos 489: T(addstr(base64_key + n, (size_t)MIN(len - n, 48),
1.1 christos 490: &buf, &buflen));
491: }
492: if (len > 15)
1.2 christos 493: T(addstr(" )", (size_t)2, &buf, &buflen));
1.1 christos 494: n = SPRINTF((tmp, " ; key_tag= %u", key_id));
1.2 christos 495: T(addstr(tmp, (size_t)n, &buf, &buflen));
1.1 christos 496:
497: break;
498: }
499:
500: case ns_t_sig: {
501: char base64_key[NS_MD5RSA_MAX_BASE64];
1.2 christos 502: u_int typ, algorithm, labels, footprint;
1.1 christos 503: const char *leader;
504: u_long t;
505: int n;
506:
507: if (rdlen < 22U)
508: goto formerr;
509:
510: /* Type covered, Algorithm, Label count, Original TTL. */
1.2 christos 511: typ = ns_get16(rdata); rdata += NS_INT16SZ;
1.1 christos 512: algorithm = *rdata++;
513: labels = *rdata++;
514: t = ns_get32(rdata); rdata += NS_INT32SZ;
515: len = SPRINTF((tmp, "%s %d %d %lu ",
1.2 christos 516: p_type((int)typ), algorithm, labels, t));
517: T(addstr(tmp, (size_t)len, &buf, &buflen));
1.1 christos 518: if (labels > (u_int)dn_count_labels(name))
519: goto formerr;
520:
521: /* Signature expiry. */
522: t = ns_get32(rdata); rdata += NS_INT32SZ;
523: len = SPRINTF((tmp, "%s ", p_secstodate(t)));
1.2 christos 524: T(addstr(tmp, (size_t)len, &buf, &buflen));
1.1 christos 525:
526: /* Time signed. */
527: t = ns_get32(rdata); rdata += NS_INT32SZ;
528: len = SPRINTF((tmp, "%s ", p_secstodate(t)));
1.2 christos 529: T(addstr(tmp, (size_t)len, &buf, &buflen));
1.1 christos 530:
531: /* Signature Footprint. */
532: footprint = ns_get16(rdata); rdata += NS_INT16SZ;
533: len = SPRINTF((tmp, "%u ", footprint));
1.2 christos 534: T(addstr(tmp, (size_t)len, &buf, &buflen));
1.1 christos 535:
536: /* Signer's name. */
537: T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
538:
539: /* Signature. */
1.2 christos 540: len = b64_ntop(rdata, (size_t)(edata - rdata),
1.1 christos 541: base64_key, sizeof base64_key);
542: if (len > 15) {
1.2 christos 543: T(addstr(" (", (size_t)2, &buf, &buflen));
1.1 christos 544: leader = "\n\t\t";
545: spaced = 0;
546: } else
547: leader = " ";
548: if (len < 0)
549: goto formerr;
550: for (n = 0; n < len; n += 48) {
551: T(addstr(leader, strlen(leader), &buf, &buflen));
1.2 christos 552: T(addstr(base64_key + n, (size_t)MIN(len - n, 48),
1.1 christos 553: &buf, &buflen));
554: }
555: if (len > 15)
1.2 christos 556: T(addstr(" )", (size_t)2, &buf, &buflen));
1.1 christos 557: break;
558: }
559:
560: case ns_t_nxt: {
561: int n, c;
562:
563: /* Next domain name. */
564: T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
565:
566: /* Type bit map. */
567: n = edata - rdata;
568: for (c = 0; c < n*8; c++)
569: if (NS_NXT_BIT_ISSET(c, rdata)) {
570: len = SPRINTF((tmp, " %s", p_type(c)));
1.2 christos 571: T(addstr(tmp, (size_t)len, &buf, &buflen));
1.1 christos 572: }
573: break;
574: }
575:
576: case ns_t_cert: {
577: u_int c_type, key_tag, alg;
578: int n;
579: unsigned int siz;
1.2 christos 580: char base64_cert[8192], tmp1[40];
1.1 christos 581: const char *leader;
582:
583: c_type = ns_get16(rdata); rdata += NS_INT16SZ;
584: key_tag = ns_get16(rdata); rdata += NS_INT16SZ;
585: alg = (u_int) *rdata++;
586:
1.2 christos 587: len = SPRINTF((tmp1, "%d %d %d ", c_type, key_tag, alg));
588: T(addstr(tmp1, (size_t)len, &buf, &buflen));
1.1 christos 589: siz = (edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */
590: if (siz > sizeof(base64_cert) * 3/4) {
591: const char *str = "record too long to print";
592: T(addstr(str, strlen(str), &buf, &buflen));
593: }
594: else {
1.2 christos 595: len = b64_ntop(rdata, (size_t)(edata-rdata),
596: base64_cert, siz);
1.1 christos 597:
598: if (len < 0)
599: goto formerr;
600: else if (len > 15) {
1.2 christos 601: T(addstr(" (", (size_t)2, &buf, &buflen));
1.1 christos 602: leader = "\n\t\t";
603: spaced = 0;
604: }
605: else
606: leader = " ";
607:
608: for (n = 0; n < len; n += 48) {
609: T(addstr(leader, strlen(leader),
610: &buf, &buflen));
1.2 christos 611: T(addstr(base64_cert + n, (size_t)MIN(len - n, 48),
1.1 christos 612: &buf, &buflen));
613: }
614: if (len > 15)
1.2 christos 615: T(addstr(" )", (size_t)2, &buf, &buflen));
1.1 christos 616: }
617: break;
618: }
619:
620: case ns_t_tkey: {
621: /* KJD - need to complete this */
622: u_long t;
623: int mode, err, keysize;
624:
625: /* Algorithm name. */
626: T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
1.2 christos 627: T(addstr(" ", (size_t)1, &buf, &buflen));
1.1 christos 628:
629: /* Inception. */
630: t = ns_get32(rdata); rdata += NS_INT32SZ;
631: len = SPRINTF((tmp, "%s ", p_secstodate(t)));
1.2 christos 632: T(addstr(tmp, (size_t)len, &buf, &buflen));
1.1 christos 633:
634: /* Experation. */
635: t = ns_get32(rdata); rdata += NS_INT32SZ;
636: len = SPRINTF((tmp, "%s ", p_secstodate(t)));
1.2 christos 637: T(addstr(tmp, (size_t)len, &buf, &buflen));
1.1 christos 638:
639: /* Mode , Error, Key Size. */
640: /* Priority, Weight, Port. */
641: mode = ns_get16(rdata); rdata += NS_INT16SZ;
642: err = ns_get16(rdata); rdata += NS_INT16SZ;
643: keysize = ns_get16(rdata); rdata += NS_INT16SZ;
644: len = SPRINTF((tmp, "%u %u %u ", mode, err, keysize));
1.2 christos 645: T(addstr(tmp, (size_t)len, &buf, &buflen));
1.1 christos 646:
647: /* XXX need to dump key, print otherdata length & other data */
648: break;
649: }
650:
651: case ns_t_tsig: {
652: /* BEW - need to complete this */
653: int n;
654:
655: T(len = addname(msg, msglen, &rdata, origin, &buf, &buflen));
1.2 christos 656: T(addstr(" ", (size_t)1, &buf, &buflen));
1.6 christos 657: rdata += 8; /*%< time */
1.1 christos 658: n = ns_get16(rdata); rdata += INT16SZ;
1.6 christos 659: rdata += n; /*%< sig */
660: n = ns_get16(rdata); rdata += INT16SZ; /*%< original id */
1.1 christos 661: sprintf(buf, "%d", ns_get16(rdata));
662: rdata += INT16SZ;
663: addlen(strlen(buf), &buf, &buflen);
664: break;
665: }
666:
667: case ns_t_a6: {
668: struct in6_addr a;
669: int pbyte, pbit;
670:
671: /* prefix length */
672: if (rdlen == 0U) goto formerr;
673: len = SPRINTF((tmp, "%d ", *rdata));
1.2 christos 674: T(addstr(tmp, (size_t)len, &buf, &buflen));
1.1 christos 675: pbit = *rdata;
676: if (pbit > 128) goto formerr;
677: pbyte = (pbit & ~7) / 8;
678: rdata++;
679:
680: /* address suffix: provided only when prefix len != 128 */
681: if (pbit < 128) {
682: if (rdata + pbyte >= edata) goto formerr;
683: memset(&a, 0, sizeof(a));
684: memcpy(&a.s6_addr[pbyte], rdata, sizeof(a) - pbyte);
685: (void) inet_ntop(AF_INET6, &a, buf, buflen);
686: addlen(strlen(buf), &buf, &buflen);
687: rdata += sizeof(a) - pbyte;
688: }
689:
690: /* prefix name: provided only when prefix len > 0 */
691: if (pbit == 0)
692: break;
693: if (rdata >= edata) goto formerr;
1.2 christos 694: T(addstr(" ", (size_t)1, &buf, &buflen));
1.1 christos 695: T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
696:
697: break;
698: }
699:
700: case ns_t_opt: {
701: len = SPRINTF((tmp, "%u bytes", class));
1.2 christos 702: T(addstr(tmp, (size_t)len, &buf, &buflen));
1.1 christos 703: break;
704: }
705:
706: default:
707: comment = "unknown RR type";
708: goto hexify;
709: }
710: return (buf - obuf);
711: formerr:
712: comment = "RR format error";
713: hexify: {
714: int n, m;
715: char *p;
716:
1.6 christos 717: len = SPRINTF((tmp, "\\# %u%s\t; %s", (unsigned)(edata - rdata),
718: rdlen != 0U ? " (" : "", comment));
1.2 christos 719: T(addstr(tmp, (size_t)len, &buf, &buflen));
1.1 christos 720: while (rdata < edata) {
721: p = tmp;
722: p += SPRINTF((p, "\n\t"));
723: spaced = 0;
724: n = MIN(16, edata - rdata);
725: for (m = 0; m < n; m++)
726: p += SPRINTF((p, "%02x ", rdata[m]));
1.2 christos 727: T(addstr(tmp, (size_t)(p - tmp), &buf, &buflen));
1.1 christos 728: if (n < 16) {
1.2 christos 729: T(addstr(")", (size_t)1, &buf, &buflen));
730: T(addtab((size_t)(p - tmp + 1), (size_t)48, spaced, &buf, &buflen));
1.1 christos 731: }
732: p = tmp;
733: p += SPRINTF((p, "; "));
734: for (m = 0; m < n; m++)
735: *p++ = (isascii(rdata[m]) && isprint(rdata[m]))
736: ? rdata[m]
737: : '.';
1.2 christos 738: T(addstr(tmp, (size_t)(p - tmp), &buf, &buflen));
1.1 christos 739: rdata += n;
740: }
741: return (buf - obuf);
742: }
743: }
744:
745: /* Private. */
746:
1.6 christos 747: /*%
1.1 christos 748: * size_t
749: * prune_origin(name, origin)
750: * Find out if the name is at or under the current origin.
751: * return:
752: * Number of characters in name before start of origin,
753: * or length of name if origin does not match.
754: * notes:
755: * This function should share code with samedomain().
756: */
757: static size_t
758: prune_origin(const char *name, const char *origin) {
759: const char *oname = name;
760:
761: while (*name != '\0') {
762: if (origin != NULL && ns_samename(name, origin) == 1)
763: return (name - oname - (name > oname));
764: while (*name != '\0') {
765: if (*name == '\\') {
766: name++;
767: /* XXX need to handle \nnn form. */
768: if (*name == '\0')
769: break;
770: } else if (*name == '.') {
771: name++;
772: break;
773: }
774: name++;
775: }
776: }
777: return (name - oname);
778: }
779:
1.6 christos 780: /*%
1.1 christos 781: * int
782: * charstr(rdata, edata, buf, buflen)
783: * Format a <character-string> into the presentation buffer.
784: * return:
785: * Number of rdata octets consumed
786: * 0 for protocol format error
787: * -1 for output buffer error
788: * side effects:
789: * buffer is advanced on success.
790: */
791: static int
792: charstr(const u_char *rdata, const u_char *edata, char **buf, size_t *buflen) {
793: const u_char *odata = rdata;
794: size_t save_buflen = *buflen;
795: char *save_buf = *buf;
796:
1.2 christos 797: if (addstr("\"", (size_t)1, buf, buflen) < 0)
1.1 christos 798: goto enospc;
799: if (rdata < edata) {
800: int n = *rdata;
801:
802: if (rdata + 1 + n <= edata) {
803: rdata++;
804: while (n-- > 0) {
805: if (strchr("\n\"\\", *rdata) != NULL)
1.2 christos 806: if (addstr("\\", (size_t)1, buf, buflen) < 0)
1.1 christos 807: goto enospc;
1.2 christos 808: if (addstr((const char *)rdata, (size_t)1,
1.1 christos 809: buf, buflen) < 0)
810: goto enospc;
811: rdata++;
812: }
813: }
814: }
1.2 christos 815: if (addstr("\"", (size_t)1, buf, buflen) < 0)
1.1 christos 816: goto enospc;
817: return (rdata - odata);
818: enospc:
819: errno = ENOSPC;
820: *buf = save_buf;
821: *buflen = save_buflen;
822: return (-1);
823: }
824:
825: static int
826: addname(const u_char *msg, size_t msglen,
827: const u_char **pp, const char *origin,
828: char **buf, size_t *buflen)
829: {
830: size_t newlen, save_buflen = *buflen;
831: char *save_buf = *buf;
832: int n;
833:
1.2 christos 834: n = dn_expand(msg, msg + msglen, *pp, *buf, (int)*buflen);
1.1 christos 835: if (n < 0)
1.6 christos 836: goto enospc; /*%< Guess. */
1.1 christos 837: newlen = prune_origin(*buf, origin);
838: if (**buf == '\0') {
839: goto root;
840: } else if (newlen == 0U) {
841: /* Use "@" instead of name. */
842: if (newlen + 2 > *buflen)
843: goto enospc; /* No room for "@\0". */
844: (*buf)[newlen++] = '@';
845: (*buf)[newlen] = '\0';
846: } else {
847: if (((origin == NULL || origin[0] == '\0') ||
848: (origin[0] != '.' && origin[1] != '\0' &&
849: (*buf)[newlen] == '\0')) && (*buf)[newlen - 1] != '.') {
850: /* No trailing dot. */
851: root:
852: if (newlen + 2 > *buflen)
853: goto enospc; /* No room for ".\0". */
854: (*buf)[newlen++] = '.';
855: (*buf)[newlen] = '\0';
856: }
857: }
858: *pp += n;
859: addlen(newlen, buf, buflen);
860: **buf = '\0';
861: return (newlen);
862: enospc:
863: errno = ENOSPC;
864: *buf = save_buf;
865: *buflen = save_buflen;
866: return (-1);
867: }
868:
869: static void
870: addlen(size_t len, char **buf, size_t *buflen) {
871: INSIST(len <= *buflen);
872: *buf += len;
873: *buflen -= len;
874: }
875:
876: static int
877: addstr(const char *src, size_t len, char **buf, size_t *buflen) {
878: if (len >= *buflen) {
879: errno = ENOSPC;
880: return (-1);
881: }
882: memcpy(*buf, src, len);
883: addlen(len, buf, buflen);
884: **buf = '\0';
885: return (0);
886: }
887:
888: static int
889: addtab(size_t len, size_t target, int spaced, char **buf, size_t *buflen) {
890: size_t save_buflen = *buflen;
891: char *save_buf = *buf;
892: int t;
893:
894: if (spaced || len >= target - 1) {
1.2 christos 895: T(addstr(" ", (size_t)2, buf, buflen));
1.1 christos 896: spaced = 1;
897: } else {
898: for (t = (target - len - 1) / 8; t >= 0; t--)
1.2 christos 899: if (addstr("\t", (size_t)1, buf, buflen) < 0) {
1.1 christos 900: *buflen = save_buflen;
901: *buf = save_buf;
902: return (-1);
903: }
904: spaced = 0;
905: }
906: return (spaced);
907: }
1.6 christos 908:
909: /*! \file */
CVSweb <webmaster@jp.NetBSD.org>