@@ -20,30 +20,43 @@ namespace {
20
20
constexpr unsigned int RECORD_PTR = 12 ;
21
21
}
22
22
23
- static frg::string<MemoryAllocator> read_dns_name (char *buf, char *&it) {
23
+ static frg::optional<frg::string<MemoryAllocator>> read_dns_name (uint8_t *buf,
24
+ size_t buf_size, uint8_t *&it) {
24
25
frg::string<MemoryAllocator> res{getAllocator ()};
25
- while ( true ) {
26
- char code = *it++;
27
- if ((code & 0xC0 ) == 0xC0 ) {
26
+ while (it < buf + buf_size ) {
27
+ uint8_t code = *it++;
28
+ if ((code & 0xC0 ) == 0xC0 ) {
28
29
// pointer
30
+ if (it + 1 > buf + buf_size)
31
+ return frg::null_opt;
32
+
29
33
uint8_t offset = ((code & 0x3F ) << 8 ) | *it++;
34
+ if (offset >= buf_size)
35
+ return frg::null_opt;
36
+
30
37
auto offset_it = buf + offset;
31
- return res + read_dns_name (buf, offset_it);
32
- } else if (!(code & 0xC0 )) {
38
+ auto sub_name = read_dns_name (buf, buf_size, offset_it);
39
+ if (!sub_name)
40
+ return frg::null_opt;
41
+
42
+ return res + *sub_name;
43
+ } else if (!(code & 0xC0 )) {
33
44
if (!code)
34
- break ;
45
+ return res;
46
+ else if (it + code > buf + buf_size)
47
+ return frg::null_opt;
35
48
36
49
for (int i = 0 ; i < code; i++)
37
50
res += (*it++);
38
51
39
- if (*it)
52
+ if (it < buf + buf_size && *it)
40
53
res += ' .' ;
41
54
} else {
42
- break ;
55
+ return frg::null_opt ;
43
56
}
44
57
}
45
58
46
- return res ;
59
+ return frg::null_opt ;
47
60
}
48
61
49
62
int lookup_name_dns (struct lookup_result &buf, const char *name,
@@ -105,10 +118,10 @@ int lookup_name_dns(struct lookup_result &buf, const char *name,
105
118
return -EAI_SYSTEM;
106
119
}
107
120
108
- char response[256 ];
121
+ uint8_t response[1500 ];
109
122
ssize_t rlen;
110
123
int num_ans = 0 ;
111
- while ((rlen = recvfrom (fd, response, 256 , 0 , NULL , NULL )) >= 0 ) {
124
+ while ((rlen = recvfrom (fd, response, sizeof (response) , 0 , NULL , NULL )) >= 0 ) {
112
125
if ((size_t )rlen < sizeof (struct dns_header ))
113
126
continue ;
114
127
auto response_header = reinterpret_cast <struct dns_header *>(response);
@@ -117,33 +130,44 @@ int lookup_name_dns(struct lookup_result &buf, const char *name,
117
130
118
131
auto it = response + sizeof (struct dns_header );
119
132
for (int i = 0 ; i < ntohs (response_header->no_q ); i++) {
120
- auto dns_name = read_dns_name (response, it);
121
- (void ) dns_name;
133
+ auto dns_name = read_dns_name (response, sizeof (response), it);
134
+ if (!dns_name)
135
+ return -EAI_FAIL;
122
136
it += 4 ;
123
137
}
124
138
125
139
for (int i = 0 ; i < ntohs (response_header->no_ans ); i++) {
126
- struct dns_addr_buf buffer;
127
- auto dns_name = read_dns_name (response, it);
140
+ auto dns_name = read_dns_name (response, sizeof (response), it);
141
+ if (!dns_name)
142
+ return -EAI_FAIL;
143
+ if (it + 10 > response + rlen)
144
+ return -EAI_FAIL;
128
145
129
146
uint16_t rr_type = (it[0 ] << 8 ) | it[1 ];
130
147
uint16_t rr_class = (it[2 ] << 8 ) | it[3 ];
131
148
uint16_t rr_length = (it[8 ] << 8 ) | it[9 ];
132
149
it += 10 ;
133
150
(void )rr_class;
151
+ if (it + rr_length > response + rlen)
152
+ return -EAI_FAIL;
134
153
154
+ struct dns_addr_buf buffer;
135
155
switch (rr_type) {
136
156
case RECORD_A:
137
157
memcpy (buffer.addr , it, rr_length);
138
158
it += rr_length;
139
159
buffer.family = AF_INET;
140
- buffer.name = std::move (dns_name);
160
+ buffer.name = std::move (* dns_name);
141
161
buf.buf .push (std::move (buffer));
142
162
break ;
143
- case RECORD_CNAME:
144
- canon_name = read_dns_name (response, it);
145
- buf.aliases .push (std::move (dns_name));
163
+ case RECORD_CNAME: {
164
+ auto cname = read_dns_name (response, sizeof (response), it);
165
+ if (!cname)
166
+ return -EAI_FAIL;
167
+ canon_name = std::move (*cname);
168
+ buf.aliases .push (std::move (*dns_name));
146
169
break ;
170
+ }
147
171
default :
148
172
mlibc::infoLogger () << " lookup_name_dns: unknown rr type "
149
173
<< rr_type << frg::endlog;
@@ -234,10 +258,10 @@ int lookup_addr_dns(frg::span<char> name, frg::array<uint8_t, 16> &addr, int fam
234
258
return -EAI_SYSTEM;
235
259
}
236
260
237
- char response[256 ];
261
+ uint8_t response[1500 ];
238
262
ssize_t rlen;
239
263
int num_ans = 0 ;
240
- while ((rlen = recvfrom (fd, response, 256 , 0 , NULL , NULL )) >= 0 ) {
264
+ while ((rlen = recvfrom (fd, response, sizeof (response) , 0 , NULL , NULL )) >= 0 ) {
241
265
if ((size_t )rlen < sizeof (struct dns_header ))
242
266
continue ;
243
267
auto response_header = reinterpret_cast <struct dns_header *>(response);
@@ -246,31 +270,38 @@ int lookup_addr_dns(frg::span<char> name, frg::array<uint8_t, 16> &addr, int fam
246
270
247
271
auto it = response + sizeof (struct dns_header );
248
272
for (int i = 0 ; i < ntohs (response_header->no_q ); i++) {
249
- auto dns_name = read_dns_name (response, it);
250
- (void ) dns_name;
273
+ auto dns_name = read_dns_name (response, sizeof (response), it);
274
+ if (!dns_name)
275
+ return -EAI_FAIL;
251
276
it += 4 ;
252
277
}
253
278
254
279
for (int i = 0 ; i < ntohs (response_header->no_ans ); i++) {
255
- struct dns_addr_buf buffer;
256
- auto dns_name = read_dns_name (response, it);
280
+ auto dns_name = read_dns_name (response, sizeof (response), it);
281
+ if (!dns_name)
282
+ return -EAI_FAIL;
283
+ if (it + 10 > response + rlen)
284
+ return -EAI_FAIL;
257
285
258
286
uint16_t rr_type = (it[0 ] << 8 ) | it[1 ];
259
287
uint16_t rr_class = (it[2 ] << 8 ) | it[3 ];
260
288
uint16_t rr_length = (it[8 ] << 8 ) | it[9 ];
261
289
it += 10 ;
262
290
(void )rr_class;
263
- (void )rr_length;
264
291
265
- (void )dns_name;
292
+ if (it + rr_length > response + rlen)
293
+ return -EAI_FAIL;
266
294
295
+ struct dns_addr_buf buffer;
267
296
switch (rr_type) {
268
297
case RECORD_PTR: {
269
- auto ptr_name = read_dns_name (response, it);
270
- if (ptr_name.size () >= name.size ())
298
+ auto ptr_name = read_dns_name (response, sizeof (response), it);
299
+ if (!ptr_name)
300
+ return -EAI_FAIL;
301
+ else if (ptr_name->size () >= name.size ())
271
302
return -EAI_OVERFLOW;
272
- std::copy (ptr_name. begin (), ptr_name. end (), name.data ());
273
- name.data ()[ptr_name. size ()] = ' \0 ' ;
303
+ std::copy (ptr_name-> begin (), ptr_name-> end (), name.data ());
304
+ name.data ()[ptr_name-> size ()] = ' \0 ' ;
274
305
return 1 ;
275
306
}
276
307
default :
0 commit comments