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 19170244Sumestatic const char rcsid[] = "$Id: ns_print.c,v 1.6.18.4 2005/04/27 05:01:09 sra 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 77156952Sume/* Public. */ 78156952Sume 79170244Sume/*% 80156952Sume * Convert an RR to presentation format. 81170244Sume * 82156952Sume * return: 83170244Sume *\li Number of characters written to buf, or -1 (check errno). 84156952Sume */ 85156952Sumeint 86156952Sumens_sprintrr(const ns_msg *handle, const ns_rr *rr, 87156952Sume const char *name_ctx, const char *origin, 88156952Sume char *buf, size_t buflen) 89156952Sume{ 90156952Sume int n; 91156952Sume 92156952Sume n = ns_sprintrrf(ns_msg_base(*handle), ns_msg_size(*handle), 93156952Sume ns_rr_name(*rr), ns_rr_class(*rr), ns_rr_type(*rr), 94156952Sume ns_rr_ttl(*rr), ns_rr_rdata(*rr), ns_rr_rdlen(*rr), 95156952Sume name_ctx, origin, buf, buflen); 96156952Sume return (n); 97156952Sume} 98156952Sume 99170244Sume/*% 100156952Sume * Convert the fields of an RR into presentation format. 101170244Sume * 102156952Sume * return: 103170244Sume *\li Number of characters written to buf, or -1 (check errno). 104156952Sume */ 105156952Sumeint 106156952Sumens_sprintrrf(const u_char *msg, size_t msglen, 107156952Sume const char *name, ns_class class, ns_type type, 108156952Sume u_long ttl, const u_char *rdata, size_t rdlen, 109156952Sume const char *name_ctx, const char *origin, 110156952Sume char *buf, size_t buflen) 111156952Sume{ 112156952Sume const char *obuf = buf; 113156952Sume const u_char *edata = rdata + rdlen; 114156952Sume int spaced = 0; 115156952Sume 116156952Sume const char *comment; 117156952Sume char tmp[100]; 118156952Sume int len, x; 119156952Sume 120156952Sume /* 121156952Sume * Owner. 122156952Sume */ 123156952Sume if (name_ctx != NULL && ns_samename(name_ctx, name) == 1) { 124156952Sume T(addstr("\t\t\t", 3, &buf, &buflen)); 125156952Sume } else { 126156952Sume len = prune_origin(name, origin); 127156952Sume if (*name == '\0') { 128156952Sume goto root; 129156952Sume } else if (len == 0) { 130156952Sume T(addstr("@\t\t\t", 4, &buf, &buflen)); 131156952Sume } else { 132156952Sume T(addstr(name, len, &buf, &buflen)); 133156952Sume /* Origin not used or not root, and no trailing dot? */ 134156952Sume if (((origin == NULL || origin[0] == '\0') || 135156952Sume (origin[0] != '.' && origin[1] != '\0' && 136156952Sume name[len] == '\0')) && name[len - 1] != '.') { 137156952Sume root: 138156952Sume T(addstr(".", 1, &buf, &buflen)); 139156952Sume len++; 140156952Sume } 141156952Sume T(spaced = addtab(len, 24, spaced, &buf, &buflen)); 142156952Sume } 143156952Sume } 144156952Sume 145156952Sume /* 146156952Sume * TTL, Class, Type. 147156952Sume */ 148156952Sume T(x = ns_format_ttl(ttl, buf, buflen)); 149156952Sume addlen(x, &buf, &buflen); 150156952Sume len = SPRINTF((tmp, " %s %s", p_class(class), p_type(type))); 151156952Sume T(addstr(tmp, len, &buf, &buflen)); 152156952Sume T(spaced = addtab(x + len, 16, spaced, &buf, &buflen)); 153156952Sume 154156952Sume /* 155156952Sume * RData. 156156952Sume */ 157156952Sume switch (type) { 158156952Sume case ns_t_a: 159156952Sume if (rdlen != (size_t)NS_INADDRSZ) 160156952Sume goto formerr; 161156952Sume (void) inet_ntop(AF_INET, rdata, buf, buflen); 162156952Sume addlen(strlen(buf), &buf, &buflen); 163156952Sume break; 164156952Sume 165156952Sume case ns_t_cname: 166156952Sume case ns_t_mb: 167156952Sume case ns_t_mg: 168156952Sume case ns_t_mr: 169156952Sume case ns_t_ns: 170156952Sume case ns_t_ptr: 171156952Sume case ns_t_dname: 172156952Sume T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 173156952Sume break; 174156952Sume 175156952Sume case ns_t_hinfo: 176156952Sume case ns_t_isdn: 177156952Sume /* First word. */ 178156952Sume T(len = charstr(rdata, edata, &buf, &buflen)); 179156952Sume if (len == 0) 180156952Sume goto formerr; 181156952Sume rdata += len; 182156952Sume T(addstr(" ", 1, &buf, &buflen)); 183156952Sume 184156952Sume 185156952Sume /* Second word, optional in ISDN records. */ 186156952Sume if (type == ns_t_isdn && rdata == edata) 187156952Sume break; 188156952Sume 189156952Sume T(len = charstr(rdata, edata, &buf, &buflen)); 190156952Sume if (len == 0) 191156952Sume goto formerr; 192156952Sume rdata += len; 193156952Sume break; 194156952Sume 195156952Sume case ns_t_soa: { 196156952Sume u_long t; 197156952Sume 198156952Sume /* Server name. */ 199156952Sume T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 200156952Sume T(addstr(" ", 1, &buf, &buflen)); 201156952Sume 202156952Sume /* Administrator name. */ 203156952Sume T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 204156952Sume T(addstr(" (\n", 3, &buf, &buflen)); 205156952Sume spaced = 0; 206156952Sume 207156952Sume if ((edata - rdata) != 5*NS_INT32SZ) 208156952Sume goto formerr; 209156952Sume 210156952Sume /* Serial number. */ 211156952Sume t = ns_get32(rdata); rdata += NS_INT32SZ; 212156952Sume T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); 213156952Sume len = SPRINTF((tmp, "%lu", t)); 214156952Sume T(addstr(tmp, len, &buf, &buflen)); 215156952Sume T(spaced = addtab(len, 16, spaced, &buf, &buflen)); 216156952Sume T(addstr("; serial\n", 9, &buf, &buflen)); 217156952Sume spaced = 0; 218156952Sume 219156952Sume /* Refresh interval. */ 220156952Sume t = ns_get32(rdata); rdata += NS_INT32SZ; 221156952Sume T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); 222156952Sume T(len = ns_format_ttl(t, buf, buflen)); 223156952Sume addlen(len, &buf, &buflen); 224156952Sume T(spaced = addtab(len, 16, spaced, &buf, &buflen)); 225156952Sume T(addstr("; refresh\n", 10, &buf, &buflen)); 226156952Sume spaced = 0; 227156952Sume 228156952Sume /* Retry interval. */ 229156952Sume t = ns_get32(rdata); rdata += NS_INT32SZ; 230156952Sume T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); 231156952Sume T(len = ns_format_ttl(t, buf, buflen)); 232156952Sume addlen(len, &buf, &buflen); 233156952Sume T(spaced = addtab(len, 16, spaced, &buf, &buflen)); 234156952Sume T(addstr("; retry\n", 8, &buf, &buflen)); 235156952Sume spaced = 0; 236156952Sume 237156952Sume /* Expiry. */ 238156952Sume t = ns_get32(rdata); rdata += NS_INT32SZ; 239156952Sume T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); 240156952Sume T(len = ns_format_ttl(t, buf, buflen)); 241156952Sume addlen(len, &buf, &buflen); 242156952Sume T(spaced = addtab(len, 16, spaced, &buf, &buflen)); 243156952Sume T(addstr("; expiry\n", 9, &buf, &buflen)); 244156952Sume spaced = 0; 245156952Sume 246156952Sume /* Minimum TTL. */ 247156952Sume t = ns_get32(rdata); rdata += NS_INT32SZ; 248156952Sume T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); 249156952Sume T(len = ns_format_ttl(t, buf, buflen)); 250156952Sume addlen(len, &buf, &buflen); 251156952Sume T(addstr(" )", 2, &buf, &buflen)); 252156952Sume T(spaced = addtab(len, 16, spaced, &buf, &buflen)); 253156952Sume T(addstr("; minimum\n", 10, &buf, &buflen)); 254156952Sume 255156952Sume break; 256156952Sume } 257156952Sume 258156952Sume case ns_t_mx: 259156952Sume case ns_t_afsdb: 260156952Sume case ns_t_rt: { 261156952Sume u_int t; 262156952Sume 263156952Sume if (rdlen < (size_t)NS_INT16SZ) 264156952Sume goto formerr; 265156952Sume 266156952Sume /* Priority. */ 267156952Sume t = ns_get16(rdata); 268156952Sume rdata += NS_INT16SZ; 269156952Sume len = SPRINTF((tmp, "%u ", t)); 270156952Sume T(addstr(tmp, len, &buf, &buflen)); 271156952Sume 272156952Sume /* Target. */ 273156952Sume T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 274156952Sume 275156952Sume break; 276156952Sume } 277156952Sume 278156952Sume case ns_t_px: { 279156952Sume u_int t; 280156952Sume 281156952Sume if (rdlen < (size_t)NS_INT16SZ) 282156952Sume goto formerr; 283156952Sume 284156952Sume /* Priority. */ 285156952Sume t = ns_get16(rdata); 286156952Sume rdata += NS_INT16SZ; 287156952Sume len = SPRINTF((tmp, "%u ", t)); 288156952Sume T(addstr(tmp, len, &buf, &buflen)); 289156952Sume 290156952Sume /* Name1. */ 291156952Sume T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 292156952Sume T(addstr(" ", 1, &buf, &buflen)); 293156952Sume 294156952Sume /* Name2. */ 295156952Sume T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 296156952Sume 297156952Sume break; 298156952Sume } 299156952Sume 300156952Sume case ns_t_x25: 301156952Sume T(len = charstr(rdata, edata, &buf, &buflen)); 302156952Sume if (len == 0) 303156952Sume goto formerr; 304156952Sume rdata += len; 305156952Sume break; 306156952Sume 307156952Sume case ns_t_txt: 308156952Sume while (rdata < edata) { 309156952Sume T(len = charstr(rdata, edata, &buf, &buflen)); 310156952Sume if (len == 0) 311156952Sume goto formerr; 312156952Sume rdata += len; 313156952Sume if (rdata < edata) 314156952Sume T(addstr(" ", 1, &buf, &buflen)); 315156952Sume } 316156952Sume break; 317156952Sume 318156952Sume case ns_t_nsap: { 319156952Sume char t[2+255*3]; 320156952Sume 321156952Sume (void) inet_nsap_ntoa(rdlen, rdata, t); 322156952Sume T(addstr(t, strlen(t), &buf, &buflen)); 323156952Sume break; 324156952Sume } 325156952Sume 326156952Sume case ns_t_aaaa: 327156952Sume if (rdlen != (size_t)NS_IN6ADDRSZ) 328156952Sume goto formerr; 329156952Sume (void) inet_ntop(AF_INET6, rdata, buf, buflen); 330156952Sume addlen(strlen(buf), &buf, &buflen); 331156952Sume break; 332156952Sume 333156952Sume case ns_t_loc: { 334156952Sume char t[255]; 335156952Sume 336156952Sume /* XXX protocol format checking? */ 337156952Sume (void) loc_ntoa(rdata, t); 338156952Sume T(addstr(t, strlen(t), &buf, &buflen)); 339156952Sume break; 340156952Sume } 341156952Sume 342156952Sume case ns_t_naptr: { 343156952Sume u_int order, preference; 344156952Sume char t[50]; 345156952Sume 346156952Sume if (rdlen < 2U*NS_INT16SZ) 347156952Sume goto formerr; 348156952Sume 349156952Sume /* Order, Precedence. */ 350156952Sume order = ns_get16(rdata); rdata += NS_INT16SZ; 351156952Sume preference = ns_get16(rdata); rdata += NS_INT16SZ; 352156952Sume len = SPRINTF((t, "%u %u ", order, preference)); 353156952Sume T(addstr(t, len, &buf, &buflen)); 354156952Sume 355156952Sume /* Flags. */ 356156952Sume T(len = charstr(rdata, edata, &buf, &buflen)); 357156952Sume if (len == 0) 358156952Sume goto formerr; 359156952Sume rdata += len; 360156952Sume T(addstr(" ", 1, &buf, &buflen)); 361156952Sume 362156952Sume /* Service. */ 363156952Sume T(len = charstr(rdata, edata, &buf, &buflen)); 364156952Sume if (len == 0) 365156952Sume goto formerr; 366156952Sume rdata += len; 367156952Sume T(addstr(" ", 1, &buf, &buflen)); 368156952Sume 369156952Sume /* Regexp. */ 370156952Sume T(len = charstr(rdata, edata, &buf, &buflen)); 371156952Sume if (len < 0) 372156952Sume return (-1); 373156952Sume if (len == 0) 374156952Sume goto formerr; 375156952Sume rdata += len; 376156952Sume T(addstr(" ", 1, &buf, &buflen)); 377156952Sume 378156952Sume /* Server. */ 379156952Sume T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 380156952Sume break; 381156952Sume } 382156952Sume 383156952Sume case ns_t_srv: { 384156952Sume u_int priority, weight, port; 385156952Sume char t[50]; 386156952Sume 387156952Sume if (rdlen < 3U*NS_INT16SZ) 388156952Sume goto formerr; 389156952Sume 390156952Sume /* Priority, Weight, Port. */ 391156952Sume priority = ns_get16(rdata); rdata += NS_INT16SZ; 392156952Sume weight = ns_get16(rdata); rdata += NS_INT16SZ; 393156952Sume port = ns_get16(rdata); rdata += NS_INT16SZ; 394156952Sume len = SPRINTF((t, "%u %u %u ", priority, weight, port)); 395156952Sume T(addstr(t, len, &buf, &buflen)); 396156952Sume 397156952Sume /* Server. */ 398156952Sume T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 399156952Sume break; 400156952Sume } 401156952Sume 402156952Sume case ns_t_minfo: 403156952Sume case ns_t_rp: 404156952Sume /* Name1. */ 405156952Sume T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 406156952Sume T(addstr(" ", 1, &buf, &buflen)); 407156952Sume 408156952Sume /* Name2. */ 409156952Sume T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 410156952Sume 411156952Sume break; 412156952Sume 413156952Sume case ns_t_wks: { 414156952Sume int n, lcnt; 415156952Sume 416156952Sume if (rdlen < 1U + NS_INT32SZ) 417156952Sume goto formerr; 418156952Sume 419156952Sume /* Address. */ 420156952Sume (void) inet_ntop(AF_INET, rdata, buf, buflen); 421156952Sume addlen(strlen(buf), &buf, &buflen); 422156952Sume rdata += NS_INADDRSZ; 423156952Sume 424156952Sume /* Protocol. */ 425156952Sume len = SPRINTF((tmp, " %u ( ", *rdata)); 426156952Sume T(addstr(tmp, len, &buf, &buflen)); 427156952Sume rdata += NS_INT8SZ; 428156952Sume 429156952Sume /* Bit map. */ 430156952Sume n = 0; 431156952Sume lcnt = 0; 432156952Sume while (rdata < edata) { 433156952Sume u_int c = *rdata++; 434156952Sume do { 435156952Sume if (c & 0200) { 436156952Sume if (lcnt == 0) { 437156952Sume T(addstr("\n\t\t\t\t", 5, 438156952Sume &buf, &buflen)); 439156952Sume lcnt = 10; 440156952Sume spaced = 0; 441156952Sume } 442156952Sume len = SPRINTF((tmp, "%d ", n)); 443156952Sume T(addstr(tmp, len, &buf, &buflen)); 444156952Sume lcnt--; 445156952Sume } 446156952Sume c <<= 1; 447156952Sume } while (++n & 07); 448156952Sume } 449156952Sume T(addstr(")", 1, &buf, &buflen)); 450156952Sume 451156952Sume break; 452156952Sume } 453156952Sume 454156952Sume case ns_t_key: { 455156952Sume char base64_key[NS_MD5RSA_MAX_BASE64]; 456156952Sume u_int keyflags, protocol, algorithm, key_id; 457156952Sume const char *leader; 458156952Sume int n; 459156952Sume 460156952Sume if (rdlen < 0U + NS_INT16SZ + NS_INT8SZ + NS_INT8SZ) 461156952Sume goto formerr; 462156952Sume 463156952Sume /* Key flags, Protocol, Algorithm. */ 464156956Sume#ifndef _LIBC 465156952Sume key_id = dst_s_dns_key_id(rdata, edata-rdata); 466156956Sume#else 467156956Sume key_id = 0; 468156956Sume#endif 469156952Sume keyflags = ns_get16(rdata); rdata += NS_INT16SZ; 470156952Sume protocol = *rdata++; 471156952Sume algorithm = *rdata++; 472156952Sume len = SPRINTF((tmp, "0x%04x %u %u", 473156952Sume keyflags, protocol, algorithm)); 474156952Sume T(addstr(tmp, len, &buf, &buflen)); 475156952Sume 476156952Sume /* Public key data. */ 477156952Sume len = b64_ntop(rdata, edata - rdata, 478156952Sume base64_key, sizeof base64_key); 479156952Sume if (len < 0) 480156952Sume goto formerr; 481156952Sume if (len > 15) { 482156952Sume T(addstr(" (", 2, &buf, &buflen)); 483156952Sume leader = "\n\t\t"; 484156952Sume spaced = 0; 485156952Sume } else 486156952Sume leader = " "; 487156952Sume for (n = 0; n < len; n += 48) { 488156952Sume T(addstr(leader, strlen(leader), &buf, &buflen)); 489156952Sume T(addstr(base64_key + n, MIN(len - n, 48), 490156952Sume &buf, &buflen)); 491156952Sume } 492156952Sume if (len > 15) 493156952Sume T(addstr(" )", 2, &buf, &buflen)); 494156952Sume n = SPRINTF((tmp, " ; key_tag= %u", key_id)); 495156952Sume T(addstr(tmp, n, &buf, &buflen)); 496156952Sume 497156952Sume break; 498156952Sume } 499156952Sume 500156952Sume case ns_t_sig: { 501156952Sume char base64_key[NS_MD5RSA_MAX_BASE64]; 502156952Sume u_int type, algorithm, labels, footprint; 503156952Sume const char *leader; 504156952Sume u_long t; 505156952Sume int n; 506156952Sume 507156952Sume if (rdlen < 22U) 508156952Sume goto formerr; 509156952Sume 510156952Sume /* Type covered, Algorithm, Label count, Original TTL. */ 511156952Sume type = ns_get16(rdata); rdata += NS_INT16SZ; 512156952Sume algorithm = *rdata++; 513156952Sume labels = *rdata++; 514156952Sume t = ns_get32(rdata); rdata += NS_INT32SZ; 515156952Sume len = SPRINTF((tmp, "%s %d %d %lu ", 516156952Sume p_type(type), algorithm, labels, t)); 517156952Sume T(addstr(tmp, len, &buf, &buflen)); 518156952Sume if (labels > (u_int)dn_count_labels(name)) 519156952Sume goto formerr; 520156952Sume 521156952Sume /* Signature expiry. */ 522156952Sume t = ns_get32(rdata); rdata += NS_INT32SZ; 523156952Sume len = SPRINTF((tmp, "%s ", p_secstodate(t))); 524156952Sume T(addstr(tmp, len, &buf, &buflen)); 525156952Sume 526156952Sume /* Time signed. */ 527156952Sume t = ns_get32(rdata); rdata += NS_INT32SZ; 528156952Sume len = SPRINTF((tmp, "%s ", p_secstodate(t))); 529156952Sume T(addstr(tmp, len, &buf, &buflen)); 530156952Sume 531156952Sume /* Signature Footprint. */ 532156952Sume footprint = ns_get16(rdata); rdata += NS_INT16SZ; 533156952Sume len = SPRINTF((tmp, "%u ", footprint)); 534156952Sume T(addstr(tmp, len, &buf, &buflen)); 535156952Sume 536156952Sume /* Signer's name. */ 537156952Sume T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 538156952Sume 539156952Sume /* Signature. */ 540156952Sume len = b64_ntop(rdata, edata - rdata, 541156952Sume base64_key, sizeof base64_key); 542156952Sume if (len > 15) { 543156952Sume T(addstr(" (", 2, &buf, &buflen)); 544156952Sume leader = "\n\t\t"; 545156952Sume spaced = 0; 546156952Sume } else 547156952Sume leader = " "; 548156952Sume if (len < 0) 549156952Sume goto formerr; 550156952Sume for (n = 0; n < len; n += 48) { 551156952Sume T(addstr(leader, strlen(leader), &buf, &buflen)); 552156952Sume T(addstr(base64_key + n, MIN(len - n, 48), 553156952Sume &buf, &buflen)); 554156952Sume } 555156952Sume if (len > 15) 556156952Sume T(addstr(" )", 2, &buf, &buflen)); 557156952Sume break; 558156952Sume } 559156952Sume 560156952Sume case ns_t_nxt: { 561156952Sume int n, c; 562156952Sume 563156952Sume /* Next domain name. */ 564156952Sume T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 565156952Sume 566156952Sume /* Type bit map. */ 567156952Sume n = edata - rdata; 568156952Sume for (c = 0; c < n*8; c++) 569156952Sume if (NS_NXT_BIT_ISSET(c, rdata)) { 570156952Sume len = SPRINTF((tmp, " %s", p_type(c))); 571156952Sume T(addstr(tmp, len, &buf, &buflen)); 572156952Sume } 573156952Sume break; 574156952Sume } 575156952Sume 576156952Sume case ns_t_cert: { 577156952Sume u_int c_type, key_tag, alg; 578156952Sume int n; 579156952Sume unsigned int siz; 580156952Sume char base64_cert[8192], tmp[40]; 581156952Sume const char *leader; 582156952Sume 583156952Sume c_type = ns_get16(rdata); rdata += NS_INT16SZ; 584156952Sume key_tag = ns_get16(rdata); rdata += NS_INT16SZ; 585156952Sume alg = (u_int) *rdata++; 586156952Sume 587156952Sume len = SPRINTF((tmp, "%d %d %d ", c_type, key_tag, alg)); 588156952Sume T(addstr(tmp, len, &buf, &buflen)); 589156952Sume siz = (edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */ 590156952Sume if (siz > sizeof(base64_cert) * 3/4) { 591156952Sume const char *str = "record too long to print"; 592156952Sume T(addstr(str, strlen(str), &buf, &buflen)); 593156952Sume } 594156952Sume else { 595156952Sume len = b64_ntop(rdata, edata-rdata, base64_cert, siz); 596156952Sume 597156952Sume if (len < 0) 598156952Sume goto formerr; 599156952Sume else if (len > 15) { 600156952Sume T(addstr(" (", 2, &buf, &buflen)); 601156952Sume leader = "\n\t\t"; 602156952Sume spaced = 0; 603156952Sume } 604156952Sume else 605156952Sume leader = " "; 606156952Sume 607156952Sume for (n = 0; n < len; n += 48) { 608156952Sume T(addstr(leader, strlen(leader), 609156952Sume &buf, &buflen)); 610156952Sume T(addstr(base64_cert + n, MIN(len - n, 48), 611156952Sume &buf, &buflen)); 612156952Sume } 613156952Sume if (len > 15) 614156952Sume T(addstr(" )", 2, &buf, &buflen)); 615156952Sume } 616156952Sume break; 617156952Sume } 618156952Sume 619156952Sume case ns_t_tkey: { 620156952Sume /* KJD - need to complete this */ 621156952Sume u_long t; 622156952Sume int mode, err, keysize; 623156952Sume 624156952Sume /* Algorithm name. */ 625156952Sume T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 626156952Sume T(addstr(" ", 1, &buf, &buflen)); 627156952Sume 628156952Sume /* Inception. */ 629156952Sume t = ns_get32(rdata); rdata += NS_INT32SZ; 630156952Sume len = SPRINTF((tmp, "%s ", p_secstodate(t))); 631156952Sume T(addstr(tmp, len, &buf, &buflen)); 632156952Sume 633156952Sume /* Experation. */ 634156952Sume t = ns_get32(rdata); rdata += NS_INT32SZ; 635156952Sume len = SPRINTF((tmp, "%s ", p_secstodate(t))); 636156952Sume T(addstr(tmp, len, &buf, &buflen)); 637156952Sume 638156952Sume /* Mode , Error, Key Size. */ 639156952Sume /* Priority, Weight, Port. */ 640156952Sume mode = ns_get16(rdata); rdata += NS_INT16SZ; 641156952Sume err = ns_get16(rdata); rdata += NS_INT16SZ; 642156952Sume keysize = ns_get16(rdata); rdata += NS_INT16SZ; 643156952Sume len = SPRINTF((tmp, "%u %u %u ", mode, err, keysize)); 644156952Sume T(addstr(tmp, len, &buf, &buflen)); 645156952Sume 646156952Sume /* XXX need to dump key, print otherdata length & other data */ 647156952Sume break; 648156952Sume } 649156952Sume 650156952Sume case ns_t_tsig: { 651156952Sume /* BEW - need to complete this */ 652156952Sume int n; 653156952Sume 654156952Sume T(len = addname(msg, msglen, &rdata, origin, &buf, &buflen)); 655156952Sume T(addstr(" ", 1, &buf, &buflen)); 656170244Sume rdata += 8; /*%< time */ 657156952Sume n = ns_get16(rdata); rdata += INT16SZ; 658170244Sume rdata += n; /*%< sig */ 659170244Sume n = ns_get16(rdata); rdata += INT16SZ; /*%< original id */ 660156952Sume sprintf(buf, "%d", ns_get16(rdata)); 661156952Sume rdata += INT16SZ; 662156952Sume addlen(strlen(buf), &buf, &buflen); 663156952Sume break; 664156952Sume } 665156952Sume 666156952Sume case ns_t_a6: { 667156952Sume struct in6_addr a; 668156952Sume int pbyte, pbit; 669156952Sume 670156952Sume /* prefix length */ 671156952Sume if (rdlen == 0U) goto formerr; 672156952Sume len = SPRINTF((tmp, "%d ", *rdata)); 673156952Sume T(addstr(tmp, len, &buf, &buflen)); 674156952Sume pbit = *rdata; 675156952Sume if (pbit > 128) goto formerr; 676156952Sume pbyte = (pbit & ~7) / 8; 677156952Sume rdata++; 678156952Sume 679156952Sume /* address suffix: provided only when prefix len != 128 */ 680156952Sume if (pbit < 128) { 681156952Sume if (rdata + pbyte >= edata) goto formerr; 682156952Sume memset(&a, 0, sizeof(a)); 683156952Sume memcpy(&a.s6_addr[pbyte], rdata, sizeof(a) - pbyte); 684156952Sume (void) inet_ntop(AF_INET6, &a, buf, buflen); 685156952Sume addlen(strlen(buf), &buf, &buflen); 686156952Sume rdata += sizeof(a) - pbyte; 687156952Sume } 688156952Sume 689156952Sume /* prefix name: provided only when prefix len > 0 */ 690156952Sume if (pbit == 0) 691156952Sume break; 692156952Sume if (rdata >= edata) goto formerr; 693156952Sume T(addstr(" ", 1, &buf, &buflen)); 694156952Sume T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); 695156952Sume 696156952Sume break; 697156952Sume } 698156952Sume 699156952Sume case ns_t_opt: { 700156952Sume len = SPRINTF((tmp, "%u bytes", class)); 701156952Sume T(addstr(tmp, len, &buf, &buflen)); 702156952Sume break; 703156952Sume } 704156952Sume 705156952Sume default: 706156952Sume comment = "unknown RR type"; 707156952Sume goto hexify; 708156952Sume } 709156952Sume return (buf - obuf); 710156952Sume formerr: 711156952Sume comment = "RR format error"; 712156952Sume hexify: { 713156952Sume int n, m; 714156952Sume char *p; 715156952Sume 716156952Sume len = SPRINTF((tmp, "\\# %u%s\t; %s", (unsigned)(edata - rdata), 717156952Sume rdlen != 0U ? " (" : "", comment)); 718156952Sume T(addstr(tmp, len, &buf, &buflen)); 719156952Sume while (rdata < edata) { 720156952Sume p = tmp; 721156952Sume p += SPRINTF((p, "\n\t")); 722156952Sume spaced = 0; 723156952Sume n = MIN(16, edata - rdata); 724156952Sume for (m = 0; m < n; m++) 725156952Sume p += SPRINTF((p, "%02x ", rdata[m])); 726156952Sume T(addstr(tmp, p - tmp, &buf, &buflen)); 727156952Sume if (n < 16) { 728156952Sume T(addstr(")", 1, &buf, &buflen)); 729156952Sume T(addtab(p - tmp + 1, 48, spaced, &buf, &buflen)); 730156952Sume } 731156952Sume p = tmp; 732156952Sume p += SPRINTF((p, "; ")); 733156952Sume for (m = 0; m < n; m++) 734156952Sume *p++ = (isascii(rdata[m]) && isprint(rdata[m])) 735156952Sume ? rdata[m] 736156952Sume : '.'; 737156952Sume T(addstr(tmp, p - tmp, &buf, &buflen)); 738156952Sume rdata += n; 739156952Sume } 740156952Sume return (buf - obuf); 741156952Sume } 742156952Sume} 743156952Sume 744156952Sume/* Private. */ 745156952Sume 746170244Sume/*% 747156952Sume * size_t 748156952Sume * prune_origin(name, origin) 749156952Sume * Find out if the name is at or under the current origin. 750156952Sume * return: 751156952Sume * Number of characters in name before start of origin, 752156952Sume * or length of name if origin does not match. 753156952Sume * notes: 754156952Sume * This function should share code with samedomain(). 755156952Sume */ 756156952Sumestatic size_t 757156952Sumeprune_origin(const char *name, const char *origin) { 758156952Sume const char *oname = name; 759156952Sume 760156952Sume while (*name != '\0') { 761156952Sume if (origin != NULL && ns_samename(name, origin) == 1) 762156952Sume return (name - oname - (name > oname)); 763156952Sume while (*name != '\0') { 764156952Sume if (*name == '\\') { 765156952Sume name++; 766156952Sume /* XXX need to handle \nnn form. */ 767156952Sume if (*name == '\0') 768156952Sume break; 769156952Sume } else if (*name == '.') { 770156952Sume name++; 771156952Sume break; 772156952Sume } 773156952Sume name++; 774156952Sume } 775156952Sume } 776156952Sume return (name - oname); 777156952Sume} 778156952Sume 779170244Sume/*% 780156952Sume * int 781156952Sume * charstr(rdata, edata, buf, buflen) 782156952Sume * Format a <character-string> into the presentation buffer. 783156952Sume * return: 784156952Sume * Number of rdata octets consumed 785156952Sume * 0 for protocol format error 786156952Sume * -1 for output buffer error 787156952Sume * side effects: 788156952Sume * buffer is advanced on success. 789156952Sume */ 790156952Sumestatic int 791156952Sumecharstr(const u_char *rdata, const u_char *edata, char **buf, size_t *buflen) { 792156952Sume const u_char *odata = rdata; 793156952Sume size_t save_buflen = *buflen; 794156952Sume char *save_buf = *buf; 795156952Sume 796156952Sume if (addstr("\"", 1, buf, buflen) < 0) 797156952Sume goto enospc; 798156952Sume if (rdata < edata) { 799156952Sume int n = *rdata; 800156952Sume 801156952Sume if (rdata + 1 + n <= edata) { 802156952Sume rdata++; 803156952Sume while (n-- > 0) { 804156952Sume if (strchr("\n\"\\", *rdata) != NULL) 805156952Sume if (addstr("\\", 1, buf, buflen) < 0) 806156952Sume goto enospc; 807156952Sume if (addstr((const char *)rdata, 1, 808156952Sume buf, buflen) < 0) 809156952Sume goto enospc; 810156952Sume rdata++; 811156952Sume } 812156952Sume } 813156952Sume } 814156952Sume if (addstr("\"", 1, buf, buflen) < 0) 815156952Sume goto enospc; 816156952Sume return (rdata - odata); 817156952Sume enospc: 818156952Sume errno = ENOSPC; 819156952Sume *buf = save_buf; 820156952Sume *buflen = save_buflen; 821156952Sume return (-1); 822156952Sume} 823156952Sume 824156952Sumestatic int 825156952Sumeaddname(const u_char *msg, size_t msglen, 826156952Sume const u_char **pp, const char *origin, 827156952Sume char **buf, size_t *buflen) 828156952Sume{ 829156952Sume size_t newlen, save_buflen = *buflen; 830156952Sume char *save_buf = *buf; 831156952Sume int n; 832156952Sume 833156952Sume n = dn_expand(msg, msg + msglen, *pp, *buf, *buflen); 834156952Sume if (n < 0) 835170244Sume goto enospc; /*%< Guess. */ 836156952Sume newlen = prune_origin(*buf, origin); 837156952Sume if (**buf == '\0') { 838156952Sume goto root; 839156952Sume } else if (newlen == 0U) { 840156952Sume /* Use "@" instead of name. */ 841156952Sume if (newlen + 2 > *buflen) 842156952Sume goto enospc; /* No room for "@\0". */ 843156952Sume (*buf)[newlen++] = '@'; 844156952Sume (*buf)[newlen] = '\0'; 845156952Sume } else { 846156952Sume if (((origin == NULL || origin[0] == '\0') || 847156952Sume (origin[0] != '.' && origin[1] != '\0' && 848156952Sume (*buf)[newlen] == '\0')) && (*buf)[newlen - 1] != '.') { 849156952Sume /* No trailing dot. */ 850156952Sume root: 851156952Sume if (newlen + 2 > *buflen) 852156952Sume goto enospc; /* No room for ".\0". */ 853156952Sume (*buf)[newlen++] = '.'; 854156952Sume (*buf)[newlen] = '\0'; 855156952Sume } 856156952Sume } 857156952Sume *pp += n; 858156952Sume addlen(newlen, buf, buflen); 859156952Sume **buf = '\0'; 860156952Sume return (newlen); 861156952Sume enospc: 862156952Sume errno = ENOSPC; 863156952Sume *buf = save_buf; 864156952Sume *buflen = save_buflen; 865156952Sume return (-1); 866156952Sume} 867156952Sume 868156952Sumestatic void 869156952Sumeaddlen(size_t len, char **buf, size_t *buflen) { 870156952Sume INSIST(len <= *buflen); 871156952Sume *buf += len; 872156952Sume *buflen -= len; 873156952Sume} 874156952Sume 875156952Sumestatic int 876156952Sumeaddstr(const char *src, size_t len, char **buf, size_t *buflen) { 877156952Sume if (len >= *buflen) { 878156952Sume errno = ENOSPC; 879156952Sume return (-1); 880156952Sume } 881156952Sume memcpy(*buf, src, len); 882156952Sume addlen(len, buf, buflen); 883156952Sume **buf = '\0'; 884156952Sume return (0); 885156952Sume} 886156952Sume 887156952Sumestatic int 888156952Sumeaddtab(size_t len, size_t target, int spaced, char **buf, size_t *buflen) { 889156952Sume size_t save_buflen = *buflen; 890156952Sume char *save_buf = *buf; 891156952Sume int t; 892156952Sume 893156952Sume if (spaced || len >= target - 1) { 894156952Sume T(addstr(" ", 2, buf, buflen)); 895156952Sume spaced = 1; 896156952Sume } else { 897156952Sume for (t = (target - len - 1) / 8; t >= 0; t--) 898156952Sume if (addstr("\t", 1, buf, buflen) < 0) { 899156952Sume *buflen = save_buflen; 900156952Sume *buf = save_buf; 901156952Sume return (-1); 902156952Sume } 903156952Sume spaced = 0; 904156952Sume } 905156952Sume return (spaced); 906156952Sume} 907170244Sume 908170244Sume/*! \file */ 909