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