00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef lint
00019 static const char rcsid[] = "$Id: ns_parse.c,v 1.3.2.1 2003/06/27 03:51:42 marka Exp $";
00020 #endif
00021
00022
00023
00024
00025 #include "config.h"
00026
00027 #include <sys/types.h>
00028
00029 #include <netinet/in.h>
00030 #include "arpa_nameser.h"
00031
00032 #include <errno.h>
00033
00034 #ifdef HAVE_STRING_H
00035 # include <string.h>
00036 #else
00037 # ifdef HAVE_STRINGS_H
00038 # include <strings.h>
00039 # endif
00040 #endif
00041
00042
00043
00044
00045
00046
00047 static void setsection(ns_msg *msg, ns_sect sect);
00048
00049
00050
00051 #define RETERR(err) do { errno = (err); return (-1); } while (0)
00052
00053
00054
00055
00056 struct _ns_flagdata _ns_flagdata[16] = {
00057 { 0x8000, 15 },
00058 { 0x7800, 11 },
00059 { 0x0400, 10 },
00060 { 0x0200, 9 },
00061 { 0x0100, 8 },
00062 { 0x0080, 7 },
00063 { 0x0040, 6 },
00064 { 0x0020, 5 },
00065 { 0x0010, 4 },
00066 { 0x000f, 0 },
00067 { 0x0000, 0 },
00068 { 0x0000, 0 },
00069 { 0x0000, 0 },
00070 { 0x0000, 0 },
00071 { 0x0000, 0 },
00072 { 0x0000, 0 },
00073 };
00074
00075 int
00076 ns_skiprr(const u_char *ptr, const u_char *eom, ns_sect section, int count) {
00077 const u_char *optr = ptr;
00078
00079 for ((void)NULL; count > 0; count--) {
00080 int b, rdlength;
00081
00082 b = dn_skipname(ptr, eom);
00083 if (b < 0)
00084 RETERR(EMSGSIZE);
00085 ptr += b + NS_INT16SZ + NS_INT16SZ;
00086 if (section != ns_s_qd) {
00087 if (ptr + NS_INT32SZ + NS_INT16SZ > eom)
00088 RETERR(EMSGSIZE);
00089 ptr += NS_INT32SZ;
00090 NS_GET16(rdlength, ptr);
00091 ptr += rdlength;
00092 }
00093 }
00094 if (ptr > eom)
00095 RETERR(EMSGSIZE);
00096 return (ptr - optr);
00097 }
00098
00099 int
00100 ns_initparse(const u_char *msg, int msglen, ns_msg *handle) {
00101 const u_char *eom = msg + msglen;
00102 int i;
00103
00104 memset(handle, 0x5e, sizeof *handle);
00105 handle->_msg = msg;
00106 handle->_eom = eom;
00107 if (msg + NS_INT16SZ > eom)
00108 RETERR(EMSGSIZE);
00109 NS_GET16(handle->_id, msg);
00110 if (msg + NS_INT16SZ > eom)
00111 RETERR(EMSGSIZE);
00112 NS_GET16(handle->_flags, msg);
00113 for (i = 0; i < ns_s_max; i++) {
00114 if (msg + NS_INT16SZ > eom)
00115 RETERR(EMSGSIZE);
00116 NS_GET16(handle->_counts[i], msg);
00117 }
00118 for (i = 0; i < ns_s_max; i++)
00119 if (handle->_counts[i] == 0)
00120 handle->_sections[i] = NULL;
00121 else {
00122 int b = ns_skiprr(msg, eom, (ns_sect)i,
00123 handle->_counts[i]);
00124
00125 if (b < 0)
00126 return (-1);
00127 handle->_sections[i] = msg;
00128 msg += b;
00129 }
00130 if (msg != eom)
00131 RETERR(EMSGSIZE);
00132 setsection(handle, ns_s_max);
00133 return (0);
00134 }
00135
00136 int
00137 ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr) {
00138 int b;
00139 int tmp;
00140
00141
00142 if ((tmp = section) < 0 || section >= ns_s_max)
00143 RETERR(ENODEV);
00144 if (section != handle->_sect)
00145 setsection(handle, section);
00146
00147
00148 if (rrnum == -1)
00149 rrnum = handle->_rrnum;
00150 if (rrnum < 0 || rrnum >= handle->_counts[(int)section])
00151 RETERR(ENODEV);
00152 if (rrnum < handle->_rrnum)
00153 setsection(handle, section);
00154 if (rrnum > handle->_rrnum) {
00155 b = ns_skiprr(handle->_msg_ptr, handle->_eom, section,
00156 rrnum - handle->_rrnum);
00157
00158 if (b < 0)
00159 return (-1);
00160 handle->_msg_ptr += b;
00161 handle->_rrnum = rrnum;
00162 }
00163
00164
00165 b = dn_expand(handle->_msg, handle->_eom,
00166 handle->_msg_ptr, rr->name, NS_MAXDNAME);
00167 if (b < 0)
00168 return (-1);
00169 handle->_msg_ptr += b;
00170 if (handle->_msg_ptr + NS_INT16SZ + NS_INT16SZ > handle->_eom)
00171 RETERR(EMSGSIZE);
00172 NS_GET16(rr->type, handle->_msg_ptr);
00173 NS_GET16(rr->rr_class, handle->_msg_ptr);
00174 if (section == ns_s_qd) {
00175 rr->ttl = 0;
00176 rr->rdlength = 0;
00177 rr->rdata = NULL;
00178 } else {
00179 if (handle->_msg_ptr + NS_INT32SZ + NS_INT16SZ > handle->_eom)
00180 RETERR(EMSGSIZE);
00181 NS_GET32(rr->ttl, handle->_msg_ptr);
00182 NS_GET16(rr->rdlength, handle->_msg_ptr);
00183 if (handle->_msg_ptr + rr->rdlength > handle->_eom)
00184 RETERR(EMSGSIZE);
00185 rr->rdata = handle->_msg_ptr;
00186 handle->_msg_ptr += rr->rdlength;
00187 }
00188 if (++handle->_rrnum > handle->_counts[(int)section])
00189 setsection(handle, (ns_sect)((int)section + 1));
00190
00191
00192 return (0);
00193 }
00194
00195
00196
00197 static void
00198 setsection(ns_msg *msg, ns_sect sect) {
00199 msg->_sect = sect;
00200 if (sect == ns_s_max) {
00201 msg->_rrnum = -1;
00202 msg->_msg_ptr = NULL;
00203 } else {
00204 msg->_rrnum = 0;
00205 msg->_msg_ptr = msg->_sections[(int)sect];
00206 }
00207 }