other-licenses/android/ns_print.c

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

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

mercurial