1*f14fb602SLionel Sambuc /* $NetBSD: ns_print.c,v 1.11 2012/03/13 21:13:39 christos Exp $ */
22fe8fb19SBen Gras
32fe8fb19SBen Gras /*
42fe8fb19SBen Gras * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
52fe8fb19SBen Gras * Copyright (c) 1996-1999 by Internet Software Consortium.
62fe8fb19SBen Gras *
72fe8fb19SBen Gras * Permission to use, copy, modify, and distribute this software for any
82fe8fb19SBen Gras * purpose with or without fee is hereby granted, provided that the above
92fe8fb19SBen Gras * copyright notice and this permission notice appear in all copies.
102fe8fb19SBen Gras *
112fe8fb19SBen Gras * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
122fe8fb19SBen Gras * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
132fe8fb19SBen Gras * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
142fe8fb19SBen Gras * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
152fe8fb19SBen Gras * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
162fe8fb19SBen Gras * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
172fe8fb19SBen Gras * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
182fe8fb19SBen Gras */
192fe8fb19SBen Gras
202fe8fb19SBen Gras #include <sys/cdefs.h>
212fe8fb19SBen Gras #ifndef lint
222fe8fb19SBen Gras #ifdef notdef
232fe8fb19SBen Gras static const char rcsid[] = "Id: ns_print.c,v 1.12 2009/03/03 05:29:58 each Exp";
242fe8fb19SBen Gras #else
25*f14fb602SLionel Sambuc __RCSID("$NetBSD: ns_print.c,v 1.11 2012/03/13 21:13:39 christos Exp $");
262fe8fb19SBen Gras #endif
272fe8fb19SBen Gras #endif
282fe8fb19SBen Gras
292fe8fb19SBen Gras /* Import. */
302fe8fb19SBen Gras
312fe8fb19SBen Gras #include "port_before.h"
322fe8fb19SBen Gras
332fe8fb19SBen Gras #include <sys/types.h>
342fe8fb19SBen Gras #include <sys/socket.h>
352fe8fb19SBen Gras
362fe8fb19SBen Gras #include <netinet/in.h>
372fe8fb19SBen Gras #include <arpa/nameser.h>
382fe8fb19SBen Gras #include <arpa/inet.h>
392fe8fb19SBen Gras
402fe8fb19SBen Gras #include <isc/assertions.h>
412fe8fb19SBen Gras #include <isc/dst.h>
42*f14fb602SLionel Sambuc #include <assert.h>
432fe8fb19SBen Gras #include <errno.h>
442fe8fb19SBen Gras #include <resolv.h>
45*f14fb602SLionel Sambuc #include <stddef.h>
462fe8fb19SBen Gras #include <string.h>
472fe8fb19SBen Gras #include <ctype.h>
482fe8fb19SBen Gras
492fe8fb19SBen Gras #include "port_after.h"
502fe8fb19SBen Gras
512fe8fb19SBen Gras #ifdef SPRINTF_CHAR
52*f14fb602SLionel Sambuc # define SPRINTF(x) ((int)strlen(sprintf/**/x))
532fe8fb19SBen Gras #else
54*f14fb602SLionel Sambuc # define SPRINTF(x) (sprintf x)
552fe8fb19SBen Gras #endif
562fe8fb19SBen Gras
572fe8fb19SBen Gras /* Forward. */
582fe8fb19SBen Gras
592fe8fb19SBen Gras static size_t prune_origin(const char *name, const char *origin);
602fe8fb19SBen Gras static int charstr(const u_char *rdata, const u_char *edata,
612fe8fb19SBen Gras char **buf, size_t *buflen);
622fe8fb19SBen Gras static int addname(const u_char *msg, size_t msglen,
632fe8fb19SBen Gras const u_char **p, const char *origin,
642fe8fb19SBen Gras char **buf, size_t *buflen);
652fe8fb19SBen Gras static void addlen(size_t len, char **buf, size_t *buflen);
662fe8fb19SBen Gras static int addstr(const char *src, size_t len,
672fe8fb19SBen Gras char **buf, size_t *buflen);
682fe8fb19SBen Gras static int addtab(size_t len, size_t target, int spaced,
692fe8fb19SBen Gras char **buf, size_t *buflen);
702fe8fb19SBen Gras
712fe8fb19SBen Gras /* Macros. */
722fe8fb19SBen Gras
732fe8fb19SBen Gras #define T(x) \
742fe8fb19SBen Gras do { \
752fe8fb19SBen Gras if ((x) < 0) \
762fe8fb19SBen Gras return (-1); \
772fe8fb19SBen Gras } while (/*CONSTCOND*/0)
782fe8fb19SBen Gras
792fe8fb19SBen Gras static const char base32hex[] =
802fe8fb19SBen Gras "0123456789ABCDEFGHIJKLMNOPQRSTUV=0123456789abcdefghijklmnopqrstuv";
812fe8fb19SBen Gras
822fe8fb19SBen Gras /* Public. */
832fe8fb19SBen Gras
842fe8fb19SBen Gras /*%
852fe8fb19SBen Gras * Convert an RR to presentation format.
862fe8fb19SBen Gras *
872fe8fb19SBen Gras * return:
882fe8fb19SBen Gras *\li Number of characters written to buf, or -1 (check errno).
892fe8fb19SBen Gras */
902fe8fb19SBen Gras int
ns_sprintrr(const ns_msg * handle,const ns_rr * rr,const char * name_ctx,const char * origin,char * buf,size_t buflen)912fe8fb19SBen Gras ns_sprintrr(const ns_msg *handle, const ns_rr *rr,
922fe8fb19SBen Gras const char *name_ctx, const char *origin,
932fe8fb19SBen Gras char *buf, size_t buflen)
942fe8fb19SBen Gras {
952fe8fb19SBen Gras int n;
962fe8fb19SBen Gras
972fe8fb19SBen Gras n = ns_sprintrrf(ns_msg_base(*handle), ns_msg_size(*handle),
982fe8fb19SBen Gras ns_rr_name(*rr), ns_rr_class(*rr), ns_rr_type(*rr),
992fe8fb19SBen Gras ns_rr_ttl(*rr), ns_rr_rdata(*rr), ns_rr_rdlen(*rr),
1002fe8fb19SBen Gras name_ctx, origin, buf, buflen);
1012fe8fb19SBen Gras return (n);
1022fe8fb19SBen Gras }
1032fe8fb19SBen Gras
1042fe8fb19SBen Gras /*%
1052fe8fb19SBen Gras * Convert the fields of an RR into presentation format.
1062fe8fb19SBen Gras *
1072fe8fb19SBen Gras * return:
1082fe8fb19SBen Gras *\li Number of characters written to buf, or -1 (check errno).
1092fe8fb19SBen Gras */
1102fe8fb19SBen Gras 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)1112fe8fb19SBen Gras ns_sprintrrf(const u_char *msg, size_t msglen,
1122fe8fb19SBen Gras const char *name, ns_class class, ns_type type,
1132fe8fb19SBen Gras u_long ttl, const u_char *rdata, size_t rdlen,
1142fe8fb19SBen Gras const char *name_ctx, const char *origin,
1152fe8fb19SBen Gras char *buf, size_t buflen)
1162fe8fb19SBen Gras {
1172fe8fb19SBen Gras const char *obuf = buf;
1182fe8fb19SBen Gras const u_char *edata = rdata + rdlen;
1192fe8fb19SBen Gras int spaced = 0;
1202fe8fb19SBen Gras
1212fe8fb19SBen Gras const char *comment;
1222fe8fb19SBen Gras char tmp[100];
1232fe8fb19SBen Gras int len, x;
1242fe8fb19SBen Gras
1252fe8fb19SBen Gras /*
1262fe8fb19SBen Gras * Owner.
1272fe8fb19SBen Gras */
1282fe8fb19SBen Gras if (name_ctx != NULL && ns_samename(name_ctx, name) == 1) {
1292fe8fb19SBen Gras T(addstr("\t\t\t", (size_t)3, &buf, &buflen));
1302fe8fb19SBen Gras } else {
131*f14fb602SLionel Sambuc len = (int)prune_origin(name, origin);
1322fe8fb19SBen Gras if (*name == '\0') {
1332fe8fb19SBen Gras goto root;
1342fe8fb19SBen Gras } else if (len == 0) {
1352fe8fb19SBen Gras T(addstr("@\t\t\t", (size_t)4, &buf, &buflen));
1362fe8fb19SBen Gras } else {
1372fe8fb19SBen Gras T(addstr(name, (size_t)len, &buf, &buflen));
1382fe8fb19SBen Gras /* Origin not used or not root, and no trailing dot? */
1392fe8fb19SBen Gras if (((origin == NULL || origin[0] == '\0') ||
1402fe8fb19SBen Gras (origin[0] != '.' && origin[1] != '\0' &&
1412fe8fb19SBen Gras name[len] == '\0')) && name[len - 1] != '.') {
1422fe8fb19SBen Gras root:
1432fe8fb19SBen Gras T(addstr(".", (size_t)1, &buf, &buflen));
1442fe8fb19SBen Gras len++;
1452fe8fb19SBen Gras }
1462fe8fb19SBen Gras T(spaced = addtab((size_t)len, 24, spaced, &buf, &buflen));
1472fe8fb19SBen Gras }
1482fe8fb19SBen Gras }
1492fe8fb19SBen Gras
1502fe8fb19SBen Gras /*
1512fe8fb19SBen Gras * TTL, Class, Type.
1522fe8fb19SBen Gras */
1532fe8fb19SBen Gras T(x = ns_format_ttl(ttl, buf, buflen));
1542fe8fb19SBen Gras addlen((size_t)x, &buf, &buflen);
1552fe8fb19SBen Gras len = SPRINTF((tmp, " %s %s", p_class(class), p_type(type)));
1562fe8fb19SBen Gras T(addstr(tmp, (size_t)len, &buf, &buflen));
1572fe8fb19SBen Gras T(spaced = addtab((size_t)(x + len), (size_t)16, spaced, &buf, &buflen));
1582fe8fb19SBen Gras
1592fe8fb19SBen Gras /*
1602fe8fb19SBen Gras * RData.
1612fe8fb19SBen Gras */
1622fe8fb19SBen Gras switch (type) {
1632fe8fb19SBen Gras case ns_t_a:
1642fe8fb19SBen Gras if (rdlen != (size_t)NS_INADDRSZ)
1652fe8fb19SBen Gras goto formerr;
166*f14fb602SLionel Sambuc (void) inet_ntop(AF_INET, rdata, buf, (socklen_t)buflen);
1672fe8fb19SBen Gras addlen(strlen(buf), &buf, &buflen);
1682fe8fb19SBen Gras break;
1692fe8fb19SBen Gras
1702fe8fb19SBen Gras case ns_t_cname:
1712fe8fb19SBen Gras case ns_t_mb:
1722fe8fb19SBen Gras case ns_t_mg:
1732fe8fb19SBen Gras case ns_t_mr:
1742fe8fb19SBen Gras case ns_t_ns:
1752fe8fb19SBen Gras case ns_t_ptr:
1762fe8fb19SBen Gras case ns_t_dname:
1772fe8fb19SBen Gras T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
1782fe8fb19SBen Gras break;
1792fe8fb19SBen Gras
1802fe8fb19SBen Gras case ns_t_hinfo:
1812fe8fb19SBen Gras case ns_t_isdn:
1822fe8fb19SBen Gras /* First word. */
1832fe8fb19SBen Gras T(len = charstr(rdata, edata, &buf, &buflen));
1842fe8fb19SBen Gras if (len == 0)
1852fe8fb19SBen Gras goto formerr;
1862fe8fb19SBen Gras rdata += len;
1872fe8fb19SBen Gras T(addstr(" ", (size_t)1, &buf, &buflen));
1882fe8fb19SBen Gras
1892fe8fb19SBen Gras
1902fe8fb19SBen Gras /* Second word, optional in ISDN records. */
1912fe8fb19SBen Gras if (type == ns_t_isdn && rdata == edata)
1922fe8fb19SBen Gras break;
1932fe8fb19SBen Gras
1942fe8fb19SBen Gras T(len = charstr(rdata, edata, &buf, &buflen));
1952fe8fb19SBen Gras if (len == 0)
1962fe8fb19SBen Gras goto formerr;
1972fe8fb19SBen Gras rdata += len;
1982fe8fb19SBen Gras break;
1992fe8fb19SBen Gras
2002fe8fb19SBen Gras case ns_t_soa: {
2012fe8fb19SBen Gras u_long t;
2022fe8fb19SBen Gras
2032fe8fb19SBen Gras /* Server name. */
2042fe8fb19SBen Gras T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
2052fe8fb19SBen Gras T(addstr(" ", (size_t)1, &buf, &buflen));
2062fe8fb19SBen Gras
2072fe8fb19SBen Gras /* Administrator name. */
2082fe8fb19SBen Gras T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
2092fe8fb19SBen Gras T(addstr(" (\n", (size_t)3, &buf, &buflen));
2102fe8fb19SBen Gras spaced = 0;
2112fe8fb19SBen Gras
2122fe8fb19SBen Gras if ((edata - rdata) != 5*NS_INT32SZ)
2132fe8fb19SBen Gras goto formerr;
2142fe8fb19SBen Gras
2152fe8fb19SBen Gras /* Serial number. */
2162fe8fb19SBen Gras t = ns_get32(rdata); rdata += NS_INT32SZ;
2172fe8fb19SBen Gras T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen));
2182fe8fb19SBen Gras len = SPRINTF((tmp, "%lu", t));
2192fe8fb19SBen Gras T(addstr(tmp, (size_t)len, &buf, &buflen));
2202fe8fb19SBen Gras T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen));
2212fe8fb19SBen Gras T(addstr("; serial\n", (size_t)9, &buf, &buflen));
2222fe8fb19SBen Gras spaced = 0;
2232fe8fb19SBen Gras
2242fe8fb19SBen Gras /* Refresh interval. */
2252fe8fb19SBen Gras t = ns_get32(rdata); rdata += NS_INT32SZ;
2262fe8fb19SBen Gras T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen));
2272fe8fb19SBen Gras T(len = ns_format_ttl(t, buf, buflen));
2282fe8fb19SBen Gras addlen((size_t)len, &buf, &buflen);
2292fe8fb19SBen Gras T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen));
2302fe8fb19SBen Gras T(addstr("; refresh\n", (size_t)10, &buf, &buflen));
2312fe8fb19SBen Gras spaced = 0;
2322fe8fb19SBen Gras
2332fe8fb19SBen Gras /* Retry interval. */
2342fe8fb19SBen Gras t = ns_get32(rdata); rdata += NS_INT32SZ;
2352fe8fb19SBen Gras T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen));
2362fe8fb19SBen Gras T(len = ns_format_ttl(t, buf, buflen));
2372fe8fb19SBen Gras addlen((size_t)len, &buf, &buflen);
2382fe8fb19SBen Gras T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen));
2392fe8fb19SBen Gras T(addstr("; retry\n", (size_t)8, &buf, &buflen));
2402fe8fb19SBen Gras spaced = 0;
2412fe8fb19SBen Gras
2422fe8fb19SBen Gras /* Expiry. */
2432fe8fb19SBen Gras t = ns_get32(rdata); rdata += NS_INT32SZ;
2442fe8fb19SBen Gras T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen));
2452fe8fb19SBen Gras T(len = ns_format_ttl(t, buf, buflen));
2462fe8fb19SBen Gras addlen((size_t)len, &buf, &buflen);
2472fe8fb19SBen Gras T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen));
2482fe8fb19SBen Gras T(addstr("; expiry\n", (size_t)9, &buf, &buflen));
2492fe8fb19SBen Gras spaced = 0;
2502fe8fb19SBen Gras
2512fe8fb19SBen Gras /* Minimum TTL. */
2522fe8fb19SBen Gras t = ns_get32(rdata); rdata += NS_INT32SZ;
2532fe8fb19SBen Gras T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen));
2542fe8fb19SBen Gras T(len = ns_format_ttl(t, buf, buflen));
2552fe8fb19SBen Gras addlen((size_t)len, &buf, &buflen);
2562fe8fb19SBen Gras T(addstr(" )", (size_t)2, &buf, &buflen));
2572fe8fb19SBen Gras T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen));
2582fe8fb19SBen Gras T(addstr("; minimum\n", (size_t)10, &buf, &buflen));
2592fe8fb19SBen Gras
2602fe8fb19SBen Gras break;
2612fe8fb19SBen Gras }
2622fe8fb19SBen Gras
2632fe8fb19SBen Gras case ns_t_mx:
2642fe8fb19SBen Gras case ns_t_afsdb:
2652fe8fb19SBen Gras case ns_t_rt:
2662fe8fb19SBen Gras case ns_t_kx: {
2672fe8fb19SBen Gras u_int t;
2682fe8fb19SBen Gras
2692fe8fb19SBen Gras if (rdlen < (size_t)NS_INT16SZ)
2702fe8fb19SBen Gras goto formerr;
2712fe8fb19SBen Gras
2722fe8fb19SBen Gras /* Priority. */
2732fe8fb19SBen Gras t = ns_get16(rdata);
2742fe8fb19SBen Gras rdata += NS_INT16SZ;
2752fe8fb19SBen Gras len = SPRINTF((tmp, "%u ", t));
2762fe8fb19SBen Gras T(addstr(tmp, (size_t)len, &buf, &buflen));
2772fe8fb19SBen Gras
2782fe8fb19SBen Gras /* Target. */
2792fe8fb19SBen Gras T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
2802fe8fb19SBen Gras
2812fe8fb19SBen Gras break;
2822fe8fb19SBen Gras }
2832fe8fb19SBen Gras
2842fe8fb19SBen Gras case ns_t_px: {
2852fe8fb19SBen Gras u_int t;
2862fe8fb19SBen Gras
2872fe8fb19SBen Gras if (rdlen < (size_t)NS_INT16SZ)
2882fe8fb19SBen Gras goto formerr;
2892fe8fb19SBen Gras
2902fe8fb19SBen Gras /* Priority. */
2912fe8fb19SBen Gras t = ns_get16(rdata);
2922fe8fb19SBen Gras rdata += NS_INT16SZ;
2932fe8fb19SBen Gras len = SPRINTF((tmp, "%u ", t));
2942fe8fb19SBen Gras T(addstr(tmp, (size_t)len, &buf, &buflen));
2952fe8fb19SBen Gras
2962fe8fb19SBen Gras /* Name1. */
2972fe8fb19SBen Gras T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
2982fe8fb19SBen Gras T(addstr(" ", (size_t)1, &buf, &buflen));
2992fe8fb19SBen Gras
3002fe8fb19SBen Gras /* Name2. */
3012fe8fb19SBen Gras T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
3022fe8fb19SBen Gras
3032fe8fb19SBen Gras break;
3042fe8fb19SBen Gras }
3052fe8fb19SBen Gras
3062fe8fb19SBen Gras case ns_t_x25:
3072fe8fb19SBen Gras T(len = charstr(rdata, edata, &buf, &buflen));
3082fe8fb19SBen Gras if (len == 0)
3092fe8fb19SBen Gras goto formerr;
3102fe8fb19SBen Gras rdata += len;
3112fe8fb19SBen Gras break;
3122fe8fb19SBen Gras
3132fe8fb19SBen Gras case ns_t_txt:
3142fe8fb19SBen Gras case ns_t_spf:
3152fe8fb19SBen Gras while (rdata < edata) {
3162fe8fb19SBen Gras T(len = charstr(rdata, edata, &buf, &buflen));
3172fe8fb19SBen Gras if (len == 0)
3182fe8fb19SBen Gras goto formerr;
3192fe8fb19SBen Gras rdata += len;
3202fe8fb19SBen Gras if (rdata < edata)
3212fe8fb19SBen Gras T(addstr(" ", (size_t)1, &buf, &buflen));
3222fe8fb19SBen Gras }
3232fe8fb19SBen Gras break;
3242fe8fb19SBen Gras
3252fe8fb19SBen Gras case ns_t_nsap: {
3262fe8fb19SBen Gras char t[2+255*3];
3272fe8fb19SBen Gras
3282fe8fb19SBen Gras (void) inet_nsap_ntoa((int)rdlen, rdata, t);
3292fe8fb19SBen Gras T(addstr(t, strlen(t), &buf, &buflen));
3302fe8fb19SBen Gras break;
3312fe8fb19SBen Gras }
3322fe8fb19SBen Gras
3332fe8fb19SBen Gras case ns_t_aaaa:
3342fe8fb19SBen Gras if (rdlen != (size_t)NS_IN6ADDRSZ)
3352fe8fb19SBen Gras goto formerr;
336*f14fb602SLionel Sambuc (void) inet_ntop(AF_INET6, rdata, buf, (socklen_t)buflen);
3372fe8fb19SBen Gras addlen(strlen(buf), &buf, &buflen);
3382fe8fb19SBen Gras break;
3392fe8fb19SBen Gras
3402fe8fb19SBen Gras case ns_t_loc: {
3412fe8fb19SBen Gras char t[255];
3422fe8fb19SBen Gras
3432fe8fb19SBen Gras /* XXX protocol format checking? */
3442fe8fb19SBen Gras (void) loc_ntoa(rdata, t);
3452fe8fb19SBen Gras T(addstr(t, strlen(t), &buf, &buflen));
3462fe8fb19SBen Gras break;
3472fe8fb19SBen Gras }
3482fe8fb19SBen Gras
3492fe8fb19SBen Gras case ns_t_naptr: {
3502fe8fb19SBen Gras u_int order, preference;
3512fe8fb19SBen Gras char t[50];
3522fe8fb19SBen Gras
3532fe8fb19SBen Gras if (rdlen < 2U*NS_INT16SZ)
3542fe8fb19SBen Gras goto formerr;
3552fe8fb19SBen Gras
3562fe8fb19SBen Gras /* Order, Precedence. */
3572fe8fb19SBen Gras order = ns_get16(rdata); rdata += NS_INT16SZ;
3582fe8fb19SBen Gras preference = ns_get16(rdata); rdata += NS_INT16SZ;
3592fe8fb19SBen Gras len = SPRINTF((t, "%u %u ", order, preference));
3602fe8fb19SBen Gras T(addstr(t, (size_t)len, &buf, &buflen));
3612fe8fb19SBen Gras
3622fe8fb19SBen Gras /* Flags. */
3632fe8fb19SBen Gras T(len = charstr(rdata, edata, &buf, &buflen));
3642fe8fb19SBen Gras if (len == 0)
3652fe8fb19SBen Gras goto formerr;
3662fe8fb19SBen Gras rdata += len;
3672fe8fb19SBen Gras T(addstr(" ", (size_t)1, &buf, &buflen));
3682fe8fb19SBen Gras
3692fe8fb19SBen Gras /* Service. */
3702fe8fb19SBen Gras T(len = charstr(rdata, edata, &buf, &buflen));
3712fe8fb19SBen Gras if (len == 0)
3722fe8fb19SBen Gras goto formerr;
3732fe8fb19SBen Gras rdata += len;
3742fe8fb19SBen Gras T(addstr(" ", (size_t)1, &buf, &buflen));
3752fe8fb19SBen Gras
3762fe8fb19SBen Gras /* Regexp. */
3772fe8fb19SBen Gras T(len = charstr(rdata, edata, &buf, &buflen));
3782fe8fb19SBen Gras if (len < 0)
3792fe8fb19SBen Gras return (-1);
3802fe8fb19SBen Gras if (len == 0)
3812fe8fb19SBen Gras goto formerr;
3822fe8fb19SBen Gras rdata += len;
3832fe8fb19SBen Gras T(addstr(" ", (size_t)1, &buf, &buflen));
3842fe8fb19SBen Gras
3852fe8fb19SBen Gras /* Server. */
3862fe8fb19SBen Gras T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
3872fe8fb19SBen Gras break;
3882fe8fb19SBen Gras }
3892fe8fb19SBen Gras
3902fe8fb19SBen Gras case ns_t_srv: {
3912fe8fb19SBen Gras u_int priority, weight, port;
3922fe8fb19SBen Gras char t[50];
3932fe8fb19SBen Gras
3942fe8fb19SBen Gras if (rdlen < 3U*NS_INT16SZ)
3952fe8fb19SBen Gras goto formerr;
3962fe8fb19SBen Gras
3972fe8fb19SBen Gras /* Priority, Weight, Port. */
3982fe8fb19SBen Gras priority = ns_get16(rdata); rdata += NS_INT16SZ;
3992fe8fb19SBen Gras weight = ns_get16(rdata); rdata += NS_INT16SZ;
4002fe8fb19SBen Gras port = ns_get16(rdata); rdata += NS_INT16SZ;
4012fe8fb19SBen Gras len = SPRINTF((t, "%u %u %u ", priority, weight, port));
4022fe8fb19SBen Gras T(addstr(t, (size_t)len, &buf, &buflen));
4032fe8fb19SBen Gras
4042fe8fb19SBen Gras /* Server. */
4052fe8fb19SBen Gras T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
4062fe8fb19SBen Gras break;
4072fe8fb19SBen Gras }
4082fe8fb19SBen Gras
4092fe8fb19SBen Gras case ns_t_minfo:
4102fe8fb19SBen Gras case ns_t_rp:
4112fe8fb19SBen Gras /* Name1. */
4122fe8fb19SBen Gras T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
4132fe8fb19SBen Gras T(addstr(" ", (size_t)1, &buf, &buflen));
4142fe8fb19SBen Gras
4152fe8fb19SBen Gras /* Name2. */
4162fe8fb19SBen Gras T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
4172fe8fb19SBen Gras
4182fe8fb19SBen Gras break;
4192fe8fb19SBen Gras
4202fe8fb19SBen Gras case ns_t_wks: {
4212fe8fb19SBen Gras int n, lcnt;
4222fe8fb19SBen Gras
4232fe8fb19SBen Gras if (rdlen < 1U + NS_INT32SZ)
4242fe8fb19SBen Gras goto formerr;
4252fe8fb19SBen Gras
4262fe8fb19SBen Gras /* Address. */
427*f14fb602SLionel Sambuc (void) inet_ntop(AF_INET, rdata, buf, (socklen_t)buflen);
4282fe8fb19SBen Gras addlen(strlen(buf), &buf, &buflen);
4292fe8fb19SBen Gras rdata += NS_INADDRSZ;
4302fe8fb19SBen Gras
4312fe8fb19SBen Gras /* Protocol. */
4322fe8fb19SBen Gras len = SPRINTF((tmp, " %u ( ", *rdata));
4332fe8fb19SBen Gras T(addstr(tmp, (size_t)len, &buf, &buflen));
4342fe8fb19SBen Gras rdata += NS_INT8SZ;
4352fe8fb19SBen Gras
4362fe8fb19SBen Gras /* Bit map. */
4372fe8fb19SBen Gras n = 0;
4382fe8fb19SBen Gras lcnt = 0;
4392fe8fb19SBen Gras while (rdata < edata) {
4402fe8fb19SBen Gras u_int c = *rdata++;
4412fe8fb19SBen Gras do {
4422fe8fb19SBen Gras if (c & 0200) {
4432fe8fb19SBen Gras if (lcnt == 0) {
4442fe8fb19SBen Gras T(addstr("\n\t\t\t\t", (size_t)5,
4452fe8fb19SBen Gras &buf, &buflen));
4462fe8fb19SBen Gras lcnt = 10;
4472fe8fb19SBen Gras spaced = 0;
4482fe8fb19SBen Gras }
4492fe8fb19SBen Gras len = SPRINTF((tmp, "%d ", n));
4502fe8fb19SBen Gras T(addstr(tmp, (size_t)len, &buf, &buflen));
4512fe8fb19SBen Gras lcnt--;
4522fe8fb19SBen Gras }
4532fe8fb19SBen Gras c <<= 1;
4542fe8fb19SBen Gras } while (++n & 07);
4552fe8fb19SBen Gras }
4562fe8fb19SBen Gras T(addstr(")", (size_t)1, &buf, &buflen));
4572fe8fb19SBen Gras
4582fe8fb19SBen Gras break;
4592fe8fb19SBen Gras }
4602fe8fb19SBen Gras
4612fe8fb19SBen Gras case ns_t_key:
4622fe8fb19SBen Gras case ns_t_dnskey: {
4632fe8fb19SBen Gras char base64_key[NS_MD5RSA_MAX_BASE64];
4642fe8fb19SBen Gras u_int keyflags, protocol, algorithm, key_id;
4652fe8fb19SBen Gras const char *leader;
4662fe8fb19SBen Gras int n;
4672fe8fb19SBen Gras
4682fe8fb19SBen Gras if (rdlen < 0U + NS_INT16SZ + NS_INT8SZ + NS_INT8SZ)
4692fe8fb19SBen Gras goto formerr;
4702fe8fb19SBen Gras
4712fe8fb19SBen Gras /* Key flags, Protocol, Algorithm. */
4722fe8fb19SBen Gras #ifndef _LIBC
4732fe8fb19SBen Gras key_id = dst_s_dns_key_id(rdata, edata-rdata);
4742fe8fb19SBen Gras #else
4752fe8fb19SBen Gras key_id = 0;
4762fe8fb19SBen Gras #endif
4772fe8fb19SBen Gras keyflags = ns_get16(rdata); rdata += NS_INT16SZ;
4782fe8fb19SBen Gras protocol = *rdata++;
4792fe8fb19SBen Gras algorithm = *rdata++;
4802fe8fb19SBen Gras len = SPRINTF((tmp, "0x%04x %u %u",
4812fe8fb19SBen Gras keyflags, protocol, algorithm));
4822fe8fb19SBen Gras T(addstr(tmp, (size_t)len, &buf, &buflen));
4832fe8fb19SBen Gras
4842fe8fb19SBen Gras /* Public key data. */
4852fe8fb19SBen Gras len = b64_ntop(rdata, (size_t)(edata - rdata),
4862fe8fb19SBen Gras base64_key, sizeof base64_key);
4872fe8fb19SBen Gras if (len < 0)
4882fe8fb19SBen Gras goto formerr;
4892fe8fb19SBen Gras if (len > 15) {
4902fe8fb19SBen Gras T(addstr(" (", (size_t)2, &buf, &buflen));
4912fe8fb19SBen Gras leader = "\n\t\t";
4922fe8fb19SBen Gras spaced = 0;
4932fe8fb19SBen Gras } else
4942fe8fb19SBen Gras leader = " ";
4952fe8fb19SBen Gras for (n = 0; n < len; n += 48) {
4962fe8fb19SBen Gras T(addstr(leader, strlen(leader), &buf, &buflen));
4972fe8fb19SBen Gras T(addstr(base64_key + n, (size_t)MIN(len - n, 48),
4982fe8fb19SBen Gras &buf, &buflen));
4992fe8fb19SBen Gras }
5002fe8fb19SBen Gras if (len > 15)
5012fe8fb19SBen Gras T(addstr(" )", (size_t)2, &buf, &buflen));
5022fe8fb19SBen Gras n = SPRINTF((tmp, " ; key_tag= %u", key_id));
5032fe8fb19SBen Gras T(addstr(tmp, (size_t)n, &buf, &buflen));
5042fe8fb19SBen Gras
5052fe8fb19SBen Gras break;
5062fe8fb19SBen Gras }
5072fe8fb19SBen Gras
5082fe8fb19SBen Gras case ns_t_sig:
5092fe8fb19SBen Gras case ns_t_rrsig: {
5102fe8fb19SBen Gras char base64_key[NS_MD5RSA_MAX_BASE64];
5112fe8fb19SBen Gras u_int typ, algorithm, labels, footprint;
5122fe8fb19SBen Gras const char *leader;
5132fe8fb19SBen Gras u_long t;
5142fe8fb19SBen Gras int n;
5152fe8fb19SBen Gras
5162fe8fb19SBen Gras if (rdlen < 22U)
5172fe8fb19SBen Gras goto formerr;
5182fe8fb19SBen Gras
5192fe8fb19SBen Gras /* Type covered, Algorithm, Label count, Original TTL. */
5202fe8fb19SBen Gras typ = ns_get16(rdata); rdata += NS_INT16SZ;
5212fe8fb19SBen Gras algorithm = *rdata++;
5222fe8fb19SBen Gras labels = *rdata++;
5232fe8fb19SBen Gras t = ns_get32(rdata); rdata += NS_INT32SZ;
5242fe8fb19SBen Gras len = SPRINTF((tmp, "%s %d %d %lu ",
5252fe8fb19SBen Gras p_type((int)typ), algorithm, labels, t));
5262fe8fb19SBen Gras T(addstr(tmp, (size_t)len, &buf, &buflen));
5272fe8fb19SBen Gras if (labels > (u_int)dn_count_labels(name))
5282fe8fb19SBen Gras goto formerr;
5292fe8fb19SBen Gras
5302fe8fb19SBen Gras /* Signature expiry. */
5312fe8fb19SBen Gras t = ns_get32(rdata); rdata += NS_INT32SZ;
5322fe8fb19SBen Gras len = SPRINTF((tmp, "%s ", p_secstodate(t)));
5332fe8fb19SBen Gras T(addstr(tmp, (size_t)len, &buf, &buflen));
5342fe8fb19SBen Gras
5352fe8fb19SBen Gras /* Time signed. */
5362fe8fb19SBen Gras t = ns_get32(rdata); rdata += NS_INT32SZ;
5372fe8fb19SBen Gras len = SPRINTF((tmp, "%s ", p_secstodate(t)));
5382fe8fb19SBen Gras T(addstr(tmp, (size_t)len, &buf, &buflen));
5392fe8fb19SBen Gras
5402fe8fb19SBen Gras /* Signature Footprint. */
5412fe8fb19SBen Gras footprint = ns_get16(rdata); rdata += NS_INT16SZ;
5422fe8fb19SBen Gras len = SPRINTF((tmp, "%u ", footprint));
5432fe8fb19SBen Gras T(addstr(tmp, (size_t)len, &buf, &buflen));
5442fe8fb19SBen Gras
5452fe8fb19SBen Gras /* Signer's name. */
5462fe8fb19SBen Gras T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
5472fe8fb19SBen Gras
5482fe8fb19SBen Gras /* Signature. */
5492fe8fb19SBen Gras len = b64_ntop(rdata, (size_t)(edata - rdata),
5502fe8fb19SBen Gras base64_key, sizeof base64_key);
5512fe8fb19SBen Gras if (len > 15) {
5522fe8fb19SBen Gras T(addstr(" (", (size_t)2, &buf, &buflen));
5532fe8fb19SBen Gras leader = "\n\t\t";
5542fe8fb19SBen Gras spaced = 0;
5552fe8fb19SBen Gras } else
5562fe8fb19SBen Gras leader = " ";
5572fe8fb19SBen Gras if (len < 0)
5582fe8fb19SBen Gras goto formerr;
5592fe8fb19SBen Gras for (n = 0; n < len; n += 48) {
5602fe8fb19SBen Gras T(addstr(leader, strlen(leader), &buf, &buflen));
5612fe8fb19SBen Gras T(addstr(base64_key + n, (size_t)MIN(len - n, 48),
5622fe8fb19SBen Gras &buf, &buflen));
5632fe8fb19SBen Gras }
5642fe8fb19SBen Gras if (len > 15)
5652fe8fb19SBen Gras T(addstr(" )", (size_t)2, &buf, &buflen));
5662fe8fb19SBen Gras break;
5672fe8fb19SBen Gras }
5682fe8fb19SBen Gras
5692fe8fb19SBen Gras case ns_t_nxt: {
570*f14fb602SLionel Sambuc ptrdiff_t n, c;
5712fe8fb19SBen Gras
5722fe8fb19SBen Gras /* Next domain name. */
5732fe8fb19SBen Gras T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
5742fe8fb19SBen Gras
5752fe8fb19SBen Gras /* Type bit map. */
5762fe8fb19SBen Gras n = edata - rdata;
5772fe8fb19SBen Gras for (c = 0; c < n*8; c++)
5782fe8fb19SBen Gras if (NS_NXT_BIT_ISSET(c, rdata)) {
579*f14fb602SLionel Sambuc len = SPRINTF((tmp, " %s", p_type((int)c)));
5802fe8fb19SBen Gras T(addstr(tmp, (size_t)len, &buf, &buflen));
5812fe8fb19SBen Gras }
5822fe8fb19SBen Gras break;
5832fe8fb19SBen Gras }
5842fe8fb19SBen Gras
5852fe8fb19SBen Gras case ns_t_cert: {
5862fe8fb19SBen Gras u_int c_type, key_tag, alg;
5872fe8fb19SBen Gras int n;
588*f14fb602SLionel Sambuc size_t siz;
5892fe8fb19SBen Gras char base64_cert[8192], tmp1[40];
5902fe8fb19SBen Gras const char *leader;
5912fe8fb19SBen Gras
5922fe8fb19SBen Gras c_type = ns_get16(rdata); rdata += NS_INT16SZ;
5932fe8fb19SBen Gras key_tag = ns_get16(rdata); rdata += NS_INT16SZ;
5942fe8fb19SBen Gras alg = (u_int) *rdata++;
5952fe8fb19SBen Gras
5962fe8fb19SBen Gras len = SPRINTF((tmp1, "%d %d %d ", c_type, key_tag, alg));
5972fe8fb19SBen Gras T(addstr(tmp1, (size_t)len, &buf, &buflen));
5982fe8fb19SBen Gras siz = (edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */
5992fe8fb19SBen Gras if (siz > sizeof(base64_cert) * 3/4) {
6002fe8fb19SBen Gras const char *str = "record too long to print";
6012fe8fb19SBen Gras T(addstr(str, strlen(str), &buf, &buflen));
6022fe8fb19SBen Gras }
6032fe8fb19SBen Gras else {
6042fe8fb19SBen Gras len = b64_ntop(rdata, (size_t)(edata-rdata),
6052fe8fb19SBen Gras base64_cert, siz);
6062fe8fb19SBen Gras
6072fe8fb19SBen Gras if (len < 0)
6082fe8fb19SBen Gras goto formerr;
6092fe8fb19SBen Gras else if (len > 15) {
6102fe8fb19SBen Gras T(addstr(" (", (size_t)2, &buf, &buflen));
6112fe8fb19SBen Gras leader = "\n\t\t";
6122fe8fb19SBen Gras spaced = 0;
6132fe8fb19SBen Gras }
6142fe8fb19SBen Gras else
6152fe8fb19SBen Gras leader = " ";
6162fe8fb19SBen Gras
6172fe8fb19SBen Gras for (n = 0; n < len; n += 48) {
6182fe8fb19SBen Gras T(addstr(leader, strlen(leader),
6192fe8fb19SBen Gras &buf, &buflen));
6202fe8fb19SBen Gras T(addstr(base64_cert + n, (size_t)MIN(len - n, 48),
6212fe8fb19SBen Gras &buf, &buflen));
6222fe8fb19SBen Gras }
6232fe8fb19SBen Gras if (len > 15)
6242fe8fb19SBen Gras T(addstr(" )", (size_t)2, &buf, &buflen));
6252fe8fb19SBen Gras }
6262fe8fb19SBen Gras break;
6272fe8fb19SBen Gras }
6282fe8fb19SBen Gras
6292fe8fb19SBen Gras case ns_t_tkey: {
6302fe8fb19SBen Gras /* KJD - need to complete this */
6312fe8fb19SBen Gras u_long t;
6322fe8fb19SBen Gras int mode, err, keysize;
6332fe8fb19SBen Gras
6342fe8fb19SBen Gras /* Algorithm name. */
6352fe8fb19SBen Gras T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
6362fe8fb19SBen Gras T(addstr(" ", (size_t)1, &buf, &buflen));
6372fe8fb19SBen Gras
6382fe8fb19SBen Gras /* Inception. */
6392fe8fb19SBen Gras t = ns_get32(rdata); rdata += NS_INT32SZ;
6402fe8fb19SBen Gras len = SPRINTF((tmp, "%s ", p_secstodate(t)));
6412fe8fb19SBen Gras T(addstr(tmp, (size_t)len, &buf, &buflen));
6422fe8fb19SBen Gras
6432fe8fb19SBen Gras /* Experation. */
6442fe8fb19SBen Gras t = ns_get32(rdata); rdata += NS_INT32SZ;
6452fe8fb19SBen Gras len = SPRINTF((tmp, "%s ", p_secstodate(t)));
6462fe8fb19SBen Gras T(addstr(tmp, (size_t)len, &buf, &buflen));
6472fe8fb19SBen Gras
6482fe8fb19SBen Gras /* Mode , Error, Key Size. */
6492fe8fb19SBen Gras /* Priority, Weight, Port. */
6502fe8fb19SBen Gras mode = ns_get16(rdata); rdata += NS_INT16SZ;
6512fe8fb19SBen Gras err = ns_get16(rdata); rdata += NS_INT16SZ;
6522fe8fb19SBen Gras keysize = ns_get16(rdata); rdata += NS_INT16SZ;
6532fe8fb19SBen Gras len = SPRINTF((tmp, "%u %u %u ", mode, err, keysize));
6542fe8fb19SBen Gras T(addstr(tmp, (size_t)len, &buf, &buflen));
6552fe8fb19SBen Gras
6562fe8fb19SBen Gras /* XXX need to dump key, print otherdata length & other data */
6572fe8fb19SBen Gras break;
6582fe8fb19SBen Gras }
6592fe8fb19SBen Gras
6602fe8fb19SBen Gras case ns_t_tsig: {
6612fe8fb19SBen Gras /* BEW - need to complete this */
6622fe8fb19SBen Gras int n;
6632fe8fb19SBen Gras
6642fe8fb19SBen Gras T(len = addname(msg, msglen, &rdata, origin, &buf, &buflen));
6652fe8fb19SBen Gras T(addstr(" ", (size_t)1, &buf, &buflen));
6662fe8fb19SBen Gras rdata += 8; /*%< time */
6672fe8fb19SBen Gras n = ns_get16(rdata); rdata += INT16SZ;
6682fe8fb19SBen Gras rdata += n; /*%< sig */
6692fe8fb19SBen Gras n = ns_get16(rdata); rdata += INT16SZ; /*%< original id */
6702fe8fb19SBen Gras sprintf(buf, "%d", ns_get16(rdata));
6712fe8fb19SBen Gras rdata += INT16SZ;
6722fe8fb19SBen Gras addlen(strlen(buf), &buf, &buflen);
6732fe8fb19SBen Gras break;
6742fe8fb19SBen Gras }
6752fe8fb19SBen Gras
6762fe8fb19SBen Gras case ns_t_a6: {
6772fe8fb19SBen Gras struct in6_addr a;
6782fe8fb19SBen Gras int pbyte, pbit;
6792fe8fb19SBen Gras
6802fe8fb19SBen Gras /* prefix length */
6812fe8fb19SBen Gras if (rdlen == 0U) goto formerr;
6822fe8fb19SBen Gras len = SPRINTF((tmp, "%d ", *rdata));
6832fe8fb19SBen Gras T(addstr(tmp, (size_t)len, &buf, &buflen));
6842fe8fb19SBen Gras pbit = *rdata;
6852fe8fb19SBen Gras if (pbit > 128) goto formerr;
6862fe8fb19SBen Gras pbyte = (pbit & ~7) / 8;
6872fe8fb19SBen Gras rdata++;
6882fe8fb19SBen Gras
6892fe8fb19SBen Gras /* address suffix: provided only when prefix len != 128 */
6902fe8fb19SBen Gras if (pbit < 128) {
6912fe8fb19SBen Gras if (rdata + pbyte >= edata) goto formerr;
6922fe8fb19SBen Gras memset(&a, 0, sizeof(a));
6932fe8fb19SBen Gras memcpy(&a.s6_addr[pbyte], rdata, sizeof(a) - pbyte);
694*f14fb602SLionel Sambuc (void) inet_ntop(AF_INET6, &a, buf, (socklen_t)buflen);
6952fe8fb19SBen Gras addlen(strlen(buf), &buf, &buflen);
6962fe8fb19SBen Gras rdata += sizeof(a) - pbyte;
6972fe8fb19SBen Gras }
6982fe8fb19SBen Gras
6992fe8fb19SBen Gras /* prefix name: provided only when prefix len > 0 */
7002fe8fb19SBen Gras if (pbit == 0)
7012fe8fb19SBen Gras break;
7022fe8fb19SBen Gras if (rdata >= edata) goto formerr;
7032fe8fb19SBen Gras T(addstr(" ", (size_t)1, &buf, &buflen));
7042fe8fb19SBen Gras T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
7052fe8fb19SBen Gras
7062fe8fb19SBen Gras break;
7072fe8fb19SBen Gras }
7082fe8fb19SBen Gras
7092fe8fb19SBen Gras case ns_t_opt: {
7102fe8fb19SBen Gras len = SPRINTF((tmp, "%u bytes", class));
7112fe8fb19SBen Gras T(addstr(tmp, (size_t)len, &buf, &buflen));
7122fe8fb19SBen Gras break;
7132fe8fb19SBen Gras }
7142fe8fb19SBen Gras
7152fe8fb19SBen Gras case ns_t_ds:
7162fe8fb19SBen Gras case ns_t_dlv:
7172fe8fb19SBen Gras case ns_t_sshfp: {
7182fe8fb19SBen Gras u_int t;
7192fe8fb19SBen Gras
7202fe8fb19SBen Gras if (type == ns_t_ds || type == ns_t_dlv) {
7212fe8fb19SBen Gras if (rdlen < 4U) goto formerr;
7222fe8fb19SBen Gras t = ns_get16(rdata);
7232fe8fb19SBen Gras rdata += NS_INT16SZ;
7242fe8fb19SBen Gras len = SPRINTF((tmp, "%u ", t));
7252fe8fb19SBen Gras T(addstr(tmp, (size_t)len, &buf, &buflen));
7262fe8fb19SBen Gras } else
7272fe8fb19SBen Gras if (rdlen < 2U) goto formerr;
7282fe8fb19SBen Gras
7292fe8fb19SBen Gras len = SPRINTF((tmp, "%u ", *rdata));
7302fe8fb19SBen Gras T(addstr(tmp, (size_t)len, &buf, &buflen));
7312fe8fb19SBen Gras rdata++;
7322fe8fb19SBen Gras
7332fe8fb19SBen Gras len = SPRINTF((tmp, "%u ", *rdata));
7342fe8fb19SBen Gras T(addstr(tmp, (size_t)len, &buf, &buflen));
7352fe8fb19SBen Gras rdata++;
7362fe8fb19SBen Gras
7372fe8fb19SBen Gras while (rdata < edata) {
7382fe8fb19SBen Gras len = SPRINTF((tmp, "%02X", *rdata));
7392fe8fb19SBen Gras T(addstr(tmp, (size_t)len, &buf, &buflen));
7402fe8fb19SBen Gras rdata++;
7412fe8fb19SBen Gras }
7422fe8fb19SBen Gras break;
7432fe8fb19SBen Gras }
7442fe8fb19SBen Gras
7452fe8fb19SBen Gras case ns_t_nsec3:
7462fe8fb19SBen Gras case ns_t_nsec3param: {
7472fe8fb19SBen Gras u_int t, w, l, j, k, c;
7482fe8fb19SBen Gras
7492fe8fb19SBen Gras len = SPRINTF((tmp, "%u ", *rdata));
7502fe8fb19SBen Gras T(addstr(tmp, (size_t)len, &buf, &buflen));
7512fe8fb19SBen Gras rdata++;
7522fe8fb19SBen Gras
7532fe8fb19SBen Gras len = SPRINTF((tmp, "%u ", *rdata));
7542fe8fb19SBen Gras T(addstr(tmp, (size_t)len, &buf, &buflen));
7552fe8fb19SBen Gras rdata++;
7562fe8fb19SBen Gras
7572fe8fb19SBen Gras t = ns_get16(rdata);
7582fe8fb19SBen Gras rdata += NS_INT16SZ;
7592fe8fb19SBen Gras len = SPRINTF((tmp, "%u ", t));
7602fe8fb19SBen Gras T(addstr(tmp, (size_t)len, &buf, &buflen));
7612fe8fb19SBen Gras
7622fe8fb19SBen Gras t = *rdata++;
7632fe8fb19SBen Gras if (t == 0) {
7642fe8fb19SBen Gras T(addstr("-", 1, &buf, &buflen));
7652fe8fb19SBen Gras } else {
7662fe8fb19SBen Gras while (t-- > 0) {
7672fe8fb19SBen Gras len = SPRINTF((tmp, "%02X", *rdata));
7682fe8fb19SBen Gras T(addstr(tmp, (size_t)len, &buf, &buflen));
7692fe8fb19SBen Gras rdata++;
7702fe8fb19SBen Gras }
7712fe8fb19SBen Gras }
7722fe8fb19SBen Gras if (type == ns_t_nsec3param)
7732fe8fb19SBen Gras break;
7742fe8fb19SBen Gras T(addstr(" ", 1, &buf, &buflen));
7752fe8fb19SBen Gras
7762fe8fb19SBen Gras t = *rdata++;
7772fe8fb19SBen Gras while (t > 0) {
7782fe8fb19SBen Gras switch (t) {
7792fe8fb19SBen Gras case 1:
7802fe8fb19SBen Gras tmp[0] = base32hex[(((uint32_t)rdata[0]>>3)&0x1f)];
7812fe8fb19SBen Gras tmp[1] = base32hex[(((uint32_t)rdata[0]<<2)&0x1c)];
7822fe8fb19SBen Gras tmp[2] = tmp[3] = tmp[4] = '=';
7832fe8fb19SBen Gras tmp[5] = tmp[6] = tmp[7] = '=';
7842fe8fb19SBen Gras break;
7852fe8fb19SBen Gras case 2:
7862fe8fb19SBen Gras tmp[0] = base32hex[(((uint32_t)rdata[0]>>3)&0x1f)];
7872fe8fb19SBen Gras tmp[1] = base32hex[(((uint32_t)rdata[0]<<2)&0x1c)|
7882fe8fb19SBen Gras (((uint32_t)rdata[1]>>6)&0x03)];
7892fe8fb19SBen Gras tmp[2] = base32hex[(((uint32_t)rdata[1]>>1)&0x1f)];
7902fe8fb19SBen Gras tmp[3] = base32hex[(((uint32_t)rdata[1]<<4)&0x10)];
7912fe8fb19SBen Gras tmp[4] = tmp[5] = tmp[6] = tmp[7] = '=';
7922fe8fb19SBen Gras break;
7932fe8fb19SBen Gras case 3:
7942fe8fb19SBen Gras tmp[0] = base32hex[(((uint32_t)rdata[0]>>3)&0x1f)];
7952fe8fb19SBen Gras tmp[1] = base32hex[(((uint32_t)rdata[0]<<2)&0x1c)|
7962fe8fb19SBen Gras (((uint32_t)rdata[1]>>6)&0x03)];
7972fe8fb19SBen Gras tmp[2] = base32hex[(((uint32_t)rdata[1]>>1)&0x1f)];
7982fe8fb19SBen Gras tmp[3] = base32hex[(((uint32_t)rdata[1]<<4)&0x10)|
7992fe8fb19SBen Gras (((uint32_t)rdata[2]>>4)&0x0f)];
8002fe8fb19SBen Gras tmp[4] = base32hex[(((uint32_t)rdata[2]<<1)&0x1e)];
8012fe8fb19SBen Gras tmp[5] = tmp[6] = tmp[7] = '=';
8022fe8fb19SBen Gras break;
8032fe8fb19SBen Gras case 4:
8042fe8fb19SBen Gras tmp[0] = base32hex[(((uint32_t)rdata[0]>>3)&0x1f)];
8052fe8fb19SBen Gras tmp[1] = base32hex[(((uint32_t)rdata[0]<<2)&0x1c)|
8062fe8fb19SBen Gras (((uint32_t)rdata[1]>>6)&0x03)];
8072fe8fb19SBen Gras tmp[2] = base32hex[(((uint32_t)rdata[1]>>1)&0x1f)];
8082fe8fb19SBen Gras tmp[3] = base32hex[(((uint32_t)rdata[1]<<4)&0x10)|
8092fe8fb19SBen Gras (((uint32_t)rdata[2]>>4)&0x0f)];
8102fe8fb19SBen Gras tmp[4] = base32hex[(((uint32_t)rdata[2]<<1)&0x1e)|
8112fe8fb19SBen Gras (((uint32_t)rdata[3]>>7)&0x01)];
8122fe8fb19SBen Gras tmp[5] = base32hex[(((uint32_t)rdata[3]>>2)&0x1f)];
8132fe8fb19SBen Gras tmp[6] = base32hex[((uint32_t)rdata[3]<<3)&0x18];
8142fe8fb19SBen Gras tmp[7] = '=';
8152fe8fb19SBen Gras break;
8162fe8fb19SBen Gras default:
8172fe8fb19SBen Gras tmp[0] = base32hex[(((uint32_t)rdata[0]>>3)&0x1f)];
8182fe8fb19SBen Gras tmp[1] = base32hex[(((uint32_t)rdata[0]<<2)&0x1c)|
8192fe8fb19SBen Gras (((uint32_t)rdata[1]>>6)&0x03)];
8202fe8fb19SBen Gras tmp[2] = base32hex[(((uint32_t)rdata[1]>>1)&0x1f)];
8212fe8fb19SBen Gras tmp[3] = base32hex[(((uint32_t)rdata[1]<<4)&0x10)|
8222fe8fb19SBen Gras (((uint32_t)rdata[2]>>4)&0x0f)];
8232fe8fb19SBen Gras tmp[4] = base32hex[(((uint32_t)rdata[2]<<1)&0x1e)|
8242fe8fb19SBen Gras (((uint32_t)rdata[3]>>7)&0x01)];
8252fe8fb19SBen Gras tmp[5] = base32hex[(((uint32_t)rdata[3]>>2)&0x1f)];
8262fe8fb19SBen Gras tmp[6] = base32hex[(((uint32_t)rdata[3]<<3)&0x18)|
8272fe8fb19SBen Gras (((uint32_t)rdata[4]>>5)&0x07)];
8282fe8fb19SBen Gras tmp[7] = base32hex[(rdata[4]&0x1f)];
8292fe8fb19SBen Gras break;
8302fe8fb19SBen Gras }
8312fe8fb19SBen Gras T(addstr(tmp, 8, &buf, &buflen));
8322fe8fb19SBen Gras if (t >= 5) {
8332fe8fb19SBen Gras rdata += 5;
8342fe8fb19SBen Gras t -= 5;
8352fe8fb19SBen Gras } else {
8362fe8fb19SBen Gras rdata += t;
8372fe8fb19SBen Gras t -= t;
8382fe8fb19SBen Gras }
8392fe8fb19SBen Gras }
8402fe8fb19SBen Gras
8412fe8fb19SBen Gras while (rdata < edata) {
8422fe8fb19SBen Gras w = *rdata++;
8432fe8fb19SBen Gras l = *rdata++;
8442fe8fb19SBen Gras for (j = 0; j < l; j++) {
8452fe8fb19SBen Gras if (rdata[j] == 0)
8462fe8fb19SBen Gras continue;
8472fe8fb19SBen Gras for (k = 0; k < 8; k++) {
8482fe8fb19SBen Gras if ((rdata[j] & (0x80 >> k)) == 0)
8492fe8fb19SBen Gras continue;
8502fe8fb19SBen Gras c = w * 256 + j * 8 + k;
8512fe8fb19SBen Gras len = SPRINTF((tmp, " %s", p_type((ns_type)c)));
8522fe8fb19SBen Gras T(addstr(tmp, (size_t)len, &buf, &buflen));
8532fe8fb19SBen Gras }
8542fe8fb19SBen Gras }
8552fe8fb19SBen Gras rdata += l;
8562fe8fb19SBen Gras }
8572fe8fb19SBen Gras break;
8582fe8fb19SBen Gras }
8592fe8fb19SBen Gras
8602fe8fb19SBen Gras case ns_t_nsec: {
8612fe8fb19SBen Gras u_int w, l, j, k, c;
8622fe8fb19SBen Gras
8632fe8fb19SBen Gras T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
8642fe8fb19SBen Gras
8652fe8fb19SBen Gras while (rdata < edata) {
8662fe8fb19SBen Gras w = *rdata++;
8672fe8fb19SBen Gras l = *rdata++;
8682fe8fb19SBen Gras for (j = 0; j < l; j++) {
8692fe8fb19SBen Gras if (rdata[j] == 0)
8702fe8fb19SBen Gras continue;
8712fe8fb19SBen Gras for (k = 0; k < 8; k++) {
8722fe8fb19SBen Gras if ((rdata[j] & (0x80 >> k)) == 0)
8732fe8fb19SBen Gras continue;
8742fe8fb19SBen Gras c = w * 256 + j * 8 + k;
8752fe8fb19SBen Gras len = SPRINTF((tmp, " %s", p_type((ns_type)c)));
8762fe8fb19SBen Gras T(addstr(tmp, (size_t)len, &buf, &buflen));
8772fe8fb19SBen Gras }
8782fe8fb19SBen Gras }
8792fe8fb19SBen Gras rdata += l;
8802fe8fb19SBen Gras }
8812fe8fb19SBen Gras break;
8822fe8fb19SBen Gras }
8832fe8fb19SBen Gras
8842fe8fb19SBen Gras case ns_t_dhcid: {
8852fe8fb19SBen Gras int n;
8862fe8fb19SBen Gras unsigned int siz;
8872fe8fb19SBen Gras char base64_dhcid[8192];
8882fe8fb19SBen Gras const char *leader;
8892fe8fb19SBen Gras
890*f14fb602SLionel Sambuc siz = (int)(edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */
8912fe8fb19SBen Gras if (siz > sizeof(base64_dhcid) * 3/4) {
8922fe8fb19SBen Gras const char *str = "record too long to print";
8932fe8fb19SBen Gras T(addstr(str, strlen(str), &buf, &buflen));
8942fe8fb19SBen Gras } else {
8952fe8fb19SBen Gras len = b64_ntop(rdata, (size_t)(edata-rdata),
8962fe8fb19SBen Gras base64_dhcid, siz);
8972fe8fb19SBen Gras
8982fe8fb19SBen Gras if (len < 0)
8992fe8fb19SBen Gras goto formerr;
9002fe8fb19SBen Gras
9012fe8fb19SBen Gras else if (len > 15) {
9022fe8fb19SBen Gras T(addstr(" (", 2, &buf, &buflen));
9032fe8fb19SBen Gras leader = "\n\t\t";
9042fe8fb19SBen Gras spaced = 0;
9052fe8fb19SBen Gras }
9062fe8fb19SBen Gras else
9072fe8fb19SBen Gras leader = " ";
9082fe8fb19SBen Gras
9092fe8fb19SBen Gras for (n = 0; n < len; n += 48) {
9102fe8fb19SBen Gras T(addstr(leader, strlen(leader),
9112fe8fb19SBen Gras &buf, &buflen));
9122fe8fb19SBen Gras T(addstr(base64_dhcid + n,
9132fe8fb19SBen Gras (size_t)MIN(len - n, 48), &buf, &buflen));
9142fe8fb19SBen Gras }
9152fe8fb19SBen Gras if (len > 15)
9162fe8fb19SBen Gras T(addstr(" )", 2, &buf, &buflen));
9172fe8fb19SBen Gras }
9182fe8fb19SBen Gras break;
9192fe8fb19SBen Gras }
9202fe8fb19SBen Gras
9212fe8fb19SBen Gras case ns_t_ipseckey: {
9222fe8fb19SBen Gras int n;
9232fe8fb19SBen Gras unsigned int siz;
9242fe8fb19SBen Gras char base64_key[8192];
9252fe8fb19SBen Gras const char *leader;
9262fe8fb19SBen Gras
9272fe8fb19SBen Gras if (rdlen < 2)
9282fe8fb19SBen Gras goto formerr;
9292fe8fb19SBen Gras
9302fe8fb19SBen Gras switch (rdata[1]) {
9312fe8fb19SBen Gras case 0:
9322fe8fb19SBen Gras case 3:
9332fe8fb19SBen Gras if (rdlen < 3)
9342fe8fb19SBen Gras goto formerr;
9352fe8fb19SBen Gras break;
9362fe8fb19SBen Gras case 1:
9372fe8fb19SBen Gras if (rdlen < 7)
9382fe8fb19SBen Gras goto formerr;
9392fe8fb19SBen Gras break;
9402fe8fb19SBen Gras case 2:
9412fe8fb19SBen Gras if (rdlen < 19)
9422fe8fb19SBen Gras goto formerr;
9432fe8fb19SBen Gras break;
9442fe8fb19SBen Gras default:
9452fe8fb19SBen Gras comment = "unknown IPSECKEY gateway type";
9462fe8fb19SBen Gras goto hexify;
9472fe8fb19SBen Gras }
9482fe8fb19SBen Gras
9492fe8fb19SBen Gras len = SPRINTF((tmp, "%u ", *rdata));
9502fe8fb19SBen Gras T(addstr(tmp, (size_t)len, &buf, &buflen));
9512fe8fb19SBen Gras rdata++;
9522fe8fb19SBen Gras
9532fe8fb19SBen Gras len = SPRINTF((tmp, "%u ", *rdata));
9542fe8fb19SBen Gras T(addstr(tmp, (size_t)len, &buf, &buflen));
9552fe8fb19SBen Gras rdata++;
9562fe8fb19SBen Gras
9572fe8fb19SBen Gras len = SPRINTF((tmp, "%u ", *rdata));
9582fe8fb19SBen Gras T(addstr(tmp, (size_t)len, &buf, &buflen));
9592fe8fb19SBen Gras rdata++;
9602fe8fb19SBen Gras
9612fe8fb19SBen Gras switch (rdata[-2]) {
9622fe8fb19SBen Gras case 0:
9632fe8fb19SBen Gras T(addstr(".", 1, &buf, &buflen));
9642fe8fb19SBen Gras break;
9652fe8fb19SBen Gras case 1:
966*f14fb602SLionel Sambuc (void) inet_ntop(AF_INET, rdata, buf, (socklen_t)buflen);
9672fe8fb19SBen Gras addlen(strlen(buf), &buf, &buflen);
9682fe8fb19SBen Gras rdata += 4;
9692fe8fb19SBen Gras break;
9702fe8fb19SBen Gras case 2:
971*f14fb602SLionel Sambuc (void) inet_ntop(AF_INET6, rdata, buf, (socklen_t)buflen);
9722fe8fb19SBen Gras addlen(strlen(buf), &buf, &buflen);
9732fe8fb19SBen Gras rdata += 16;
9742fe8fb19SBen Gras break;
9752fe8fb19SBen Gras case 3:
9762fe8fb19SBen Gras T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
9772fe8fb19SBen Gras break;
9782fe8fb19SBen Gras }
9792fe8fb19SBen Gras
9802fe8fb19SBen Gras if (rdata >= edata)
9812fe8fb19SBen Gras break;
9822fe8fb19SBen Gras
983*f14fb602SLionel Sambuc siz = (int)(edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */
9842fe8fb19SBen Gras if (siz > sizeof(base64_key) * 3/4) {
9852fe8fb19SBen Gras const char *str = "record too long to print";
9862fe8fb19SBen Gras T(addstr(str, strlen(str), &buf, &buflen));
9872fe8fb19SBen Gras } else {
9882fe8fb19SBen Gras len = b64_ntop(rdata, (size_t)(edata-rdata),
9892fe8fb19SBen Gras base64_key, siz);
9902fe8fb19SBen Gras
9912fe8fb19SBen Gras if (len < 0)
9922fe8fb19SBen Gras goto formerr;
9932fe8fb19SBen Gras
9942fe8fb19SBen Gras else if (len > 15) {
9952fe8fb19SBen Gras T(addstr(" (", 2, &buf, &buflen));
9962fe8fb19SBen Gras leader = "\n\t\t";
9972fe8fb19SBen Gras spaced = 0;
9982fe8fb19SBen Gras }
9992fe8fb19SBen Gras else
10002fe8fb19SBen Gras leader = " ";
10012fe8fb19SBen Gras
10022fe8fb19SBen Gras for (n = 0; n < len; n += 48) {
10032fe8fb19SBen Gras T(addstr(leader, strlen(leader),
10042fe8fb19SBen Gras &buf, &buflen));
10052fe8fb19SBen Gras T(addstr(base64_key + n,
10062fe8fb19SBen Gras (size_t)MIN(len - n, 48), &buf, &buflen));
10072fe8fb19SBen Gras }
10082fe8fb19SBen Gras if (len > 15)
10092fe8fb19SBen Gras T(addstr(" )", 2, &buf, &buflen));
10102fe8fb19SBen Gras }
10112fe8fb19SBen Gras break;
10122fe8fb19SBen Gras }
10132fe8fb19SBen Gras
10142fe8fb19SBen Gras case ns_t_hip: {
10152fe8fb19SBen Gras unsigned int i, hip_len, algorithm, key_len;
10162fe8fb19SBen Gras char base64_key[NS_MD5RSA_MAX_BASE64];
10172fe8fb19SBen Gras unsigned int siz;
10182fe8fb19SBen Gras const char *leader = "\n\t\t\t\t\t";
10192fe8fb19SBen Gras
10202fe8fb19SBen Gras hip_len = *rdata++;
10212fe8fb19SBen Gras algorithm = *rdata++;
10222fe8fb19SBen Gras key_len = ns_get16(rdata);
10232fe8fb19SBen Gras rdata += NS_INT16SZ;
10242fe8fb19SBen Gras
10252fe8fb19SBen Gras siz = key_len*4/3 + 4; /* "+4" accounts for trailing \0 */
10262fe8fb19SBen Gras if (siz > sizeof(base64_key) * 3/4) {
10272fe8fb19SBen Gras const char *str = "record too long to print";
10282fe8fb19SBen Gras T(addstr(str, strlen(str), &buf, &buflen));
10292fe8fb19SBen Gras } else {
10302fe8fb19SBen Gras len = sprintf(tmp, "( %u ", algorithm);
10312fe8fb19SBen Gras T(addstr(tmp, (size_t)len, &buf, &buflen));
10322fe8fb19SBen Gras
10332fe8fb19SBen Gras for (i = 0; i < hip_len; i++) {
10342fe8fb19SBen Gras len = sprintf(tmp, "%02X", *rdata);
10352fe8fb19SBen Gras T(addstr(tmp, (size_t)len, &buf, &buflen));
10362fe8fb19SBen Gras rdata++;
10372fe8fb19SBen Gras }
10382fe8fb19SBen Gras T(addstr(leader, strlen(leader), &buf, &buflen));
10392fe8fb19SBen Gras
10402fe8fb19SBen Gras len = b64_ntop(rdata, key_len, base64_key, siz);
10412fe8fb19SBen Gras if (len < 0)
10422fe8fb19SBen Gras goto formerr;
10432fe8fb19SBen Gras
10442fe8fb19SBen Gras T(addstr(base64_key, (size_t)len, &buf, &buflen));
10452fe8fb19SBen Gras
10462fe8fb19SBen Gras rdata += key_len;
10472fe8fb19SBen Gras while (rdata < edata) {
10482fe8fb19SBen Gras T(addstr(leader, strlen(leader), &buf, &buflen));
10492fe8fb19SBen Gras T(addname(msg, msglen, &rdata, origin,
10502fe8fb19SBen Gras &buf, &buflen));
10512fe8fb19SBen Gras }
10522fe8fb19SBen Gras T(addstr(" )", 2, &buf, &buflen));
10532fe8fb19SBen Gras }
10542fe8fb19SBen Gras break;
10552fe8fb19SBen Gras }
10562fe8fb19SBen Gras
10572fe8fb19SBen Gras default:
10582fe8fb19SBen Gras comment = "unknown RR type";
10592fe8fb19SBen Gras goto hexify;
10602fe8fb19SBen Gras }
1061*f14fb602SLionel Sambuc _DIAGASSERT(__type_fit(int, buf - obuf));
1062*f14fb602SLionel Sambuc return (int)(buf - obuf);
10632fe8fb19SBen Gras formerr:
10642fe8fb19SBen Gras comment = "RR format error";
10652fe8fb19SBen Gras hexify: {
10662fe8fb19SBen Gras int n, m;
10672fe8fb19SBen Gras char *p;
10682fe8fb19SBen Gras
10692fe8fb19SBen Gras len = SPRINTF((tmp, "\\# %u%s\t; %s", (unsigned)(edata - rdata),
10702fe8fb19SBen Gras rdlen != 0U ? " (" : "", comment));
10712fe8fb19SBen Gras T(addstr(tmp, (size_t)len, &buf, &buflen));
10722fe8fb19SBen Gras while (rdata < edata) {
10732fe8fb19SBen Gras p = tmp;
10742fe8fb19SBen Gras p += SPRINTF((p, "\n\t"));
10752fe8fb19SBen Gras spaced = 0;
1076*f14fb602SLionel Sambuc n = MIN(16, (int)(edata - rdata));
10772fe8fb19SBen Gras for (m = 0; m < n; m++)
10782fe8fb19SBen Gras p += SPRINTF((p, "%02x ", rdata[m]));
10792fe8fb19SBen Gras T(addstr(tmp, (size_t)(p - tmp), &buf, &buflen));
10802fe8fb19SBen Gras if (n < 16) {
10812fe8fb19SBen Gras T(addstr(")", (size_t)1, &buf, &buflen));
10822fe8fb19SBen Gras T(addtab((size_t)(p - tmp + 1), (size_t)48, spaced, &buf, &buflen));
10832fe8fb19SBen Gras }
10842fe8fb19SBen Gras p = tmp;
10852fe8fb19SBen Gras p += SPRINTF((p, "; "));
10862fe8fb19SBen Gras for (m = 0; m < n; m++)
10872fe8fb19SBen Gras *p++ = (isascii(rdata[m]) && isprint(rdata[m]))
10882fe8fb19SBen Gras ? rdata[m]
10892fe8fb19SBen Gras : '.';
10902fe8fb19SBen Gras T(addstr(tmp, (size_t)(p - tmp), &buf, &buflen));
10912fe8fb19SBen Gras rdata += n;
10922fe8fb19SBen Gras }
1093*f14fb602SLionel Sambuc _DIAGASSERT(__type_fit(int, buf - obuf));
1094*f14fb602SLionel Sambuc return (int)(buf - obuf);
10952fe8fb19SBen Gras }
10962fe8fb19SBen Gras }
10972fe8fb19SBen Gras
10982fe8fb19SBen Gras /* Private. */
10992fe8fb19SBen Gras
11002fe8fb19SBen Gras /*%
11012fe8fb19SBen Gras * size_t
11022fe8fb19SBen Gras * prune_origin(name, origin)
11032fe8fb19SBen Gras * Find out if the name is at or under the current origin.
11042fe8fb19SBen Gras * return:
11052fe8fb19SBen Gras * Number of characters in name before start of origin,
11062fe8fb19SBen Gras * or length of name if origin does not match.
11072fe8fb19SBen Gras * notes:
11082fe8fb19SBen Gras * This function should share code with samedomain().
11092fe8fb19SBen Gras */
11102fe8fb19SBen Gras static size_t
prune_origin(const char * name,const char * origin)11112fe8fb19SBen Gras prune_origin(const char *name, const char *origin) {
11122fe8fb19SBen Gras const char *oname = name;
11132fe8fb19SBen Gras
11142fe8fb19SBen Gras while (*name != '\0') {
11152fe8fb19SBen Gras if (origin != NULL && ns_samename(name, origin) == 1)
11162fe8fb19SBen Gras return (name - oname - (name > oname));
11172fe8fb19SBen Gras while (*name != '\0') {
11182fe8fb19SBen Gras if (*name == '\\') {
11192fe8fb19SBen Gras name++;
11202fe8fb19SBen Gras /* XXX need to handle \nnn form. */
11212fe8fb19SBen Gras if (*name == '\0')
11222fe8fb19SBen Gras break;
11232fe8fb19SBen Gras } else if (*name == '.') {
11242fe8fb19SBen Gras name++;
11252fe8fb19SBen Gras break;
11262fe8fb19SBen Gras }
11272fe8fb19SBen Gras name++;
11282fe8fb19SBen Gras }
11292fe8fb19SBen Gras }
11302fe8fb19SBen Gras return (name - oname);
11312fe8fb19SBen Gras }
11322fe8fb19SBen Gras
11332fe8fb19SBen Gras /*%
11342fe8fb19SBen Gras * int
11352fe8fb19SBen Gras * charstr(rdata, edata, buf, buflen)
11362fe8fb19SBen Gras * Format a <character-string> into the presentation buffer.
11372fe8fb19SBen Gras * return:
11382fe8fb19SBen Gras * Number of rdata octets consumed
11392fe8fb19SBen Gras * 0 for protocol format error
11402fe8fb19SBen Gras * -1 for output buffer error
11412fe8fb19SBen Gras * side effects:
11422fe8fb19SBen Gras * buffer is advanced on success.
11432fe8fb19SBen Gras */
11442fe8fb19SBen Gras static int
charstr(const u_char * rdata,const u_char * edata,char ** buf,size_t * buflen)11452fe8fb19SBen Gras charstr(const u_char *rdata, const u_char *edata, char **buf, size_t *buflen) {
11462fe8fb19SBen Gras const u_char *odata = rdata;
11472fe8fb19SBen Gras size_t save_buflen = *buflen;
11482fe8fb19SBen Gras char *save_buf = *buf;
11492fe8fb19SBen Gras
11502fe8fb19SBen Gras if (addstr("\"", (size_t)1, buf, buflen) < 0)
11512fe8fb19SBen Gras goto enospc;
11522fe8fb19SBen Gras if (rdata < edata) {
11532fe8fb19SBen Gras int n = *rdata;
11542fe8fb19SBen Gras
11552fe8fb19SBen Gras if (rdata + 1 + n <= edata) {
11562fe8fb19SBen Gras rdata++;
11572fe8fb19SBen Gras while (n-- > 0) {
11582fe8fb19SBen Gras if (strchr("\n\"\\", *rdata) != NULL)
11592fe8fb19SBen Gras if (addstr("\\", (size_t)1, buf, buflen) < 0)
11602fe8fb19SBen Gras goto enospc;
11612fe8fb19SBen Gras if (addstr((const char *)rdata, (size_t)1,
11622fe8fb19SBen Gras buf, buflen) < 0)
11632fe8fb19SBen Gras goto enospc;
11642fe8fb19SBen Gras rdata++;
11652fe8fb19SBen Gras }
11662fe8fb19SBen Gras }
11672fe8fb19SBen Gras }
11682fe8fb19SBen Gras if (addstr("\"", (size_t)1, buf, buflen) < 0)
11692fe8fb19SBen Gras goto enospc;
1170*f14fb602SLionel Sambuc _DIAGASSERT(__type_fit(int, rdata - odata));
1171*f14fb602SLionel Sambuc return (int)(rdata - odata);
11722fe8fb19SBen Gras enospc:
11732fe8fb19SBen Gras errno = ENOSPC;
11742fe8fb19SBen Gras *buf = save_buf;
11752fe8fb19SBen Gras *buflen = save_buflen;
11762fe8fb19SBen Gras return (-1);
11772fe8fb19SBen Gras }
11782fe8fb19SBen Gras
11792fe8fb19SBen Gras static int
addname(const u_char * msg,size_t msglen,const u_char ** pp,const char * origin,char ** buf,size_t * buflen)11802fe8fb19SBen Gras addname(const u_char *msg, size_t msglen,
11812fe8fb19SBen Gras const u_char **pp, const char *origin,
11822fe8fb19SBen Gras char **buf, size_t *buflen)
11832fe8fb19SBen Gras {
11842fe8fb19SBen Gras size_t newlen, save_buflen = *buflen;
11852fe8fb19SBen Gras char *save_buf = *buf;
11862fe8fb19SBen Gras int n;
11872fe8fb19SBen Gras
11882fe8fb19SBen Gras n = dn_expand(msg, msg + msglen, *pp, *buf, (int)*buflen);
11892fe8fb19SBen Gras if (n < 0)
11902fe8fb19SBen Gras goto enospc; /*%< Guess. */
11912fe8fb19SBen Gras newlen = prune_origin(*buf, origin);
11922fe8fb19SBen Gras if (**buf == '\0') {
11932fe8fb19SBen Gras goto root;
11942fe8fb19SBen Gras } else if (newlen == 0U) {
11952fe8fb19SBen Gras /* Use "@" instead of name. */
11962fe8fb19SBen Gras if (newlen + 2 > *buflen)
11972fe8fb19SBen Gras goto enospc; /* No room for "@\0". */
11982fe8fb19SBen Gras (*buf)[newlen++] = '@';
11992fe8fb19SBen Gras (*buf)[newlen] = '\0';
12002fe8fb19SBen Gras } else {
12012fe8fb19SBen Gras if (((origin == NULL || origin[0] == '\0') ||
12022fe8fb19SBen Gras (origin[0] != '.' && origin[1] != '\0' &&
12032fe8fb19SBen Gras (*buf)[newlen] == '\0')) && (*buf)[newlen - 1] != '.') {
12042fe8fb19SBen Gras /* No trailing dot. */
12052fe8fb19SBen Gras root:
12062fe8fb19SBen Gras if (newlen + 2 > *buflen)
12072fe8fb19SBen Gras goto enospc; /* No room for ".\0". */
12082fe8fb19SBen Gras (*buf)[newlen++] = '.';
12092fe8fb19SBen Gras (*buf)[newlen] = '\0';
12102fe8fb19SBen Gras }
12112fe8fb19SBen Gras }
12122fe8fb19SBen Gras *pp += n;
12132fe8fb19SBen Gras addlen(newlen, buf, buflen);
12142fe8fb19SBen Gras **buf = '\0';
1215*f14fb602SLionel Sambuc _DIAGASSERT(__type_fit(int, newlen));
1216*f14fb602SLionel Sambuc return (int)newlen;
12172fe8fb19SBen Gras enospc:
12182fe8fb19SBen Gras errno = ENOSPC;
12192fe8fb19SBen Gras *buf = save_buf;
12202fe8fb19SBen Gras *buflen = save_buflen;
12212fe8fb19SBen Gras return (-1);
12222fe8fb19SBen Gras }
12232fe8fb19SBen Gras
12242fe8fb19SBen Gras static void
addlen(size_t len,char ** buf,size_t * buflen)12252fe8fb19SBen Gras addlen(size_t len, char **buf, size_t *buflen) {
12262fe8fb19SBen Gras INSIST(len <= *buflen);
12272fe8fb19SBen Gras *buf += len;
12282fe8fb19SBen Gras *buflen -= len;
12292fe8fb19SBen Gras }
12302fe8fb19SBen Gras
12312fe8fb19SBen Gras static int
addstr(const char * src,size_t len,char ** buf,size_t * buflen)12322fe8fb19SBen Gras addstr(const char *src, size_t len, char **buf, size_t *buflen) {
12332fe8fb19SBen Gras if (len >= *buflen) {
12342fe8fb19SBen Gras errno = ENOSPC;
12352fe8fb19SBen Gras return (-1);
12362fe8fb19SBen Gras }
12372fe8fb19SBen Gras memcpy(*buf, src, len);
12382fe8fb19SBen Gras addlen(len, buf, buflen);
12392fe8fb19SBen Gras **buf = '\0';
12402fe8fb19SBen Gras return (0);
12412fe8fb19SBen Gras }
12422fe8fb19SBen Gras
12432fe8fb19SBen Gras static int
addtab(size_t len,size_t target,int spaced,char ** buf,size_t * buflen)12442fe8fb19SBen Gras addtab(size_t len, size_t target, int spaced, char **buf, size_t *buflen) {
12452fe8fb19SBen Gras size_t save_buflen = *buflen;
12462fe8fb19SBen Gras char *save_buf = *buf;
1247*f14fb602SLionel Sambuc ptrdiff_t t;
12482fe8fb19SBen Gras
12492fe8fb19SBen Gras if (spaced || len >= target - 1) {
12502fe8fb19SBen Gras T(addstr(" ", (size_t)2, buf, buflen));
12512fe8fb19SBen Gras spaced = 1;
12522fe8fb19SBen Gras } else {
12532fe8fb19SBen Gras for (t = (target - len - 1) / 8; t >= 0; t--)
12542fe8fb19SBen Gras if (addstr("\t", (size_t)1, buf, buflen) < 0) {
12552fe8fb19SBen Gras *buflen = save_buflen;
12562fe8fb19SBen Gras *buf = save_buf;
12572fe8fb19SBen Gras return (-1);
12582fe8fb19SBen Gras }
12592fe8fb19SBen Gras spaced = 0;
12602fe8fb19SBen Gras }
12612fe8fb19SBen Gras return (spaced);
12622fe8fb19SBen Gras }
12632fe8fb19SBen Gras
12642fe8fb19SBen Gras /*! \file */
1265