xref: /dflybsd-src/lib/libc/nameser/ns_parse.c (revision fbfb85d2836918c8381a60d528f004e7f0bbbe31)
1ee65b806SJan Lentfer /*
2ee65b806SJan Lentfer  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
3ee65b806SJan Lentfer  * Copyright (c) 1996,1999 by Internet Software Consortium.
4ee65b806SJan Lentfer  *
5ee65b806SJan Lentfer  * Permission to use, copy, modify, and distribute this software for any
6ee65b806SJan Lentfer  * purpose with or without fee is hereby granted, provided that the above
7ee65b806SJan Lentfer  * copyright notice and this permission notice appear in all copies.
8ee65b806SJan Lentfer  *
9ee65b806SJan Lentfer  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
10ee65b806SJan Lentfer  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11ee65b806SJan Lentfer  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
12ee65b806SJan Lentfer  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13ee65b806SJan Lentfer  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14ee65b806SJan Lentfer  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
15ee65b806SJan Lentfer  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16*fbfb85d2SSascha Wildner  *
17*fbfb85d2SSascha Wildner  * $Id: ns_parse.c,v 1.9 2007/08/27 03:32:26 marka Exp $
18ee65b806SJan Lentfer  */
19ee65b806SJan Lentfer 
20ee65b806SJan Lentfer /* Import. */
21ee65b806SJan Lentfer 
22ee65b806SJan Lentfer #include "port_before.h"
23ee65b806SJan Lentfer 
24ee65b806SJan Lentfer #include <sys/types.h>
25ee65b806SJan Lentfer 
26ee65b806SJan Lentfer #include <netinet/in.h>
27ee65b806SJan Lentfer #include <arpa/nameser.h>
28ee65b806SJan Lentfer 
29ee65b806SJan Lentfer #include <errno.h>
30ee65b806SJan Lentfer #include <resolv.h>
31ee65b806SJan Lentfer #include <string.h>
32ee65b806SJan Lentfer 
33ee65b806SJan Lentfer #include "port_after.h"
34ee65b806SJan Lentfer 
35ee65b806SJan Lentfer /* Forward. */
36ee65b806SJan Lentfer 
37ee65b806SJan Lentfer static void	setsection(ns_msg *msg, ns_sect sect);
38ee65b806SJan Lentfer 
39ee65b806SJan Lentfer /* Macros. */
40ee65b806SJan Lentfer 
41ee65b806SJan Lentfer #if !defined(SOLARIS2) || defined(__COVERITY__)
42ee65b806SJan Lentfer #define RETERR(err) do { errno = (err); return (-1); } while (0)
43ee65b806SJan Lentfer #else
44ee65b806SJan Lentfer #define RETERR(err) \
45ee65b806SJan Lentfer 	do { errno = (err); if (errno == errno) return (-1); } while (0)
46ee65b806SJan Lentfer #endif
47ee65b806SJan Lentfer 
48ee65b806SJan Lentfer /* Public. */
49ee65b806SJan Lentfer 
50ee65b806SJan Lentfer /* These need to be in the same order as the nres.h:ns_flag enum. */
51ee65b806SJan Lentfer struct _ns_flagdata _ns_flagdata[16] = {
52ee65b806SJan Lentfer 	{ 0x8000, 15 },		/*%< qr. */
53ee65b806SJan Lentfer 	{ 0x7800, 11 },		/*%< opcode. */
54ee65b806SJan Lentfer 	{ 0x0400, 10 },		/*%< aa. */
55ee65b806SJan Lentfer 	{ 0x0200, 9 },		/*%< tc. */
56ee65b806SJan Lentfer 	{ 0x0100, 8 },		/*%< rd. */
57ee65b806SJan Lentfer 	{ 0x0080, 7 },		/*%< ra. */
58ee65b806SJan Lentfer 	{ 0x0040, 6 },		/*%< z. */
59ee65b806SJan Lentfer 	{ 0x0020, 5 },		/*%< ad. */
60ee65b806SJan Lentfer 	{ 0x0010, 4 },		/*%< cd. */
61ee65b806SJan Lentfer 	{ 0x000f, 0 },		/*%< rcode. */
62ee65b806SJan Lentfer 	{ 0x0000, 0 },		/*%< expansion (1/6). */
63ee65b806SJan Lentfer 	{ 0x0000, 0 },		/*%< expansion (2/6). */
64ee65b806SJan Lentfer 	{ 0x0000, 0 },		/*%< expansion (3/6). */
65ee65b806SJan Lentfer 	{ 0x0000, 0 },		/*%< expansion (4/6). */
66ee65b806SJan Lentfer 	{ 0x0000, 0 },		/*%< expansion (5/6). */
67ee65b806SJan Lentfer 	{ 0x0000, 0 },		/*%< expansion (6/6). */
68ee65b806SJan Lentfer };
69ee65b806SJan Lentfer 
ns_msg_getflag(ns_msg handle,int flag)70ee65b806SJan Lentfer int ns_msg_getflag(ns_msg handle, int flag) {
71ee65b806SJan Lentfer 	return(((handle)._flags & _ns_flagdata[flag].mask) >> _ns_flagdata[flag].shift);
72ee65b806SJan Lentfer }
73ee65b806SJan Lentfer 
74ee65b806SJan Lentfer int
ns_skiprr(const u_char * ptr,const u_char * eom,ns_sect section,int count)75ee65b806SJan Lentfer ns_skiprr(const u_char *ptr, const u_char *eom, ns_sect section, int count) {
76ee65b806SJan Lentfer 	const u_char *optr = ptr;
77ee65b806SJan Lentfer 
78ee65b806SJan Lentfer 	for ((void)NULL; count > 0; count--) {
79ee65b806SJan Lentfer 		int b, rdlength;
80ee65b806SJan Lentfer 
81ee65b806SJan Lentfer 		b = dn_skipname(ptr, eom);
82ee65b806SJan Lentfer 		if (b < 0)
83ee65b806SJan Lentfer 			RETERR(EMSGSIZE);
84ee65b806SJan Lentfer 		ptr += b/*Name*/ + NS_INT16SZ/*Type*/ + NS_INT16SZ/*Class*/;
85ee65b806SJan Lentfer 		if (section != ns_s_qd) {
86ee65b806SJan Lentfer 			if (ptr + NS_INT32SZ + NS_INT16SZ > eom)
87ee65b806SJan Lentfer 				RETERR(EMSGSIZE);
88ee65b806SJan Lentfer 			ptr += NS_INT32SZ/*TTL*/;
89ee65b806SJan Lentfer 			NS_GET16(rdlength, ptr);
90ee65b806SJan Lentfer 			ptr += rdlength/*RData*/;
91ee65b806SJan Lentfer 		}
92ee65b806SJan Lentfer 	}
93ee65b806SJan Lentfer 	if (ptr > eom)
94ee65b806SJan Lentfer 		RETERR(EMSGSIZE);
95ee65b806SJan Lentfer 	return (ptr - optr);
96ee65b806SJan Lentfer }
97ee65b806SJan Lentfer 
98ee65b806SJan Lentfer int
ns_initparse(const u_char * msg,int msglen,ns_msg * handle)99ee65b806SJan Lentfer ns_initparse(const u_char *msg, int msglen, ns_msg *handle) {
100ee65b806SJan Lentfer 	const u_char *eom = msg + msglen;
101ee65b806SJan Lentfer 	int i;
102ee65b806SJan Lentfer 
103ee65b806SJan Lentfer 	memset(handle, 0x5e, sizeof *handle);
104ee65b806SJan Lentfer 	handle->_msg = msg;
105ee65b806SJan Lentfer 	handle->_eom = eom;
106ee65b806SJan Lentfer 	if (msg + NS_INT16SZ > eom)
107ee65b806SJan Lentfer 		RETERR(EMSGSIZE);
108ee65b806SJan Lentfer 	NS_GET16(handle->_id, msg);
109ee65b806SJan Lentfer 	if (msg + NS_INT16SZ > eom)
110ee65b806SJan Lentfer 		RETERR(EMSGSIZE);
111ee65b806SJan Lentfer 	NS_GET16(handle->_flags, msg);
112ee65b806SJan Lentfer 	for (i = 0; i < ns_s_max; i++) {
113ee65b806SJan Lentfer 		if (msg + NS_INT16SZ > eom)
114ee65b806SJan Lentfer 			RETERR(EMSGSIZE);
115ee65b806SJan Lentfer 		NS_GET16(handle->_counts[i], msg);
116ee65b806SJan Lentfer 	}
117ee65b806SJan Lentfer 	for (i = 0; i < ns_s_max; i++)
118ee65b806SJan Lentfer 		if (handle->_counts[i] == 0)
119ee65b806SJan Lentfer 			handle->_sections[i] = NULL;
120ee65b806SJan Lentfer 		else {
121ee65b806SJan Lentfer 			int b = ns_skiprr(msg, eom, (ns_sect)i,
122ee65b806SJan Lentfer 					  handle->_counts[i]);
123ee65b806SJan Lentfer 
124ee65b806SJan Lentfer 			if (b < 0)
125ee65b806SJan Lentfer 				return (-1);
126ee65b806SJan Lentfer 			handle->_sections[i] = msg;
127ee65b806SJan Lentfer 			msg += b;
128ee65b806SJan Lentfer 		}
129ee65b806SJan Lentfer 	if (msg != eom)
130ee65b806SJan Lentfer 		RETERR(EMSGSIZE);
131ee65b806SJan Lentfer 	setsection(handle, ns_s_max);
132ee65b806SJan Lentfer 	return (0);
133ee65b806SJan Lentfer }
134ee65b806SJan Lentfer 
135ee65b806SJan Lentfer int
ns_parserr(ns_msg * handle,ns_sect section,int rrnum,ns_rr * rr)136ee65b806SJan Lentfer ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr) {
137ee65b806SJan Lentfer 	int b;
138ee65b806SJan Lentfer 	int tmp;
139ee65b806SJan Lentfer 
140ee65b806SJan Lentfer 	/* Make section right. */
141ee65b806SJan Lentfer 	tmp = section;
142ee65b806SJan Lentfer 	if (tmp < 0 || section >= ns_s_max)
143ee65b806SJan Lentfer 		RETERR(ENODEV);
144ee65b806SJan Lentfer 	if (section != handle->_sect)
145ee65b806SJan Lentfer 		setsection(handle, section);
146ee65b806SJan Lentfer 
147ee65b806SJan Lentfer 	/* Make rrnum right. */
148ee65b806SJan Lentfer 	if (rrnum == -1)
149ee65b806SJan Lentfer 		rrnum = handle->_rrnum;
150ee65b806SJan Lentfer 	if (rrnum < 0 || rrnum >= handle->_counts[(int)section])
151ee65b806SJan Lentfer 		RETERR(ENODEV);
152ee65b806SJan Lentfer 	if (rrnum < handle->_rrnum)
153ee65b806SJan Lentfer 		setsection(handle, section);
154ee65b806SJan Lentfer 	if (rrnum > handle->_rrnum) {
155ee65b806SJan Lentfer 		b = ns_skiprr(handle->_msg_ptr, handle->_eom, section,
156ee65b806SJan Lentfer 			      rrnum - handle->_rrnum);
157ee65b806SJan Lentfer 
158ee65b806SJan Lentfer 		if (b < 0)
159ee65b806SJan Lentfer 			return (-1);
160ee65b806SJan Lentfer 		handle->_msg_ptr += b;
161ee65b806SJan Lentfer 		handle->_rrnum = rrnum;
162ee65b806SJan Lentfer 	}
163ee65b806SJan Lentfer 
164ee65b806SJan Lentfer 	/* Do the parse. */
165ee65b806SJan Lentfer 	b = dn_expand(handle->_msg, handle->_eom,
166ee65b806SJan Lentfer 		      handle->_msg_ptr, rr->name, NS_MAXDNAME);
167ee65b806SJan Lentfer 	if (b < 0)
168ee65b806SJan Lentfer 		return (-1);
169ee65b806SJan Lentfer 	handle->_msg_ptr += b;
170ee65b806SJan Lentfer 	if (handle->_msg_ptr + NS_INT16SZ + NS_INT16SZ > handle->_eom)
171ee65b806SJan Lentfer 		RETERR(EMSGSIZE);
172ee65b806SJan Lentfer 	NS_GET16(rr->type, handle->_msg_ptr);
173ee65b806SJan Lentfer 	NS_GET16(rr->rr_class, handle->_msg_ptr);
174ee65b806SJan Lentfer 	if (section == ns_s_qd) {
175ee65b806SJan Lentfer 		rr->ttl = 0;
176ee65b806SJan Lentfer 		rr->rdlength = 0;
177ee65b806SJan Lentfer 		rr->rdata = NULL;
178ee65b806SJan Lentfer 	} else {
179ee65b806SJan Lentfer 		if (handle->_msg_ptr + NS_INT32SZ + NS_INT16SZ > handle->_eom)
180ee65b806SJan Lentfer 			RETERR(EMSGSIZE);
181ee65b806SJan Lentfer 		NS_GET32(rr->ttl, handle->_msg_ptr);
182ee65b806SJan Lentfer 		NS_GET16(rr->rdlength, handle->_msg_ptr);
183ee65b806SJan Lentfer 		if (handle->_msg_ptr + rr->rdlength > handle->_eom)
184ee65b806SJan Lentfer 			RETERR(EMSGSIZE);
185ee65b806SJan Lentfer 		rr->rdata = handle->_msg_ptr;
186ee65b806SJan Lentfer 		handle->_msg_ptr += rr->rdlength;
187ee65b806SJan Lentfer 	}
188ee65b806SJan Lentfer 	if (++handle->_rrnum > handle->_counts[(int)section])
189ee65b806SJan Lentfer 		setsection(handle, (ns_sect)((int)section + 1));
190ee65b806SJan Lentfer 
191ee65b806SJan Lentfer 	/* All done. */
192ee65b806SJan Lentfer 	return (0);
193ee65b806SJan Lentfer }
194ee65b806SJan Lentfer 
195ee65b806SJan Lentfer /* Private. */
196ee65b806SJan Lentfer 
197ee65b806SJan Lentfer static void
setsection(ns_msg * msg,ns_sect sect)198ee65b806SJan Lentfer setsection(ns_msg *msg, ns_sect sect) {
199ee65b806SJan Lentfer 	msg->_sect = sect;
200ee65b806SJan Lentfer 	if (sect == ns_s_max) {
201ee65b806SJan Lentfer 		msg->_rrnum = -1;
202ee65b806SJan Lentfer 		msg->_msg_ptr = NULL;
203ee65b806SJan Lentfer 	} else {
204ee65b806SJan Lentfer 		msg->_rrnum = 0;
205ee65b806SJan Lentfer 		msg->_msg_ptr = msg->_sections[(int)sect];
206ee65b806SJan Lentfer 	}
207ee65b806SJan Lentfer }
208ee65b806SJan Lentfer 
209ee65b806SJan Lentfer /*! \file */
210