1fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle/*	$NetBSD: ns_name.c,v 1.9 2012/03/13 21:13:39 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
23fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravlestatic const char rcsid[] = "Id: ns_name.c,v 1.11 2009/01/23 19:59:16 each Exp";
241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#else
25fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle__RCSID("$NetBSD: ns_name.c,v 1.9 2012/03/13 21:13:39 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>
32569fb9887d00104509df79fa77d92e3cf9afe7dbCalin Juravle#include <arpa/nameser.h>
331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
34fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle#include <assert.h>
351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <errno.h>
361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef ANDROID_CHANGES
371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "resolv_private.h"
381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#else
391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <resolv.h>
401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <string.h>
421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <ctype.h>
431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdlib.h>
441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <limits.h>
451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef SPRINTF_CHAR
47fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle# define SPRINTF(x) ((int)strlen(sprintf/**/x))
481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#else
49fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle# define SPRINTF(x) (sprintf x)
501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define NS_TYPE_ELT			0x40 /* EDNS0 extended label type */
531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define DNS_LABELTYPE_BITSTRING		0x41
541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Data. */
561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const char	digits[] = "0123456789";
581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const char digitvalue[256] = {
601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,	/*16*/
611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/
621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/
631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1, /*64*/
641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/
651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/
661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/
671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/
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,
751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/
761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project};
771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Forward. */
791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int		special(int);
811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int		printable(int);
821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int		dn_find(const u_char *, const u_char *,
831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				const u_char * const *,
841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				const u_char * const *);
851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int		encode_bitsring(const char **, const char *,
861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					unsigned char **, unsigned char **,
871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					unsigned const char *);
881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int		labellen(const u_char *);
891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int		decode_bitstring(const unsigned char **,
901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					 char *, const char *);
911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Public. */
931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
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)
98fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle *
991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notes:
1001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	The root is returned as "."
1011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	All other domains are returned in non absolute form
1021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
1031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint
1041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectns_name_ntop(const u_char *src, char *dst, size_t dstsiz)
1051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
1061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const u_char *cp;
1071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	char *dn, *eom;
1081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	u_char c;
1091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	u_int n;
1101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int l;
1111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	cp = src;
1131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	dn = dst;
1141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	eom = dst + dstsiz;
1151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	while ((n = *cp++) != 0) {
1171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
1181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/* Some kind of compression pointer. */
1191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			errno = EMSGSIZE;
1201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
1211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
1221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (dn != dst) {
1231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (dn >= eom) {
1241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				errno = EMSGSIZE;
1251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return (-1);
1261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
1271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			*dn++ = '.';
1281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
1291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if ((l = labellen(cp - 1)) < 0) {
1301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			errno = EMSGSIZE; /* XXX */
1311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return(-1);
1321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
1331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (dn + l >= eom) {
1341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			errno = EMSGSIZE;
1351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
1361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
1371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if ((n & NS_CMPRSFLGS) == NS_TYPE_ELT) {
1381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			int m;
1391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (n != DNS_LABELTYPE_BITSTRING) {
1411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				/* XXX: labellen should reject this case */
1421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				errno = EINVAL;
1431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return(-1);
1441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
1451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if ((m = decode_bitstring(&cp, dn, eom)) < 0)
1461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			{
1471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				errno = EMSGSIZE;
1481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return(-1);
1491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
1501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			dn += m;
1511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			continue;
1521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
1531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		for (; l > 0; l--) {
1541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			c = *cp++;
1551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (special(c)) {
1561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (dn + 1 >= eom) {
1571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					errno = EMSGSIZE;
1581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					return (-1);
1591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
1601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				*dn++ = '\\';
1611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				*dn++ = (char)c;
1621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			} else if (!printable(c)) {
1631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (dn + 3 >= eom) {
1641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					errno = EMSGSIZE;
1651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					return (-1);
1661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
1671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				*dn++ = '\\';
1681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				*dn++ = digits[c / 100];
1691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				*dn++ = digits[(c % 100) / 10];
1701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				*dn++ = digits[c % 10];
1711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			} else {
1721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (dn >= eom) {
1731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					errno = EMSGSIZE;
1741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					return (-1);
1751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
1761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				*dn++ = (char)c;
1771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
1781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
1791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
1801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (dn == dst) {
1811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (dn >= eom) {
1821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			errno = EMSGSIZE;
1831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
1841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
1851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		*dn++ = '.';
1861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
1871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (dn >= eom) {
1881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		errno = EMSGSIZE;
1891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (-1);
1901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
1911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	*dn++ = '\0';
192fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	_DIAGASSERT(__type_fit(int, dn - dst));
193fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	return (int)(dn - dst);
194fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle}
195fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle
196fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle/*
197fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle *	Convert a ascii string into an encoded domain name as per RFC1035.
198fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle *
199fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * return:
200fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle *
201fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle *	-1 if it fails
202fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle *	1 if string was fully qualified
203fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle *	0 is string was not fully qualified
204fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle *
205fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * notes:
206fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle *	Enforces label and domain length limits.
207fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle */
208fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravleint
209fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravlens_name_pton(const char *src, u_char *dst, size_t dstsiz) {
210fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	return (ns_name_pton2(src, dst, dstsiz, NULL));
2111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
2121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
214fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * ns_name_pton2(src, dst, dstsiz, *dstlen)
2151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	Convert a ascii string into an encoded domain name as per RFC1035.
2161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return:
2171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	-1 if it fails
2181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	1 if string was fully qualified
2191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	0 is string was not fully qualified
220fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * side effects:
221fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle *	fills in *dstlen (if non-NULL)
2221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notes:
2231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	Enforces label and domain length limits.
2241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
2251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint
227fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravlens_name_pton2(const char *src, u_char *dst, size_t dstsiz, size_t *dstlen) {
2281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	u_char *label, *bp, *eom;
2291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int c, n, escaped, e = 0;
2301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	char *cp;
2311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	escaped = 0;
2331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	bp = dst;
2341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	eom = dst + dstsiz;
2351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	label = bp++;
2361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	while ((c = *src++) != 0) {
2381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (escaped) {
2391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (c == '[') { /* start a bit string label */
2401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if ((cp = strchr(src, ']')) == NULL) {
2411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					errno = EINVAL; /* ??? */
2421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					return(-1);
2431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
2441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if ((e = encode_bitsring(&src, cp + 2,
2451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project							 &label, &bp, eom))
2461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				    != 0) {
2471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					errno = e;
2481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					return(-1);
2491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
2501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				escaped = 0;
2511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				label = bp++;
2521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if ((c = *src++) == 0)
2531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					goto done;
2541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				else if (c != '.') {
2551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					errno = EINVAL;
2561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					return(-1);
2571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
2581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				continue;
2591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
2601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			else if ((cp = strchr(digits, c)) != NULL) {
261fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle				n = (int)(cp - digits) * 100;
2621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if ((c = *src++) == 0 ||
2631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				    (cp = strchr(digits, c)) == NULL) {
2641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					errno = EMSGSIZE;
2651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					return (-1);
2661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
267fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle				n += (int)(cp - digits) * 10;
2681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if ((c = *src++) == 0 ||
2691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				    (cp = strchr(digits, c)) == NULL) {
2701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					errno = EMSGSIZE;
2711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					return (-1);
2721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
273fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle				n += (int)(cp - digits);
2741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (n > 255) {
2751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					errno = EMSGSIZE;
2761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					return (-1);
2771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
2781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				c = n;
2791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
2801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			escaped = 0;
2811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		} else if (c == '\\') {
2821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			escaped = 1;
2831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			continue;
2841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		} else if (c == '.') {
285fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle			c = (int)(bp - label - 1);
2861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if ((c & NS_CMPRSFLGS) != 0) {	/* Label too big. */
2871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				errno = EMSGSIZE;
2881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return (-1);
2891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
2901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (label >= eom) {
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 = c;
2951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/* Fully qualified ? */
2961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (*src == '\0') {
2971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (c != 0) {
2981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					if (bp >= eom) {
2991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project						errno = EMSGSIZE;
3001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project						return (-1);
3011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					}
3021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					*bp++ = '\0';
3031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
3041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if ((bp - dst) > MAXCDNAME) {
3051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					errno = EMSGSIZE;
3061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					return (-1);
3071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
308fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle				if (dstlen != NULL)
309fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle					*dstlen = (bp - dst);
3101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return (1);
3111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
3121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (c == 0 || *src == '.') {
3131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				errno = EMSGSIZE;
3141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return (-1);
3151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
3161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			label = bp++;
3171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			continue;
3181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
3191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (bp >= eom) {
3201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			errno = EMSGSIZE;
3211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
3221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
3231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		*bp++ = (u_char)c;
3241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
325fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	c = (int)(bp - label - 1);
3261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if ((c & NS_CMPRSFLGS) != 0) {		/* Label too big. */
3271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		errno = EMSGSIZE;
3281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (-1);
3291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
3301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project  done:
3311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (label >= eom) {
3321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		errno = EMSGSIZE;
3331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (-1);
3341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
3351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	*label = c;
3361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (c != 0) {
3371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (bp >= eom) {
3381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			errno = EMSGSIZE;
3391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
3401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
3411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		*bp++ = 0;
3421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
3431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if ((bp - dst) > MAXCDNAME) {	/* src too big */
3441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		errno = EMSGSIZE;
3451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (-1);
3461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
347fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	if (dstlen != NULL)
348fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle		*dstlen = (bp - dst);
3491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (0);
3501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
3511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
3531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	Convert a network strings labels into all lowercase.
354fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle *
3551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return:
3561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	Number of bytes written to buffer, or -1 (with errno set)
357fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle *
3581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notes:
3591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	Enforces label and domain length limits.
3601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
3611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint
3631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectns_name_ntol(const u_char *src, u_char *dst, size_t dstsiz)
3641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
3651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const u_char *cp;
3661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	u_char *dn, *eom;
3671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	u_char c;
3681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	u_int n;
3691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int l;
3701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	cp = src;
3721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	dn = dst;
3731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	eom = dst + dstsiz;
3741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (dn >= eom) {
3761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		errno = EMSGSIZE;
3771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (-1);
3781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
3791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	while ((n = *cp++) != 0) {
3801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
3811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/* Some kind of compression pointer. */
3821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			errno = EMSGSIZE;
3831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
3841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
3851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		*dn++ = n;
3861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if ((l = labellen(cp - 1)) < 0) {
3871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			errno = EMSGSIZE;
3881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
3891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
3901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (dn + l >= eom) {
3911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			errno = EMSGSIZE;
3921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
3931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
3941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		for (; l > 0; l--) {
3951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			c = *cp++;
396fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle			if (isascii(c) && isupper(c))
3971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				*dn++ = tolower(c);
3981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			else
3991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				*dn++ = c;
4001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
4011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
4021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	*dn++ = '\0';
403fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	_DIAGASSERT(__type_fit(int, dn - dst));
404fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	return (int)(dn - dst);
4051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
4061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
4081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	Unpack a domain name from a message, source may be compressed.
409fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle *
4101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return:
4111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	-1 if it fails, or consumed octets if it succeeds.
4121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
4131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint
4141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src,
4151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	       u_char *dst, size_t dstsiz)
4161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
417fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	return (ns_name_unpack2(msg, eom, src, dst, dstsiz, NULL));
418fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle}
419fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle
420fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle/*
421fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * ns_name_unpack2(msg, eom, src, dst, dstsiz, *dstlen)
422fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle *	Unpack a domain name from a message, source may be compressed.
423fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * return:
424fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle *	-1 if it fails, or consumed octets if it succeeds.
425fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * side effect:
426fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle *	fills in *dstlen (if non-NULL).
427fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle */
428fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravleint
429fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravlens_name_unpack2(const u_char *msg, const u_char *eom, const u_char *src,
430fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle		u_char *dst, size_t dstsiz, size_t *dstlen)
431fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle{
4321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const u_char *srcp, *dstlim;
4331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	u_char *dstp;
4341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int n, len, checked, l;
4351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	len = -1;
4371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	checked = 0;
4381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	dstp = dst;
4391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	srcp = src;
4401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	dstlim = dst + dstsiz;
4411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (srcp < msg || srcp >= eom) {
4421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		errno = EMSGSIZE;
4431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (-1);
4441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
4451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/* Fetch next label in domain name. */
4461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	while ((n = *srcp++) != 0) {
4471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/* Check for indirection. */
4481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		switch (n & NS_CMPRSFLGS) {
4491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 0:
4501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case NS_TYPE_ELT:
4511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/* Limit checks. */
4521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if ((l = labellen(srcp - 1)) < 0) {
4531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				errno = EMSGSIZE;
4541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return(-1);
4551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
4561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (dstp + l + 1 >= dstlim || srcp + l >= eom) {
4571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				errno = EMSGSIZE;
4581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return (-1);
4591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
4601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			checked += l + 1;
4611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			*dstp++ = n;
4621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			memcpy(dstp, srcp, (size_t)l);
4631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			dstp += l;
4641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			srcp += l;
4651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
4661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case NS_CMPRSFLGS:
4681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (srcp >= eom) {
4691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				errno = EMSGSIZE;
4701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return (-1);
4711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
472fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle			if (len < 0) {
473fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle				_DIAGASSERT(__type_fit(int, srcp - src + 1));
474fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle				len = (int)(srcp - src + 1);
475fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle			}
47685c5202a64e3cb63e54550fca7bb11f24b9d12ccCalin Juravle			// BEGIN android-changed: safer pointer overflow check
47785c5202a64e3cb63e54550fca7bb11f24b9d12ccCalin Juravle			l = (((n & 0x3f) << 8) | (*srcp & 0xff));
47885c5202a64e3cb63e54550fca7bb11f24b9d12ccCalin Juravle			if (l >= eom - msg) {  /* Out of range. */
4791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				errno = EMSGSIZE;
4801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return (-1);
4811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
48285c5202a64e3cb63e54550fca7bb11f24b9d12ccCalin Juravle			srcp = msg + l;
48385c5202a64e3cb63e54550fca7bb11f24b9d12ccCalin Juravle			// END android-changed
4841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			checked += 2;
4851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/*
4861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 * Check for loops in the compressed name;
4871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 * if we've looked at the whole message,
4881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 * there must be a loop.
4891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 */
4901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (checked >= eom - msg) {
4911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				errno = EMSGSIZE;
4921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return (-1);
4931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
4941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
4951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		default:
4971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			errno = EMSGSIZE;
4981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);			/* flag error */
4991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
5001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
501fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	*dstp++ = 0;
502fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	if (dstlen != NULL)
503fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle		*dstlen = dstp - dst;
504fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	if (len < 0) {
505fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle		_DIAGASSERT(__type_fit(int, srcp - src));
506fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle		len = (int)(srcp - src);
507fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	}
508fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	return len;
5091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
5101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
5121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	Pack domain name 'domain' into 'comp_dn'.
513fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle *
5141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return:
5151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	Size of the compressed name, or -1.
516fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle *
5171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notes:
5181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	'dnptrs' is an array of pointers to previous compressed names.
5191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	dnptrs[0] is a pointer to the beginning of the message. The array
5201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	ends with NULL.
5211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	'lastdnptr' is a pointer to the end of the array pointed to
5221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	by 'dnptrs'.
523fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle *
5241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Side effects:
5251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	The list of pointers in dnptrs is updated for labels inserted into
5261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	the message as we compress the name.  If 'dnptr' is NULL, we don't
5271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	try to compress names. If 'lastdnptr' is NULL, we don't update the
5281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	list.
5291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
5301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint
5311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectns_name_pack(const u_char *src, u_char *dst, int dstsiz,
5321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	     const u_char **dnptrs, const u_char **lastdnptr)
5331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
5341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	u_char *dstp;
5351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const u_char **cpp, **lpp, *eob, *msg;
5361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const u_char *srcp;
5371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int n, l, first = 1;
5381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	srcp = src;
5401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	dstp = dst;
5411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	eob = dstp + dstsiz;
5421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	lpp = cpp = NULL;
5431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (dnptrs != NULL) {
5441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if ((msg = *dnptrs++) != NULL) {
5451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			for (cpp = dnptrs; *cpp != NULL; cpp++)
546fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle				continue;
5471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			lpp = cpp;	/* end of list to search */
5481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
5491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	} else
5501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		msg = NULL;
5511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/* make sure the domain we are about to add is legal */
5531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	l = 0;
5541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	do {
5551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		int l0;
5561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		n = *srcp;
5581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
5591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			errno = EMSGSIZE;
5601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
5611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
5621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if ((l0 = labellen(srcp)) < 0) {
5631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			errno = EINVAL;
5641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return(-1);
5651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
5661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		l += l0 + 1;
5671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (l > MAXCDNAME) {
5681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			errno = EMSGSIZE;
5691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
5701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
5711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		srcp += l0 + 1;
5721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	} while (n != 0);
5731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/* from here on we need to reset compression pointer array on error */
5751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	srcp = src;
5761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	do {
5771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/* Look to see if we can use pointers. */
5781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		n = *srcp;
5791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (n != 0 && msg != NULL) {
5801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			l = dn_find(srcp, msg, (const u_char * const *)dnptrs,
5811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				    (const u_char * const *)lpp);
5821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (l >= 0) {
5831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (dstp + 1 >= eob) {
5841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					goto cleanup;
5851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
5861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				*dstp++ = ((u_int32_t)l >> 8) | NS_CMPRSFLGS;
5871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				*dstp++ = l % 256;
588fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle				_DIAGASSERT(__type_fit(int, dstp - dst));
589fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle				return (int)(dstp - dst);
5901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
5911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/* Not found, save it. */
5921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (lastdnptr != NULL && cpp < lastdnptr - 1 &&
5931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			    (dstp - msg) < 0x4000 && first) {
5941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				*cpp++ = dstp;
5951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				*cpp = NULL;
5961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				first = 0;
5971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
5981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
5991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/* copy label to buffer */
6001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
6011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/* Should not happen. */
6021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto cleanup;
6031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
6041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		n = labellen(srcp);
6051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (dstp + 1 + n >= eob) {
6061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto cleanup;
6071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
6081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		memcpy(dstp, srcp, (size_t)(n + 1));
6091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		srcp += n + 1;
6101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		dstp += n + 1;
6111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	} while (n != 0);
6121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (dstp > eob) {
6141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectcleanup:
6151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (msg != NULL)
6161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			*lpp = NULL;
6171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		errno = EMSGSIZE;
6181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (-1);
6191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
620fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	_DIAGASSERT(__type_fit(int, dstp - dst));
621fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	return (int)(dstp - dst);
6221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
6231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
6251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	Expand compressed domain name to presentation format.
626fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle *
6271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return:
6281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	Number of bytes read out of `src', or -1 (with errno set).
629fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle *
6301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * note:
6311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	Root domain returns as "." not "".
6321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
6331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint
6341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectns_name_uncompress(const u_char *msg, const u_char *eom, const u_char *src,
6351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		   char *dst, size_t dstsiz)
6361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
6371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	u_char tmp[NS_MAXCDNAME];
6381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int n;
6391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if ((n = ns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1)
6411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (-1);
6421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (ns_name_ntop(tmp, dst, dstsiz) == -1)
6431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (-1);
6441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (n);
6451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
6461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
6481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	Compress a domain name into wire format, using compression pointers.
649fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle *
6501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return:
6511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	Number of bytes consumed in `dst' or -1 (with errno set).
652fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle *
6531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notes:
6541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	'dnptrs' is an array of pointers to previous compressed names.
6551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	dnptrs[0] is a pointer to the beginning of the message.
6561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	The list ends with NULL.  'lastdnptr' is a pointer to the end of the
6571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	array pointed to by 'dnptrs'. Side effect is to update the list of
6581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	pointers for labels inserted into the message as we compress the name.
6591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
6601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	is NULL, we don't update the list.
6611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
6621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint
6631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectns_name_compress(const char *src, u_char *dst, size_t dstsiz,
6641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 const u_char **dnptrs, const u_char **lastdnptr)
6651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
6661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	u_char tmp[NS_MAXCDNAME];
6671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (ns_name_pton(src, tmp, sizeof tmp) == -1)
6691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (-1);
6701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (ns_name_pack(tmp, dst, (int)dstsiz, dnptrs, lastdnptr));
6711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
6721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
6741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Reset dnptrs so that there are no active references to pointers at or
6751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * after src.
6761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
6771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectvoid
6781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectns_name_rollback(const u_char *src, const u_char **dnptrs,
6791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 const u_char **lastdnptr)
6801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
6811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	while (dnptrs < lastdnptr && *dnptrs != NULL) {
6821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (*dnptrs >= src) {
6831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			*dnptrs = NULL;
6841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
6851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
6861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		dnptrs++;
6871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
6881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
6891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
6911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	Advance *ptrptr to skip over the compressed name it points at.
692fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle *
6931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return:
6941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	0 on success, -1 (with errno set) on failure.
6951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
6961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint
6971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectns_name_skip(const u_char **ptrptr, const u_char *eom)
6981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
6991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const u_char *cp;
7001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	u_int n;
7011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int l;
7021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
7031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	cp = *ptrptr;
7041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	while (cp < eom && (n = *cp++) != 0) {
7051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/* Check for indirection. */
7061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		switch (n & NS_CMPRSFLGS) {
7071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 0:			/* normal case, n == len */
7081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			cp += n;
7091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			continue;
7101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case NS_TYPE_ELT: /* EDNS0 extended label */
7111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if ((l = labellen(cp - 1)) < 0) {
7121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				errno = EMSGSIZE; /* XXX */
7131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return(-1);
7141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
7151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			cp += l;
7161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			continue;
7171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case NS_CMPRSFLGS:	/* indirection */
7181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			cp++;
7191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
7201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		default:		/* illegal type */
7211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			errno = EMSGSIZE;
7221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
7231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
7241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		break;
7251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
7261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (cp > eom) {
7271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		errno = EMSGSIZE;
7281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (-1);
7291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
7301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	*ptrptr = cp;
7311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (0);
7321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
7331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
734fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle/* Find the number of octets an nname takes up, including the root label.
735fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * (This is basically ns_name_skip() without compression-pointer support.)
736fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * ((NOTE: can only return zero if passed-in namesiz argument is zero.))
737fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle */
738fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravlessize_t
739fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravlens_name_length(ns_nname_ct nname, size_t namesiz) {
740fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	ns_nname_ct orig = nname;
741fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	u_int n;
742fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle
743fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	while (namesiz-- > 0 && (n = *nname++) != 0) {
744fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle		if ((n & NS_CMPRSFLGS) != 0) {
745fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle			errno = EISDIR;
746fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle			return (-1);
747fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle		}
748fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle		if (n > namesiz) {
749fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle			errno = EMSGSIZE;
750fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle			return (-1);
751fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle		}
752fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle		nname += n;
753fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle		namesiz -= n;
754fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	}
755fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	return (nname - orig);
756fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle}
757fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle
758fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle/* Compare two nname's for equality.  Return -1 on error (setting errno).
759fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle */
760fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravleint
761fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravlens_name_eq(ns_nname_ct a, size_t as, ns_nname_ct b, size_t bs) {
762fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	ns_nname_ct ae = a + as, be = b + bs;
763fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	int ac, bc;
764fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle
765fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	while (ac = *a, bc = *b, ac != 0 && bc != 0) {
766fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle		if ((ac & NS_CMPRSFLGS) != 0 || (bc & NS_CMPRSFLGS) != 0) {
767fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle			errno = EISDIR;
768fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle			return (-1);
769fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle		}
770fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle		if (a + ac >= ae || b + bc >= be) {
771fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle			errno = EMSGSIZE;
772fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle			return (-1);
773fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle		}
774fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle		if (ac != bc || strncasecmp((const char *) ++a,
775fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle					    (const char *) ++b,
776fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle					    (size_t)ac) != 0)
777fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle			return (0);
778fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle		a += ac, b += bc;
779fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	}
780fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	return (ac == 0 && bc == 0);
781fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle}
782fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle
783fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle/* Is domain "A" owned by (at or below) domain "B"?
784fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle */
785fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravleint
786fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravlens_name_owned(ns_namemap_ct a, int an, ns_namemap_ct b, int bn) {
787fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	/* If A is shorter, it cannot be owned by B. */
788fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	if (an < bn)
789fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle		return (0);
790fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle
791fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	/* If they are unequal before the length of the shorter, A cannot... */
792fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	while (bn > 0) {
793fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle		if (a->len != b->len ||
794fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle		    strncasecmp((const char *) a->base,
795fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle				(const char *) b->base, (size_t)a->len) != 0)
796fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle			return (0);
797fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle		a++, an--;
798fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle		b++, bn--;
799fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	}
800fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle
801fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	/* A might be longer or not, but either way, B owns it. */
802fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	return (1);
803fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle}
804fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle
805fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle/* Build an array of <base,len> tuples from an nname, top-down order.
806fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * Return the number of tuples (labels) thus discovered.
807fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle */
808fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravleint
809fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravlens_name_map(ns_nname_ct nname, size_t namelen, ns_namemap_t map, int mapsize) {
810fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	u_int n;
811fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	int l;
812fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle
813fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	n = *nname++;
814fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	namelen--;
815fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle
816fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	/* Root zone? */
817fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	if (n == 0) {
818fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle		/* Extra data follows name? */
819fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle		if (namelen > 0) {
820fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle			errno = EMSGSIZE;
821fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle			return (-1);
822fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle		}
823fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle		return (0);
824fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	}
825fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle
826fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	/* Compression pointer? */
827fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	if ((n & NS_CMPRSFLGS) != 0) {
828fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle		errno = EISDIR;
829fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle		return (-1);
830fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	}
831fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle
832fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	/* Label too long? */
833fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	if (n > namelen) {
834fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle		errno = EMSGSIZE;
835fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle		return (-1);
836fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	}
837fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle
838fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	/* Recurse to get rest of name done first. */
839fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	l = ns_name_map(nname + n, namelen - n, map, mapsize);
840fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	if (l < 0)
841fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle		return (-1);
842fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle
843fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	/* Too many labels? */
844fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	if (l >= mapsize) {
845fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle		errno = ENAMETOOLONG;
846fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle		return (-1);
847fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	}
848fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle
849fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	/* We're on our way back up-stack, store current map data. */
850fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	map[l].base = nname;
851fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	map[l].len = n;
852fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	return (l + 1);
853fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle}
854fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle
855fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle/* Count the labels in a domain name.  Root counts, so COM. has two.  This
856fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * is to make the result comparable to the result of ns_name_map().
857fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle */
858fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravleint
859fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravlens_name_labels(ns_nname_ct nname, size_t namesiz) {
860fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	int ret = 0;
861fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	u_int n;
862fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle
863fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	while (namesiz-- > 0 && (n = *nname++) != 0) {
864fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle		if ((n & NS_CMPRSFLGS) != 0) {
865fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle			errno = EISDIR;
866fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle			return (-1);
867fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle		}
868fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle		if (n > namesiz) {
869fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle			errno = EMSGSIZE;
870fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle			return (-1);
871fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle		}
872fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle		nname += n;
873fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle		namesiz -= n;
874fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle		ret++;
875fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	}
876fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	return (ret + 1);
877fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle}
8781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Private. */
8791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
8801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
8811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	Thinking in noninternationalized USASCII (per the DNS spec),
8821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	is this characted special ("in need of quoting") ?
883fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle *
8841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return:
8851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	boolean.
8861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
8871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int
8881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectspecial(int ch) {
8891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	switch (ch) {
8901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	case 0x22: /* '"' */
8911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	case 0x2E: /* '.' */
8921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	case 0x3B: /* ';' */
8931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	case 0x5C: /* '\\' */
8941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	case 0x28: /* '(' */
8951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	case 0x29: /* ')' */
8961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/* Special modifiers in zone files. */
8971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	case 0x40: /* '@' */
8981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	case 0x24: /* '$' */
8991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (1);
9001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	default:
9011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (0);
9021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
9031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
9041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
9061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	Thinking in noninternationalized USASCII (per the DNS spec),
9071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	is this character visible and not a space when printed ?
908fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle *
9091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return:
9101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	boolean.
9111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
9121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int
9131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectprintable(int ch) {
9141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (ch > 0x20 && ch < 0x7f);
9151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
9161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
9181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	Thinking in noninternationalized USASCII (per the DNS spec),
9191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	convert this character to lower case if it's upper case.
9201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
9211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int
9221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectmklower(int ch) {
9231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (ch >= 0x41 && ch <= 0x5A)
9241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (ch + 0x20);
9251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (ch);
9261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
9271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
9291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	Search for the counted-label name in an array of compressed names.
930fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle *
9311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return:
9321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	offset from msg if found, or -1.
933fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle *
9341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notes:
9351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	dnptrs is the pointer to the first name on the list,
9361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	not the pointer to the start of the message.
9371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
9381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int
9391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdn_find(const u_char *domain, const u_char *msg,
9401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const u_char * const *dnptrs,
9411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const u_char * const *lastdnptr)
9421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
9431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const u_char *dn, *cp, *sp;
9441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const u_char * const *cpp;
9451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	u_int n;
9461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
9481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		sp = *cpp;
9491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/*
9501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * terminate search on:
9511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * root label
9521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * compression pointer
9531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * unusable offset
9541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 */
9551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		while (*sp != 0 && (*sp & NS_CMPRSFLGS) == 0 &&
9561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		       (sp - msg) < 0x4000) {
9571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			dn = domain;
9581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			cp = sp;
9591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			while ((n = *cp++) != 0) {
9601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				/*
9611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				 * check for indirection
9621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				 */
9631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				switch (n & NS_CMPRSFLGS) {
9641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				case 0:		/* normal case, n == len */
9651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					n = labellen(cp - 1); /* XXX */
9661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					if (n != *dn++)
9681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project						goto next;
9691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					for (; n > 0; n--)
9711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project						if (mklower(*dn++) !=
9721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project						    mklower(*cp++))
9731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project							goto next;
9741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					/* Is next root for both ? */
975fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle					if (*dn == '\0' && *cp == '\0') {
976fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle						_DIAGASSERT(__type_fit(int,
977fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle						    sp - msg));
978fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle						return (int)(sp - msg);
979fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle					}
9801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					if (*dn)
9811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project						continue;
9821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					goto next;
9831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				case NS_CMPRSFLGS:	/* indirection */
9841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					cp = msg + (((n & 0x3f) << 8) | *cp);
9851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					break;
9861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				default:	/* illegal type */
9881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					errno = EMSGSIZE;
9891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					return (-1);
9901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
9911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
9921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project next: ;
9931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			sp += *sp + 1;
9941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
9951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
9961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	errno = ENOENT;
9971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (-1);
9981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
9991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
10001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int
10011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdecode_bitstring(const unsigned char **cpp, char *dn, const char *eom)
10021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
10031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const unsigned char *cp = *cpp;
10041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	char *beg = dn, tc;
10051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int b, blen, plen, i;
10061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
10071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if ((blen = (*cp & 0xff)) == 0)
10081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		blen = 256;
10091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	plen = (blen + 3) / 4;
1010fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	plen += (int)sizeof("\\[x/]") + (blen > 99 ? 3 : (blen > 9) ? 2 : 1);
10111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (dn + plen >= eom)
10121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return(-1);
10131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
10141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	cp++;
10151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	i = SPRINTF((dn, "\\[x"));
10161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (i < 0)
10171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (-1);
10181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	dn += i;
10191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	for (b = blen; b > 7; b -= 8, cp++) {
10201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		i = SPRINTF((dn, "%02x", *cp & 0xff));
10211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (i < 0)
10221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
10231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		dn += i;
10241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
10251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (b > 4) {
10261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		tc = *cp++;
10271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		i = SPRINTF((dn, "%02x", tc & (0xff << (8 - b))));
10281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (i < 0)
10291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
10301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		dn += i;
10311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	} else if (b > 0) {
10321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		tc = *cp++;
10331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		i = SPRINTF((dn, "%1x",
10341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			       (((u_int32_t)tc >> 4) & 0x0f) & (0x0f << (4 - b))));
10351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (i < 0)
10361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
10371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		dn += i;
10381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
10391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	i = SPRINTF((dn, "/%d]", blen));
10401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (i < 0)
10411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (-1);
10421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	dn += i;
10431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
10441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	*cpp = cp;
1045fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	_DIAGASSERT(__type_fit(int, dn - beg));
1046fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle	return (int)(dn - beg);
10471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
10481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
10491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int
10501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectencode_bitsring(const char **bp, const char *end, unsigned char **labelp,
10511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	        unsigned char ** dst, unsigned const char *eom)
10521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
10531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int afterslash = 0;
10541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const char *cp = *bp;
10551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	unsigned char *tp;
10561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	char c;
10571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const char *beg_blen;
10581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	char *end_blen = NULL;
10591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int value = 0, count = 0, tbcount = 0, blen = 0;
10601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
10611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	beg_blen = end_blen = NULL;
10621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
10631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/* a bitstring must contain at least 2 characters */
10641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (end - cp < 2)
10651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return(EINVAL);
10661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
10671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/* XXX: currently, only hex strings are supported */
10681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (*cp++ != 'x')
10691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return(EINVAL);
10701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (!isxdigit((*cp) & 0xff)) /* reject '\[x/BLEN]' */
10711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return(EINVAL);
10721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
10731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	for (tp = *dst + 1; cp < end && tp < eom; cp++) {
10741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		switch((c = *cp)) {
10751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case ']':	/* end of the bitstring */
10761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (afterslash) {
10771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (beg_blen == NULL)
10781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					return(EINVAL);
10791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				blen = (int)strtol(beg_blen, &end_blen, 10);
10801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (*end_blen != ']')
10811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					return(EINVAL);
10821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
10831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (count)
10841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				*tp++ = ((value << 4) & 0xff);
10851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			cp++;	/* skip ']' */
10861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto done;
10871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case '/':
10881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			afterslash = 1;
10891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
10901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		default:
10911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (afterslash) {
10921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (!isdigit(c&0xff))
10931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					return(EINVAL);
10941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (beg_blen == NULL) {
10951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
10961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					if (c == '0') {
10971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project						/* blen never begings with 0 */
10981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project						return(EINVAL);
10991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					}
11001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					beg_blen = cp;
11011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
11021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			} else {
11031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (!isxdigit(c&0xff))
11041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					return(EINVAL);
11051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				value <<= 4;
11061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				value += digitvalue[(int)c];
11071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				count += 4;
11081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				tbcount += 4;
11091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (tbcount > 256)
11101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					return(EINVAL);
11111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (count == 8) {
11121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					*tp++ = value;
11131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					count = 0;
11141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
11151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
11161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
11171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
11181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
11191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project  done:
11201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (cp >= end || tp >= eom)
11211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return(EMSGSIZE);
11221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
11231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/*
11241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * bit length validation:
11251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * If a <length> is present, the number of digits in the <bit-data>
11261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * MUST be just sufficient to contain the number of bits specified
11271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * by the <length>. If there are insignificant bits in a final
11281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * hexadecimal or octal digit, they MUST be zero.
11291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * RFC 2673, Section 3.2.
11301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 */
11311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (blen > 0) {
11321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		int traillen;
11331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
11341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (((blen + 3) & ~3) != tbcount)
11351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return(EINVAL);
11361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		traillen = tbcount - blen; /* between 0 and 3 */
11371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (((value << (8 - traillen)) & 0xff) != 0)
11381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return(EINVAL);
11391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
11401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	else
11411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		blen = tbcount;
11421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (blen == 256)
11431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		blen = 0;
11441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
11451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/* encode the type and the significant bit fields */
11461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	**labelp = DNS_LABELTYPE_BITSTRING;
11471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	**dst = blen;
11481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
11491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	*bp = cp;
11501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	*dst = tp;
11511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
11521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return(0);
11531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
11541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
11551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int
11561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectlabellen(const u_char *lp)
11571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
11581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int bitlen;
11591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	u_char l = *lp;
11601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
11611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if ((l & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
11621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/* should be avoided by the caller */
11631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return(-1);
11641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
11651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
11661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if ((l & NS_CMPRSFLGS) == NS_TYPE_ELT) {
11671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (l == DNS_LABELTYPE_BITSTRING) {
11681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if ((bitlen = *(lp + 1)) == 0)
11691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				bitlen = 256;
11701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return((bitlen + 7 ) / 8 + 1);
11711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
11721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return(-1);	/* unknwon ELT */
11731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
11741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return(l);
11751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
1176