00001
00034 #ifdef LL_STANDALONE
00035 # include <ares_dns.h>
00036 #else
00037 # include <ares/ares_dns.h>
00038 #endif
00039
00040 #include "apr-1/apr_portable.h"
00041 #include "apr-1/apr_network_io.h"
00042 #include "apr-1/apr_poll.h"
00043
00044 #include "linden_common.h"
00045 #include "llapr.h"
00046 #include "llares.h"
00047
00048 #if defined(LL_WINDOWS)
00049 # define ns_c_in 1
00050 # define NS_HFIXEDSZ 12
00051 # define NS_QFIXEDSZ 4
00052 # define NS_RRFIXEDSZ 10
00053 #else
00054 # include <arpa/nameser.h>
00055 #endif
00056
00057 LLAres::HostResponder::~HostResponder()
00058 {
00059 }
00060
00061 void LLAres::HostResponder::hostResult(const hostent *ent)
00062 {
00063 llinfos << "LLAres::HostResponder::hostResult not implemented" << llendl;
00064 }
00065
00066 void LLAres::HostResponder::hostError(int code)
00067 {
00068 llinfos << "LLAres::HostResponder::hostError " << code << ": "
00069 << LLAres::strerror(code) << llendl;
00070 }
00071
00072 LLAres::NameInfoResponder::~NameInfoResponder()
00073 {
00074 }
00075
00076 void LLAres::NameInfoResponder::nameInfoResult(const char *node,
00077 const char *service)
00078 {
00079 llinfos << "LLAres::NameInfoResponder::nameInfoResult not implemented"
00080 << llendl;
00081 }
00082
00083 void LLAres::NameInfoResponder::nameInfoError(int code)
00084 {
00085 llinfos << "LLAres::NameInfoResponder::nameInfoError " << code << ": "
00086 << LLAres::strerror(code) << llendl;
00087 }
00088
00089 LLAres::QueryResponder::~QueryResponder()
00090 {
00091 }
00092
00093 void LLAres::QueryResponder::queryResult(const char *buf, size_t len)
00094 {
00095 llinfos << "LLAres::QueryResponder::queryResult not implemented"
00096 << llendl;
00097 }
00098
00099 void LLAres::QueryResponder::queryError(int code)
00100 {
00101 llinfos << "LLAres::QueryResponder::queryError " << code << ": "
00102 << LLAres::strerror(code) << llendl;
00103 }
00104
00105 LLAres::LLAres()
00106 : chan_(NULL)
00107 {
00108 ares_init(&chan_);
00109 }
00110
00111 LLAres::~LLAres()
00112 {
00113 if (chan_)
00114 ares_destroy(chan_);
00115 }
00116
00117 void LLAres::cancel()
00118 {
00119 if (chan_)
00120 ares_cancel(chan_);
00121 }
00122
00123 static void host_callback(void *arg, int status, struct hostent *ent)
00124 {
00125 LLPointer<LLAres::HostResponder> *resp =
00126 (LLPointer<LLAres::HostResponder> *) arg;
00127
00128 if (status == ARES_SUCCESS)
00129 {
00130 (*resp)->hostResult(ent);
00131 } else {
00132 (*resp)->hostError(status);
00133 }
00134
00135 delete resp;
00136 }
00137
00138 void LLAres::getHostByName(const char *name, HostResponder *resp,
00139 int family)
00140 {
00141 if (!chan_)
00142 {
00143 resp->hostError(ARES_EBADRESP);
00144 return;
00145 }
00146 ares_gethostbyname(chan_, name, family, host_callback,
00147 new LLPointer<LLAres::HostResponder>(resp));
00148 }
00149
00150 void LLAres::getSrvRecords(const std::string &name, SrvResponder *resp)
00151 {
00152 search(name, RES_SRV, resp);
00153 }
00154
00155 void LLAres::rewriteURI(const std::string &uri, UriRewriteResponder *resp)
00156 {
00157 LL_DEBUGS2("AppInit","Rewrite") << "Rewriting " << uri << LL_ENDL;
00158
00159 resp->mUri = LLURI(uri);
00160 search("_" + resp->mUri.scheme() + "._tcp." + resp->mUri.hostName(),
00161 RES_SRV, resp);
00162 }
00163
00164 LLQueryResponder::LLQueryResponder()
00165 : LLAres::QueryResponder(),
00166 mResult(ARES_ENODATA),
00167 mType(RES_INVALID)
00168 {
00169 }
00170
00171 int LLQueryResponder::parseRR(const char *buf, size_t len, const char *&pos,
00172 LLPointer<LLDnsRecord> &r)
00173 {
00174 std::string rrname;
00175 size_t enclen;
00176 int ret;
00177
00178
00179
00180 ret = LLAres::expandName(pos, buf, len, rrname, enclen);
00181 if (ret != ARES_SUCCESS)
00182 {
00183 return ret;
00184 }
00185
00186 pos += enclen;
00187
00188 if (pos + NS_RRFIXEDSZ > buf + len)
00189 {
00190 return ARES_EBADRESP;
00191 }
00192
00193 int rrtype = DNS_RR_TYPE(pos);
00194 int rrclass = DNS_RR_CLASS(pos);
00195 int rrttl = DNS_RR_TTL(pos);
00196 int rrlen = DNS_RR_LEN(pos);
00197
00198 if (rrclass != ns_c_in)
00199 {
00200 return ARES_EBADRESP;
00201 }
00202
00203 pos += NS_RRFIXEDSZ;
00204
00205 if (pos + rrlen > buf + len)
00206 {
00207 return ARES_EBADRESP;
00208 }
00209
00210 switch (rrtype)
00211 {
00212 case RES_A:
00213 r = new LLARecord(rrname, rrttl);
00214 break;
00215 case RES_NS:
00216 r = new LLNsRecord(rrname, rrttl);
00217 break;
00218 case RES_CNAME:
00219 r = new LLCnameRecord(rrname, rrttl);
00220 break;
00221 case RES_PTR:
00222 r = new LLPtrRecord(rrname, rrttl);
00223 break;
00224 case RES_AAAA:
00225 r = new LLAaaaRecord(rrname, rrttl);
00226 break;
00227 case RES_SRV:
00228 r = new LLSrvRecord(rrname, rrttl);
00229 break;
00230 default:
00231 llinfos << "LLQueryResponder::parseRR got unknown RR type " << rrtype
00232 << llendl;
00233 return ARES_EBADRESP;
00234 }
00235
00236 ret = r->parse(buf, len, pos, rrlen);
00237
00238 if (ret == ARES_SUCCESS)
00239 {
00240 pos += rrlen;
00241 } else {
00242 r = NULL;
00243 }
00244
00245 return ret;
00246 }
00247
00248 int LLQueryResponder::parseSection(const char *buf, size_t len,
00249 size_t count, const char *&pos,
00250 dns_rrs_t &rrs)
00251 {
00252 int ret = ARES_SUCCESS;
00253
00254 for (size_t i = 0; i < count; i++)
00255 {
00256 LLPointer<LLDnsRecord> r;
00257 ret = parseRR(buf, len, pos, r);
00258 if (ret != ARES_SUCCESS)
00259 {
00260 break;
00261 }
00262 rrs.push_back(r);
00263 }
00264
00265 return ret;
00266 }
00267
00268 void LLQueryResponder::queryResult(const char *buf, size_t len)
00269 {
00270 const char *pos = buf;
00271 int qdcount = DNS_HEADER_QDCOUNT(pos);
00272 int ancount = DNS_HEADER_ANCOUNT(pos);
00273 int nscount = DNS_HEADER_NSCOUNT(pos);
00274 int arcount = DNS_HEADER_ARCOUNT(pos);
00275 int ret;
00276
00277 if (qdcount == 0 || ancount + nscount + arcount == 0)
00278 {
00279 ret = ARES_ENODATA;
00280 goto bail;
00281 }
00282
00283 pos += NS_HFIXEDSZ;
00284
00285 for (int i = 0; i < qdcount; i++)
00286 {
00287 std::string ignore;
00288 size_t enclen;
00289
00290 ret = LLAres::expandName(pos, buf, len, i == 0 ? mQuery : ignore,
00291 enclen);
00292 if (ret != ARES_SUCCESS)
00293 {
00294 goto bail;
00295 }
00296
00297 pos += enclen;
00298
00299 if (i == 0)
00300 {
00301 int t = DNS_QUESTION_TYPE(pos);
00302 switch (t)
00303 {
00304 case RES_A:
00305 case RES_NS:
00306 case RES_CNAME:
00307 case RES_PTR:
00308 case RES_AAAA:
00309 case RES_SRV:
00310 mType = (LLResType) t;
00311 break;
00312 default:
00313 llinfos << "Cannot grok query type " << t << llendl;
00314 ret = ARES_EBADQUERY;
00315 goto bail;
00316 }
00317 }
00318
00319 pos += NS_QFIXEDSZ;
00320 if (pos > buf + len)
00321 {
00322 ret = ARES_EBADRESP;
00323 goto bail;
00324 }
00325 }
00326
00327 ret = parseSection(buf, len, ancount, pos, mAnswers);
00328 if (ret != ARES_SUCCESS)
00329 {
00330 goto bail;
00331 }
00332
00333 ret = parseSection(buf, len, nscount, pos, mAuthorities);
00334 if (ret != ARES_SUCCESS)
00335 {
00336 goto bail;
00337 }
00338
00339 ret = parseSection(buf, len, arcount, pos, mAdditional);
00340
00341 bail:
00342 mResult = ret;
00343 if (mResult == ARES_SUCCESS)
00344 {
00345 queryResult();
00346 } else {
00347 queryError(mResult);
00348 }
00349 }
00350
00351 void LLQueryResponder::queryResult()
00352 {
00353 llinfos << "LLQueryResponder::queryResult not implemented" << llendl;
00354 }
00355
00356 void LLAres::SrvResponder::queryResult()
00357 {
00358 if (mType == RES_SRV)
00359 {
00360 srvResult(mAnswers);
00361 } else {
00362 srvError(ARES_EBADRESP);
00363 }
00364 }
00365
00366 void LLAres::SrvResponder::queryError(int code)
00367 {
00368 srvError(code);
00369 }
00370
00371 void LLAres::SrvResponder::srvResult(const dns_rrs_t &ents)
00372 {
00373 llinfos << "LLAres::SrvResponder::srvResult not implemented" << llendl;
00374
00375 for (size_t i = 0; i < ents.size(); i++)
00376 {
00377 const LLSrvRecord *s = (const LLSrvRecord *) ents[i].get();
00378
00379 llinfos << "[" << i << "] " << s->host() << ":" << s->port()
00380 << " priority " << s->priority()
00381 << " weight " << s->weight()
00382 << llendl;
00383 }
00384 }
00385
00386 void LLAres::SrvResponder::srvError(int code)
00387 {
00388 llinfos << "LLAres::SrvResponder::srvError " << code << ": "
00389 << LLAres::strerror(code) << llendl;
00390 }
00391
00392 static void nameinfo_callback(void *arg, int status, char *node, char *service)
00393 {
00394 LLPointer<LLAres::NameInfoResponder> *resp =
00395 (LLPointer<LLAres::NameInfoResponder> *) arg;
00396
00397 if (status == ARES_SUCCESS)
00398 {
00399 (*resp)->nameInfoResult(node, service);
00400 } else {
00401 (*resp)->nameInfoError(status);
00402 }
00403
00404 delete resp;
00405 }
00406
00407 void LLAres::getNameInfo(const struct sockaddr &sa, socklen_t salen, int flags,
00408 NameInfoResponder *resp)
00409 {
00410 if (!chan_)
00411 {
00412 resp->nameInfoError(ARES_EBADRESP);
00413 return;
00414 }
00415 ares_getnameinfo(chan_, &sa, salen, flags, nameinfo_callback,
00416 new LLPointer<NameInfoResponder>(resp));
00417 }
00418
00419 static void search_callback(void *arg, int status, unsigned char *abuf,
00420 int alen)
00421 {
00422 LLPointer<LLAres::QueryResponder> *resp =
00423 (LLPointer<LLAres::QueryResponder> *) arg;
00424
00425 if (status == ARES_SUCCESS)
00426 {
00427 (*resp)->queryResult((const char *) abuf, alen);
00428 } else {
00429 (*resp)->queryError(status);
00430 }
00431
00432 delete resp;
00433 }
00434
00435 void LLAres::search(const std::string &query, LLResType type,
00436 QueryResponder *resp)
00437 {
00438 if (!chan_)
00439 {
00440 resp->queryError(ARES_EBADRESP);
00441 return;
00442 }
00443 ares_search(chan_, query.c_str(), ns_c_in, type, search_callback,
00444 new LLPointer<QueryResponder>(resp));
00445 }
00446
00447 bool LLAres::process(U64 timeout)
00448 {
00449 if (!gAPRPoolp)
00450 {
00451 ll_init_apr();
00452 }
00453
00454 int socks[ARES_GETSOCK_MAXNUM];
00455 apr_pollfd_t aprFds[ARES_GETSOCK_MAXNUM];
00456 apr_int32_t nsds = 0;
00457 apr_status_t status;
00458 apr_pool_t *pool;
00459 int nactive = 0;
00460 int bitmask;
00461
00462 if (!chan_)
00463 {
00464 goto bail;
00465 }
00466
00467 bitmask = ares_getsock(chan_, socks, ARES_GETSOCK_MAXNUM);
00468
00469 if (bitmask == 0)
00470 {
00471 goto bail;
00472 }
00473
00474 status = apr_pool_create(&pool, gAPRPoolp);
00475 ll_apr_assert_status(status);
00476
00477 for (int i = 0; i < ARES_GETSOCK_MAXNUM; i++)
00478 {
00479 if (ARES_GETSOCK_READABLE(bitmask, i))
00480 {
00481 aprFds[nactive].reqevents = APR_POLLIN | APR_POLLERR;
00482 }
00483 else if (ARES_GETSOCK_WRITABLE(bitmask, i))
00484 {
00485 aprFds[nactive].reqevents = APR_POLLOUT | APR_POLLERR;
00486 } else {
00487 continue;
00488 }
00489
00490 apr_socket_t *aprSock = NULL;
00491
00492 status = apr_os_sock_put(&aprSock, (apr_os_sock_t *) &socks[i], pool);
00493 if (status != APR_SUCCESS)
00494 {
00495 ll_apr_warn_status(status);
00496 goto bail_pool;
00497 }
00498
00499 aprFds[nactive].desc.s = aprSock;
00500 aprFds[nactive].desc_type = APR_POLL_SOCKET;
00501 aprFds[nactive].p = pool;
00502 aprFds[nactive].rtnevents = 0;
00503 aprFds[nactive].client_data = &socks[i];
00504
00505 nactive++;
00506 }
00507
00508 if (nactive > 0)
00509 {
00510 status = apr_poll(aprFds, nactive, &nsds, timeout);
00511
00512 if (status != APR_SUCCESS && status != APR_TIMEUP)
00513 {
00514 ll_apr_warn_status(status);
00515 }
00516
00517 for (int i = 0; i < nactive; i++)
00518 {
00519 int evts = aprFds[i].rtnevents;
00520 int ifd = (evts & (APR_POLLIN | APR_POLLERR))
00521 ? *((int *) aprFds[i].client_data) : ARES_SOCKET_BAD;
00522 int ofd = (evts & (APR_POLLOUT | APR_POLLERR))
00523 ? *((int *) aprFds[i].client_data) : ARES_SOCKET_BAD;
00524
00525 ares_process_fd(chan_, ifd, ofd);
00526 }
00527 }
00528
00529 bail_pool:
00530 apr_pool_destroy(pool);
00531
00532 bail:
00533 return nsds > 0;
00534 }
00535
00536 bool LLAres::processAll()
00537 {
00538 if (!chan_)
00539 {
00540 return false;
00541 }
00542
00543 bool anyProcessed = false, ret;
00544
00545 do {
00546 timeval tv;
00547
00548 ret = ares_timeout(chan_, NULL, &tv) != NULL;
00549
00550 if (ret)
00551 {
00552 ret = process(tv.tv_sec * 1000000LL + tv.tv_usec);
00553 anyProcessed |= ret;
00554 }
00555 } while (ret);
00556
00557 return anyProcessed;
00558 }
00559
00560 int LLAres::expandName(const char *encoded, const char *abuf, size_t alen,
00561 std::string &s, size_t &enclen)
00562 {
00563 char *t;
00564 int ret;
00565 long e;
00566
00567 ret = ares_expand_name((const unsigned char *) encoded,
00568 (const unsigned char *) abuf, alen, &t, &e);
00569 if (ret == ARES_SUCCESS)
00570 {
00571 s.assign(t);
00572 enclen = e;
00573 ares_free_string(t);
00574 }
00575 return ret;
00576 }
00577
00578 const char *LLAres::strerror(int code)
00579 {
00580 return ares_strerror(code);
00581 }
00582
00583 LLAres *gAres;
00584
00585 LLAres *ll_init_ares()
00586 {
00587 if (gAres == NULL)
00588 {
00589 gAres = new LLAres();
00590 }
00591 return gAres;
00592 }
00593
00594 LLDnsRecord::LLDnsRecord(LLResType type, const std::string &name,
00595 unsigned ttl)
00596 : LLRefCount(),
00597 mType(type),
00598 mName(name),
00599 mTTL(ttl)
00600 {
00601 }
00602
00603 LLHostRecord::LLHostRecord(LLResType type, const std::string &name,
00604 unsigned ttl)
00605 : LLDnsRecord(type, name, ttl)
00606 {
00607 }
00608
00609 int LLHostRecord::parse(const char *buf, size_t len, const char *pos,
00610 size_t rrlen)
00611 {
00612 int ret;
00613
00614 ret = LLAres::expandName(pos, buf, len, mHost);
00615 if (ret != ARES_SUCCESS)
00616 {
00617 goto bail;
00618 }
00619
00620 ret = ARES_SUCCESS;
00621
00622 bail:
00623 return ret;
00624 }
00625
00626 LLCnameRecord::LLCnameRecord(const std::string &name, unsigned ttl)
00627 : LLHostRecord(RES_CNAME, name, ttl)
00628 {
00629 }
00630
00631 LLPtrRecord::LLPtrRecord(const std::string &name, unsigned ttl)
00632 : LLHostRecord(RES_PTR, name, ttl)
00633 {
00634 }
00635
00636 LLAddrRecord::LLAddrRecord(LLResType type, const std::string &name,
00637 unsigned ttl)
00638 : LLDnsRecord(type, name, ttl)
00639 {
00640 }
00641
00642 LLARecord::LLARecord(const std::string &name, unsigned ttl)
00643 : LLAddrRecord(RES_A, name, ttl)
00644 {
00645 }
00646
00647 int LLARecord::parse(const char *buf, size_t len, const char *pos,
00648 size_t rrlen)
00649 {
00650 int ret;
00651
00652 if (rrlen != sizeof(mSA.sin.sin_addr.s_addr))
00653 {
00654 ret = ARES_EBADRESP;
00655 goto bail;
00656 }
00657
00658 memset(&mSA, 0, sizeof(mSA));
00659 memcpy(&mSA.sin.sin_addr.s_addr, pos, rrlen);
00660 mSA.sin.sin_family = AF_INET6;
00661 mSize = sizeof(mSA.sin);
00662
00663 ret = ARES_SUCCESS;
00664
00665 bail:
00666 return ret;
00667 }
00668
00669 LLAaaaRecord::LLAaaaRecord(const std::string &name, unsigned ttl)
00670 : LLAddrRecord(RES_AAAA, name, ttl)
00671 {
00672 }
00673
00674 int LLAaaaRecord::parse(const char *buf, size_t len, const char *pos,
00675 size_t rrlen)
00676 {
00677 int ret;
00678
00679 if (rrlen != sizeof(mSA.sin6.sin6_addr))
00680 {
00681 ret = ARES_EBADRESP;
00682 goto bail;
00683 }
00684
00685 memset(&mSA, 0, sizeof(mSA));
00686 memcpy(&mSA.sin6.sin6_addr.s6_addr, pos, rrlen);
00687 mSA.sin6.sin6_family = AF_INET6;
00688 mSize = sizeof(mSA.sin6);
00689
00690 ret = ARES_SUCCESS;
00691
00692 bail:
00693 return ret;
00694 }
00695
00696 LLSrvRecord::LLSrvRecord(const std::string &name, unsigned ttl)
00697 : LLHostRecord(RES_SRV, name, ttl)
00698 {
00699 }
00700
00701 int LLSrvRecord::parse(const char *buf, size_t len, const char *pos,
00702 size_t rrlen)
00703 {
00704 int ret;
00705
00706 if (rrlen < 6)
00707 {
00708 ret = ARES_EBADRESP;
00709 goto bail;
00710 }
00711
00712 memcpy(&mPriority, pos, 2);
00713 memcpy(&mWeight, pos + 2, 2);
00714 memcpy(&mPort, pos + 4, 2);
00715
00716 mPriority = ntohs(mPriority);
00717 mWeight = ntohs(mWeight);
00718 mPort = ntohs(mPort);
00719
00720 ret = LLHostRecord::parse(buf, len, pos + 6, rrlen - 6);
00721
00722 bail:
00723 return ret;
00724 }
00725
00726 LLNsRecord::LLNsRecord(const std::string &name, unsigned ttl)
00727 : LLHostRecord(RES_NS, name, ttl)
00728 {
00729 }
00730
00731 void LLAres::UriRewriteResponder::queryError(int code)
00732 {
00733 std::vector<std::string> uris;
00734 uris.push_back(mUri.asString());
00735 rewriteResult(uris);
00736 }
00737
00738 void LLAres::UriRewriteResponder::queryResult()
00739 {
00740 std::vector<std::string> uris;
00741
00742 if (mType != RES_SRV)
00743 {
00744 goto bail;
00745 }
00746
00747 for (size_t i = 0; i < mAnswers.size(); i++)
00748 {
00749 const LLSrvRecord *r = (const LLSrvRecord *) mAnswers[i].get();
00750
00751 if (r->type() == RES_SRV)
00752 {
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762 static const std::string domain(".lindenlab.com");
00763 const std::string &host = r->host();
00764
00765 std::string::size_type s = host.find(domain) + domain.length();
00766
00767 if (s != host.length() && s != host.length() - 1)
00768 {
00769 continue;
00770 }
00771
00772 LLURI uri(mUri.scheme(),
00773 mUri.userName(),
00774 mUri.password(),
00775 r->host(),
00776 mUri.defaultPort() ? r->port() : mUri.hostPort(),
00777 mUri.escapedPath(),
00778 mUri.escapedQuery());
00779 uris.push_back(uri.asString());
00780 }
00781 }
00782
00783 if (!uris.empty())
00784 {
00785 goto done;
00786 }
00787
00788 bail:
00789 uris.push_back(mUri.asString());
00790
00791 done:
00792 rewriteResult(uris);
00793 }
00794
00795 void LLAres::UriRewriteResponder::rewriteResult(
00796 const std::vector<std::string> &uris)
00797 {
00798 llinfos << "LLAres::UriRewriteResponder::rewriteResult not implemented"
00799 << llendl;
00800
00801 for (size_t i = 0; i < uris.size(); i++)
00802 {
00803 llinfos << "[" << i << "] " << uris[i] << llendl;
00804 }
00805 }