xref: /minix/external/bsd/dhcp/dist/common/ns_name.c (revision 83ee113e)
1*83ee113eSDavid van Moolenbroek /*	$NetBSD: ns_name.c,v 1.7 2014/07/12 12:09:37 spz Exp $	*/
2*83ee113eSDavid van Moolenbroek /*
3*83ee113eSDavid van Moolenbroek  * Copyright (c) 2004,2009 by Internet Systems Consortium, Inc. ("ISC")
4*83ee113eSDavid van Moolenbroek  * Copyright (c) 1996-2003 by Internet Software Consortium
5*83ee113eSDavid van Moolenbroek  *
6*83ee113eSDavid van Moolenbroek  * Permission to use, copy, modify, and distribute this software for any
7*83ee113eSDavid van Moolenbroek  * purpose with or without fee is hereby granted, provided that the above
8*83ee113eSDavid van Moolenbroek  * copyright notice and this permission notice appear in all copies.
9*83ee113eSDavid van Moolenbroek  *
10*83ee113eSDavid van Moolenbroek  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
11*83ee113eSDavid van Moolenbroek  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12*83ee113eSDavid van Moolenbroek  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
13*83ee113eSDavid van Moolenbroek  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14*83ee113eSDavid van Moolenbroek  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15*83ee113eSDavid van Moolenbroek  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
16*83ee113eSDavid van Moolenbroek  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*83ee113eSDavid van Moolenbroek  *
18*83ee113eSDavid van Moolenbroek  *   Internet Systems Consortium, Inc.
19*83ee113eSDavid van Moolenbroek  *   950 Charter Street
20*83ee113eSDavid van Moolenbroek  *   Redwood City, CA 94063
21*83ee113eSDavid van Moolenbroek  *   <info@isc.org>
22*83ee113eSDavid van Moolenbroek  *   http://www.isc.org/
23*83ee113eSDavid van Moolenbroek  */
24*83ee113eSDavid van Moolenbroek 
25*83ee113eSDavid van Moolenbroek #include <sys/cdefs.h>
26*83ee113eSDavid van Moolenbroek __RCSID("$NetBSD: ns_name.c,v 1.7 2014/07/12 12:09:37 spz Exp $");
27*83ee113eSDavid van Moolenbroek 
28*83ee113eSDavid van Moolenbroek #ifndef lint
29*83ee113eSDavid van Moolenbroek static const char rcsid[] = "Id: ns_name.c,v 1.2 2009/10/28 04:12:29 sar Exp ";
30*83ee113eSDavid van Moolenbroek #endif
31*83ee113eSDavid van Moolenbroek 
32*83ee113eSDavid van Moolenbroek #include <sys/types.h>
33*83ee113eSDavid van Moolenbroek 
34*83ee113eSDavid van Moolenbroek #include <netinet/in.h>
35*83ee113eSDavid van Moolenbroek #include <sys/socket.h>
36*83ee113eSDavid van Moolenbroek 
37*83ee113eSDavid van Moolenbroek #include <errno.h>
38*83ee113eSDavid van Moolenbroek #include <string.h>
39*83ee113eSDavid van Moolenbroek #include <ctype.h>
40*83ee113eSDavid van Moolenbroek 
41*83ee113eSDavid van Moolenbroek #include "minires.h"
42*83ee113eSDavid van Moolenbroek #include "arpa/nameser.h"
43*83ee113eSDavid van Moolenbroek 
44*83ee113eSDavid van Moolenbroek /* Data. */
45*83ee113eSDavid van Moolenbroek 
46*83ee113eSDavid van Moolenbroek static const char	digits[] = "0123456789";
47*83ee113eSDavid van Moolenbroek 
48*83ee113eSDavid van Moolenbroek /* Forward. */
49*83ee113eSDavid van Moolenbroek 
50*83ee113eSDavid van Moolenbroek static int		special(int);
51*83ee113eSDavid van Moolenbroek static int		printable(int);
52*83ee113eSDavid van Moolenbroek static int		dn_find(const u_char *, const u_char *,
53*83ee113eSDavid van Moolenbroek 				const u_char * const *,
54*83ee113eSDavid van Moolenbroek 				const u_char * const *);
55*83ee113eSDavid van Moolenbroek 
56*83ee113eSDavid van Moolenbroek /* Public. */
57*83ee113eSDavid van Moolenbroek 
58*83ee113eSDavid van Moolenbroek /*
59*83ee113eSDavid van Moolenbroek  * MRns_name_ntop(src, dst, dstsiz)
60*83ee113eSDavid van Moolenbroek  *	Convert an encoded domain name to printable ascii as per RFC1035.
61*83ee113eSDavid van Moolenbroek  * return:
62*83ee113eSDavid van Moolenbroek  *	Number of bytes written to buffer, or -1 (with errno set)
63*83ee113eSDavid van Moolenbroek  * notes:
64*83ee113eSDavid van Moolenbroek  *	The root is returned as "."
65*83ee113eSDavid van Moolenbroek  *	All other domains are returned in non absolute form
66*83ee113eSDavid van Moolenbroek  */
67*83ee113eSDavid van Moolenbroek int
MRns_name_ntop(const u_char * src,char * dst,size_t dstsiz)68*83ee113eSDavid van Moolenbroek MRns_name_ntop(const u_char *src, char *dst, size_t dstsiz) {
69*83ee113eSDavid van Moolenbroek 	const u_char *cp;
70*83ee113eSDavid van Moolenbroek 	char *dn, *eom;
71*83ee113eSDavid van Moolenbroek 	u_char c;
72*83ee113eSDavid van Moolenbroek 	u_int n;
73*83ee113eSDavid van Moolenbroek 
74*83ee113eSDavid van Moolenbroek 	cp = src;
75*83ee113eSDavid van Moolenbroek 	dn = dst;
76*83ee113eSDavid van Moolenbroek 	eom = dst + dstsiz;
77*83ee113eSDavid van Moolenbroek 
78*83ee113eSDavid van Moolenbroek 	while ((n = *cp++) != 0) {
79*83ee113eSDavid van Moolenbroek 		if ((n & NS_CMPRSFLGS) != 0) {
80*83ee113eSDavid van Moolenbroek 			/* Some kind of compression pointer. */
81*83ee113eSDavid van Moolenbroek 			errno = EMSGSIZE;
82*83ee113eSDavid van Moolenbroek 			return (-1);
83*83ee113eSDavid van Moolenbroek 		}
84*83ee113eSDavid van Moolenbroek 		if (dn != dst) {
85*83ee113eSDavid van Moolenbroek 			if (dn >= eom) {
86*83ee113eSDavid van Moolenbroek 				errno = EMSGSIZE;
87*83ee113eSDavid van Moolenbroek 				return (-1);
88*83ee113eSDavid van Moolenbroek 			}
89*83ee113eSDavid van Moolenbroek 			*dn++ = '.';
90*83ee113eSDavid van Moolenbroek 		}
91*83ee113eSDavid van Moolenbroek 		if (dn + n >= eom) {
92*83ee113eSDavid van Moolenbroek 			errno = EMSGSIZE;
93*83ee113eSDavid van Moolenbroek 			return (-1);
94*83ee113eSDavid van Moolenbroek 		}
95*83ee113eSDavid van Moolenbroek 		for ((void)NULL; n > 0; n--) {
96*83ee113eSDavid van Moolenbroek 			c = *cp++;
97*83ee113eSDavid van Moolenbroek 			if (special(c)) {
98*83ee113eSDavid van Moolenbroek 				if (dn + 1 >= eom) {
99*83ee113eSDavid van Moolenbroek 					errno = EMSGSIZE;
100*83ee113eSDavid van Moolenbroek 					return (-1);
101*83ee113eSDavid van Moolenbroek 				}
102*83ee113eSDavid van Moolenbroek 				*dn++ = '\\';
103*83ee113eSDavid van Moolenbroek 				*dn++ = (char)c;
104*83ee113eSDavid van Moolenbroek 			} else if (!printable(c)) {
105*83ee113eSDavid van Moolenbroek 				if (dn + 3 >= eom) {
106*83ee113eSDavid van Moolenbroek 					errno = EMSGSIZE;
107*83ee113eSDavid van Moolenbroek 					return (-1);
108*83ee113eSDavid van Moolenbroek 				}
109*83ee113eSDavid van Moolenbroek 				*dn++ = '\\';
110*83ee113eSDavid van Moolenbroek 				*dn++ = digits[c / 100];
111*83ee113eSDavid van Moolenbroek 				*dn++ = digits[(c % 100) / 10];
112*83ee113eSDavid van Moolenbroek 				*dn++ = digits[c % 10];
113*83ee113eSDavid van Moolenbroek 			} else {
114*83ee113eSDavid van Moolenbroek 				if (dn >= eom) {
115*83ee113eSDavid van Moolenbroek 					errno = EMSGSIZE;
116*83ee113eSDavid van Moolenbroek 					return (-1);
117*83ee113eSDavid van Moolenbroek 				}
118*83ee113eSDavid van Moolenbroek 				*dn++ = (char)c;
119*83ee113eSDavid van Moolenbroek 			}
120*83ee113eSDavid van Moolenbroek 		}
121*83ee113eSDavid van Moolenbroek 	}
122*83ee113eSDavid van Moolenbroek 	if (dn == dst) {
123*83ee113eSDavid van Moolenbroek 		if (dn >= eom) {
124*83ee113eSDavid van Moolenbroek 			errno = EMSGSIZE;
125*83ee113eSDavid van Moolenbroek 			return (-1);
126*83ee113eSDavid van Moolenbroek 		}
127*83ee113eSDavid van Moolenbroek 		*dn++ = '.';
128*83ee113eSDavid van Moolenbroek 	}
129*83ee113eSDavid van Moolenbroek 	if (dn >= eom) {
130*83ee113eSDavid van Moolenbroek 		errno = EMSGSIZE;
131*83ee113eSDavid van Moolenbroek 		return (-1);
132*83ee113eSDavid van Moolenbroek 	}
133*83ee113eSDavid van Moolenbroek 	*dn++ = '\0';
134*83ee113eSDavid van Moolenbroek 	return (dn - dst);
135*83ee113eSDavid van Moolenbroek }
136*83ee113eSDavid van Moolenbroek 
137*83ee113eSDavid van Moolenbroek /*
138*83ee113eSDavid van Moolenbroek  * MRns_name_pton(src, dst, dstsiz)
139*83ee113eSDavid van Moolenbroek  *	Convert a ascii string into an encoded domain name as per RFC1035.
140*83ee113eSDavid van Moolenbroek  * return:
141*83ee113eSDavid van Moolenbroek  *	-1 if it fails
142*83ee113eSDavid van Moolenbroek  *	1 if string was fully qualified
143*83ee113eSDavid van Moolenbroek  *	0 is string was not fully qualified
144*83ee113eSDavid van Moolenbroek  * notes:
145*83ee113eSDavid van Moolenbroek  *	Enforces label and domain length limits.
146*83ee113eSDavid van Moolenbroek  */
147*83ee113eSDavid van Moolenbroek 
148*83ee113eSDavid van Moolenbroek int
MRns_name_pton(const char * src,u_char * dst,size_t dstsiz)149*83ee113eSDavid van Moolenbroek MRns_name_pton(const char *src, u_char *dst, size_t dstsiz) {
150*83ee113eSDavid van Moolenbroek 	u_char *label, *bp, *eom;
151*83ee113eSDavid van Moolenbroek 	int c, n, escaped;
152*83ee113eSDavid van Moolenbroek 	char *cp;
153*83ee113eSDavid van Moolenbroek 
154*83ee113eSDavid van Moolenbroek 	escaped = 0;
155*83ee113eSDavid van Moolenbroek 	bp = dst;
156*83ee113eSDavid van Moolenbroek 	eom = dst + dstsiz;
157*83ee113eSDavid van Moolenbroek 	label = bp++;
158*83ee113eSDavid van Moolenbroek 
159*83ee113eSDavid van Moolenbroek 	while ((c = *src++) != 0) {
160*83ee113eSDavid van Moolenbroek 		if (escaped) {
161*83ee113eSDavid van Moolenbroek 			if ((cp = strchr(digits, c)) != NULL) {
162*83ee113eSDavid van Moolenbroek 				n = (cp - digits) * 100;
163*83ee113eSDavid van Moolenbroek 				if ((c = *src++) == 0 ||
164*83ee113eSDavid van Moolenbroek 				    (cp = strchr(digits, c)) == NULL) {
165*83ee113eSDavid van Moolenbroek 					errno = EMSGSIZE;
166*83ee113eSDavid van Moolenbroek 					return (-1);
167*83ee113eSDavid van Moolenbroek 				}
168*83ee113eSDavid van Moolenbroek 				n += (cp - digits) * 10;
169*83ee113eSDavid van Moolenbroek 				if ((c = *src++) == 0 ||
170*83ee113eSDavid van Moolenbroek 				    (cp = strchr(digits, c)) == NULL) {
171*83ee113eSDavid van Moolenbroek 					errno = EMSGSIZE;
172*83ee113eSDavid van Moolenbroek 					return (-1);
173*83ee113eSDavid van Moolenbroek 				}
174*83ee113eSDavid van Moolenbroek 				n += (cp - digits);
175*83ee113eSDavid van Moolenbroek 				if (n > 255) {
176*83ee113eSDavid van Moolenbroek 					errno = EMSGSIZE;
177*83ee113eSDavid van Moolenbroek 					return (-1);
178*83ee113eSDavid van Moolenbroek 				}
179*83ee113eSDavid van Moolenbroek 				c = n;
180*83ee113eSDavid van Moolenbroek 			}
181*83ee113eSDavid van Moolenbroek 			escaped = 0;
182*83ee113eSDavid van Moolenbroek 		} else if (c == '\\') {
183*83ee113eSDavid van Moolenbroek 			escaped = 1;
184*83ee113eSDavid van Moolenbroek 			continue;
185*83ee113eSDavid van Moolenbroek 		} else if (c == '.') {
186*83ee113eSDavid van Moolenbroek 			c = (bp - label - 1);
187*83ee113eSDavid van Moolenbroek 			if ((c & NS_CMPRSFLGS) != 0) {	/* Label too big. */
188*83ee113eSDavid van Moolenbroek 				errno = EMSGSIZE;
189*83ee113eSDavid van Moolenbroek 				return (-1);
190*83ee113eSDavid van Moolenbroek 			}
191*83ee113eSDavid van Moolenbroek 			if (label >= eom) {
192*83ee113eSDavid van Moolenbroek 				errno = EMSGSIZE;
193*83ee113eSDavid van Moolenbroek 				return (-1);
194*83ee113eSDavid van Moolenbroek 			}
195*83ee113eSDavid van Moolenbroek 			*label = c;
196*83ee113eSDavid van Moolenbroek 			/* Fully qualified ? */
197*83ee113eSDavid van Moolenbroek 			if (*src == '\0') {
198*83ee113eSDavid van Moolenbroek 				if (c != 0) {
199*83ee113eSDavid van Moolenbroek 					if (bp >= eom) {
200*83ee113eSDavid van Moolenbroek 						errno = EMSGSIZE;
201*83ee113eSDavid van Moolenbroek 						return (-1);
202*83ee113eSDavid van Moolenbroek 					}
203*83ee113eSDavid van Moolenbroek 					*bp++ = '\0';
204*83ee113eSDavid van Moolenbroek 				}
205*83ee113eSDavid van Moolenbroek 				if ((bp - dst) > MAXCDNAME) {
206*83ee113eSDavid van Moolenbroek 					errno = EMSGSIZE;
207*83ee113eSDavid van Moolenbroek 					return (-1);
208*83ee113eSDavid van Moolenbroek 				}
209*83ee113eSDavid van Moolenbroek 				return (1);
210*83ee113eSDavid van Moolenbroek 			}
211*83ee113eSDavid van Moolenbroek 			if (c == 0 || *src == '.') {
212*83ee113eSDavid van Moolenbroek 				errno = EMSGSIZE;
213*83ee113eSDavid van Moolenbroek 				return (-1);
214*83ee113eSDavid van Moolenbroek 			}
215*83ee113eSDavid van Moolenbroek 			label = bp++;
216*83ee113eSDavid van Moolenbroek 			continue;
217*83ee113eSDavid van Moolenbroek 		}
218*83ee113eSDavid van Moolenbroek 		if (bp >= eom) {
219*83ee113eSDavid van Moolenbroek 			errno = EMSGSIZE;
220*83ee113eSDavid van Moolenbroek 			return (-1);
221*83ee113eSDavid van Moolenbroek 		}
222*83ee113eSDavid van Moolenbroek 		*bp++ = (u_char)c;
223*83ee113eSDavid van Moolenbroek 	}
224*83ee113eSDavid van Moolenbroek 	c = (bp - label - 1);
225*83ee113eSDavid van Moolenbroek 	if ((c & NS_CMPRSFLGS) != 0) {		/* Label too big. */
226*83ee113eSDavid van Moolenbroek 		errno = EMSGSIZE;
227*83ee113eSDavid van Moolenbroek 		return (-1);
228*83ee113eSDavid van Moolenbroek 	}
229*83ee113eSDavid van Moolenbroek 	if (label >= eom) {
230*83ee113eSDavid van Moolenbroek 		errno = EMSGSIZE;
231*83ee113eSDavid van Moolenbroek 		return (-1);
232*83ee113eSDavid van Moolenbroek 	}
233*83ee113eSDavid van Moolenbroek 	*label = c;
234*83ee113eSDavid van Moolenbroek 	if (c != 0) {
235*83ee113eSDavid van Moolenbroek 		if (bp >= eom) {
236*83ee113eSDavid van Moolenbroek 			errno = EMSGSIZE;
237*83ee113eSDavid van Moolenbroek 			return (-1);
238*83ee113eSDavid van Moolenbroek 		}
239*83ee113eSDavid van Moolenbroek 		*bp++ = 0;
240*83ee113eSDavid van Moolenbroek 	}
241*83ee113eSDavid van Moolenbroek 	if ((bp - dst) > MAXCDNAME) {	/* src too big */
242*83ee113eSDavid van Moolenbroek 		errno = EMSGSIZE;
243*83ee113eSDavid van Moolenbroek 		return (-1);
244*83ee113eSDavid van Moolenbroek 	}
245*83ee113eSDavid van Moolenbroek 	return (0);
246*83ee113eSDavid van Moolenbroek }
247*83ee113eSDavid van Moolenbroek 
248*83ee113eSDavid van Moolenbroek #ifdef notdef
249*83ee113eSDavid van Moolenbroek /*
250*83ee113eSDavid van Moolenbroek  * MRns_name_ntol(src, dst, dstsiz)
251*83ee113eSDavid van Moolenbroek  *	Convert a network strings labels into all lowercase.
252*83ee113eSDavid van Moolenbroek  * return:
253*83ee113eSDavid van Moolenbroek  *	Number of bytes written to buffer, or -1 (with errno set)
254*83ee113eSDavid van Moolenbroek  * notes:
255*83ee113eSDavid van Moolenbroek  *	Enforces label and domain length limits.
256*83ee113eSDavid van Moolenbroek  */
257*83ee113eSDavid van Moolenbroek 
258*83ee113eSDavid van Moolenbroek int
MRns_name_ntol(const u_char * src,u_char * dst,size_t dstsiz)259*83ee113eSDavid van Moolenbroek MRns_name_ntol(const u_char *src, u_char *dst, size_t dstsiz) {
260*83ee113eSDavid van Moolenbroek 	const u_char *cp;
261*83ee113eSDavid van Moolenbroek 	u_char *dn, *eom;
262*83ee113eSDavid van Moolenbroek 	u_char c;
263*83ee113eSDavid van Moolenbroek 	u_int n;
264*83ee113eSDavid van Moolenbroek 
265*83ee113eSDavid van Moolenbroek 	cp = src;
266*83ee113eSDavid van Moolenbroek 	dn = dst;
267*83ee113eSDavid van Moolenbroek 	eom = dst + dstsiz;
268*83ee113eSDavid van Moolenbroek 
269*83ee113eSDavid van Moolenbroek 	if (dn >= eom) {
270*83ee113eSDavid van Moolenbroek 		errno = EMSGSIZE;
271*83ee113eSDavid van Moolenbroek 		return (-1);
272*83ee113eSDavid van Moolenbroek 	}
273*83ee113eSDavid van Moolenbroek 	while ((n = *cp++) != 0) {
274*83ee113eSDavid van Moolenbroek 		if ((n & NS_CMPRSFLGS) != 0) {
275*83ee113eSDavid van Moolenbroek 			/* Some kind of compression pointer. */
276*83ee113eSDavid van Moolenbroek 			errno = EMSGSIZE;
277*83ee113eSDavid van Moolenbroek 			return (-1);
278*83ee113eSDavid van Moolenbroek 		}
279*83ee113eSDavid van Moolenbroek 		*dn++ = n;
280*83ee113eSDavid van Moolenbroek 		if (dn + n >= eom) {
281*83ee113eSDavid van Moolenbroek 			errno = EMSGSIZE;
282*83ee113eSDavid van Moolenbroek 			return (-1);
283*83ee113eSDavid van Moolenbroek 		}
284*83ee113eSDavid van Moolenbroek 		for ((void)NULL; n > 0; n--) {
285*83ee113eSDavid van Moolenbroek 			c = *cp++;
286*83ee113eSDavid van Moolenbroek 			if (isupper(c))
287*83ee113eSDavid van Moolenbroek 				*dn++ = tolower(c);
288*83ee113eSDavid van Moolenbroek 			else
289*83ee113eSDavid van Moolenbroek 				*dn++ = c;
290*83ee113eSDavid van Moolenbroek 		}
291*83ee113eSDavid van Moolenbroek 	}
292*83ee113eSDavid van Moolenbroek 	*dn++ = '\0';
293*83ee113eSDavid van Moolenbroek 	return (dn - dst);
294*83ee113eSDavid van Moolenbroek }
295*83ee113eSDavid van Moolenbroek #endif
296*83ee113eSDavid van Moolenbroek 
297*83ee113eSDavid van Moolenbroek /*
298*83ee113eSDavid van Moolenbroek  * MRns_name_unpack(msg, eom, src, dst, dstsiz)
299*83ee113eSDavid van Moolenbroek  *	Unpack a domain name from a message, source may be compressed.
300*83ee113eSDavid van Moolenbroek  * return:
301*83ee113eSDavid van Moolenbroek  *	-1 if it fails, or consumed octets if it succeeds.
302*83ee113eSDavid van Moolenbroek  */
303*83ee113eSDavid van Moolenbroek int
MRns_name_unpack(const u_char * msg,const u_char * eom,const u_char * src,u_char * dst,size_t dstsiz)304*83ee113eSDavid van Moolenbroek MRns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src,
305*83ee113eSDavid van Moolenbroek 	         u_char *dst, size_t dstsiz)
306*83ee113eSDavid van Moolenbroek {
307*83ee113eSDavid van Moolenbroek 	const u_char *srcp, *dstlim;
308*83ee113eSDavid van Moolenbroek 	u_char *dstp;
309*83ee113eSDavid van Moolenbroek 	unsigned n;
310*83ee113eSDavid van Moolenbroek 	int len;
311*83ee113eSDavid van Moolenbroek 	int checked;
312*83ee113eSDavid van Moolenbroek 
313*83ee113eSDavid van Moolenbroek 	len = -1;
314*83ee113eSDavid van Moolenbroek 	checked = 0;
315*83ee113eSDavid van Moolenbroek 	dstp = dst;
316*83ee113eSDavid van Moolenbroek 	srcp = src;
317*83ee113eSDavid van Moolenbroek 	dstlim = dst + dstsiz;
318*83ee113eSDavid van Moolenbroek 	if (srcp < msg || srcp >= eom) {
319*83ee113eSDavid van Moolenbroek 		errno = EMSGSIZE;
320*83ee113eSDavid van Moolenbroek 		return (-1);
321*83ee113eSDavid van Moolenbroek 	}
322*83ee113eSDavid van Moolenbroek 	/* Fetch next label in domain name. */
323*83ee113eSDavid van Moolenbroek 	while ((n = *srcp++) != 0) {
324*83ee113eSDavid van Moolenbroek 		/* Check for indirection. */
325*83ee113eSDavid van Moolenbroek 		switch (n & NS_CMPRSFLGS) {
326*83ee113eSDavid van Moolenbroek 		case 0:
327*83ee113eSDavid van Moolenbroek 			/* Limit checks. */
328*83ee113eSDavid van Moolenbroek 			if (dstp + n + 1 >= dstlim || srcp + n >= eom) {
329*83ee113eSDavid van Moolenbroek 				errno = EMSGSIZE;
330*83ee113eSDavid van Moolenbroek 				return (-1);
331*83ee113eSDavid van Moolenbroek 			}
332*83ee113eSDavid van Moolenbroek 			checked += n + 1;
333*83ee113eSDavid van Moolenbroek 			*dstp++ = n;
334*83ee113eSDavid van Moolenbroek 			memcpy(dstp, srcp, n);
335*83ee113eSDavid van Moolenbroek 			dstp += n;
336*83ee113eSDavid van Moolenbroek 			srcp += n;
337*83ee113eSDavid van Moolenbroek 			break;
338*83ee113eSDavid van Moolenbroek 
339*83ee113eSDavid van Moolenbroek 		case NS_CMPRSFLGS:
340*83ee113eSDavid van Moolenbroek 			if (srcp >= eom) {
341*83ee113eSDavid van Moolenbroek 				errno = EMSGSIZE;
342*83ee113eSDavid van Moolenbroek 				return (-1);
343*83ee113eSDavid van Moolenbroek 			}
344*83ee113eSDavid van Moolenbroek 			if (len < 0)
345*83ee113eSDavid van Moolenbroek 				len = srcp - src + 1;
346*83ee113eSDavid van Moolenbroek 			n = ((n & 0x3f) << 8) | (*srcp & 0xff);
347*83ee113eSDavid van Moolenbroek 			if (n >= eom - msg) {  /* Out of range. */
348*83ee113eSDavid van Moolenbroek 				errno = EMSGSIZE;
349*83ee113eSDavid van Moolenbroek 				return (-1);
350*83ee113eSDavid van Moolenbroek 			}
351*83ee113eSDavid van Moolenbroek 			srcp = msg + n;
352*83ee113eSDavid van Moolenbroek 			checked += 2;
353*83ee113eSDavid van Moolenbroek 			/*
354*83ee113eSDavid van Moolenbroek 			 * Check for loops in the compressed name;
355*83ee113eSDavid van Moolenbroek 			 * if we've looked at the whole message,
356*83ee113eSDavid van Moolenbroek 			 * there must be a loop.
357*83ee113eSDavid van Moolenbroek 			 */
358*83ee113eSDavid van Moolenbroek 			if (checked >= eom - msg) {
359*83ee113eSDavid van Moolenbroek 				errno = EMSGSIZE;
360*83ee113eSDavid van Moolenbroek 				return (-1);
361*83ee113eSDavid van Moolenbroek 			}
362*83ee113eSDavid van Moolenbroek 			break;
363*83ee113eSDavid van Moolenbroek 
364*83ee113eSDavid van Moolenbroek 		default:
365*83ee113eSDavid van Moolenbroek 			errno = EMSGSIZE;
366*83ee113eSDavid van Moolenbroek 			return (-1);			/* flag error */
367*83ee113eSDavid van Moolenbroek 		}
368*83ee113eSDavid van Moolenbroek 	}
369*83ee113eSDavid van Moolenbroek 	*dstp = '\0';
370*83ee113eSDavid van Moolenbroek 	if (len < 0)
371*83ee113eSDavid van Moolenbroek 		len = srcp - src;
372*83ee113eSDavid van Moolenbroek 	return (len);
373*83ee113eSDavid van Moolenbroek }
374*83ee113eSDavid van Moolenbroek 
375*83ee113eSDavid van Moolenbroek /*
376*83ee113eSDavid van Moolenbroek  * MRns_name_pack(src, dst, dstsiz, dnptrs, lastdnptr)
377*83ee113eSDavid van Moolenbroek  *	Pack domain name 'domain' into 'comp_dn'.
378*83ee113eSDavid van Moolenbroek  * return:
379*83ee113eSDavid van Moolenbroek  *	Size of the compressed name, or -1.
380*83ee113eSDavid van Moolenbroek  * notes:
381*83ee113eSDavid van Moolenbroek  *	'dnptrs' is an array of pointers to previous compressed names.
382*83ee113eSDavid van Moolenbroek  *	dnptrs[0] is a pointer to the beginning of the message. The array
383*83ee113eSDavid van Moolenbroek  *	ends with NULL.
384*83ee113eSDavid van Moolenbroek  *	'lastdnptr' is a pointer to the end of the array pointed to
385*83ee113eSDavid van Moolenbroek  *	by 'dnptrs'.
386*83ee113eSDavid van Moolenbroek  * Side effects:
387*83ee113eSDavid van Moolenbroek  *	The list of pointers in dnptrs is updated for labels inserted into
388*83ee113eSDavid van Moolenbroek  *	the message as we compress the name.  If 'dnptr' is NULL, we don't
389*83ee113eSDavid van Moolenbroek  *	try to compress names. If 'lastdnptr' is NULL, we don't update the
390*83ee113eSDavid van Moolenbroek  *	list.
391*83ee113eSDavid van Moolenbroek  */
392*83ee113eSDavid van Moolenbroek int
MRns_name_pack(const u_char * src,u_char * dst,unsigned dstsiz,const u_char ** dnptrs,const u_char ** lastdnptr)393*83ee113eSDavid van Moolenbroek MRns_name_pack(const u_char *src, u_char *dst, unsigned dstsiz,
394*83ee113eSDavid van Moolenbroek 	       const u_char **dnptrs, const u_char **lastdnptr)
395*83ee113eSDavid van Moolenbroek {
396*83ee113eSDavid van Moolenbroek 	u_char *dstp;
397*83ee113eSDavid van Moolenbroek 	const u_char **cpp, **lpp, *eob, *msg;
398*83ee113eSDavid van Moolenbroek 	const u_char *srcp;
399*83ee113eSDavid van Moolenbroek 	unsigned n;
400*83ee113eSDavid van Moolenbroek 	int l;
401*83ee113eSDavid van Moolenbroek 
402*83ee113eSDavid van Moolenbroek 	srcp = src;
403*83ee113eSDavid van Moolenbroek 	dstp = dst;
404*83ee113eSDavid van Moolenbroek 	eob = dstp + dstsiz;
405*83ee113eSDavid van Moolenbroek 	lpp = cpp = NULL;
406*83ee113eSDavid van Moolenbroek 	if (dnptrs != NULL) {
407*83ee113eSDavid van Moolenbroek 		if ((msg = *dnptrs++) != NULL) {
408*83ee113eSDavid van Moolenbroek 			for (cpp = dnptrs; *cpp != NULL; cpp++)
409*83ee113eSDavid van Moolenbroek 				(void)NULL;
410*83ee113eSDavid van Moolenbroek 			lpp = cpp;	/* end of list to search */
411*83ee113eSDavid van Moolenbroek 		}
412*83ee113eSDavid van Moolenbroek 	} else
413*83ee113eSDavid van Moolenbroek 		msg = NULL;
414*83ee113eSDavid van Moolenbroek 
415*83ee113eSDavid van Moolenbroek 	/* make sure the domain we are about to add is legal */
416*83ee113eSDavid van Moolenbroek 	l = 0;
417*83ee113eSDavid van Moolenbroek 	do {
418*83ee113eSDavid van Moolenbroek 		n = *srcp;
419*83ee113eSDavid van Moolenbroek 		if ((n & NS_CMPRSFLGS) != 0) {
420*83ee113eSDavid van Moolenbroek 			errno = EMSGSIZE;
421*83ee113eSDavid van Moolenbroek 			return (-1);
422*83ee113eSDavid van Moolenbroek 		}
423*83ee113eSDavid van Moolenbroek 		l += n + 1;
424*83ee113eSDavid van Moolenbroek 		if (l > MAXCDNAME) {
425*83ee113eSDavid van Moolenbroek 			errno = EMSGSIZE;
426*83ee113eSDavid van Moolenbroek 			return (-1);
427*83ee113eSDavid van Moolenbroek 		}
428*83ee113eSDavid van Moolenbroek 		srcp += n + 1;
429*83ee113eSDavid van Moolenbroek 	} while (n != 0);
430*83ee113eSDavid van Moolenbroek 
431*83ee113eSDavid van Moolenbroek 	/* from here on we need to reset compression pointer array on error */
432*83ee113eSDavid van Moolenbroek 	srcp = src;
433*83ee113eSDavid van Moolenbroek 	do {
434*83ee113eSDavid van Moolenbroek 		/* Look to see if we can use pointers. */
435*83ee113eSDavid van Moolenbroek 		n = *srcp;
436*83ee113eSDavid van Moolenbroek 		if (n != 0 && msg != NULL) {
437*83ee113eSDavid van Moolenbroek 			l = dn_find(srcp, msg, (const u_char * const *)dnptrs,
438*83ee113eSDavid van Moolenbroek 				    (const u_char * const *)lpp);
439*83ee113eSDavid van Moolenbroek 			if (l >= 0) {
440*83ee113eSDavid van Moolenbroek 				if (dstp + 1 >= eob) {
441*83ee113eSDavid van Moolenbroek 					goto cleanup;
442*83ee113eSDavid van Moolenbroek 				}
443*83ee113eSDavid van Moolenbroek 				*dstp++ = (l >> 8) | NS_CMPRSFLGS;
444*83ee113eSDavid van Moolenbroek 				*dstp++ = l % 256;
445*83ee113eSDavid van Moolenbroek 				return (dstp - dst);
446*83ee113eSDavid van Moolenbroek 			}
447*83ee113eSDavid van Moolenbroek 			/* Not found, save it. */
448*83ee113eSDavid van Moolenbroek 			if (lastdnptr != NULL && cpp < lastdnptr - 1 &&
449*83ee113eSDavid van Moolenbroek 			    (dstp - msg) < 0x4000) {
450*83ee113eSDavid van Moolenbroek 				*cpp++ = dstp;
451*83ee113eSDavid van Moolenbroek 				*cpp = NULL;
452*83ee113eSDavid van Moolenbroek 			}
453*83ee113eSDavid van Moolenbroek 		}
454*83ee113eSDavid van Moolenbroek 		/* copy label to buffer */
455*83ee113eSDavid van Moolenbroek 		if (n & NS_CMPRSFLGS) {		/* Should not happen. */
456*83ee113eSDavid van Moolenbroek 			goto cleanup;
457*83ee113eSDavid van Moolenbroek 		}
458*83ee113eSDavid van Moolenbroek 		if (dstp + 1 + n >= eob) {
459*83ee113eSDavid van Moolenbroek 			goto cleanup;
460*83ee113eSDavid van Moolenbroek 		}
461*83ee113eSDavid van Moolenbroek 		memcpy(dstp, srcp, n + 1);
462*83ee113eSDavid van Moolenbroek 		srcp += n + 1;
463*83ee113eSDavid van Moolenbroek 		dstp += n + 1;
464*83ee113eSDavid van Moolenbroek 	} while (n != 0);
465*83ee113eSDavid van Moolenbroek 
466*83ee113eSDavid van Moolenbroek 	if (dstp > eob) {
467*83ee113eSDavid van Moolenbroek cleanup:
468*83ee113eSDavid van Moolenbroek 		if (msg != NULL)
469*83ee113eSDavid van Moolenbroek 			*lpp = NULL;
470*83ee113eSDavid van Moolenbroek 		errno = EMSGSIZE;
471*83ee113eSDavid van Moolenbroek 		return (-1);
472*83ee113eSDavid van Moolenbroek 	}
473*83ee113eSDavid van Moolenbroek 	return (dstp - dst);
474*83ee113eSDavid van Moolenbroek }
475*83ee113eSDavid van Moolenbroek 
476*83ee113eSDavid van Moolenbroek #ifdef notdef
477*83ee113eSDavid van Moolenbroek /*
478*83ee113eSDavid van Moolenbroek  * MRns_name_uncompress(msg, eom, src, dst, dstsiz)
479*83ee113eSDavid van Moolenbroek  *	Expand compressed domain name to presentation format.
480*83ee113eSDavid van Moolenbroek  * return:
481*83ee113eSDavid van Moolenbroek  *	Number of bytes read out of `src', or -1 (with errno set).
482*83ee113eSDavid van Moolenbroek  * note:
483*83ee113eSDavid van Moolenbroek  *	Root domain returns as "." not "".
484*83ee113eSDavid van Moolenbroek  */
485*83ee113eSDavid van Moolenbroek int
MRns_name_uncompress(const u_char * msg,const u_char * eom,const u_char * src,char * dst,size_t dstsiz)486*83ee113eSDavid van Moolenbroek MRns_name_uncompress(const u_char *msg, const u_char *eom, const u_char *src,
487*83ee113eSDavid van Moolenbroek 		     char *dst, size_t dstsiz)
488*83ee113eSDavid van Moolenbroek {
489*83ee113eSDavid van Moolenbroek 	u_char tmp[NS_MAXCDNAME];
490*83ee113eSDavid van Moolenbroek 	int n;
491*83ee113eSDavid van Moolenbroek 
492*83ee113eSDavid van Moolenbroek 	if ((n = MRns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1)
493*83ee113eSDavid van Moolenbroek 		return (-1);
494*83ee113eSDavid van Moolenbroek 	if (MRns_name_ntop(tmp, dst, dstsiz) == -1)
495*83ee113eSDavid van Moolenbroek 		return (-1);
496*83ee113eSDavid van Moolenbroek 	return (n);
497*83ee113eSDavid van Moolenbroek }
498*83ee113eSDavid van Moolenbroek #endif
499*83ee113eSDavid van Moolenbroek 
500*83ee113eSDavid van Moolenbroek /*
501*83ee113eSDavid van Moolenbroek  * MRns_name_compress(src, dst, dstsiz, dnptrs, lastdnptr)
502*83ee113eSDavid van Moolenbroek  *	Compress a domain name into wire format, using compression pointers.
503*83ee113eSDavid van Moolenbroek  * return:
504*83ee113eSDavid van Moolenbroek  *	Number of bytes consumed in `dst' or -1 (with errno set).
505*83ee113eSDavid van Moolenbroek  * notes:
506*83ee113eSDavid van Moolenbroek  *	'dnptrs' is an array of pointers to previous compressed names.
507*83ee113eSDavid van Moolenbroek  *	dnptrs[0] is a pointer to the beginning of the message.
508*83ee113eSDavid van Moolenbroek  *	The list ends with NULL.  'lastdnptr' is a pointer to the end of the
509*83ee113eSDavid van Moolenbroek  *	array pointed to by 'dnptrs'. Side effect is to update the list of
510*83ee113eSDavid van Moolenbroek  *	pointers for labels inserted into the message as we compress the name.
511*83ee113eSDavid van Moolenbroek  *	If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
512*83ee113eSDavid van Moolenbroek  *	is NULL, we don't update the list.
513*83ee113eSDavid van Moolenbroek  */
514*83ee113eSDavid van Moolenbroek int
MRns_name_compress(const char * src,u_char * dst,size_t dstsiz,const u_char ** dnptrs,const u_char ** lastdnptr)515*83ee113eSDavid van Moolenbroek MRns_name_compress(const char *src, u_char *dst, size_t dstsiz,
516*83ee113eSDavid van Moolenbroek 		 const u_char **dnptrs, const u_char **lastdnptr)
517*83ee113eSDavid van Moolenbroek {
518*83ee113eSDavid van Moolenbroek 	u_char tmp[NS_MAXCDNAME];
519*83ee113eSDavid van Moolenbroek 
520*83ee113eSDavid van Moolenbroek 	if (MRns_name_pton(src, tmp, sizeof tmp) == -1)
521*83ee113eSDavid van Moolenbroek 		return (-1);
522*83ee113eSDavid van Moolenbroek 	return (MRns_name_pack(tmp, dst, dstsiz, dnptrs, lastdnptr));
523*83ee113eSDavid van Moolenbroek }
524*83ee113eSDavid van Moolenbroek 
525*83ee113eSDavid van Moolenbroek #ifdef notdef
526*83ee113eSDavid van Moolenbroek /*
527*83ee113eSDavid van Moolenbroek  * MRns_name_skip(ptrptr, eom)
528*83ee113eSDavid van Moolenbroek  *	Advance *ptrptr to skip over the compressed name it points at.
529*83ee113eSDavid van Moolenbroek  * return:
530*83ee113eSDavid van Moolenbroek  *	0 on success, -1 (with errno set) on failure.
531*83ee113eSDavid van Moolenbroek  */
532*83ee113eSDavid van Moolenbroek int
MRns_name_skip(const u_char ** ptrptr,const u_char * eom)533*83ee113eSDavid van Moolenbroek MRns_name_skip(const u_char **ptrptr, const u_char *eom) {
534*83ee113eSDavid van Moolenbroek 	const u_char *cp;
535*83ee113eSDavid van Moolenbroek 	u_int n;
536*83ee113eSDavid van Moolenbroek 
537*83ee113eSDavid van Moolenbroek 	cp = *ptrptr;
538*83ee113eSDavid van Moolenbroek 	while (cp < eom && (n = *cp++) != 0) {
539*83ee113eSDavid van Moolenbroek 		/* Check for indirection. */
540*83ee113eSDavid van Moolenbroek 		switch (n & NS_CMPRSFLGS) {
541*83ee113eSDavid van Moolenbroek 		case 0:			/* normal case, n == len */
542*83ee113eSDavid van Moolenbroek 			cp += n;
543*83ee113eSDavid van Moolenbroek 			continue;
544*83ee113eSDavid van Moolenbroek 		case NS_CMPRSFLGS:	/* indirection */
545*83ee113eSDavid van Moolenbroek 			cp++;
546*83ee113eSDavid van Moolenbroek 			break;
547*83ee113eSDavid van Moolenbroek 		default:		/* illegal type */
548*83ee113eSDavid van Moolenbroek 			errno = EMSGSIZE;
549*83ee113eSDavid van Moolenbroek 			return (-1);
550*83ee113eSDavid van Moolenbroek 		}
551*83ee113eSDavid van Moolenbroek 		break;
552*83ee113eSDavid van Moolenbroek 	}
553*83ee113eSDavid van Moolenbroek 	if (cp > eom) {
554*83ee113eSDavid van Moolenbroek 		errno = EMSGSIZE;
555*83ee113eSDavid van Moolenbroek 		return (-1);
556*83ee113eSDavid van Moolenbroek 	}
557*83ee113eSDavid van Moolenbroek 	*ptrptr = cp;
558*83ee113eSDavid van Moolenbroek 	return (0);
559*83ee113eSDavid van Moolenbroek }
560*83ee113eSDavid van Moolenbroek #endif
561*83ee113eSDavid van Moolenbroek 
562*83ee113eSDavid van Moolenbroek /* Private. */
563*83ee113eSDavid van Moolenbroek 
564*83ee113eSDavid van Moolenbroek /*
565*83ee113eSDavid van Moolenbroek  * special(ch)
566*83ee113eSDavid van Moolenbroek  *	Thinking in noninternationalized USASCII (per the DNS spec),
567*83ee113eSDavid van Moolenbroek  *	is this characted special ("in need of quoting") ?
568*83ee113eSDavid van Moolenbroek  * return:
569*83ee113eSDavid van Moolenbroek  *	boolean.
570*83ee113eSDavid van Moolenbroek  */
571*83ee113eSDavid van Moolenbroek static int
special(int ch)572*83ee113eSDavid van Moolenbroek special(int ch) {
573*83ee113eSDavid van Moolenbroek 	switch (ch) {
574*83ee113eSDavid van Moolenbroek 	case 0x22: /* '"' */
575*83ee113eSDavid van Moolenbroek 	case 0x2E: /* '.' */
576*83ee113eSDavid van Moolenbroek 	case 0x3B: /* ';' */
577*83ee113eSDavid van Moolenbroek 	case 0x5C: /* '\\' */
578*83ee113eSDavid van Moolenbroek 	/* Special modifiers in zone files. */
579*83ee113eSDavid van Moolenbroek 	case 0x40: /* '@' */
580*83ee113eSDavid van Moolenbroek 	case 0x24: /* '$' */
581*83ee113eSDavid van Moolenbroek 		return (1);
582*83ee113eSDavid van Moolenbroek 	default:
583*83ee113eSDavid van Moolenbroek 		return (0);
584*83ee113eSDavid van Moolenbroek 	}
585*83ee113eSDavid van Moolenbroek }
586*83ee113eSDavid van Moolenbroek 
587*83ee113eSDavid van Moolenbroek /*
588*83ee113eSDavid van Moolenbroek  * printable(ch)
589*83ee113eSDavid van Moolenbroek  *	Thinking in noninternationalized USASCII (per the DNS spec),
590*83ee113eSDavid van Moolenbroek  *	is this character visible and not a space when printed ?
591*83ee113eSDavid van Moolenbroek  * return:
592*83ee113eSDavid van Moolenbroek  *	boolean.
593*83ee113eSDavid van Moolenbroek  */
594*83ee113eSDavid van Moolenbroek static int
printable(int ch)595*83ee113eSDavid van Moolenbroek printable(int ch) {
596*83ee113eSDavid van Moolenbroek 	return (ch > 0x20 && ch < 0x7f);
597*83ee113eSDavid van Moolenbroek }
598*83ee113eSDavid van Moolenbroek 
599*83ee113eSDavid van Moolenbroek /*
600*83ee113eSDavid van Moolenbroek  *	Thinking in noninternationalized USASCII (per the DNS spec),
601*83ee113eSDavid van Moolenbroek  *	convert this character to lower case if it's upper case.
602*83ee113eSDavid van Moolenbroek  */
603*83ee113eSDavid van Moolenbroek static int
mklower(int ch)604*83ee113eSDavid van Moolenbroek mklower(int ch) {
605*83ee113eSDavid van Moolenbroek 	if (ch >= 0x41 && ch <= 0x5A)
606*83ee113eSDavid van Moolenbroek 		return (ch + 0x20);
607*83ee113eSDavid van Moolenbroek 	return (ch);
608*83ee113eSDavid van Moolenbroek }
609*83ee113eSDavid van Moolenbroek 
610*83ee113eSDavid van Moolenbroek /*
611*83ee113eSDavid van Moolenbroek  * dn_find(domain, msg, dnptrs, lastdnptr)
612*83ee113eSDavid van Moolenbroek  *	Search for the counted-label name in an array of compressed names.
613*83ee113eSDavid van Moolenbroek  * return:
614*83ee113eSDavid van Moolenbroek  *	offset from msg if found, or -1.
615*83ee113eSDavid van Moolenbroek  * notes:
616*83ee113eSDavid van Moolenbroek  *	dnptrs is the pointer to the first name on the list,
617*83ee113eSDavid van Moolenbroek  *	not the pointer to the start of the message.
618*83ee113eSDavid van Moolenbroek  */
619*83ee113eSDavid van Moolenbroek static int
dn_find(const u_char * domain,const u_char * msg,const u_char * const * dnptrs,const u_char * const * lastdnptr)620*83ee113eSDavid van Moolenbroek dn_find(const u_char *domain, const u_char *msg,
621*83ee113eSDavid van Moolenbroek 	const u_char * const *dnptrs,
622*83ee113eSDavid van Moolenbroek 	const u_char * const *lastdnptr)
623*83ee113eSDavid van Moolenbroek {
624*83ee113eSDavid van Moolenbroek 	const u_char *dn, *cp, *sp;
625*83ee113eSDavid van Moolenbroek 	const u_char * const *cpp;
626*83ee113eSDavid van Moolenbroek 	u_int n;
627*83ee113eSDavid van Moolenbroek 
628*83ee113eSDavid van Moolenbroek 	for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
629*83ee113eSDavid van Moolenbroek 		dn = domain;
630*83ee113eSDavid van Moolenbroek 		sp = cp = *cpp;
631*83ee113eSDavid van Moolenbroek 		while ((n = *cp++) != 0) {
632*83ee113eSDavid van Moolenbroek 			/*
633*83ee113eSDavid van Moolenbroek 			 * check for indirection
634*83ee113eSDavid van Moolenbroek 			 */
635*83ee113eSDavid van Moolenbroek 			switch (n & NS_CMPRSFLGS) {
636*83ee113eSDavid van Moolenbroek 			case 0:			/* normal case, n == len */
637*83ee113eSDavid van Moolenbroek 				if (n != *dn++)
638*83ee113eSDavid van Moolenbroek 					goto next;
639*83ee113eSDavid van Moolenbroek 				for ((void)NULL; n > 0; n--)
640*83ee113eSDavid van Moolenbroek 					if (mklower(*dn++) != mklower(*cp++))
641*83ee113eSDavid van Moolenbroek 						goto next;
642*83ee113eSDavid van Moolenbroek 				/* Is next root for both ? */
643*83ee113eSDavid van Moolenbroek 				if (*dn == '\0' && *cp == '\0')
644*83ee113eSDavid van Moolenbroek 					return (sp - msg);
645*83ee113eSDavid van Moolenbroek 				if (*dn)
646*83ee113eSDavid van Moolenbroek 					continue;
647*83ee113eSDavid van Moolenbroek 				goto next;
648*83ee113eSDavid van Moolenbroek 
649*83ee113eSDavid van Moolenbroek 			case NS_CMPRSFLGS:	/* indirection */
650*83ee113eSDavid van Moolenbroek 				cp = msg + (((n & 0x3f) << 8) | *cp);
651*83ee113eSDavid van Moolenbroek 				break;
652*83ee113eSDavid van Moolenbroek 
653*83ee113eSDavid van Moolenbroek 			default:	/* illegal type */
654*83ee113eSDavid van Moolenbroek 				errno = EMSGSIZE;
655*83ee113eSDavid van Moolenbroek 				return (-1);
656*83ee113eSDavid van Moolenbroek 			}
657*83ee113eSDavid van Moolenbroek 		}
658*83ee113eSDavid van Moolenbroek  next: ;
659*83ee113eSDavid van Moolenbroek 	}
660*83ee113eSDavid van Moolenbroek 	errno = ENOENT;
661*83ee113eSDavid van Moolenbroek 	return (-1);
662*83ee113eSDavid van Moolenbroek }
663