Back to index

glibc  2.9
ns_parse.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
00003  * Copyright (c) 1996,1999 by Internet Software Consortium.
00004  *
00005  * Permission to use, copy, modify, and distribute this software for any
00006  * purpose with or without fee is hereby granted, provided that the above
00007  * copyright notice and this permission notice appear in all copies.
00008  *
00009  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
00010  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
00011  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
00012  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00013  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00014  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
00015  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00016  */
00017 
00018 #if !defined(_LIBC) && !defined(lint)
00019 static const char rcsid[] = "$BINDId: ns_parse.c,v 8.13 1999/10/13 16:39:35 vixie Exp $";
00020 #endif
00021 
00022 /* Import. */
00023 
00024 #include <sys/types.h>
00025 
00026 #include <netinet/in.h>
00027 #include <arpa/nameser.h>
00028 
00029 #include <errno.h>
00030 #include <resolv.h>
00031 #include <string.h>
00032 
00033 /* Forward. */
00034 
00035 static void   setsection(ns_msg *msg, ns_sect sect);
00036 
00037 /* Macros. */
00038 
00039 #define RETERR(err) do { __set_errno (err); return (-1); } while (0)
00040 
00041 /* Public. */
00042 
00043 /* These need to be in the same order as the nres.h:ns_flag enum. */
00044 const struct _ns_flagdata _ns_flagdata[16] = {
00045        { 0x8000, 15 },             /*%< qr. */
00046        { 0x7800, 11 },             /*%< opcode. */
00047        { 0x0400, 10 },             /*%< aa. */
00048        { 0x0200, 9 },              /*%< tc. */
00049        { 0x0100, 8 },              /*%< rd. */
00050        { 0x0080, 7 },              /*%< ra. */
00051        { 0x0040, 6 },              /*%< z. */
00052        { 0x0020, 5 },              /*%< ad. */
00053        { 0x0010, 4 },              /*%< cd. */
00054        { 0x000f, 0 },              /*%< rcode. */
00055        { 0x0000, 0 },              /*%< expansion (1/6). */
00056        { 0x0000, 0 },              /*%< expansion (2/6). */
00057        { 0x0000, 0 },              /*%< expansion (3/6). */
00058        { 0x0000, 0 },              /*%< expansion (4/6). */
00059        { 0x0000, 0 },              /*%< expansion (5/6). */
00060        { 0x0000, 0 },              /*%< expansion (6/6). */
00061 };
00062 
00063 #undef ns_msg_getflag
00064 int ns_msg_getflag(ns_msg handle, int flag) {
00065        return(((handle)._flags & _ns_flagdata[flag].mask) >> _ns_flagdata[flag].shift);
00066 }
00067 
00068 int
00069 ns_skiprr(const u_char *ptr, const u_char *eom, ns_sect section, int count) {
00070        const u_char *optr = ptr;
00071 
00072        for ((void)NULL; count > 0; count--) {
00073               int b, rdlength;
00074 
00075               b = dn_skipname(ptr, eom);
00076               if (b < 0)
00077                      RETERR(EMSGSIZE);
00078               ptr += b/*Name*/ + NS_INT16SZ/*Type*/ + NS_INT16SZ/*Class*/;
00079               if (section != ns_s_qd) {
00080                      if (ptr + NS_INT32SZ + NS_INT16SZ > eom)
00081                             RETERR(EMSGSIZE);
00082                      ptr += NS_INT32SZ/*TTL*/;
00083                      NS_GET16(rdlength, ptr);
00084                      ptr += rdlength/*RData*/;
00085               }
00086        }
00087        if (ptr > eom)
00088               RETERR(EMSGSIZE);
00089        return (ptr - optr);
00090 }
00091 libresolv_hidden_def (ns_skiprr)
00092 
00093 int
00094 ns_initparse(const u_char *msg, int msglen, ns_msg *handle) {
00095        const u_char *eom = msg + msglen;
00096        int i;
00097 
00098        memset(handle, 0x5e, sizeof *handle);
00099        handle->_msg = msg;
00100        handle->_eom = eom;
00101        if (msg + NS_INT16SZ > eom)
00102               RETERR(EMSGSIZE);
00103        NS_GET16(handle->_id, msg);
00104        if (msg + NS_INT16SZ > eom)
00105               RETERR(EMSGSIZE);
00106        NS_GET16(handle->_flags, msg);
00107        for (i = 0; i < ns_s_max; i++) {
00108               if (msg + NS_INT16SZ > eom)
00109                      RETERR(EMSGSIZE);
00110               NS_GET16(handle->_counts[i], msg);
00111        }
00112        for (i = 0; i < ns_s_max; i++)
00113               if (handle->_counts[i] == 0)
00114                      handle->_sections[i] = NULL;
00115               else {
00116                      int b = ns_skiprr(msg, eom, (ns_sect)i,
00117                                      handle->_counts[i]);
00118 
00119                      if (b < 0)
00120                             return (-1);
00121                      handle->_sections[i] = msg;
00122                      msg += b;
00123               }
00124        if (msg != eom)
00125               RETERR(EMSGSIZE);
00126        setsection(handle, ns_s_max);
00127        return (0);
00128 }
00129 libresolv_hidden_def (ns_initparse)
00130 
00131 int
00132 ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr) {
00133        int b;
00134        int tmp;
00135 
00136        /* Make section right. */
00137        tmp = section;
00138        if (tmp < 0 || section >= ns_s_max)
00139               RETERR(ENODEV);
00140        if (section != handle->_sect)
00141               setsection(handle, section);
00142 
00143        /* Make rrnum right. */
00144        if (rrnum == -1)
00145               rrnum = handle->_rrnum;
00146        if (rrnum < 0 || rrnum >= handle->_counts[(int)section])
00147               RETERR(ENODEV);
00148        if (rrnum < handle->_rrnum)
00149               setsection(handle, section);
00150        if (rrnum > handle->_rrnum) {
00151               b = ns_skiprr(handle->_msg_ptr, handle->_eom, section,
00152                            rrnum - handle->_rrnum);
00153 
00154               if (b < 0)
00155                      return (-1);
00156               handle->_msg_ptr += b;
00157               handle->_rrnum = rrnum;
00158        }
00159 
00160        /* Do the parse. */
00161        b = dn_expand(handle->_msg, handle->_eom,
00162                     handle->_msg_ptr, rr->name, NS_MAXDNAME);
00163        if (b < 0)
00164               return (-1);
00165        handle->_msg_ptr += b;
00166        if (handle->_msg_ptr + NS_INT16SZ + NS_INT16SZ > handle->_eom)
00167               RETERR(EMSGSIZE);
00168        NS_GET16(rr->type, handle->_msg_ptr);
00169        NS_GET16(rr->rr_class, handle->_msg_ptr);
00170        if (section == ns_s_qd) {
00171               rr->ttl = 0;
00172               rr->rdlength = 0;
00173               rr->rdata = NULL;
00174        } else {
00175               if (handle->_msg_ptr + NS_INT32SZ + NS_INT16SZ > handle->_eom)
00176                      RETERR(EMSGSIZE);
00177               NS_GET32(rr->ttl, handle->_msg_ptr);
00178               NS_GET16(rr->rdlength, handle->_msg_ptr);
00179               if (handle->_msg_ptr + rr->rdlength > handle->_eom)
00180                      RETERR(EMSGSIZE);
00181               rr->rdata = handle->_msg_ptr;
00182               handle->_msg_ptr += rr->rdlength;
00183        }
00184        if (++handle->_rrnum > handle->_counts[(int)section])
00185               setsection(handle, (ns_sect)((int)section + 1));
00186 
00187        /* All done. */
00188        return (0);
00189 }
00190 libresolv_hidden_def (ns_parserr)
00191 
00192 /* Private. */
00193 
00194 static void
00195 setsection(ns_msg *msg, ns_sect sect) {
00196        msg->_sect = sect;
00197        if (sect == ns_s_max) {
00198               msg->_rrnum = -1;
00199               msg->_msg_ptr = NULL;
00200        } else {
00201               msg->_rrnum = 0;
00202               msg->_msg_ptr = msg->_sections[(int)sect];
00203        }
00204 }
00205