17c478bd9Sstevel@tonic-gate /* 2*9525b14bSRao Shoaib * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 37c478bd9Sstevel@tonic-gate * Copyright (c) 1996,1999 by Internet Software Consortium. 47c478bd9Sstevel@tonic-gate * 57c478bd9Sstevel@tonic-gate * Permission to use, copy, modify, and distribute this software for any 67c478bd9Sstevel@tonic-gate * purpose with or without fee is hereby granted, provided that the above 77c478bd9Sstevel@tonic-gate * copyright notice and this permission notice appear in all copies. 87c478bd9Sstevel@tonic-gate * 9*9525b14bSRao Shoaib * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 10*9525b14bSRao Shoaib * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11*9525b14bSRao Shoaib * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 12*9525b14bSRao Shoaib * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13*9525b14bSRao Shoaib * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14*9525b14bSRao Shoaib * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 15*9525b14bSRao Shoaib * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 167c478bd9Sstevel@tonic-gate */ 177c478bd9Sstevel@tonic-gate 187c478bd9Sstevel@tonic-gate #ifndef lint 19*9525b14bSRao Shoaib static const char rcsid[] = "$Id: ns_parse.c,v 1.10 2009/01/23 19:59:16 each Exp $"; 207c478bd9Sstevel@tonic-gate #endif 217c478bd9Sstevel@tonic-gate 227c478bd9Sstevel@tonic-gate /* Import. */ 237c478bd9Sstevel@tonic-gate 247c478bd9Sstevel@tonic-gate #include "port_before.h" 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #include <sys/types.h> 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #include <netinet/in.h> 297c478bd9Sstevel@tonic-gate #include <arpa/nameser.h> 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate #include <errno.h> 327c478bd9Sstevel@tonic-gate #include <resolv.h> 337c478bd9Sstevel@tonic-gate #include <string.h> 347c478bd9Sstevel@tonic-gate 357c478bd9Sstevel@tonic-gate #include "port_after.h" 367c478bd9Sstevel@tonic-gate 377c478bd9Sstevel@tonic-gate /* Forward. */ 387c478bd9Sstevel@tonic-gate 397c478bd9Sstevel@tonic-gate static void setsection(ns_msg *msg, ns_sect sect); 407c478bd9Sstevel@tonic-gate 417c478bd9Sstevel@tonic-gate /* Macros. */ 427c478bd9Sstevel@tonic-gate 43*9525b14bSRao Shoaib #if !defined(SOLARIS2) || defined(__COVERITY__) 447c478bd9Sstevel@tonic-gate #define RETERR(err) do { errno = (err); return (-1); } while (0) 457c478bd9Sstevel@tonic-gate #else 46*9525b14bSRao Shoaib #define RETERR(err) \ 47*9525b14bSRao Shoaib do { errno = (err); if (errno == errno) return (-1); } while (0) 487c478bd9Sstevel@tonic-gate #endif 497c478bd9Sstevel@tonic-gate 50*9525b14bSRao Shoaib #define PARSE_FMT_PRESO 0 /* Parse using presentation-format names */ 51*9525b14bSRao Shoaib #define PARSE_FMT_WIRE 1 /* Parse using network-format names */ 52*9525b14bSRao Shoaib 537c478bd9Sstevel@tonic-gate /* Public. */ 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate /* These need to be in the same order as the nres.h:ns_flag enum. */ 567c478bd9Sstevel@tonic-gate struct _ns_flagdata _ns_flagdata[16] = { 57*9525b14bSRao Shoaib { 0x8000, 15 }, /*%< qr. */ 58*9525b14bSRao Shoaib { 0x7800, 11 }, /*%< opcode. */ 59*9525b14bSRao Shoaib { 0x0400, 10 }, /*%< aa. */ 60*9525b14bSRao Shoaib { 0x0200, 9 }, /*%< tc. */ 61*9525b14bSRao Shoaib { 0x0100, 8 }, /*%< rd. */ 62*9525b14bSRao Shoaib { 0x0080, 7 }, /*%< ra. */ 63*9525b14bSRao Shoaib { 0x0040, 6 }, /*%< z. */ 64*9525b14bSRao Shoaib { 0x0020, 5 }, /*%< ad. */ 65*9525b14bSRao Shoaib { 0x0010, 4 }, /*%< cd. */ 66*9525b14bSRao Shoaib { 0x000f, 0 }, /*%< rcode. */ 67*9525b14bSRao Shoaib { 0x0000, 0 }, /*%< expansion (1/6). */ 68*9525b14bSRao Shoaib { 0x0000, 0 }, /*%< expansion (2/6). */ 69*9525b14bSRao Shoaib { 0x0000, 0 }, /*%< expansion (3/6). */ 70*9525b14bSRao Shoaib { 0x0000, 0 }, /*%< expansion (4/6). */ 71*9525b14bSRao Shoaib { 0x0000, 0 }, /*%< expansion (5/6). */ 72*9525b14bSRao Shoaib { 0x0000, 0 }, /*%< expansion (6/6). */ 737c478bd9Sstevel@tonic-gate }; 747c478bd9Sstevel@tonic-gate 757c478bd9Sstevel@tonic-gate int ns_msg_getflag(ns_msg handle, int flag) { 767c478bd9Sstevel@tonic-gate return(((handle)._flags & _ns_flagdata[flag].mask) >> _ns_flagdata[flag].shift); 777c478bd9Sstevel@tonic-gate } 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate int 807c478bd9Sstevel@tonic-gate ns_skiprr(const u_char *ptr, const u_char *eom, ns_sect section, int count) { 817c478bd9Sstevel@tonic-gate const u_char *optr = ptr; 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate for ((void)NULL; count > 0; count--) { 847c478bd9Sstevel@tonic-gate int b, rdlength; 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate b = dn_skipname(ptr, eom); 877c478bd9Sstevel@tonic-gate if (b < 0) 887c478bd9Sstevel@tonic-gate RETERR(EMSGSIZE); 897c478bd9Sstevel@tonic-gate ptr += b/*Name*/ + NS_INT16SZ/*Type*/ + NS_INT16SZ/*Class*/; 907c478bd9Sstevel@tonic-gate if (section != ns_s_qd) { 917c478bd9Sstevel@tonic-gate if (ptr + NS_INT32SZ + NS_INT16SZ > eom) 927c478bd9Sstevel@tonic-gate RETERR(EMSGSIZE); 937c478bd9Sstevel@tonic-gate ptr += NS_INT32SZ/*TTL*/; 947c478bd9Sstevel@tonic-gate NS_GET16(rdlength, ptr); 957c478bd9Sstevel@tonic-gate ptr += rdlength/*RData*/; 967c478bd9Sstevel@tonic-gate } 977c478bd9Sstevel@tonic-gate } 987c478bd9Sstevel@tonic-gate if (ptr > eom) 997c478bd9Sstevel@tonic-gate RETERR(EMSGSIZE); 1007c478bd9Sstevel@tonic-gate return (ptr - optr); 1017c478bd9Sstevel@tonic-gate } 1027c478bd9Sstevel@tonic-gate 1037c478bd9Sstevel@tonic-gate int 1047c478bd9Sstevel@tonic-gate ns_initparse(const u_char *msg, int msglen, ns_msg *handle) { 1057c478bd9Sstevel@tonic-gate const u_char *eom = msg + msglen; 1067c478bd9Sstevel@tonic-gate int i; 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate handle->_msg = msg; 1097c478bd9Sstevel@tonic-gate handle->_eom = eom; 1107c478bd9Sstevel@tonic-gate if (msg + NS_INT16SZ > eom) 1117c478bd9Sstevel@tonic-gate RETERR(EMSGSIZE); 1127c478bd9Sstevel@tonic-gate NS_GET16(handle->_id, msg); 1137c478bd9Sstevel@tonic-gate if (msg + NS_INT16SZ > eom) 1147c478bd9Sstevel@tonic-gate RETERR(EMSGSIZE); 1157c478bd9Sstevel@tonic-gate NS_GET16(handle->_flags, msg); 1167c478bd9Sstevel@tonic-gate for (i = 0; i < ns_s_max; i++) { 1177c478bd9Sstevel@tonic-gate if (msg + NS_INT16SZ > eom) 1187c478bd9Sstevel@tonic-gate RETERR(EMSGSIZE); 1197c478bd9Sstevel@tonic-gate NS_GET16(handle->_counts[i], msg); 1207c478bd9Sstevel@tonic-gate } 1217c478bd9Sstevel@tonic-gate for (i = 0; i < ns_s_max; i++) 1227c478bd9Sstevel@tonic-gate if (handle->_counts[i] == 0) 1237c478bd9Sstevel@tonic-gate handle->_sections[i] = NULL; 1247c478bd9Sstevel@tonic-gate else { 1257c478bd9Sstevel@tonic-gate int b = ns_skiprr(msg, eom, (ns_sect)i, 1267c478bd9Sstevel@tonic-gate handle->_counts[i]); 1277c478bd9Sstevel@tonic-gate 1287c478bd9Sstevel@tonic-gate if (b < 0) 1297c478bd9Sstevel@tonic-gate return (-1); 1307c478bd9Sstevel@tonic-gate handle->_sections[i] = msg; 1317c478bd9Sstevel@tonic-gate msg += b; 1327c478bd9Sstevel@tonic-gate } 1337c478bd9Sstevel@tonic-gate if (msg != eom) 1347c478bd9Sstevel@tonic-gate RETERR(EMSGSIZE); 1357c478bd9Sstevel@tonic-gate setsection(handle, ns_s_max); 1367c478bd9Sstevel@tonic-gate return (0); 1377c478bd9Sstevel@tonic-gate } 1387c478bd9Sstevel@tonic-gate 1397c478bd9Sstevel@tonic-gate int 1407c478bd9Sstevel@tonic-gate ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr) { 1417c478bd9Sstevel@tonic-gate int b; 1427c478bd9Sstevel@tonic-gate int tmp; 1437c478bd9Sstevel@tonic-gate 1447c478bd9Sstevel@tonic-gate /* Make section right. */ 145*9525b14bSRao Shoaib tmp = section; 146*9525b14bSRao Shoaib if (tmp < 0 || section >= ns_s_max) 1477c478bd9Sstevel@tonic-gate RETERR(ENODEV); 1487c478bd9Sstevel@tonic-gate if (section != handle->_sect) 1497c478bd9Sstevel@tonic-gate setsection(handle, section); 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate /* Make rrnum right. */ 1527c478bd9Sstevel@tonic-gate if (rrnum == -1) 1537c478bd9Sstevel@tonic-gate rrnum = handle->_rrnum; 1547c478bd9Sstevel@tonic-gate if (rrnum < 0 || rrnum >= handle->_counts[(int)section]) 1557c478bd9Sstevel@tonic-gate RETERR(ENODEV); 1567c478bd9Sstevel@tonic-gate if (rrnum < handle->_rrnum) 1577c478bd9Sstevel@tonic-gate setsection(handle, section); 1587c478bd9Sstevel@tonic-gate if (rrnum > handle->_rrnum) { 1597c478bd9Sstevel@tonic-gate b = ns_skiprr(handle->_msg_ptr, handle->_eom, section, 1607c478bd9Sstevel@tonic-gate rrnum - handle->_rrnum); 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate if (b < 0) 1637c478bd9Sstevel@tonic-gate return (-1); 1647c478bd9Sstevel@tonic-gate handle->_msg_ptr += b; 1657c478bd9Sstevel@tonic-gate handle->_rrnum = rrnum; 1667c478bd9Sstevel@tonic-gate } 1677c478bd9Sstevel@tonic-gate 1687c478bd9Sstevel@tonic-gate /* Do the parse. */ 1697c478bd9Sstevel@tonic-gate b = dn_expand(handle->_msg, handle->_eom, 1707c478bd9Sstevel@tonic-gate handle->_msg_ptr, rr->name, NS_MAXDNAME); 1717c478bd9Sstevel@tonic-gate if (b < 0) 1727c478bd9Sstevel@tonic-gate return (-1); 1737c478bd9Sstevel@tonic-gate handle->_msg_ptr += b; 1747c478bd9Sstevel@tonic-gate if (handle->_msg_ptr + NS_INT16SZ + NS_INT16SZ > handle->_eom) 1757c478bd9Sstevel@tonic-gate RETERR(EMSGSIZE); 1767c478bd9Sstevel@tonic-gate NS_GET16(rr->type, handle->_msg_ptr); 1777c478bd9Sstevel@tonic-gate NS_GET16(rr->rr_class, handle->_msg_ptr); 1787c478bd9Sstevel@tonic-gate if (section == ns_s_qd) { 1797c478bd9Sstevel@tonic-gate rr->ttl = 0; 1807c478bd9Sstevel@tonic-gate rr->rdlength = 0; 1817c478bd9Sstevel@tonic-gate rr->rdata = NULL; 1827c478bd9Sstevel@tonic-gate } else { 1837c478bd9Sstevel@tonic-gate if (handle->_msg_ptr + NS_INT32SZ + NS_INT16SZ > handle->_eom) 1847c478bd9Sstevel@tonic-gate RETERR(EMSGSIZE); 1857c478bd9Sstevel@tonic-gate NS_GET32(rr->ttl, handle->_msg_ptr); 1867c478bd9Sstevel@tonic-gate NS_GET16(rr->rdlength, handle->_msg_ptr); 1877c478bd9Sstevel@tonic-gate if (handle->_msg_ptr + rr->rdlength > handle->_eom) 1887c478bd9Sstevel@tonic-gate RETERR(EMSGSIZE); 1897c478bd9Sstevel@tonic-gate rr->rdata = handle->_msg_ptr; 1907c478bd9Sstevel@tonic-gate handle->_msg_ptr += rr->rdlength; 1917c478bd9Sstevel@tonic-gate } 1927c478bd9Sstevel@tonic-gate if (++handle->_rrnum > handle->_counts[(int)section]) 1937c478bd9Sstevel@tonic-gate setsection(handle, (ns_sect)((int)section + 1)); 1947c478bd9Sstevel@tonic-gate 1957c478bd9Sstevel@tonic-gate /* All done. */ 1967c478bd9Sstevel@tonic-gate return (0); 1977c478bd9Sstevel@tonic-gate } 1987c478bd9Sstevel@tonic-gate 199*9525b14bSRao Shoaib /* 200*9525b14bSRao Shoaib * This is identical to the above but uses network-format (uncompressed) names. 201*9525b14bSRao Shoaib */ 202*9525b14bSRao Shoaib int 203*9525b14bSRao Shoaib ns_parserr2(ns_msg *handle, ns_sect section, int rrnum, ns_rr2 *rr) { 204*9525b14bSRao Shoaib int b; 205*9525b14bSRao Shoaib int tmp; 206*9525b14bSRao Shoaib 207*9525b14bSRao Shoaib /* Make section right. */ 208*9525b14bSRao Shoaib if ((tmp = section) < 0 || section >= ns_s_max) 209*9525b14bSRao Shoaib RETERR(ENODEV); 210*9525b14bSRao Shoaib if (section != handle->_sect) 211*9525b14bSRao Shoaib setsection(handle, section); 212*9525b14bSRao Shoaib 213*9525b14bSRao Shoaib /* Make rrnum right. */ 214*9525b14bSRao Shoaib if (rrnum == -1) 215*9525b14bSRao Shoaib rrnum = handle->_rrnum; 216*9525b14bSRao Shoaib if (rrnum < 0 || rrnum >= handle->_counts[(int)section]) 217*9525b14bSRao Shoaib RETERR(ENODEV); 218*9525b14bSRao Shoaib if (rrnum < handle->_rrnum) 219*9525b14bSRao Shoaib setsection(handle, section); 220*9525b14bSRao Shoaib if (rrnum > handle->_rrnum) { 221*9525b14bSRao Shoaib b = ns_skiprr(handle->_msg_ptr, handle->_eom, section, 222*9525b14bSRao Shoaib rrnum - handle->_rrnum); 223*9525b14bSRao Shoaib 224*9525b14bSRao Shoaib if (b < 0) 225*9525b14bSRao Shoaib return (-1); 226*9525b14bSRao Shoaib handle->_msg_ptr += b; 227*9525b14bSRao Shoaib handle->_rrnum = rrnum; 228*9525b14bSRao Shoaib } 229*9525b14bSRao Shoaib 230*9525b14bSRao Shoaib /* Do the parse. */ 231*9525b14bSRao Shoaib b = ns_name_unpack2(handle->_msg, handle->_eom, handle->_msg_ptr, 232*9525b14bSRao Shoaib rr->nname, NS_MAXNNAME, &rr->nnamel); 233*9525b14bSRao Shoaib if (b < 0) 234*9525b14bSRao Shoaib return (-1); 235*9525b14bSRao Shoaib handle->_msg_ptr += b; 236*9525b14bSRao Shoaib if (handle->_msg_ptr + NS_INT16SZ + NS_INT16SZ > handle->_eom) 237*9525b14bSRao Shoaib RETERR(EMSGSIZE); 238*9525b14bSRao Shoaib NS_GET16(rr->type, handle->_msg_ptr); 239*9525b14bSRao Shoaib NS_GET16(rr->rr_class, handle->_msg_ptr); 240*9525b14bSRao Shoaib if (section == ns_s_qd) { 241*9525b14bSRao Shoaib rr->ttl = 0; 242*9525b14bSRao Shoaib rr->rdlength = 0; 243*9525b14bSRao Shoaib rr->rdata = NULL; 244*9525b14bSRao Shoaib } else { 245*9525b14bSRao Shoaib if (handle->_msg_ptr + NS_INT32SZ + NS_INT16SZ > handle->_eom) 246*9525b14bSRao Shoaib RETERR(EMSGSIZE); 247*9525b14bSRao Shoaib NS_GET32(rr->ttl, handle->_msg_ptr); 248*9525b14bSRao Shoaib NS_GET16(rr->rdlength, handle->_msg_ptr); 249*9525b14bSRao Shoaib if (handle->_msg_ptr + rr->rdlength > handle->_eom) 250*9525b14bSRao Shoaib RETERR(EMSGSIZE); 251*9525b14bSRao Shoaib rr->rdata = handle->_msg_ptr; 252*9525b14bSRao Shoaib handle->_msg_ptr += rr->rdlength; 253*9525b14bSRao Shoaib } 254*9525b14bSRao Shoaib if (++handle->_rrnum > handle->_counts[(int)section]) 255*9525b14bSRao Shoaib setsection(handle, (ns_sect)((int)section + 1)); 256*9525b14bSRao Shoaib 257*9525b14bSRao Shoaib /* All done. */ 258*9525b14bSRao Shoaib return (0); 259*9525b14bSRao Shoaib } 260*9525b14bSRao Shoaib 2617c478bd9Sstevel@tonic-gate /* Private. */ 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate static void 2647c478bd9Sstevel@tonic-gate setsection(ns_msg *msg, ns_sect sect) { 2657c478bd9Sstevel@tonic-gate msg->_sect = sect; 2667c478bd9Sstevel@tonic-gate if (sect == ns_s_max) { 2677c478bd9Sstevel@tonic-gate msg->_rrnum = -1; 2687c478bd9Sstevel@tonic-gate msg->_msg_ptr = NULL; 2697c478bd9Sstevel@tonic-gate } else { 2707c478bd9Sstevel@tonic-gate msg->_rrnum = 0; 2717c478bd9Sstevel@tonic-gate msg->_msg_ptr = msg->_sections[(int)sect]; 2727c478bd9Sstevel@tonic-gate } 2737c478bd9Sstevel@tonic-gate } 274*9525b14bSRao Shoaib 275*9525b14bSRao Shoaib /*! \file */ 276