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