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