other-licenses/android/ns_name.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/other-licenses/android/ns_name.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,987 @@
     1.4 +/*	$NetBSD: ns_name.c,v 1.3 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_name.c,v 1.3.2.4.4.2 2004/05/04 03:27:47 marka Exp";
    1.40 +#else
    1.41 +__RCSID("$NetBSD: ns_name.c,v 1.3 2004/11/07 02:19:49 christos Exp $");
    1.42 +#endif
    1.43 +#endif
    1.44 +
    1.45 +#include <sys/types.h>
    1.46 +
    1.47 +#include <netinet/in.h>
    1.48 +#include "arpa_nameser.h"
    1.49 +
    1.50 +#include <errno.h>
    1.51 +#ifdef ANDROID_CHANGES
    1.52 +#include "resolv_private.h"
    1.53 +#else
    1.54 +#include <resolv.h>
    1.55 +#endif
    1.56 +#include <string.h>
    1.57 +#include <ctype.h>
    1.58 +#include <stdlib.h>
    1.59 +#include <limits.h>
    1.60 +
    1.61 +#ifdef SPRINTF_CHAR
    1.62 +# define SPRINTF(x) strlen(sprintf/**/x)
    1.63 +#else
    1.64 +# define SPRINTF(x) ((size_t)sprintf x)
    1.65 +#endif
    1.66 +
    1.67 +#define NS_TYPE_ELT			0x40 /* EDNS0 extended label type */
    1.68 +#define DNS_LABELTYPE_BITSTRING		0x41
    1.69 +
    1.70 +/* Data. */
    1.71 +
    1.72 +static const char	digits[] = "0123456789";
    1.73 +
    1.74 +static const char digitvalue[256] = {
    1.75 +	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,	/*16*/
    1.76 +	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/
    1.77 +	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/
    1.78 +	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1, /*64*/
    1.79 +	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/
    1.80 +	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/
    1.81 +	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/
    1.82 +	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/
    1.83 +	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    1.84 +	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    1.85 +	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    1.86 +	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    1.87 +	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    1.88 +	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    1.89 +	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    1.90 +	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/
    1.91 +};
    1.92 +
    1.93 +/* Forward. */
    1.94 +
    1.95 +static int		special(int);
    1.96 +static int		printable(int);
    1.97 +static int		dn_find(const u_char *, const u_char *,
    1.98 +				const u_char * const *,
    1.99 +				const u_char * const *);
   1.100 +static int		encode_bitsring(const char **, const char *,
   1.101 +					unsigned char **, unsigned char **,
   1.102 +					unsigned const char *);
   1.103 +static int		labellen(const u_char *);
   1.104 +static int		decode_bitstring(const unsigned char **,
   1.105 +					 char *, const char *);
   1.106 +
   1.107 +/* Public. */
   1.108 +
   1.109 +/*
   1.110 + * ns_name_ntop(src, dst, dstsiz)
   1.111 + *	Convert an encoded domain name to printable ascii as per RFC1035.
   1.112 + * return:
   1.113 + *	Number of bytes written to buffer, or -1 (with errno set)
   1.114 + * notes:
   1.115 + *	The root is returned as "."
   1.116 + *	All other domains are returned in non absolute form
   1.117 + */
   1.118 +int
   1.119 +ns_name_ntop(const u_char *src, char *dst, size_t dstsiz)
   1.120 +{
   1.121 +	const u_char *cp;
   1.122 +	char *dn, *eom;
   1.123 +	u_char c;
   1.124 +	u_int n;
   1.125 +	int l;
   1.126 +
   1.127 +	cp = src;
   1.128 +	dn = dst;
   1.129 +	eom = dst + dstsiz;
   1.130 +
   1.131 +	while ((n = *cp++) != 0) {
   1.132 +		if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
   1.133 +			/* Some kind of compression pointer. */
   1.134 +			errno = EMSGSIZE;
   1.135 +			return (-1);
   1.136 +		}
   1.137 +		if (dn != dst) {
   1.138 +			if (dn >= eom) {
   1.139 +				errno = EMSGSIZE;
   1.140 +				return (-1);
   1.141 +			}
   1.142 +			*dn++ = '.';
   1.143 +		}
   1.144 +		if ((l = labellen(cp - 1)) < 0) {
   1.145 +			errno = EMSGSIZE; /* XXX */
   1.146 +			return(-1);
   1.147 +		}
   1.148 +		if (dn + l >= eom) {
   1.149 +			errno = EMSGSIZE;
   1.150 +			return (-1);
   1.151 +		}
   1.152 +		if ((n & NS_CMPRSFLGS) == NS_TYPE_ELT) {
   1.153 +			int m;
   1.154 +
   1.155 +			if (n != DNS_LABELTYPE_BITSTRING) {
   1.156 +				/* XXX: labellen should reject this case */
   1.157 +				errno = EINVAL;
   1.158 +				return(-1);
   1.159 +			}
   1.160 +			if ((m = decode_bitstring(&cp, dn, eom)) < 0)
   1.161 +			{
   1.162 +				errno = EMSGSIZE;
   1.163 +				return(-1);
   1.164 +			}
   1.165 +			dn += m;
   1.166 +			continue;
   1.167 +		}
   1.168 +		for (; l > 0; l--) {
   1.169 +			c = *cp++;
   1.170 +			if (special(c)) {
   1.171 +				if (dn + 1 >= eom) {
   1.172 +					errno = EMSGSIZE;
   1.173 +					return (-1);
   1.174 +				}
   1.175 +				*dn++ = '\\';
   1.176 +				*dn++ = (char)c;
   1.177 +			} else if (!printable(c)) {
   1.178 +				if (dn + 3 >= eom) {
   1.179 +					errno = EMSGSIZE;
   1.180 +					return (-1);
   1.181 +				}
   1.182 +				*dn++ = '\\';
   1.183 +				*dn++ = digits[c / 100];
   1.184 +				*dn++ = digits[(c % 100) / 10];
   1.185 +				*dn++ = digits[c % 10];
   1.186 +			} else {
   1.187 +				if (dn >= eom) {
   1.188 +					errno = EMSGSIZE;
   1.189 +					return (-1);
   1.190 +				}
   1.191 +				*dn++ = (char)c;
   1.192 +			}
   1.193 +		}
   1.194 +	}
   1.195 +	if (dn == dst) {
   1.196 +		if (dn >= eom) {
   1.197 +			errno = EMSGSIZE;
   1.198 +			return (-1);
   1.199 +		}
   1.200 +		*dn++ = '.';
   1.201 +	}
   1.202 +	if (dn >= eom) {
   1.203 +		errno = EMSGSIZE;
   1.204 +		return (-1);
   1.205 +	}
   1.206 +	*dn++ = '\0';
   1.207 +	return (dn - dst);
   1.208 +}
   1.209 +
   1.210 +/*
   1.211 + * ns_name_pton(src, dst, dstsiz)
   1.212 + *	Convert a ascii string into an encoded domain name as per RFC1035.
   1.213 + * return:
   1.214 + *	-1 if it fails
   1.215 + *	1 if string was fully qualified
   1.216 + *	0 is string was not fully qualified
   1.217 + * notes:
   1.218 + *	Enforces label and domain length limits.
   1.219 + */
   1.220 +
   1.221 +int
   1.222 +ns_name_pton(const char *src, u_char *dst, size_t dstsiz)
   1.223 +{
   1.224 +	u_char *label, *bp, *eom;
   1.225 +	int c, n, escaped, e = 0;
   1.226 +	char *cp;
   1.227 +
   1.228 +	escaped = 0;
   1.229 +	bp = dst;
   1.230 +	eom = dst + dstsiz;
   1.231 +	label = bp++;
   1.232 +
   1.233 +	while ((c = *src++) != 0) {
   1.234 +		if (escaped) {
   1.235 +			if (c == '[') { /* start a bit string label */
   1.236 +				if ((cp = strchr(src, ']')) == NULL) {
   1.237 +					errno = EINVAL; /* ??? */
   1.238 +					return(-1);
   1.239 +				}
   1.240 +				if ((e = encode_bitsring(&src, cp + 2,
   1.241 +							 &label, &bp, eom))
   1.242 +				    != 0) {
   1.243 +					errno = e;
   1.244 +					return(-1);
   1.245 +				}
   1.246 +				escaped = 0;
   1.247 +				label = bp++;
   1.248 +				if ((c = *src++) == 0)
   1.249 +					goto done;
   1.250 +				else if (c != '.') {
   1.251 +					errno = EINVAL;
   1.252 +					return(-1);
   1.253 +				}
   1.254 +				continue;
   1.255 +			}
   1.256 +			else if ((cp = strchr(digits, c)) != NULL) {
   1.257 +				n = (cp - digits) * 100;
   1.258 +				if ((c = *src++) == 0 ||
   1.259 +				    (cp = strchr(digits, c)) == NULL) {
   1.260 +					errno = EMSGSIZE;
   1.261 +					return (-1);
   1.262 +				}
   1.263 +				n += (cp - digits) * 10;
   1.264 +				if ((c = *src++) == 0 ||
   1.265 +				    (cp = strchr(digits, c)) == NULL) {
   1.266 +					errno = EMSGSIZE;
   1.267 +					return (-1);
   1.268 +				}
   1.269 +				n += (cp - digits);
   1.270 +				if (n > 255) {
   1.271 +					errno = EMSGSIZE;
   1.272 +					return (-1);
   1.273 +				}
   1.274 +				c = n;
   1.275 +			}
   1.276 +			escaped = 0;
   1.277 +		} else if (c == '\\') {
   1.278 +			escaped = 1;
   1.279 +			continue;
   1.280 +		} else if (c == '.') {
   1.281 +			c = (bp - label - 1);
   1.282 +			if ((c & NS_CMPRSFLGS) != 0) {	/* Label too big. */
   1.283 +				errno = EMSGSIZE;
   1.284 +				return (-1);
   1.285 +			}
   1.286 +			if (label >= eom) {
   1.287 +				errno = EMSGSIZE;
   1.288 +				return (-1);
   1.289 +			}
   1.290 +			*label = c;
   1.291 +			/* Fully qualified ? */
   1.292 +			if (*src == '\0') {
   1.293 +				if (c != 0) {
   1.294 +					if (bp >= eom) {
   1.295 +						errno = EMSGSIZE;
   1.296 +						return (-1);
   1.297 +					}
   1.298 +					*bp++ = '\0';
   1.299 +				}
   1.300 +				if ((bp - dst) > MAXCDNAME) {
   1.301 +					errno = EMSGSIZE;
   1.302 +					return (-1);
   1.303 +				}
   1.304 +				return (1);
   1.305 +			}
   1.306 +			if (c == 0 || *src == '.') {
   1.307 +				errno = EMSGSIZE;
   1.308 +				return (-1);
   1.309 +			}
   1.310 +			label = bp++;
   1.311 +			continue;
   1.312 +		}
   1.313 +		if (bp >= eom) {
   1.314 +			errno = EMSGSIZE;
   1.315 +			return (-1);
   1.316 +		}
   1.317 +		*bp++ = (u_char)c;
   1.318 +	}
   1.319 +	c = (bp - label - 1);
   1.320 +	if ((c & NS_CMPRSFLGS) != 0) {		/* Label too big. */
   1.321 +		errno = EMSGSIZE;
   1.322 +		return (-1);
   1.323 +	}
   1.324 +  done:
   1.325 +	if (label >= eom) {
   1.326 +		errno = EMSGSIZE;
   1.327 +		return (-1);
   1.328 +	}
   1.329 +	*label = c;
   1.330 +	if (c != 0) {
   1.331 +		if (bp >= eom) {
   1.332 +			errno = EMSGSIZE;
   1.333 +			return (-1);
   1.334 +		}
   1.335 +		*bp++ = 0;
   1.336 +	}
   1.337 +	if ((bp - dst) > MAXCDNAME) {	/* src too big */
   1.338 +		errno = EMSGSIZE;
   1.339 +		return (-1);
   1.340 +	}
   1.341 +	return (0);
   1.342 +}
   1.343 +
   1.344 +#ifndef MOZILLA_NECKO_EXCLUDE_CODE
   1.345 +/*
   1.346 + * ns_name_ntol(src, dst, dstsiz)
   1.347 + *	Convert a network strings labels into all lowercase.
   1.348 + * return:
   1.349 + *	Number of bytes written to buffer, or -1 (with errno set)
   1.350 + * notes:
   1.351 + *	Enforces label and domain length limits.
   1.352 + */
   1.353 +
   1.354 +int
   1.355 +ns_name_ntol(const u_char *src, u_char *dst, size_t dstsiz)
   1.356 +{
   1.357 +	const u_char *cp;
   1.358 +	u_char *dn, *eom;
   1.359 +	u_char c;
   1.360 +	u_int n;
   1.361 +	int l;
   1.362 +
   1.363 +	cp = src;
   1.364 +	dn = dst;
   1.365 +	eom = dst + dstsiz;
   1.366 +
   1.367 +	if (dn >= eom) {
   1.368 +		errno = EMSGSIZE;
   1.369 +		return (-1);
   1.370 +	}
   1.371 +	while ((n = *cp++) != 0) {
   1.372 +		if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
   1.373 +			/* Some kind of compression pointer. */
   1.374 +			errno = EMSGSIZE;
   1.375 +			return (-1);
   1.376 +		}
   1.377 +		*dn++ = n;
   1.378 +		if ((l = labellen(cp - 1)) < 0) {
   1.379 +			errno = EMSGSIZE;
   1.380 +			return (-1);
   1.381 +		}
   1.382 +		if (dn + l >= eom) {
   1.383 +			errno = EMSGSIZE;
   1.384 +			return (-1);
   1.385 +		}
   1.386 +		for (; l > 0; l--) {
   1.387 +			c = *cp++;
   1.388 +			if (isupper(c))
   1.389 +				*dn++ = tolower(c);
   1.390 +			else
   1.391 +				*dn++ = c;
   1.392 +		}
   1.393 +	}
   1.394 +	*dn++ = '\0';
   1.395 +	return (dn - dst);
   1.396 +}
   1.397 +#endif
   1.398 +
   1.399 +/*
   1.400 + * ns_name_unpack(msg, eom, src, dst, dstsiz)
   1.401 + *	Unpack a domain name from a message, source may be compressed.
   1.402 + * return:
   1.403 + *	-1 if it fails, or consumed octets if it succeeds.
   1.404 + */
   1.405 +int
   1.406 +ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src,
   1.407 +	       u_char *dst, size_t dstsiz)
   1.408 +{
   1.409 +	const u_char *srcp, *dstlim;
   1.410 +	u_char *dstp;
   1.411 +	int n, len, checked, l;
   1.412 +
   1.413 +	len = -1;
   1.414 +	checked = 0;
   1.415 +	dstp = dst;
   1.416 +	srcp = src;
   1.417 +	dstlim = dst + dstsiz;
   1.418 +	if (srcp < msg || srcp >= eom) {
   1.419 +		errno = EMSGSIZE;
   1.420 +		return (-1);
   1.421 +	}
   1.422 +	/* Fetch next label in domain name. */
   1.423 +	while ((n = *srcp++) != 0) {
   1.424 +		/* Check for indirection. */
   1.425 +		switch (n & NS_CMPRSFLGS) {
   1.426 +		case 0:
   1.427 +		case NS_TYPE_ELT:
   1.428 +			/* Limit checks. */
   1.429 +			if ((l = labellen(srcp - 1)) < 0) {
   1.430 +				errno = EMSGSIZE;
   1.431 +				return(-1);
   1.432 +			}
   1.433 +			if (dstp + l + 1 >= dstlim || srcp + l >= eom) {
   1.434 +				errno = EMSGSIZE;
   1.435 +				return (-1);
   1.436 +			}
   1.437 +			checked += l + 1;
   1.438 +			*dstp++ = n;
   1.439 +			memcpy(dstp, srcp, (size_t)l);
   1.440 +			dstp += l;
   1.441 +			srcp += l;
   1.442 +			break;
   1.443 +
   1.444 +		case NS_CMPRSFLGS:
   1.445 +			if (srcp >= eom) {
   1.446 +				errno = EMSGSIZE;
   1.447 +				return (-1);
   1.448 +			}
   1.449 +			if (len < 0)
   1.450 +				len = srcp - src + 1;
   1.451 +			srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff));
   1.452 +			if (srcp < msg || srcp >= eom) {  /* Out of range. */
   1.453 +				errno = EMSGSIZE;
   1.454 +				return (-1);
   1.455 +			}
   1.456 +			checked += 2;
   1.457 +			/*
   1.458 +			 * Check for loops in the compressed name;
   1.459 +			 * if we've looked at the whole message,
   1.460 +			 * there must be a loop.
   1.461 +			 */
   1.462 +			if (checked >= eom - msg) {
   1.463 +				errno = EMSGSIZE;
   1.464 +				return (-1);
   1.465 +			}
   1.466 +			break;
   1.467 +
   1.468 +		default:
   1.469 +			errno = EMSGSIZE;
   1.470 +			return (-1);			/* flag error */
   1.471 +		}
   1.472 +	}
   1.473 +	*dstp = '\0';
   1.474 +	if (len < 0)
   1.475 +		len = srcp - src;
   1.476 +	return (len);
   1.477 +}
   1.478 +
   1.479 +/*
   1.480 + * ns_name_pack(src, dst, dstsiz, dnptrs, lastdnptr)
   1.481 + *	Pack domain name 'domain' into 'comp_dn'.
   1.482 + * return:
   1.483 + *	Size of the compressed name, or -1.
   1.484 + * notes:
   1.485 + *	'dnptrs' is an array of pointers to previous compressed names.
   1.486 + *	dnptrs[0] is a pointer to the beginning of the message. The array
   1.487 + *	ends with NULL.
   1.488 + *	'lastdnptr' is a pointer to the end of the array pointed to
   1.489 + *	by 'dnptrs'.
   1.490 + * Side effects:
   1.491 + *	The list of pointers in dnptrs is updated for labels inserted into
   1.492 + *	the message as we compress the name.  If 'dnptr' is NULL, we don't
   1.493 + *	try to compress names. If 'lastdnptr' is NULL, we don't update the
   1.494 + *	list.
   1.495 + */
   1.496 +int
   1.497 +ns_name_pack(const u_char *src, u_char *dst, int dstsiz,
   1.498 +	     const u_char **dnptrs, const u_char **lastdnptr)
   1.499 +{
   1.500 +	u_char *dstp;
   1.501 +	const u_char **cpp, **lpp, *eob, *msg;
   1.502 +	const u_char *srcp;
   1.503 +	int n, l, first = 1;
   1.504 +
   1.505 +	srcp = src;
   1.506 +	dstp = dst;
   1.507 +	eob = dstp + dstsiz;
   1.508 +	lpp = cpp = NULL;
   1.509 +	if (dnptrs != NULL) {
   1.510 +		if ((msg = *dnptrs++) != NULL) {
   1.511 +			for (cpp = dnptrs; *cpp != NULL; cpp++)
   1.512 +				;
   1.513 +			lpp = cpp;	/* end of list to search */
   1.514 +		}
   1.515 +	} else
   1.516 +		msg = NULL;
   1.517 +
   1.518 +	/* make sure the domain we are about to add is legal */
   1.519 +	l = 0;
   1.520 +	do {
   1.521 +		int l0;
   1.522 +
   1.523 +		n = *srcp;
   1.524 +		if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
   1.525 +			errno = EMSGSIZE;
   1.526 +			return (-1);
   1.527 +		}
   1.528 +		if ((l0 = labellen(srcp)) < 0) {
   1.529 +			errno = EINVAL;
   1.530 +			return(-1);
   1.531 +		}
   1.532 +		l += l0 + 1;
   1.533 +		if (l > MAXCDNAME) {
   1.534 +			errno = EMSGSIZE;
   1.535 +			return (-1);
   1.536 +		}
   1.537 +		srcp += l0 + 1;
   1.538 +	} while (n != 0);
   1.539 +
   1.540 +	/* from here on we need to reset compression pointer array on error */
   1.541 +	srcp = src;
   1.542 +	do {
   1.543 +		/* Look to see if we can use pointers. */
   1.544 +		n = *srcp;
   1.545 +		if (n != 0 && msg != NULL) {
   1.546 +			l = dn_find(srcp, msg, (const u_char * const *)dnptrs,
   1.547 +				    (const u_char * const *)lpp);
   1.548 +			if (l >= 0) {
   1.549 +				if (dstp + 1 >= eob) {
   1.550 +					goto cleanup;
   1.551 +				}
   1.552 +				*dstp++ = ((u_int32_t)l >> 8) | NS_CMPRSFLGS;
   1.553 +				*dstp++ = l % 256;
   1.554 +				return (dstp - dst);
   1.555 +			}
   1.556 +			/* Not found, save it. */
   1.557 +			if (lastdnptr != NULL && cpp < lastdnptr - 1 &&
   1.558 +			    (dstp - msg) < 0x4000 && first) {
   1.559 +				*cpp++ = dstp;
   1.560 +				*cpp = NULL;
   1.561 +				first = 0;
   1.562 +			}
   1.563 +		}
   1.564 +		/* copy label to buffer */
   1.565 +		if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
   1.566 +			/* Should not happen. */
   1.567 +			goto cleanup;
   1.568 +		}
   1.569 +		n = labellen(srcp);
   1.570 +		if (dstp + 1 + n >= eob) {
   1.571 +			goto cleanup;
   1.572 +		}
   1.573 +		memcpy(dstp, srcp, (size_t)(n + 1));
   1.574 +		srcp += n + 1;
   1.575 +		dstp += n + 1;
   1.576 +	} while (n != 0);
   1.577 +
   1.578 +	if (dstp > eob) {
   1.579 +cleanup:
   1.580 +		if (msg != NULL)
   1.581 +			*lpp = NULL;
   1.582 +		errno = EMSGSIZE;
   1.583 +		return (-1);
   1.584 +	}
   1.585 +	return (dstp - dst);
   1.586 +}
   1.587 +
   1.588 +/*
   1.589 + * ns_name_uncompress(msg, eom, src, dst, dstsiz)
   1.590 + *	Expand compressed domain name to presentation format.
   1.591 + * return:
   1.592 + *	Number of bytes read out of `src', or -1 (with errno set).
   1.593 + * note:
   1.594 + *	Root domain returns as "." not "".
   1.595 + */
   1.596 +int
   1.597 +ns_name_uncompress(const u_char *msg, const u_char *eom, const u_char *src,
   1.598 +		   char *dst, size_t dstsiz)
   1.599 +{
   1.600 +	u_char tmp[NS_MAXCDNAME];
   1.601 +	int n;
   1.602 +
   1.603 +	if ((n = ns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1)
   1.604 +		return (-1);
   1.605 +	if (ns_name_ntop(tmp, dst, dstsiz) == -1)
   1.606 +		return (-1);
   1.607 +	return (n);
   1.608 +}
   1.609 +
   1.610 +/*
   1.611 + * ns_name_compress(src, dst, dstsiz, dnptrs, lastdnptr)
   1.612 + *	Compress a domain name into wire format, using compression pointers.
   1.613 + * return:
   1.614 + *	Number of bytes consumed in `dst' or -1 (with errno set).
   1.615 + * notes:
   1.616 + *	'dnptrs' is an array of pointers to previous compressed names.
   1.617 + *	dnptrs[0] is a pointer to the beginning of the message.
   1.618 + *	The list ends with NULL.  'lastdnptr' is a pointer to the end of the
   1.619 + *	array pointed to by 'dnptrs'. Side effect is to update the list of
   1.620 + *	pointers for labels inserted into the message as we compress the name.
   1.621 + *	If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
   1.622 + *	is NULL, we don't update the list.
   1.623 + */
   1.624 +int
   1.625 +ns_name_compress(const char *src, u_char *dst, size_t dstsiz,
   1.626 +		 const u_char **dnptrs, const u_char **lastdnptr)
   1.627 +{
   1.628 +	u_char tmp[NS_MAXCDNAME];
   1.629 +
   1.630 +	if (ns_name_pton(src, tmp, sizeof tmp) == -1)
   1.631 +		return (-1);
   1.632 +	return (ns_name_pack(tmp, dst, (int)dstsiz, dnptrs, lastdnptr));
   1.633 +}
   1.634 +
   1.635 +#ifndef MOZILLA_NECKO_EXCLUDE_CODE
   1.636 +/*
   1.637 + * Reset dnptrs so that there are no active references to pointers at or
   1.638 + * after src.
   1.639 + */
   1.640 +void
   1.641 +ns_name_rollback(const u_char *src, const u_char **dnptrs,
   1.642 +		 const u_char **lastdnptr)
   1.643 +{
   1.644 +	while (dnptrs < lastdnptr && *dnptrs != NULL) {
   1.645 +		if (*dnptrs >= src) {
   1.646 +			*dnptrs = NULL;
   1.647 +			break;
   1.648 +		}
   1.649 +		dnptrs++;
   1.650 +	}
   1.651 +}
   1.652 +#endif
   1.653 +
   1.654 +/*
   1.655 + * ns_name_skip(ptrptr, eom)
   1.656 + *	Advance *ptrptr to skip over the compressed name it points at.
   1.657 + * return:
   1.658 + *	0 on success, -1 (with errno set) on failure.
   1.659 + */
   1.660 +int
   1.661 +ns_name_skip(const u_char **ptrptr, const u_char *eom)
   1.662 +{
   1.663 +	const u_char *cp;
   1.664 +	u_int n;
   1.665 +	int l;
   1.666 +
   1.667 +	cp = *ptrptr;
   1.668 +	while (cp < eom && (n = *cp++) != 0) {
   1.669 +		/* Check for indirection. */
   1.670 +		switch (n & NS_CMPRSFLGS) {
   1.671 +		case 0:			/* normal case, n == len */
   1.672 +			cp += n;
   1.673 +			continue;
   1.674 +		case NS_TYPE_ELT: /* EDNS0 extended label */
   1.675 +			if ((l = labellen(cp - 1)) < 0) {
   1.676 +				errno = EMSGSIZE; /* XXX */
   1.677 +				return(-1);
   1.678 +			}
   1.679 +			cp += l;
   1.680 +			continue;
   1.681 +		case NS_CMPRSFLGS:	/* indirection */
   1.682 +			cp++;
   1.683 +			break;
   1.684 +		default:		/* illegal type */
   1.685 +			errno = EMSGSIZE;
   1.686 +			return (-1);
   1.687 +		}
   1.688 +		break;
   1.689 +	}
   1.690 +	if (cp > eom) {
   1.691 +		errno = EMSGSIZE;
   1.692 +		return (-1);
   1.693 +	}
   1.694 +	*ptrptr = cp;
   1.695 +	return (0);
   1.696 +}
   1.697 +
   1.698 +/* Private. */
   1.699 +
   1.700 +/*
   1.701 + * special(ch)
   1.702 + *	Thinking in noninternationalized USASCII (per the DNS spec),
   1.703 + *	is this characted special ("in need of quoting") ?
   1.704 + * return:
   1.705 + *	boolean.
   1.706 + */
   1.707 +static int
   1.708 +special(int ch) {
   1.709 +	switch (ch) {
   1.710 +	case 0x22: /* '"' */
   1.711 +	case 0x2E: /* '.' */
   1.712 +	case 0x3B: /* ';' */
   1.713 +	case 0x5C: /* '\\' */
   1.714 +	case 0x28: /* '(' */
   1.715 +	case 0x29: /* ')' */
   1.716 +	/* Special modifiers in zone files. */
   1.717 +	case 0x40: /* '@' */
   1.718 +	case 0x24: /* '$' */
   1.719 +		return (1);
   1.720 +	default:
   1.721 +		return (0);
   1.722 +	}
   1.723 +}
   1.724 +
   1.725 +/*
   1.726 + * printable(ch)
   1.727 + *	Thinking in noninternationalized USASCII (per the DNS spec),
   1.728 + *	is this character visible and not a space when printed ?
   1.729 + * return:
   1.730 + *	boolean.
   1.731 + */
   1.732 +static int
   1.733 +printable(int ch) {
   1.734 +	return (ch > 0x20 && ch < 0x7f);
   1.735 +}
   1.736 +
   1.737 +/*
   1.738 + *	Thinking in noninternationalized USASCII (per the DNS spec),
   1.739 + *	convert this character to lower case if it's upper case.
   1.740 + */
   1.741 +static int
   1.742 +mklower(int ch) {
   1.743 +	if (ch >= 0x41 && ch <= 0x5A)
   1.744 +		return (ch + 0x20);
   1.745 +	return (ch);
   1.746 +}
   1.747 +
   1.748 +/*
   1.749 + * dn_find(domain, msg, dnptrs, lastdnptr)
   1.750 + *	Search for the counted-label name in an array of compressed names.
   1.751 + * return:
   1.752 + *	offset from msg if found, or -1.
   1.753 + * notes:
   1.754 + *	dnptrs is the pointer to the first name on the list,
   1.755 + *	not the pointer to the start of the message.
   1.756 + */
   1.757 +static int
   1.758 +dn_find(const u_char *domain, const u_char *msg,
   1.759 +	const u_char * const *dnptrs,
   1.760 +	const u_char * const *lastdnptr)
   1.761 +{
   1.762 +	const u_char *dn, *cp, *sp;
   1.763 +	const u_char * const *cpp;
   1.764 +	u_int n;
   1.765 +
   1.766 +	for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
   1.767 +		sp = *cpp;
   1.768 +		/*
   1.769 +		 * terminate search on:
   1.770 +		 * root label
   1.771 +		 * compression pointer
   1.772 +		 * unusable offset
   1.773 +		 */
   1.774 +		while (*sp != 0 && (*sp & NS_CMPRSFLGS) == 0 &&
   1.775 +		       (sp - msg) < 0x4000) {
   1.776 +			dn = domain;
   1.777 +			cp = sp;
   1.778 +			while ((n = *cp++) != 0) {
   1.779 +				/*
   1.780 +				 * check for indirection
   1.781 +				 */
   1.782 +				switch (n & NS_CMPRSFLGS) {
   1.783 +				case 0:		/* normal case, n == len */
   1.784 +					n = labellen(cp - 1); /* XXX */
   1.785 +
   1.786 +					if (n != *dn++)
   1.787 +						goto next;
   1.788 +
   1.789 +					for (; n > 0; n--)
   1.790 +						if (mklower(*dn++) !=
   1.791 +						    mklower(*cp++))
   1.792 +							goto next;
   1.793 +					/* Is next root for both ? */
   1.794 +					if (*dn == '\0' && *cp == '\0')
   1.795 +						return (sp - msg);
   1.796 +					if (*dn)
   1.797 +						continue;
   1.798 +					goto next;
   1.799 +				case NS_CMPRSFLGS:	/* indirection */
   1.800 +					cp = msg + (((n & 0x3f) << 8) | *cp);
   1.801 +					break;
   1.802 +
   1.803 +				default:	/* illegal type */
   1.804 +					errno = EMSGSIZE;
   1.805 +					return (-1);
   1.806 +				}
   1.807 +			}
   1.808 + next: ;
   1.809 +			sp += *sp + 1;
   1.810 +		}
   1.811 +	}
   1.812 +	errno = ENOENT;
   1.813 +	return (-1);
   1.814 +}
   1.815 +
   1.816 +static int
   1.817 +decode_bitstring(const unsigned char **cpp, char *dn, const char *eom)
   1.818 +{
   1.819 +	const unsigned char *cp = *cpp;
   1.820 +	char *beg = dn, tc;
   1.821 +	int b, blen, plen, i;
   1.822 +
   1.823 +	if ((blen = (*cp & 0xff)) == 0)
   1.824 +		blen = 256;
   1.825 +	plen = (blen + 3) / 4;
   1.826 +	plen += sizeof("\\[x/]") + (blen > 99 ? 3 : (blen > 9) ? 2 : 1);
   1.827 +	if (dn + plen >= eom)
   1.828 +		return(-1);
   1.829 +
   1.830 +	cp++;
   1.831 +	i = SPRINTF((dn, "\\[x"));
   1.832 +	if (i < 0)
   1.833 +		return (-1);
   1.834 +	dn += i;
   1.835 +	for (b = blen; b > 7; b -= 8, cp++) {
   1.836 +		i = SPRINTF((dn, "%02x", *cp & 0xff));
   1.837 +		if (i < 0)
   1.838 +			return (-1);
   1.839 +		dn += i;
   1.840 +	}
   1.841 +	if (b > 4) {
   1.842 +		tc = *cp++;
   1.843 +		i = SPRINTF((dn, "%02x", tc & (0xff << (8 - b))));
   1.844 +		if (i < 0)
   1.845 +			return (-1);
   1.846 +		dn += i;
   1.847 +	} else if (b > 0) {
   1.848 +		tc = *cp++;
   1.849 +		i = SPRINTF((dn, "%1x",
   1.850 +			       (((u_int32_t)tc >> 4) & 0x0f) & (0x0f << (4 - b))));
   1.851 +		if (i < 0)
   1.852 +			return (-1);
   1.853 +		dn += i;
   1.854 +	}
   1.855 +	i = SPRINTF((dn, "/%d]", blen));
   1.856 +	if (i < 0)
   1.857 +		return (-1);
   1.858 +	dn += i;
   1.859 +
   1.860 +	*cpp = cp;
   1.861 +	return(dn - beg);
   1.862 +}
   1.863 +
   1.864 +static int
   1.865 +encode_bitsring(const char **bp, const char *end, unsigned char **labelp,
   1.866 +	        unsigned char ** dst, unsigned const char *eom)
   1.867 +{
   1.868 +	int afterslash = 0;
   1.869 +	const char *cp = *bp;
   1.870 +	unsigned char *tp;
   1.871 +	char c;
   1.872 +	const char *beg_blen;
   1.873 +	char *end_blen = NULL;
   1.874 +	int value = 0, count = 0, tbcount = 0, blen = 0;
   1.875 +
   1.876 +	beg_blen = end_blen = NULL;
   1.877 +
   1.878 +	/* a bitstring must contain at least 2 characters */
   1.879 +	if (end - cp < 2)
   1.880 +		return(EINVAL);
   1.881 +
   1.882 +	/* XXX: currently, only hex strings are supported */
   1.883 +	if (*cp++ != 'x')
   1.884 +		return(EINVAL);
   1.885 +	if (!isxdigit((*cp) & 0xff)) /* reject '\[x/BLEN]' */
   1.886 +		return(EINVAL);
   1.887 +
   1.888 +	for (tp = *dst + 1; cp < end && tp < eom; cp++) {
   1.889 +		switch((c = *cp)) {
   1.890 +		case ']':	/* end of the bitstring */
   1.891 +			if (afterslash) {
   1.892 +				if (beg_blen == NULL)
   1.893 +					return(EINVAL);
   1.894 +				blen = (int)strtol(beg_blen, &end_blen, 10);
   1.895 +				if (*end_blen != ']')
   1.896 +					return(EINVAL);
   1.897 +			}
   1.898 +			if (count)
   1.899 +				*tp++ = ((value << 4) & 0xff);
   1.900 +			cp++;	/* skip ']' */
   1.901 +			goto done;
   1.902 +		case '/':
   1.903 +			afterslash = 1;
   1.904 +			break;
   1.905 +		default:
   1.906 +			if (afterslash) {
   1.907 +				if (!isdigit(c&0xff))
   1.908 +					return(EINVAL);
   1.909 +				if (beg_blen == NULL) {
   1.910 +
   1.911 +					if (c == '0') {
   1.912 +						/* blen never begings with 0 */
   1.913 +						return(EINVAL);
   1.914 +					}
   1.915 +					beg_blen = cp;
   1.916 +				}
   1.917 +			} else {
   1.918 +				if (!isxdigit(c&0xff))
   1.919 +					return(EINVAL);
   1.920 +				value <<= 4;
   1.921 +				value += digitvalue[(int)c];
   1.922 +				count += 4;
   1.923 +				tbcount += 4;
   1.924 +				if (tbcount > 256)
   1.925 +					return(EINVAL);
   1.926 +				if (count == 8) {
   1.927 +					*tp++ = value;
   1.928 +					count = 0;
   1.929 +				}
   1.930 +			}
   1.931 +			break;
   1.932 +		}
   1.933 +	}
   1.934 +  done:
   1.935 +	if (cp >= end || tp >= eom)
   1.936 +		return(EMSGSIZE);
   1.937 +
   1.938 +	/*
   1.939 +	 * bit length validation:
   1.940 +	 * If a <length> is present, the number of digits in the <bit-data>
   1.941 +	 * MUST be just sufficient to contain the number of bits specified
   1.942 +	 * by the <length>. If there are insignificant bits in a final
   1.943 +	 * hexadecimal or octal digit, they MUST be zero.
   1.944 +	 * RFC 2673, Section 3.2.
   1.945 +	 */
   1.946 +	if (blen > 0) {
   1.947 +		int traillen;
   1.948 +
   1.949 +		if (((blen + 3) & ~3) != tbcount)
   1.950 +			return(EINVAL);
   1.951 +		traillen = tbcount - blen; /* between 0 and 3 */
   1.952 +		if (((value << (8 - traillen)) & 0xff) != 0)
   1.953 +			return(EINVAL);
   1.954 +	}
   1.955 +	else
   1.956 +		blen = tbcount;
   1.957 +	if (blen == 256)
   1.958 +		blen = 0;
   1.959 +
   1.960 +	/* encode the type and the significant bit fields */
   1.961 +	**labelp = DNS_LABELTYPE_BITSTRING;
   1.962 +	**dst = blen;
   1.963 +
   1.964 +	*bp = cp;
   1.965 +	*dst = tp;
   1.966 +
   1.967 +	return(0);
   1.968 +}
   1.969 +
   1.970 +static int
   1.971 +labellen(const u_char *lp)
   1.972 +{
   1.973 +	int bitlen;
   1.974 +	u_char l = *lp;
   1.975 +
   1.976 +	if ((l & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
   1.977 +		/* should be avoided by the caller */
   1.978 +		return(-1);
   1.979 +	}
   1.980 +
   1.981 +	if ((l & NS_CMPRSFLGS) == NS_TYPE_ELT) {
   1.982 +		if (l == DNS_LABELTYPE_BITSTRING) {
   1.983 +			if ((bitlen = *(lp + 1)) == 0)
   1.984 +				bitlen = 256;
   1.985 +			return((bitlen + 7 ) / 8 + 1);
   1.986 +		}
   1.987 +		return(-1);	/* unknwon ELT */
   1.988 +	}
   1.989 +	return(l);
   1.990 +}

mercurial