1 #define _BSD_SOURCE
2 #include <errno.h>
3 #include <stddef.h>
4 #include <resolv.h>
5 #include <arpa/nameser.h>
6
7 const struct _ns_flagdata _ns_flagdata[16] = {
8 { 0x8000, 15 },
9 { 0x7800, 11 },
10 { 0x0400, 10 },
11 { 0x0200, 9 },
12 { 0x0100, 8 },
13 { 0x0080, 7 },
14 { 0x0040, 6 },
15 { 0x0020, 5 },
16 { 0x0010, 4 },
17 { 0x000f, 0 },
18 { 0x0000, 0 },
19 { 0x0000, 0 },
20 { 0x0000, 0 },
21 { 0x0000, 0 },
22 { 0x0000, 0 },
23 { 0x0000, 0 },
24 };
25
ns_get16(const unsigned char * cp)26 unsigned ns_get16(const unsigned char *cp)
27 {
28 return cp[0]<<8 | cp[1];
29 }
30
ns_get32(const unsigned char * cp)31 unsigned long ns_get32(const unsigned char *cp)
32 {
33 return (unsigned)cp[0]<<24 | cp[1]<<16 | cp[2]<<8 | cp[3];
34 }
35
ns_put16(unsigned s,unsigned char * cp)36 void ns_put16(unsigned s, unsigned char *cp)
37 {
38 *cp++ = s>>8;
39 *cp++ = s;
40 }
41
ns_put32(unsigned long l,unsigned char * cp)42 void ns_put32(unsigned long l, unsigned char *cp)
43 {
44 *cp++ = l>>24;
45 *cp++ = l>>16;
46 *cp++ = l>>8;
47 *cp++ = l;
48 }
49
ns_initparse(const unsigned char * msg,int msglen,ns_msg * handle)50 int ns_initparse(const unsigned char *msg, int msglen, ns_msg *handle)
51 {
52 int i, r;
53
54 handle->_msg = msg;
55 handle->_eom = msg + msglen;
56 if (msglen < (2 + ns_s_max) * NS_INT16SZ) goto bad;
57 NS_GET16(handle->_id, msg);
58 NS_GET16(handle->_flags, msg);
59 for (i = 0; i < ns_s_max; i++) NS_GET16(handle->_counts[i], msg);
60 for (i = 0; i < ns_s_max; i++) {
61 if (handle->_counts[i]) {
62 handle->_sections[i] = msg;
63 r = ns_skiprr(msg, handle->_eom, i, handle->_counts[i]);
64 if (r < 0) return -1;
65 msg += r;
66 } else {
67 handle->_sections[i] = NULL;
68 }
69 }
70 if (msg != handle->_eom) goto bad;
71 handle->_sect = ns_s_max;
72 handle->_rrnum = -1;
73 handle->_msg_ptr = NULL;
74 return 0;
75 bad:
76 errno = EMSGSIZE;
77 return -1;
78 }
79
ns_skiprr(const unsigned char * ptr,const unsigned char * eom,ns_sect section,int count)80 int ns_skiprr(const unsigned char *ptr, const unsigned char *eom, ns_sect section, int count)
81 {
82 const unsigned char *p = ptr;
83 int r;
84
85 while (count--) {
86 r = dn_skipname(p, eom);
87 if (r < 0) goto bad;
88 if (r + 2 * NS_INT16SZ > eom - p) goto bad;
89 p += r + 2 * NS_INT16SZ;
90 if (section != ns_s_qd) {
91 if (NS_INT32SZ + NS_INT16SZ > eom - p) goto bad;
92 p += NS_INT32SZ;
93 NS_GET16(r, p);
94 if (r > eom - p) goto bad;
95 p += r;
96 }
97 }
98 return p - ptr;
99 bad:
100 errno = EMSGSIZE;
101 return -1;
102 }
103
ns_parserr(ns_msg * handle,ns_sect section,int rrnum,ns_rr * rr)104 int ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr)
105 {
106 int r;
107
108 if (section < 0 || section >= ns_s_max) goto bad;
109 if (section != handle->_sect) {
110 handle->_sect = section;
111 handle->_rrnum = 0;
112 handle->_msg_ptr = handle->_sections[section];
113 }
114 if (rrnum == -1) rrnum = handle->_rrnum;
115 if (rrnum < 0 || rrnum >= handle->_counts[section]) goto bad;
116 if (rrnum < handle->_rrnum) {
117 handle->_rrnum = 0;
118 handle->_msg_ptr = handle->_sections[section];
119 }
120 if (rrnum > handle->_rrnum) {
121 r = ns_skiprr(handle->_msg_ptr, handle->_eom, section, rrnum - handle->_rrnum);
122 if (r < 0) return -1;
123 handle->_msg_ptr += r;
124 handle->_rrnum = rrnum;
125 }
126 r = ns_name_uncompress(handle->_msg, handle->_eom, handle->_msg_ptr, rr->name, NS_MAXDNAME);
127 if (r < 0) return -1;
128 handle->_msg_ptr += r;
129 if (2 * NS_INT16SZ > handle->_eom - handle->_msg_ptr) goto size;
130 NS_GET16(rr->type, handle->_msg_ptr);
131 NS_GET16(rr->rr_class, handle->_msg_ptr);
132 if (section != ns_s_qd) {
133 if (NS_INT32SZ + NS_INT16SZ > handle->_eom - handle->_msg_ptr) goto size;
134 NS_GET32(rr->ttl, handle->_msg_ptr);
135 NS_GET16(rr->rdlength, handle->_msg_ptr);
136 if (rr->rdlength > handle->_eom - handle->_msg_ptr) goto size;
137 rr->rdata = handle->_msg_ptr;
138 handle->_msg_ptr += rr->rdlength;
139 } else {
140 rr->ttl = 0;
141 rr->rdlength = 0;
142 rr->rdata = NULL;
143 }
144 handle->_rrnum++;
145 if (handle->_rrnum > handle->_counts[section]) {
146 handle->_sect = section + 1;
147 if (handle->_sect == ns_s_max) {
148 handle->_rrnum = -1;
149 handle->_msg_ptr = NULL;
150 } else {
151 handle->_rrnum = 0;
152 }
153 }
154 return 0;
155 bad:
156 errno = ENODEV;
157 return -1;
158 size:
159 errno = EMSGSIZE;
160 return -1;
161 }
162
ns_name_uncompress(const unsigned char * msg,const unsigned char * eom,const unsigned char * src,char * dst,size_t dstsiz)163 int ns_name_uncompress(const unsigned char *msg, const unsigned char *eom,
164 const unsigned char *src, char *dst, size_t dstsiz)
165 {
166 int r;
167 r = dn_expand(msg, eom, src, dst, dstsiz);
168 if (r < 0) errno = EMSGSIZE;
169 return r;
170 }
171
172