vector<TSrvRecord> GetRecords(const string& host) const { ares_channel channel; int status; status = ares_init(&channel); if(status != ARES_SUCCESS) { throw UException(std::string("Failed to init ares channel: ") + ares_strerror(status)); } TCallbackInfo info; ares_query(channel, host.c_str(), ns_c_in, ns_t_srv, callback, &info); wait_ares(channel); ares_destroy(channel); if (info.Status != ARES_SUCCESS) { throw UException(std::string("Failed to make ares request: ") + ares_strerror(info.Status)); } struct ares_srv_reply* reply; status = ares_parse_srv_reply((const unsigned char*)info.Data.data(), info.Data.length(), &reply); if (info.Status != ARES_SUCCESS) { throw UException(std::string("Failed to parse response: ") + ares_strerror(status)); } vector<TSrvRecord> records; struct ares_srv_reply* next = reply; while (next != NULL) { TSrvRecord record; record.Host = next->host; record.Port = next->port; record.Priority = next->priority; record.Weight = next->weight; records.push_back(record); next = next->next; } ares_free_data(reply); return records; }
struct hostent *nssrs_resolver_by_servers(char *name, char *nameserver) { ares_channel channel = NULL; int status, optmask = 0; struct ares_options options; struct hostent *results; status = ares_library_init(ARES_LIB_INIT_ALL); if (status != ARES_SUCCESS) { debug("ares_library_init: %s\n", ares_strerror(status)); return NULL; } optmask = ARES_OPT_SERVERS | ARES_OPT_UDP_PORT; options.servers = NULL; options.nservers = 0; options.flags = ARES_FLAG_NOCHECKRESP; status = ares_init_options(&channel, &options, optmask); if(status != ARES_SUCCESS) { debug("ares_init_options: %s\n", ares_strerror(status)); return NULL; } status = ares_set_servers_csv(channel, nameserver); if (status != ARES_SUCCESS) { debug("ares_set_servers_csv: %s\n", ares_strerror(status)); ares_destroy(channel); ares_library_cleanup(); return NULL; } // Wait resolver results = malloc(sizeof(struct hostent)); ares_gethostbyname(channel, name, AF_INET, &callback, results); wait_ares(channel); ares_destroy(channel); ares_library_cleanup(); if (results->h_name != NULL) { return results; } free(results); return NULL; }
// Bad synchronous gethostbyname demo uint32_t tm__sync_gethostbyname (const char *domain) { ares_channel channel; int status; struct ares_options options; int optmask = 0; ipaddr[0] = ipaddr[1] = ipaddr[2] = ipaddr[3] = 0; struct in_addr ns1; inet_aton("8.8.8.8",&ns1); status = ares_library_init(ARES_LIB_INIT_ALL); if (status != ARES_SUCCESS){ printf("ares_library_init: %s\n", ares_strerror(status)); return 1; } options.servers = &ns1; options.nservers = 1; optmask |= ARES_OPT_SERVERS; options.sock_state_cb = state_cb; // options.sock_state_cb_data; optmask |= ARES_OPT_SOCK_STATE_CB; status = ares_init_options(&channel, &options, optmask); if(status != ARES_SUCCESS) { printf("ares_init_options: %s\n", ares_strerror(status)); return 1; } ares_gethostbyname(channel, domain, AF_INET, callback, NULL); wait_ares(channel); ares_destroy(channel); ares_library_cleanup(); // printf("fin\n"); // printf("result => %d.%d.%d.%d\n", ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]); return (ipaddr[0] << 24) | (ipaddr[1] << 16) | (ipaddr[2] << 8) | ipaddr[3]; }
struct address_list * lookup_host (const char *host, int flags) { struct address_list *al; bool silent = !!(flags & LH_SILENT); bool use_cache; bool numeric_address = false; double timeout = opt.dns_timeout; #ifndef ENABLE_IPV6 /* If we're not using getaddrinfo, first check if HOST specifies a numeric IPv4 address. Some implementations of gethostbyname (e.g. the Ultrix one and possibly Winsock) don't accept dotted-decimal IPv4 addresses. */ { uint32_t addr_ipv4 = (uint32_t)inet_addr (host); if (addr_ipv4 != (uint32_t) -1) { /* No need to cache host->addr relation, just return the address. */ char *vec[2]; vec[0] = (char *)&addr_ipv4; vec[1] = NULL; return address_list_from_ipv4_addresses (vec); } } #else /* ENABLE_IPV6 */ /* If we're using getaddrinfo, at least check whether the address is already numeric, in which case there is no need to print the "Resolving..." output. (This comes at no additional cost since the is_valid_ipv*_address are already required for url_parse.) */ { const char *end = host + strlen (host); if (is_valid_ipv4_address (host, end) || is_valid_ipv6_address (host, end)) numeric_address = true; } #endif /* Cache is normally on, but can be turned off with --no-dns-cache. Don't cache passive lookups under IPv6. */ use_cache = opt.dns_cache; #ifdef ENABLE_IPV6 if ((flags & LH_BIND) || numeric_address) use_cache = false; #endif /* Try to find the host in the cache so we don't need to talk to the resolver. If LH_REFRESH is requested, remove HOST from the cache instead. */ if (use_cache) { if (!(flags & LH_REFRESH)) { al = cache_query (host); if (al) return al; } else cache_remove (host); } /* No luck with the cache; resolve HOST. */ if (!silent && !numeric_address) { char *str = NULL, *name; if (opt.enable_iri && (name = idn_decode ((char *) host)) != NULL) { int len = strlen (host) + strlen (name) + 4; str = xmalloc (len); snprintf (str, len, "%s (%s)", name, host); str[len-1] = '\0'; idn_free (name); } logprintf (LOG_VERBOSE, _("Resolving %s... "), quotearg_style (escape_quoting_style, str ? str : host)); xfree (str); } #ifdef ENABLE_IPV6 #ifdef HAVE_LIBCARES if (ares) { struct address_list *al4; struct address_list *al6; if (opt.ipv4_only || !opt.ipv6_only) ares_gethostbyname (ares, host, AF_INET, callback, &al4); if (opt.ipv6_only || !opt.ipv4_only) ares_gethostbyname (ares, host, AF_INET6, callback, &al6); wait_ares (ares); if (al4 && al6) al = merge_address_lists (al4, al6); else if (al4) al = al4; else al = al6; } else #endif { int err; struct addrinfo hints, *res; xzero (hints); hints.ai_socktype = SOCK_STREAM; if (opt.ipv4_only) hints.ai_family = AF_INET; else if (opt.ipv6_only) hints.ai_family = AF_INET6; else /* We tried using AI_ADDRCONFIG, but removed it because: it misinterprets IPv6 loopbacks, it is broken on AIX 5.1, and it's unneeded since we sort the addresses anyway. */ hints.ai_family = AF_UNSPEC; if (flags & LH_BIND) hints.ai_flags |= AI_PASSIVE; #ifdef AI_NUMERICHOST if (numeric_address) { /* Where available, the AI_NUMERICHOST hint can prevent costly access to DNS servers. */ hints.ai_flags |= AI_NUMERICHOST; timeout = 0; /* no timeout needed when "resolving" numeric hosts -- avoid setting up signal handlers and such. */ } #endif err = getaddrinfo_with_timeout (host, NULL, &hints, &res, timeout); if (err != 0 || res == NULL) { if (!silent) logprintf (LOG_VERBOSE, _ ("failed: %s.\n"), err != EAI_SYSTEM ? gai_strerror (err) : strerror (errno)); return NULL; } al = address_list_from_addrinfo (res); freeaddrinfo (res); } if (!al) { logprintf (LOG_VERBOSE, _ ("failed: No IPv4/IPv6 addresses for host.\n")); return NULL; } /* Reorder addresses so that IPv4 ones (or IPv6 ones, as per --prefer-family) come first. Sorting is stable so the order of the addresses with the same family is undisturbed. */ if (al->count > 1 && opt.prefer_family != prefer_none) stable_sort (al->addresses, al->count, sizeof (ip_address), opt.prefer_family == prefer_ipv4 ? cmp_prefer_ipv4 : cmp_prefer_ipv6); #else /* not ENABLE_IPV6 */ #ifdef HAVE_LIBCARES if (ares) { ares_gethostbyname (ares, host, AF_INET, callback, &al); wait_ares (ares); } else #endif { struct hostent *hptr = gethostbyname_with_timeout (host, timeout); if (!hptr) { if (!silent) { if (errno != ETIMEDOUT) logprintf (LOG_VERBOSE, _ ("failed: %s.\n"), host_errstr (h_errno)); else logputs (LOG_VERBOSE, _ ("failed: timed out.\n")); } return NULL; } /* Do older systems have h_addr_list? */ al = address_list_from_ipv4_addresses (hptr->h_addr_list); } #endif /* not ENABLE_IPV6 */ /* Print the addresses determined by DNS lookup, but no more than three if show_all_dns_entries is not specified. */ if (!silent && !numeric_address) { int i; int printmax = al->count; if (!opt.show_all_dns_entries && printmax > 3) printmax = 3; for (i = 0; i < printmax; i++) { logputs (LOG_VERBOSE, print_address (al->addresses + i)); if (i < printmax - 1) logputs (LOG_VERBOSE, ", "); } if (printmax != al->count) logputs (LOG_VERBOSE, ", ..."); logputs (LOG_VERBOSE, "\n"); } /* Cache the lookup information. */ if (use_cache) cache_store (host, al); return al; }