res_comp.c revision 165903
1275970Scy/*
2275970Scy * Copyright (c) 1985, 1993
3275970Scy *    The Regents of the University of California.  All rights reserved.
4275970Scy *
5275970Scy * Redistribution and use in source and binary forms, with or without
6275970Scy * modification, are permitted provided that the following conditions
7275970Scy * are met:
8275970Scy * 1. Redistributions of source code must retain the above copyright
9275970Scy *    notice, this list of conditions and the following disclaimer.
10275970Scy * 2. Redistributions in binary form must reproduce the above copyright
11275970Scy *    notice, this list of conditions and the following disclaimer in the
12275970Scy *    documentation and/or other materials provided with the distribution.
13275970Scy * 4. Neither the name of the University nor the names of its contributors
14275970Scy *    may be used to endorse or promote products derived from this software
15275970Scy *    without specific prior written permission.
16275970Scy *
17275970Scy * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18275970Scy * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19275970Scy * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20275970Scy * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21275970Scy * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22275970Scy * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23275970Scy * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24275970Scy * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25275970Scy * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26275970Scy * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27275970Scy * SUCH DAMAGE.
28275970Scy */
29275970Scy
30275970Scy/*
31275970Scy * Portions Copyright (c) 1993 by Digital Equipment Corporation.
32275970Scy *
33275970Scy * Permission to use, copy, modify, and distribute this software for any
34275970Scy * purpose with or without fee is hereby granted, provided that the above
35275970Scy * copyright notice and this permission notice appear in all copies, and that
36275970Scy * the name of Digital Equipment Corporation not be used in advertising or
37275970Scy * publicity pertaining to distribution of the document or software without
38275970Scy * specific, written prior permission.
39275970Scy *
40275970Scy * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
41275970Scy * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
42275970Scy * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
43275970Scy * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
44275970Scy * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
45275970Scy * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
46275970Scy * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
47275970Scy * SOFTWARE.
48275970Scy */
49275970Scy
50275970Scy/*
51275970Scy * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
52275970Scy * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
53275970Scy *
54275970Scy * Permission to use, copy, modify, and distribute this software for any
55275970Scy * purpose with or without fee is hereby granted, provided that the above
56275970Scy * copyright notice and this permission notice appear in all copies.
57275970Scy *
58275970Scy * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
59275970Scy * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
60275970Scy * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
61275970Scy * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
62275970Scy * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
63275970Scy * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
64275970Scy * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
65275970Scy */
66275970Scy
67275970Scy#if defined(LIBC_SCCS) && !defined(lint)
68275970Scystatic const char sccsid[] = "@(#)res_comp.c	8.1 (Berkeley) 6/4/93";
69275970Scystatic const char rcsid[] = "$Id: res_comp.c,v 1.1.2.1.4.2 2005/07/28 07:43:22 marka Exp $";
70275970Scy#endif /* LIBC_SCCS and not lint */
71275970Scy#include <sys/cdefs.h>
72275970Scy__FBSDID("$FreeBSD: head/lib/libc/resolv/res_comp.c 165903 2007-01-09 00:28:16Z imp $");
73275970Scy
74275970Scy#include "port_before.h"
75275970Scy#include <sys/types.h>
76275970Scy#include <sys/param.h>
77275970Scy#include <netinet/in.h>
78275970Scy#include <arpa/nameser.h>
79275970Scy#include <ctype.h>
80275970Scy#include <resolv.h>
81275970Scy#include <stdio.h>
82275970Scy#include <string.h>
83275970Scy#include <unistd.h>
84275970Scy#include "port_after.h"
85275970Scy
86275970Scy/*
87275970Scy * Expand compressed domain name 'src' to full domain name.
88275970Scy * 'msg' is a pointer to the begining of the message,
89275970Scy * 'eom' points to the first location after the message,
90275970Scy * 'dst' is a pointer to a buffer of size 'dstsiz' for the result.
91275970Scy * Return size of compressed name or -1 if there was an error.
92275970Scy */
93275970Scyint
94275970Scydn_expand(const u_char *msg, const u_char *eom, const u_char *src,
95275970Scy	  char *dst, int dstsiz)
96275970Scy{
97275970Scy	int n = ns_name_uncompress(msg, eom, src, dst, (size_t)dstsiz);
98275970Scy
99275970Scy	if (n > 0 && dst[0] == '.')
100275970Scy		dst[0] = '\0';
101275970Scy	return (n);
102275970Scy}
103275970Scy
104275970Scy/*
105275970Scy * Pack domain name 'exp_dn' in presentation form into 'comp_dn'.
106275970Scy * Return the size of the compressed name or -1.
107275970Scy * 'length' is the size of the array pointed to by 'comp_dn'.
108275970Scy */
109275970Scyint
110275970Scydn_comp(const char *src, u_char *dst, int dstsiz,
111275970Scy	u_char **dnptrs, u_char **lastdnptr)
112275970Scy{
113275970Scy	return (ns_name_compress(src, dst, (size_t)dstsiz,
114275970Scy				 (const u_char **)dnptrs,
115275970Scy				 (const u_char **)lastdnptr));
116275970Scy}
117275970Scy
118275970Scy/*
119275970Scy * Skip over a compressed domain name. Return the size or -1.
120275970Scy */
121275970Scyint
122275970Scydn_skipname(const u_char *ptr, const u_char *eom) {
123275970Scy	const u_char *saveptr = ptr;
124275970Scy
125275970Scy	if (ns_name_skip(&ptr, eom) == -1)
126275970Scy		return (-1);
127275970Scy	return (ptr - saveptr);
128275970Scy}
129275970Scy
130275970Scy/*
131275970Scy * Verify that a domain name uses an acceptable character set.
132275970Scy */
133275970Scy
134275970Scy/*
135275970Scy * Note the conspicuous absence of ctype macros in these definitions.  On
136275970Scy * non-ASCII hosts, we can't depend on string literals or ctype macros to
137275970Scy * tell us anything about network-format data.  The rest of the BIND system
138275970Scy * is not careful about this, but for some reason, we're doing it right here.
139275970Scy */
140275970Scy#define PERIOD 0x2e
141275970Scy#define	hyphenchar(c) ((c) == 0x2d)
142275970Scy#define bslashchar(c) ((c) == 0x5c)
143275970Scy#define periodchar(c) ((c) == PERIOD)
144275970Scy#define asterchar(c) ((c) == 0x2a)
145275970Scy#define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \
146275970Scy		   || ((c) >= 0x61 && (c) <= 0x7a))
147275970Scy#define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
148275970Scy
149275970Scy#define borderchar(c) (alphachar(c) || digitchar(c))
150275970Scy#define middlechar(c) (borderchar(c) || hyphenchar(c))
151275970Scy#define	domainchar(c) ((c) > 0x20 && (c) < 0x7f)
152275970Scy
153275970Scyint
154275970Scyres_hnok(const char *dn) {
155275970Scy	int pch = PERIOD, ch = *dn++;
156275970Scy
157275970Scy	while (ch != '\0') {
158275970Scy		int nch = *dn++;
159275970Scy
160275970Scy		if (periodchar(ch)) {
161275970Scy			(void)NULL;
162275970Scy		} else if (periodchar(pch)) {
163275970Scy			if (!borderchar(ch))
164275970Scy				return (0);
165275970Scy		} else if (periodchar(nch) || nch == '\0') {
166275970Scy			if (!borderchar(ch))
167275970Scy				return (0);
168275970Scy		} else {
169275970Scy			if (!middlechar(ch))
170275970Scy				return (0);
171275970Scy		}
172275970Scy		pch = ch, ch = nch;
173275970Scy	}
174275970Scy	return (1);
175275970Scy}
176275970Scy
177275970Scy/*
178275970Scy * hostname-like (A, MX, WKS) owners can have "*" as their first label
179275970Scy * but must otherwise be as a host name.
180275970Scy */
181275970Scyint
182275970Scyres_ownok(const char *dn) {
183275970Scy	if (asterchar(dn[0])) {
184275970Scy		if (periodchar(dn[1]))
185275970Scy			return (res_hnok(dn+2));
186275970Scy		if (dn[1] == '\0')
187275970Scy			return (1);
188275970Scy	}
189275970Scy	return (res_hnok(dn));
190275970Scy}
191275970Scy
192275970Scy/*
193275970Scy * SOA RNAMEs and RP RNAMEs can have any printable character in their first
194275970Scy * label, but the rest of the name has to look like a host name.
195275970Scy */
196275970Scyint
197275970Scyres_mailok(const char *dn) {
198275970Scy	int ch, escaped = 0;
199275970Scy
200275970Scy	/* "." is a valid missing representation */
201275970Scy	if (*dn == '\0')
202275970Scy		return (1);
203275970Scy
204275970Scy	/* otherwise <label>.<hostname> */
205275970Scy	while ((ch = *dn++) != '\0') {
206275970Scy		if (!domainchar(ch))
207275970Scy			return (0);
208275970Scy		if (!escaped && periodchar(ch))
209275970Scy			break;
210275970Scy		if (escaped)
211275970Scy			escaped = 0;
212275970Scy		else if (bslashchar(ch))
213275970Scy			escaped = 1;
214280849Scy	}
215275970Scy	if (periodchar(ch))
216275970Scy		return (res_hnok(dn));
217275970Scy	return (0);
218275970Scy}
219275970Scy
220280849Scy/*
221275970Scy * This function is quite liberal, since RFC 1034's character sets are only
222275970Scy * recommendations.
223280849Scy */
224280849Scyint
225275970Scyres_dnok(const char *dn) {
226275970Scy	int ch;
227275970Scy
228275970Scy	while ((ch = *dn++) != '\0')
229275970Scy		if (!domainchar(ch))
230275970Scy			return (0);
231275970Scy	return (1);
232275970Scy}
233275970Scy
234275970Scy#ifdef BIND_4_COMPAT
235275970Scy/*
236275970Scy * This module must export the following externally-visible symbols:
237275970Scy *	___putlong
238275970Scy *	___putshort
239275970Scy *	__getlong
240275970Scy *	__getshort
241275970Scy * Note that one _ comes from C and the others come from us.
242275970Scy */
243275970Scy
244275970Scy#ifdef SOLARIS2
245275970Scy#ifdef  __putlong
246275970Scy#undef  __putlong
247275970Scy#endif
248275970Scy#ifdef  __putshort
249275970Scy#undef  __putshort
250275970Scy#endif
251275970Scy#pragma weak    putlong         =       __putlong
252275970Scy#pragma weak    putshort        =       __putshort
253275970Scy#endif /* SOLARIS2 */
254275970Scy
255275970Scyvoid __putlong(u_int32_t src, u_char *dst) { ns_put32(src, dst); }
256275970Scyvoid __putshort(u_int16_t src, u_char *dst) { ns_put16(src, dst); }
257275970Scy#ifndef __ultrix__
258275970Scyu_int32_t _getlong(const u_char *src) { return (ns_get32(src)); }
259275970Scyu_int16_t _getshort(const u_char *src) { return (ns_get16(src)); }
260275970Scy#endif /*__ultrix__*/
261275970Scy#endif /*BIND_4_COMPAT*/
262275970Scy
263275970Scy/*
264275970Scy * Weak aliases for applications that use certain private entry points,
265275970Scy * and fail to include <resolv.h>.
266275970Scy */
267275970Scy#undef dn_comp
268275970Scy__weak_reference(__dn_comp, dn_comp);
269275970Scy#undef dn_expand
270275970Scy__weak_reference(__dn_expand, dn_expand);
271275970Scy