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