File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / dhcp / minires / ns_parse.c
Revision 1.1: download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 22:30:18 2012 UTC (12 years, 4 months ago) by misho
CVS tags: MAIN, HEAD
Initial revision

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>