1156952Sume/* 2156952Sume * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 3156952Sume * Copyright (c) 1996-1999 by Internet Software Consortium. 4156952Sume * 5156952Sume * Permission to use, copy, modify, and distribute this software for any 6156952Sume * purpose with or without fee is hereby granted, provided that the above 7156952Sume * copyright notice and this permission notice appear in all copies. 8156952Sume * 9156952Sume * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 10156952Sume * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11156952Sume * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 12156952Sume * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13156952Sume * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14156952Sume * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 15156952Sume * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16156952Sume */ 17156952Sume 18156952Sume#ifndef lint 19269867Sumestatic const char rcsid[] = "$Id: ns_print.c,v 1.12 2009/03/03 05:29:58 each Exp $"; 20156952Sume#endif 21156956Sume#include <sys/cdefs.h> 22156956Sume__FBSDID("$FreeBSD$"); 23156952Sume 24156952Sume/* Import. */ 25156952Sume 26156952Sume#include "port_before.h" 27156952Sume 28156952Sume#include <sys/types.h> 29156952Sume#include <sys/socket.h> 30156952Sume 31156952Sume#include <netinet/in.h> 32156952Sume#include <arpa/nameser.h> 33156952Sume#include <arpa/inet.h> 34156952Sume 35156956Sume#ifdef _LIBC 36156956Sume#include <assert.h> 37156956Sume#define INSIST(cond) assert(cond) 38156956Sume#else 39156952Sume#include <isc/assertions.h> 40156952Sume#include <isc/dst.h> 41156956Sume#endif 42156952Sume#include <errno.h> 43156952Sume#include <resolv.h> 44156952Sume#include <string.h> 45156952Sume#include <ctype.h> 46156952Sume 47156952Sume#include "port_after.h" 48156952Sume 49156952Sume#ifdef SPRINTF_CHAR 50156952Sume# define SPRINTF(x) strlen(sprintf/**/x) 51156952Sume#else 52156952Sume# define SPRINTF(x) ((size_t)sprintf x) 53156952Sume#endif 54156952Sume 55156952Sume/* Forward. */ 56156952Sume 57156952Sumestatic size_t prune_origin(const char *name, const char *origin); 58156952Sumestatic int charstr(const u_char *rdata, const u_char *edata, 59156952Sume char **buf, size_t *buflen); 60156952Sumestatic int addname(const u_char *msg, size_t msglen, 61156952Sume const u_char **p, const char *origin, 62156952Sume char **buf, size_t *buflen); 63156952Sumestatic void addlen(size_t len, char **buf, size_t *buflen); 64156952Sumestatic int addstr(const char *src, size_t len, 65156952Sume char **buf, size_t *buflen); 66156952Sumestatic int addtab(size_t len, size_t target, int spaced, 67156952Sume char **buf, size_t *buflen); 68156952Sume 69156952Sume/* Macros. */ 70156952Sume 71156952Sume#define T(x) \ 72156952Sume do { \ 73156952Sume if ((x) < 0) \ 74156952Sume return (-1); \ 75156952Sume } while (0) 76156952Sume 77269867Sumestatic const char base32hex[] = 78269867Sume "0123456789ABCDEFGHIJKLMNOPQRSTUV=0123456789abcdefghijklmnopqrstuv"; 79269867Sume 80156952Sume/* Public. */ 81156952Sume 82170244Sume/*% 83156952Sume * Convert an RR to presentation format. 84170244Sume * 85156952Sume * return: 86170244Sume *\li Number of characters written to buf, or -1 (check errno). 87156952Sume */ 88156952Sumeint 89156952Sumens_sprintrr(const ns_msg *handle, const ns_rr *rr, 90156952Sume const char *name_ctx, const char *origin, 91156952Sume char *buf, size_t buflen) 92156952Sume{ 93156952Sume int n; 94156952Sume 95156952Sume n = ns_sprintrrf(ns_msg_base(*handle), ns_msg_size(*handle), 96156952Sume ns_rr_name(*rr), ns_rr_class(*rr), ns_rr_type(*rr), 97156952Sume ns_rr_ttl(*rr), ns_rr_rdata(*rr), ns_rr_rdlen(*rr), 98156952Sume name_ctx, origin, buf, buflen); 99156952Sume return (n); 100156952Sume} 101156952Sume 102170244Sume/*% 103156952Sume * Convert the fields of an RR into presentation format. 104170244Sume * 105156952Sume * return: 106170244Sume *\li Number of characters written to buf, or -1 (check errno). 107156952Sume */ 108156952Sumeint 109156952Sumens_sprintrrf(const u_char *msg, size_t msglen, 110156952Sume const char *name, ns_class class, ns_type type, 111156952Sume u_long ttl, const u_char *rdata, size_t rdlen, 112156952Sume const char *name_ctx, const char *origin, 113156952Sume char *buf, size_t buflen) 114156952Sume{ 115156952Sume const char *obuf = buf; 116156952Sume const u_char *edata = rdata + rdlen; 117156952Sume int spaced = 0; 118156952Sume 119156952Sume const char *comment; 120156952Sume char tmp[100]; 121156952Sume int len, x; 122156952Sume 123156952Sume /* 124156952Sume * Owner. 125156952Sume */ 126156952Sume if (name_ctx != NULL && ns_samename(name_ctx, name) == 1) { 127156952Sume T(addstr("\t\t\t", 3, &buf, &buflen)); 128156952Sume } else { 129156952Sume len = prune_origin(name, origin); 130156952Sume if (*name == '\0') { 131156952Sume goto root; 132156952Sume } else if (len == 0) { 133156952Sume T(addstr("@\t\t\t", 4, &buf, &buflen)); 134156952Sume } else { 135156952Sume T(addstr(name, len, &buf, &buflen)); 136156952Sume /* Origin not used or not root, and no trailing dot? */ 137156952Sume if (((origin == NULL || origin[0] == '\0') || 138156952Sume (origin[0] != '.' && origin[1] != '\0' && 139156952Sume name[len] == '\0')) && name[len - 1] != '.') { 140156952Sume root: 141156952Sume T(addstr(".", 1, &buf, &buflen)); 142156952Sume len++; 143156952Sume } 144156952Sume T(spaced = addtab(len, 24, spaced, &buf, &buflen)); 145156952Sume } 146156952Sume } 147156952Sume 148156952Sume /* 149156952Sume * TTL, Class, Type. 150156952Sume */ 151156952Sume T(x = ns_format_ttl(ttl, buf, buflen)); 152156952Sume addlen(x, &buf, &buflen); 153156952Sume len = SPRINTF((tmp, " %s %s", p_class(class), p_type(type))); 154156952Sume T(addstr(tmp, len, &buf, &buflen)); 155156952Sume T(spaced = addtab(x + len, 16, spaced, &buf, &buflen)); 156156952Sume 157156952Sume /* 158156952Sume * RData. 159156952Sume */ 160156952Sume switch (type) { 161156952Sume case ns_t_a: 162156952Sume if (rdlen != (size_t)NS_INADDRSZ) 163156952Sume goto formerr; 164156952Sume (void) inet_ntop(AF_INET, rdata, buf, buflen); 165156952Sume addlen(strlen(buf), &buf, &buflen); 166156952Sume break; 167156952Sume 168156952Sume case ns_t_cname: 169156952Sume case ns_t_mb: 170156952Sume case ns_t_mg: 171156952Sume case ns_t_mr: 172156952Sume case ns_t_ns: 173156952Sume case ns_t_ptr: 174156952Sume case ns_t_dname: 175156952Sume T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 176156952Sume break; 177156952Sume 178156952Sume case ns_t_hinfo: 179156952Sume case ns_t_isdn: 180156952Sume /* First word. */ 181156952Sume T(len = charstr(rdata, edata, &buf, &buflen)); 182156952Sume if (len == 0) 183156952Sume goto formerr; 184156952Sume rdata += len; 185156952Sume T(addstr(" ", 1, &buf, &buflen)); 186156952Sume 187156952Sume 188156952Sume /* Second word, optional in ISDN records. */ 189156952Sume if (type == ns_t_isdn && rdata == edata) 190156952Sume break; 191156952Sume 192156952Sume T(len = charstr(rdata, edata, &buf, &buflen)); 193156952Sume if (len == 0) 194156952Sume goto formerr; 195156952Sume rdata += len; 196156952Sume break; 197156952Sume 198156952Sume case ns_t_soa: { 199156952Sume u_long t; 200156952Sume 201156952Sume /* Server name. */ 202156952Sume T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 203156952Sume T(addstr(" ", 1, &buf, &buflen)); 204156952Sume 205156952Sume /* Administrator name. */ 206156952Sume T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 207156952Sume T(addstr(" (\n", 3, &buf, &buflen)); 208156952Sume spaced = 0; 209156952Sume 210156952Sume if ((edata - rdata) != 5*NS_INT32SZ) 211156952Sume goto formerr; 212156952Sume 213156952Sume /* Serial number. */ 214156952Sume t = ns_get32(rdata); rdata += NS_INT32SZ; 215156952Sume T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); 216156952Sume len = SPRINTF((tmp, "%lu", t)); 217156952Sume T(addstr(tmp, len, &buf, &buflen)); 218156952Sume T(spaced = addtab(len, 16, spaced, &buf, &buflen)); 219156952Sume T(addstr("; serial\n", 9, &buf, &buflen)); 220156952Sume spaced = 0; 221156952Sume 222156952Sume /* Refresh interval. */ 223156952Sume t = ns_get32(rdata); rdata += NS_INT32SZ; 224156952Sume T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); 225156952Sume T(len = ns_format_ttl(t, buf, buflen)); 226156952Sume addlen(len, &buf, &buflen); 227156952Sume T(spaced = addtab(len, 16, spaced, &buf, &buflen)); 228156952Sume T(addstr("; refresh\n", 10, &buf, &buflen)); 229156952Sume spaced = 0; 230156952Sume 231156952Sume /* Retry interval. */ 232156952Sume t = ns_get32(rdata); rdata += NS_INT32SZ; 233156952Sume T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); 234156952Sume T(len = ns_format_ttl(t, buf, buflen)); 235156952Sume addlen(len, &buf, &buflen); 236156952Sume T(spaced = addtab(len, 16, spaced, &buf, &buflen)); 237156952Sume T(addstr("; retry\n", 8, &buf, &buflen)); 238156952Sume spaced = 0; 239156952Sume 240156952Sume /* Expiry. */ 241156952Sume t = ns_get32(rdata); rdata += NS_INT32SZ; 242156952Sume T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); 243156952Sume T(len = ns_format_ttl(t, buf, buflen)); 244156952Sume addlen(len, &buf, &buflen); 245156952Sume T(spaced = addtab(len, 16, spaced, &buf, &buflen)); 246156952Sume T(addstr("; expiry\n", 9, &buf, &buflen)); 247156952Sume spaced = 0; 248156952Sume 249156952Sume /* Minimum TTL. */ 250156952Sume t = ns_get32(rdata); rdata += NS_INT32SZ; 251156952Sume T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); 252156952Sume T(len = ns_format_ttl(t, buf, buflen)); 253156952Sume addlen(len, &buf, &buflen); 254156952Sume T(addstr(" )", 2, &buf, &buflen)); 255156952Sume T(spaced = addtab(len, 16, spaced, &buf, &buflen)); 256156952Sume T(addstr("; minimum\n", 10, &buf, &buflen)); 257156952Sume 258156952Sume break; 259156952Sume } 260156952Sume 261156952Sume case ns_t_mx: 262156952Sume case ns_t_afsdb: 263269867Sume case ns_t_rt: 264269867Sume case ns_t_kx: { 265156952Sume u_int t; 266156952Sume 267156952Sume if (rdlen < (size_t)NS_INT16SZ) 268156952Sume goto formerr; 269156952Sume 270156952Sume /* Priority. */ 271156952Sume t = ns_get16(rdata); 272156952Sume rdata += NS_INT16SZ; 273156952Sume len = SPRINTF((tmp, "%u ", t)); 274156952Sume T(addstr(tmp, len, &buf, &buflen)); 275156952Sume 276156952Sume /* Target. */ 277156952Sume T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 278156952Sume 279156952Sume break; 280156952Sume } 281156952Sume 282156952Sume case ns_t_px: { 283156952Sume u_int t; 284156952Sume 285156952Sume if (rdlen < (size_t)NS_INT16SZ) 286156952Sume goto formerr; 287156952Sume 288156952Sume /* Priority. */ 289156952Sume t = ns_get16(rdata); 290156952Sume rdata += NS_INT16SZ; 291156952Sume len = SPRINTF((tmp, "%u ", t)); 292156952Sume T(addstr(tmp, len, &buf, &buflen)); 293156952Sume 294156952Sume /* Name1. */ 295156952Sume T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 296156952Sume T(addstr(" ", 1, &buf, &buflen)); 297156952Sume 298156952Sume /* Name2. */ 299156952Sume T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 300156952Sume 301156952Sume break; 302156952Sume } 303156952Sume 304156952Sume case ns_t_x25: 305156952Sume T(len = charstr(rdata, edata, &buf, &buflen)); 306156952Sume if (len == 0) 307156952Sume goto formerr; 308156952Sume rdata += len; 309156952Sume break; 310156952Sume 311156952Sume case ns_t_txt: 312269867Sume case ns_t_spf: 313156952Sume while (rdata < edata) { 314156952Sume T(len = charstr(rdata, edata, &buf, &buflen)); 315156952Sume if (len == 0) 316156952Sume goto formerr; 317156952Sume rdata += len; 318156952Sume if (rdata < edata) 319156952Sume T(addstr(" ", 1, &buf, &buflen)); 320156952Sume } 321156952Sume break; 322156952Sume 323156952Sume case ns_t_nsap: { 324156952Sume char t[2+255*3]; 325156952Sume 326156952Sume (void) inet_nsap_ntoa(rdlen, rdata, t); 327156952Sume T(addstr(t, strlen(t), &buf, &buflen)); 328156952Sume break; 329156952Sume } 330156952Sume 331156952Sume case ns_t_aaaa: 332156952Sume if (rdlen != (size_t)NS_IN6ADDRSZ) 333156952Sume goto formerr; 334156952Sume (void) inet_ntop(AF_INET6, rdata, buf, buflen); 335156952Sume addlen(strlen(buf), &buf, &buflen); 336156952Sume break; 337156952Sume 338156952Sume case ns_t_loc: { 339156952Sume char t[255]; 340156952Sume 341156952Sume /* XXX protocol format checking? */ 342156952Sume (void) loc_ntoa(rdata, t); 343156952Sume T(addstr(t, strlen(t), &buf, &buflen)); 344156952Sume break; 345156952Sume } 346156952Sume 347156952Sume case ns_t_naptr: { 348156952Sume u_int order, preference; 349156952Sume char t[50]; 350156952Sume 351156952Sume if (rdlen < 2U*NS_INT16SZ) 352156952Sume goto formerr; 353156952Sume 354156952Sume /* Order, Precedence. */ 355156952Sume order = ns_get16(rdata); rdata += NS_INT16SZ; 356156952Sume preference = ns_get16(rdata); rdata += NS_INT16SZ; 357156952Sume len = SPRINTF((t, "%u %u ", order, preference)); 358156952Sume T(addstr(t, len, &buf, &buflen)); 359156952Sume 360156952Sume /* Flags. */ 361156952Sume T(len = charstr(rdata, edata, &buf, &buflen)); 362156952Sume if (len == 0) 363156952Sume goto formerr; 364156952Sume rdata += len; 365156952Sume T(addstr(" ", 1, &buf, &buflen)); 366156952Sume 367156952Sume /* Service. */ 368156952Sume T(len = charstr(rdata, edata, &buf, &buflen)); 369156952Sume if (len == 0) 370156952Sume goto formerr; 371156952Sume rdata += len; 372156952Sume T(addstr(" ", 1, &buf, &buflen)); 373156952Sume 374156952Sume /* Regexp. */ 375156952Sume T(len = charstr(rdata, edata, &buf, &buflen)); 376156952Sume if (len < 0) 377156952Sume return (-1); 378156952Sume if (len == 0) 379156952Sume goto formerr; 380156952Sume rdata += len; 381156952Sume T(addstr(" ", 1, &buf, &buflen)); 382156952Sume 383156952Sume /* Server. */ 384156952Sume T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 385156952Sume break; 386156952Sume } 387156952Sume 388156952Sume case ns_t_srv: { 389156952Sume u_int priority, weight, port; 390156952Sume char t[50]; 391156952Sume 392156952Sume if (rdlen < 3U*NS_INT16SZ) 393156952Sume goto formerr; 394156952Sume 395156952Sume /* Priority, Weight, Port. */ 396156952Sume priority = ns_get16(rdata); rdata += NS_INT16SZ; 397156952Sume weight = ns_get16(rdata); rdata += NS_INT16SZ; 398156952Sume port = ns_get16(rdata); rdata += NS_INT16SZ; 399156952Sume len = SPRINTF((t, "%u %u %u ", priority, weight, port)); 400156952Sume T(addstr(t, len, &buf, &buflen)); 401156952Sume 402156952Sume /* Server. */ 403156952Sume T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 404156952Sume break; 405156952Sume } 406156952Sume 407156952Sume case ns_t_minfo: 408156952Sume case ns_t_rp: 409156952Sume /* Name1. */ 410156952Sume T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 411156952Sume T(addstr(" ", 1, &buf, &buflen)); 412156952Sume 413156952Sume /* Name2. */ 414156952Sume T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 415156952Sume 416156952Sume break; 417156952Sume 418156952Sume case ns_t_wks: { 419156952Sume int n, lcnt; 420156952Sume 421156952Sume if (rdlen < 1U + NS_INT32SZ) 422156952Sume goto formerr; 423156952Sume 424156952Sume /* Address. */ 425156952Sume (void) inet_ntop(AF_INET, rdata, buf, buflen); 426156952Sume addlen(strlen(buf), &buf, &buflen); 427156952Sume rdata += NS_INADDRSZ; 428156952Sume 429156952Sume /* Protocol. */ 430156952Sume len = SPRINTF((tmp, " %u ( ", *rdata)); 431156952Sume T(addstr(tmp, len, &buf, &buflen)); 432156952Sume rdata += NS_INT8SZ; 433156952Sume 434156952Sume /* Bit map. */ 435156952Sume n = 0; 436156952Sume lcnt = 0; 437156952Sume while (rdata < edata) { 438156952Sume u_int c = *rdata++; 439156952Sume do { 440156952Sume if (c & 0200) { 441156952Sume if (lcnt == 0) { 442156952Sume T(addstr("\n\t\t\t\t", 5, 443156952Sume &buf, &buflen)); 444156952Sume lcnt = 10; 445156952Sume spaced = 0; 446156952Sume } 447156952Sume len = SPRINTF((tmp, "%d ", n)); 448156952Sume T(addstr(tmp, len, &buf, &buflen)); 449156952Sume lcnt--; 450156952Sume } 451156952Sume c <<= 1; 452156952Sume } while (++n & 07); 453156952Sume } 454156952Sume T(addstr(")", 1, &buf, &buflen)); 455156952Sume 456156952Sume break; 457156952Sume } 458156952Sume 459269867Sume case ns_t_key: 460269867Sume case ns_t_dnskey: { 461156952Sume char base64_key[NS_MD5RSA_MAX_BASE64]; 462156952Sume u_int keyflags, protocol, algorithm, key_id; 463156952Sume const char *leader; 464156952Sume int n; 465156952Sume 466156952Sume if (rdlen < 0U + NS_INT16SZ + NS_INT8SZ + NS_INT8SZ) 467156952Sume goto formerr; 468156952Sume 469156952Sume /* Key flags, Protocol, Algorithm. */ 470156956Sume#ifndef _LIBC 471156952Sume key_id = dst_s_dns_key_id(rdata, edata-rdata); 472156956Sume#else 473156956Sume key_id = 0; 474156956Sume#endif 475156952Sume keyflags = ns_get16(rdata); rdata += NS_INT16SZ; 476156952Sume protocol = *rdata++; 477156952Sume algorithm = *rdata++; 478156952Sume len = SPRINTF((tmp, "0x%04x %u %u", 479156952Sume keyflags, protocol, algorithm)); 480156952Sume T(addstr(tmp, len, &buf, &buflen)); 481156952Sume 482156952Sume /* Public key data. */ 483156952Sume len = b64_ntop(rdata, edata - rdata, 484156952Sume base64_key, sizeof base64_key); 485156952Sume if (len < 0) 486156952Sume goto formerr; 487156952Sume if (len > 15) { 488156952Sume T(addstr(" (", 2, &buf, &buflen)); 489156952Sume leader = "\n\t\t"; 490156952Sume spaced = 0; 491156952Sume } else 492156952Sume leader = " "; 493156952Sume for (n = 0; n < len; n += 48) { 494156952Sume T(addstr(leader, strlen(leader), &buf, &buflen)); 495156952Sume T(addstr(base64_key + n, MIN(len - n, 48), 496156952Sume &buf, &buflen)); 497156952Sume } 498156952Sume if (len > 15) 499156952Sume T(addstr(" )", 2, &buf, &buflen)); 500156952Sume n = SPRINTF((tmp, " ; key_tag= %u", key_id)); 501156952Sume T(addstr(tmp, n, &buf, &buflen)); 502156952Sume 503156952Sume break; 504156952Sume } 505156952Sume 506269867Sume case ns_t_sig: 507269867Sume case ns_t_rrsig: { 508156952Sume char base64_key[NS_MD5RSA_MAX_BASE64]; 509156952Sume u_int type, algorithm, labels, footprint; 510156952Sume const char *leader; 511156952Sume u_long t; 512156952Sume int n; 513156952Sume 514156952Sume if (rdlen < 22U) 515156952Sume goto formerr; 516156952Sume 517156952Sume /* Type covered, Algorithm, Label count, Original TTL. */ 518269867Sume type = ns_get16(rdata); rdata += NS_INT16SZ; 519156952Sume algorithm = *rdata++; 520156952Sume labels = *rdata++; 521156952Sume t = ns_get32(rdata); rdata += NS_INT32SZ; 522156952Sume len = SPRINTF((tmp, "%s %d %d %lu ", 523156952Sume p_type(type), algorithm, labels, t)); 524156952Sume T(addstr(tmp, len, &buf, &buflen)); 525156952Sume if (labels > (u_int)dn_count_labels(name)) 526156952Sume goto formerr; 527156952Sume 528156952Sume /* Signature expiry. */ 529156952Sume t = ns_get32(rdata); rdata += NS_INT32SZ; 530156952Sume len = SPRINTF((tmp, "%s ", p_secstodate(t))); 531156952Sume T(addstr(tmp, len, &buf, &buflen)); 532156952Sume 533156952Sume /* Time signed. */ 534156952Sume t = ns_get32(rdata); rdata += NS_INT32SZ; 535156952Sume len = SPRINTF((tmp, "%s ", p_secstodate(t))); 536156952Sume T(addstr(tmp, len, &buf, &buflen)); 537156952Sume 538156952Sume /* Signature Footprint. */ 539156952Sume footprint = ns_get16(rdata); rdata += NS_INT16SZ; 540156952Sume len = SPRINTF((tmp, "%u ", footprint)); 541156952Sume T(addstr(tmp, len, &buf, &buflen)); 542156952Sume 543156952Sume /* Signer's name. */ 544156952Sume T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 545156952Sume 546156952Sume /* Signature. */ 547156952Sume len = b64_ntop(rdata, edata - rdata, 548156952Sume base64_key, sizeof base64_key); 549156952Sume if (len > 15) { 550156952Sume T(addstr(" (", 2, &buf, &buflen)); 551156952Sume leader = "\n\t\t"; 552156952Sume spaced = 0; 553156952Sume } else 554156952Sume leader = " "; 555156952Sume if (len < 0) 556156952Sume goto formerr; 557156952Sume for (n = 0; n < len; n += 48) { 558156952Sume T(addstr(leader, strlen(leader), &buf, &buflen)); 559156952Sume T(addstr(base64_key + n, MIN(len - n, 48), 560156952Sume &buf, &buflen)); 561156952Sume } 562156952Sume if (len > 15) 563156952Sume T(addstr(" )", 2, &buf, &buflen)); 564156952Sume break; 565156952Sume } 566156952Sume 567156952Sume case ns_t_nxt: { 568156952Sume int n, c; 569156952Sume 570156952Sume /* Next domain name. */ 571156952Sume T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 572156952Sume 573156952Sume /* Type bit map. */ 574156952Sume n = edata - rdata; 575156952Sume for (c = 0; c < n*8; c++) 576156952Sume if (NS_NXT_BIT_ISSET(c, rdata)) { 577156952Sume len = SPRINTF((tmp, " %s", p_type(c))); 578156952Sume T(addstr(tmp, len, &buf, &buflen)); 579156952Sume } 580156952Sume break; 581156952Sume } 582156952Sume 583156952Sume case ns_t_cert: { 584156952Sume u_int c_type, key_tag, alg; 585156952Sume int n; 586156952Sume unsigned int siz; 587156952Sume char base64_cert[8192], tmp[40]; 588156952Sume const char *leader; 589156952Sume 590156952Sume c_type = ns_get16(rdata); rdata += NS_INT16SZ; 591156952Sume key_tag = ns_get16(rdata); rdata += NS_INT16SZ; 592156952Sume alg = (u_int) *rdata++; 593156952Sume 594156952Sume len = SPRINTF((tmp, "%d %d %d ", c_type, key_tag, alg)); 595156952Sume T(addstr(tmp, len, &buf, &buflen)); 596156952Sume siz = (edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */ 597156952Sume if (siz > sizeof(base64_cert) * 3/4) { 598156952Sume const char *str = "record too long to print"; 599156952Sume T(addstr(str, strlen(str), &buf, &buflen)); 600156952Sume } 601156952Sume else { 602156952Sume len = b64_ntop(rdata, edata-rdata, base64_cert, siz); 603156952Sume 604156952Sume if (len < 0) 605156952Sume goto formerr; 606156952Sume else if (len > 15) { 607156952Sume T(addstr(" (", 2, &buf, &buflen)); 608156952Sume leader = "\n\t\t"; 609156952Sume spaced = 0; 610156952Sume } 611156952Sume else 612156952Sume leader = " "; 613156952Sume 614156952Sume for (n = 0; n < len; n += 48) { 615156952Sume T(addstr(leader, strlen(leader), 616156952Sume &buf, &buflen)); 617156952Sume T(addstr(base64_cert + n, MIN(len - n, 48), 618156952Sume &buf, &buflen)); 619156952Sume } 620156952Sume if (len > 15) 621156952Sume T(addstr(" )", 2, &buf, &buflen)); 622156952Sume } 623156952Sume break; 624156952Sume } 625156952Sume 626156952Sume case ns_t_tkey: { 627156952Sume /* KJD - need to complete this */ 628156952Sume u_long t; 629156952Sume int mode, err, keysize; 630156952Sume 631156952Sume /* Algorithm name. */ 632156952Sume T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 633156952Sume T(addstr(" ", 1, &buf, &buflen)); 634156952Sume 635156952Sume /* Inception. */ 636156952Sume t = ns_get32(rdata); rdata += NS_INT32SZ; 637156952Sume len = SPRINTF((tmp, "%s ", p_secstodate(t))); 638156952Sume T(addstr(tmp, len, &buf, &buflen)); 639156952Sume 640156952Sume /* Experation. */ 641156952Sume t = ns_get32(rdata); rdata += NS_INT32SZ; 642156952Sume len = SPRINTF((tmp, "%s ", p_secstodate(t))); 643156952Sume T(addstr(tmp, len, &buf, &buflen)); 644156952Sume 645156952Sume /* Mode , Error, Key Size. */ 646156952Sume /* Priority, Weight, Port. */ 647156952Sume mode = ns_get16(rdata); rdata += NS_INT16SZ; 648156952Sume err = ns_get16(rdata); rdata += NS_INT16SZ; 649156952Sume keysize = ns_get16(rdata); rdata += NS_INT16SZ; 650156952Sume len = SPRINTF((tmp, "%u %u %u ", mode, err, keysize)); 651156952Sume T(addstr(tmp, len, &buf, &buflen)); 652156952Sume 653156952Sume /* XXX need to dump key, print otherdata length & other data */ 654156952Sume break; 655156952Sume } 656156952Sume 657156952Sume case ns_t_tsig: { 658156952Sume /* BEW - need to complete this */ 659156952Sume int n; 660156952Sume 661156952Sume T(len = addname(msg, msglen, &rdata, origin, &buf, &buflen)); 662156952Sume T(addstr(" ", 1, &buf, &buflen)); 663170244Sume rdata += 8; /*%< time */ 664156952Sume n = ns_get16(rdata); rdata += INT16SZ; 665170244Sume rdata += n; /*%< sig */ 666170244Sume n = ns_get16(rdata); rdata += INT16SZ; /*%< original id */ 667156952Sume sprintf(buf, "%d", ns_get16(rdata)); 668156952Sume rdata += INT16SZ; 669156952Sume addlen(strlen(buf), &buf, &buflen); 670156952Sume break; 671156952Sume } 672156952Sume 673156952Sume case ns_t_a6: { 674156952Sume struct in6_addr a; 675156952Sume int pbyte, pbit; 676156952Sume 677156952Sume /* prefix length */ 678156952Sume if (rdlen == 0U) goto formerr; 679156952Sume len = SPRINTF((tmp, "%d ", *rdata)); 680156952Sume T(addstr(tmp, len, &buf, &buflen)); 681156952Sume pbit = *rdata; 682156952Sume if (pbit > 128) goto formerr; 683156952Sume pbyte = (pbit & ~7) / 8; 684156952Sume rdata++; 685156952Sume 686156952Sume /* address suffix: provided only when prefix len != 128 */ 687156952Sume if (pbit < 128) { 688156952Sume if (rdata + pbyte >= edata) goto formerr; 689156952Sume memset(&a, 0, sizeof(a)); 690156952Sume memcpy(&a.s6_addr[pbyte], rdata, sizeof(a) - pbyte); 691156952Sume (void) inet_ntop(AF_INET6, &a, buf, buflen); 692156952Sume addlen(strlen(buf), &buf, &buflen); 693156952Sume rdata += sizeof(a) - pbyte; 694156952Sume } 695156952Sume 696156952Sume /* prefix name: provided only when prefix len > 0 */ 697156952Sume if (pbit == 0) 698156952Sume break; 699156952Sume if (rdata >= edata) goto formerr; 700156952Sume T(addstr(" ", 1, &buf, &buflen)); 701156952Sume T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 702156952Sume 703156952Sume break; 704156952Sume } 705156952Sume 706156952Sume case ns_t_opt: { 707156952Sume len = SPRINTF((tmp, "%u bytes", class)); 708156952Sume T(addstr(tmp, len, &buf, &buflen)); 709156952Sume break; 710156952Sume } 711156952Sume 712269867Sume case ns_t_ds: 713269867Sume case ns_t_dlv: 714269867Sume case ns_t_sshfp: { 715269867Sume u_int t; 716269867Sume 717269867Sume if (type == ns_t_ds || type == ns_t_dlv) { 718269867Sume if (rdlen < 4U) goto formerr; 719269867Sume t = ns_get16(rdata); 720269867Sume rdata += NS_INT16SZ; 721269867Sume len = SPRINTF((tmp, "%u ", t)); 722269867Sume T(addstr(tmp, len, &buf, &buflen)); 723269867Sume } else 724269867Sume if (rdlen < 2U) goto formerr; 725269867Sume 726269867Sume len = SPRINTF((tmp, "%u ", *rdata)); 727269867Sume T(addstr(tmp, len, &buf, &buflen)); 728269867Sume rdata++; 729269867Sume 730269867Sume len = SPRINTF((tmp, "%u ", *rdata)); 731269867Sume T(addstr(tmp, len, &buf, &buflen)); 732269867Sume rdata++; 733269867Sume 734269867Sume while (rdata < edata) { 735269867Sume len = SPRINTF((tmp, "%02X", *rdata)); 736269867Sume T(addstr(tmp, len, &buf, &buflen)); 737269867Sume rdata++; 738269867Sume } 739269867Sume break; 740269867Sume } 741269867Sume 742269867Sume case ns_t_nsec3: 743269867Sume case ns_t_nsec3param: { 744269867Sume u_int t, w, l, j, k, c; 745269867Sume 746269867Sume len = SPRINTF((tmp, "%u ", *rdata)); 747269867Sume T(addstr(tmp, len, &buf, &buflen)); 748269867Sume rdata++; 749269867Sume 750269867Sume len = SPRINTF((tmp, "%u ", *rdata)); 751269867Sume T(addstr(tmp, len, &buf, &buflen)); 752269867Sume rdata++; 753269867Sume 754269867Sume t = ns_get16(rdata); 755269867Sume rdata += NS_INT16SZ; 756269867Sume len = SPRINTF((tmp, "%u ", t)); 757269867Sume T(addstr(tmp, len, &buf, &buflen)); 758269867Sume 759269867Sume t = *rdata++; 760269867Sume if (t == 0) { 761269867Sume T(addstr("-", 1, &buf, &buflen)); 762269867Sume } else { 763269867Sume while (t-- > 0) { 764269867Sume len = SPRINTF((tmp, "%02X", *rdata)); 765269867Sume T(addstr(tmp, len, &buf, &buflen)); 766269867Sume rdata++; 767269867Sume } 768269867Sume } 769269867Sume if (type == ns_t_nsec3param) 770269867Sume break; 771269867Sume T(addstr(" ", 1, &buf, &buflen)); 772269867Sume 773269867Sume t = *rdata++; 774269867Sume while (t > 0) { 775269867Sume switch (t) { 776269867Sume case 1: 777269867Sume tmp[0] = base32hex[((rdata[0]>>3)&0x1f)]; 778269867Sume tmp[1] = base32hex[((rdata[0]<<2)&0x1c)]; 779269867Sume tmp[2] = tmp[3] = tmp[4] = '='; 780269867Sume tmp[5] = tmp[6] = tmp[7] = '='; 781269867Sume break; 782269867Sume case 2: 783269867Sume tmp[0] = base32hex[((rdata[0]>>3)&0x1f)]; 784269867Sume tmp[1] = base32hex[((rdata[0]<<2)&0x1c)| 785269867Sume ((rdata[1]>>6)&0x03)]; 786269867Sume tmp[2] = base32hex[((rdata[1]>>1)&0x1f)]; 787269867Sume tmp[3] = base32hex[((rdata[1]<<4)&0x10)]; 788269867Sume tmp[4] = tmp[5] = tmp[6] = tmp[7] = '='; 789269867Sume break; 790269867Sume case 3: 791269867Sume tmp[0] = base32hex[((rdata[0]>>3)&0x1f)]; 792269867Sume tmp[1] = base32hex[((rdata[0]<<2)&0x1c)| 793269867Sume ((rdata[1]>>6)&0x03)]; 794269867Sume tmp[2] = base32hex[((rdata[1]>>1)&0x1f)]; 795269867Sume tmp[3] = base32hex[((rdata[1]<<4)&0x10)| 796269867Sume ((rdata[2]>>4)&0x0f)]; 797269867Sume tmp[4] = base32hex[((rdata[2]<<1)&0x1e)]; 798269867Sume tmp[5] = tmp[6] = tmp[7] = '='; 799269867Sume break; 800269867Sume case 4: 801269867Sume tmp[0] = base32hex[((rdata[0]>>3)&0x1f)]; 802269867Sume tmp[1] = base32hex[((rdata[0]<<2)&0x1c)| 803269867Sume ((rdata[1]>>6)&0x03)]; 804269867Sume tmp[2] = base32hex[((rdata[1]>>1)&0x1f)]; 805269867Sume tmp[3] = base32hex[((rdata[1]<<4)&0x10)| 806269867Sume ((rdata[2]>>4)&0x0f)]; 807269867Sume tmp[4] = base32hex[((rdata[2]<<1)&0x1e)| 808269867Sume ((rdata[3]>>7)&0x01)]; 809269867Sume tmp[5] = base32hex[((rdata[3]>>2)&0x1f)]; 810269867Sume tmp[6] = base32hex[(rdata[3]<<3)&0x18]; 811269867Sume tmp[7] = '='; 812269867Sume break; 813269867Sume default: 814269867Sume tmp[0] = base32hex[((rdata[0]>>3)&0x1f)]; 815269867Sume tmp[1] = base32hex[((rdata[0]<<2)&0x1c)| 816269867Sume ((rdata[1]>>6)&0x03)]; 817269867Sume tmp[2] = base32hex[((rdata[1]>>1)&0x1f)]; 818269867Sume tmp[3] = base32hex[((rdata[1]<<4)&0x10)| 819269867Sume ((rdata[2]>>4)&0x0f)]; 820269867Sume tmp[4] = base32hex[((rdata[2]<<1)&0x1e)| 821269867Sume ((rdata[3]>>7)&0x01)]; 822269867Sume tmp[5] = base32hex[((rdata[3]>>2)&0x1f)]; 823269867Sume tmp[6] = base32hex[((rdata[3]<<3)&0x18)| 824269867Sume ((rdata[4]>>5)&0x07)]; 825269867Sume tmp[7] = base32hex[(rdata[4]&0x1f)]; 826269867Sume break; 827269867Sume } 828269867Sume T(addstr(tmp, 8, &buf, &buflen)); 829269867Sume if (t >= 5) { 830269867Sume rdata += 5; 831269867Sume t -= 5; 832269867Sume } else { 833269867Sume rdata += t; 834269867Sume t -= t; 835269867Sume } 836269867Sume } 837269867Sume 838269867Sume while (rdata < edata) { 839269867Sume w = *rdata++; 840269867Sume l = *rdata++; 841269867Sume for (j = 0; j < l; j++) { 842269867Sume if (rdata[j] == 0) 843269867Sume continue; 844269867Sume for (k = 0; k < 8; k++) { 845269867Sume if ((rdata[j] & (0x80 >> k)) == 0) 846269867Sume continue; 847269867Sume c = w * 256 + j * 8 + k; 848269867Sume len = SPRINTF((tmp, " %s", p_type(c))); 849269867Sume T(addstr(tmp, len, &buf, &buflen)); 850269867Sume } 851269867Sume } 852269867Sume rdata += l; 853269867Sume } 854269867Sume break; 855269867Sume } 856269867Sume 857269867Sume case ns_t_nsec: { 858269867Sume u_int w, l, j, k, c; 859269867Sume 860269867Sume T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 861269867Sume 862269867Sume while (rdata < edata) { 863269867Sume w = *rdata++; 864269867Sume l = *rdata++; 865269867Sume for (j = 0; j < l; j++) { 866269867Sume if (rdata[j] == 0) 867269867Sume continue; 868269867Sume for (k = 0; k < 8; k++) { 869269867Sume if ((rdata[j] & (0x80 >> k)) == 0) 870269867Sume continue; 871269867Sume c = w * 256 + j * 8 + k; 872269867Sume len = SPRINTF((tmp, " %s", p_type(c))); 873269867Sume T(addstr(tmp, len, &buf, &buflen)); 874269867Sume } 875269867Sume } 876269867Sume rdata += l; 877269867Sume } 878269867Sume break; 879269867Sume } 880269867Sume 881269867Sume case ns_t_dhcid: { 882269867Sume int n; 883269867Sume unsigned int siz; 884269867Sume char base64_dhcid[8192]; 885269867Sume const char *leader; 886269867Sume 887269867Sume siz = (edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */ 888269867Sume if (siz > sizeof(base64_dhcid) * 3/4) { 889269867Sume const char *str = "record too long to print"; 890269867Sume T(addstr(str, strlen(str), &buf, &buflen)); 891269867Sume } else { 892269867Sume len = b64_ntop(rdata, edata-rdata, base64_dhcid, siz); 893269867Sume 894269867Sume if (len < 0) 895269867Sume goto formerr; 896269867Sume 897269867Sume else if (len > 15) { 898269867Sume T(addstr(" (", 2, &buf, &buflen)); 899269867Sume leader = "\n\t\t"; 900269867Sume spaced = 0; 901269867Sume } 902269867Sume else 903269867Sume leader = " "; 904269867Sume 905269867Sume for (n = 0; n < len; n += 48) { 906269867Sume T(addstr(leader, strlen(leader), 907269867Sume &buf, &buflen)); 908269867Sume T(addstr(base64_dhcid + n, MIN(len - n, 48), 909269867Sume &buf, &buflen)); 910269867Sume } 911269867Sume if (len > 15) 912269867Sume T(addstr(" )", 2, &buf, &buflen)); 913269867Sume } 914270215Spfg break; 915269867Sume } 916269867Sume 917269867Sume case ns_t_ipseckey: { 918269867Sume int n; 919269867Sume unsigned int siz; 920269867Sume char base64_key[8192]; 921269867Sume const char *leader; 922269867Sume 923269867Sume if (rdlen < 2) 924269867Sume goto formerr; 925269867Sume 926269867Sume switch (rdata[1]) { 927269867Sume case 0: 928269867Sume case 3: 929269867Sume if (rdlen < 3) 930269867Sume goto formerr; 931269867Sume break; 932269867Sume case 1: 933269867Sume if (rdlen < 7) 934269867Sume goto formerr; 935269867Sume break; 936269867Sume case 2: 937269867Sume if (rdlen < 19) 938269867Sume goto formerr; 939269867Sume break; 940269867Sume default: 941269867Sume comment = "unknown IPSECKEY gateway type"; 942269867Sume goto hexify; 943269867Sume } 944269867Sume 945269867Sume len = SPRINTF((tmp, "%u ", *rdata)); 946269867Sume T(addstr(tmp, len, &buf, &buflen)); 947269867Sume rdata++; 948269867Sume 949269867Sume len = SPRINTF((tmp, "%u ", *rdata)); 950269867Sume T(addstr(tmp, len, &buf, &buflen)); 951269867Sume rdata++; 952269867Sume 953269867Sume len = SPRINTF((tmp, "%u ", *rdata)); 954269867Sume T(addstr(tmp, len, &buf, &buflen)); 955269867Sume rdata++; 956269867Sume 957269867Sume switch (rdata[-2]) { 958269867Sume case 0: 959269867Sume T(addstr(".", 1, &buf, &buflen)); 960269867Sume break; 961269867Sume case 1: 962269867Sume (void) inet_ntop(AF_INET, rdata, buf, buflen); 963269867Sume addlen(strlen(buf), &buf, &buflen); 964269867Sume rdata += 4; 965269867Sume break; 966269867Sume case 2: 967269867Sume (void) inet_ntop(AF_INET6, rdata, buf, buflen); 968269867Sume addlen(strlen(buf), &buf, &buflen); 969269867Sume rdata += 16; 970269867Sume break; 971269867Sume case 3: 972269867Sume T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 973269867Sume break; 974269867Sume } 975269867Sume 976269867Sume if (rdata >= edata) 977269867Sume break; 978269867Sume 979269867Sume siz = (edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */ 980269867Sume if (siz > sizeof(base64_key) * 3/4) { 981269867Sume const char *str = "record too long to print"; 982269867Sume T(addstr(str, strlen(str), &buf, &buflen)); 983269867Sume } else { 984269867Sume len = b64_ntop(rdata, edata-rdata, base64_key, siz); 985269867Sume 986269867Sume if (len < 0) 987269867Sume goto formerr; 988269867Sume 989269867Sume else if (len > 15) { 990269867Sume T(addstr(" (", 2, &buf, &buflen)); 991269867Sume leader = "\n\t\t"; 992269867Sume spaced = 0; 993269867Sume } 994269867Sume else 995269867Sume leader = " "; 996269867Sume 997269867Sume for (n = 0; n < len; n += 48) { 998269867Sume T(addstr(leader, strlen(leader), 999269867Sume &buf, &buflen)); 1000269867Sume T(addstr(base64_key + n, MIN(len - n, 48), 1001269867Sume &buf, &buflen)); 1002269867Sume } 1003269867Sume if (len > 15) 1004269867Sume T(addstr(" )", 2, &buf, &buflen)); 1005269867Sume } 1006269867Sume } 1007269867Sume 1008269867Sume case ns_t_hip: { 1009269867Sume unsigned int i, hip_len, algorithm, key_len; 1010269867Sume char base64_key[NS_MD5RSA_MAX_BASE64]; 1011269867Sume unsigned int siz; 1012269867Sume const char *leader = "\n\t\t\t\t\t"; 1013269867Sume 1014269867Sume hip_len = *rdata++; 1015269867Sume algorithm = *rdata++; 1016269867Sume key_len = ns_get16(rdata); 1017269867Sume rdata += NS_INT16SZ; 1018269867Sume 1019269867Sume siz = key_len*4/3 + 4; /* "+4" accounts for trailing \0 */ 1020269867Sume if (siz > sizeof(base64_key) * 3/4) { 1021269867Sume const char *str = "record too long to print"; 1022269867Sume T(addstr(str, strlen(str), &buf, &buflen)); 1023269867Sume } else { 1024269867Sume len = sprintf(tmp, "( %u ", algorithm); 1025269867Sume T(addstr(tmp, len, &buf, &buflen)); 1026269867Sume 1027269867Sume for (i = 0; i < hip_len; i++) { 1028269867Sume len = sprintf(tmp, "%02X", *rdata); 1029269867Sume T(addstr(tmp, len, &buf, &buflen)); 1030269867Sume rdata++; 1031269867Sume } 1032269867Sume T(addstr(leader, strlen(leader), &buf, &buflen)); 1033269867Sume 1034269867Sume len = b64_ntop(rdata, key_len, base64_key, siz); 1035269867Sume if (len < 0) 1036269867Sume goto formerr; 1037269867Sume 1038269867Sume T(addstr(base64_key, len, &buf, &buflen)); 1039269867Sume 1040269867Sume rdata += key_len; 1041269867Sume while (rdata < edata) { 1042269867Sume T(addstr(leader, strlen(leader), &buf, &buflen)); 1043269867Sume T(addname(msg, msglen, &rdata, origin, 1044269867Sume &buf, &buflen)); 1045269867Sume } 1046269867Sume T(addstr(" )", 2, &buf, &buflen)); 1047269867Sume } 1048269867Sume break; 1049269867Sume } 1050269867Sume 1051156952Sume default: 1052156952Sume comment = "unknown RR type"; 1053156952Sume goto hexify; 1054156952Sume } 1055156952Sume return (buf - obuf); 1056156952Sume formerr: 1057156952Sume comment = "RR format error"; 1058156952Sume hexify: { 1059156952Sume int n, m; 1060156952Sume char *p; 1061156952Sume 1062156952Sume len = SPRINTF((tmp, "\\# %u%s\t; %s", (unsigned)(edata - rdata), 1063156952Sume rdlen != 0U ? " (" : "", comment)); 1064156952Sume T(addstr(tmp, len, &buf, &buflen)); 1065156952Sume while (rdata < edata) { 1066156952Sume p = tmp; 1067156952Sume p += SPRINTF((p, "\n\t")); 1068156952Sume spaced = 0; 1069156952Sume n = MIN(16, edata - rdata); 1070156952Sume for (m = 0; m < n; m++) 1071156952Sume p += SPRINTF((p, "%02x ", rdata[m])); 1072156952Sume T(addstr(tmp, p - tmp, &buf, &buflen)); 1073156952Sume if (n < 16) { 1074156952Sume T(addstr(")", 1, &buf, &buflen)); 1075156952Sume T(addtab(p - tmp + 1, 48, spaced, &buf, &buflen)); 1076156952Sume } 1077156952Sume p = tmp; 1078156952Sume p += SPRINTF((p, "; ")); 1079156952Sume for (m = 0; m < n; m++) 1080156952Sume *p++ = (isascii(rdata[m]) && isprint(rdata[m])) 1081156952Sume ? rdata[m] 1082156952Sume : '.'; 1083156952Sume T(addstr(tmp, p - tmp, &buf, &buflen)); 1084156952Sume rdata += n; 1085156952Sume } 1086156952Sume return (buf - obuf); 1087156952Sume } 1088156952Sume} 1089156952Sume 1090156952Sume/* Private. */ 1091156952Sume 1092170244Sume/*% 1093156952Sume * size_t 1094156952Sume * prune_origin(name, origin) 1095156952Sume * Find out if the name is at or under the current origin. 1096156952Sume * return: 1097156952Sume * Number of characters in name before start of origin, 1098156952Sume * or length of name if origin does not match. 1099156952Sume * notes: 1100156952Sume * This function should share code with samedomain(). 1101156952Sume */ 1102156952Sumestatic size_t 1103156952Sumeprune_origin(const char *name, const char *origin) { 1104156952Sume const char *oname = name; 1105156952Sume 1106156952Sume while (*name != '\0') { 1107156952Sume if (origin != NULL && ns_samename(name, origin) == 1) 1108156952Sume return (name - oname - (name > oname)); 1109156952Sume while (*name != '\0') { 1110156952Sume if (*name == '\\') { 1111156952Sume name++; 1112156952Sume /* XXX need to handle \nnn form. */ 1113156952Sume if (*name == '\0') 1114156952Sume break; 1115156952Sume } else if (*name == '.') { 1116156952Sume name++; 1117156952Sume break; 1118156952Sume } 1119156952Sume name++; 1120156952Sume } 1121156952Sume } 1122156952Sume return (name - oname); 1123156952Sume} 1124156952Sume 1125170244Sume/*% 1126156952Sume * int 1127156952Sume * charstr(rdata, edata, buf, buflen) 1128156952Sume * Format a <character-string> into the presentation buffer. 1129156952Sume * return: 1130156952Sume * Number of rdata octets consumed 1131156952Sume * 0 for protocol format error 1132156952Sume * -1 for output buffer error 1133156952Sume * side effects: 1134156952Sume * buffer is advanced on success. 1135156952Sume */ 1136156952Sumestatic int 1137156952Sumecharstr(const u_char *rdata, const u_char *edata, char **buf, size_t *buflen) { 1138156952Sume const u_char *odata = rdata; 1139156952Sume size_t save_buflen = *buflen; 1140156952Sume char *save_buf = *buf; 1141156952Sume 1142156952Sume if (addstr("\"", 1, buf, buflen) < 0) 1143156952Sume goto enospc; 1144156952Sume if (rdata < edata) { 1145156952Sume int n = *rdata; 1146156952Sume 1147156952Sume if (rdata + 1 + n <= edata) { 1148156952Sume rdata++; 1149156952Sume while (n-- > 0) { 1150156952Sume if (strchr("\n\"\\", *rdata) != NULL) 1151156952Sume if (addstr("\\", 1, buf, buflen) < 0) 1152156952Sume goto enospc; 1153156952Sume if (addstr((const char *)rdata, 1, 1154156952Sume buf, buflen) < 0) 1155156952Sume goto enospc; 1156156952Sume rdata++; 1157156952Sume } 1158156952Sume } 1159156952Sume } 1160156952Sume if (addstr("\"", 1, buf, buflen) < 0) 1161156952Sume goto enospc; 1162156952Sume return (rdata - odata); 1163156952Sume enospc: 1164156952Sume errno = ENOSPC; 1165156952Sume *buf = save_buf; 1166156952Sume *buflen = save_buflen; 1167156952Sume return (-1); 1168156952Sume} 1169156952Sume 1170156952Sumestatic int 1171156952Sumeaddname(const u_char *msg, size_t msglen, 1172156952Sume const u_char **pp, const char *origin, 1173156952Sume char **buf, size_t *buflen) 1174156952Sume{ 1175156952Sume size_t newlen, save_buflen = *buflen; 1176156952Sume char *save_buf = *buf; 1177156952Sume int n; 1178156952Sume 1179156952Sume n = dn_expand(msg, msg + msglen, *pp, *buf, *buflen); 1180156952Sume if (n < 0) 1181170244Sume goto enospc; /*%< Guess. */ 1182156952Sume newlen = prune_origin(*buf, origin); 1183156952Sume if (**buf == '\0') { 1184156952Sume goto root; 1185156952Sume } else if (newlen == 0U) { 1186156952Sume /* Use "@" instead of name. */ 1187156952Sume if (newlen + 2 > *buflen) 1188156952Sume goto enospc; /* No room for "@\0". */ 1189156952Sume (*buf)[newlen++] = '@'; 1190156952Sume (*buf)[newlen] = '\0'; 1191156952Sume } else { 1192156952Sume if (((origin == NULL || origin[0] == '\0') || 1193156952Sume (origin[0] != '.' && origin[1] != '\0' && 1194156952Sume (*buf)[newlen] == '\0')) && (*buf)[newlen - 1] != '.') { 1195156952Sume /* No trailing dot. */ 1196156952Sume root: 1197156952Sume if (newlen + 2 > *buflen) 1198156952Sume goto enospc; /* No room for ".\0". */ 1199156952Sume (*buf)[newlen++] = '.'; 1200156952Sume (*buf)[newlen] = '\0'; 1201156952Sume } 1202156952Sume } 1203156952Sume *pp += n; 1204156952Sume addlen(newlen, buf, buflen); 1205156952Sume **buf = '\0'; 1206156952Sume return (newlen); 1207156952Sume enospc: 1208156952Sume errno = ENOSPC; 1209156952Sume *buf = save_buf; 1210156952Sume *buflen = save_buflen; 1211156952Sume return (-1); 1212156952Sume} 1213156952Sume 1214156952Sumestatic void 1215156952Sumeaddlen(size_t len, char **buf, size_t *buflen) { 1216156952Sume INSIST(len <= *buflen); 1217156952Sume *buf += len; 1218156952Sume *buflen -= len; 1219156952Sume} 1220156952Sume 1221156952Sumestatic int 1222156952Sumeaddstr(const char *src, size_t len, char **buf, size_t *buflen) { 1223156952Sume if (len >= *buflen) { 1224156952Sume errno = ENOSPC; 1225156952Sume return (-1); 1226156952Sume } 1227156952Sume memcpy(*buf, src, len); 1228156952Sume addlen(len, buf, buflen); 1229156952Sume **buf = '\0'; 1230156952Sume return (0); 1231156952Sume} 1232156952Sume 1233156952Sumestatic int 1234156952Sumeaddtab(size_t len, size_t target, int spaced, char **buf, size_t *buflen) { 1235156952Sume size_t save_buflen = *buflen; 1236156952Sume char *save_buf = *buf; 1237156952Sume int t; 1238156952Sume 1239156952Sume if (spaced || len >= target - 1) { 1240156952Sume T(addstr(" ", 2, buf, buflen)); 1241156952Sume spaced = 1; 1242156952Sume } else { 1243156952Sume for (t = (target - len - 1) / 8; t >= 0; t--) 1244156952Sume if (addstr("\t", 1, buf, buflen) < 0) { 1245156952Sume *buflen = save_buflen; 1246156952Sume *buf = save_buf; 1247156952Sume return (-1); 1248156952Sume } 1249156952Sume spaced = 0; 1250156952Sume } 1251156952Sume return (spaced); 1252156952Sume} 1253170244Sume 1254170244Sume/*! \file */ 1255