other-licenses/android/ns_print.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/other-licenses/android/ns_print.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,928 @@
     1.4 +/*	$NetBSD: ns_print.c,v 1.5 2004/11/07 02:19:49 christos Exp $	*/
     1.5 +
     1.6 +/*
     1.7 + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
     1.8 + * Copyright (c) 1996-1999 by Internet Software Consortium.
     1.9 + *
    1.10 + * Permission to use, copy, modify, and distribute this software for any
    1.11 + * purpose with or without fee is hereby granted, provided that the above
    1.12 + * copyright notice and this permission notice appear in all copies.
    1.13 + *
    1.14 + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
    1.15 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
    1.16 + * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
    1.17 + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
    1.18 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
    1.19 + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
    1.20 + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    1.21 + */
    1.22 +
    1.23 +/*
    1.24 + * This version of this file is derived from Android 2.3 "Gingerbread",
    1.25 + * which contains uncredited changes by Android/Google developers.  It has
    1.26 + * been modified in 2011 for use in the Android build of Mozilla Firefox by
    1.27 + * Mozilla contributors (including Michael Edwards <m.k.edwards@gmail.com>,
    1.28 + * and Steve Workman <sjhworkman@gmail.com>).
    1.29 + * These changes are offered under the same license as the original NetBSD
    1.30 + * file, whose copyright and license are unchanged above.
    1.31 + */
    1.32 +
    1.33 +#define ANDROID_CHANGES 1
    1.34 +#define MOZILLA_NECKO_EXCLUDE_CODE 1 
    1.35 +
    1.36 +#include <sys/cdefs.h>
    1.37 +#ifndef lint
    1.38 +#ifdef notdef
    1.39 +static const char rcsid[] = "Id: ns_print.c,v 1.3.2.1.4.5 2004/07/28 20:16:45 marka Exp";
    1.40 +#else
    1.41 +__RCSID("$NetBSD: ns_print.c,v 1.5 2004/11/07 02:19:49 christos Exp $");
    1.42 +#endif
    1.43 +#endif
    1.44 +
    1.45 +/* Import. */
    1.46 +
    1.47 +#include <sys/types.h>
    1.48 +#include <sys/socket.h>
    1.49 +
    1.50 +#include <netinet/in.h>
    1.51 +#include "arpa_nameser.h"
    1.52 +#include <arpa/inet.h>
    1.53 +
    1.54 +#include "assertions.h"
    1.55 +#include "dst.h"
    1.56 +#include <errno.h>
    1.57 +#ifdef ANDROID_CHANGES
    1.58 +#include "resolv_private.h"
    1.59 +#else
    1.60 +#include <resolv.h>
    1.61 +#endif
    1.62 +#include <string.h>
    1.63 +#include <ctype.h>
    1.64 +#include <assert.h>
    1.65 +
    1.66 +#ifdef SPRINTF_CHAR
    1.67 +# define SPRINTF(x) strlen(sprintf/**/x)
    1.68 +#else
    1.69 +# define SPRINTF(x) ((size_t)sprintf x)
    1.70 +#endif
    1.71 +
    1.72 +#ifndef MIN
    1.73 +#define	MIN(x,y)	((x)<(y)?(x):(y))
    1.74 +#endif
    1.75 +
    1.76 +/* Forward. */
    1.77 +
    1.78 +static size_t	prune_origin(const char *name, const char *origin);
    1.79 +static int	charstr(const u_char *rdata, const u_char *edata,
    1.80 +			char **buf, size_t *buflen);
    1.81 +static int	addname(const u_char *msg, size_t msglen,
    1.82 +			const u_char **p, const char *origin,
    1.83 +			char **buf, size_t *buflen);
    1.84 +static void	addlen(size_t len, char **buf, size_t *buflen);
    1.85 +static int	addstr(const char *src, size_t len,
    1.86 +		       char **buf, size_t *buflen);
    1.87 +static int	addtab(size_t len, size_t target, int spaced,
    1.88 +		       char **buf, size_t *buflen);
    1.89 +
    1.90 +/* Macros. */
    1.91 +
    1.92 +#define	T(x) \
    1.93 +	do { \
    1.94 +		if ((x) < 0) \
    1.95 +			return (-1); \
    1.96 +	} while (/*CONSTCOND*/0)
    1.97 +
    1.98 +/* Public. */
    1.99 +
   1.100 +/*
   1.101 + * int
   1.102 + * ns_sprintrr(handle, rr, name_ctx, origin, buf, buflen)
   1.103 + *	Convert an RR to presentation format.
   1.104 + * return:
   1.105 + *	Number of characters written to buf, or -1 (check errno).
   1.106 + */
   1.107 +int
   1.108 +ns_sprintrr(const ns_msg *handle, const ns_rr *rr,
   1.109 +	    const char *name_ctx, const char *origin,
   1.110 +	    char *buf, size_t buflen)
   1.111 +{
   1.112 +	int n;
   1.113 +
   1.114 +	n = ns_sprintrrf(ns_msg_base(*handle), ns_msg_size(*handle),
   1.115 +			 ns_rr_name(*rr), ns_rr_class(*rr), ns_rr_type(*rr),
   1.116 +			 ns_rr_ttl(*rr), ns_rr_rdata(*rr), ns_rr_rdlen(*rr),
   1.117 +			 name_ctx, origin, buf, buflen);
   1.118 +	return (n);
   1.119 +}
   1.120 +
   1.121 +/*
   1.122 + * int
   1.123 + * ns_sprintrrf(msg, msglen, name, class, type, ttl, rdata, rdlen,
   1.124 + *	       name_ctx, origin, buf, buflen)
   1.125 + *	Convert the fields of an RR into presentation format.
   1.126 + * return:
   1.127 + *	Number of characters written to buf, or -1 (check errno).
   1.128 + */
   1.129 +int
   1.130 +ns_sprintrrf(const u_char *msg, size_t msglen,
   1.131 +	    const char *name, ns_class class, ns_type type,
   1.132 +	    u_long ttl, const u_char *rdata, size_t rdlen,
   1.133 +	    const char *name_ctx, const char *origin,
   1.134 +	    char *buf, size_t buflen)
   1.135 +{
   1.136 +	const char *obuf = buf;
   1.137 +	const u_char *edata = rdata + rdlen;
   1.138 +	int spaced = 0;
   1.139 +
   1.140 +	const char *comment;
   1.141 +	char tmp[100];
   1.142 +	int len, x;
   1.143 +
   1.144 +	/*
   1.145 +	 * Owner.
   1.146 +	 */
   1.147 +	if (name_ctx != NULL && ns_samename(name_ctx, name) == 1) {
   1.148 +		T(addstr("\t\t\t", (size_t)3, &buf, &buflen));
   1.149 +	} else {
   1.150 +		len = prune_origin(name, origin);
   1.151 +		if (*name == '\0') {
   1.152 +			goto root;
   1.153 +		} else if (len == 0) {
   1.154 +			T(addstr("@\t\t\t", (size_t)4, &buf, &buflen));
   1.155 +		} else {
   1.156 +			T(addstr(name, (size_t)len, &buf, &buflen));
   1.157 +			/* Origin not used or not root, and no trailing dot? */
   1.158 +			if (((origin == NULL || origin[0] == '\0') ||
   1.159 +			    (origin[0] != '.' && origin[1] != '\0' &&
   1.160 +			    name[len] == '\0')) && name[len - 1] != '.') {
   1.161 + root:
   1.162 +				T(addstr(".", (size_t)1, &buf, &buflen));
   1.163 +				len++;
   1.164 +			}
   1.165 +			T(spaced = addtab((size_t)len, 24, spaced, &buf, &buflen));
   1.166 +		}
   1.167 +	}
   1.168 +
   1.169 +	/*
   1.170 +	 * TTL, Class, Type.
   1.171 +	 */
   1.172 +	T(x = ns_format_ttl(ttl, buf, buflen));
   1.173 +	addlen((size_t)x, &buf, &buflen);
   1.174 +	len = SPRINTF((tmp, " %s %s", p_class(class), p_type(type)));
   1.175 +	T(addstr(tmp, (size_t)len, &buf, &buflen));
   1.176 +	T(spaced = addtab((size_t)(x + len), (size_t)16, spaced, &buf, &buflen));
   1.177 +
   1.178 +	/*
   1.179 +	 * RData.
   1.180 +	 */
   1.181 +	switch (type) {
   1.182 +	case ns_t_a:
   1.183 +		if (rdlen != (size_t)NS_INADDRSZ)
   1.184 +			goto formerr;
   1.185 +		(void) inet_ntop(AF_INET, rdata, buf, buflen);
   1.186 +		addlen(strlen(buf), &buf, &buflen);
   1.187 +		break;
   1.188 +
   1.189 +	case ns_t_cname:
   1.190 +	case ns_t_mb:
   1.191 +	case ns_t_mg:
   1.192 +	case ns_t_mr:
   1.193 +	case ns_t_ns:
   1.194 +	case ns_t_ptr:
   1.195 +	case ns_t_dname:
   1.196 +		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
   1.197 +		break;
   1.198 +
   1.199 +	case ns_t_hinfo:
   1.200 +	case ns_t_isdn:
   1.201 +		/* First word. */
   1.202 +		T(len = charstr(rdata, edata, &buf, &buflen));
   1.203 +		if (len == 0)
   1.204 +			goto formerr;
   1.205 +		rdata += len;
   1.206 +		T(addstr(" ", (size_t)1, &buf, &buflen));
   1.207 +
   1.208 +
   1.209 +		/* Second word, optional in ISDN records. */
   1.210 +		if (type == ns_t_isdn && rdata == edata)
   1.211 +			break;
   1.212 +
   1.213 +		T(len = charstr(rdata, edata, &buf, &buflen));
   1.214 +		if (len == 0)
   1.215 +			goto formerr;
   1.216 +		rdata += len;
   1.217 +		break;
   1.218 +
   1.219 +	case ns_t_soa: {
   1.220 +		u_long t;
   1.221 +
   1.222 +		/* Server name. */
   1.223 +		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
   1.224 +		T(addstr(" ", (size_t)1, &buf, &buflen));
   1.225 +
   1.226 +		/* Administrator name. */
   1.227 +		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
   1.228 +		T(addstr(" (\n", (size_t)3, &buf, &buflen));
   1.229 +		spaced = 0;
   1.230 +
   1.231 +		if ((edata - rdata) != 5*NS_INT32SZ)
   1.232 +			goto formerr;
   1.233 +
   1.234 +		/* Serial number. */
   1.235 +		t = ns_get32(rdata);  rdata += NS_INT32SZ;
   1.236 +		T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen));
   1.237 +		len = SPRINTF((tmp, "%lu", t));
   1.238 +		T(addstr(tmp, (size_t)len, &buf, &buflen));
   1.239 +		T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen));
   1.240 +		T(addstr("; serial\n", (size_t)9, &buf, &buflen));
   1.241 +		spaced = 0;
   1.242 +
   1.243 +		/* Refresh interval. */
   1.244 +		t = ns_get32(rdata);  rdata += NS_INT32SZ;
   1.245 +		T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen));
   1.246 +		T(len = ns_format_ttl(t, buf, buflen));
   1.247 +		addlen((size_t)len, &buf, &buflen);
   1.248 +		T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen));
   1.249 +		T(addstr("; refresh\n", (size_t)10, &buf, &buflen));
   1.250 +		spaced = 0;
   1.251 +
   1.252 +		/* Retry interval. */
   1.253 +		t = ns_get32(rdata);  rdata += NS_INT32SZ;
   1.254 +		T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen));
   1.255 +		T(len = ns_format_ttl(t, buf, buflen));
   1.256 +		addlen((size_t)len, &buf, &buflen);
   1.257 +		T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen));
   1.258 +		T(addstr("; retry\n", (size_t)8, &buf, &buflen));
   1.259 +		spaced = 0;
   1.260 +
   1.261 +		/* Expiry. */
   1.262 +		t = ns_get32(rdata);  rdata += NS_INT32SZ;
   1.263 +		T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen));
   1.264 +		T(len = ns_format_ttl(t, buf, buflen));
   1.265 +		addlen((size_t)len, &buf, &buflen);
   1.266 +		T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen));
   1.267 +		T(addstr("; expiry\n", (size_t)9, &buf, &buflen));
   1.268 +		spaced = 0;
   1.269 +
   1.270 +		/* Minimum TTL. */
   1.271 +		t = ns_get32(rdata);  rdata += NS_INT32SZ;
   1.272 +		T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen));
   1.273 +		T(len = ns_format_ttl(t, buf, buflen));
   1.274 +		addlen((size_t)len, &buf, &buflen);
   1.275 +		T(addstr(" )", (size_t)2, &buf, &buflen));
   1.276 +		T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen));
   1.277 +		T(addstr("; minimum\n", (size_t)10, &buf, &buflen));
   1.278 +
   1.279 +		break;
   1.280 +	    }
   1.281 +
   1.282 +	case ns_t_mx:
   1.283 +	case ns_t_afsdb:
   1.284 +	case ns_t_rt: {
   1.285 +		u_int t;
   1.286 +
   1.287 +		if (rdlen < (size_t)NS_INT16SZ)
   1.288 +			goto formerr;
   1.289 +
   1.290 +		/* Priority. */
   1.291 +		t = ns_get16(rdata);
   1.292 +		rdata += NS_INT16SZ;
   1.293 +		len = SPRINTF((tmp, "%u ", t));
   1.294 +		T(addstr(tmp, (size_t)len, &buf, &buflen));
   1.295 +
   1.296 +		/* Target. */
   1.297 +		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
   1.298 +
   1.299 +		break;
   1.300 +	    }
   1.301 +
   1.302 +	case ns_t_px: {
   1.303 +		u_int t;
   1.304 +
   1.305 +		if (rdlen < (size_t)NS_INT16SZ)
   1.306 +			goto formerr;
   1.307 +
   1.308 +		/* Priority. */
   1.309 +		t = ns_get16(rdata);
   1.310 +		rdata += NS_INT16SZ;
   1.311 +		len = SPRINTF((tmp, "%u ", t));
   1.312 +		T(addstr(tmp, (size_t)len, &buf, &buflen));
   1.313 +
   1.314 +		/* Name1. */
   1.315 +		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
   1.316 +		T(addstr(" ", (size_t)1, &buf, &buflen));
   1.317 +
   1.318 +		/* Name2. */
   1.319 +		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
   1.320 +
   1.321 +		break;
   1.322 +	    }
   1.323 +
   1.324 +	case ns_t_x25:
   1.325 +		T(len = charstr(rdata, edata, &buf, &buflen));
   1.326 +		if (len == 0)
   1.327 +			goto formerr;
   1.328 +		rdata += len;
   1.329 +		break;
   1.330 +
   1.331 +	case ns_t_txt:
   1.332 +		while (rdata < edata) {
   1.333 +			T(len = charstr(rdata, edata, &buf, &buflen));
   1.334 +			if (len == 0)
   1.335 +				goto formerr;
   1.336 +			rdata += len;
   1.337 +			if (rdata < edata)
   1.338 +				T(addstr(" ", (size_t)1, &buf, &buflen));
   1.339 +		}
   1.340 +		break;
   1.341 +
   1.342 +	case ns_t_nsap: {
   1.343 +		char t[2+255*3];
   1.344 +
   1.345 +		(void) inet_nsap_ntoa((int)rdlen, rdata, t);
   1.346 +		T(addstr(t, strlen(t), &buf, &buflen));
   1.347 +		break;
   1.348 +	    }
   1.349 +
   1.350 +	case ns_t_aaaa:
   1.351 +		if (rdlen != (size_t)NS_IN6ADDRSZ)
   1.352 +			goto formerr;
   1.353 +		(void) inet_ntop(AF_INET6, rdata, buf, buflen);
   1.354 +		addlen(strlen(buf), &buf, &buflen);
   1.355 +		break;
   1.356 +
   1.357 +	case ns_t_loc: {
   1.358 +		char t[255];
   1.359 +
   1.360 +		/* XXX protocol format checking? */
   1.361 +		(void) loc_ntoa(rdata, t);
   1.362 +		T(addstr(t, strlen(t), &buf, &buflen));
   1.363 +		break;
   1.364 +	    }
   1.365 +
   1.366 +	case ns_t_naptr: {
   1.367 +		u_int order, preference;
   1.368 +		char t[50];
   1.369 +
   1.370 +		if (rdlen < 2U*NS_INT16SZ)
   1.371 +			goto formerr;
   1.372 +
   1.373 +		/* Order, Precedence. */
   1.374 +		order = ns_get16(rdata);	rdata += NS_INT16SZ;
   1.375 +		preference = ns_get16(rdata);	rdata += NS_INT16SZ;
   1.376 +		len = SPRINTF((t, "%u %u ", order, preference));
   1.377 +		T(addstr(t, (size_t)len, &buf, &buflen));
   1.378 +
   1.379 +		/* Flags. */
   1.380 +		T(len = charstr(rdata, edata, &buf, &buflen));
   1.381 +		if (len == 0)
   1.382 +			goto formerr;
   1.383 +		rdata += len;
   1.384 +		T(addstr(" ", (size_t)1, &buf, &buflen));
   1.385 +
   1.386 +		/* Service. */
   1.387 +		T(len = charstr(rdata, edata, &buf, &buflen));
   1.388 +		if (len == 0)
   1.389 +			goto formerr;
   1.390 +		rdata += len;
   1.391 +		T(addstr(" ", (size_t)1, &buf, &buflen));
   1.392 +
   1.393 +		/* Regexp. */
   1.394 +		T(len = charstr(rdata, edata, &buf, &buflen));
   1.395 +		if (len < 0)
   1.396 +			return (-1);
   1.397 +		if (len == 0)
   1.398 +			goto formerr;
   1.399 +		rdata += len;
   1.400 +		T(addstr(" ", (size_t)1, &buf, &buflen));
   1.401 +
   1.402 +		/* Server. */
   1.403 +		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
   1.404 +		break;
   1.405 +	    }
   1.406 +
   1.407 +	case ns_t_srv: {
   1.408 +		u_int priority, weight, port;
   1.409 +		char t[50];
   1.410 +
   1.411 +		if (rdlen < 3U*NS_INT16SZ)
   1.412 +			goto formerr;
   1.413 +
   1.414 +		/* Priority, Weight, Port. */
   1.415 +		priority = ns_get16(rdata);  rdata += NS_INT16SZ;
   1.416 +		weight   = ns_get16(rdata);  rdata += NS_INT16SZ;
   1.417 +		port     = ns_get16(rdata);  rdata += NS_INT16SZ;
   1.418 +		len = SPRINTF((t, "%u %u %u ", priority, weight, port));
   1.419 +		T(addstr(t, (size_t)len, &buf, &buflen));
   1.420 +
   1.421 +		/* Server. */
   1.422 +		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
   1.423 +		break;
   1.424 +	    }
   1.425 +
   1.426 +	case ns_t_minfo:
   1.427 +	case ns_t_rp:
   1.428 +		/* Name1. */
   1.429 +		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
   1.430 +		T(addstr(" ", (size_t)1, &buf, &buflen));
   1.431 +
   1.432 +		/* Name2. */
   1.433 +		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
   1.434 +
   1.435 +		break;
   1.436 +
   1.437 +	case ns_t_wks: {
   1.438 +		int n, lcnt;
   1.439 +
   1.440 +		if (rdlen < 1U + NS_INT32SZ)
   1.441 +			goto formerr;
   1.442 +
   1.443 +		/* Address. */
   1.444 +		(void) inet_ntop(AF_INET, rdata, buf, buflen);
   1.445 +		addlen(strlen(buf), &buf, &buflen);
   1.446 +		rdata += NS_INADDRSZ;
   1.447 +
   1.448 +		/* Protocol. */
   1.449 +		len = SPRINTF((tmp, " %u ( ", *rdata));
   1.450 +		T(addstr(tmp, (size_t)len, &buf, &buflen));
   1.451 +		rdata += NS_INT8SZ;
   1.452 +
   1.453 +		/* Bit map. */
   1.454 +		n = 0;
   1.455 +		lcnt = 0;
   1.456 +		while (rdata < edata) {
   1.457 +			u_int c = *rdata++;
   1.458 +			do {
   1.459 +				if (c & 0200) {
   1.460 +					if (lcnt == 0) {
   1.461 +						T(addstr("\n\t\t\t\t", (size_t)5,
   1.462 +							 &buf, &buflen));
   1.463 +						lcnt = 10;
   1.464 +						spaced = 0;
   1.465 +					}
   1.466 +					len = SPRINTF((tmp, "%d ", n));
   1.467 +					T(addstr(tmp, (size_t)len, &buf, &buflen));
   1.468 +					lcnt--;
   1.469 +				}
   1.470 +				c <<= 1;
   1.471 +			} while (++n & 07);
   1.472 +		}
   1.473 +		T(addstr(")", (size_t)1, &buf, &buflen));
   1.474 +
   1.475 +		break;
   1.476 +	    }
   1.477 +
   1.478 +	case ns_t_key: {
   1.479 +		char base64_key[NS_MD5RSA_MAX_BASE64];
   1.480 +		u_int keyflags, protocol, algorithm, key_id;
   1.481 +		const char *leader;
   1.482 +		int n;
   1.483 +
   1.484 +		if (rdlen < 0U + NS_INT16SZ + NS_INT8SZ + NS_INT8SZ)
   1.485 +			goto formerr;
   1.486 +
   1.487 +		/* Key flags, Protocol, Algorithm. */
   1.488 +#if !defined(MOZILLA_NECKO_EXCLUDE_CODE) && !defined(_LIBC)
   1.489 +		key_id = dst_s_dns_key_id(rdata, edata-rdata);
   1.490 +#else
   1.491 +		key_id = 0;
   1.492 +#endif
   1.493 +		keyflags = ns_get16(rdata);  rdata += NS_INT16SZ;
   1.494 +		protocol = *rdata++;
   1.495 +		algorithm = *rdata++;
   1.496 +		len = SPRINTF((tmp, "0x%04x %u %u",
   1.497 +			       keyflags, protocol, algorithm));
   1.498 +		T(addstr(tmp, (size_t)len, &buf, &buflen));
   1.499 +
   1.500 +		/* Public key data. */
   1.501 +		len = b64_ntop(rdata, (size_t)(edata - rdata),
   1.502 +			       base64_key, sizeof base64_key);
   1.503 +		if (len < 0)
   1.504 +			goto formerr;
   1.505 +		if (len > 15) {
   1.506 +			T(addstr(" (", (size_t)2, &buf, &buflen));
   1.507 +			leader = "\n\t\t";
   1.508 +			spaced = 0;
   1.509 +		} else
   1.510 +			leader = " ";
   1.511 +		for (n = 0; n < len; n += 48) {
   1.512 +			T(addstr(leader, strlen(leader), &buf, &buflen));
   1.513 +			T(addstr(base64_key + n, (size_t)MIN(len - n, 48),
   1.514 +				 &buf, &buflen));
   1.515 +		}
   1.516 +		if (len > 15)
   1.517 +			T(addstr(" )", (size_t)2, &buf, &buflen));
   1.518 +		n = SPRINTF((tmp, " ; key_tag= %u", key_id));
   1.519 +		T(addstr(tmp, (size_t)n, &buf, &buflen));
   1.520 +
   1.521 +		break;
   1.522 +	    }
   1.523 +
   1.524 +	case ns_t_sig: {
   1.525 +		char base64_key[NS_MD5RSA_MAX_BASE64];
   1.526 +		u_int typ, algorithm, labels, footprint;
   1.527 +		const char *leader;
   1.528 +		u_long t;
   1.529 +		int n;
   1.530 +
   1.531 +		if (rdlen < 22U)
   1.532 +			goto formerr;
   1.533 +
   1.534 +		/* Type covered, Algorithm, Label count, Original TTL. */
   1.535 +	        typ = ns_get16(rdata);  rdata += NS_INT16SZ;
   1.536 +		algorithm = *rdata++;
   1.537 +		labels = *rdata++;
   1.538 +		t = ns_get32(rdata);  rdata += NS_INT32SZ;
   1.539 +		len = SPRINTF((tmp, "%s %d %d %lu ",
   1.540 +			       p_type((int)typ), algorithm, labels, t));
   1.541 +		T(addstr(tmp, (size_t)len, &buf, &buflen));
   1.542 +		if (labels > (u_int)dn_count_labels(name))
   1.543 +			goto formerr;
   1.544 +
   1.545 +		/* Signature expiry. */
   1.546 +		t = ns_get32(rdata);  rdata += NS_INT32SZ;
   1.547 +		len = SPRINTF((tmp, "%s ", p_secstodate(t)));
   1.548 +		T(addstr(tmp, (size_t)len, &buf, &buflen));
   1.549 +
   1.550 +		/* Time signed. */
   1.551 +		t = ns_get32(rdata);  rdata += NS_INT32SZ;
   1.552 +		len = SPRINTF((tmp, "%s ", p_secstodate(t)));
   1.553 +		T(addstr(tmp, (size_t)len, &buf, &buflen));
   1.554 +
   1.555 +		/* Signature Footprint. */
   1.556 +		footprint = ns_get16(rdata);  rdata += NS_INT16SZ;
   1.557 +		len = SPRINTF((tmp, "%u ", footprint));
   1.558 +		T(addstr(tmp, (size_t)len, &buf, &buflen));
   1.559 +
   1.560 +		/* Signer's name. */
   1.561 +		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
   1.562 +
   1.563 +		/* Signature. */
   1.564 +		len = b64_ntop(rdata, (size_t)(edata - rdata),
   1.565 +			       base64_key, sizeof base64_key);
   1.566 +		if (len > 15) {
   1.567 +			T(addstr(" (", (size_t)2, &buf, &buflen));
   1.568 +			leader = "\n\t\t";
   1.569 +			spaced = 0;
   1.570 +		} else
   1.571 +			leader = " ";
   1.572 +		if (len < 0)
   1.573 +			goto formerr;
   1.574 +		for (n = 0; n < len; n += 48) {
   1.575 +			T(addstr(leader, strlen(leader), &buf, &buflen));
   1.576 +			T(addstr(base64_key + n, (size_t)MIN(len - n, 48),
   1.577 +				 &buf, &buflen));
   1.578 +		}
   1.579 +		if (len > 15)
   1.580 +			T(addstr(" )", (size_t)2, &buf, &buflen));
   1.581 +		break;
   1.582 +	    }
   1.583 +
   1.584 +	case ns_t_nxt: {
   1.585 +		int n, c;
   1.586 +
   1.587 +		/* Next domain name. */
   1.588 +		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
   1.589 +
   1.590 +		/* Type bit map. */
   1.591 +		n = edata - rdata;
   1.592 +		for (c = 0; c < n*8; c++)
   1.593 +			if (NS_NXT_BIT_ISSET(c, rdata)) {
   1.594 +				len = SPRINTF((tmp, " %s", p_type(c)));
   1.595 +				T(addstr(tmp, (size_t)len, &buf, &buflen));
   1.596 +			}
   1.597 +		break;
   1.598 +	    }
   1.599 +
   1.600 +	case ns_t_cert: {
   1.601 +		u_int c_type, key_tag, alg;
   1.602 +		int n;
   1.603 +		unsigned int siz;
   1.604 +		char base64_cert[8192], tmp1[40];
   1.605 +		const char *leader;
   1.606 +
   1.607 +		c_type  = ns_get16(rdata); rdata += NS_INT16SZ;
   1.608 +		key_tag = ns_get16(rdata); rdata += NS_INT16SZ;
   1.609 +		alg = (u_int) *rdata++;
   1.610 +
   1.611 +		len = SPRINTF((tmp1, "%d %d %d ", c_type, key_tag, alg));
   1.612 +		T(addstr(tmp1, (size_t)len, &buf, &buflen));
   1.613 +		siz = (edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */
   1.614 +		if (siz > sizeof(base64_cert) * 3/4) {
   1.615 +			const char *str = "record too long to print";
   1.616 +			T(addstr(str, strlen(str), &buf, &buflen));
   1.617 +		}
   1.618 +		else {
   1.619 +			len = b64_ntop(rdata, (size_t)(edata-rdata),
   1.620 +			    base64_cert, siz);
   1.621 +
   1.622 +			if (len < 0)
   1.623 +				goto formerr;
   1.624 +			else if (len > 15) {
   1.625 +				T(addstr(" (", (size_t)2, &buf, &buflen));
   1.626 +				leader = "\n\t\t";
   1.627 +				spaced = 0;
   1.628 +			}
   1.629 +			else
   1.630 +				leader = " ";
   1.631 +
   1.632 +			for (n = 0; n < len; n += 48) {
   1.633 +				T(addstr(leader, strlen(leader),
   1.634 +					 &buf, &buflen));
   1.635 +				T(addstr(base64_cert + n, (size_t)MIN(len - n, 48),
   1.636 +					 &buf, &buflen));
   1.637 +			}
   1.638 +			if (len > 15)
   1.639 +				T(addstr(" )", (size_t)2, &buf, &buflen));
   1.640 +		}
   1.641 +		break;
   1.642 +	    }
   1.643 +
   1.644 +	case ns_t_tkey: {
   1.645 +		/* KJD - need to complete this */
   1.646 +		u_long t;
   1.647 +		int mode, err, keysize;
   1.648 +
   1.649 +		/* Algorithm name. */
   1.650 +		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
   1.651 +		T(addstr(" ", (size_t)1, &buf, &buflen));
   1.652 +
   1.653 +		/* Inception. */
   1.654 +		t = ns_get32(rdata);  rdata += NS_INT32SZ;
   1.655 +		len = SPRINTF((tmp, "%s ", p_secstodate(t)));
   1.656 +		T(addstr(tmp, (size_t)len, &buf, &buflen));
   1.657 +
   1.658 +		/* Experation. */
   1.659 +		t = ns_get32(rdata);  rdata += NS_INT32SZ;
   1.660 +		len = SPRINTF((tmp, "%s ", p_secstodate(t)));
   1.661 +		T(addstr(tmp, (size_t)len, &buf, &buflen));
   1.662 +
   1.663 +		/* Mode , Error, Key Size. */
   1.664 +		/* Priority, Weight, Port. */
   1.665 +		mode = ns_get16(rdata);  rdata += NS_INT16SZ;
   1.666 +		err  = ns_get16(rdata);  rdata += NS_INT16SZ;
   1.667 +		keysize  = ns_get16(rdata);  rdata += NS_INT16SZ;
   1.668 +		len = SPRINTF((tmp, "%u %u %u ", mode, err, keysize));
   1.669 +		T(addstr(tmp, (size_t)len, &buf, &buflen));
   1.670 +
   1.671 +		/* XXX need to dump key, print otherdata length & other data */
   1.672 +		break;
   1.673 +	    }
   1.674 +
   1.675 +	case ns_t_tsig: {
   1.676 +		/* BEW - need to complete this */
   1.677 +		int n;
   1.678 +
   1.679 +		T(len = addname(msg, msglen, &rdata, origin, &buf, &buflen));
   1.680 +		T(addstr(" ", (size_t)1, &buf, &buflen));
   1.681 +		rdata += 8; /* time */
   1.682 +		n = ns_get16(rdata); rdata += INT16SZ;
   1.683 +		rdata += n; /* sig */
   1.684 +		n = ns_get16(rdata); rdata += INT16SZ; /* original id */
   1.685 +		sprintf(buf, "%d", ns_get16(rdata));
   1.686 +		rdata += INT16SZ;
   1.687 +		addlen(strlen(buf), &buf, &buflen);
   1.688 +		break;
   1.689 +	    }
   1.690 +
   1.691 +	case ns_t_a6: {
   1.692 +		struct in6_addr a;
   1.693 +		int pbyte, pbit;
   1.694 +
   1.695 +		/* prefix length */
   1.696 +		if (rdlen == 0U) goto formerr;
   1.697 +		len = SPRINTF((tmp, "%d ", *rdata));
   1.698 +		T(addstr(tmp, (size_t)len, &buf, &buflen));
   1.699 +		pbit = *rdata;
   1.700 +		if (pbit > 128) goto formerr;
   1.701 +		pbyte = (pbit & ~7) / 8;
   1.702 +		rdata++;
   1.703 +
   1.704 +		/* address suffix: provided only when prefix len != 128 */
   1.705 +		if (pbit < 128) {
   1.706 +			if (rdata + pbyte >= edata) goto formerr;
   1.707 +			memset(&a, 0, sizeof(a));
   1.708 +			memcpy(&a.s6_addr[pbyte], rdata, sizeof(a) - pbyte);
   1.709 +			(void) inet_ntop(AF_INET6, &a, buf, buflen);
   1.710 +			addlen(strlen(buf), &buf, &buflen);
   1.711 +			rdata += sizeof(a) - pbyte;
   1.712 +		}
   1.713 +
   1.714 +		/* prefix name: provided only when prefix len > 0 */
   1.715 +		if (pbit == 0)
   1.716 +			break;
   1.717 +		if (rdata >= edata) goto formerr;
   1.718 +		T(addstr(" ", (size_t)1, &buf, &buflen));
   1.719 +		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
   1.720 +
   1.721 +		break;
   1.722 +	    }
   1.723 +
   1.724 +	case ns_t_opt: {
   1.725 +		len = SPRINTF((tmp, "%u bytes", class));
   1.726 +		T(addstr(tmp, (size_t)len, &buf, &buflen));
   1.727 +		break;
   1.728 +	    }
   1.729 +
   1.730 +	default:
   1.731 +		comment = "unknown RR type";
   1.732 +		goto hexify;
   1.733 +	}
   1.734 +	return (buf - obuf);
   1.735 + formerr:
   1.736 +	comment = "RR format error";
   1.737 + hexify: {
   1.738 +	int n, m;
   1.739 +	char *p;
   1.740 +
   1.741 +	len = SPRINTF((tmp, "\\# %tu%s\t; %s", edata - rdata,
   1.742 +		       rdlen != 0 ? " (" : "", comment));
   1.743 +	T(addstr(tmp, (size_t)len, &buf, &buflen));
   1.744 +	while (rdata < edata) {
   1.745 +		p = tmp;
   1.746 +		p += SPRINTF((p, "\n\t"));
   1.747 +		spaced = 0;
   1.748 +		n = MIN(16, edata - rdata);
   1.749 +		for (m = 0; m < n; m++)
   1.750 +			p += SPRINTF((p, "%02x ", rdata[m]));
   1.751 +		T(addstr(tmp, (size_t)(p - tmp), &buf, &buflen));
   1.752 +		if (n < 16) {
   1.753 +			T(addstr(")", (size_t)1, &buf, &buflen));
   1.754 +			T(addtab((size_t)(p - tmp + 1), (size_t)48, spaced, &buf, &buflen));
   1.755 +		}
   1.756 +		p = tmp;
   1.757 +		p += SPRINTF((p, "; "));
   1.758 +		for (m = 0; m < n; m++)
   1.759 +			*p++ = (isascii(rdata[m]) && isprint(rdata[m]))
   1.760 +				? rdata[m]
   1.761 +				: '.';
   1.762 +		T(addstr(tmp, (size_t)(p - tmp), &buf, &buflen));
   1.763 +		rdata += n;
   1.764 +	}
   1.765 +	return (buf - obuf);
   1.766 +    }
   1.767 +}
   1.768 +
   1.769 +/* Private. */
   1.770 +
   1.771 +/*
   1.772 + * size_t
   1.773 + * prune_origin(name, origin)
   1.774 + *	Find out if the name is at or under the current origin.
   1.775 + * return:
   1.776 + *	Number of characters in name before start of origin,
   1.777 + *	or length of name if origin does not match.
   1.778 + * notes:
   1.779 + *	This function should share code with samedomain().
   1.780 + */
   1.781 +static size_t
   1.782 +prune_origin(const char *name, const char *origin) {
   1.783 +	const char *oname = name;
   1.784 +
   1.785 +	while (*name != '\0') {
   1.786 +		if (origin != NULL && ns_samename(name, origin) == 1)
   1.787 +			return (name - oname - (name > oname));
   1.788 +		while (*name != '\0') {
   1.789 +			if (*name == '\\') {
   1.790 +				name++;
   1.791 +				/* XXX need to handle \nnn form. */
   1.792 +				if (*name == '\0')
   1.793 +					break;
   1.794 +			} else if (*name == '.') {
   1.795 +				name++;
   1.796 +				break;
   1.797 +			}
   1.798 +			name++;
   1.799 +		}
   1.800 +	}
   1.801 +	return (name - oname);
   1.802 +}
   1.803 +
   1.804 +/*
   1.805 + * int
   1.806 + * charstr(rdata, edata, buf, buflen)
   1.807 + *	Format a <character-string> into the presentation buffer.
   1.808 + * return:
   1.809 + *	Number of rdata octets consumed
   1.810 + *	0 for protocol format error
   1.811 + *	-1 for output buffer error
   1.812 + * side effects:
   1.813 + *	buffer is advanced on success.
   1.814 + */
   1.815 +static int
   1.816 +charstr(const u_char *rdata, const u_char *edata, char **buf, size_t *buflen) {
   1.817 +	const u_char *odata = rdata;
   1.818 +	size_t save_buflen = *buflen;
   1.819 +	char *save_buf = *buf;
   1.820 +
   1.821 +	if (addstr("\"", (size_t)1, buf, buflen) < 0)
   1.822 +		goto enospc;
   1.823 +	if (rdata < edata) {
   1.824 +		int n = *rdata;
   1.825 +
   1.826 +		if (rdata + 1 + n <= edata) {
   1.827 +			rdata++;
   1.828 +			while (n-- > 0) {
   1.829 +				if (strchr("\n\"\\", *rdata) != NULL)
   1.830 +					if (addstr("\\", (size_t)1, buf, buflen) < 0)
   1.831 +						goto enospc;
   1.832 +				if (addstr((const char *)rdata, (size_t)1,
   1.833 +					   buf, buflen) < 0)
   1.834 +					goto enospc;
   1.835 +				rdata++;
   1.836 +			}
   1.837 +		}
   1.838 +	}
   1.839 +	if (addstr("\"", (size_t)1, buf, buflen) < 0)
   1.840 +		goto enospc;
   1.841 +	return (rdata - odata);
   1.842 + enospc:
   1.843 +	errno = ENOSPC;
   1.844 +	*buf = save_buf;
   1.845 +	*buflen = save_buflen;
   1.846 +	return (-1);
   1.847 +}
   1.848 +
   1.849 +static int
   1.850 +addname(const u_char *msg, size_t msglen,
   1.851 +	const u_char **pp, const char *origin,
   1.852 +	char **buf, size_t *buflen)
   1.853 +{
   1.854 +	size_t newlen, save_buflen = *buflen;
   1.855 +	char *save_buf = *buf;
   1.856 +	int n;
   1.857 +
   1.858 +	n = dn_expand(msg, msg + msglen, *pp, *buf, (int)*buflen);
   1.859 +	if (n < 0)
   1.860 +		goto enospc;	/* Guess. */
   1.861 +	newlen = prune_origin(*buf, origin);
   1.862 +	if (**buf == '\0') {
   1.863 +		goto root;
   1.864 +	} else if (newlen == 0U) {
   1.865 +		/* Use "@" instead of name. */
   1.866 +		if (newlen + 2 > *buflen)
   1.867 +			goto enospc;        /* No room for "@\0". */
   1.868 +		(*buf)[newlen++] = '@';
   1.869 +		(*buf)[newlen] = '\0';
   1.870 +	} else {
   1.871 +		if (((origin == NULL || origin[0] == '\0') ||
   1.872 +		    (origin[0] != '.' && origin[1] != '\0' &&
   1.873 +		    (*buf)[newlen] == '\0')) && (*buf)[newlen - 1] != '.') {
   1.874 +			/* No trailing dot. */
   1.875 + root:
   1.876 +			if (newlen + 2 > *buflen)
   1.877 +				goto enospc;	/* No room for ".\0". */
   1.878 +			(*buf)[newlen++] = '.';
   1.879 +			(*buf)[newlen] = '\0';
   1.880 +		}
   1.881 +	}
   1.882 +	*pp += n;
   1.883 +	addlen(newlen, buf, buflen);
   1.884 +	**buf = '\0';
   1.885 +	return (newlen);
   1.886 + enospc:
   1.887 +	errno = ENOSPC;
   1.888 +	*buf = save_buf;
   1.889 +	*buflen = save_buflen;
   1.890 +	return (-1);
   1.891 +}
   1.892 +
   1.893 +static void
   1.894 +addlen(size_t len, char **buf, size_t *buflen) {
   1.895 +	assert(len <= *buflen);
   1.896 +	*buf += len;
   1.897 +	*buflen -= len;
   1.898 +}
   1.899 +
   1.900 +static int
   1.901 +addstr(const char *src, size_t len, char **buf, size_t *buflen) {
   1.902 +	if (len >= *buflen) {
   1.903 +		errno = ENOSPC;
   1.904 +		return (-1);
   1.905 +	}
   1.906 +	memcpy(*buf, src, len);
   1.907 +	addlen(len, buf, buflen);
   1.908 +	**buf = '\0';
   1.909 +	return (0);
   1.910 +}
   1.911 +
   1.912 +static int
   1.913 +addtab(size_t len, size_t target, int spaced, char **buf, size_t *buflen) {
   1.914 +	size_t save_buflen = *buflen;
   1.915 +	char *save_buf = *buf;
   1.916 +	int t;
   1.917 +
   1.918 +	if (spaced || len >= target - 1) {
   1.919 +		T(addstr("  ", (size_t)2, buf, buflen));
   1.920 +		spaced = 1;
   1.921 +	} else {
   1.922 +		for (t = (target - len - 1) / 8; t >= 0; t--)
   1.923 +			if (addstr("\t", (size_t)1, buf, buflen) < 0) {
   1.924 +				*buflen = save_buflen;
   1.925 +				*buf = save_buf;
   1.926 +				return (-1);
   1.927 +			}
   1.928 +		spaced = 0;
   1.929 +	}
   1.930 +	return (spaced);
   1.931 +}

mercurial