11dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*	$NetBSD: ns_name.c,v 1.3 2004/11/07 02:19:49 christos Exp $	*/
21dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
31dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
41dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
51dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Copyright (c) 1996,1999 by Internet Software Consortium.
61dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
71dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Permission to use, copy, modify, and distribute this software for any
81dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * purpose with or without fee is hereby granted, provided that the above
91dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * copyright notice and this permission notice appear in all copies.
101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/cdefs.h>
211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifndef lint
221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef notdef
231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const char rcsid[] = "Id: ns_name.c,v 1.3.2.4.4.2 2004/05/04 03:27:47 marka Exp";
241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#else
251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project__RCSID("$NetBSD: ns_name.c,v 1.3 2004/11/07 02:19:49 christos Exp $");
261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/types.h>
301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <netinet/in.h>
321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "arpa_nameser.h"
331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <errno.h>
351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef ANDROID_CHANGES
361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "resolv_private.h"
371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#else
381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <resolv.h>
391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <string.h>
411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <ctype.h>
421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdlib.h>
431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <limits.h>
441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef SPRINTF_CHAR
461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# define SPRINTF(x) strlen(sprintf/**/x)
471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#else
481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# define SPRINTF(x) ((size_t)sprintf x)
491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define NS_TYPE_ELT			0x40 /* EDNS0 extended label type */
521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define DNS_LABELTYPE_BITSTRING		0x41
531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Data. */
551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const char	digits[] = "0123456789";
571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const char digitvalue[256] = {
591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,	/*16*/
601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/
611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/
621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1, /*64*/
631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/
641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/
651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/
661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/
671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/
751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project};
761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Forward. */
781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int		special(int);
801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int		printable(int);
811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int		dn_find(const u_char *, const u_char *,
821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				const u_char * const *,
831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				const u_char * const *);
841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int		encode_bitsring(const char **, const char *,
851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					unsigned char **, unsigned char **,
861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					unsigned const char *);
871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int		labellen(const u_char *);
881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int		decode_bitstring(const unsigned char **,
891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					 char *, const char *);
901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Public. */
921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ns_name_ntop(src, dst, dstsiz)
951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	Convert an encoded domain name to printable ascii as per RFC1035.
961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return:
971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	Number of bytes written to buffer, or -1 (with errno set)
981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notes:
991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	The root is returned as "."
1001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	All other domains are returned in non absolute form
1011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
1021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint
1031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectns_name_ntop(const u_char *src, char *dst, size_t dstsiz)
1041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
1051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const u_char *cp;
1061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	char *dn, *eom;
1071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	u_char c;
1081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	u_int n;
1091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int l;
1101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	cp = src;
1121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	dn = dst;
1131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	eom = dst + dstsiz;
1141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	while ((n = *cp++) != 0) {
1161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
1171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/* Some kind of compression pointer. */
1181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			errno = EMSGSIZE;
1191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
1201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
1211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (dn != dst) {
1221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (dn >= eom) {
1231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				errno = EMSGSIZE;
1241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return (-1);
1251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
1261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			*dn++ = '.';
1271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
1281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if ((l = labellen(cp - 1)) < 0) {
1291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			errno = EMSGSIZE; /* XXX */
1301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return(-1);
1311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
1321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (dn + l >= eom) {
1331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			errno = EMSGSIZE;
1341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
1351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
1361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if ((n & NS_CMPRSFLGS) == NS_TYPE_ELT) {
1371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			int m;
1381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (n != DNS_LABELTYPE_BITSTRING) {
1401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				/* XXX: labellen should reject this case */
1411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				errno = EINVAL;
1421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return(-1);
1431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
1441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if ((m = decode_bitstring(&cp, dn, eom)) < 0)
1451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			{
1461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				errno = EMSGSIZE;
1471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return(-1);
1481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
1491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			dn += m;
1501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			continue;
1511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
1521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		for (; l > 0; l--) {
1531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			c = *cp++;
1541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (special(c)) {
1551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (dn + 1 >= eom) {
1561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					errno = EMSGSIZE;
1571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					return (-1);
1581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
1591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				*dn++ = '\\';
1601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				*dn++ = (char)c;
1611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			} else if (!printable(c)) {
1621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (dn + 3 >= eom) {
1631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					errno = EMSGSIZE;
1641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					return (-1);
1651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
1661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				*dn++ = '\\';
1671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				*dn++ = digits[c / 100];
1681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				*dn++ = digits[(c % 100) / 10];
1691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				*dn++ = digits[c % 10];
1701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			} else {
1711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (dn >= eom) {
1721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					errno = EMSGSIZE;
1731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					return (-1);
1741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
1751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				*dn++ = (char)c;
1761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
1771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
1781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
1791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (dn == dst) {
1801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (dn >= eom) {
1811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			errno = EMSGSIZE;
1821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
1831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
1841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		*dn++ = '.';
1851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
1861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (dn >= eom) {
1871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		errno = EMSGSIZE;
1881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (-1);
1891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
1901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	*dn++ = '\0';
1911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (dn - dst);
1921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
1931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
1951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ns_name_pton(src, dst, dstsiz)
1961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	Convert a ascii string into an encoded domain name as per RFC1035.
1971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return:
1981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	-1 if it fails
1991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	1 if string was fully qualified
2001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	0 is string was not fully qualified
2011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notes:
2021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	Enforces label and domain length limits.
2031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
2041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint
2061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectns_name_pton(const char *src, u_char *dst, size_t dstsiz)
2071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
2081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	u_char *label, *bp, *eom;
2091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int c, n, escaped, e = 0;
2101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	char *cp;
2111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	escaped = 0;
2131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	bp = dst;
2141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	eom = dst + dstsiz;
2151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	label = bp++;
2161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	while ((c = *src++) != 0) {
2181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (escaped) {
2191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (c == '[') { /* start a bit string label */
2201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if ((cp = strchr(src, ']')) == NULL) {
2211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					errno = EINVAL; /* ??? */
2221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					return(-1);
2231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
2241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if ((e = encode_bitsring(&src, cp + 2,
2251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project							 &label, &bp, eom))
2261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				    != 0) {
2271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					errno = e;
2281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					return(-1);
2291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
2301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				escaped = 0;
2311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				label = bp++;
2321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if ((c = *src++) == 0)
2331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					goto done;
2341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				else if (c != '.') {
2351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					errno = EINVAL;
2361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					return(-1);
2371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
2381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				continue;
2391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
2401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			else if ((cp = strchr(digits, c)) != NULL) {
2411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				n = (cp - digits) * 100;
2421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if ((c = *src++) == 0 ||
2431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				    (cp = strchr(digits, c)) == NULL) {
2441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					errno = EMSGSIZE;
2451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					return (-1);
2461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
2471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				n += (cp - digits) * 10;
2481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if ((c = *src++) == 0 ||
2491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				    (cp = strchr(digits, c)) == NULL) {
2501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					errno = EMSGSIZE;
2511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					return (-1);
2521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
2531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				n += (cp - digits);
2541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (n > 255) {
2551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					errno = EMSGSIZE;
2561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					return (-1);
2571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
2581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				c = n;
2591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
2601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			escaped = 0;
2611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		} else if (c == '\\') {
2621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			escaped = 1;
2631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			continue;
2641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		} else if (c == '.') {
2651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			c = (bp - label - 1);
2661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if ((c & NS_CMPRSFLGS) != 0) {	/* Label too big. */
2671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				errno = EMSGSIZE;
2681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return (-1);
2691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
2701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (label >= eom) {
2711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				errno = EMSGSIZE;
2721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return (-1);
2731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
2741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			*label = c;
2751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/* Fully qualified ? */
2761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (*src == '\0') {
2771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (c != 0) {
2781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					if (bp >= eom) {
2791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project						errno = EMSGSIZE;
2801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project						return (-1);
2811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					}
2821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					*bp++ = '\0';
2831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
2841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if ((bp - dst) > MAXCDNAME) {
2851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					errno = EMSGSIZE;
2861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					return (-1);
2871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
2881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return (1);
2891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
2901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (c == 0 || *src == '.') {
2911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				errno = EMSGSIZE;
2921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return (-1);
2931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
2941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			label = bp++;
2951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			continue;
2961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
2971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (bp >= eom) {
2981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			errno = EMSGSIZE;
2991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
3001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
3011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		*bp++ = (u_char)c;
3021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
3031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	c = (bp - label - 1);
3041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if ((c & NS_CMPRSFLGS) != 0) {		/* Label too big. */
3051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		errno = EMSGSIZE;
3061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (-1);
3071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
3081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project  done:
3091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (label >= eom) {
3101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		errno = EMSGSIZE;
3111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (-1);
3121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
3131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	*label = c;
3141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (c != 0) {
3151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (bp >= eom) {
3161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			errno = EMSGSIZE;
3171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
3181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
3191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		*bp++ = 0;
3201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
3211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if ((bp - dst) > MAXCDNAME) {	/* src too big */
3221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		errno = EMSGSIZE;
3231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (-1);
3241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
3251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (0);
3261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
3271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
3291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ns_name_ntol(src, dst, dstsiz)
3301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	Convert a network strings labels into all lowercase.
3311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return:
3321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	Number of bytes written to buffer, or -1 (with errno set)
3331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notes:
3341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	Enforces label and domain length limits.
3351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
3361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint
3381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectns_name_ntol(const u_char *src, u_char *dst, size_t dstsiz)
3391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
3401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const u_char *cp;
3411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	u_char *dn, *eom;
3421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	u_char c;
3431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	u_int n;
3441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int l;
3451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	cp = src;
3471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	dn = dst;
3481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	eom = dst + dstsiz;
3491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (dn >= eom) {
3511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		errno = EMSGSIZE;
3521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (-1);
3531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
3541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	while ((n = *cp++) != 0) {
3551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
3561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/* Some kind of compression pointer. */
3571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			errno = EMSGSIZE;
3581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
3591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
3601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		*dn++ = n;
3611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if ((l = labellen(cp - 1)) < 0) {
3621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			errno = EMSGSIZE;
3631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
3641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
3651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (dn + l >= eom) {
3661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			errno = EMSGSIZE;
3671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
3681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
3691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		for (; l > 0; l--) {
3701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			c = *cp++;
3711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (isupper(c))
3721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				*dn++ = tolower(c);
3731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			else
3741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				*dn++ = c;
3751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
3761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
3771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	*dn++ = '\0';
3781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (dn - dst);
3791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
3801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
3821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ns_name_unpack(msg, eom, src, dst, dstsiz)
3831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	Unpack a domain name from a message, source may be compressed.
3841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return:
3851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	-1 if it fails, or consumed octets if it succeeds.
3861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
3871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint
3881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src,
3891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	       u_char *dst, size_t dstsiz)
3901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
3911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const u_char *srcp, *dstlim;
3921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	u_char *dstp;
3931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int n, len, checked, l;
3941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	len = -1;
3961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	checked = 0;
3971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	dstp = dst;
3981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	srcp = src;
3991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	dstlim = dst + dstsiz;
4001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (srcp < msg || srcp >= eom) {
4011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		errno = EMSGSIZE;
4021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (-1);
4031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
4041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/* Fetch next label in domain name. */
4051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	while ((n = *srcp++) != 0) {
4061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/* Check for indirection. */
4071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		switch (n & NS_CMPRSFLGS) {
4081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 0:
4091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case NS_TYPE_ELT:
4101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/* Limit checks. */
4111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if ((l = labellen(srcp - 1)) < 0) {
4121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				errno = EMSGSIZE;
4131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return(-1);
4141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
4151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (dstp + l + 1 >= dstlim || srcp + l >= eom) {
4161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				errno = EMSGSIZE;
4171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return (-1);
4181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
4191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			checked += l + 1;
4201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			*dstp++ = n;
4211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			memcpy(dstp, srcp, (size_t)l);
4221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			dstp += l;
4231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			srcp += l;
4241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
4251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case NS_CMPRSFLGS:
4271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (srcp >= eom) {
4281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				errno = EMSGSIZE;
4291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return (-1);
4301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
4311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (len < 0)
4321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				len = srcp - src + 1;
4331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff));
4341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (srcp < msg || srcp >= eom) {  /* Out of range. */
4351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				errno = EMSGSIZE;
4361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return (-1);
4371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
4381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			checked += 2;
4391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/*
4401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 * Check for loops in the compressed name;
4411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 * if we've looked at the whole message,
4421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 * there must be a loop.
4431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 */
4441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (checked >= eom - msg) {
4451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				errno = EMSGSIZE;
4461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return (-1);
4471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
4481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
4491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		default:
4511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			errno = EMSGSIZE;
4521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);			/* flag error */
4531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
4541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
4551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	*dstp = '\0';
4561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (len < 0)
4571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		len = srcp - src;
4581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (len);
4591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
4601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
4621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ns_name_pack(src, dst, dstsiz, dnptrs, lastdnptr)
4631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	Pack domain name 'domain' into 'comp_dn'.
4641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return:
4651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	Size of the compressed name, or -1.
4661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notes:
4671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	'dnptrs' is an array of pointers to previous compressed names.
4681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	dnptrs[0] is a pointer to the beginning of the message. The array
4691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	ends with NULL.
4701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	'lastdnptr' is a pointer to the end of the array pointed to
4711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	by 'dnptrs'.
4721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Side effects:
4731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	The list of pointers in dnptrs is updated for labels inserted into
4741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	the message as we compress the name.  If 'dnptr' is NULL, we don't
4751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	try to compress names. If 'lastdnptr' is NULL, we don't update the
4761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	list.
4771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
4781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint
4791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectns_name_pack(const u_char *src, u_char *dst, int dstsiz,
4801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	     const u_char **dnptrs, const u_char **lastdnptr)
4811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
4821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	u_char *dstp;
4831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const u_char **cpp, **lpp, *eob, *msg;
4841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const u_char *srcp;
4851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int n, l, first = 1;
4861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	srcp = src;
4881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	dstp = dst;
4891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	eob = dstp + dstsiz;
4901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	lpp = cpp = NULL;
4911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (dnptrs != NULL) {
4921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if ((msg = *dnptrs++) != NULL) {
4931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			for (cpp = dnptrs; *cpp != NULL; cpp++)
4941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				;
4951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			lpp = cpp;	/* end of list to search */
4961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
4971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	} else
4981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		msg = NULL;
4991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/* make sure the domain we are about to add is legal */
5011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	l = 0;
5021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	do {
5031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		int l0;
5041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		n = *srcp;
5061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
5071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			errno = EMSGSIZE;
5081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
5091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
5101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if ((l0 = labellen(srcp)) < 0) {
5111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			errno = EINVAL;
5121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return(-1);
5131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
5141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		l += l0 + 1;
5151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (l > MAXCDNAME) {
5161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			errno = EMSGSIZE;
5171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
5181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
5191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		srcp += l0 + 1;
5201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	} while (n != 0);
5211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/* from here on we need to reset compression pointer array on error */
5231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	srcp = src;
5241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	do {
5251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/* Look to see if we can use pointers. */
5261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		n = *srcp;
5271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (n != 0 && msg != NULL) {
5281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			l = dn_find(srcp, msg, (const u_char * const *)dnptrs,
5291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				    (const u_char * const *)lpp);
5301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (l >= 0) {
5311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (dstp + 1 >= eob) {
5321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					goto cleanup;
5331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
5341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				*dstp++ = ((u_int32_t)l >> 8) | NS_CMPRSFLGS;
5351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				*dstp++ = l % 256;
5361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return (dstp - dst);
5371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
5381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/* Not found, save it. */
5391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (lastdnptr != NULL && cpp < lastdnptr - 1 &&
5401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			    (dstp - msg) < 0x4000 && first) {
5411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				*cpp++ = dstp;
5421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				*cpp = NULL;
5431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				first = 0;
5441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
5451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
5461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/* copy label to buffer */
5471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
5481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/* Should not happen. */
5491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto cleanup;
5501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
5511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		n = labellen(srcp);
5521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (dstp + 1 + n >= eob) {
5531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto cleanup;
5541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
5551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		memcpy(dstp, srcp, (size_t)(n + 1));
5561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		srcp += n + 1;
5571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		dstp += n + 1;
5581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	} while (n != 0);
5591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (dstp > eob) {
5611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectcleanup:
5621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (msg != NULL)
5631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			*lpp = NULL;
5641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		errno = EMSGSIZE;
5651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (-1);
5661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
5671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (dstp - dst);
5681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
5691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
5711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ns_name_uncompress(msg, eom, src, dst, dstsiz)
5721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	Expand compressed domain name to presentation format.
5731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return:
5741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	Number of bytes read out of `src', or -1 (with errno set).
5751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * note:
5761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	Root domain returns as "." not "".
5771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
5781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint
5791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectns_name_uncompress(const u_char *msg, const u_char *eom, const u_char *src,
5801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		   char *dst, size_t dstsiz)
5811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
5821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	u_char tmp[NS_MAXCDNAME];
5831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int n;
5841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if ((n = ns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1)
5861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (-1);
5871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (ns_name_ntop(tmp, dst, dstsiz) == -1)
5881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (-1);
5891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (n);
5901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
5911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
5931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ns_name_compress(src, dst, dstsiz, dnptrs, lastdnptr)
5941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	Compress a domain name into wire format, using compression pointers.
5951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return:
5961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	Number of bytes consumed in `dst' or -1 (with errno set).
5971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notes:
5981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	'dnptrs' is an array of pointers to previous compressed names.
5991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	dnptrs[0] is a pointer to the beginning of the message.
6001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	The list ends with NULL.  'lastdnptr' is a pointer to the end of the
6011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	array pointed to by 'dnptrs'. Side effect is to update the list of
6021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	pointers for labels inserted into the message as we compress the name.
6031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
6041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	is NULL, we don't update the list.
6051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
6061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint
6071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectns_name_compress(const char *src, u_char *dst, size_t dstsiz,
6081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 const u_char **dnptrs, const u_char **lastdnptr)
6091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
6101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	u_char tmp[NS_MAXCDNAME];
6111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (ns_name_pton(src, tmp, sizeof tmp) == -1)
6131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (-1);
6141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (ns_name_pack(tmp, dst, (int)dstsiz, dnptrs, lastdnptr));
6151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
6161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
6181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Reset dnptrs so that there are no active references to pointers at or
6191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * after src.
6201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
6211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectvoid
6221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectns_name_rollback(const u_char *src, const u_char **dnptrs,
6231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 const u_char **lastdnptr)
6241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
6251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	while (dnptrs < lastdnptr && *dnptrs != NULL) {
6261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (*dnptrs >= src) {
6271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			*dnptrs = NULL;
6281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
6291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
6301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		dnptrs++;
6311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
6321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
6331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
6351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ns_name_skip(ptrptr, eom)
6361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	Advance *ptrptr to skip over the compressed name it points at.
6371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return:
6381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	0 on success, -1 (with errno set) on failure.
6391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
6401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint
6411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectns_name_skip(const u_char **ptrptr, const u_char *eom)
6421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
6431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const u_char *cp;
6441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	u_int n;
6451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int l;
6461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	cp = *ptrptr;
6481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	while (cp < eom && (n = *cp++) != 0) {
6491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/* Check for indirection. */
6501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		switch (n & NS_CMPRSFLGS) {
6511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 0:			/* normal case, n == len */
6521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			cp += n;
6531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			continue;
6541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case NS_TYPE_ELT: /* EDNS0 extended label */
6551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if ((l = labellen(cp - 1)) < 0) {
6561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				errno = EMSGSIZE; /* XXX */
6571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return(-1);
6581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
6591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			cp += l;
6601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			continue;
6611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case NS_CMPRSFLGS:	/* indirection */
6621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			cp++;
6631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
6641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		default:		/* illegal type */
6651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			errno = EMSGSIZE;
6661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
6671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
6681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		break;
6691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
6701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (cp > eom) {
6711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		errno = EMSGSIZE;
6721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (-1);
6731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
6741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	*ptrptr = cp;
6751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (0);
6761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
6771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Private. */
6791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
6811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * special(ch)
6821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	Thinking in noninternationalized USASCII (per the DNS spec),
6831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	is this characted special ("in need of quoting") ?
6841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return:
6851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	boolean.
6861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
6871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int
6881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectspecial(int ch) {
6891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	switch (ch) {
6901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	case 0x22: /* '"' */
6911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	case 0x2E: /* '.' */
6921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	case 0x3B: /* ';' */
6931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	case 0x5C: /* '\\' */
6941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	case 0x28: /* '(' */
6951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	case 0x29: /* ')' */
6961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/* Special modifiers in zone files. */
6971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	case 0x40: /* '@' */
6981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	case 0x24: /* '$' */
6991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (1);
7001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	default:
7011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (0);
7021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
7031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
7041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
7051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
7061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * printable(ch)
7071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	Thinking in noninternationalized USASCII (per the DNS spec),
7081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	is this character visible and not a space when printed ?
7091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return:
7101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	boolean.
7111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
7121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int
7131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectprintable(int ch) {
7141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (ch > 0x20 && ch < 0x7f);
7151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
7161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
7171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
7181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	Thinking in noninternationalized USASCII (per the DNS spec),
7191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	convert this character to lower case if it's upper case.
7201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
7211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int
7221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectmklower(int ch) {
7231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (ch >= 0x41 && ch <= 0x5A)
7241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (ch + 0x20);
7251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (ch);
7261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
7271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
7281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
7291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * dn_find(domain, msg, dnptrs, lastdnptr)
7301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	Search for the counted-label name in an array of compressed names.
7311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return:
7321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	offset from msg if found, or -1.
7331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notes:
7341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	dnptrs is the pointer to the first name on the list,
7351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	not the pointer to the start of the message.
7361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
7371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int
7381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdn_find(const u_char *domain, const u_char *msg,
7391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const u_char * const *dnptrs,
7401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const u_char * const *lastdnptr)
7411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
7421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const u_char *dn, *cp, *sp;
7431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const u_char * const *cpp;
7441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	u_int n;
7451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
7461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
7471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		sp = *cpp;
7481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/*
7491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * terminate search on:
7501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * root label
7511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * compression pointer
7521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * unusable offset
7531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 */
7541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		while (*sp != 0 && (*sp & NS_CMPRSFLGS) == 0 &&
7551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		       (sp - msg) < 0x4000) {
7561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			dn = domain;
7571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			cp = sp;
7581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			while ((n = *cp++) != 0) {
7591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				/*
7601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				 * check for indirection
7611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				 */
7621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				switch (n & NS_CMPRSFLGS) {
7631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				case 0:		/* normal case, n == len */
7641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					n = labellen(cp - 1); /* XXX */
7651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
7661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					if (n != *dn++)
7671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project						goto next;
7681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
7691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					for (; n > 0; n--)
7701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project						if (mklower(*dn++) !=
7711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project						    mklower(*cp++))
7721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project							goto next;
7731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					/* Is next root for both ? */
7741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					if (*dn == '\0' && *cp == '\0')
7751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project						return (sp - msg);
7761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					if (*dn)
7771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project						continue;
7781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					goto next;
7791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				case NS_CMPRSFLGS:	/* indirection */
7801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					cp = msg + (((n & 0x3f) << 8) | *cp);
7811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					break;
7821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
7831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				default:	/* illegal type */
7841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					errno = EMSGSIZE;
7851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					return (-1);
7861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
7871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
7881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project next: ;
7891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			sp += *sp + 1;
7901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
7911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
7921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	errno = ENOENT;
7931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (-1);
7941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
7951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
7961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int
7971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdecode_bitstring(const unsigned char **cpp, char *dn, const char *eom)
7981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
7991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const unsigned char *cp = *cpp;
8001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	char *beg = dn, tc;
8011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int b, blen, plen, i;
8021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
8031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if ((blen = (*cp & 0xff)) == 0)
8041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		blen = 256;
8051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	plen = (blen + 3) / 4;
8061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	plen += sizeof("\\[x/]") + (blen > 99 ? 3 : (blen > 9) ? 2 : 1);
8071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (dn + plen >= eom)
8081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return(-1);
8091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
8101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	cp++;
8111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	i = SPRINTF((dn, "\\[x"));
8121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (i < 0)
8131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (-1);
8141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	dn += i;
8151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	for (b = blen; b > 7; b -= 8, cp++) {
8161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		i = SPRINTF((dn, "%02x", *cp & 0xff));
8171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (i < 0)
8181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
8191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		dn += i;
8201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
8211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (b > 4) {
8221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		tc = *cp++;
8231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		i = SPRINTF((dn, "%02x", tc & (0xff << (8 - b))));
8241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (i < 0)
8251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
8261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		dn += i;
8271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	} else if (b > 0) {
8281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		tc = *cp++;
8291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		i = SPRINTF((dn, "%1x",
8301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			       (((u_int32_t)tc >> 4) & 0x0f) & (0x0f << (4 - b))));
8311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (i < 0)
8321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
8331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		dn += i;
8341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
8351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	i = SPRINTF((dn, "/%d]", blen));
8361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (i < 0)
8371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (-1);
8381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	dn += i;
8391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
8401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	*cpp = cp;
8411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return(dn - beg);
8421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
8431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
8441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int
8451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectencode_bitsring(const char **bp, const char *end, unsigned char **labelp,
8461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	        unsigned char ** dst, unsigned const char *eom)
8471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
8481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int afterslash = 0;
8491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const char *cp = *bp;
8501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	unsigned char *tp;
8511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	char c;
8521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const char *beg_blen;
8531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	char *end_blen = NULL;
8541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int value = 0, count = 0, tbcount = 0, blen = 0;
8551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
8561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	beg_blen = end_blen = NULL;
8571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
8581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/* a bitstring must contain at least 2 characters */
8591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (end - cp < 2)
8601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return(EINVAL);
8611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
8621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/* XXX: currently, only hex strings are supported */
8631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (*cp++ != 'x')
8641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return(EINVAL);
8651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (!isxdigit((*cp) & 0xff)) /* reject '\[x/BLEN]' */
8661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return(EINVAL);
8671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
8681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	for (tp = *dst + 1; cp < end && tp < eom; cp++) {
8691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		switch((c = *cp)) {
8701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case ']':	/* end of the bitstring */
8711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (afterslash) {
8721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (beg_blen == NULL)
8731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					return(EINVAL);
8741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				blen = (int)strtol(beg_blen, &end_blen, 10);
8751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (*end_blen != ']')
8761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					return(EINVAL);
8771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
8781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (count)
8791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				*tp++ = ((value << 4) & 0xff);
8801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			cp++;	/* skip ']' */
8811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto done;
8821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case '/':
8831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			afterslash = 1;
8841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
8851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		default:
8861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (afterslash) {
8871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (!isdigit(c&0xff))
8881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					return(EINVAL);
8891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (beg_blen == NULL) {
8901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
8911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					if (c == '0') {
8921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project						/* blen never begings with 0 */
8931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project						return(EINVAL);
8941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					}
8951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					beg_blen = cp;
8961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
8971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			} else {
8981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (!isxdigit(c&0xff))
8991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					return(EINVAL);
9001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				value <<= 4;
9011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				value += digitvalue[(int)c];
9021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				count += 4;
9031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				tbcount += 4;
9041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (tbcount > 256)
9051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					return(EINVAL);
9061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (count == 8) {
9071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					*tp++ = value;
9081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					count = 0;
9091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
9101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
9111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
9121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
9131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
9141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project  done:
9151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (cp >= end || tp >= eom)
9161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return(EMSGSIZE);
9171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/*
9191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * bit length validation:
9201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * If a <length> is present, the number of digits in the <bit-data>
9211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * MUST be just sufficient to contain the number of bits specified
9221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * by the <length>. If there are insignificant bits in a final
9231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * hexadecimal or octal digit, they MUST be zero.
9241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * RFC 2673, Section 3.2.
9251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 */
9261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (blen > 0) {
9271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		int traillen;
9281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (((blen + 3) & ~3) != tbcount)
9301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return(EINVAL);
9311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		traillen = tbcount - blen; /* between 0 and 3 */
9321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (((value << (8 - traillen)) & 0xff) != 0)
9331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return(EINVAL);
9341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
9351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	else
9361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		blen = tbcount;
9371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (blen == 256)
9381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		blen = 0;
9391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/* encode the type and the significant bit fields */
9411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	**labelp = DNS_LABELTYPE_BITSTRING;
9421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	**dst = blen;
9431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	*bp = cp;
9451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	*dst = tp;
9461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return(0);
9481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
9491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int
9511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectlabellen(const u_char *lp)
9521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
9531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int bitlen;
9541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	u_char l = *lp;
9551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if ((l & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
9571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/* should be avoided by the caller */
9581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return(-1);
9591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
9601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if ((l & NS_CMPRSFLGS) == NS_TYPE_ELT) {
9621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (l == DNS_LABELTYPE_BITSTRING) {
9631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if ((bitlen = *(lp + 1)) == 0)
9641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				bitlen = 256;
9651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return((bitlen + 7 ) / 8 + 1);
9661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
9671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return(-1);	/* unknwon ELT */
9681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
9691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return(l);
9701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
971