diff options
author | Jacek Antonelli | 2008-09-06 18:24:57 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-09-06 18:25:07 -0500 |
commit | 798d367d54a6c6379ad355bd8345fa40e31e7fe9 (patch) | |
tree | 1921f1708cd0240648c97bc02df2c2ab5f2fc41e /linden/indra/llmessage/llares.cpp | |
parent | Second Life viewer sources 1.20.15 (diff) | |
download | meta-impy-798d367d54a6c6379ad355bd8345fa40e31e7fe9.zip meta-impy-798d367d54a6c6379ad355bd8345fa40e31e7fe9.tar.gz meta-impy-798d367d54a6c6379ad355bd8345fa40e31e7fe9.tar.bz2 meta-impy-798d367d54a6c6379ad355bd8345fa40e31e7fe9.tar.xz |
Second Life viewer sources 1.21.0-RC
Diffstat (limited to 'linden/indra/llmessage/llares.cpp')
-rw-r--r-- | linden/indra/llmessage/llares.cpp | 804 |
1 files changed, 804 insertions, 0 deletions
diff --git a/linden/indra/llmessage/llares.cpp b/linden/indra/llmessage/llares.cpp new file mode 100644 index 0000000..5a310b3 --- /dev/null +++ b/linden/indra/llmessage/llares.cpp | |||
@@ -0,0 +1,804 @@ | |||
1 | /** | ||
2 | * @file llares.cpp | ||
3 | * @author Bryan O'Sullivan | ||
4 | * @date 2007-08-15 | ||
5 | * @brief Wrapper for asynchronous DNS lookups. | ||
6 | * | ||
7 | * $LicenseInfo:firstyear=2007&license=viewergpl$ | ||
8 | * | ||
9 | * Copyright (c) 2007-2008, Linden Research, Inc. | ||
10 | * | ||
11 | * Second Life Viewer Source Code | ||
12 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
13 | * to you under the terms of the GNU General Public License, version 2.0 | ||
14 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
15 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
16 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
17 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
18 | * | ||
19 | * There are special exceptions to the terms and conditions of the GPL as | ||
20 | * it is applied to this Source Code. View the full text of the exception | ||
21 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
22 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
23 | * | ||
24 | * By copying, modifying or distributing this software, you acknowledge | ||
25 | * that you have read and understood your obligations described above, | ||
26 | * and agree to abide by those obligations. | ||
27 | * | ||
28 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
29 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
30 | * COMPLETENESS OR PERFORMANCE. | ||
31 | * $/LicenseInfo$ | ||
32 | */ | ||
33 | |||
34 | #include "linden_common.h" | ||
35 | |||
36 | #include <ares_dns.h> | ||
37 | #include <ares_version.h> | ||
38 | |||
39 | #include "apr_portable.h" | ||
40 | #include "apr_network_io.h" | ||
41 | #include "apr_poll.h" | ||
42 | |||
43 | #include "llapr.h" | ||
44 | #include "llares.h" | ||
45 | |||
46 | #if defined(LL_WINDOWS) | ||
47 | # define ns_c_in 1 | ||
48 | # define NS_HFIXEDSZ 12 /* #/bytes of fixed data in header */ | ||
49 | # define NS_QFIXEDSZ 4 /* #/bytes of fixed data in query */ | ||
50 | # define NS_RRFIXEDSZ 10 /* #/bytes of fixed data in r record */ | ||
51 | #else | ||
52 | # include <arpa/nameser.h> | ||
53 | #endif | ||
54 | |||
55 | LLAres::HostResponder::~HostResponder() | ||
56 | { | ||
57 | } | ||
58 | |||
59 | void LLAres::HostResponder::hostResult(const hostent *ent) | ||
60 | { | ||
61 | llinfos << "LLAres::HostResponder::hostResult not implemented" << llendl; | ||
62 | } | ||
63 | |||
64 | void LLAres::HostResponder::hostError(int code) | ||
65 | { | ||
66 | llinfos << "LLAres::HostResponder::hostError " << code << ": " | ||
67 | << LLAres::strerror(code) << llendl; | ||
68 | } | ||
69 | |||
70 | LLAres::NameInfoResponder::~NameInfoResponder() | ||
71 | { | ||
72 | } | ||
73 | |||
74 | void LLAres::NameInfoResponder::nameInfoResult(const char *node, | ||
75 | const char *service) | ||
76 | { | ||
77 | llinfos << "LLAres::NameInfoResponder::nameInfoResult not implemented" | ||
78 | << llendl; | ||
79 | } | ||
80 | |||
81 | void LLAres::NameInfoResponder::nameInfoError(int code) | ||
82 | { | ||
83 | llinfos << "LLAres::NameInfoResponder::nameInfoError " << code << ": " | ||
84 | << LLAres::strerror(code) << llendl; | ||
85 | } | ||
86 | |||
87 | LLAres::QueryResponder::~QueryResponder() | ||
88 | { | ||
89 | } | ||
90 | |||
91 | void LLAres::QueryResponder::queryResult(const char *buf, size_t len) | ||
92 | { | ||
93 | llinfos << "LLAres::QueryResponder::queryResult not implemented" | ||
94 | << llendl; | ||
95 | } | ||
96 | |||
97 | void LLAres::QueryResponder::queryError(int code) | ||
98 | { | ||
99 | llinfos << "LLAres::QueryResponder::queryError " << code << ": " | ||
100 | << LLAres::strerror(code) << llendl; | ||
101 | } | ||
102 | |||
103 | LLAres::LLAres() | ||
104 | { | ||
105 | ares_init(&chan_); | ||
106 | } | ||
107 | |||
108 | LLAres::~LLAres() | ||
109 | { | ||
110 | ares_destroy(chan_); | ||
111 | } | ||
112 | |||
113 | void LLAres::cancel() | ||
114 | { | ||
115 | ares_cancel(chan_); | ||
116 | } | ||
117 | |||
118 | static void host_callback_1_5(void *arg, int status, int timeouts, | ||
119 | struct hostent *ent) | ||
120 | { | ||
121 | LLPointer<LLAres::HostResponder> *resp = | ||
122 | (LLPointer<LLAres::HostResponder> *) arg; | ||
123 | |||
124 | if (status == ARES_SUCCESS) | ||
125 | { | ||
126 | (*resp)->hostResult(ent); | ||
127 | } else { | ||
128 | (*resp)->hostError(status); | ||
129 | } | ||
130 | |||
131 | delete resp; | ||
132 | } | ||
133 | |||
134 | #if ARES_VERSION_MAJOR == 1 && ARES_VERSION_MINOR == 4 | ||
135 | static void host_callback(void *arg, int status, struct hostent *ent) | ||
136 | { | ||
137 | host_callback_1_5(arg, status, 0, ent); | ||
138 | } | ||
139 | #else | ||
140 | # define host_callback host_callback_1_5 | ||
141 | #endif | ||
142 | |||
143 | void LLAres::getHostByName(const char *name, HostResponder *resp, | ||
144 | int family) | ||
145 | { | ||
146 | ares_gethostbyname(chan_, name, family, host_callback, | ||
147 | new LLPointer<LLAres::HostResponder>(resp)); | ||
148 | } | ||
149 | |||
150 | void LLAres::getSrvRecords(const std::string &name, SrvResponder *resp) | ||
151 | { | ||
152 | search(name, RES_SRV, resp); | ||
153 | } | ||
154 | |||
155 | void LLAres::rewriteURI(const std::string &uri, UriRewriteResponder *resp) | ||
156 | { | ||
157 | llinfos << "Rewriting " << uri << llendl; | ||
158 | |||
159 | resp->mUri = LLURI(uri); | ||
160 | search("_" + resp->mUri.scheme() + "._tcp." + resp->mUri.hostName(), | ||
161 | RES_SRV, resp); | ||
162 | } | ||
163 | |||
164 | LLQueryResponder::LLQueryResponder() | ||
165 | : LLAres::QueryResponder(), | ||
166 | mResult(ARES_ENODATA) | ||
167 | { | ||
168 | } | ||
169 | |||
170 | int LLQueryResponder::parseRR(const char *buf, size_t len, const char *&pos, | ||
171 | LLPointer<LLDnsRecord> &r) | ||
172 | { | ||
173 | std::string rrname; | ||
174 | size_t enclen; | ||
175 | int ret; | ||
176 | |||
177 | // RR name. | ||
178 | |||
179 | ret = LLAres::expandName(pos, buf, len, rrname, enclen); | ||
180 | if (ret != ARES_SUCCESS) | ||
181 | { | ||
182 | return ret; | ||
183 | } | ||
184 | |||
185 | pos += enclen; | ||
186 | |||
187 | if (pos + NS_RRFIXEDSZ > buf + len) | ||
188 | { | ||
189 | return ARES_EBADRESP; | ||
190 | } | ||
191 | |||
192 | int rrtype = DNS_RR_TYPE(pos); | ||
193 | int rrclass = DNS_RR_CLASS(pos); | ||
194 | int rrttl = DNS_RR_TTL(pos); | ||
195 | int rrlen = DNS_RR_LEN(pos); | ||
196 | |||
197 | if (rrclass != ns_c_in) | ||
198 | { | ||
199 | return ARES_EBADRESP; | ||
200 | } | ||
201 | |||
202 | pos += NS_RRFIXEDSZ; | ||
203 | |||
204 | if (pos + rrlen > buf + len) | ||
205 | { | ||
206 | return ARES_EBADRESP; | ||
207 | } | ||
208 | |||
209 | switch (rrtype) | ||
210 | { | ||
211 | case RES_A: | ||
212 | r = new LLARecord(rrname, rrttl); | ||
213 | break; | ||
214 | case RES_NS: | ||
215 | r = new LLNsRecord(rrname, rrttl); | ||
216 | break; | ||
217 | case RES_CNAME: | ||
218 | r = new LLCnameRecord(rrname, rrttl); | ||
219 | break; | ||
220 | case RES_PTR: | ||
221 | r = new LLPtrRecord(rrname, rrttl); | ||
222 | break; | ||
223 | case RES_AAAA: | ||
224 | r = new LLAaaaRecord(rrname, rrttl); | ||
225 | break; | ||
226 | case RES_SRV: | ||
227 | r = new LLSrvRecord(rrname, rrttl); | ||
228 | break; | ||
229 | default: | ||
230 | llinfos << "LLQueryResponder::parseRR got unknown RR type " << rrtype | ||
231 | << llendl; | ||
232 | return ARES_EBADRESP; | ||
233 | } | ||
234 | |||
235 | ret = r->parse(buf, len, pos, rrlen); | ||
236 | |||
237 | if (ret == ARES_SUCCESS) | ||
238 | { | ||
239 | pos += rrlen; | ||
240 | } else { | ||
241 | r = NULL; | ||
242 | } | ||
243 | |||
244 | return ret; | ||
245 | } | ||
246 | |||
247 | int LLQueryResponder::parseSection(const char *buf, size_t len, | ||
248 | size_t count, const char *&pos, | ||
249 | dns_rrs_t &rrs) | ||
250 | { | ||
251 | int ret = ARES_SUCCESS; | ||
252 | |||
253 | for (size_t i = 0; i < count; i++) | ||
254 | { | ||
255 | LLPointer<LLDnsRecord> r; | ||
256 | ret = parseRR(buf, len, pos, r); | ||
257 | if (ret != ARES_SUCCESS) | ||
258 | { | ||
259 | break; | ||
260 | } | ||
261 | rrs.push_back(r); | ||
262 | } | ||
263 | |||
264 | return ret; | ||
265 | } | ||
266 | |||
267 | void LLQueryResponder::queryResult(const char *buf, size_t len) | ||
268 | { | ||
269 | const char *pos = buf; | ||
270 | int qdcount = DNS_HEADER_QDCOUNT(pos); | ||
271 | int ancount = DNS_HEADER_ANCOUNT(pos); | ||
272 | int nscount = DNS_HEADER_NSCOUNT(pos); | ||
273 | int arcount = DNS_HEADER_ARCOUNT(pos); | ||
274 | int ret; | ||
275 | |||
276 | if (qdcount == 0 || ancount + nscount + arcount == 0) | ||
277 | { | ||
278 | ret = ARES_ENODATA; | ||
279 | goto bail; | ||
280 | } | ||
281 | |||
282 | pos += NS_HFIXEDSZ; | ||
283 | |||
284 | for (int i = 0; i < qdcount; i++) | ||
285 | { | ||
286 | std::string ignore; | ||
287 | size_t enclen; | ||
288 | |||
289 | ret = LLAres::expandName(pos, buf, len, i == 0 ? mQuery : ignore, | ||
290 | enclen); | ||
291 | if (ret != ARES_SUCCESS) | ||
292 | { | ||
293 | goto bail; | ||
294 | } | ||
295 | |||
296 | pos += enclen; | ||
297 | |||
298 | if (i == 0) | ||
299 | { | ||
300 | int t = DNS_QUESTION_TYPE(pos); | ||
301 | switch (t) | ||
302 | { | ||
303 | case RES_A: | ||
304 | case RES_NS: | ||
305 | case RES_CNAME: | ||
306 | case RES_PTR: | ||
307 | case RES_AAAA: | ||
308 | case RES_SRV: | ||
309 | mType = (LLResType) t; | ||
310 | break; | ||
311 | default: | ||
312 | llinfos << "Cannot grok query type " << t << llendl; | ||
313 | ret = ARES_EBADQUERY; | ||
314 | goto bail; | ||
315 | } | ||
316 | } | ||
317 | |||
318 | pos += NS_QFIXEDSZ; | ||
319 | if (pos > buf + len) | ||
320 | { | ||
321 | ret = ARES_EBADRESP; | ||
322 | goto bail; | ||
323 | } | ||
324 | } | ||
325 | |||
326 | ret = parseSection(buf, len, ancount, pos, mAnswers); | ||
327 | if (ret != ARES_SUCCESS) | ||
328 | { | ||
329 | goto bail; | ||
330 | } | ||
331 | |||
332 | ret = parseSection(buf, len, nscount, pos, mAuthorities); | ||
333 | if (ret != ARES_SUCCESS) | ||
334 | { | ||
335 | goto bail; | ||
336 | } | ||
337 | |||
338 | ret = parseSection(buf, len, arcount, pos, mAdditional); | ||
339 | |||
340 | bail: | ||
341 | mResult = ret; | ||
342 | if (mResult == ARES_SUCCESS) | ||
343 | { | ||
344 | querySuccess(); | ||
345 | } else { | ||
346 | queryError(mResult); | ||
347 | } | ||
348 | } | ||
349 | |||
350 | void LLQueryResponder::querySuccess() | ||
351 | { | ||
352 | llinfos << "LLQueryResponder::queryResult not implemented" << llendl; | ||
353 | } | ||
354 | |||
355 | void LLAres::SrvResponder::querySuccess() | ||
356 | { | ||
357 | if (mType == RES_SRV) | ||
358 | { | ||
359 | srvResult(mAnswers); | ||
360 | } else { | ||
361 | srvError(ARES_EBADRESP); | ||
362 | } | ||
363 | } | ||
364 | |||
365 | void LLAres::SrvResponder::queryError(int code) | ||
366 | { | ||
367 | srvError(code); | ||
368 | } | ||
369 | |||
370 | void LLAres::SrvResponder::srvResult(const dns_rrs_t &ents) | ||
371 | { | ||
372 | llinfos << "LLAres::SrvResponder::srvResult not implemented" << llendl; | ||
373 | |||
374 | for (size_t i = 0; i < ents.size(); i++) | ||
375 | { | ||
376 | const LLSrvRecord *s = (const LLSrvRecord *) ents[i].get(); | ||
377 | |||
378 | llinfos << "[" << i << "] " << s->host() << ":" << s->port() | ||
379 | << " priority " << s->priority() | ||
380 | << " weight " << s->weight() | ||
381 | << llendl; | ||
382 | } | ||
383 | } | ||
384 | |||
385 | void LLAres::SrvResponder::srvError(int code) | ||
386 | { | ||
387 | llinfos << "LLAres::SrvResponder::srvError " << code << ": " | ||
388 | << LLAres::strerror(code) << llendl; | ||
389 | } | ||
390 | |||
391 | static void nameinfo_callback_1_5(void *arg, int status, int timeouts, | ||
392 | char *node, char *service) | ||
393 | { | ||
394 | LLPointer<LLAres::NameInfoResponder> *resp = | ||
395 | (LLPointer<LLAres::NameInfoResponder> *) arg; | ||
396 | |||
397 | if (status == ARES_SUCCESS) | ||
398 | { | ||
399 | (*resp)->nameInfoResult(node, service); | ||
400 | } else { | ||
401 | (*resp)->nameInfoError(status); | ||
402 | } | ||
403 | |||
404 | delete resp; | ||
405 | } | ||
406 | |||
407 | #if ARES_VERSION_MAJOR == 1 && ARES_VERSION_MINOR == 4 | ||
408 | static void nameinfo_callback(void *arg, int status, char *node, char *service) | ||
409 | { | ||
410 | nameinfo_callback_1_5(arg, status, 0, node, service); | ||
411 | } | ||
412 | #else | ||
413 | # define nameinfo_callback nameinfo_callback_1_5 | ||
414 | #endif | ||
415 | |||
416 | void LLAres::getNameInfo(const struct sockaddr &sa, socklen_t salen, int flags, | ||
417 | NameInfoResponder *resp) | ||
418 | { | ||
419 | ares_getnameinfo(chan_, &sa, salen, flags, nameinfo_callback, | ||
420 | new LLPointer<NameInfoResponder>(resp)); | ||
421 | } | ||
422 | |||
423 | static void search_callback_1_5(void *arg, int status, int timeouts, | ||
424 | unsigned char *abuf, int alen) | ||
425 | { | ||
426 | LLPointer<LLAres::QueryResponder> *resp = | ||
427 | (LLPointer<LLAres::QueryResponder> *) arg; | ||
428 | |||
429 | if (status == ARES_SUCCESS) | ||
430 | { | ||
431 | (*resp)->queryResult((const char *) abuf, alen); | ||
432 | } else { | ||
433 | (*resp)->queryError(status); | ||
434 | } | ||
435 | |||
436 | delete resp; | ||
437 | } | ||
438 | |||
439 | #if ARES_VERSION_MAJOR == 1 && ARES_VERSION_MINOR == 4 | ||
440 | static void search_callback(void *arg, int status, unsigned char *abuf, | ||
441 | int alen) | ||
442 | { | ||
443 | search_callback_1_5(arg, status, 0, abuf, alen); | ||
444 | } | ||
445 | #else | ||
446 | # define search_callback search_callback_1_5 | ||
447 | #endif | ||
448 | |||
449 | void LLAres::search(const std::string &query, LLResType type, | ||
450 | QueryResponder *resp) | ||
451 | { | ||
452 | ares_search(chan_, query.c_str(), ns_c_in, type, search_callback, | ||
453 | new LLPointer<QueryResponder>(resp)); | ||
454 | } | ||
455 | |||
456 | bool LLAres::process(U64 timeout) | ||
457 | { | ||
458 | if (!gAPRPoolp) | ||
459 | { | ||
460 | ll_init_apr(); | ||
461 | } | ||
462 | |||
463 | int socks[ARES_GETSOCK_MAXNUM]; | ||
464 | apr_pollfd_t aprFds[ARES_GETSOCK_MAXNUM]; | ||
465 | apr_int32_t nsds = 0; | ||
466 | apr_status_t status; | ||
467 | apr_pool_t *pool; | ||
468 | int nactive = 0; | ||
469 | int bitmask; | ||
470 | |||
471 | bitmask = ares_getsock(chan_, socks, ARES_GETSOCK_MAXNUM); | ||
472 | |||
473 | if (bitmask == 0) | ||
474 | { | ||
475 | goto bail; | ||
476 | } | ||
477 | |||
478 | status = apr_pool_create(&pool, gAPRPoolp); | ||
479 | ll_apr_assert_status(status); | ||
480 | |||
481 | for (int i = 0; i < ARES_GETSOCK_MAXNUM; i++) | ||
482 | { | ||
483 | if (ARES_GETSOCK_READABLE(bitmask, i)) | ||
484 | { | ||
485 | aprFds[nactive].reqevents = APR_POLLIN | APR_POLLERR; | ||
486 | } | ||
487 | else if (ARES_GETSOCK_WRITABLE(bitmask, i)) | ||
488 | { | ||
489 | aprFds[nactive].reqevents = APR_POLLOUT | APR_POLLERR; | ||
490 | } else { | ||
491 | continue; | ||
492 | } | ||
493 | |||
494 | apr_socket_t *aprSock = NULL; | ||
495 | |||
496 | status = apr_os_sock_put(&aprSock, (apr_os_sock_t *) &socks[i], pool); | ||
497 | if (status != APR_SUCCESS) | ||
498 | { | ||
499 | ll_apr_warn_status(status); | ||
500 | goto bail_pool; | ||
501 | } | ||
502 | |||
503 | aprFds[nactive].desc.s = aprSock; | ||
504 | aprFds[nactive].desc_type = APR_POLL_SOCKET; | ||
505 | aprFds[nactive].p = pool; | ||
506 | aprFds[nactive].rtnevents = 0; | ||
507 | aprFds[nactive].client_data = &socks[i]; | ||
508 | |||
509 | nactive++; | ||
510 | } | ||
511 | |||
512 | if (nactive > 0) | ||
513 | { | ||
514 | status = apr_poll(aprFds, nactive, &nsds, timeout); | ||
515 | |||
516 | if (status != APR_SUCCESS && status != APR_TIMEUP) | ||
517 | { | ||
518 | ll_apr_warn_status(status); | ||
519 | } | ||
520 | |||
521 | for (int i = 0; i < nactive; i++) | ||
522 | { | ||
523 | int evts = aprFds[i].rtnevents; | ||
524 | int ifd = (evts & (APR_POLLIN | APR_POLLERR)) | ||
525 | ? *((int *) aprFds[i].client_data) : ARES_SOCKET_BAD; | ||
526 | int ofd = (evts & (APR_POLLOUT | APR_POLLERR)) | ||
527 | ? *((int *) aprFds[i].client_data) : ARES_SOCKET_BAD; | ||
528 | |||
529 | ares_process_fd(chan_, ifd, ofd); | ||
530 | } | ||
531 | } | ||
532 | |||
533 | bail_pool: | ||
534 | apr_pool_destroy(pool); | ||
535 | |||
536 | bail: | ||
537 | return nsds > 0; | ||
538 | } | ||
539 | |||
540 | bool LLAres::processAll() | ||
541 | { | ||
542 | bool anyProcessed = false, ret; | ||
543 | |||
544 | do { | ||
545 | timeval tv; | ||
546 | |||
547 | ret = ares_timeout(chan_, NULL, &tv) != NULL; | ||
548 | |||
549 | if (ret) | ||
550 | { | ||
551 | ret = process(tv.tv_sec * 1000000LL + tv.tv_usec); | ||
552 | anyProcessed |= ret; | ||
553 | } | ||
554 | } while (ret); | ||
555 | |||
556 | return anyProcessed; | ||
557 | } | ||
558 | |||
559 | int LLAres::expandName(const char *encoded, const char *abuf, size_t alen, | ||
560 | std::string &s, size_t &enclen) | ||
561 | { | ||
562 | char *t; | ||
563 | int ret; | ||
564 | long e; | ||
565 | |||
566 | ret = ares_expand_name((const unsigned char *) encoded, | ||
567 | (const unsigned char *) abuf, alen, &t, &e); | ||
568 | if (ret == ARES_SUCCESS) | ||
569 | { | ||
570 | s.assign(t); | ||
571 | enclen = e; | ||
572 | ares_free_string(t); | ||
573 | } | ||
574 | return ret; | ||
575 | } | ||
576 | |||
577 | const char *LLAres::strerror(int code) | ||
578 | { | ||
579 | return ares_strerror(code); | ||
580 | } | ||
581 | |||
582 | LLAres *gAres; | ||
583 | |||
584 | LLAres *ll_init_ares() | ||
585 | { | ||
586 | if (gAres == NULL) | ||
587 | { | ||
588 | gAres = new LLAres(); | ||
589 | } | ||
590 | return gAres; | ||
591 | } | ||
592 | |||
593 | LLDnsRecord::LLDnsRecord(LLResType type, const std::string &name, | ||
594 | unsigned ttl) | ||
595 | : LLRefCount(), | ||
596 | mType(type), | ||
597 | mName(name), | ||
598 | mTTL(ttl) | ||
599 | { | ||
600 | } | ||
601 | |||
602 | LLHostRecord::LLHostRecord(LLResType type, const std::string &name, | ||
603 | unsigned ttl) | ||
604 | : LLDnsRecord(type, name, ttl) | ||
605 | { | ||
606 | } | ||
607 | |||
608 | int LLHostRecord::parse(const char *buf, size_t len, const char *pos, | ||
609 | size_t rrlen) | ||
610 | { | ||
611 | int ret; | ||
612 | |||
613 | ret = LLAres::expandName(pos, buf, len, mHost); | ||
614 | if (ret != ARES_SUCCESS) | ||
615 | { | ||
616 | goto bail; | ||
617 | } | ||
618 | |||
619 | ret = ARES_SUCCESS; | ||
620 | |||
621 | bail: | ||
622 | return ret; | ||
623 | } | ||
624 | |||
625 | LLCnameRecord::LLCnameRecord(const std::string &name, unsigned ttl) | ||
626 | : LLHostRecord(RES_CNAME, name, ttl) | ||
627 | { | ||
628 | } | ||
629 | |||
630 | LLPtrRecord::LLPtrRecord(const std::string &name, unsigned ttl) | ||
631 | : LLHostRecord(RES_PTR, name, ttl) | ||
632 | { | ||
633 | } | ||
634 | |||
635 | LLAddrRecord::LLAddrRecord(LLResType type, const std::string &name, | ||
636 | unsigned ttl) | ||
637 | : LLDnsRecord(type, name, ttl) | ||
638 | { | ||
639 | } | ||
640 | |||
641 | LLARecord::LLARecord(const std::string &name, unsigned ttl) | ||
642 | : LLAddrRecord(RES_A, name, ttl) | ||
643 | { | ||
644 | } | ||
645 | |||
646 | int LLARecord::parse(const char *buf, size_t len, const char *pos, | ||
647 | size_t rrlen) | ||
648 | { | ||
649 | int ret; | ||
650 | |||
651 | if (rrlen != sizeof(mSA.sin.sin_addr.s_addr)) | ||
652 | { | ||
653 | ret = ARES_EBADRESP; | ||
654 | goto bail; | ||
655 | } | ||
656 | |||
657 | memset(&mSA, 0, sizeof(mSA)); | ||
658 | memcpy(&mSA.sin.sin_addr.s_addr, pos, rrlen); | ||
659 | mSA.sin.sin_family = AF_INET6; | ||
660 | mSize = sizeof(mSA.sin); | ||
661 | |||
662 | ret = ARES_SUCCESS; | ||
663 | |||
664 | bail: | ||
665 | return ret; | ||
666 | } | ||
667 | |||
668 | LLAaaaRecord::LLAaaaRecord(const std::string &name, unsigned ttl) | ||
669 | : LLAddrRecord(RES_AAAA, name, ttl) | ||
670 | { | ||
671 | } | ||
672 | |||
673 | int LLAaaaRecord::parse(const char *buf, size_t len, const char *pos, | ||
674 | size_t rrlen) | ||
675 | { | ||
676 | int ret; | ||
677 | |||
678 | if (rrlen != sizeof(mSA.sin6.sin6_addr)) | ||
679 | { | ||
680 | ret = ARES_EBADRESP; | ||
681 | goto bail; | ||
682 | } | ||
683 | |||
684 | memset(&mSA, 0, sizeof(mSA)); | ||
685 | memcpy(&mSA.sin6.sin6_addr.s6_addr, pos, rrlen); | ||
686 | mSA.sin6.sin6_family = AF_INET6; | ||
687 | mSize = sizeof(mSA.sin6); | ||
688 | |||
689 | ret = ARES_SUCCESS; | ||
690 | |||
691 | bail: | ||
692 | return ret; | ||
693 | } | ||
694 | |||
695 | LLSrvRecord::LLSrvRecord(const std::string &name, unsigned ttl) | ||
696 | : LLHostRecord(RES_SRV, name, ttl) | ||
697 | { | ||
698 | } | ||
699 | |||
700 | int LLSrvRecord::parse(const char *buf, size_t len, const char *pos, | ||
701 | size_t rrlen) | ||
702 | { | ||
703 | int ret; | ||
704 | |||
705 | if (rrlen < 6) | ||
706 | { | ||
707 | ret = ARES_EBADRESP; | ||
708 | goto bail; | ||
709 | } | ||
710 | |||
711 | memcpy(&mPriority, pos, 2); | ||
712 | memcpy(&mWeight, pos + 2, 2); | ||
713 | memcpy(&mPort, pos + 4, 2); | ||
714 | |||
715 | mPriority = ntohs(mPriority); | ||
716 | mWeight = ntohs(mWeight); | ||
717 | mPort = ntohs(mPort); | ||
718 | |||
719 | ret = LLHostRecord::parse(buf, len, pos + 6, rrlen - 6); | ||
720 | |||
721 | bail: | ||
722 | return ret; | ||
723 | } | ||
724 | |||
725 | LLNsRecord::LLNsRecord(const std::string &name, unsigned ttl) | ||
726 | : LLHostRecord(RES_NS, name, ttl) | ||
727 | { | ||
728 | } | ||
729 | |||
730 | void LLAres::UriRewriteResponder::queryError(int code) | ||
731 | { | ||
732 | std::vector<std::string> uris; | ||
733 | uris.push_back(mUri.asString()); | ||
734 | rewriteResult(uris); | ||
735 | } | ||
736 | |||
737 | void LLAres::UriRewriteResponder::querySuccess() | ||
738 | { | ||
739 | std::vector<std::string> uris; | ||
740 | |||
741 | if (mType != RES_SRV) | ||
742 | { | ||
743 | goto bail; | ||
744 | } | ||
745 | |||
746 | for (size_t i = 0; i < mAnswers.size(); i++) | ||
747 | { | ||
748 | const LLSrvRecord *r = (const LLSrvRecord *) mAnswers[i].get(); | ||
749 | |||
750 | if (r->type() == RES_SRV) | ||
751 | { | ||
752 | // Check the domain in the response to ensure that it's | ||
753 | // the same as the domain in the request, so that bad guys | ||
754 | // can't forge responses that point to their own login | ||
755 | // servers with their own certificates. | ||
756 | |||
757 | // Hard-coding the domain to check here is a bit of a | ||
758 | // hack. Hoist it to an outer caller if anyone ever needs | ||
759 | // this functionality on other domains. | ||
760 | |||
761 | static const std::string domain(".lindenlab.com"); | ||
762 | const std::string &host = r->host(); | ||
763 | |||
764 | std::string::size_type s = host.find(domain) + domain.length(); | ||
765 | |||
766 | if (s != host.length() && s != host.length() - 1) | ||
767 | { | ||
768 | continue; | ||
769 | } | ||
770 | |||
771 | LLURI uri(mUri.scheme(), | ||
772 | mUri.userName(), | ||
773 | mUri.password(), | ||
774 | r->host(), | ||
775 | mUri.defaultPort() ? r->port() : mUri.hostPort(), | ||
776 | mUri.escapedPath(), | ||
777 | mUri.escapedQuery()); | ||
778 | uris.push_back(uri.asString()); | ||
779 | } | ||
780 | } | ||
781 | |||
782 | if (!uris.empty()) | ||
783 | { | ||
784 | goto done; | ||
785 | } | ||
786 | |||
787 | bail: | ||
788 | uris.push_back(mUri.asString()); | ||
789 | |||
790 | done: | ||
791 | rewriteResult(uris); | ||
792 | } | ||
793 | |||
794 | void LLAres::UriRewriteResponder::rewriteResult( | ||
795 | const std::vector<std::string> &uris) | ||
796 | { | ||
797 | llinfos << "LLAres::UriRewriteResponder::rewriteResult not implemented" | ||
798 | << llendl; | ||
799 | |||
800 | for (size_t i = 0; i < uris.size(); i++) | ||
801 | { | ||
802 | llinfos << "[" << i << "] " << uris[i] << llendl; | ||
803 | } | ||
804 | } | ||