00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "P_DNS.h"
00025 #include <ts/ink_inet.h>
00026
00027 #ifdef SPLIT_DNS
00028 #include "I_SplitDNS.h"
00029 #endif
00030
00031 #define SRV_COST (RRFIXEDSZ+0)
00032 #define SRV_WEIGHT (RRFIXEDSZ+2)
00033 #define SRV_PORT (RRFIXEDSZ+4)
00034 #define SRV_SERVER (RRFIXEDSZ+6)
00035 #define SRV_FIXEDSZ (RRFIXEDSZ+6)
00036
00037 EventType ET_DNS = ET_CALL;
00038
00039
00040
00041
00042 int dns_timeout = DEFAULT_DNS_TIMEOUT;
00043 int dns_retries = DEFAULT_DNS_RETRIES;
00044 int dns_search = DEFAULT_DNS_SEARCH;
00045 int dns_failover_number = DEFAULT_FAILOVER_NUMBER;
00046 int dns_failover_period = DEFAULT_FAILOVER_PERIOD;
00047 int dns_failover_try_period = DEFAULT_FAILOVER_TRY_PERIOD;
00048 int dns_max_dns_in_flight = MAX_DNS_IN_FLIGHT;
00049 int dns_validate_qname = 0;
00050 unsigned int dns_handler_initialized = 0;
00051 int dns_ns_rr = 0;
00052 int dns_ns_rr_init_down = 1;
00053 char *dns_ns_list = NULL;
00054 char *dns_resolv_conf = NULL;
00055 char *dns_local_ipv6 = NULL;
00056 char *dns_local_ipv4 = NULL;
00057 int dns_thread = 0;
00058 int dns_prefer_ipv6 = 0;
00059 namespace {
00060
00061 inline char const* QtypeName(int qtype) {
00062 return T_AAAA == qtype ? "AAAA" : T_A == qtype ? "A" : "*";
00063 }
00064 inline bool is_addr_query(int qtype) {
00065 return qtype == T_A || qtype == T_AAAA;
00066 }
00067 }
00068
00069 DNSProcessor dnsProcessor;
00070 ClassAllocator<DNSEntry> dnsEntryAllocator("dnsEntryAllocator");
00071
00072
00073 ClassAllocator<HostEnt> dnsBufAllocator("dnsBufAllocator", 2);
00074
00075
00076
00077
00078
00079 static bool dns_process(DNSHandler *h, HostEnt *ent, int len);
00080 static DNSEntry *get_dns(DNSHandler *h, uint16_t id);
00081
00082 static void dns_result(DNSHandler *h, DNSEntry *e, HostEnt *ent, bool retry);
00083 static void write_dns(DNSHandler *h);
00084 static bool write_dns_event(DNSHandler *h, DNSEntry *e);
00085
00086
00087 static int try_servers = 0;
00088 static int local_num_entries = 1;
00089 static int attempt_num_entries = 1;
00090 char try_server_names[DEFAULT_NUM_TRY_SERVER][MAXDNAME];
00091
00092 static inline char *
00093 strnchr(char *s, char c, int len) {
00094 while (*s && *s != c && len)
00095 ++s, --len;
00096 return *s == c ? s : (char *) NULL;
00097 }
00098
00099 static inline uint16_t
00100 ink_get16(const uint8_t *src) {
00101 uint16_t dst;
00102
00103 NS_GET16(dst, src);
00104 return dst;
00105 }
00106
00107 void HostEnt::free() {
00108 dnsBufAllocator.free(this);
00109 }
00110
00111 void
00112 make_ipv4_ptr(in_addr_t addr, char *buffer)
00113 {
00114 char *p = buffer;
00115 uint8_t const* u = reinterpret_cast<uint8_t*>(&addr);
00116
00117 if (u[3] > 99)
00118 *p++ = (u[3] / 100) + '0';
00119 if (u[3] > 9)
00120 *p++ = ((u[3] / 10) % 10) + '0';
00121 *p++ = u[3] % 10 + '0';
00122 *p++ = '.';
00123 if (u[2] > 99)
00124 *p++ = (u[2] / 100) + '0';
00125 if (u[2] > 9)
00126 *p++ = ((u[2] / 10) % 10) + '0';
00127 *p++ = u[2] % 10 + '0';
00128 *p++ = '.';
00129 if (u[1] > 99)
00130 *p++ = (u[1] / 100) + '0';
00131 if (u[1] > 9)
00132 *p++ = ((u[1] / 10) % 10) + '0';
00133 *p++ = u[1] % 10 + '0';
00134 *p++ = '.';
00135 if (u[0] > 99)
00136 *p++ = (u[0] / 100) + '0';
00137 if (u[0] > 9)
00138 *p++ = ((u[0] / 10) % 10) + '0';
00139 *p++ = u[0] % 10 + '0';
00140 *p++ = '.';
00141 ink_strlcpy(p, "in-addr.arpa", MAXDNAME - (p - buffer + 1));
00142 }
00143
00144 void
00145 make_ipv6_ptr(in6_addr const* addr, char *buffer)
00146 {
00147 const char hex_digit[] = "0123456789abcdef";
00148 char *p = buffer;
00149 uint8_t const* src = addr->s6_addr;
00150 int i;
00151
00152 for (i = TS_IP6_SIZE-1 ; i >= 0; --i) {
00153 *p++ = hex_digit[src[i] & 0x0f];
00154 *p++ = '.';
00155 *p++ = hex_digit[src[i] >> 4];
00156 *p++ = '.';
00157 }
00158
00159 ink_strlcpy(p, "ip6.arpa", MAXDNAME - (p - buffer + 1));
00160 }
00161
00162
00163
00164
00165
00166 int
00167 DNSProcessor::start(int, size_t stacksize) {
00168
00169
00170
00171 REC_EstablishStaticConfigInt32(dns_retries, "proxy.config.dns.retries");
00172 REC_EstablishStaticConfigInt32(dns_timeout, "proxy.config.dns.lookup_timeout");
00173 REC_EstablishStaticConfigInt32(dns_search, "proxy.config.dns.search_default_domains");
00174 REC_EstablishStaticConfigInt32(dns_failover_number, "proxy.config.dns.failover_number");
00175 REC_EstablishStaticConfigInt32(dns_failover_period, "proxy.config.dns.failover_period");
00176 REC_EstablishStaticConfigInt32(dns_max_dns_in_flight, "proxy.config.dns.max_dns_in_flight");
00177 REC_EstablishStaticConfigInt32(dns_validate_qname, "proxy.config.dns.validate_query_name");
00178 REC_EstablishStaticConfigInt32(dns_ns_rr, "proxy.config.dns.round_robin_nameservers");
00179 REC_ReadConfigStringAlloc(dns_ns_list, "proxy.config.dns.nameservers");
00180 REC_ReadConfigStringAlloc(dns_local_ipv4, "proxy.config.dns.local_ipv4");
00181 REC_ReadConfigStringAlloc(dns_local_ipv6, "proxy.config.dns.local_ipv6");
00182 REC_ReadConfigStringAlloc(dns_resolv_conf, "proxy.config.dns.resolv_conf");
00183 REC_EstablishStaticConfigInt32(dns_thread, "proxy.config.dns.dedicated_thread");
00184
00185 if (dns_thread > 0) {
00186
00187 ET_DNS = eventProcessor.spawn_event_threads(1, "ET_DNS", stacksize);
00188 initialize_thread_for_net(eventProcessor.eventthread[ET_DNS][0]);
00189 } else {
00190
00191 ET_DNS = ET_CALL;
00192 }
00193 thread = eventProcessor.eventthread[ET_DNS][0];
00194
00195 dns_failover_try_period = dns_timeout + 1;
00196
00197 if (SplitDNSConfig::gsplit_dns_enabled) {
00198
00199 SplitDNSConfig::reconfigure();
00200 }
00201
00202
00203 dns_init();
00204 open();
00205
00206 return 0;
00207 }
00208
00209 void
00210 DNSProcessor::open(sockaddr const* target, int aoptions)
00211 {
00212 DNSHandler *h = new DNSHandler;
00213
00214 h->options = aoptions;
00215 h->mutex = thread->mutex;
00216 h->m_res = &l_res;
00217 ats_ip_copy(&h->local_ipv4.sa, &local_ipv4.sa);
00218 ats_ip_copy(&h->local_ipv6.sa, &local_ipv6.sa);
00219
00220 if (target)
00221 ats_ip_copy(&h->ip, target);
00222 else
00223 ats_ip_invalidate(&h->ip);
00224
00225 if (!dns_handler_initialized)
00226 handler = h;
00227
00228 SET_CONTINUATION_HANDLER(h, &DNSHandler::startEvent);
00229 thread->schedule_imm(h);
00230 }
00231
00232
00233
00234
00235 void
00236 DNSProcessor::dns_init()
00237 {
00238 gethostname(try_server_names[0], 255);
00239 Debug("dns", "localhost=%s\n", try_server_names[0]);
00240 Debug("dns", "Round-robin nameservers = %d\n", dns_ns_rr);
00241
00242 IpEndpoint nameserver[MAX_NAMED];
00243 size_t nserv = 0;
00244
00245 if (dns_ns_list) {
00246 Debug("dns", "Nameserver list specified \"%s\"\n", dns_ns_list);
00247 int i;
00248 char *last;
00249 char *ns_list = ats_strdup(dns_ns_list);
00250 char *ns = (char *) strtok_r(ns_list, " ,;\t\r", &last);
00251
00252 for (i = 0, nserv = 0 ; (i < MAX_NAMED) && ns ; ++i) {
00253 Debug("dns", "Nameserver list - parsing \"%s\"\n", ns);
00254 bool err = false;
00255 int prt = DOMAIN_SERVICE_PORT;
00256 char* colon = 0;
00257
00258 if ('[' == *ns) {
00259 char* ndx = strchr(ns+1, ']');
00260 if (ndx) {
00261 if (':' == ndx[1]) colon = ndx+1;
00262 } else {
00263 err = true;
00264 Warning("Unmatched '[' in address for nameserver '%s', discarding.", ns);
00265 }
00266 } else colon = strchr(ns, ':');
00267
00268 if (!err && colon) {
00269 *colon = '\0';
00270
00271 if (sscanf(colon + 1, "%d%*s", &prt) != 1) {
00272 Debug("dns", "Unable to parse port number '%s' for nameserver '%s', discardin.", colon + 1, ns);
00273 Warning("Unable to parse port number '%s' for nameserver '%s', discarding.", colon + 1, ns);
00274 err = true;
00275 }
00276 }
00277
00278 if (!err && 0 != ats_ip_pton(ns, &nameserver[nserv].sa)) {
00279 Debug("dns", "Invalid IP address given for nameserver '%s', discarding", ns);
00280 Warning("Invalid IP address given for nameserver '%s', discarding", ns);
00281 err = true;
00282 }
00283
00284 if (!err) {
00285 ip_port_text_buffer buff;
00286
00287 ats_ip_port_cast(&nameserver[nserv].sa) = htons(prt);
00288
00289 Debug("dns", "Adding nameserver %s to nameserver list",
00290 ats_ip_nptop(&nameserver[nserv].sa, buff, sizeof(buff))
00291 );
00292 ++nserv;
00293 }
00294
00295 ns = (char *) strtok_r(NULL, " ,;\t\r", &last);
00296 }
00297 ats_free(ns_list);
00298 }
00299
00300
00301 if (ink_res_init(&l_res, nameserver, nserv, NULL, NULL, dns_resolv_conf) < 0)
00302 Warning("Failed to build DNS res records for the servers (%s). Using resolv.conf.", dns_ns_list);
00303
00304
00305
00306 if (dns_local_ipv6) {
00307 if (0 != ats_ip_pton(dns_local_ipv6, &local_ipv6)) {
00308 ats_ip_invalidate(&local_ipv6);
00309 Warning("Invalid IP address '%s' for dns.local_ipv6 value, discarding.", dns_local_ipv6);
00310 } else if (!ats_is_ip6(&local_ipv6.sa)) {
00311 ats_ip_invalidate(&local_ipv6);
00312 Warning("IP address '%s' for dns.local_ipv6 value was not IPv6, discarding.", dns_local_ipv6);
00313 }
00314 }
00315
00316 if (dns_local_ipv4) {
00317 if (0 != ats_ip_pton(dns_local_ipv4, &local_ipv4)) {
00318 ats_ip_invalidate(&local_ipv4);
00319 Warning("Invalid IP address '%s' for dns.local_ipv4 value, discarding.", dns_local_ipv4);
00320 } else if (!ats_is_ip4(&local_ipv4.sa)) {
00321 ats_ip_invalidate(&local_ipv4);
00322 Warning("IP address '%s' for dns.local_ipv4 value was not IPv4, discarding.", dns_local_ipv4);
00323 }
00324 }
00325 }
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335 inline int
00336 ink_dn_expand(const u_char *msg, const u_char *eom, const u_char *comp_dn, u_char *exp_dn, int length)
00337 {
00338 return::dn_expand((unsigned char *) msg, (unsigned char *) eom, (unsigned char *) comp_dn, (char *) exp_dn, length);
00339 }
00340
00341 DNSProcessor::DNSProcessor()
00342 : thread(NULL), handler(NULL)
00343 {
00344 ink_zero(l_res);
00345 ink_zero(local_ipv6);
00346 ink_zero(local_ipv4);
00347 }
00348
00349 void
00350 DNSEntry::init(const char *x, int len, int qtype_arg, Continuation* acont,
00351 DNSProcessor::Options const& opt)
00352 {
00353 qtype = qtype_arg;
00354 host_res_style = opt.host_res_style;
00355 if (is_addr_query(qtype)) {
00356
00357 if (HOST_RES_IPV4 == host_res_style ||
00358 HOST_RES_IPV4_ONLY == host_res_style) {
00359 qtype = T_A;
00360 } else if (HOST_RES_IPV6 == host_res_style ||
00361 HOST_RES_IPV6_ONLY == host_res_style) {
00362 qtype = T_AAAA;
00363 }
00364 }
00365 submit_time = ink_get_hrtime();
00366 action = acont;
00367 submit_thread = acont->mutex->thread_holding;
00368
00369 #ifdef SPLIT_DNS
00370 if (SplitDNSConfig::gsplit_dns_enabled) {
00371 dnsH = opt.handler ? opt.handler : dnsProcessor.handler;
00372 } else {
00373 dnsH = dnsProcessor.handler;
00374 }
00375 #else
00376 dnsH = dnsProcessor.handler;
00377 #endif // SPLIT_DNS
00378
00379 dnsH->txn_lookup_timeout = opt.timeout;
00380
00381 mutex = dnsH->mutex;
00382
00383 if (is_addr_query(qtype) || qtype == T_SRV) {
00384 if (len) {
00385 len = len > (MAXDNAME - 1) ? (MAXDNAME - 1) : len;
00386 memcpy(qname, x, len);
00387 qname[len] = 0;
00388 orig_qname_len = qname_len = len;
00389 } else {
00390 qname_len = ink_strlcpy(qname, x, MAXDNAME);
00391 orig_qname_len = qname_len;
00392 }
00393 } else {
00394 IpAddr const* ip = reinterpret_cast<IpAddr const*>(x);
00395 if (ip->isIp6())
00396 make_ipv6_ptr(&ip->_addr._ip6, qname);
00397 else if (ip->isIp4())
00398 make_ipv4_ptr(ip->_addr._ip4, qname);
00399 else
00400 ink_assert(!"T_PTR query to DNS must be IP address.");
00401 }
00402
00403 SET_HANDLER((DNSEntryHandler) & DNSEntry::mainEvent);
00404 }
00405
00406
00407
00408
00409
00410
00411 void
00412 DNSHandler::open_con(sockaddr const* target, bool failed, int icon)
00413 {
00414 ip_port_text_buffer ip_text;
00415 PollDescriptor *pd = get_PollDescriptor(dnsProcessor.thread);
00416
00417 if (!icon && target) {
00418 ats_ip_copy(&ip, target);
00419 } else if (!target) {
00420 target = &ip.sa;
00421 }
00422
00423 Debug("dns", "open_con: opening connection %s", ats_ip_nptop(target, ip_text, sizeof ip_text));
00424
00425 if (con[icon].fd != NO_FD) {
00426 con[icon].eio.stop();
00427 con[icon].close();
00428 }
00429
00430 if (con[icon].connect(
00431 target, DNSConnection::Options()
00432 .setNonBlockingConnect(true)
00433 .setNonBlockingIo(true)
00434 .setUseTcp(false)
00435 .setBindRandomPort(true)
00436 .setLocalIpv6(&local_ipv6.sa)
00437 .setLocalIpv4(&local_ipv4.sa)
00438 ) < 0) {
00439 Debug("dns", "opening connection %s FAILED for %d", ip_text, icon);
00440 if (!failed) {
00441 if (dns_ns_rr)
00442 rr_failure(icon);
00443 else
00444 failover();
00445 }
00446 return;
00447 } else {
00448 ns_down[icon] = 0;
00449 if (con[icon].eio.start(pd, &con[icon], EVENTIO_READ) < 0) {
00450 Error("[iocore_dns] open_con: Failed to add %d server to epoll list\n", icon);
00451 } else {
00452 con[icon].num = icon;
00453 Debug("dns", "opening connection %s SUCCEEDED for %d", ip_text, icon);
00454 }
00455 }
00456 }
00457
00458 void
00459 DNSHandler::validate_ip() {
00460 if (!ip.isValid()) {
00461
00462
00463 if (!m_res->nscount || !ats_ip_copy(&ip.sa, &m_res->nsaddr_list[0].sa)) {
00464 Warning("bad nameserver config, fallback to loopback");
00465 ip.setToLoopback(AF_INET);
00466 }
00467 }
00468 }
00469
00470
00471
00472
00473
00474 int
00475 DNSHandler::startEvent(int , Event *e)
00476 {
00477
00478
00479 Debug("dns", "DNSHandler::startEvent: on thread %d\n", e->ethread->id);
00480
00481 this->validate_ip();
00482
00483 if (!dns_handler_initialized) {
00484
00485
00486
00487
00488 dns_handler_initialized = 1;
00489 SET_HANDLER(&DNSHandler::mainEvent);
00490 if (dns_ns_rr) {
00491 int max_nscount = m_res->nscount;
00492 if (max_nscount > MAX_NAMED)
00493 max_nscount = MAX_NAMED;
00494 n_con = 0;
00495 for (int i = 0; i < max_nscount; i++) {
00496 ip_port_text_buffer buff;
00497 sockaddr *sa = &m_res->nsaddr_list[i].sa;
00498 if (ats_is_ip(sa)) {
00499 open_con(sa, false, n_con);
00500 ++n_con;
00501 Debug("dns_pas", "opened connection to %s, n_con = %d",
00502 ats_ip_nptop(sa, buff, sizeof(buff)),
00503 n_con
00504 );
00505 }
00506 }
00507 dns_ns_rr_init_down = 0;
00508 } else {
00509 open_con(0);
00510 n_con = 1;
00511 }
00512 e->ethread->schedule_every(this, DNS_PERIOD);
00513
00514 return EVENT_CONT;
00515 } else {
00516 ink_assert(false);
00517 return EVENT_DONE;
00518 }
00519 }
00520
00521
00522
00523
00524
00525 int
00526 DNSHandler::startEvent_sdns(int , Event *e)
00527 {
00528 Debug("dns", "DNSHandler::startEvent_sdns: on thread %d\n", e->ethread->id);
00529 this->validate_ip();
00530
00531 SET_HANDLER(&DNSHandler::mainEvent);
00532 open_con(&ip.sa, false, n_con);
00533 ++n_con;
00534
00535 e->schedule_every(DNS_PERIOD);
00536 return EVENT_CONT;
00537 }
00538
00539 static inline int
00540 _ink_res_mkquery(ink_res_state res, char *qname, int qtype, char *buffer)
00541 {
00542 int r = ink_res_mkquery(res, QUERY, qname, C_IN, qtype,
00543 NULL, 0, NULL, (unsigned char *) buffer,
00544 MAX_DNS_PACKET_LEN);
00545 return r;
00546 }
00547
00548 void
00549 DNSHandler::recover()
00550 {
00551 ip_text_buffer buff;
00552 Warning("connection to DNS server %s restored", ats_ip_ntop(&ip.sa, buff, sizeof(buff)));
00553 name_server = 0;
00554 switch_named(name_server);
00555 }
00556
00557 void
00558 DNSHandler::retry_named(int ndx, ink_hrtime t, bool reopen)
00559 {
00560 if (reopen && ((t - last_primary_reopen) > DNS_PRIMARY_REOPEN_PERIOD)) {
00561 Debug("dns", "retry_named: reopening DNS connection for index %d", ndx);
00562 last_primary_reopen = t;
00563 con[ndx].close();
00564 open_con(&m_res->nsaddr_list[ndx].sa, true, ndx);
00565 }
00566
00567 char buffer[MAX_DNS_PACKET_LEN];
00568 Debug("dns", "trying to resolve '%s' from DNS connection, ndx %d", try_server_names[try_servers], ndx);
00569 int r = _ink_res_mkquery(m_res, try_server_names[try_servers], T_A, buffer);
00570 try_servers = (try_servers + 1) % countof(try_server_names);
00571 ink_assert(r >= 0);
00572 if (r >= 0) {
00573 int res = socketManager.send(con[ndx].fd, buffer, r, 0);
00574 Debug("dns", "ping result = %d", res);
00575 }
00576 }
00577
00578 void
00579 DNSHandler::try_primary_named(bool reopen)
00580 {
00581 ink_hrtime t = ink_get_hrtime();
00582 if (reopen && ((t - last_primary_reopen) > DNS_PRIMARY_REOPEN_PERIOD)) {
00583 Debug("dns", "try_primary_named: reopening primary DNS connection");
00584 last_primary_reopen = t;
00585 open_con(&ip.sa, true, 0);
00586 }
00587 if ((t - last_primary_retry) > DNS_PRIMARY_RETRY_PERIOD) {
00588 char buffer[MAX_DNS_PACKET_LEN];
00589
00590 last_primary_retry = t;
00591 Debug("dns", "trying to resolve '%s' from primary DNS connection", try_server_names[try_servers]);
00592 int r = _ink_res_mkquery(m_res, try_server_names[try_servers], T_A, buffer);
00593
00594
00595 if (local_num_entries < DEFAULT_NUM_TRY_SERVER)
00596 try_servers = (try_servers + 1) % local_num_entries;
00597 else
00598 try_servers = (try_servers + 1) % countof(try_server_names);
00599 ink_assert(r >= 0);
00600 if (r >= 0) {
00601 int res = socketManager.send(con[0].fd, buffer, r, 0);
00602 Debug("dns", "ping result = %d", res);
00603 }
00604 }
00605 }
00606
00607
00608 void
00609 DNSHandler::switch_named(int ndx)
00610 {
00611 for (DNSEntry *e = entries.head; e; e = (DNSEntry *) e->link.next) {
00612 e->written_flag = 0;
00613 if (e->retries < dns_retries)
00614 ++(e->retries);
00615 }
00616 in_flight = 0;
00617 received_one(ndx);
00618 }
00619
00620
00621 void
00622 DNSHandler::failover()
00623 {
00624 Debug("dns", "failover: initiating failover attempt, current name_server=%d", name_server);
00625
00626 if (m_res->nscount > 1) {
00627 ip_text_buffer buff1, buff2;
00628 int max_nscount = m_res->nscount;
00629
00630 if (max_nscount > MAX_NAMED)
00631 max_nscount = MAX_NAMED;
00632 sockaddr const* old_addr = &m_res->nsaddr_list[name_server].sa;
00633 name_server = (name_server + 1) % max_nscount;
00634 Debug("dns", "failover: failing over to name_server=%d", name_server);
00635
00636 IpEndpoint target;
00637 ats_ip_copy(&target.sa, &m_res->nsaddr_list[name_server].sa);
00638
00639 Warning("failover: connection to DNS server %s lost, move to %s",
00640 ats_ip_ntop(old_addr, buff1, sizeof(buff1)),
00641 ats_ip_ntop(&target.sa, buff2, sizeof(buff2))
00642 );
00643
00644 if (!target.isValid()) target.setToLoopback(AF_INET);
00645
00646 open_con(&target.sa, true, name_server);
00647 if (n_con <= name_server)
00648 n_con = name_server + 1;
00649 switch_named(name_server);
00650 } else {
00651 ip_text_buffer buff;
00652 Warning("failover: connection to DNS server %s lost, retrying",
00653 ats_ip_ntop(&ip.sa, buff, sizeof(buff))
00654 );
00655 }
00656 }
00657
00658
00659 void
00660 DNSHandler::rr_failure(int ndx)
00661 {
00662
00663 if (!ns_down[ndx]) {
00664 ip_text_buffer buff;
00665
00666 Debug("dns", "rr_failure: Marking nameserver %d as down", ndx);
00667 ns_down[ndx] = 1;
00668 Warning("connection to DNS server %s lost, marking as down",
00669 ats_ip_ntop(&m_res->nsaddr_list[ndx].sa, buff, sizeof(buff))
00670 );
00671 }
00672
00673 int nscount = m_res->nscount;
00674 if (nscount > MAX_NAMED)
00675 nscount = MAX_NAMED;
00676
00677
00678 int all_down = 1;
00679
00680 for (int i = 0; i < nscount && all_down; i++) {
00681 Debug("dns", "nsdown[%d]=%d", i, ns_down[i]);
00682 if (!ns_down[i]) {
00683 all_down = 0;
00684 }
00685 }
00686
00687 if (all_down && !dns_ns_rr_init_down) {
00688 Warning("connection to all DNS servers lost, retrying");
00689
00690
00691 for (DNSEntry *e = entries.head; e; e = (DNSEntry *) e->link.next) {
00692 e->written_flag = 0;
00693 if (e->retries < dns_retries)
00694 ++(e->retries);
00695 --in_flight;
00696 DNS_DECREMENT_DYN_STAT(dns_in_flight_stat);
00697 }
00698 } else {
00699
00700 for (DNSEntry *e = entries.head; e; e = (DNSEntry *) e->link.next) {
00701 if (e->which_ns == ndx) {
00702 e->written_flag = 0;
00703 if (e->retries < dns_retries)
00704 ++(e->retries);
00705 --in_flight;
00706 DNS_DECREMENT_DYN_STAT(dns_in_flight_stat);
00707 }
00708 }
00709 }
00710 }
00711
00712 static inline unsigned int get_rcode(char* buff) {
00713 return reinterpret_cast<HEADER*>(buff)->rcode;
00714 }
00715
00716 static inline unsigned int get_rcode(HostEnt* ent) {
00717 return get_rcode(reinterpret_cast<char*>(ent));
00718 }
00719
00720 static bool
00721 good_rcode(char *buff) {
00722 unsigned int r = get_rcode(buff);
00723 return NOERROR == r || NXDOMAIN == r;
00724 }
00725
00726
00727 void
00728 DNSHandler::recv_dns(int , Event * )
00729 {
00730 DNSConnection *dnsc = NULL;
00731 ip_text_buffer ipbuff1, ipbuff2;
00732
00733 while ((dnsc = (DNSConnection *) triggered.dequeue())) {
00734 while (1) {
00735 IpEndpoint from_ip;
00736 socklen_t from_length = sizeof(from_ip);
00737
00738 if (!hostent_cache)
00739 hostent_cache = dnsBufAllocator.alloc();
00740 HostEnt *buf = hostent_cache;
00741
00742 int res = socketManager.recvfrom(dnsc->fd, buf->buf, MAX_DNS_PACKET_LEN, 0, &from_ip.sa, &from_length);
00743
00744 if (res == -EAGAIN)
00745 break;
00746 if (res <= 0) {
00747 Debug("dns", "named error: %d", res);
00748 if (dns_ns_rr)
00749 rr_failure(dnsc->num);
00750 else if (dnsc->num == name_server)
00751 failover();
00752 break;
00753 }
00754
00755
00756 if (!ats_ip_addr_eq(&dnsc->ip.sa, &from_ip.sa)) {
00757 Warning("unexpected DNS response from %s (expected %s)",
00758 ats_ip_ntop(&from_ip.sa, ipbuff1, sizeof ipbuff1),
00759 ats_ip_ntop(&dnsc->ip.sa, ipbuff2, sizeof ipbuff2)
00760 );
00761 continue;
00762 }
00763 hostent_cache = 0;
00764 buf->packet_size = res;
00765 Debug("dns", "received packet size = %d", res);
00766 if (dns_ns_rr) {
00767 Debug("dns", "round-robin: nameserver %d DNS response code = %d", dnsc->num, get_rcode(buf));
00768 if (good_rcode(buf->buf)) {
00769 received_one(dnsc->num);
00770 if (ns_down[dnsc->num]) {
00771 Warning("connection to DNS server %s restored",
00772 ats_ip_ntop(&m_res->nsaddr_list[dnsc->num].sa, ipbuff1, sizeof ipbuff1)
00773 );
00774 ns_down[dnsc->num] = 0;
00775 }
00776 }
00777 } else {
00778 if (!dnsc->num) {
00779 Debug("dns", "primary DNS response code = %d", get_rcode(buf));
00780 if (good_rcode(buf->buf)) {
00781 if (name_server)
00782 recover();
00783 else
00784 received_one(name_server);
00785 }
00786 }
00787 }
00788 Ptr<HostEnt> protect_hostent = make_ptr(buf);
00789 if (dns_process(this, buf, res)) {
00790 if (dnsc->num == name_server)
00791 received_one(name_server);
00792 }
00793 }
00794 }
00795 }
00796
00797
00798 int
00799 DNSHandler::mainEvent(int event, Event *e)
00800 {
00801 recv_dns(event, e);
00802 if (dns_ns_rr) {
00803 ink_hrtime t = ink_get_hrtime();
00804 if (t - last_primary_retry > DNS_PRIMARY_RETRY_PERIOD) {
00805 for (int i = 0; i < n_con; i++) {
00806 if (ns_down[i]) {
00807 Debug("dns", "mainEvent: nameserver = %d is down", i);
00808 retry_named(i, t, true);
00809 }
00810 }
00811 last_primary_retry = t;
00812 }
00813 for (int i = 0; i < n_con; i++) {
00814 if (!ns_down[i] && failover_soon(i)) {
00815 Debug("dns", "mainEvent: nameserver = %d failover soon", name_server);
00816 if (failover_now(i))
00817 rr_failure(i);
00818 else {
00819 Debug("dns", "mainEvent: nameserver = %d no failover now - retrying", i);
00820 retry_named(i, t, false);
00821 ++failover_soon_number[i];
00822 }
00823 }
00824 }
00825 } else {
00826 if (failover_soon(name_server)) {
00827 Debug("dns", "mainEvent: will failover soon");
00828 if (failover_now(name_server)) {
00829 Debug("dns", "mainEvent: failing over now to another nameserver");
00830 failover();
00831 } else {
00832 try_primary_named(false);
00833 ++failover_soon_number[name_server];
00834 }
00835 } else if (name_server)
00836 try_primary_named(true);
00837 }
00838
00839 if (entries.head)
00840 write_dns(this);
00841
00842 return EVENT_CONT;
00843 }
00844
00845
00846 inline static DNSEntry *
00847 get_dns(DNSHandler *h, uint16_t id)
00848 {
00849 for (DNSEntry *e = h->entries.head; e; e = (DNSEntry *) e->link.next) {
00850 if (e->once_written_flag) {
00851 for (int j = 0; j < MAX_DNS_RETRIES; j++) {
00852 if (e->id[j] == id) {
00853 return e;
00854 } else if (e->id[j] < 0) {
00855 goto Lnext;
00856 }
00857 }
00858 }
00859 Lnext:;
00860 }
00861 return NULL;
00862 }
00863
00864
00865 inline static DNSEntry *
00866 get_entry(DNSHandler *h, char *qname, int qtype)
00867 {
00868 for (DNSEntry *e = h->entries.head; e; e = (DNSEntry *) e->link.next) {
00869 if (e->qtype == qtype) {
00870 if (is_addr_query(qtype)) {
00871 if (!strcmp(qname, e->qname))
00872 return e;
00873 } else if (0 == memcmp(qname, e->qname, e->qname_len))
00874 return e;
00875 }
00876 }
00877 return NULL;
00878 }
00879
00880
00881 static void
00882 write_dns(DNSHandler *h)
00883 {
00884 ProxyMutex *mutex = h->mutex;
00885 DNS_INCREMENT_DYN_STAT(dns_total_lookups_stat);
00886 int max_nscount = h->m_res->nscount;
00887 if (max_nscount > MAX_NAMED)
00888 max_nscount = MAX_NAMED;
00889
00890 if (h->in_write_dns)
00891 return;
00892 h->in_write_dns = true;
00893
00894 if (h->in_flight < dns_max_dns_in_flight) {
00895 DNSEntry *e = h->entries.head;
00896 while (e) {
00897 DNSEntry *n = (DNSEntry *) e->link.next;
00898 if (!e->written_flag) {
00899 if (dns_ns_rr) {
00900 int ns_start = h->name_server;
00901 do {
00902 h->name_server = (h->name_server + 1) % max_nscount;
00903 } while (h->ns_down[h->name_server] && h->name_server != ns_start);
00904 }
00905 if (!write_dns_event(h, e))
00906 break;
00907 }
00908 if (h->in_flight >= dns_max_dns_in_flight)
00909 break;
00910 e = n;
00911 }
00912 }
00913 h->in_write_dns = false;
00914 }
00915
00916 uint16_t
00917 DNSHandler::get_query_id()
00918 {
00919 uint16_t q1, q2;
00920 q2 = q1 = (uint16_t)(generator.random() & 0xFFFF);
00921 if (query_id_in_use(q2)) {
00922 uint16_t i = q2>>6;
00923 while (qid_in_flight[i] == UINT64_MAX) {
00924 if (++i == sizeof(qid_in_flight)/sizeof(uint64_t)) {
00925 i = 0;
00926 }
00927 if (i == q1>>6) {
00928 Error("[iocore_dns] get_query_id: Exhausted all DNS query ids");
00929 return q1;
00930 }
00931 }
00932 i <<= 6;
00933 q2 &= 0x3F;
00934 while (query_id_in_use(i+q2)) {
00935 ++q2;
00936 q2 &= 0x3F;
00937 if (q2 == (q1 & 0x3F)) {
00938 Error("[iocore_dns] get_query_id: Exhausted all DNS query ids");
00939 return q1;
00940 }
00941 }
00942 q2 += i;
00943 }
00944
00945 set_query_id_in_use(q2);
00946 return q2;
00947 }
00948
00949
00950
00951
00952
00953
00954
00955 static bool
00956 write_dns_event(DNSHandler *h, DNSEntry *e)
00957 {
00958 ProxyMutex *mutex = h->mutex;
00959 union {
00960 HEADER _h;
00961 char _b[MAX_DNS_PACKET_LEN];
00962 } blob;
00963 int r = 0;
00964
00965 if ((r = _ink_res_mkquery(h->m_res, e->qname, e->qtype, blob._b)) <= 0) {
00966 Debug("dns", "cannot build query: %s", e->qname);
00967 dns_result(h, e, NULL, false);
00968 return true;
00969 }
00970
00971 uint16_t i = h->get_query_id();
00972 blob._h.id = htons(i);
00973 if (e->id[dns_retries - e->retries] >= 0) {
00974
00975 h->release_query_id(e->id[dns_retries - e->retries]);
00976 }
00977 e->id[dns_retries - e->retries] = i;
00978 Debug("dns", "send query (qtype=%d) for %s to fd %d", e->qtype, e->qname, h->con[h->name_server].fd);
00979
00980 int s = socketManager.send(h->con[h->name_server].fd, blob._b, r, 0);
00981 if (s != r) {
00982 Debug("dns", "send() failed: qname = %s, %d != %d, nameserver= %d", e->qname, s, r, h->name_server);
00983
00984 if (s < 0) {
00985 if (dns_ns_rr)
00986 h->rr_failure(h->name_server);
00987 else
00988 h->failover();
00989 }
00990 return false;
00991 }
00992
00993 e->written_flag = true;
00994 e->which_ns = h->name_server;
00995 e->once_written_flag = true;
00996 ++h->in_flight;
00997 DNS_INCREMENT_DYN_STAT(dns_in_flight_stat);
00998
00999 e->send_time = ink_get_hrtime();
01000
01001 if (e->timeout)
01002 e->timeout->cancel();
01003
01004 if (h->txn_lookup_timeout) {
01005 e->timeout = h->mutex->thread_holding->schedule_in(e, HRTIME_MSECONDS(h->txn_lookup_timeout));
01006 } else {
01007 e->timeout = h->mutex->thread_holding->schedule_in(e, HRTIME_SECONDS(dns_timeout));
01008 }
01009
01010 Debug("dns", "sent qname = %s, id = %u, nameserver = %d", e->qname, e->id[dns_retries - e->retries], h->name_server);
01011 h->sent_one();
01012 return true;
01013 }
01014
01015
01016 int
01017 DNSEntry::delayEvent(int event, Event *e)
01018 {
01019 (void) event;
01020 if (dnsProcessor.handler) {
01021 SET_HANDLER((DNSEntryHandler) & DNSEntry::mainEvent);
01022 return handleEvent(EVENT_IMMEDIATE, e);
01023 }
01024 e->schedule_in(DNS_DELAY_PERIOD);
01025 return EVENT_CONT;
01026 }
01027
01028
01029 int
01030 DNSEntry::mainEvent(int event, Event *e)
01031 {
01032 switch (event) {
01033 default:
01034 ink_assert(!"bad case");
01035 return EVENT_DONE;
01036 case EVENT_IMMEDIATE:{
01037 if (!dnsH)
01038 dnsH = dnsProcessor.handler;
01039 if (!dnsH) {
01040 Debug("dns", "handler not found, retrying...");
01041 SET_HANDLER((DNSEntryHandler) & DNSEntry::delayEvent);
01042 return handleEvent(event, e);
01043 }
01044
01045
01046 if (dns_search && ('.' != qname[orig_qname_len - 1])) {
01047 domains = dnsH->m_res->dnsrch;
01048
01049
01050 if (domains && !strnchr(qname, '.', MAXDNAME)) {
01051 qname[orig_qname_len] = '.';
01052 qname_len = orig_qname_len + 1 + ink_strlcpy(qname + orig_qname_len + 1, *domains,
01053 MAXDNAME - (orig_qname_len + 1));
01054 ++domains;
01055 }
01056 } else {
01057 domains = NULL;
01058 }
01059 Debug("dns", "enqueing query %s", qname);
01060 DNSEntry *dup = get_entry(dnsH, qname, qtype);
01061 if (dup) {
01062 Debug("dns", "collapsing NS request");
01063 dup->dups.enqueue(this);
01064 } else {
01065 Debug("dns", "adding first to collapsing queue");
01066 dnsH->entries.enqueue(this);
01067 write_dns(dnsH);
01068 }
01069 return EVENT_DONE;
01070 }
01071 case EVENT_INTERVAL:
01072 Debug("dns", "timeout for query %s", qname);
01073 if (dnsH->txn_lookup_timeout) {
01074 timeout = NULL;
01075 dns_result(dnsH, this, result_ent, false);
01076 return EVENT_DONE;
01077 }
01078 if (written_flag) {
01079 Debug("dns", "marking %s as not-written", qname);
01080 written_flag = false;
01081 --(dnsH->in_flight);
01082 DNS_DECREMENT_DYN_STAT(dns_in_flight_stat);
01083 }
01084 timeout = NULL;
01085 dns_result(dnsH, this, result_ent, true);
01086 return EVENT_DONE;
01087 }
01088 }
01089
01090 Action *
01091 DNSProcessor::getby(const char *x, int len, int type, Continuation *cont, Options const& opt)
01092 {
01093 Debug("dns", "received query %s type = %d, timeout = %d", x, type, opt.timeout);
01094 if (type == T_SRV) {
01095 Debug("dns_srv", "DNSProcessor::getby attempting an SRV lookup for %s, timeout = %d", x, opt.timeout);
01096 }
01097 DNSEntry *e = dnsEntryAllocator.alloc();
01098 e->retries = dns_retries;
01099 e->init(x, len, type, cont, opt);
01100 MUTEX_TRY_LOCK(lock, e->mutex, this_ethread());
01101 if (!lock)
01102 thread->schedule_imm(e);
01103 else
01104 e->handleEvent(EVENT_IMMEDIATE, 0);
01105 return &e->action;
01106 }
01107
01108
01109
01110
01111
01112 static void
01113 dns_result(DNSHandler *h, DNSEntry *e, HostEnt *ent, bool retry) {
01114 ProxyMutex *mutex = h->mutex;
01115 bool cancelled = (e->action.cancelled ? true : false);
01116
01117 if (!ent && !cancelled) {
01118
01119 if (retry && e->retries) {
01120 Debug("dns", "doing retry for %s", e->qname);
01121
01122 DNS_INCREMENT_DYN_STAT(dns_retries_stat);
01123
01124 --(e->retries);
01125 write_dns(h);
01126 return;
01127 } else if (e->domains && *e->domains) {
01128 do {
01129 Debug("dns", "domain extending, last tried '%s', original '%.*s'", e->qname, e->orig_qname_len, e->qname);
01130
01131
01132 if (e->orig_qname_len + strlen(*e->domains) + 2 > MAXDNAME) {
01133 Debug("dns", "domain too large %.*s + %s", e->orig_qname_len, e->qname, *e->domains);
01134 } else {
01135 e->qname[e->orig_qname_len] = '.';
01136 e->qname_len = e->orig_qname_len + 1 + ink_strlcpy(e->qname + e->orig_qname_len + 1, *e->domains,
01137 MAXDNAME - (e->orig_qname_len + 1));
01138 ++(e->domains);
01139 e->retries = dns_retries;
01140 Debug("dns", "new name = %s retries = %d", e->qname, e->retries);
01141 write_dns(h);
01142
01143 return;
01144 }
01145
01146
01147 ++(e->domains);
01148 } while (*e->domains);
01149 } else {
01150 e->qname[e->qname_len] = 0;
01151 if (!strchr(e->qname, '.') && !e->last) {
01152 e->last = true;
01153 write_dns(h);
01154 return;
01155 }
01156 }
01157 if (retry) {
01158 DNS_INCREMENT_DYN_STAT(dns_max_retries_exceeded_stat);
01159 }
01160 }
01161 if (ent == BAD_DNS_RESULT)
01162 ent = NULL;
01163 if (!cancelled) {
01164 if (!ent) {
01165 DNS_SUM_DYN_STAT(dns_fail_time_stat, ink_get_hrtime() - e->submit_time);
01166 } else {
01167 DNS_SUM_DYN_STAT(dns_success_time_stat, ink_get_hrtime() - e->submit_time);
01168 }
01169 }
01170 h->entries.remove(e);
01171
01172 if (is_debug_tag_set("dns")) {
01173 if (is_addr_query(e->qtype)) {
01174 ip_text_buffer buff;
01175 char const* ptr = "<none>";
01176 char const* result = "FAIL";
01177 if (ent) {
01178 result = "SUCCESS";
01179 ptr = inet_ntop(e->qtype == T_AAAA ? AF_INET6 : AF_INET, ent->ent.h_addr_list[0], buff, sizeof(buff));
01180 }
01181 Debug("dns", "%s result for %s = %s retry %d", result, e->qname, ptr, retry);
01182 } else {
01183 if (ent) {
01184 Debug("dns", "SUCCESS result for %s = %s af=%d retry %d", e->qname, ent->ent.h_name, ent->ent.h_addrtype, retry);
01185 } else {
01186 Debug("dns", "FAIL result for %s = <not found> retry %d", e->qname, retry);
01187 }
01188 }
01189 }
01190
01191 if (ent) {
01192 DNS_INCREMENT_DYN_STAT(dns_lookup_success_stat);
01193 } else {
01194 DNS_INCREMENT_DYN_STAT(dns_lookup_fail_stat);
01195 }
01196
01197 DNSEntry *dup = NULL;
01198 while ((dup = e->dups.dequeue())) {
01199 if (dup->post(h, ent)) {
01200 e->dups.enqueue(dup);
01201 goto Lretry;
01202 }
01203 }
01204
01205 if (e->timeout) {
01206 e->timeout->cancel(e);
01207 e->timeout = NULL;
01208 }
01209 e->result_ent = ent;
01210
01211 if (h->mutex->thread_holding == e->submit_thread) {
01212 MUTEX_TRY_LOCK(lock, e->action.mutex, h->mutex->thread_holding);
01213 if (!lock) {
01214 Debug("dns", "failed lock for result %s", e->qname);
01215 goto Lretry;
01216 }
01217 for (int i = 0; i < MAX_DNS_RETRIES; i++) {
01218 if (e->id[i] < 0)
01219 break;
01220 h->release_query_id(e->id[i]);
01221 }
01222 e->postEvent(0, 0);
01223 } else {
01224 for (int i = 0; i < MAX_DNS_RETRIES; i++) {
01225 if (e->id[i] < 0)
01226 break;
01227 h->release_query_id(e->id[i]);
01228 }
01229 e->mutex = e->action.mutex;
01230 SET_CONTINUATION_HANDLER(e, &DNSEntry::postEvent);
01231 e->submit_thread->schedule_imm_signal(e);
01232 }
01233 return;
01234 Lretry:
01235 e->result_ent = ent;
01236 e->retries = 0;
01237 if (e->timeout)
01238 e->timeout->cancel();
01239 e->timeout = h->mutex->thread_holding->schedule_in(e, DNS_PERIOD);
01240 }
01241
01242 int
01243 DNSEntry::post(DNSHandler *h, HostEnt *ent)
01244 {
01245 if (timeout) {
01246 timeout->cancel(this);
01247 timeout = NULL;
01248 }
01249 result_ent = ent;
01250 if (h->mutex->thread_holding == submit_thread) {
01251 MUTEX_TRY_LOCK(lock, action.mutex, h->mutex->thread_holding);
01252 if (!lock) {
01253 Debug("dns", "failed lock for result %s", qname);
01254 return 1;
01255 }
01256 postEvent(0, 0);
01257 } else {
01258 mutex = action.mutex;
01259 SET_HANDLER(&DNSEntry::postEvent);
01260 submit_thread->schedule_imm_signal(this);
01261 }
01262 return 0;
01263 }
01264
01265 int
01266 DNSEntry::postEvent(int , Event * )
01267 {
01268 if (!action.cancelled) {
01269 Debug("dns", "called back continuation for %s", qname);
01270 action.continuation->handleEvent(DNS_EVENT_LOOKUP, result_ent);
01271 }
01272 result_ent = NULL;
01273 action.mutex = NULL;
01274 mutex = NULL;
01275 dnsEntryAllocator.free(this);
01276 return EVENT_DONE;
01277 }
01278
01279
01280 static bool
01281 dns_process(DNSHandler *handler, HostEnt *buf, int len)
01282 {
01283 ProxyMutex *mutex = handler->mutex;
01284 HEADER *h = (HEADER *) (buf->buf);
01285 DNSEntry *e = get_dns(handler, (uint16_t) ntohs(h->id));
01286 bool retry = false;
01287 bool server_ok = true;
01288 uint32_t temp_ttl = 0;
01289
01290
01291
01292
01293 if (!e || !e->written_flag) {
01294 Debug("dns", "unknown DNS id = %u", (uint16_t) ntohs(h->id));
01295 return false;
01296 }
01297
01298
01299
01300 e->written_flag = false;
01301 --(handler->in_flight);
01302 DNS_DECREMENT_DYN_STAT(dns_in_flight_stat);
01303
01304 DNS_SUM_DYN_STAT(dns_response_time_stat, ink_get_hrtime() - e->send_time);
01305
01306 if (h->rcode != NOERROR || !h->ancount) {
01307 Debug("dns", "received rcode = %d", h->rcode);
01308 switch (h->rcode) {
01309 default:
01310 Warning("Unknown DNS error %d for [%s]", h->rcode, e->qname);
01311 retry = true;
01312 server_ok = false;
01313 goto Lerror;
01314 case SERVFAIL:
01315 retry = true;
01316 case FORMERR:
01317 case REFUSED:
01318 case NOTIMP:
01319 Debug("dns", "DNS error %d for [%s]", h->rcode, e->qname);
01320 server_ok = false;
01321 goto Lerror;
01322 case NOERROR:
01323 case NXDOMAIN:
01324 case 6:
01325 case 7:
01326 case 8:
01327 case 9:
01328 case 10:
01329 Debug("dns", "DNS error %d for [%s]", h->rcode, e->qname);
01330 goto Lerror;
01331 }
01332 } else {
01333
01334
01335
01336
01337
01338 u_char tbuf[MAXDNAME + 1];
01339 buf->ent.h_name = NULL;
01340
01341 int ancount = ntohs(h->ancount);
01342 unsigned char *bp = buf->hostbuf;
01343 int buflen = sizeof(buf->hostbuf);
01344 u_char *cp = ((u_char *) h) + HFIXEDSZ;
01345 u_char *eom = (u_char *) h + len;
01346 int n;
01347 ink_assert(buf->srv_hosts.srv_host_count == 0 && buf->srv_hosts.srv_hosts_length == 0);
01348 buf->srv_hosts.srv_host_count = 0;
01349 buf->srv_hosts.srv_hosts_length = 0;
01350 unsigned& num_srv = buf->srv_hosts.srv_host_count;
01351 int rname_len = -1;
01352
01353
01354
01355
01356 if ((n = ink_dn_expand((u_char *) h, eom, cp, bp, buflen)) < 0)
01357 goto Lerror;
01358
01359
01360 if (dns_validate_qname) {
01361 int qlen = e->qname_len;
01362 int rlen = strlen((char *)bp);
01363
01364 rname_len = rlen;
01365 if ((qlen > 0) && ('.' == e->qname[qlen-1]))
01366 --qlen;
01367 if ((rlen > 0) && ('.' == bp[rlen-1]))
01368 --rlen;
01369
01370
01371
01372 if ((qlen != rlen) || (strncasecmp(e->qname, (const char*)bp, qlen) != 0)) {
01373
01374 Warning("received DNS response with query name of '%s', but response query name is '%s'", e->qname, bp);
01375 goto Lerror;
01376 } else {
01377 Debug("dns", "query name validated properly for %s", e->qname);
01378 }
01379 }
01380
01381 cp += n + QFIXEDSZ;
01382 if (is_addr_query(e->qtype)) {
01383 if (-1 == rname_len)
01384 n = strlen((char *)bp) + 1;
01385 else
01386 n = rname_len + 1;
01387 buf->ent.h_name = (char *) bp;
01388 bp += n;
01389 buflen -= n;
01390 }
01391
01392
01393
01394 u_char **ap = buf->host_aliases;
01395 buf->ent.h_aliases = (char **) buf->host_aliases;
01396 u_char **hap = (u_char **) buf->h_addr_ptrs;
01397 *hap = NULL;
01398 buf->ent.h_addr_list = (char **) buf->h_addr_ptrs;
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409 if (local_num_entries >= DEFAULT_NUM_TRY_SERVER) {
01410 if ((attempt_num_entries % 50) == 0) {
01411 try_servers = (try_servers + 1) % countof(try_server_names);
01412 ink_strlcpy(try_server_names[try_servers], e->qname, MAXDNAME);
01413 memset(&try_server_names[try_servers][strlen(e->qname)], 0, 1);
01414 attempt_num_entries = 0;
01415 }
01416 ++attempt_num_entries;
01417 } else {
01418
01419 try_servers = local_num_entries++;
01420 ink_strlcpy(try_server_names[try_servers], e->qname, MAXDNAME);
01421 memset(&try_server_names[try_servers][strlen(e->qname)], 0, 1);
01422 }
01423
01424
01425
01426
01427 unsigned char *here = (unsigned char *) buf->buf + HFIXEDSZ;
01428 if (e->qtype == T_SRV) {
01429 for (int ctr = ntohs(h->qdcount); ctr > 0; ctr--) {
01430 int strlen = dn_skipname(here, eom);
01431 here += strlen + QFIXEDSZ;
01432 }
01433 }
01434
01435
01436
01437 int answer = false, error = false;
01438
01439 while (ancount-- > 0 && cp < eom && !error) {
01440 n = ink_dn_expand((u_char *) h, eom, cp, bp, buflen);
01441 if (n < 0) {
01442 ++error;
01443 break;
01444 }
01445 cp += n;
01446 short int type;
01447 NS_GET16(type, cp);
01448 cp += NS_INT16SZ;
01449 NS_GET32(temp_ttl, cp);
01450 if ((temp_ttl < buf->ttl) || (buf->ttl == 0))
01451 buf->ttl = temp_ttl;
01452 NS_GET16(n, cp);
01453
01454
01455
01456
01457 if (is_addr_query(e->qtype) && type == T_CNAME) {
01458 if (ap >= &buf->host_aliases[DNS_MAX_ALIASES - 1])
01459 continue;
01460 n = ink_dn_expand((u_char *) h, eom, cp, tbuf, sizeof(tbuf));
01461 if (n < 0) {
01462 ++error;
01463 break;
01464 }
01465 cp += n;
01466 *ap++ = (unsigned char *) bp;
01467 n = strlen((char *) bp) + 1;
01468 bp += n;
01469 buflen -= n;
01470 n = strlen((char *) tbuf) + 1;
01471 if (n > buflen) {
01472 ++error;
01473 break;
01474 }
01475 ink_strlcpy((char *) bp, (char *) tbuf, buflen);
01476 bp += n;
01477 buflen -= n;
01478 Debug("dns", "received cname = %s", tbuf);
01479 continue;
01480 }
01481 if (e->qtype != type) {
01482 ++error;
01483 break;
01484 }
01485
01486
01487
01488 if (type == T_PTR) {
01489 n = ink_dn_expand((u_char *) h, eom, cp, bp, buflen);
01490 if (n < 0) {
01491 ++error;
01492 break;
01493 }
01494 cp += n;
01495 if (!answer) {
01496 buf->ent.h_name = (char *) bp;
01497 Debug("dns", "received PTR name = %s", bp);
01498 n = strlen((char *) bp) + 1;
01499 bp += n;
01500 buflen -= n;
01501 } else if (ap < &buf->host_aliases[DNS_MAX_ALIASES - 1]) {
01502 *ap++ = bp;
01503 Debug("dns", "received PTR alias = %s", bp);
01504 n = strlen((char *) bp) + 1;
01505 bp += n;
01506 buflen -= n;
01507 }
01508 } else if (type == T_SRV) {
01509 if (num_srv >= HOST_DB_MAX_ROUND_ROBIN_INFO)
01510 break;
01511 cp = here;
01512 int strlen = dn_skipname(cp, eom);
01513 cp += strlen;
01514 const unsigned char *srv_off = cp;
01515 cp += SRV_FIXEDSZ;
01516 cp += dn_skipname(cp, eom);
01517 here = cp;
01518 SRV *srv = &buf->srv_hosts.hosts[num_srv];
01519 int r = ink_ns_name_ntop(srv_off + SRV_SERVER, srv->host, MAXDNAME);
01520 if (r <= 0) {
01521
01522 ++error;
01523 goto Lerror;
01524 }
01525 Debug("dns_srv", "Discovered SRV record [from NS lookup] with cost:%d weight:%d port:%d with host:%s",
01526 ink_get16(srv_off + SRV_COST),
01527 ink_get16(srv_off + SRV_WEIGHT), ink_get16(srv_off + SRV_PORT), srv->host);
01528
01529 srv->port = ink_get16(srv_off + SRV_PORT);
01530 srv->priority = ink_get16(srv_off + SRV_COST);
01531 srv->weight = ink_get16(srv_off + SRV_WEIGHT);
01532 srv->host_len = r;
01533 srv->host[r-1] = '\0';
01534 srv->key = makeHostHash(srv->host);
01535
01536 if (srv->host[0] != '\0')
01537 buf->srv_hosts.srv_hosts_length += r;
01538 else
01539 continue;
01540 ++num_srv;
01541 } else if (is_addr_query(type)) {
01542 if (answer) {
01543 if (n != buf->ent.h_length) {
01544 cp += n;
01545 continue;
01546 }
01547 } else {
01548 int nn;
01549 buf->ent.h_length = n;
01550 buf->ent.h_addrtype = T_A == type ? AF_INET : AF_INET6;
01551 buf->ent.h_name = (char *) bp;
01552 nn = strlen((char *) bp) + 1;
01553 Debug("dns", "received %s name = %s", QtypeName(type), bp);
01554 bp += nn;
01555 buflen -= nn;
01556 }
01557
01558 if (!(((uintptr_t) cp) % sizeof(unsigned int))) {
01559 *hap++ = cp;
01560 cp += n;
01561 } else {
01562 ip_text_buffer ip_string;
01563 bp = (unsigned char *) align_pointer_forward(bp, sizeof(int));
01564 if (bp + n >= buf->hostbuf + DNS_HOSTBUF_SIZE) {
01565 ++error;
01566 break;
01567 }
01568 memcpy((*hap++ = bp), cp, n);
01569 Debug("dns", "received %s = %s", QtypeName(type),
01570 inet_ntop(T_AAAA == type ? AF_INET6 : AF_INET, bp, ip_string, sizeof(ip_string))
01571 );
01572 bp += n;
01573 cp += n;
01574 }
01575 } else
01576 goto Lerror;
01577 ++answer;
01578 }
01579 if (answer) {
01580 *ap = NULL;
01581 *hap = NULL;
01582
01583
01584
01585
01586 if (!buf->ent.h_name) {
01587 Debug("dns", "inserting name = %s", e->qname);
01588 ink_strlcpy((char *) bp, e->qname, sizeof(buf->hostbuf) - (bp - buf->hostbuf));
01589 buf->ent.h_name = (char *) bp;
01590 }
01591 dns_result(handler, e, buf, retry);
01592 return server_ok;
01593 }
01594 }
01595 Lerror:;
01596 DNS_INCREMENT_DYN_STAT(dns_lookup_fail_stat);
01597 dns_result(handler, e, NULL, retry);
01598 return server_ok;
01599 }
01600
01601
01602 RecRawStatBlock *dns_rsb;
01603
01604 void
01605 ink_dns_init(ModuleVersion v)
01606 {
01607 static int init_called = 0;
01608
01609 Debug("dns", "ink_dns_init: called with init_called = %d", init_called);
01610
01611 ink_release_assert(!checkModuleVersion(v, HOSTDB_MODULE_VERSION));
01612 if (init_called)
01613 return;
01614
01615 init_called = 1;
01616
01617
01618 dns_rsb = RecAllocateRawStatBlock((int) DNS_Stat_Count);
01619
01620
01621
01622
01623 RecRegisterRawStat(dns_rsb, RECT_PROCESS,
01624 "proxy.process.dns.total_dns_lookups",
01625 RECD_INT, RECP_PERSISTENT, (int) dns_total_lookups_stat, RecRawStatSyncSum);
01626
01627 RecRegisterRawStat(dns_rsb, RECT_PROCESS,
01628 "proxy.process.dns.lookup_avg_time",
01629 RECD_INT, RECP_PERSISTENT, (int) dns_response_time_stat, RecRawStatSyncHrTimeAvg);
01630
01631 RecRegisterRawStat(dns_rsb, RECT_PROCESS,
01632 "proxy.process.dns.success_avg_time",
01633 RECD_INT, RECP_NON_PERSISTENT, (int) dns_success_time_stat, RecRawStatSyncHrTimeAvg);
01634
01635 RecRegisterRawStat(dns_rsb, RECT_PROCESS,
01636 "proxy.process.dns.lookup_successes",
01637 RECD_INT, RECP_PERSISTENT, (int) dns_lookup_success_stat, RecRawStatSyncSum);
01638
01639 RecRegisterRawStat(dns_rsb, RECT_PROCESS,
01640 "proxy.process.dns.fail_avg_time",
01641 RECD_INT, RECP_PERSISTENT, (int) dns_fail_time_stat, RecRawStatSyncHrTimeAvg);
01642
01643 RecRegisterRawStat(dns_rsb, RECT_PROCESS,
01644 "proxy.process.dns.lookup_failures",
01645 RECD_INT, RECP_PERSISTENT, (int) dns_lookup_fail_stat, RecRawStatSyncSum);
01646
01647 RecRegisterRawStat(dns_rsb, RECT_PROCESS,
01648 "proxy.process.dns.retries", RECD_INT, RECP_PERSISTENT, (int) dns_retries_stat, RecRawStatSyncSum);
01649
01650 RecRegisterRawStat(dns_rsb, RECT_PROCESS,
01651 "proxy.process.dns.max_retries_exceeded",
01652 RECD_INT, RECP_PERSISTENT, (int) dns_max_retries_exceeded_stat, RecRawStatSyncSum);
01653
01654 RecRegisterRawStat(dns_rsb, RECT_PROCESS,
01655 "proxy.process.dns.in_flight",
01656 RECD_INT, RECP_NON_PERSISTENT, (int) dns_in_flight_stat, RecRawStatSyncSum);
01657
01658 }
01659
01660
01661 #ifdef TS_HAS_TESTS
01662 struct DNSRegressionContinuation;
01663 typedef int (DNSRegressionContinuation::*DNSRegContHandler) (int, void *);
01664
01665 struct DNSRegressionContinuation: public Continuation
01666 {
01667 int hosts;
01668 const char **hostnames;
01669 int type;
01670 int *status;
01671 int found;
01672 int tofind;
01673 int i;
01674 RegressionTest *test;
01675
01676 int mainEvent(int event, HostEnt *he)
01677 {
01678 (void) event;
01679 if (event == DNS_EVENT_LOOKUP) {
01680 if (he) {
01681 struct in_addr in;
01682 ++found;
01683 in.s_addr = *(unsigned int *) he->ent.h_addr_list[0];
01684 rprintf(test, "host %s [%s] = %s\n", hostnames[i - 1], he->ent.h_name, inet_ntoa(in));
01685 } else {
01686 rprintf(test, "host %s not found\n", hostnames[i - 1]);
01687 }
01688 }
01689 if (i < hosts) {
01690 dnsProcessor.gethostbyname(this, hostnames[i], DNSProcessor::Options().setHostResStyle(HOST_RES_IPV4_ONLY));
01691 ++i;
01692 return EVENT_CONT;
01693 } else {
01694 if (found == tofind)
01695 *status = REGRESSION_TEST_PASSED;
01696 else
01697 *status = REGRESSION_TEST_FAILED;
01698 return EVENT_DONE;
01699 }
01700 }
01701
01702 DNSRegressionContinuation(int ahosts, int atofind, const char **ahostnames, RegressionTest *t, int atype, int *astatus)
01703 : Continuation(new_ProxyMutex()), hosts(ahosts), hostnames(ahostnames), type(atype),
01704 status(astatus), found(0), tofind(atofind), i(0), test(t) {
01705 SET_HANDLER((DNSRegContHandler) & DNSRegressionContinuation::mainEvent);
01706 }
01707 };
01708
01709 static const char *dns_test_hosts[] = {
01710 "www.apple.com",
01711 "www.ibm.com",
01712 "www.microsoft.com",
01713 "www.coke.com"
01714 };
01715
01716 REGRESSION_TEST(DNS) (RegressionTest *t, int atype, int *pstatus) {
01717 eventProcessor.schedule_in(new DNSRegressionContinuation(4, 4, dns_test_hosts, t, atype, pstatus),
01718 HRTIME_SECONDS(1));
01719 }
01720
01721 #endif