xref: /aosp_15_r20/bionic/libc/dns/nameser/ns_name.c (revision 8d67ca893c1523eb926b9080dbe4e2ffd2a27ba1)
1*8d67ca89SAndroid Build Coastguard Worker /*	$NetBSD: ns_name.c,v 1.9 2012/03/13 21:13:39 christos Exp $	*/
2*8d67ca89SAndroid Build Coastguard Worker 
3*8d67ca89SAndroid Build Coastguard Worker /*
4*8d67ca89SAndroid Build Coastguard Worker  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
5*8d67ca89SAndroid Build Coastguard Worker  * Copyright (c) 1996,1999 by Internet Software Consortium.
6*8d67ca89SAndroid Build Coastguard Worker  *
7*8d67ca89SAndroid Build Coastguard Worker  * Permission to use, copy, modify, and distribute this software for any
8*8d67ca89SAndroid Build Coastguard Worker  * purpose with or without fee is hereby granted, provided that the above
9*8d67ca89SAndroid Build Coastguard Worker  * copyright notice and this permission notice appear in all copies.
10*8d67ca89SAndroid Build Coastguard Worker  *
11*8d67ca89SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
12*8d67ca89SAndroid Build Coastguard Worker  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13*8d67ca89SAndroid Build Coastguard Worker  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
14*8d67ca89SAndroid Build Coastguard Worker  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15*8d67ca89SAndroid Build Coastguard Worker  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16*8d67ca89SAndroid Build Coastguard Worker  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
17*8d67ca89SAndroid Build Coastguard Worker  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18*8d67ca89SAndroid Build Coastguard Worker  */
19*8d67ca89SAndroid Build Coastguard Worker 
20*8d67ca89SAndroid Build Coastguard Worker #include <sys/cdefs.h>
21*8d67ca89SAndroid Build Coastguard Worker #ifndef lint
22*8d67ca89SAndroid Build Coastguard Worker #ifdef notdef
23*8d67ca89SAndroid Build Coastguard Worker static const char rcsid[] = "Id: ns_name.c,v 1.11 2009/01/23 19:59:16 each Exp";
24*8d67ca89SAndroid Build Coastguard Worker #else
25*8d67ca89SAndroid Build Coastguard Worker __RCSID("$NetBSD: ns_name.c,v 1.9 2012/03/13 21:13:39 christos Exp $");
26*8d67ca89SAndroid Build Coastguard Worker #endif
27*8d67ca89SAndroid Build Coastguard Worker #endif
28*8d67ca89SAndroid Build Coastguard Worker 
29*8d67ca89SAndroid Build Coastguard Worker #include <sys/types.h>
30*8d67ca89SAndroid Build Coastguard Worker 
31*8d67ca89SAndroid Build Coastguard Worker #include <netinet/in.h>
32*8d67ca89SAndroid Build Coastguard Worker #include <arpa/nameser.h>
33*8d67ca89SAndroid Build Coastguard Worker 
34*8d67ca89SAndroid Build Coastguard Worker #include <assert.h>
35*8d67ca89SAndroid Build Coastguard Worker #include <errno.h>
36*8d67ca89SAndroid Build Coastguard Worker #ifdef ANDROID_CHANGES
37*8d67ca89SAndroid Build Coastguard Worker #include "resolv_private.h"
38*8d67ca89SAndroid Build Coastguard Worker #else
39*8d67ca89SAndroid Build Coastguard Worker #include <resolv.h>
40*8d67ca89SAndroid Build Coastguard Worker #endif
41*8d67ca89SAndroid Build Coastguard Worker #include <string.h>
42*8d67ca89SAndroid Build Coastguard Worker #include <ctype.h>
43*8d67ca89SAndroid Build Coastguard Worker #include <stdlib.h>
44*8d67ca89SAndroid Build Coastguard Worker #include <limits.h>
45*8d67ca89SAndroid Build Coastguard Worker 
46*8d67ca89SAndroid Build Coastguard Worker #define NS_TYPE_ELT			0x40 /* EDNS0 extended label type */
47*8d67ca89SAndroid Build Coastguard Worker #define DNS_LABELTYPE_BITSTRING		0x41
48*8d67ca89SAndroid Build Coastguard Worker 
49*8d67ca89SAndroid Build Coastguard Worker /* Data. */
50*8d67ca89SAndroid Build Coastguard Worker 
51*8d67ca89SAndroid Build Coastguard Worker static const char	digits[] = "0123456789";
52*8d67ca89SAndroid Build Coastguard Worker 
53*8d67ca89SAndroid Build Coastguard Worker static const char digitvalue[256] = {
54*8d67ca89SAndroid Build Coastguard Worker 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,	/*16*/
55*8d67ca89SAndroid Build Coastguard Worker 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/
56*8d67ca89SAndroid Build Coastguard Worker 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/
57*8d67ca89SAndroid Build Coastguard Worker 	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1, /*64*/
58*8d67ca89SAndroid Build Coastguard Worker 	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/
59*8d67ca89SAndroid Build Coastguard Worker 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/
60*8d67ca89SAndroid Build Coastguard Worker 	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/
61*8d67ca89SAndroid Build Coastguard Worker 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/
62*8d67ca89SAndroid Build Coastguard Worker 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
63*8d67ca89SAndroid Build Coastguard Worker 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
64*8d67ca89SAndroid Build Coastguard Worker 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
65*8d67ca89SAndroid Build Coastguard Worker 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
66*8d67ca89SAndroid Build Coastguard Worker 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
67*8d67ca89SAndroid Build Coastguard Worker 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
68*8d67ca89SAndroid Build Coastguard Worker 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
69*8d67ca89SAndroid Build Coastguard Worker 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/
70*8d67ca89SAndroid Build Coastguard Worker };
71*8d67ca89SAndroid Build Coastguard Worker 
72*8d67ca89SAndroid Build Coastguard Worker /* Forward. */
73*8d67ca89SAndroid Build Coastguard Worker 
74*8d67ca89SAndroid Build Coastguard Worker static int		special(int);
75*8d67ca89SAndroid Build Coastguard Worker static int		printable(int);
76*8d67ca89SAndroid Build Coastguard Worker static int		dn_find(const u_char *, const u_char *,
77*8d67ca89SAndroid Build Coastguard Worker 				const u_char * const *,
78*8d67ca89SAndroid Build Coastguard Worker 				const u_char * const *);
79*8d67ca89SAndroid Build Coastguard Worker static int		encode_bitsring(const char **, const char *,
80*8d67ca89SAndroid Build Coastguard Worker 					unsigned char **, unsigned char **,
81*8d67ca89SAndroid Build Coastguard Worker 					unsigned const char *);
82*8d67ca89SAndroid Build Coastguard Worker static int		labellen(const u_char *);
83*8d67ca89SAndroid Build Coastguard Worker static int		decode_bitstring(const unsigned char **,
84*8d67ca89SAndroid Build Coastguard Worker 					 char *, const char *);
85*8d67ca89SAndroid Build Coastguard Worker 
86*8d67ca89SAndroid Build Coastguard Worker /* Public. */
87*8d67ca89SAndroid Build Coastguard Worker 
88*8d67ca89SAndroid Build Coastguard Worker /*
89*8d67ca89SAndroid Build Coastguard Worker  *	Convert an encoded domain name to printable ascii as per RFC1035.
90*8d67ca89SAndroid Build Coastguard Worker  * return:
91*8d67ca89SAndroid Build Coastguard Worker  *	Number of bytes written to buffer, or -1 (with errno set)
92*8d67ca89SAndroid Build Coastguard Worker  *
93*8d67ca89SAndroid Build Coastguard Worker  * notes:
94*8d67ca89SAndroid Build Coastguard Worker  *	The root is returned as "."
95*8d67ca89SAndroid Build Coastguard Worker  *	All other domains are returned in non absolute form
96*8d67ca89SAndroid Build Coastguard Worker  */
97*8d67ca89SAndroid Build Coastguard Worker int
ns_name_ntop(const u_char * src,char * dst,size_t dstsiz)98*8d67ca89SAndroid Build Coastguard Worker ns_name_ntop(const u_char *src, char *dst, size_t dstsiz)
99*8d67ca89SAndroid Build Coastguard Worker {
100*8d67ca89SAndroid Build Coastguard Worker 	const u_char *cp;
101*8d67ca89SAndroid Build Coastguard Worker 	char *dn, *eom;
102*8d67ca89SAndroid Build Coastguard Worker 	u_char c;
103*8d67ca89SAndroid Build Coastguard Worker 	u_int n;
104*8d67ca89SAndroid Build Coastguard Worker 	int l;
105*8d67ca89SAndroid Build Coastguard Worker 
106*8d67ca89SAndroid Build Coastguard Worker 	cp = src;
107*8d67ca89SAndroid Build Coastguard Worker 	dn = dst;
108*8d67ca89SAndroid Build Coastguard Worker 	eom = dst + dstsiz;
109*8d67ca89SAndroid Build Coastguard Worker 
110*8d67ca89SAndroid Build Coastguard Worker 	while ((n = *cp++) != 0) {
111*8d67ca89SAndroid Build Coastguard Worker 		if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
112*8d67ca89SAndroid Build Coastguard Worker 			/* Some kind of compression pointer. */
113*8d67ca89SAndroid Build Coastguard Worker 			errno = EMSGSIZE;
114*8d67ca89SAndroid Build Coastguard Worker 			return (-1);
115*8d67ca89SAndroid Build Coastguard Worker 		}
116*8d67ca89SAndroid Build Coastguard Worker 		if (dn != dst) {
117*8d67ca89SAndroid Build Coastguard Worker 			if (dn >= eom) {
118*8d67ca89SAndroid Build Coastguard Worker 				errno = EMSGSIZE;
119*8d67ca89SAndroid Build Coastguard Worker 				return (-1);
120*8d67ca89SAndroid Build Coastguard Worker 			}
121*8d67ca89SAndroid Build Coastguard Worker 			*dn++ = '.';
122*8d67ca89SAndroid Build Coastguard Worker 		}
123*8d67ca89SAndroid Build Coastguard Worker 		if ((l = labellen(cp - 1)) < 0) {
124*8d67ca89SAndroid Build Coastguard Worker 			errno = EMSGSIZE; /* XXX */
125*8d67ca89SAndroid Build Coastguard Worker 			return(-1);
126*8d67ca89SAndroid Build Coastguard Worker 		}
127*8d67ca89SAndroid Build Coastguard Worker 		if (dn + l >= eom) {
128*8d67ca89SAndroid Build Coastguard Worker 			errno = EMSGSIZE;
129*8d67ca89SAndroid Build Coastguard Worker 			return (-1);
130*8d67ca89SAndroid Build Coastguard Worker 		}
131*8d67ca89SAndroid Build Coastguard Worker 		if ((n & NS_CMPRSFLGS) == NS_TYPE_ELT) {
132*8d67ca89SAndroid Build Coastguard Worker 			int m;
133*8d67ca89SAndroid Build Coastguard Worker 
134*8d67ca89SAndroid Build Coastguard Worker 			if (n != DNS_LABELTYPE_BITSTRING) {
135*8d67ca89SAndroid Build Coastguard Worker 				/* XXX: labellen should reject this case */
136*8d67ca89SAndroid Build Coastguard Worker 				errno = EINVAL;
137*8d67ca89SAndroid Build Coastguard Worker 				return(-1);
138*8d67ca89SAndroid Build Coastguard Worker 			}
139*8d67ca89SAndroid Build Coastguard Worker 			if ((m = decode_bitstring(&cp, dn, eom)) < 0)
140*8d67ca89SAndroid Build Coastguard Worker 			{
141*8d67ca89SAndroid Build Coastguard Worker 				errno = EMSGSIZE;
142*8d67ca89SAndroid Build Coastguard Worker 				return(-1);
143*8d67ca89SAndroid Build Coastguard Worker 			}
144*8d67ca89SAndroid Build Coastguard Worker 			dn += m;
145*8d67ca89SAndroid Build Coastguard Worker 			continue;
146*8d67ca89SAndroid Build Coastguard Worker 		}
147*8d67ca89SAndroid Build Coastguard Worker 		for (; l > 0; l--) {
148*8d67ca89SAndroid Build Coastguard Worker 			c = *cp++;
149*8d67ca89SAndroid Build Coastguard Worker 			if (special(c)) {
150*8d67ca89SAndroid Build Coastguard Worker 				if (dn + 1 >= eom) {
151*8d67ca89SAndroid Build Coastguard Worker 					errno = EMSGSIZE;
152*8d67ca89SAndroid Build Coastguard Worker 					return (-1);
153*8d67ca89SAndroid Build Coastguard Worker 				}
154*8d67ca89SAndroid Build Coastguard Worker 				*dn++ = '\\';
155*8d67ca89SAndroid Build Coastguard Worker 				*dn++ = (char)c;
156*8d67ca89SAndroid Build Coastguard Worker 			} else if (!printable(c)) {
157*8d67ca89SAndroid Build Coastguard Worker 				if (dn + 3 >= eom) {
158*8d67ca89SAndroid Build Coastguard Worker 					errno = EMSGSIZE;
159*8d67ca89SAndroid Build Coastguard Worker 					return (-1);
160*8d67ca89SAndroid Build Coastguard Worker 				}
161*8d67ca89SAndroid Build Coastguard Worker 				*dn++ = '\\';
162*8d67ca89SAndroid Build Coastguard Worker 				*dn++ = digits[c / 100];
163*8d67ca89SAndroid Build Coastguard Worker 				*dn++ = digits[(c % 100) / 10];
164*8d67ca89SAndroid Build Coastguard Worker 				*dn++ = digits[c % 10];
165*8d67ca89SAndroid Build Coastguard Worker 			} else {
166*8d67ca89SAndroid Build Coastguard Worker 				if (dn >= eom) {
167*8d67ca89SAndroid Build Coastguard Worker 					errno = EMSGSIZE;
168*8d67ca89SAndroid Build Coastguard Worker 					return (-1);
169*8d67ca89SAndroid Build Coastguard Worker 				}
170*8d67ca89SAndroid Build Coastguard Worker 				*dn++ = (char)c;
171*8d67ca89SAndroid Build Coastguard Worker 			}
172*8d67ca89SAndroid Build Coastguard Worker 		}
173*8d67ca89SAndroid Build Coastguard Worker 	}
174*8d67ca89SAndroid Build Coastguard Worker 	if (dn == dst) {
175*8d67ca89SAndroid Build Coastguard Worker 		if (dn >= eom) {
176*8d67ca89SAndroid Build Coastguard Worker 			errno = EMSGSIZE;
177*8d67ca89SAndroid Build Coastguard Worker 			return (-1);
178*8d67ca89SAndroid Build Coastguard Worker 		}
179*8d67ca89SAndroid Build Coastguard Worker 		*dn++ = '.';
180*8d67ca89SAndroid Build Coastguard Worker 	}
181*8d67ca89SAndroid Build Coastguard Worker 	if (dn >= eom) {
182*8d67ca89SAndroid Build Coastguard Worker 		errno = EMSGSIZE;
183*8d67ca89SAndroid Build Coastguard Worker 		return (-1);
184*8d67ca89SAndroid Build Coastguard Worker 	}
185*8d67ca89SAndroid Build Coastguard Worker 	*dn++ = '\0';
186*8d67ca89SAndroid Build Coastguard Worker 	_DIAGASSERT(__type_fit(int, dn - dst));
187*8d67ca89SAndroid Build Coastguard Worker 	return (int)(dn - dst);
188*8d67ca89SAndroid Build Coastguard Worker }
189*8d67ca89SAndroid Build Coastguard Worker 
190*8d67ca89SAndroid Build Coastguard Worker /*
191*8d67ca89SAndroid Build Coastguard Worker  *	Convert a ascii string into an encoded domain name as per RFC1035.
192*8d67ca89SAndroid Build Coastguard Worker  *
193*8d67ca89SAndroid Build Coastguard Worker  * return:
194*8d67ca89SAndroid Build Coastguard Worker  *
195*8d67ca89SAndroid Build Coastguard Worker  *	-1 if it fails
196*8d67ca89SAndroid Build Coastguard Worker  *	1 if string was fully qualified
197*8d67ca89SAndroid Build Coastguard Worker  *	0 is string was not fully qualified
198*8d67ca89SAndroid Build Coastguard Worker  *
199*8d67ca89SAndroid Build Coastguard Worker  * notes:
200*8d67ca89SAndroid Build Coastguard Worker  *	Enforces label and domain length limits.
201*8d67ca89SAndroid Build Coastguard Worker  */
202*8d67ca89SAndroid Build Coastguard Worker int
ns_name_pton(const char * src,u_char * dst,size_t dstsiz)203*8d67ca89SAndroid Build Coastguard Worker ns_name_pton(const char *src, u_char *dst, size_t dstsiz) {
204*8d67ca89SAndroid Build Coastguard Worker 	return (ns_name_pton2(src, dst, dstsiz, NULL));
205*8d67ca89SAndroid Build Coastguard Worker }
206*8d67ca89SAndroid Build Coastguard Worker 
207*8d67ca89SAndroid Build Coastguard Worker /*
208*8d67ca89SAndroid Build Coastguard Worker  * ns_name_pton2(src, dst, dstsiz, *dstlen)
209*8d67ca89SAndroid Build Coastguard Worker  *	Convert a ascii string into an encoded domain name as per RFC1035.
210*8d67ca89SAndroid Build Coastguard Worker  * return:
211*8d67ca89SAndroid Build Coastguard Worker  *	-1 if it fails
212*8d67ca89SAndroid Build Coastguard Worker  *	1 if string was fully qualified
213*8d67ca89SAndroid Build Coastguard Worker  *	0 is string was not fully qualified
214*8d67ca89SAndroid Build Coastguard Worker  * side effects:
215*8d67ca89SAndroid Build Coastguard Worker  *	fills in *dstlen (if non-NULL)
216*8d67ca89SAndroid Build Coastguard Worker  * notes:
217*8d67ca89SAndroid Build Coastguard Worker  *	Enforces label and domain length limits.
218*8d67ca89SAndroid Build Coastguard Worker  */
219*8d67ca89SAndroid Build Coastguard Worker 
220*8d67ca89SAndroid Build Coastguard Worker int
ns_name_pton2(const char * src,u_char * dst,size_t dstsiz,size_t * dstlen)221*8d67ca89SAndroid Build Coastguard Worker ns_name_pton2(const char *src, u_char *dst, size_t dstsiz, size_t *dstlen) {
222*8d67ca89SAndroid Build Coastguard Worker 	u_char *label, *bp, *eom;
223*8d67ca89SAndroid Build Coastguard Worker 	int c, n, escaped, e = 0;
224*8d67ca89SAndroid Build Coastguard Worker 	char *cp;
225*8d67ca89SAndroid Build Coastguard Worker 
226*8d67ca89SAndroid Build Coastguard Worker 	escaped = 0;
227*8d67ca89SAndroid Build Coastguard Worker 	bp = dst;
228*8d67ca89SAndroid Build Coastguard Worker 	eom = dst + dstsiz;
229*8d67ca89SAndroid Build Coastguard Worker 	label = bp++;
230*8d67ca89SAndroid Build Coastguard Worker 
231*8d67ca89SAndroid Build Coastguard Worker 	while ((c = *src++) != 0) {
232*8d67ca89SAndroid Build Coastguard Worker 		if (escaped) {
233*8d67ca89SAndroid Build Coastguard Worker 			if (c == '[') { /* start a bit string label */
234*8d67ca89SAndroid Build Coastguard Worker 				if ((cp = strchr(src, ']')) == NULL) {
235*8d67ca89SAndroid Build Coastguard Worker 					errno = EINVAL; /* ??? */
236*8d67ca89SAndroid Build Coastguard Worker 					return(-1);
237*8d67ca89SAndroid Build Coastguard Worker 				}
238*8d67ca89SAndroid Build Coastguard Worker 				if ((e = encode_bitsring(&src, cp + 2,
239*8d67ca89SAndroid Build Coastguard Worker 							 &label, &bp, eom))
240*8d67ca89SAndroid Build Coastguard Worker 				    != 0) {
241*8d67ca89SAndroid Build Coastguard Worker 					errno = e;
242*8d67ca89SAndroid Build Coastguard Worker 					return(-1);
243*8d67ca89SAndroid Build Coastguard Worker 				}
244*8d67ca89SAndroid Build Coastguard Worker 				escaped = 0;
245*8d67ca89SAndroid Build Coastguard Worker 				label = bp++;
246*8d67ca89SAndroid Build Coastguard Worker 				if ((c = *src++) == 0)
247*8d67ca89SAndroid Build Coastguard Worker 					goto done;
248*8d67ca89SAndroid Build Coastguard Worker 				else if (c != '.') {
249*8d67ca89SAndroid Build Coastguard Worker 					errno = EINVAL;
250*8d67ca89SAndroid Build Coastguard Worker 					return(-1);
251*8d67ca89SAndroid Build Coastguard Worker 				}
252*8d67ca89SAndroid Build Coastguard Worker 				continue;
253*8d67ca89SAndroid Build Coastguard Worker 			}
254*8d67ca89SAndroid Build Coastguard Worker 			else if ((cp = strchr(digits, c)) != NULL) {
255*8d67ca89SAndroid Build Coastguard Worker 				n = (int)(cp - digits) * 100;
256*8d67ca89SAndroid Build Coastguard Worker 				if ((c = *src++) == 0 ||
257*8d67ca89SAndroid Build Coastguard Worker 				    (cp = strchr(digits, c)) == NULL) {
258*8d67ca89SAndroid Build Coastguard Worker 					errno = EMSGSIZE;
259*8d67ca89SAndroid Build Coastguard Worker 					return (-1);
260*8d67ca89SAndroid Build Coastguard Worker 				}
261*8d67ca89SAndroid Build Coastguard Worker 				n += (int)(cp - digits) * 10;
262*8d67ca89SAndroid Build Coastguard Worker 				if ((c = *src++) == 0 ||
263*8d67ca89SAndroid Build Coastguard Worker 				    (cp = strchr(digits, c)) == NULL) {
264*8d67ca89SAndroid Build Coastguard Worker 					errno = EMSGSIZE;
265*8d67ca89SAndroid Build Coastguard Worker 					return (-1);
266*8d67ca89SAndroid Build Coastguard Worker 				}
267*8d67ca89SAndroid Build Coastguard Worker 				n += (int)(cp - digits);
268*8d67ca89SAndroid Build Coastguard Worker 				if (n > 255) {
269*8d67ca89SAndroid Build Coastguard Worker 					errno = EMSGSIZE;
270*8d67ca89SAndroid Build Coastguard Worker 					return (-1);
271*8d67ca89SAndroid Build Coastguard Worker 				}
272*8d67ca89SAndroid Build Coastguard Worker 				c = n;
273*8d67ca89SAndroid Build Coastguard Worker 			}
274*8d67ca89SAndroid Build Coastguard Worker 			escaped = 0;
275*8d67ca89SAndroid Build Coastguard Worker 		} else if (c == '\\') {
276*8d67ca89SAndroid Build Coastguard Worker 			escaped = 1;
277*8d67ca89SAndroid Build Coastguard Worker 			continue;
278*8d67ca89SAndroid Build Coastguard Worker 		} else if (c == '.') {
279*8d67ca89SAndroid Build Coastguard Worker 			c = (int)(bp - label - 1);
280*8d67ca89SAndroid Build Coastguard Worker 			if ((c & NS_CMPRSFLGS) != 0) {	/* Label too big. */
281*8d67ca89SAndroid Build Coastguard Worker 				errno = EMSGSIZE;
282*8d67ca89SAndroid Build Coastguard Worker 				return (-1);
283*8d67ca89SAndroid Build Coastguard Worker 			}
284*8d67ca89SAndroid Build Coastguard Worker 			if (label >= eom) {
285*8d67ca89SAndroid Build Coastguard Worker 				errno = EMSGSIZE;
286*8d67ca89SAndroid Build Coastguard Worker 				return (-1);
287*8d67ca89SAndroid Build Coastguard Worker 			}
288*8d67ca89SAndroid Build Coastguard Worker 			*label = c;
289*8d67ca89SAndroid Build Coastguard Worker 			/* Fully qualified ? */
290*8d67ca89SAndroid Build Coastguard Worker 			if (*src == '\0') {
291*8d67ca89SAndroid Build Coastguard Worker 				if (c != 0) {
292*8d67ca89SAndroid Build Coastguard Worker 					if (bp >= eom) {
293*8d67ca89SAndroid Build Coastguard Worker 						errno = EMSGSIZE;
294*8d67ca89SAndroid Build Coastguard Worker 						return (-1);
295*8d67ca89SAndroid Build Coastguard Worker 					}
296*8d67ca89SAndroid Build Coastguard Worker 					*bp++ = '\0';
297*8d67ca89SAndroid Build Coastguard Worker 				}
298*8d67ca89SAndroid Build Coastguard Worker 				if ((bp - dst) > MAXCDNAME) {
299*8d67ca89SAndroid Build Coastguard Worker 					errno = EMSGSIZE;
300*8d67ca89SAndroid Build Coastguard Worker 					return (-1);
301*8d67ca89SAndroid Build Coastguard Worker 				}
302*8d67ca89SAndroid Build Coastguard Worker 				if (dstlen != NULL)
303*8d67ca89SAndroid Build Coastguard Worker 					*dstlen = (bp - dst);
304*8d67ca89SAndroid Build Coastguard Worker 				return (1);
305*8d67ca89SAndroid Build Coastguard Worker 			}
306*8d67ca89SAndroid Build Coastguard Worker 			if (c == 0 || *src == '.') {
307*8d67ca89SAndroid Build Coastguard Worker 				errno = EMSGSIZE;
308*8d67ca89SAndroid Build Coastguard Worker 				return (-1);
309*8d67ca89SAndroid Build Coastguard Worker 			}
310*8d67ca89SAndroid Build Coastguard Worker 			label = bp++;
311*8d67ca89SAndroid Build Coastguard Worker 			continue;
312*8d67ca89SAndroid Build Coastguard Worker 		}
313*8d67ca89SAndroid Build Coastguard Worker 		if (bp >= eom) {
314*8d67ca89SAndroid Build Coastguard Worker 			errno = EMSGSIZE;
315*8d67ca89SAndroid Build Coastguard Worker 			return (-1);
316*8d67ca89SAndroid Build Coastguard Worker 		}
317*8d67ca89SAndroid Build Coastguard Worker 		*bp++ = (u_char)c;
318*8d67ca89SAndroid Build Coastguard Worker 	}
319*8d67ca89SAndroid Build Coastguard Worker 	c = (int)(bp - label - 1);
320*8d67ca89SAndroid Build Coastguard Worker 	if ((c & NS_CMPRSFLGS) != 0) {		/* Label too big. */
321*8d67ca89SAndroid Build Coastguard Worker 		errno = EMSGSIZE;
322*8d67ca89SAndroid Build Coastguard Worker 		return (-1);
323*8d67ca89SAndroid Build Coastguard Worker 	}
324*8d67ca89SAndroid Build Coastguard Worker   done:
325*8d67ca89SAndroid Build Coastguard Worker 	if (label >= eom) {
326*8d67ca89SAndroid Build Coastguard Worker 		errno = EMSGSIZE;
327*8d67ca89SAndroid Build Coastguard Worker 		return (-1);
328*8d67ca89SAndroid Build Coastguard Worker 	}
329*8d67ca89SAndroid Build Coastguard Worker 	*label = c;
330*8d67ca89SAndroid Build Coastguard Worker 	if (c != 0) {
331*8d67ca89SAndroid Build Coastguard Worker 		if (bp >= eom) {
332*8d67ca89SAndroid Build Coastguard Worker 			errno = EMSGSIZE;
333*8d67ca89SAndroid Build Coastguard Worker 			return (-1);
334*8d67ca89SAndroid Build Coastguard Worker 		}
335*8d67ca89SAndroid Build Coastguard Worker 		*bp++ = 0;
336*8d67ca89SAndroid Build Coastguard Worker 	}
337*8d67ca89SAndroid Build Coastguard Worker 	if ((bp - dst) > MAXCDNAME) {	/* src too big */
338*8d67ca89SAndroid Build Coastguard Worker 		errno = EMSGSIZE;
339*8d67ca89SAndroid Build Coastguard Worker 		return (-1);
340*8d67ca89SAndroid Build Coastguard Worker 	}
341*8d67ca89SAndroid Build Coastguard Worker 	if (dstlen != NULL)
342*8d67ca89SAndroid Build Coastguard Worker 		*dstlen = (bp - dst);
343*8d67ca89SAndroid Build Coastguard Worker 	return (0);
344*8d67ca89SAndroid Build Coastguard Worker }
345*8d67ca89SAndroid Build Coastguard Worker 
346*8d67ca89SAndroid Build Coastguard Worker /*
347*8d67ca89SAndroid Build Coastguard Worker  *	Convert a network strings labels into all lowercase.
348*8d67ca89SAndroid Build Coastguard Worker  *
349*8d67ca89SAndroid Build Coastguard Worker  * return:
350*8d67ca89SAndroid Build Coastguard Worker  *	Number of bytes written to buffer, or -1 (with errno set)
351*8d67ca89SAndroid Build Coastguard Worker  *
352*8d67ca89SAndroid Build Coastguard Worker  * notes:
353*8d67ca89SAndroid Build Coastguard Worker  *	Enforces label and domain length limits.
354*8d67ca89SAndroid Build Coastguard Worker  */
355*8d67ca89SAndroid Build Coastguard Worker 
356*8d67ca89SAndroid Build Coastguard Worker int
ns_name_ntol(const u_char * src,u_char * dst,size_t dstsiz)357*8d67ca89SAndroid Build Coastguard Worker ns_name_ntol(const u_char *src, u_char *dst, size_t dstsiz)
358*8d67ca89SAndroid Build Coastguard Worker {
359*8d67ca89SAndroid Build Coastguard Worker 	const u_char *cp;
360*8d67ca89SAndroid Build Coastguard Worker 	u_char *dn, *eom;
361*8d67ca89SAndroid Build Coastguard Worker 	u_char c;
362*8d67ca89SAndroid Build Coastguard Worker 	u_int n;
363*8d67ca89SAndroid Build Coastguard Worker 	int l;
364*8d67ca89SAndroid Build Coastguard Worker 
365*8d67ca89SAndroid Build Coastguard Worker 	cp = src;
366*8d67ca89SAndroid Build Coastguard Worker 	dn = dst;
367*8d67ca89SAndroid Build Coastguard Worker 	eom = dst + dstsiz;
368*8d67ca89SAndroid Build Coastguard Worker 
369*8d67ca89SAndroid Build Coastguard Worker 	if (dn >= eom) {
370*8d67ca89SAndroid Build Coastguard Worker 		errno = EMSGSIZE;
371*8d67ca89SAndroid Build Coastguard Worker 		return (-1);
372*8d67ca89SAndroid Build Coastguard Worker 	}
373*8d67ca89SAndroid Build Coastguard Worker 	while ((n = *cp++) != 0) {
374*8d67ca89SAndroid Build Coastguard Worker 		if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
375*8d67ca89SAndroid Build Coastguard Worker 			/* Some kind of compression pointer. */
376*8d67ca89SAndroid Build Coastguard Worker 			errno = EMSGSIZE;
377*8d67ca89SAndroid Build Coastguard Worker 			return (-1);
378*8d67ca89SAndroid Build Coastguard Worker 		}
379*8d67ca89SAndroid Build Coastguard Worker 		*dn++ = n;
380*8d67ca89SAndroid Build Coastguard Worker 		if ((l = labellen(cp - 1)) < 0) {
381*8d67ca89SAndroid Build Coastguard Worker 			errno = EMSGSIZE;
382*8d67ca89SAndroid Build Coastguard Worker 			return (-1);
383*8d67ca89SAndroid Build Coastguard Worker 		}
384*8d67ca89SAndroid Build Coastguard Worker 		if (dn + l >= eom) {
385*8d67ca89SAndroid Build Coastguard Worker 			errno = EMSGSIZE;
386*8d67ca89SAndroid Build Coastguard Worker 			return (-1);
387*8d67ca89SAndroid Build Coastguard Worker 		}
388*8d67ca89SAndroid Build Coastguard Worker 		for (; l > 0; l--) {
389*8d67ca89SAndroid Build Coastguard Worker 			c = *cp++;
390*8d67ca89SAndroid Build Coastguard Worker 			if (isascii(c) && isupper(c))
391*8d67ca89SAndroid Build Coastguard Worker 				*dn++ = tolower(c);
392*8d67ca89SAndroid Build Coastguard Worker 			else
393*8d67ca89SAndroid Build Coastguard Worker 				*dn++ = c;
394*8d67ca89SAndroid Build Coastguard Worker 		}
395*8d67ca89SAndroid Build Coastguard Worker 	}
396*8d67ca89SAndroid Build Coastguard Worker 	*dn++ = '\0';
397*8d67ca89SAndroid Build Coastguard Worker 	_DIAGASSERT(__type_fit(int, dn - dst));
398*8d67ca89SAndroid Build Coastguard Worker 	return (int)(dn - dst);
399*8d67ca89SAndroid Build Coastguard Worker }
400*8d67ca89SAndroid Build Coastguard Worker 
401*8d67ca89SAndroid Build Coastguard Worker /*
402*8d67ca89SAndroid Build Coastguard Worker  *	Unpack a domain name from a message, source may be compressed.
403*8d67ca89SAndroid Build Coastguard Worker  *
404*8d67ca89SAndroid Build Coastguard Worker  * return:
405*8d67ca89SAndroid Build Coastguard Worker  *	-1 if it fails, or consumed octets if it succeeds.
406*8d67ca89SAndroid Build Coastguard Worker  */
407*8d67ca89SAndroid Build Coastguard Worker int
ns_name_unpack(const u_char * msg,const u_char * eom,const u_char * src,u_char * dst,size_t dstsiz)408*8d67ca89SAndroid Build Coastguard Worker ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src,
409*8d67ca89SAndroid Build Coastguard Worker 	       u_char *dst, size_t dstsiz)
410*8d67ca89SAndroid Build Coastguard Worker {
411*8d67ca89SAndroid Build Coastguard Worker 	return (ns_name_unpack2(msg, eom, src, dst, dstsiz, NULL));
412*8d67ca89SAndroid Build Coastguard Worker }
413*8d67ca89SAndroid Build Coastguard Worker 
414*8d67ca89SAndroid Build Coastguard Worker /*
415*8d67ca89SAndroid Build Coastguard Worker  * ns_name_unpack2(msg, eom, src, dst, dstsiz, *dstlen)
416*8d67ca89SAndroid Build Coastguard Worker  *	Unpack a domain name from a message, source may be compressed.
417*8d67ca89SAndroid Build Coastguard Worker  * return:
418*8d67ca89SAndroid Build Coastguard Worker  *	-1 if it fails, or consumed octets if it succeeds.
419*8d67ca89SAndroid Build Coastguard Worker  * side effect:
420*8d67ca89SAndroid Build Coastguard Worker  *	fills in *dstlen (if non-NULL).
421*8d67ca89SAndroid Build Coastguard Worker  */
422*8d67ca89SAndroid Build Coastguard Worker int
ns_name_unpack2(const u_char * msg,const u_char * eom,const u_char * src,u_char * dst,size_t dstsiz,size_t * dstlen)423*8d67ca89SAndroid Build Coastguard Worker ns_name_unpack2(const u_char *msg, const u_char *eom, const u_char *src,
424*8d67ca89SAndroid Build Coastguard Worker 		u_char *dst, size_t dstsiz, size_t *dstlen)
425*8d67ca89SAndroid Build Coastguard Worker {
426*8d67ca89SAndroid Build Coastguard Worker 	const u_char *srcp, *dstlim;
427*8d67ca89SAndroid Build Coastguard Worker 	u_char *dstp;
428*8d67ca89SAndroid Build Coastguard Worker 	int n, len, checked, l;
429*8d67ca89SAndroid Build Coastguard Worker 
430*8d67ca89SAndroid Build Coastguard Worker 	len = -1;
431*8d67ca89SAndroid Build Coastguard Worker 	checked = 0;
432*8d67ca89SAndroid Build Coastguard Worker 	dstp = dst;
433*8d67ca89SAndroid Build Coastguard Worker 	srcp = src;
434*8d67ca89SAndroid Build Coastguard Worker 	dstlim = dst + dstsiz;
435*8d67ca89SAndroid Build Coastguard Worker 	if (srcp < msg || srcp >= eom) {
436*8d67ca89SAndroid Build Coastguard Worker 		errno = EMSGSIZE;
437*8d67ca89SAndroid Build Coastguard Worker 		return (-1);
438*8d67ca89SAndroid Build Coastguard Worker 	}
439*8d67ca89SAndroid Build Coastguard Worker 	/* Fetch next label in domain name. */
440*8d67ca89SAndroid Build Coastguard Worker 	while ((n = *srcp++) != 0) {
441*8d67ca89SAndroid Build Coastguard Worker 		/* Check for indirection. */
442*8d67ca89SAndroid Build Coastguard Worker 		switch (n & NS_CMPRSFLGS) {
443*8d67ca89SAndroid Build Coastguard Worker 		case 0:
444*8d67ca89SAndroid Build Coastguard Worker 		case NS_TYPE_ELT:
445*8d67ca89SAndroid Build Coastguard Worker 			/* Limit checks. */
446*8d67ca89SAndroid Build Coastguard Worker 			if ((l = labellen(srcp - 1)) < 0) {
447*8d67ca89SAndroid Build Coastguard Worker 				errno = EMSGSIZE;
448*8d67ca89SAndroid Build Coastguard Worker 				return(-1);
449*8d67ca89SAndroid Build Coastguard Worker 			}
450*8d67ca89SAndroid Build Coastguard Worker 			if (dstp + l + 1 >= dstlim || srcp + l >= eom) {
451*8d67ca89SAndroid Build Coastguard Worker 				errno = EMSGSIZE;
452*8d67ca89SAndroid Build Coastguard Worker 				return (-1);
453*8d67ca89SAndroid Build Coastguard Worker 			}
454*8d67ca89SAndroid Build Coastguard Worker 			checked += l + 1;
455*8d67ca89SAndroid Build Coastguard Worker 			*dstp++ = n;
456*8d67ca89SAndroid Build Coastguard Worker 			memcpy(dstp, srcp, (size_t)l);
457*8d67ca89SAndroid Build Coastguard Worker 			dstp += l;
458*8d67ca89SAndroid Build Coastguard Worker 			srcp += l;
459*8d67ca89SAndroid Build Coastguard Worker 			break;
460*8d67ca89SAndroid Build Coastguard Worker 
461*8d67ca89SAndroid Build Coastguard Worker 		case NS_CMPRSFLGS:
462*8d67ca89SAndroid Build Coastguard Worker 			if (srcp >= eom) {
463*8d67ca89SAndroid Build Coastguard Worker 				errno = EMSGSIZE;
464*8d67ca89SAndroid Build Coastguard Worker 				return (-1);
465*8d67ca89SAndroid Build Coastguard Worker 			}
466*8d67ca89SAndroid Build Coastguard Worker 			if (len < 0) {
467*8d67ca89SAndroid Build Coastguard Worker 				_DIAGASSERT(__type_fit(int, srcp - src + 1));
468*8d67ca89SAndroid Build Coastguard Worker 				len = (int)(srcp - src + 1);
469*8d67ca89SAndroid Build Coastguard Worker 			}
470*8d67ca89SAndroid Build Coastguard Worker 			// BEGIN android-changed: safer pointer overflow check
471*8d67ca89SAndroid Build Coastguard Worker 			l = (((n & 0x3f) << 8) | (*srcp & 0xff));
472*8d67ca89SAndroid Build Coastguard Worker 			if (l >= eom - msg) {  /* Out of range. */
473*8d67ca89SAndroid Build Coastguard Worker 				errno = EMSGSIZE;
474*8d67ca89SAndroid Build Coastguard Worker 				return (-1);
475*8d67ca89SAndroid Build Coastguard Worker 			}
476*8d67ca89SAndroid Build Coastguard Worker 			srcp = msg + l;
477*8d67ca89SAndroid Build Coastguard Worker 			// END android-changed
478*8d67ca89SAndroid Build Coastguard Worker 			checked += 2;
479*8d67ca89SAndroid Build Coastguard Worker 			/*
480*8d67ca89SAndroid Build Coastguard Worker 			 * Check for loops in the compressed name;
481*8d67ca89SAndroid Build Coastguard Worker 			 * if we've looked at the whole message,
482*8d67ca89SAndroid Build Coastguard Worker 			 * there must be a loop.
483*8d67ca89SAndroid Build Coastguard Worker 			 */
484*8d67ca89SAndroid Build Coastguard Worker 			if (checked >= eom - msg) {
485*8d67ca89SAndroid Build Coastguard Worker 				errno = EMSGSIZE;
486*8d67ca89SAndroid Build Coastguard Worker 				return (-1);
487*8d67ca89SAndroid Build Coastguard Worker 			}
488*8d67ca89SAndroid Build Coastguard Worker 			break;
489*8d67ca89SAndroid Build Coastguard Worker 
490*8d67ca89SAndroid Build Coastguard Worker 		default:
491*8d67ca89SAndroid Build Coastguard Worker 			errno = EMSGSIZE;
492*8d67ca89SAndroid Build Coastguard Worker 			return (-1);			/* flag error */
493*8d67ca89SAndroid Build Coastguard Worker 		}
494*8d67ca89SAndroid Build Coastguard Worker 	}
495*8d67ca89SAndroid Build Coastguard Worker 	*dstp++ = 0;
496*8d67ca89SAndroid Build Coastguard Worker 	if (dstlen != NULL)
497*8d67ca89SAndroid Build Coastguard Worker 		*dstlen = dstp - dst;
498*8d67ca89SAndroid Build Coastguard Worker 	if (len < 0) {
499*8d67ca89SAndroid Build Coastguard Worker 		_DIAGASSERT(__type_fit(int, srcp - src));
500*8d67ca89SAndroid Build Coastguard Worker 		len = (int)(srcp - src);
501*8d67ca89SAndroid Build Coastguard Worker 	}
502*8d67ca89SAndroid Build Coastguard Worker 	return len;
503*8d67ca89SAndroid Build Coastguard Worker }
504*8d67ca89SAndroid Build Coastguard Worker 
505*8d67ca89SAndroid Build Coastguard Worker /*
506*8d67ca89SAndroid Build Coastguard Worker  *	Pack domain name 'domain' into 'comp_dn'.
507*8d67ca89SAndroid Build Coastguard Worker  *
508*8d67ca89SAndroid Build Coastguard Worker  * return:
509*8d67ca89SAndroid Build Coastguard Worker  *	Size of the compressed name, or -1.
510*8d67ca89SAndroid Build Coastguard Worker  *
511*8d67ca89SAndroid Build Coastguard Worker  * notes:
512*8d67ca89SAndroid Build Coastguard Worker  *	'dnptrs' is an array of pointers to previous compressed names.
513*8d67ca89SAndroid Build Coastguard Worker  *	dnptrs[0] is a pointer to the beginning of the message. The array
514*8d67ca89SAndroid Build Coastguard Worker  *	ends with NULL.
515*8d67ca89SAndroid Build Coastguard Worker  *	'lastdnptr' is a pointer to the end of the array pointed to
516*8d67ca89SAndroid Build Coastguard Worker  *	by 'dnptrs'.
517*8d67ca89SAndroid Build Coastguard Worker  *
518*8d67ca89SAndroid Build Coastguard Worker  * Side effects:
519*8d67ca89SAndroid Build Coastguard Worker  *	The list of pointers in dnptrs is updated for labels inserted into
520*8d67ca89SAndroid Build Coastguard Worker  *	the message as we compress the name.  If 'dnptr' is NULL, we don't
521*8d67ca89SAndroid Build Coastguard Worker  *	try to compress names. If 'lastdnptr' is NULL, we don't update the
522*8d67ca89SAndroid Build Coastguard Worker  *	list.
523*8d67ca89SAndroid Build Coastguard Worker  */
524*8d67ca89SAndroid Build Coastguard Worker int
ns_name_pack(const u_char * src,u_char * dst,int dstsiz,const u_char ** dnptrs,const u_char ** lastdnptr)525*8d67ca89SAndroid Build Coastguard Worker ns_name_pack(const u_char *src, u_char *dst, int dstsiz,
526*8d67ca89SAndroid Build Coastguard Worker 	     const u_char **dnptrs, const u_char **lastdnptr)
527*8d67ca89SAndroid Build Coastguard Worker {
528*8d67ca89SAndroid Build Coastguard Worker 	u_char *dstp;
529*8d67ca89SAndroid Build Coastguard Worker 	const u_char **cpp, **lpp, *eob, *msg;
530*8d67ca89SAndroid Build Coastguard Worker 	const u_char *srcp;
531*8d67ca89SAndroid Build Coastguard Worker 	int n, l, first = 1;
532*8d67ca89SAndroid Build Coastguard Worker 
533*8d67ca89SAndroid Build Coastguard Worker 	srcp = src;
534*8d67ca89SAndroid Build Coastguard Worker 	dstp = dst;
535*8d67ca89SAndroid Build Coastguard Worker 	eob = dstp + dstsiz;
536*8d67ca89SAndroid Build Coastguard Worker 	lpp = cpp = NULL;
537*8d67ca89SAndroid Build Coastguard Worker 	if (dnptrs != NULL) {
538*8d67ca89SAndroid Build Coastguard Worker 		if ((msg = *dnptrs++) != NULL) {
539*8d67ca89SAndroid Build Coastguard Worker 			for (cpp = dnptrs; *cpp != NULL; cpp++)
540*8d67ca89SAndroid Build Coastguard Worker 				continue;
541*8d67ca89SAndroid Build Coastguard Worker 			lpp = cpp;	/* end of list to search */
542*8d67ca89SAndroid Build Coastguard Worker 		}
543*8d67ca89SAndroid Build Coastguard Worker 	} else
544*8d67ca89SAndroid Build Coastguard Worker 		msg = NULL;
545*8d67ca89SAndroid Build Coastguard Worker 
546*8d67ca89SAndroid Build Coastguard Worker 	/* make sure the domain we are about to add is legal */
547*8d67ca89SAndroid Build Coastguard Worker 	l = 0;
548*8d67ca89SAndroid Build Coastguard Worker 	do {
549*8d67ca89SAndroid Build Coastguard Worker 		int l0;
550*8d67ca89SAndroid Build Coastguard Worker 
551*8d67ca89SAndroid Build Coastguard Worker 		n = *srcp;
552*8d67ca89SAndroid Build Coastguard Worker 		if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
553*8d67ca89SAndroid Build Coastguard Worker 			errno = EMSGSIZE;
554*8d67ca89SAndroid Build Coastguard Worker 			return (-1);
555*8d67ca89SAndroid Build Coastguard Worker 		}
556*8d67ca89SAndroid Build Coastguard Worker 		if ((l0 = labellen(srcp)) < 0) {
557*8d67ca89SAndroid Build Coastguard Worker 			errno = EINVAL;
558*8d67ca89SAndroid Build Coastguard Worker 			return(-1);
559*8d67ca89SAndroid Build Coastguard Worker 		}
560*8d67ca89SAndroid Build Coastguard Worker 		l += l0 + 1;
561*8d67ca89SAndroid Build Coastguard Worker 		if (l > MAXCDNAME) {
562*8d67ca89SAndroid Build Coastguard Worker 			errno = EMSGSIZE;
563*8d67ca89SAndroid Build Coastguard Worker 			return (-1);
564*8d67ca89SAndroid Build Coastguard Worker 		}
565*8d67ca89SAndroid Build Coastguard Worker 		srcp += l0 + 1;
566*8d67ca89SAndroid Build Coastguard Worker 	} while (n != 0);
567*8d67ca89SAndroid Build Coastguard Worker 
568*8d67ca89SAndroid Build Coastguard Worker 	/* from here on we need to reset compression pointer array on error */
569*8d67ca89SAndroid Build Coastguard Worker 	srcp = src;
570*8d67ca89SAndroid Build Coastguard Worker 	do {
571*8d67ca89SAndroid Build Coastguard Worker 		/* Look to see if we can use pointers. */
572*8d67ca89SAndroid Build Coastguard Worker 		n = *srcp;
573*8d67ca89SAndroid Build Coastguard Worker 		if (n != 0 && msg != NULL) {
574*8d67ca89SAndroid Build Coastguard Worker 			l = dn_find(srcp, msg, (const u_char * const *)dnptrs,
575*8d67ca89SAndroid Build Coastguard Worker 				    (const u_char * const *)lpp);
576*8d67ca89SAndroid Build Coastguard Worker 			if (l >= 0) {
577*8d67ca89SAndroid Build Coastguard Worker 				if (dstp + 1 >= eob) {
578*8d67ca89SAndroid Build Coastguard Worker 					goto cleanup;
579*8d67ca89SAndroid Build Coastguard Worker 				}
580*8d67ca89SAndroid Build Coastguard Worker 				*dstp++ = ((u_int32_t)l >> 8) | NS_CMPRSFLGS;
581*8d67ca89SAndroid Build Coastguard Worker 				*dstp++ = l % 256;
582*8d67ca89SAndroid Build Coastguard Worker 				_DIAGASSERT(__type_fit(int, dstp - dst));
583*8d67ca89SAndroid Build Coastguard Worker 				return (int)(dstp - dst);
584*8d67ca89SAndroid Build Coastguard Worker 			}
585*8d67ca89SAndroid Build Coastguard Worker 			/* Not found, save it. */
586*8d67ca89SAndroid Build Coastguard Worker 			if (lastdnptr != NULL && cpp < lastdnptr - 1 &&
587*8d67ca89SAndroid Build Coastguard Worker 			    (dstp - msg) < 0x4000 && first) {
588*8d67ca89SAndroid Build Coastguard Worker 				*cpp++ = dstp;
589*8d67ca89SAndroid Build Coastguard Worker 				*cpp = NULL;
590*8d67ca89SAndroid Build Coastguard Worker 				first = 0;
591*8d67ca89SAndroid Build Coastguard Worker 			}
592*8d67ca89SAndroid Build Coastguard Worker 		}
593*8d67ca89SAndroid Build Coastguard Worker 		/* copy label to buffer */
594*8d67ca89SAndroid Build Coastguard Worker 		if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
595*8d67ca89SAndroid Build Coastguard Worker 			/* Should not happen. */
596*8d67ca89SAndroid Build Coastguard Worker 			goto cleanup;
597*8d67ca89SAndroid Build Coastguard Worker 		}
598*8d67ca89SAndroid Build Coastguard Worker 		n = labellen(srcp);
599*8d67ca89SAndroid Build Coastguard Worker 		if (dstp + 1 + n >= eob) {
600*8d67ca89SAndroid Build Coastguard Worker 			goto cleanup;
601*8d67ca89SAndroid Build Coastguard Worker 		}
602*8d67ca89SAndroid Build Coastguard Worker 		memcpy(dstp, srcp, (size_t)(n + 1));
603*8d67ca89SAndroid Build Coastguard Worker 		srcp += n + 1;
604*8d67ca89SAndroid Build Coastguard Worker 		dstp += n + 1;
605*8d67ca89SAndroid Build Coastguard Worker 	} while (n != 0);
606*8d67ca89SAndroid Build Coastguard Worker 
607*8d67ca89SAndroid Build Coastguard Worker 	if (dstp > eob) {
608*8d67ca89SAndroid Build Coastguard Worker cleanup:
609*8d67ca89SAndroid Build Coastguard Worker 		if (msg != NULL)
610*8d67ca89SAndroid Build Coastguard Worker 			*lpp = NULL;
611*8d67ca89SAndroid Build Coastguard Worker 		errno = EMSGSIZE;
612*8d67ca89SAndroid Build Coastguard Worker 		return (-1);
613*8d67ca89SAndroid Build Coastguard Worker 	}
614*8d67ca89SAndroid Build Coastguard Worker 	_DIAGASSERT(__type_fit(int, dstp - dst));
615*8d67ca89SAndroid Build Coastguard Worker 	return (int)(dstp - dst);
616*8d67ca89SAndroid Build Coastguard Worker }
617*8d67ca89SAndroid Build Coastguard Worker 
618*8d67ca89SAndroid Build Coastguard Worker /*
619*8d67ca89SAndroid Build Coastguard Worker  *	Expand compressed domain name to presentation format.
620*8d67ca89SAndroid Build Coastguard Worker  *
621*8d67ca89SAndroid Build Coastguard Worker  * return:
622*8d67ca89SAndroid Build Coastguard Worker  *	Number of bytes read out of `src', or -1 (with errno set).
623*8d67ca89SAndroid Build Coastguard Worker  *
624*8d67ca89SAndroid Build Coastguard Worker  * note:
625*8d67ca89SAndroid Build Coastguard Worker  *	Root domain returns as "." not "".
626*8d67ca89SAndroid Build Coastguard Worker  */
627*8d67ca89SAndroid Build Coastguard Worker int
ns_name_uncompress(const u_char * msg,const u_char * eom,const u_char * src,char * dst,size_t dstsiz)628*8d67ca89SAndroid Build Coastguard Worker ns_name_uncompress(const u_char *msg, const u_char *eom, const u_char *src,
629*8d67ca89SAndroid Build Coastguard Worker 		   char *dst, size_t dstsiz)
630*8d67ca89SAndroid Build Coastguard Worker {
631*8d67ca89SAndroid Build Coastguard Worker 	u_char tmp[NS_MAXCDNAME];
632*8d67ca89SAndroid Build Coastguard Worker 	int n;
633*8d67ca89SAndroid Build Coastguard Worker 
634*8d67ca89SAndroid Build Coastguard Worker 	if ((n = ns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1)
635*8d67ca89SAndroid Build Coastguard Worker 		return (-1);
636*8d67ca89SAndroid Build Coastguard Worker 	if (ns_name_ntop(tmp, dst, dstsiz) == -1)
637*8d67ca89SAndroid Build Coastguard Worker 		return (-1);
638*8d67ca89SAndroid Build Coastguard Worker 	return (n);
639*8d67ca89SAndroid Build Coastguard Worker }
640*8d67ca89SAndroid Build Coastguard Worker 
641*8d67ca89SAndroid Build Coastguard Worker /*
642*8d67ca89SAndroid Build Coastguard Worker  *	Compress a domain name into wire format, using compression pointers.
643*8d67ca89SAndroid Build Coastguard Worker  *
644*8d67ca89SAndroid Build Coastguard Worker  * return:
645*8d67ca89SAndroid Build Coastguard Worker  *	Number of bytes consumed in `dst' or -1 (with errno set).
646*8d67ca89SAndroid Build Coastguard Worker  *
647*8d67ca89SAndroid Build Coastguard Worker  * notes:
648*8d67ca89SAndroid Build Coastguard Worker  *	'dnptrs' is an array of pointers to previous compressed names.
649*8d67ca89SAndroid Build Coastguard Worker  *	dnptrs[0] is a pointer to the beginning of the message.
650*8d67ca89SAndroid Build Coastguard Worker  *	The list ends with NULL.  'lastdnptr' is a pointer to the end of the
651*8d67ca89SAndroid Build Coastguard Worker  *	array pointed to by 'dnptrs'. Side effect is to update the list of
652*8d67ca89SAndroid Build Coastguard Worker  *	pointers for labels inserted into the message as we compress the name.
653*8d67ca89SAndroid Build Coastguard Worker  *	If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
654*8d67ca89SAndroid Build Coastguard Worker  *	is NULL, we don't update the list.
655*8d67ca89SAndroid Build Coastguard Worker  */
656*8d67ca89SAndroid Build Coastguard Worker int
ns_name_compress(const char * src,u_char * dst,size_t dstsiz,const u_char ** dnptrs,const u_char ** lastdnptr)657*8d67ca89SAndroid Build Coastguard Worker ns_name_compress(const char *src, u_char *dst, size_t dstsiz,
658*8d67ca89SAndroid Build Coastguard Worker 		 const u_char **dnptrs, const u_char **lastdnptr)
659*8d67ca89SAndroid Build Coastguard Worker {
660*8d67ca89SAndroid Build Coastguard Worker 	u_char tmp[NS_MAXCDNAME];
661*8d67ca89SAndroid Build Coastguard Worker 
662*8d67ca89SAndroid Build Coastguard Worker 	if (ns_name_pton(src, tmp, sizeof tmp) == -1)
663*8d67ca89SAndroid Build Coastguard Worker 		return (-1);
664*8d67ca89SAndroid Build Coastguard Worker 	return (ns_name_pack(tmp, dst, (int)dstsiz, dnptrs, lastdnptr));
665*8d67ca89SAndroid Build Coastguard Worker }
666*8d67ca89SAndroid Build Coastguard Worker 
667*8d67ca89SAndroid Build Coastguard Worker /*
668*8d67ca89SAndroid Build Coastguard Worker  * Reset dnptrs so that there are no active references to pointers at or
669*8d67ca89SAndroid Build Coastguard Worker  * after src.
670*8d67ca89SAndroid Build Coastguard Worker  */
671*8d67ca89SAndroid Build Coastguard Worker void
ns_name_rollback(const u_char * src,const u_char ** dnptrs,const u_char ** lastdnptr)672*8d67ca89SAndroid Build Coastguard Worker ns_name_rollback(const u_char *src, const u_char **dnptrs,
673*8d67ca89SAndroid Build Coastguard Worker 		 const u_char **lastdnptr)
674*8d67ca89SAndroid Build Coastguard Worker {
675*8d67ca89SAndroid Build Coastguard Worker 	while (dnptrs < lastdnptr && *dnptrs != NULL) {
676*8d67ca89SAndroid Build Coastguard Worker 		if (*dnptrs >= src) {
677*8d67ca89SAndroid Build Coastguard Worker 			*dnptrs = NULL;
678*8d67ca89SAndroid Build Coastguard Worker 			break;
679*8d67ca89SAndroid Build Coastguard Worker 		}
680*8d67ca89SAndroid Build Coastguard Worker 		dnptrs++;
681*8d67ca89SAndroid Build Coastguard Worker 	}
682*8d67ca89SAndroid Build Coastguard Worker }
683*8d67ca89SAndroid Build Coastguard Worker 
684*8d67ca89SAndroid Build Coastguard Worker /*
685*8d67ca89SAndroid Build Coastguard Worker  *	Advance *ptrptr to skip over the compressed name it points at.
686*8d67ca89SAndroid Build Coastguard Worker  *
687*8d67ca89SAndroid Build Coastguard Worker  * return:
688*8d67ca89SAndroid Build Coastguard Worker  *	0 on success, -1 (with errno set) on failure.
689*8d67ca89SAndroid Build Coastguard Worker  */
690*8d67ca89SAndroid Build Coastguard Worker int
ns_name_skip(const u_char ** ptrptr,const u_char * eom)691*8d67ca89SAndroid Build Coastguard Worker ns_name_skip(const u_char **ptrptr, const u_char *eom)
692*8d67ca89SAndroid Build Coastguard Worker {
693*8d67ca89SAndroid Build Coastguard Worker 	const u_char *cp;
694*8d67ca89SAndroid Build Coastguard Worker 	u_int n;
695*8d67ca89SAndroid Build Coastguard Worker 	int l=0;
696*8d67ca89SAndroid Build Coastguard Worker 
697*8d67ca89SAndroid Build Coastguard Worker 	cp = *ptrptr;
698*8d67ca89SAndroid Build Coastguard Worker 	while (cp < eom && (n = *cp++) != 0) {
699*8d67ca89SAndroid Build Coastguard Worker 		/* Check for indirection. */
700*8d67ca89SAndroid Build Coastguard Worker 		switch (n & NS_CMPRSFLGS) {
701*8d67ca89SAndroid Build Coastguard Worker 		case 0:			/* normal case, n == len */
702*8d67ca89SAndroid Build Coastguard Worker 			cp += n;
703*8d67ca89SAndroid Build Coastguard Worker 			continue;
704*8d67ca89SAndroid Build Coastguard Worker 		case NS_TYPE_ELT: /* EDNS0 extended label */
705*8d67ca89SAndroid Build Coastguard Worker 			if (cp < eom && (l = labellen(cp - 1)) < 0) {
706*8d67ca89SAndroid Build Coastguard Worker 				errno = EMSGSIZE; /* XXX */
707*8d67ca89SAndroid Build Coastguard Worker 				return(-1);
708*8d67ca89SAndroid Build Coastguard Worker 			}
709*8d67ca89SAndroid Build Coastguard Worker 			cp += l;
710*8d67ca89SAndroid Build Coastguard Worker 			continue;
711*8d67ca89SAndroid Build Coastguard Worker 		case NS_CMPRSFLGS:	/* indirection */
712*8d67ca89SAndroid Build Coastguard Worker 			cp++;
713*8d67ca89SAndroid Build Coastguard Worker 			break;
714*8d67ca89SAndroid Build Coastguard Worker 		default:		/* illegal type */
715*8d67ca89SAndroid Build Coastguard Worker 			errno = EMSGSIZE;
716*8d67ca89SAndroid Build Coastguard Worker 			return (-1);
717*8d67ca89SAndroid Build Coastguard Worker 		}
718*8d67ca89SAndroid Build Coastguard Worker 		break;
719*8d67ca89SAndroid Build Coastguard Worker 	}
720*8d67ca89SAndroid Build Coastguard Worker 	if (cp > eom) {
721*8d67ca89SAndroid Build Coastguard Worker 		errno = EMSGSIZE;
722*8d67ca89SAndroid Build Coastguard Worker 		return (-1);
723*8d67ca89SAndroid Build Coastguard Worker 	}
724*8d67ca89SAndroid Build Coastguard Worker 	*ptrptr = cp;
725*8d67ca89SAndroid Build Coastguard Worker 	return (0);
726*8d67ca89SAndroid Build Coastguard Worker }
727*8d67ca89SAndroid Build Coastguard Worker 
728*8d67ca89SAndroid Build Coastguard Worker /* Find the number of octets an nname takes up, including the root label.
729*8d67ca89SAndroid Build Coastguard Worker  * (This is basically ns_name_skip() without compression-pointer support.)
730*8d67ca89SAndroid Build Coastguard Worker  * ((NOTE: can only return zero if passed-in namesiz argument is zero.))
731*8d67ca89SAndroid Build Coastguard Worker  */
732*8d67ca89SAndroid Build Coastguard Worker ssize_t
ns_name_length(ns_nname_ct nname,size_t namesiz)733*8d67ca89SAndroid Build Coastguard Worker ns_name_length(ns_nname_ct nname, size_t namesiz) {
734*8d67ca89SAndroid Build Coastguard Worker 	ns_nname_ct orig = nname;
735*8d67ca89SAndroid Build Coastguard Worker 	u_int n;
736*8d67ca89SAndroid Build Coastguard Worker 
737*8d67ca89SAndroid Build Coastguard Worker 	while (namesiz-- > 0 && (n = *nname++) != 0) {
738*8d67ca89SAndroid Build Coastguard Worker 		if ((n & NS_CMPRSFLGS) != 0) {
739*8d67ca89SAndroid Build Coastguard Worker 			errno = EISDIR;
740*8d67ca89SAndroid Build Coastguard Worker 			return (-1);
741*8d67ca89SAndroid Build Coastguard Worker 		}
742*8d67ca89SAndroid Build Coastguard Worker 		if (n > namesiz) {
743*8d67ca89SAndroid Build Coastguard Worker 			errno = EMSGSIZE;
744*8d67ca89SAndroid Build Coastguard Worker 			return (-1);
745*8d67ca89SAndroid Build Coastguard Worker 		}
746*8d67ca89SAndroid Build Coastguard Worker 		nname += n;
747*8d67ca89SAndroid Build Coastguard Worker 		namesiz -= n;
748*8d67ca89SAndroid Build Coastguard Worker 	}
749*8d67ca89SAndroid Build Coastguard Worker 	return (nname - orig);
750*8d67ca89SAndroid Build Coastguard Worker }
751*8d67ca89SAndroid Build Coastguard Worker 
752*8d67ca89SAndroid Build Coastguard Worker /* Compare two nname's for equality.  Return -1 on error (setting errno).
753*8d67ca89SAndroid Build Coastguard Worker  */
754*8d67ca89SAndroid Build Coastguard Worker int
ns_name_eq(ns_nname_ct a,size_t as,ns_nname_ct b,size_t bs)755*8d67ca89SAndroid Build Coastguard Worker ns_name_eq(ns_nname_ct a, size_t as, ns_nname_ct b, size_t bs) {
756*8d67ca89SAndroid Build Coastguard Worker 	ns_nname_ct ae = a + as, be = b + bs;
757*8d67ca89SAndroid Build Coastguard Worker 	int ac, bc;
758*8d67ca89SAndroid Build Coastguard Worker 
759*8d67ca89SAndroid Build Coastguard Worker 	while (ac = *a, bc = *b, ac != 0 && bc != 0) {
760*8d67ca89SAndroid Build Coastguard Worker 		if ((ac & NS_CMPRSFLGS) != 0 || (bc & NS_CMPRSFLGS) != 0) {
761*8d67ca89SAndroid Build Coastguard Worker 			errno = EISDIR;
762*8d67ca89SAndroid Build Coastguard Worker 			return (-1);
763*8d67ca89SAndroid Build Coastguard Worker 		}
764*8d67ca89SAndroid Build Coastguard Worker 		if (a + ac >= ae || b + bc >= be) {
765*8d67ca89SAndroid Build Coastguard Worker 			errno = EMSGSIZE;
766*8d67ca89SAndroid Build Coastguard Worker 			return (-1);
767*8d67ca89SAndroid Build Coastguard Worker 		}
768*8d67ca89SAndroid Build Coastguard Worker 		if (ac != bc || strncasecmp((const char *) ++a,
769*8d67ca89SAndroid Build Coastguard Worker 					    (const char *) ++b,
770*8d67ca89SAndroid Build Coastguard Worker 					    (size_t)ac) != 0)
771*8d67ca89SAndroid Build Coastguard Worker 			return (0);
772*8d67ca89SAndroid Build Coastguard Worker 		a += ac, b += bc;
773*8d67ca89SAndroid Build Coastguard Worker 	}
774*8d67ca89SAndroid Build Coastguard Worker 	return (ac == 0 && bc == 0);
775*8d67ca89SAndroid Build Coastguard Worker }
776*8d67ca89SAndroid Build Coastguard Worker 
777*8d67ca89SAndroid Build Coastguard Worker /* Is domain "A" owned by (at or below) domain "B"?
778*8d67ca89SAndroid Build Coastguard Worker  */
779*8d67ca89SAndroid Build Coastguard Worker int
ns_name_owned(ns_namemap_ct a,int an,ns_namemap_ct b,int bn)780*8d67ca89SAndroid Build Coastguard Worker ns_name_owned(ns_namemap_ct a, int an, ns_namemap_ct b, int bn) {
781*8d67ca89SAndroid Build Coastguard Worker 	/* If A is shorter, it cannot be owned by B. */
782*8d67ca89SAndroid Build Coastguard Worker 	if (an < bn)
783*8d67ca89SAndroid Build Coastguard Worker 		return (0);
784*8d67ca89SAndroid Build Coastguard Worker 
785*8d67ca89SAndroid Build Coastguard Worker 	/* If they are unequal before the length of the shorter, A cannot... */
786*8d67ca89SAndroid Build Coastguard Worker 	while (bn > 0) {
787*8d67ca89SAndroid Build Coastguard Worker 		if (a->len != b->len ||
788*8d67ca89SAndroid Build Coastguard Worker 		    strncasecmp((const char *) a->base,
789*8d67ca89SAndroid Build Coastguard Worker 				(const char *) b->base, (size_t)a->len) != 0)
790*8d67ca89SAndroid Build Coastguard Worker 			return (0);
791*8d67ca89SAndroid Build Coastguard Worker 		a++, an--;
792*8d67ca89SAndroid Build Coastguard Worker 		b++, bn--;
793*8d67ca89SAndroid Build Coastguard Worker 	}
794*8d67ca89SAndroid Build Coastguard Worker 
795*8d67ca89SAndroid Build Coastguard Worker 	/* A might be longer or not, but either way, B owns it. */
796*8d67ca89SAndroid Build Coastguard Worker 	return (1);
797*8d67ca89SAndroid Build Coastguard Worker }
798*8d67ca89SAndroid Build Coastguard Worker 
799*8d67ca89SAndroid Build Coastguard Worker /* Build an array of <base,len> tuples from an nname, top-down order.
800*8d67ca89SAndroid Build Coastguard Worker  * Return the number of tuples (labels) thus discovered.
801*8d67ca89SAndroid Build Coastguard Worker  */
802*8d67ca89SAndroid Build Coastguard Worker int
ns_name_map(ns_nname_ct nname,size_t namelen,ns_namemap_t map,int mapsize)803*8d67ca89SAndroid Build Coastguard Worker ns_name_map(ns_nname_ct nname, size_t namelen, ns_namemap_t map, int mapsize) {
804*8d67ca89SAndroid Build Coastguard Worker 	u_int n;
805*8d67ca89SAndroid Build Coastguard Worker 	int l;
806*8d67ca89SAndroid Build Coastguard Worker 
807*8d67ca89SAndroid Build Coastguard Worker 	n = *nname++;
808*8d67ca89SAndroid Build Coastguard Worker 	namelen--;
809*8d67ca89SAndroid Build Coastguard Worker 
810*8d67ca89SAndroid Build Coastguard Worker 	/* Root zone? */
811*8d67ca89SAndroid Build Coastguard Worker 	if (n == 0) {
812*8d67ca89SAndroid Build Coastguard Worker 		/* Extra data follows name? */
813*8d67ca89SAndroid Build Coastguard Worker 		if (namelen > 0) {
814*8d67ca89SAndroid Build Coastguard Worker 			errno = EMSGSIZE;
815*8d67ca89SAndroid Build Coastguard Worker 			return (-1);
816*8d67ca89SAndroid Build Coastguard Worker 		}
817*8d67ca89SAndroid Build Coastguard Worker 		return (0);
818*8d67ca89SAndroid Build Coastguard Worker 	}
819*8d67ca89SAndroid Build Coastguard Worker 
820*8d67ca89SAndroid Build Coastguard Worker 	/* Compression pointer? */
821*8d67ca89SAndroid Build Coastguard Worker 	if ((n & NS_CMPRSFLGS) != 0) {
822*8d67ca89SAndroid Build Coastguard Worker 		errno = EISDIR;
823*8d67ca89SAndroid Build Coastguard Worker 		return (-1);
824*8d67ca89SAndroid Build Coastguard Worker 	}
825*8d67ca89SAndroid Build Coastguard Worker 
826*8d67ca89SAndroid Build Coastguard Worker 	/* Label too long? */
827*8d67ca89SAndroid Build Coastguard Worker 	if (n > namelen) {
828*8d67ca89SAndroid Build Coastguard Worker 		errno = EMSGSIZE;
829*8d67ca89SAndroid Build Coastguard Worker 		return (-1);
830*8d67ca89SAndroid Build Coastguard Worker 	}
831*8d67ca89SAndroid Build Coastguard Worker 
832*8d67ca89SAndroid Build Coastguard Worker 	/* Recurse to get rest of name done first. */
833*8d67ca89SAndroid Build Coastguard Worker 	l = ns_name_map(nname + n, namelen - n, map, mapsize);
834*8d67ca89SAndroid Build Coastguard Worker 	if (l < 0)
835*8d67ca89SAndroid Build Coastguard Worker 		return (-1);
836*8d67ca89SAndroid Build Coastguard Worker 
837*8d67ca89SAndroid Build Coastguard Worker 	/* Too many labels? */
838*8d67ca89SAndroid Build Coastguard Worker 	if (l >= mapsize) {
839*8d67ca89SAndroid Build Coastguard Worker 		errno = ENAMETOOLONG;
840*8d67ca89SAndroid Build Coastguard Worker 		return (-1);
841*8d67ca89SAndroid Build Coastguard Worker 	}
842*8d67ca89SAndroid Build Coastguard Worker 
843*8d67ca89SAndroid Build Coastguard Worker 	/* We're on our way back up-stack, store current map data. */
844*8d67ca89SAndroid Build Coastguard Worker 	map[l].base = nname;
845*8d67ca89SAndroid Build Coastguard Worker 	map[l].len = n;
846*8d67ca89SAndroid Build Coastguard Worker 	return (l + 1);
847*8d67ca89SAndroid Build Coastguard Worker }
848*8d67ca89SAndroid Build Coastguard Worker 
849*8d67ca89SAndroid Build Coastguard Worker /* Count the labels in a domain name.  Root counts, so COM. has two.  This
850*8d67ca89SAndroid Build Coastguard Worker  * is to make the result comparable to the result of ns_name_map().
851*8d67ca89SAndroid Build Coastguard Worker  */
852*8d67ca89SAndroid Build Coastguard Worker int
ns_name_labels(ns_nname_ct nname,size_t namesiz)853*8d67ca89SAndroid Build Coastguard Worker ns_name_labels(ns_nname_ct nname, size_t namesiz) {
854*8d67ca89SAndroid Build Coastguard Worker 	int ret = 0;
855*8d67ca89SAndroid Build Coastguard Worker 	u_int n;
856*8d67ca89SAndroid Build Coastguard Worker 
857*8d67ca89SAndroid Build Coastguard Worker 	while (namesiz-- > 0 && (n = *nname++) != 0) {
858*8d67ca89SAndroid Build Coastguard Worker 		if ((n & NS_CMPRSFLGS) != 0) {
859*8d67ca89SAndroid Build Coastguard Worker 			errno = EISDIR;
860*8d67ca89SAndroid Build Coastguard Worker 			return (-1);
861*8d67ca89SAndroid Build Coastguard Worker 		}
862*8d67ca89SAndroid Build Coastguard Worker 		if (n > namesiz) {
863*8d67ca89SAndroid Build Coastguard Worker 			errno = EMSGSIZE;
864*8d67ca89SAndroid Build Coastguard Worker 			return (-1);
865*8d67ca89SAndroid Build Coastguard Worker 		}
866*8d67ca89SAndroid Build Coastguard Worker 		nname += n;
867*8d67ca89SAndroid Build Coastguard Worker 		namesiz -= n;
868*8d67ca89SAndroid Build Coastguard Worker 		ret++;
869*8d67ca89SAndroid Build Coastguard Worker 	}
870*8d67ca89SAndroid Build Coastguard Worker 	return (ret + 1);
871*8d67ca89SAndroid Build Coastguard Worker }
872*8d67ca89SAndroid Build Coastguard Worker /* Private. */
873*8d67ca89SAndroid Build Coastguard Worker 
874*8d67ca89SAndroid Build Coastguard Worker /*
875*8d67ca89SAndroid Build Coastguard Worker  *	Thinking in noninternationalized USASCII (per the DNS spec),
876*8d67ca89SAndroid Build Coastguard Worker  *	is this characted special ("in need of quoting") ?
877*8d67ca89SAndroid Build Coastguard Worker  *
878*8d67ca89SAndroid Build Coastguard Worker  * return:
879*8d67ca89SAndroid Build Coastguard Worker  *	boolean.
880*8d67ca89SAndroid Build Coastguard Worker  */
881*8d67ca89SAndroid Build Coastguard Worker static int
special(int ch)882*8d67ca89SAndroid Build Coastguard Worker special(int ch) {
883*8d67ca89SAndroid Build Coastguard Worker 	switch (ch) {
884*8d67ca89SAndroid Build Coastguard Worker 	case 0x22: /* '"' */
885*8d67ca89SAndroid Build Coastguard Worker 	case 0x2E: /* '.' */
886*8d67ca89SAndroid Build Coastguard Worker 	case 0x3B: /* ';' */
887*8d67ca89SAndroid Build Coastguard Worker 	case 0x5C: /* '\\' */
888*8d67ca89SAndroid Build Coastguard Worker 	case 0x28: /* '(' */
889*8d67ca89SAndroid Build Coastguard Worker 	case 0x29: /* ')' */
890*8d67ca89SAndroid Build Coastguard Worker 	/* Special modifiers in zone files. */
891*8d67ca89SAndroid Build Coastguard Worker 	case 0x40: /* '@' */
892*8d67ca89SAndroid Build Coastguard Worker 	case 0x24: /* '$' */
893*8d67ca89SAndroid Build Coastguard Worker 		return (1);
894*8d67ca89SAndroid Build Coastguard Worker 	default:
895*8d67ca89SAndroid Build Coastguard Worker 		return (0);
896*8d67ca89SAndroid Build Coastguard Worker 	}
897*8d67ca89SAndroid Build Coastguard Worker }
898*8d67ca89SAndroid Build Coastguard Worker 
899*8d67ca89SAndroid Build Coastguard Worker /*
900*8d67ca89SAndroid Build Coastguard Worker  *	Thinking in noninternationalized USASCII (per the DNS spec),
901*8d67ca89SAndroid Build Coastguard Worker  *	is this character visible and not a space when printed ?
902*8d67ca89SAndroid Build Coastguard Worker  *
903*8d67ca89SAndroid Build Coastguard Worker  * return:
904*8d67ca89SAndroid Build Coastguard Worker  *	boolean.
905*8d67ca89SAndroid Build Coastguard Worker  */
906*8d67ca89SAndroid Build Coastguard Worker static int
printable(int ch)907*8d67ca89SAndroid Build Coastguard Worker printable(int ch) {
908*8d67ca89SAndroid Build Coastguard Worker 	return (ch > 0x20 && ch < 0x7f);
909*8d67ca89SAndroid Build Coastguard Worker }
910*8d67ca89SAndroid Build Coastguard Worker 
911*8d67ca89SAndroid Build Coastguard Worker /*
912*8d67ca89SAndroid Build Coastguard Worker  *	Thinking in noninternationalized USASCII (per the DNS spec),
913*8d67ca89SAndroid Build Coastguard Worker  *	convert this character to lower case if it's upper case.
914*8d67ca89SAndroid Build Coastguard Worker  */
915*8d67ca89SAndroid Build Coastguard Worker static int
mklower(int ch)916*8d67ca89SAndroid Build Coastguard Worker mklower(int ch) {
917*8d67ca89SAndroid Build Coastguard Worker 	if (ch >= 0x41 && ch <= 0x5A)
918*8d67ca89SAndroid Build Coastguard Worker 		return (ch + 0x20);
919*8d67ca89SAndroid Build Coastguard Worker 	return (ch);
920*8d67ca89SAndroid Build Coastguard Worker }
921*8d67ca89SAndroid Build Coastguard Worker 
922*8d67ca89SAndroid Build Coastguard Worker /*
923*8d67ca89SAndroid Build Coastguard Worker  *	Search for the counted-label name in an array of compressed names.
924*8d67ca89SAndroid Build Coastguard Worker  *
925*8d67ca89SAndroid Build Coastguard Worker  * return:
926*8d67ca89SAndroid Build Coastguard Worker  *	offset from msg if found, or -1.
927*8d67ca89SAndroid Build Coastguard Worker  *
928*8d67ca89SAndroid Build Coastguard Worker  * notes:
929*8d67ca89SAndroid Build Coastguard Worker  *	dnptrs is the pointer to the first name on the list,
930*8d67ca89SAndroid Build Coastguard Worker  *	not the pointer to the start of the message.
931*8d67ca89SAndroid Build Coastguard Worker  */
932*8d67ca89SAndroid Build Coastguard Worker static int
dn_find(const u_char * domain,const u_char * msg,const u_char * const * dnptrs,const u_char * const * lastdnptr)933*8d67ca89SAndroid Build Coastguard Worker dn_find(const u_char *domain, const u_char *msg,
934*8d67ca89SAndroid Build Coastguard Worker 	const u_char * const *dnptrs,
935*8d67ca89SAndroid Build Coastguard Worker 	const u_char * const *lastdnptr)
936*8d67ca89SAndroid Build Coastguard Worker {
937*8d67ca89SAndroid Build Coastguard Worker 	const u_char *dn, *cp, *sp;
938*8d67ca89SAndroid Build Coastguard Worker 	const u_char * const *cpp;
939*8d67ca89SAndroid Build Coastguard Worker 	u_int n;
940*8d67ca89SAndroid Build Coastguard Worker 
941*8d67ca89SAndroid Build Coastguard Worker 	for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
942*8d67ca89SAndroid Build Coastguard Worker 		sp = *cpp;
943*8d67ca89SAndroid Build Coastguard Worker 		/*
944*8d67ca89SAndroid Build Coastguard Worker 		 * terminate search on:
945*8d67ca89SAndroid Build Coastguard Worker 		 * root label
946*8d67ca89SAndroid Build Coastguard Worker 		 * compression pointer
947*8d67ca89SAndroid Build Coastguard Worker 		 * unusable offset
948*8d67ca89SAndroid Build Coastguard Worker 		 */
949*8d67ca89SAndroid Build Coastguard Worker 		while (*sp != 0 && (*sp & NS_CMPRSFLGS) == 0 &&
950*8d67ca89SAndroid Build Coastguard Worker 		       (sp - msg) < 0x4000) {
951*8d67ca89SAndroid Build Coastguard Worker 			dn = domain;
952*8d67ca89SAndroid Build Coastguard Worker 			cp = sp;
953*8d67ca89SAndroid Build Coastguard Worker 			while ((n = *cp++) != 0) {
954*8d67ca89SAndroid Build Coastguard Worker 				/*
955*8d67ca89SAndroid Build Coastguard Worker 				 * check for indirection
956*8d67ca89SAndroid Build Coastguard Worker 				 */
957*8d67ca89SAndroid Build Coastguard Worker 				switch (n & NS_CMPRSFLGS) {
958*8d67ca89SAndroid Build Coastguard Worker 				case 0:		/* normal case, n == len */
959*8d67ca89SAndroid Build Coastguard Worker 					n = labellen(cp - 1); /* XXX */
960*8d67ca89SAndroid Build Coastguard Worker 
961*8d67ca89SAndroid Build Coastguard Worker 					if (n != *dn++)
962*8d67ca89SAndroid Build Coastguard Worker 						goto next;
963*8d67ca89SAndroid Build Coastguard Worker 
964*8d67ca89SAndroid Build Coastguard Worker 					for (; n > 0; n--)
965*8d67ca89SAndroid Build Coastguard Worker 						if (mklower(*dn++) !=
966*8d67ca89SAndroid Build Coastguard Worker 						    mklower(*cp++))
967*8d67ca89SAndroid Build Coastguard Worker 							goto next;
968*8d67ca89SAndroid Build Coastguard Worker 					/* Is next root for both ? */
969*8d67ca89SAndroid Build Coastguard Worker 					if (*dn == '\0' && *cp == '\0') {
970*8d67ca89SAndroid Build Coastguard Worker 						_DIAGASSERT(__type_fit(int,
971*8d67ca89SAndroid Build Coastguard Worker 						    sp - msg));
972*8d67ca89SAndroid Build Coastguard Worker 						return (int)(sp - msg);
973*8d67ca89SAndroid Build Coastguard Worker 					}
974*8d67ca89SAndroid Build Coastguard Worker 					if (*dn)
975*8d67ca89SAndroid Build Coastguard Worker 						continue;
976*8d67ca89SAndroid Build Coastguard Worker 					goto next;
977*8d67ca89SAndroid Build Coastguard Worker 				case NS_CMPRSFLGS:	/* indirection */
978*8d67ca89SAndroid Build Coastguard Worker 					cp = msg + (((n & 0x3f) << 8) | *cp);
979*8d67ca89SAndroid Build Coastguard Worker 					break;
980*8d67ca89SAndroid Build Coastguard Worker 
981*8d67ca89SAndroid Build Coastguard Worker 				default:	/* illegal type */
982*8d67ca89SAndroid Build Coastguard Worker 					errno = EMSGSIZE;
983*8d67ca89SAndroid Build Coastguard Worker 					return (-1);
984*8d67ca89SAndroid Build Coastguard Worker 				}
985*8d67ca89SAndroid Build Coastguard Worker 			}
986*8d67ca89SAndroid Build Coastguard Worker  next: ;
987*8d67ca89SAndroid Build Coastguard Worker 			sp += *sp + 1;
988*8d67ca89SAndroid Build Coastguard Worker 		}
989*8d67ca89SAndroid Build Coastguard Worker 	}
990*8d67ca89SAndroid Build Coastguard Worker 	errno = ENOENT;
991*8d67ca89SAndroid Build Coastguard Worker 	return (-1);
992*8d67ca89SAndroid Build Coastguard Worker }
993*8d67ca89SAndroid Build Coastguard Worker 
994*8d67ca89SAndroid Build Coastguard Worker static int
decode_bitstring(const unsigned char ** cpp,char * dn,const char * eom)995*8d67ca89SAndroid Build Coastguard Worker decode_bitstring(const unsigned char **cpp, char *dn, const char *eom)
996*8d67ca89SAndroid Build Coastguard Worker {
997*8d67ca89SAndroid Build Coastguard Worker 	const unsigned char *cp = *cpp;
998*8d67ca89SAndroid Build Coastguard Worker 	char *beg = dn, tc;
999*8d67ca89SAndroid Build Coastguard Worker 	int b, blen, plen, i;
1000*8d67ca89SAndroid Build Coastguard Worker 
1001*8d67ca89SAndroid Build Coastguard Worker 	if ((blen = (*cp & 0xff)) == 0)
1002*8d67ca89SAndroid Build Coastguard Worker 		blen = 256;
1003*8d67ca89SAndroid Build Coastguard Worker 	plen = (blen + 3) / 4;
1004*8d67ca89SAndroid Build Coastguard Worker 	plen += (int)sizeof("\\[x/]") + (blen > 99 ? 3 : (blen > 9) ? 2 : 1);
1005*8d67ca89SAndroid Build Coastguard Worker 	if (dn + plen >= eom)
1006*8d67ca89SAndroid Build Coastguard Worker 		return(-1);
1007*8d67ca89SAndroid Build Coastguard Worker 
1008*8d67ca89SAndroid Build Coastguard Worker 	cp++;
1009*8d67ca89SAndroid Build Coastguard Worker 	i = snprintf(dn, eom - dn, "\\[x");
1010*8d67ca89SAndroid Build Coastguard Worker 	if (i < 0)
1011*8d67ca89SAndroid Build Coastguard Worker 		return (-1);
1012*8d67ca89SAndroid Build Coastguard Worker 	dn += i;
1013*8d67ca89SAndroid Build Coastguard Worker 	for (b = blen; b > 7; b -= 8, cp++) {
1014*8d67ca89SAndroid Build Coastguard Worker 		i = snprintf(dn, eom - dn, "%02x", *cp & 0xff);
1015*8d67ca89SAndroid Build Coastguard Worker 		if (i < 0)
1016*8d67ca89SAndroid Build Coastguard Worker 			return (-1);
1017*8d67ca89SAndroid Build Coastguard Worker 		dn += i;
1018*8d67ca89SAndroid Build Coastguard Worker 	}
1019*8d67ca89SAndroid Build Coastguard Worker 	if (b > 4) {
1020*8d67ca89SAndroid Build Coastguard Worker 		tc = *cp++;
1021*8d67ca89SAndroid Build Coastguard Worker 		i = snprintf(dn, eom - dn, "%02x", tc & (0xff << (8 - b)));
1022*8d67ca89SAndroid Build Coastguard Worker 		if (i < 0)
1023*8d67ca89SAndroid Build Coastguard Worker 			return (-1);
1024*8d67ca89SAndroid Build Coastguard Worker 		dn += i;
1025*8d67ca89SAndroid Build Coastguard Worker 	} else if (b > 0) {
1026*8d67ca89SAndroid Build Coastguard Worker 		tc = *cp++;
1027*8d67ca89SAndroid Build Coastguard Worker 		i = snprintf(dn, eom - dn, "%1x",
1028*8d67ca89SAndroid Build Coastguard Worker 			       (((u_int32_t)tc >> 4) & 0x0f) & (0x0f << (4 - b)));
1029*8d67ca89SAndroid Build Coastguard Worker 		if (i < 0)
1030*8d67ca89SAndroid Build Coastguard Worker 			return (-1);
1031*8d67ca89SAndroid Build Coastguard Worker 		dn += i;
1032*8d67ca89SAndroid Build Coastguard Worker 	}
1033*8d67ca89SAndroid Build Coastguard Worker 	i = snprintf(dn, eom - dn, "/%d]", blen);
1034*8d67ca89SAndroid Build Coastguard Worker 	if (i < 0)
1035*8d67ca89SAndroid Build Coastguard Worker 		return (-1);
1036*8d67ca89SAndroid Build Coastguard Worker 	dn += i;
1037*8d67ca89SAndroid Build Coastguard Worker 
1038*8d67ca89SAndroid Build Coastguard Worker 	*cpp = cp;
1039*8d67ca89SAndroid Build Coastguard Worker 	_DIAGASSERT(__type_fit(int, dn - beg));
1040*8d67ca89SAndroid Build Coastguard Worker 	return (int)(dn - beg);
1041*8d67ca89SAndroid Build Coastguard Worker }
1042*8d67ca89SAndroid Build Coastguard Worker 
1043*8d67ca89SAndroid Build Coastguard Worker static int
encode_bitsring(const char ** bp,const char * end,unsigned char ** labelp,unsigned char ** dst,unsigned const char * eom)1044*8d67ca89SAndroid Build Coastguard Worker encode_bitsring(const char **bp, const char *end, unsigned char **labelp,
1045*8d67ca89SAndroid Build Coastguard Worker 	        unsigned char ** dst, unsigned const char *eom)
1046*8d67ca89SAndroid Build Coastguard Worker {
1047*8d67ca89SAndroid Build Coastguard Worker 	int afterslash = 0;
1048*8d67ca89SAndroid Build Coastguard Worker 	const char *cp = *bp;
1049*8d67ca89SAndroid Build Coastguard Worker 	unsigned char *tp;
1050*8d67ca89SAndroid Build Coastguard Worker 	char c;
1051*8d67ca89SAndroid Build Coastguard Worker 	const char *beg_blen;
1052*8d67ca89SAndroid Build Coastguard Worker 	char *end_blen = NULL;
1053*8d67ca89SAndroid Build Coastguard Worker 	int value = 0, count = 0, tbcount = 0, blen = 0;
1054*8d67ca89SAndroid Build Coastguard Worker 
1055*8d67ca89SAndroid Build Coastguard Worker 	beg_blen = end_blen = NULL;
1056*8d67ca89SAndroid Build Coastguard Worker 
1057*8d67ca89SAndroid Build Coastguard Worker 	/* a bitstring must contain at least 2 characters */
1058*8d67ca89SAndroid Build Coastguard Worker 	if (end - cp < 2)
1059*8d67ca89SAndroid Build Coastguard Worker 		return(EINVAL);
1060*8d67ca89SAndroid Build Coastguard Worker 
1061*8d67ca89SAndroid Build Coastguard Worker 	/* XXX: currently, only hex strings are supported */
1062*8d67ca89SAndroid Build Coastguard Worker 	if (*cp++ != 'x')
1063*8d67ca89SAndroid Build Coastguard Worker 		return(EINVAL);
1064*8d67ca89SAndroid Build Coastguard Worker 	if (!isxdigit((*cp) & 0xff)) /* reject '\[x/BLEN]' */
1065*8d67ca89SAndroid Build Coastguard Worker 		return(EINVAL);
1066*8d67ca89SAndroid Build Coastguard Worker 
1067*8d67ca89SAndroid Build Coastguard Worker 	for (tp = *dst + 1; cp < end && tp < eom; cp++) {
1068*8d67ca89SAndroid Build Coastguard Worker 		switch((c = *cp)) {
1069*8d67ca89SAndroid Build Coastguard Worker 		case ']':	/* end of the bitstring */
1070*8d67ca89SAndroid Build Coastguard Worker 			if (afterslash) {
1071*8d67ca89SAndroid Build Coastguard Worker 				if (beg_blen == NULL)
1072*8d67ca89SAndroid Build Coastguard Worker 					return(EINVAL);
1073*8d67ca89SAndroid Build Coastguard Worker 				blen = (int)strtol(beg_blen, &end_blen, 10);
1074*8d67ca89SAndroid Build Coastguard Worker 				if (*end_blen != ']')
1075*8d67ca89SAndroid Build Coastguard Worker 					return(EINVAL);
1076*8d67ca89SAndroid Build Coastguard Worker 			}
1077*8d67ca89SAndroid Build Coastguard Worker 			if (count)
1078*8d67ca89SAndroid Build Coastguard Worker 				*tp++ = ((value << 4) & 0xff);
1079*8d67ca89SAndroid Build Coastguard Worker 			cp++;	/* skip ']' */
1080*8d67ca89SAndroid Build Coastguard Worker 			goto done;
1081*8d67ca89SAndroid Build Coastguard Worker 		case '/':
1082*8d67ca89SAndroid Build Coastguard Worker 			afterslash = 1;
1083*8d67ca89SAndroid Build Coastguard Worker 			break;
1084*8d67ca89SAndroid Build Coastguard Worker 		default:
1085*8d67ca89SAndroid Build Coastguard Worker 			if (afterslash) {
1086*8d67ca89SAndroid Build Coastguard Worker 				if (!isdigit(c&0xff))
1087*8d67ca89SAndroid Build Coastguard Worker 					return(EINVAL);
1088*8d67ca89SAndroid Build Coastguard Worker 				if (beg_blen == NULL) {
1089*8d67ca89SAndroid Build Coastguard Worker 
1090*8d67ca89SAndroid Build Coastguard Worker 					if (c == '0') {
1091*8d67ca89SAndroid Build Coastguard Worker 						/* blen never begings with 0 */
1092*8d67ca89SAndroid Build Coastguard Worker 						return(EINVAL);
1093*8d67ca89SAndroid Build Coastguard Worker 					}
1094*8d67ca89SAndroid Build Coastguard Worker 					beg_blen = cp;
1095*8d67ca89SAndroid Build Coastguard Worker 				}
1096*8d67ca89SAndroid Build Coastguard Worker 			} else {
1097*8d67ca89SAndroid Build Coastguard Worker 				if (!isxdigit(c&0xff))
1098*8d67ca89SAndroid Build Coastguard Worker 					return(EINVAL);
1099*8d67ca89SAndroid Build Coastguard Worker 				value <<= 4;
1100*8d67ca89SAndroid Build Coastguard Worker 				value += digitvalue[(int)c];
1101*8d67ca89SAndroid Build Coastguard Worker 				count += 4;
1102*8d67ca89SAndroid Build Coastguard Worker 				tbcount += 4;
1103*8d67ca89SAndroid Build Coastguard Worker 				if (tbcount > 256)
1104*8d67ca89SAndroid Build Coastguard Worker 					return(EINVAL);
1105*8d67ca89SAndroid Build Coastguard Worker 				if (count == 8) {
1106*8d67ca89SAndroid Build Coastguard Worker 					*tp++ = value;
1107*8d67ca89SAndroid Build Coastguard Worker 					count = 0;
1108*8d67ca89SAndroid Build Coastguard Worker 				}
1109*8d67ca89SAndroid Build Coastguard Worker 			}
1110*8d67ca89SAndroid Build Coastguard Worker 			break;
1111*8d67ca89SAndroid Build Coastguard Worker 		}
1112*8d67ca89SAndroid Build Coastguard Worker 	}
1113*8d67ca89SAndroid Build Coastguard Worker   done:
1114*8d67ca89SAndroid Build Coastguard Worker 	if (cp >= end || tp >= eom)
1115*8d67ca89SAndroid Build Coastguard Worker 		return(EMSGSIZE);
1116*8d67ca89SAndroid Build Coastguard Worker 
1117*8d67ca89SAndroid Build Coastguard Worker 	/*
1118*8d67ca89SAndroid Build Coastguard Worker 	 * bit length validation:
1119*8d67ca89SAndroid Build Coastguard Worker 	 * If a <length> is present, the number of digits in the <bit-data>
1120*8d67ca89SAndroid Build Coastguard Worker 	 * MUST be just sufficient to contain the number of bits specified
1121*8d67ca89SAndroid Build Coastguard Worker 	 * by the <length>. If there are insignificant bits in a final
1122*8d67ca89SAndroid Build Coastguard Worker 	 * hexadecimal or octal digit, they MUST be zero.
1123*8d67ca89SAndroid Build Coastguard Worker 	 * RFC 2673, Section 3.2.
1124*8d67ca89SAndroid Build Coastguard Worker 	 */
1125*8d67ca89SAndroid Build Coastguard Worker 	if (blen > 0) {
1126*8d67ca89SAndroid Build Coastguard Worker 		int traillen;
1127*8d67ca89SAndroid Build Coastguard Worker 
1128*8d67ca89SAndroid Build Coastguard Worker 		if (((blen + 3) & ~3) != tbcount)
1129*8d67ca89SAndroid Build Coastguard Worker 			return(EINVAL);
1130*8d67ca89SAndroid Build Coastguard Worker 		traillen = tbcount - blen; /* between 0 and 3 */
1131*8d67ca89SAndroid Build Coastguard Worker 		if (((value << (8 - traillen)) & 0xff) != 0)
1132*8d67ca89SAndroid Build Coastguard Worker 			return(EINVAL);
1133*8d67ca89SAndroid Build Coastguard Worker 	}
1134*8d67ca89SAndroid Build Coastguard Worker 	else
1135*8d67ca89SAndroid Build Coastguard Worker 		blen = tbcount;
1136*8d67ca89SAndroid Build Coastguard Worker 	if (blen == 256)
1137*8d67ca89SAndroid Build Coastguard Worker 		blen = 0;
1138*8d67ca89SAndroid Build Coastguard Worker 
1139*8d67ca89SAndroid Build Coastguard Worker 	/* encode the type and the significant bit fields */
1140*8d67ca89SAndroid Build Coastguard Worker 	**labelp = DNS_LABELTYPE_BITSTRING;
1141*8d67ca89SAndroid Build Coastguard Worker 	**dst = blen;
1142*8d67ca89SAndroid Build Coastguard Worker 
1143*8d67ca89SAndroid Build Coastguard Worker 	*bp = cp;
1144*8d67ca89SAndroid Build Coastguard Worker 	*dst = tp;
1145*8d67ca89SAndroid Build Coastguard Worker 
1146*8d67ca89SAndroid Build Coastguard Worker 	return(0);
1147*8d67ca89SAndroid Build Coastguard Worker }
1148*8d67ca89SAndroid Build Coastguard Worker 
1149*8d67ca89SAndroid Build Coastguard Worker static int
labellen(const u_char * lp)1150*8d67ca89SAndroid Build Coastguard Worker labellen(const u_char *lp)
1151*8d67ca89SAndroid Build Coastguard Worker {
1152*8d67ca89SAndroid Build Coastguard Worker 	int bitlen;
1153*8d67ca89SAndroid Build Coastguard Worker 	u_char l = *lp;
1154*8d67ca89SAndroid Build Coastguard Worker 
1155*8d67ca89SAndroid Build Coastguard Worker 	if ((l & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
1156*8d67ca89SAndroid Build Coastguard Worker 		/* should be avoided by the caller */
1157*8d67ca89SAndroid Build Coastguard Worker 		return(-1);
1158*8d67ca89SAndroid Build Coastguard Worker 	}
1159*8d67ca89SAndroid Build Coastguard Worker 
1160*8d67ca89SAndroid Build Coastguard Worker 	if ((l & NS_CMPRSFLGS) == NS_TYPE_ELT) {
1161*8d67ca89SAndroid Build Coastguard Worker 		if (l == DNS_LABELTYPE_BITSTRING) {
1162*8d67ca89SAndroid Build Coastguard Worker 			if ((bitlen = *(lp + 1)) == 0)
1163*8d67ca89SAndroid Build Coastguard Worker 				bitlen = 256;
1164*8d67ca89SAndroid Build Coastguard Worker 			return((bitlen + 7 ) / 8 + 1);
1165*8d67ca89SAndroid Build Coastguard Worker 		}
1166*8d67ca89SAndroid Build Coastguard Worker 		return(-1);	/* unknwon ELT */
1167*8d67ca89SAndroid Build Coastguard Worker 	}
1168*8d67ca89SAndroid Build Coastguard Worker 	return(l);
1169*8d67ca89SAndroid Build Coastguard Worker }
1170