void resolv_start(const char *hostname, uint16_t port, void (*client_cb)(struct sockaddr *, void *), void (*free_cb)(void *), void *data) { /* * Wrap c-ares's call back in our own */ struct resolv_query *query = ss_malloc(sizeof(struct resolv_query)); memset(query, 0, sizeof(struct resolv_query)); query->port = port; query->client_cb = client_cb; query->response_count = 0; query->responses = NULL; query->data = data; query->free_cb = free_cb; query->requests[0] = AF_INET; query->requests[1] = AF_INET6; ares_gethostbyname(default_ctx.channel, hostname, AF_INET, dns_query_v4_cb, query); ares_gethostbyname(default_ctx.channel, hostname, AF_INET6, dns_query_v6_cb, query); reset_timer(); }
/* * Curl_getaddrinfo() - when using ares * * Returns name information about the given hostname and port number. If * successful, the 'hostent' is returned and the forth argument will point to * memory we need to free after use. That memory *MUST* be freed with * Curl_freeaddrinfo(), nothing else. */ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, char *hostname, int port, int *waitp) { char *bufp; struct SessionHandle *data = conn->data; in_addr_t in = inet_addr(hostname); *waitp = FALSE; if (in != CURL_INADDR_NONE) { /* This is a dotted IP address 123.123.123.123-style */ return Curl_ip2addr(in, hostname, port); } bufp = strdup(hostname); if(bufp) { Curl_safefree(conn->async.hostname); conn->async.hostname = bufp; conn->async.port = port; conn->async.done = FALSE; /* not done */ conn->async.status = 0; /* clear */ conn->async.dns = NULL; /* clear */ /* areschannel is already setup in the Curl_open() function */ ares_gethostbyname(data->state.areschannel, hostname, PF_INET, (ares_host_callback)Curl_addrinfo4_callback, conn); *waitp = TRUE; /* please wait for the response */ } return NULL; /* no struct yet */ }
static PyObject * Channel_func_gethostbyname(Channel *self, PyObject *args) { char *name; int family; PyObject *callback, *ret; CHECK_CHANNEL(self); if (!PyArg_ParseTuple(args, "etiO:gethostbyname", "idna", &name, &family, &callback)) { return NULL; } if (!PyCallable_Check(callback)) { PyErr_SetString(PyExc_TypeError, "a callable is required"); ret = NULL; goto finally; } Py_INCREF(callback); ares_gethostbyname(self->channel, name, family, &host_cb, (void *)callback); ret = Py_None; finally: PyMem_Free(name); Py_XINCREF(ret); return ret; }
static PyObject * DNSResolver_func_gethostbyname(DNSResolver *self, PyObject *args, PyObject *kwargs) { char *name; ares_cb_data_t *cb_data; PyObject *callback; if (!PyArg_ParseTuple(args, "sO:gethostbyname", &name, &callback)) { return NULL; } if (!PyCallable_Check(callback)) { PyErr_SetString(PyExc_TypeError, "a callable is required"); return NULL; } cb_data = (ares_cb_data_t*) PyMem_Malloc(sizeof *cb_data); if (!cb_data) { return PyErr_NoMemory(); } Py_INCREF(callback); cb_data->resolver = self; cb_data->cb = callback; ares_gethostbyname(self->channel, name, AF_INET, &host_cb, (void *)cb_data); Py_RETURN_NONE; }
ape_dns_state *ape_gethostbyname(const char *host, ape_gethostbyname_callback callback, void *arg, ape_global *ape) { struct in_addr addr4; if (inet_pton(AF_INET, host, &addr4) == 1) { callback(host, arg, ARES_SUCCESS); return NULL; } else { struct _ape_dns_cb_argv *cb = malloc(sizeof(*cb)); cb->ape = ape; cb->callback = callback; cb->origin = host; cb->arg = arg; cb->invalidate = 0; cb->done = 0; ares_gethostbyname(ape->dns.channel, host, AF_INET, ares_gethostbyname_cb, cb); if (cb->done) { return NULL; } return cb; } }
/* * Return name information about the given hostname and port number. If * successful, the 'hostent' is returned and the forth argument will point to * memory we need to free after use. That meory *MUST* be freed with * Curl_freeaddrinfo(), nothing else. */ static Curl_addrinfo *my_getaddrinfo(struct connectdata *conn, char *hostname, int port, int *waitp) { char *bufp; struct SessionHandle *data = conn->data; *waitp = FALSE; bufp = strdup(hostname); if(bufp) { Curl_safefree(conn->async.hostname); conn->async.hostname = bufp; conn->async.port = port; conn->async.done = FALSE; /* not done */ conn->async.status = 0; /* clear */ conn->async.dns = NULL; /* clear */ /* areschannel is already setup in the Curl_open() function */ ares_gethostbyname(data->state.areschannel, hostname, PF_INET, host_callback, conn); *waitp = TRUE; /* please wait for the response */ } return NULL; /* no struct yet */ }
void Resolver::gethostbyname(Callback cb, const char* name, int family/*=AF_INET*/, int timeout_ms/*=1000*/) { assert(channel_ != nullptr); cb_ = std::move(cb); //# note that for file lookups still AF_INET can be returned for AF_INET6 request ares_gethostbyname(channel_, name, family, Resolver::ares_host_callback, this); timer_ = io_loop_->addTimeout(timeout_ms, std::bind(&Resolver::on_timer, this, std::placeholders::_1, std::placeholders::_2)); }
EAPI int ecore_con_info_get(Ecore_Con_Server *svr, Ecore_Con_Info_Cb done_cb, void *data, struct addrinfo *hints) { Ecore_Con_CAres *cares; int ai_family = AF_INET6; cares = calloc(1, sizeof(Ecore_Con_CAres)); if (!cares) return 0; cares->svr = svr; cares->done_cb = done_cb; cares->data = data; if (hints) { ai_family = hints->ai_family; memcpy(&cares->hints, hints, sizeof(struct addrinfo)); } if (inet_pton(AF_INET, svr->name, &cares->addr.v4) == 1) { cares->byaddr = EINA_TRUE; cares->isv6 = EINA_FALSE; ares_gethostbyaddr(info_channel, &cares->addr.v4, sizeof(cares->addr.v4), AF_INET, (ares_host_callback)_ecore_con_info_ares_host_cb, cares); } else if (inet_pton(AF_INET6, svr->name, &cares->addr.v6) == 1) { cares->byaddr = EINA_TRUE; cares->isv6 = EINA_TRUE; ares_gethostbyaddr(info_channel, &cares->addr.v6, sizeof(cares->addr.v6), AF_INET6, (ares_host_callback)_ecore_con_info_ares_host_cb, cares); } else { cares->byaddr = EINA_FALSE; ares_gethostbyname(info_channel, svr->name, ai_family, (ares_host_callback)_ecore_con_info_ares_host_cb, cares); } svr->infos = eina_list_append(svr->infos, cares); return 1; }
void ph_dns_channel_gethostbyname( ph_dns_channel_t *chan, const char *name, int family, ares_host_callback func, void *arg) { chan = fixup_chan(chan); pthread_mutex_lock(&chan->chanlock); ares_gethostbyname(chan->chan, name, family, func, arg); pthread_mutex_unlock(&chan->chanlock); }
void dns_lookup(myconn_t *rec) { /* Push a normal DNS lookup into the DNS queue */ time_t updtime = 0; char *res = NULL; dbgprintf("dns_lookup(): Lookup %s, family %d\n", rec->netparams.lookupstring, rec->netparams.af_index-1); if (xymon_sqldb_dns_lookup_search(dns_lookup_sequence[rec->netparams.af_index], rec->netparams.lookupstring, &updtime, &res) != 0) { rec->netparams.lookupstatus = LOOKUP_FAILED; return; } if (!rec->netparams.lookupstring || (strlen(rec->netparams.lookupstring) == 0)) { errprintf("Invalid DNS lookup - string is %s\n", (rec->netparams.lookupstring ? "empty" : "null")); rec->netparams.lookupstatus = LOOKUP_FAILED; return; } if (!res) { /* No cache record, create one */ xymon_sqldb_dns_lookup_create(dns_lookup_sequence[rec->netparams.af_index], rec->netparams.lookupstring); } else if (res && ((time(NULL) - updtime) < 3600)) { /* We have a valid cache-record */ if ((strcmp(res, "-") != 0)) { /* Successfully resolved from cache */ dns_return_lookupdata(rec, res); } else { /* Continue with next address family */ rec->netparams.af_index++; rec->netparams.lookupstatus = LOOKUP_NEEDED; } } xymon_sqldb_dns_lookup_finish(); /* Cache data missing or invalid, do the DNS lookup */ if (rec->netparams.af_index == 0) getntimer(&rec->netparams.lookupstart); rec->netparams.lookupstatus = LOOKUP_ACTIVE; /* * Must increment af_index before calling ares_gethostbyname(), since the callback may be triggered * immediately (e.g. if the hostname is listed in /etc/hosts) */ rec->netparams.af_index++; /* Use ares_search() here, we want to use the whole shebang of name lookup options */ ares_gethostbyname(dns_lookupchannel, rec->netparams.lookupstring, dns_lookup_sequence[rec->netparams.af_index-1], dns_lookup_callback, rec); }
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; }
void start_resolve() { if( ares ) { ares_destroy(ares); ares = 0; } state = kResolving; std::string actual_url = redirect_url.size() ? redirect_url:url; std::string host = extract_host(actual_url); std::string res = dns_cache->get_ent(host); if( !res.size() ) { ares_init(&ares); ares_gethostbyname(ares,host.c_str(),AF_INET,Request::GotResolveStatic,this); } else { char buf[1024]; sprintf(buf,"%d.%d.%d.%d",res[0],res[1],res[2],res[3]); direct_ip = buf; state = kStartDownload; } }
// 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]; }
void p_dns_gethostbyname(char *hostname, int af, dns_host_callback callback, void *arg) { pcontext; ares_gethostbyname(resolver, hostname, af, (ares_host_callback)callback, arg); }
/* * Curl_getaddrinfo() - when using ares * * Returns name information about the given hostname and port number. If * successful, the 'hostent' is returned and the forth argument will point to * memory we need to free after use. That memory *MUST* be freed with * Curl_freeaddrinfo(), nothing else. */ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, const char *hostname, int port, int *waitp) { char *bufp; struct SessionHandle *data = conn->data; struct in_addr in; int family = PF_INET; #ifdef ENABLE_IPV6 /* CURLRES_IPV6 */ struct in6_addr in6; #endif /* CURLRES_IPV6 */ *waitp = FALSE; /* First check if this is an IPv4 address string */ if(Curl_inet_pton(AF_INET, hostname, &in) > 0) { /* This is a dotted IP address 123.123.123.123-style */ return Curl_ip2addr(AF_INET, &in, hostname, port); } #ifdef ENABLE_IPV6 /* CURLRES_IPV6 */ /* Otherwise, check if this is an IPv6 address string */ if (Curl_inet_pton (AF_INET6, hostname, &in6) > 0) { /* This must be an IPv6 address literal. */ return Curl_ip2addr(AF_INET6, &in6, hostname, port); } switch(data->set.ip_version) { default: #if ARES_VERSION >= 0x010601 family = PF_UNSPEC; /* supported by c-ares since 1.6.1, so for older c-ares versions this just falls through and defaults to PF_INET */ break; #endif case CURL_IPRESOLVE_V4: family = PF_INET; break; case CURL_IPRESOLVE_V6: family = PF_INET6; break; } #endif /* CURLRES_IPV6 */ bufp = strdup(hostname); if(bufp) { Curl_safefree(conn->async.hostname); conn->async.hostname = bufp; conn->async.port = port; conn->async.done = FALSE; /* not done */ conn->async.status = 0; /* clear */ conn->async.dns = NULL; /* clear */ /* areschannel is already setup in the Curl_open() function */ ares_gethostbyname(data->state.areschannel, hostname, family, (ares_host_callback)Curl_addrinfo4_callback, conn); *waitp = TRUE; /* please wait for the response */ } return NULL; /* no struct yet */ }
void LLAres::getHostByName(const char *name, HostResponder *resp, int family) { ares_gethostbyname(chan_, name, family, host_callback, new LLPointer<LLAres::HostResponder>(resp)); }
int gethostbyname_with_ares(const char *name, int af, struct hostent *ret_h, char *buf, size_t &buflen, struct hostent **result, int *h_errnop) { int err = 0; if (!h_errnop) h_errnop = &err; cares_async_context ctx; ctx.called = false; ctx.errnop = h_errnop; ctx.ret = 0; ctx.result = result; ctx.buf = buf; ctx.buflen = &buflen; ares_channel c; ares_init(&c); ares_gethostbyname(c, name, af, [](void * arg, int status, int timeouts, struct hostent *hostent) { cares_async_context *ctx = (cares_async_context *)arg; ctx->called = true; if (status != ARES_SUCCESS) { *ctx->result = nullptr; switch (status) { case ARES_ENODATA: *ctx->errnop = NO_DATA; break; case ARES_EBADNAME: *ctx->errnop = NO_RECOVERY; break; case ARES_ENOTFOUND: default: *ctx->errnop = HOST_NOT_FOUND; break; } ctx->ret = -1; return ; } if (!hostent_dup(hostent, *ctx->result, ctx->buf, *ctx->buflen)) { *ctx->result = nullptr; *ctx->errnop = ENOEXEC; // 奇怪的错误码. ctx->ret = -1; return ; } *ctx->errnop = 0; ctx->ret = 0; }, &ctx); fd_set readers, writers; FD_ZERO(&readers); FD_ZERO(&writers); int nfds = ares_fds(c, &readers, &writers); if (nfds) { struct timeval tv, *tvp; tvp = ares_timeout(c, NULL, &tv); int count = select(nfds, &readers, &writers, NULL, tvp); if (count > 0) { ares_process(c, &readers, &writers); } } if (ctx.called) return ctx.ret; // No yet invoke callback. *result = nullptr; *h_errnop = HOST_NOT_FOUND; // TODO return -1; }
static void printer_hes_callback(void *arg, int status, int timeouts, unsigned char *abuf, int alen) { struct printer_poll_args *pargs = (struct printer_poll_args *) arg; struct serverstate *state = pargs->state; struct printer *printer = pargs->printer; char **vec = NULL, *p, *q; if (status == ARES_EDESTRUCTION) { syslog(LOG_DEBUG, "printer_hes_callback: printer %s hesiod query " "halted for channel destruction", printer->name); free(pargs); return; } if (status != ARES_SUCCESS) { syslog(LOG_ERR, "printer_hes_callback: could not resolve Hesiod pcap " "for printer %s: %s", printer->name, ares_strerror(status)); goto failure; } /* Parse the result buffer into text records. */ vec = hesiod_parse_result(state->hescontext, abuf, alen); if (!vec || !*vec) { syslog(LOG_ERR, "printer_hes_callback: could not parse Hesiod pcap " "result for printer %s: %m", printer->name); goto failure; } /* Look for the print server name. */ p = strchr(*vec, ':'); while (p) { if (strncmp(p + 1, "rm=", 3) == 0) break; p = strchr(p + 1, ':'); } if (!p) { syslog(LOG_ERR, "printer_hes_callback: can't find print server name in " "Hesiod pcap result for printer %s", printer->name); goto failure; } p += 4; q = p; while (*q && *q != ':') q++; *q = 0; syslog(LOG_DEBUG, "printer_hes_callback: printer %s starting query for %s", printer->name, p); ares_gethostbyname(state->channel, p, AF_INET, printer_host_callback, pargs); hesiod_free_list(state->hescontext, vec); return; failure: if (vec) hesiod_free_list(state->hescontext, vec); printer->timer = timer_set_rel(60, printer_poll, pargs); }
int main(int argc, char **argv) { struct ares_options options; int optmask = 0; ares_channel channel; int status, nfds, c, addr_family = AF_INET; fd_set read_fds, write_fds; struct timeval *tvp, tv; struct in_addr addr4; struct ares_in6_addr addr6; #ifdef USE_WINSOCK WORD wVersionRequested = MAKEWORD(USE_WINSOCK,USE_WINSOCK); WSADATA wsaData; WSAStartup(wVersionRequested, &wsaData); #endif memset(&options, 0, sizeof(options)); status = ares_library_init(ARES_LIB_INIT_ALL); if (status != ARES_SUCCESS) { fprintf(stderr, "ares_library_init: %s\n", ares_strerror(status)); return 1; } while ((c = ares_getopt(argc,argv,"dt:hs:")) != -1) { switch (c) { case 'd': #ifdef WATT32 dbug_init(); #endif break; case 's': optmask |= ARES_OPT_DOMAINS; options.ndomains++; options.domains = realloc(options.domains, options.ndomains * sizeof(char *)); options.domains[options.ndomains - 1] = strdup(optarg); break; case 't': if (!strcasecmp(optarg,"a")) addr_family = AF_INET; else if (!strcasecmp(optarg,"aaaa")) addr_family = AF_INET6; else if (!strcasecmp(optarg,"u")) addr_family = AF_UNSPEC; else usage(); break; case 'h': default: usage(); break; } } argc -= optind; argv += optind; if (argc < 1) usage(); status = ares_init_options(&channel, &options, optmask); if (status != ARES_SUCCESS) { fprintf(stderr, "ares_init: %s\n", ares_strerror(status)); return 1; } /* Initiate the queries, one per command-line argument. */ for ( ; *argv; argv++) { if (ares_inet_pton(AF_INET, *argv, &addr4) == 1) { ares_gethostbyaddr(channel, &addr4, sizeof(addr4), AF_INET, callback, *argv); } else if (ares_inet_pton(AF_INET6, *argv, &addr6) == 1) { ares_gethostbyaddr(channel, &addr6, sizeof(addr6), AF_INET6, callback, *argv); } else { ares_gethostbyname(channel, *argv, addr_family, callback, *argv); } } /* Wait for all queries to complete. */ for (;;) { int res; FD_ZERO(&read_fds); FD_ZERO(&write_fds); nfds = ares_fds(channel, &read_fds, &write_fds); if (nfds == 0) break; tvp = ares_timeout(channel, NULL, &tv); res = select(nfds, &read_fds, &write_fds, NULL, tvp); if (-1 == res) break; ares_process(channel, &read_fds, &write_fds); } ares_destroy(channel); ares_library_cleanup(); #ifdef USE_WINSOCK WSACleanup(); #endif return 0; }
EAPI int ecore_con_info_get(Ecore_Con_Server *obj, Ecore_Con_Info_Cb done_cb, void *data, struct addrinfo *hints) { Ecore_Con_Server_Data *svr = eo_data_scope_get(obj, ECORE_CON_SERVER_CLASS); Ecore_Con_CAres *cares; #ifdef HAVE_IPV6 int ai_family = AF_INET6; #else int ai_family = AF_INET; #endif cares = calloc(1, sizeof(Ecore_Con_CAres)); if (!cares) return 0; cares->svr = obj; cares->done_cb = done_cb; cares->data = data; if (hints) { ai_family = hints->ai_family; memcpy(&cares->hints, hints, sizeof(struct addrinfo)); } if (inet_pton(AF_INET, svr->ecs ? svr->ecs->ip : svr->name, &cares->addr.v4) == 1) { cares->byaddr = EINA_TRUE; cares->isv6 = EINA_FALSE; ares_gethostbyaddr(info_channel, &cares->addr.v4, sizeof(cares->addr.v4), AF_INET, (ares_host_callback)_ecore_con_info_ares_host_cb, cares); } #ifdef HAVE_IPV6 else if (inet_pton(AF_INET6, svr->ecs ? svr->ecs->ip : svr->name, &cares->addr.v6) == 1) { cares->byaddr = EINA_TRUE; cares->isv6 = EINA_TRUE; ares_gethostbyaddr(info_channel, &cares->addr.v6, sizeof(cares->addr.v6), AF_INET6, (ares_host_callback)_ecore_con_info_ares_host_cb, cares); } #endif else { cares->byaddr = EINA_FALSE; ares_gethostbyname(info_channel, svr->ecs ? svr->ecs->ip : svr->name, ai_family, (ares_host_callback)_ecore_con_info_ares_host_cb, cares); } svr->infos = eina_list_append(svr->infos, cares); return 1; }
/* * Curl_resolver_getaddrinfo() - when using ares * * Returns name information about the given hostname and port number. If * successful, the 'hostent' is returned and the forth argument will point to * memory we need to free after use. That memory *MUST* be freed with * Curl_freeaddrinfo(), nothing else. */ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, const char *hostname, int port, int *waitp) { char *bufp; struct SessionHandle *data = conn->data; struct in_addr in; int family = PF_INET; #ifdef ENABLE_IPV6 /* CURLRES_IPV6 */ struct in6_addr in6; #endif /* CURLRES_IPV6 */ *waitp = 0; /* default to synchronous response */ /* First check if this is an IPv4 address string */ if(Curl_inet_pton(AF_INET, hostname, &in) > 0) { /* This is a dotted IP address 123.123.123.123-style */ return Curl_ip2addr(AF_INET, &in, hostname, port); } #ifdef ENABLE_IPV6 /* CURLRES_IPV6 */ /* Otherwise, check if this is an IPv6 address string */ if(Curl_inet_pton (AF_INET6, hostname, &in6) > 0) /* This must be an IPv6 address literal. */ return Curl_ip2addr(AF_INET6, &in6, hostname, port); switch(conn->ip_version) { default: #if ARES_VERSION >= 0x010601 family = PF_UNSPEC; /* supported by c-ares since 1.6.1, so for older c-ares versions this just falls through and defaults to PF_INET */ break; #endif case CURL_IPRESOLVE_V4: family = PF_INET; break; case CURL_IPRESOLVE_V6: family = PF_INET6; break; } #endif /* CURLRES_IPV6 */ bufp = strdup(hostname); if(bufp) { struct ResolverResults *res = NULL; Curl_safefree(conn->async.hostname); conn->async.hostname = bufp; conn->async.port = port; conn->async.done = FALSE; /* not done */ conn->async.status = 0; /* clear */ conn->async.dns = NULL; /* clear */ res = calloc(sizeof(struct ResolverResults),1); if(!res) { Curl_safefree(conn->async.hostname); conn->async.hostname = NULL; return NULL; } conn->async.os_specific = res; /* initial status - failed */ res->last_status = ARES_ENOTFOUND; #ifdef ENABLE_IPV6 /* CURLRES_IPV6 */ if(family == PF_UNSPEC) { if(Curl_ipv6works()) { res->num_pending = 2; /* areschannel is already setup in the Curl_open() function */ ares_gethostbyname((ares_channel)data->state.resolver, hostname, PF_INET, query_completed_cb, conn); ares_gethostbyname((ares_channel)data->state.resolver, hostname, PF_INET6, query_completed_cb, conn); } else { res->num_pending = 1; /* areschannel is already setup in the Curl_open() function */ ares_gethostbyname((ares_channel)data->state.resolver, hostname, PF_INET, query_completed_cb, conn); } } else #endif /* CURLRES_IPV6 */ { res->num_pending = 1; /* areschannel is already setup in the Curl_open() function */ ares_gethostbyname((ares_channel)data->state.resolver, hostname, family, query_completed_cb, conn); } *waitp = 1; /* expect asynchronous response */ } return NULL; /* no struct yet */ }
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; }