static void next_lookup(struct addr_query *aquery) { const char *p; char name[128]; int status; struct hostent *host; for (p = aquery->remaining_lookups; *p; p++) { switch (*p) { case 'b': ptr_rr_name(name, &aquery->addr); aquery->remaining_lookups = p + 1; ares_query(aquery->channel, name, C_IN, T_PTR, addr_callback, aquery); return; case 'f': status = file_lookup(&aquery->addr, &host); /* this status check below previously checked for !ARES_ENOTFOUND, but we should not assume that this single error code is the one that can occur, as that is in fact no longer the case */ if (status == ARES_SUCCESS) { end_aquery(aquery, status, host); return; } break; } } end_aquery(aquery, ARES_ENOTFOUND, NULL); }
static int query(const char *domain, int type, int flags, cell_db_entry *dbservers, int max_num, int *ret_num, int *lowest_ttl) { struct ko_dns_query q; q.domain = domain; q.flags = flags & (CELL_QUERY|HOST_QUERY); q.dbservers = dbservers; q.max_num = max_num; if (type & CELL_QUERY) q.dbnum = 0; else q.dbnum = max_num; if (lowest_ttl) q.lowest_ttl = *lowest_ttl; IOMGR_Cancel(ares_pid); ares_query(achannel, domain, C_IN, type, callback, &q); while((q.flags & QUERY_DONE) == 0) LWP_WaitProcess(&q); if (lowest_ttl) *lowest_ttl = q.lowest_ttl; if (ret_num) *ret_num = q.dbnum; return q.error; }
static PyObject * DNSResolver_func_query_a(DNSResolver *self, PyObject *args) { char *name; ares_cb_data_t *cb_data; PyObject *callback; if (!PyArg_ParseTuple(args, "sO:query_a", &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_query(self->channel, name, C_IN, T_A, &query_a_cb, (void *)cb_data); Py_RETURN_NONE; }
void makeDNSTask(struct DNSTask * dnstask) { int type; struct ares_options options; int optmask; switch (dnstask->role) { case DNS_TASK: gettimeofday(&dnstask->CheckDt, NULL); optmask = ARES_OPT_FLAGS; options.servers = getNulledMemory(sizeof (struct in_addr)); options.nservers = 1; options.flags = ARES_FLAG_NOCHECKRESP; optmask |= ARES_OPT_SERVERS; memcpy(options.servers, &dnstask->task->resolv->NSIP, sizeof (struct in_addr)); ares_init_options(&dnstask->channel, &options, optmask); MSToTimeval(dnstask->task->Record.TimeOut, tv); type = dnstask->taskType; break; default: return; break; } ares_query(dnstask->channel, getPTR(dnstask->task->Record.HostName), C_IN, type, DNSTaskResolvCallback, dnstask); ares_getsock(dnstask->channel, &dnstask->fd, 1); event_assign(&dnstask->ev, base, dnstask->fd, EV_READ | EV_TIMEOUT, OnEventDNSTask, dnstask); event_add(&dnstask->ev, &tv); }
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; }
inline unsigned long srv_ares(char *host, int *port, char *srv) { int nfds, count, srvh_len; char *srvh; fd_set read_fds, write_fds; struct timeval *tvp, tv; caport = 0; caadr = 0; ca_tmpname = NULL; #ifdef DEBUG printf("!!! ARES query !!!\n"); #endif srvh_len = strlen(host) + strlen(srv) + 2; srvh = malloc(srvh_len); if (srvh == NULL) { printf("error: failed to allocate memory (%i) for ares query\n", srvh_len); exit_code(2); } memset(srvh, 0, srvh_len); strncpy(srvh, srv, strlen(srv)); memcpy(srvh + strlen(srv), ".", 1); strcpy(srvh + strlen(srv) + 1, host); #ifdef DEBUG printf("hostname: '%s', len: %i\n", srvh, srvh_len); #endif ares_query(channel, srvh, CARES_CLASS_C_IN, CARES_TYPE_SRV, cares_callback, (char *) NULL); #ifdef DEBUG printf("after ares_query\n"); #endif /* wait for query to complete */ while (1) { 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); count = select(nfds, &read_fds, &write_fds, NULL, tvp); if (count < 0 && errno != EINVAL) { perror("ares select"); exit_code(2); } ares_process(channel, &read_fds, &write_fds); } #ifdef DEBUG printf("end of while\n"); #endif *port = caport; if (caadr == 0 && ca_tmpname != NULL) { caadr = getaddress(ca_tmpname); } if (ca_tmpname != NULL) free(ca_tmpname); free(srvh); return caadr; }
static void search_callback(void *arg, int status, unsigned char *abuf, int alen) { struct search_query *squery = (struct search_query *) arg; ares_channel channel = squery->channel; char *s; /* Stop searching unless we got a non-fatal error. */ if (status != ARES_ENODATA && status != ARES_ESERVFAIL && status != ARES_ENOTFOUND) end_squery(squery, status, abuf, alen); else { /* Save the status if we were trying as-is. */ if (squery->trying_as_is) squery->status_as_is = status; if (squery->next_domain < channel->ndomains) { /* Try the next domain. */ status = cat_domain(squery->name, channel->domains[squery->next_domain], &s); if (status != ARES_SUCCESS) end_squery(squery, status, NULL, 0); else { squery->trying_as_is = 0; squery->next_domain++; ares_query(channel, s, squery->dnsclass, squery->type, search_callback, squery); free(s); } } else if (squery->status_as_is == -1) { /* Try the name as-is at the end. */ squery->trying_as_is = 1; ares_query(channel, squery->name, squery->dnsclass, squery->type, search_callback, squery); } else end_squery(squery, squery->status_as_is, NULL, 0); } }
int cert_updater_start(ProxyContext * const proxy_context) { CertUpdater *cert_updater = &proxy_context->cert_updater; DNSCRYPT_PROXY_CERTS_UPDATE_START(); ares_query(cert_updater->ar_channel, proxy_context->provider_name, DNS_CLASS_IN, DNS_TYPE_TXT, cert_query_cb, proxy_context); return 0; }
void DnsCachedResolver::DnsTsx::execute() { ares_query(_channel->channel, _domain.c_str(), ns_c_in, _dnstype, DnsTsx::ares_callback, this); ++_channel->pending_queries; }
static inline unsigned long srv_ares(char *host, int *port, char *srv) { int nfds, count, srvh_len; char *srvh; fd_set read_fds, write_fds; struct timeval *tvp, tv; caport = 0; caadr = 0; ca_tmpname = NULL; dbg("starting ARES query\n"); srvh_len = strlen(host) + strlen(srv) + 2; srvh = malloc(srvh_len); if (srvh == NULL) { printf("error: failed to allocate memory (%i) for ares query\n", srvh_len); exit_code(2, __PRETTY_FUNCTION__, "memory allocation failure"); } memset(srvh, 0, srvh_len); strncpy(srvh, srv, strlen(srv)); memcpy(srvh + strlen(srv), ".", 1); strcpy(srvh + strlen(srv) + 1, host); dbg("hostname: '%s', len: %i\n", srvh, srvh_len); ares_query(channel, srvh, CARES_CLASS_C_IN, CARES_TYPE_SRV, cares_callback, (char *) NULL); dbg("ares_query finished, waiting for result...\n"); /* wait for query to complete */ while (1) { 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); count = select(nfds, &read_fds, &write_fds, NULL, tvp); if (count < 0 && errno != EINVAL) { perror("ares select"); exit_code(2, __PRETTY_FUNCTION__, "ares DNS resolution failure"); } ares_process(channel, &read_fds, &write_fds); } dbg("ARES answer processed\n"); *port = caport; if (caadr == 0 && ca_tmpname != NULL) { caadr = getaddress(ca_tmpname); } if (ca_tmpname != NULL) free(ca_tmpname); free(srvh); return caadr; }
static void printer_poll(void *arg) { struct printer_poll_args *pargs = (struct printer_poll_args *) arg; struct serverstate *state = pargs->state; struct printer *printer = pargs->printer; char *hesname; /* Null out the timer, since it may have just gone off. */ printer->timer = NULL; hesname = hesiod_to_bind(state->hescontext, printer->name, "pcap"); if (hesname == NULL) { syslog(LOG_ERR, "printer_poll: can't convert printer name %s to " "hesiod name: %m", printer->name); printer->timer = timer_set_rel(60, printer_poll, pargs); return; } syslog(LOG_DEBUG, "printer_poll: printer %s starting query for %s", printer->name, hesname); ares_query(state->channel, hesname, C_IN, T_TXT, printer_hes_callback, pargs); hesiod_free_string(state->hescontext, hesname); }
void ares_search(ares_channel channel, const char *name, int dnsclass, int type, ares_callback callback, void *arg) { struct search_query *squery; char *s; const char *p; int status, ndots; /* If name only yields one domain to search, then we don't have * to keep extra state, so just do an ares_query(). */ status = single_domain(channel, name, &s); if (status != ARES_SUCCESS) { callback(arg, status, NULL, 0); return; } if (s) { ares_query(channel, s, dnsclass, type, callback, arg); free(s); return; } /* Allocate a search_query structure to hold the state necessary for * doing multiple lookups. */ squery = malloc(sizeof(struct search_query)); if (!squery) { callback(arg, ARES_ENOMEM, NULL, 0); return; } squery->channel = channel; squery->name = strdup(name); if (!squery->name) { free(squery); callback(arg, ARES_ENOMEM, NULL, 0); return; } squery->dnsclass = dnsclass; squery->type = type; squery->status_as_is = -1; squery->callback = callback; squery->arg = arg; /* Count the number of dots in name. */ ndots = 0; for (p = name; *p; p++) { if (*p == '.') ndots++; } /* If ndots is at least the channel ndots threshold (usually 1), * then we try the name as-is first. Otherwise, we try the name * as-is last. */ if (ndots >= channel->ndots) { /* Try the name as-is first. */ squery->next_domain = 0; squery->trying_as_is = 1; ares_query(channel, name, dnsclass, type, search_callback, squery); } else { /* Try the name as-is last; start with the first search domain. */ squery->next_domain = 1; squery->trying_as_is = 0; status = cat_domain(name, channel->domains[0], &s); if (status == ARES_SUCCESS) { ares_query(channel, s, dnsclass, type, search_callback, squery); free(s); } else { free(squery->name); free(squery); callback(arg, status, NULL, 0); } } }
int main(int argc, char **argv) { ares_channel channel; int c, i, optmask = ARES_OPT_FLAGS, dnsclass = C_IN, type = T_A; int status, nfds, count; struct ares_options options; struct hostent *hostent; fd_set read_fds, write_fds; struct timeval *tvp, tv; struct ares_addr_node *srvr, *servers = NULL; #ifdef USE_WINSOCK WORD wVersionRequested = MAKEWORD(USE_WINSOCK,USE_WINSOCK); WSADATA wsaData; WSAStartup(wVersionRequested, &wsaData); #endif status = ares_library_init(ARES_LIB_INIT_ALL); if (status != ARES_SUCCESS) { fprintf(stderr, "ares_library_init: %s\n", ares_strerror(status)); return 1; } options.flags = ARES_FLAG_NOCHECKRESP; options.servers = NULL; options.nservers = 0; while ((c = ares_getopt(argc, argv, "df:s:c:t:T:U:")) != -1) { switch (c) { case 'd': #ifdef WATT32 dbug_init(); #endif break; case 'f': /* Add a flag. */ for (i = 0; i < nflags; i++) { if (strcmp(flags[i].name, optarg) == 0) break; } if (i < nflags) options.flags |= flags[i].value; else usage(); break; case 's': /* User-specified name servers override default ones. */ srvr = malloc(sizeof(struct ares_addr_node)); if (!srvr) { fprintf(stderr, "Out of memory!\n"); destroy_addr_list(servers); return 1; } append_addr_list(&servers, srvr); if (ares_inet_pton(AF_INET, optarg, &srvr->addr.addr4) > 0) srvr->family = AF_INET; else if (ares_inet_pton(AF_INET6, optarg, &srvr->addr.addr6) > 0) srvr->family = AF_INET6; else { hostent = gethostbyname(optarg); if (!hostent) { fprintf(stderr, "adig: server %s not found.\n", optarg); destroy_addr_list(servers); return 1; } switch (hostent->h_addrtype) { case AF_INET: srvr->family = AF_INET; memcpy(&srvr->addr.addr4, hostent->h_addr, sizeof(srvr->addr.addr4)); break; case AF_INET6: srvr->family = AF_INET6; memcpy(&srvr->addr.addr6, hostent->h_addr, sizeof(srvr->addr.addr6)); break; default: fprintf(stderr, "adig: server %s unsupported address family.\n", optarg); destroy_addr_list(servers); return 1; } } /* Notice that calling ares_init_options() without servers in the * options struct and with ARES_OPT_SERVERS set simultaneously in * the options mask, results in an initialization with no servers. * When alternative name servers have been specified these are set * later calling ares_set_servers() overriding any existing server * configuration. To prevent initial configuration with default * servers that will be discarded later, ARES_OPT_SERVERS is set. * If this flag is not set here the result shall be the same but * ares_init_options() will do needless work. */ optmask |= ARES_OPT_SERVERS; break; case 'c': /* Set the query class. */ for (i = 0; i < nclasses; i++) { if (strcasecmp(classes[i].name, optarg) == 0) break; } if (i < nclasses) dnsclass = classes[i].value; else usage(); break; case 't': /* Set the query type. */ for (i = 0; i < ntypes; i++) { if (strcasecmp(types[i].name, optarg) == 0) break; } if (i < ntypes) type = types[i].value; else usage(); break; case 'T': /* Set the TCP port number. */ if (!ISDIGIT(*optarg)) usage(); options.tcp_port = (unsigned short)strtol(optarg, NULL, 0); optmask |= ARES_OPT_TCP_PORT; break; case 'U': /* Set the UDP port number. */ if (!ISDIGIT(*optarg)) usage(); options.udp_port = (unsigned short)strtol(optarg, NULL, 0); optmask |= ARES_OPT_UDP_PORT; break; } } argc -= optind; argv += optind; if (argc == 0) usage(); status = ares_init_options(&channel, &options, optmask); if (status != ARES_SUCCESS) { fprintf(stderr, "ares_init_options: %s\n", ares_strerror(status)); return 1; } if(servers) { status = ares_set_servers(channel, servers); destroy_addr_list(servers); if (status != ARES_SUCCESS) { fprintf(stderr, "ares_init_options: %s\n", ares_strerror(status)); return 1; } } /* Initiate the queries, one per command-line argument. If there is * only one query to do, supply NULL as the callback argument; * otherwise, supply the query name as an argument so we can * distinguish responses for the user when printing them out. */ if (argc == 1) ares_query(channel, *argv, dnsclass, type, callback, (char *) NULL); else { for (; *argv; argv++) ares_query(channel, *argv, dnsclass, type, callback, *argv); } /* Wait for all queries to complete. */ for (;;) { 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); count = select(nfds, &read_fds, &write_fds, NULL, tvp); if (count < 0 && SOCKERRNO != EINVAL) { perror("select"); return 1; } ares_process(channel, &read_fds, &write_fds); } ares_destroy(channel); ares_library_cleanup(); #ifdef USE_WINSOCK WSACleanup(); #endif return 0; }
/*Scheduler input function*/ void auth_mgr_input(nkn_task_id_t id) { nkn_task_set_state(id, TASK_STATE_EVENT_WAIT); struct nkn_task *ntask = nkn_task_get_task(id); int dns_type; int ret=0; char domain_name[2048]; char *p_domain_name; assert(ntask); auth_msg_t *data = (auth_msg_t*)nkn_task_get_data(id); /* If its DNS lookup, the scheduler thread will just fire this request and leave, so no need to put it into a queue like auth tasks*/ if (data->authtype==DNSLOOKUP) { if (adnsd_enabled) { adns_daemon_input(id); return; } auth_dns_t* pdns=(auth_dns_t*)(data->authdata); pdns->auth_task_id=id; //Returns void pthread_mutex_lock(&cares_mutex); AO_fetch_and_add1(&glob_dns_task_called); /* Since we will support ttl provided by nameserver * we will not be using gethostbyname() anymore * Also, I should be using nameser.h and have ns_c_in * and ns_t_a for the below query, but lots of woes. * ares_gethostbyname(channel,(char*)pdns->domain,AF_INET, * cares_callback,data); */ /* TODO: use nameser.h */ if (pdns->ip[0].family == AF_INET) { dns_type = 1; // ns_t_a } else { dns_type = 28; // ns_t_aaaa } if (pdns->dns_query_len == 0) { p_domain_name = (char *)pdns->domain; } else { memcpy(domain_name, pdns->domain, pdns->domain_len); domain_name[pdns->domain_len] = '.'; memcpy(domain_name + pdns->domain_len + 1, pdns->dns_query, pdns->dns_query_len); domain_name[pdns->domain_len + 1 + pdns->dns_query_len] = '\0'; p_domain_name = domain_name; } ares_query(channel, p_domain_name, 1, /*ns_c_in = 1 Class: Internet. */ dns_type, cares_callback_req, data); /* * Wake up the select loop. */ if (channel_ready == 0) { ares_destroy(channel); //re-init the channel to get a new port ret = ares_init_options(&channel, &options, optmask); if (ret != ARES_SUCCESS) { DBG_LOG(SEVERE, MOD_AUTHMGR,"ares_init: %d %s", ret, ares_strerror(ret)); assert(0); } channel_ready = 1; AO_fetch_and_add1(&glob_dns_channel_reinit); pthread_mutex_unlock(&cares_mutex); return; } pthread_cond_signal(&cares_cond); pthread_mutex_unlock(&cares_mutex); } else { NKN_MUTEX_LOCK(&authreq_mutex); if (isam_task_arrFull()) { nkn_task_set_action_and_state(id, TASK_ACTION_OUTPUT, TASK_STATE_RUNNABLE); NKN_MUTEX_UNLOCK(&authreq_mutex); return; } auth_task_arr[auth_task_arr_tail] = id; if (auth_task_arr_tail == (MAX_AM_TASK_ARR - 1)) { auth_task_arr_tail = 0; } else { auth_task_arr_tail++; } pthread_cond_signal(&authreq_cond); NKN_MUTEX_UNLOCK(&authreq_mutex); } return; }
int main(int argc, char **argv) { ares_channel channel; int c, i, optmask = ARES_OPT_FLAGS, dnsclass = C_IN, type = T_A; int status, nfds, count; struct ares_options options; struct hostent *hostent; fd_set read_fds, write_fds; struct timeval *tvp, tv; #ifdef USE_WINSOCK WORD wVersionRequested = MAKEWORD(USE_WINSOCK,USE_WINSOCK); WSADATA wsaData; WSAStartup(wVersionRequested, &wsaData); #endif options.flags = ARES_FLAG_NOCHECKRESP; options.servers = NULL; options.nservers = 0; while ((c = ares_getopt(argc, argv, "df:s:c:t:T:U:")) != -1) { switch (c) { case 'd': #ifdef WATT32 dbug_init(); #endif break; case 'f': /* Add a flag. */ for (i = 0; i < nflags; i++) { if (strcmp(flags[i].name, optarg) == 0) break; } if (i == nflags) usage(); options.flags |= flags[i].value; break; case 's': /* Add a server, and specify servers in the option mask. */ if (ares_inet_pton(AF_INET, optarg, &inaddr) <= 0) { hostent = gethostbyname(optarg); if (!hostent || hostent->h_addrtype != AF_INET) { fprintf(stderr, "adig: server %s not found.\n", optarg); return 1; } memcpy(&inaddr, hostent->h_addr, sizeof(struct in_addr)); } options.servers = realloc(options.servers, (options.nservers + 1) * sizeof(struct in_addr)); if (!options.servers) { fprintf(stderr, "Out of memory!\n"); return 1; } memcpy(&options.servers[options.nservers], &inaddr, sizeof(struct in_addr)); options.nservers++; optmask |= ARES_OPT_SERVERS; break; case 'c': /* Set the query class. */ for (i = 0; i < nclasses; i++) { if (strcasecmp(classes[i].name, optarg) == 0) break; } if (i == nclasses) usage(); dnsclass = classes[i].value; break; case 't': /* Set the query type. */ for (i = 0; i < ntypes; i++) { if (strcasecmp(types[i].name, optarg) == 0) break; } if (i == ntypes) usage(); type = types[i].value; break; case 'T': /* Set the TCP port number. */ if (!ISDIGIT(*optarg)) usage(); options.tcp_port = (unsigned short)strtol(optarg, NULL, 0); optmask |= ARES_OPT_TCP_PORT; break; case 'U': /* Set the UDP port number. */ if (!ISDIGIT(*optarg)) usage(); options.udp_port = (unsigned short)strtol(optarg, NULL, 0); optmask |= ARES_OPT_UDP_PORT; break; } } argc -= optind; argv += optind; if (argc == 0) usage(); status = ares_init_options(&channel, &options, optmask); if (status != ARES_SUCCESS) { fprintf(stderr, "ares_init_options: %s\n", ares_strerror(status)); return 1; } /* Initiate the queries, one per command-line argument. If there is * only one query to do, supply NULL as the callback argument; * otherwise, supply the query name as an argument so we can * distinguish responses for the user when printing them out. */ if (argc == 1) ares_query(channel, *argv, dnsclass, type, callback, (char *) NULL); else { for (; *argv; argv++) ares_query(channel, *argv, dnsclass, type, callback, *argv); } /* Wait for all queries to complete. */ while (1) { 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); count = select(nfds, &read_fds, &write_fds, NULL, tvp); if (count < 0 && SOCKERRNO != EINVAL) { perror("select"); return 1; } ares_process(channel, &read_fds, &write_fds); } ares_destroy(channel); #ifdef USE_WINSOCK WSACleanup(); #endif return 0; }
static PyObject * Channel_func_query(Channel *self, PyObject *args) { char *name; int query_type; PyObject *callback, *ret; CHECK_CHANNEL(self); if (!PyArg_ParseTuple(args, "etiO:query", "idna", &name, &query_type, &callback)) { return NULL; } if (!PyCallable_Check(callback)) { PyErr_SetString(PyExc_TypeError, "a callable is required"); ret = NULL; goto finally; } Py_INCREF(callback); switch (query_type) { case T_A: { ares_query(self->channel, name, C_IN, T_A, &query_a_cb, (void *)callback); break; } case T_AAAA: { ares_query(self->channel, name, C_IN, T_AAAA, &query_aaaa_cb, (void *)callback); break; } case T_CNAME: { ares_query(self->channel, name, C_IN, T_CNAME, &query_cname_cb, (void *)callback); break; } case T_MX: { ares_query(self->channel, name, C_IN, T_MX, &query_mx_cb, (void *)callback); break; } case T_NAPTR: { ares_query(self->channel, name, C_IN, T_NAPTR, &query_naptr_cb, (void *)callback); break; } case T_NS: { ares_query(self->channel, name, C_IN, T_NS, &query_ns_cb, (void *)callback); break; } case T_PTR: { ares_query(self->channel, name, C_IN, T_PTR, &query_ptr_cb, (void *)callback); break; } case T_SOA: { ares_query(self->channel, name, C_IN, T_SOA, &query_soa_cb, (void *)callback); break; } case T_SRV: { ares_query(self->channel, name, C_IN, T_SRV, &query_srv_cb, (void *)callback); break; } case T_TXT: { ares_query(self->channel, name, C_IN, T_TXT, &query_txt_cb, (void *)callback); break; } default: { Py_DECREF(callback); PyErr_SetString(PyExc_AresError, "invalid query type specified"); ret = NULL; goto finally; } } ret = Py_None; finally: PyMem_Free(name); Py_XINCREF(ret); return ret; }
int dns_start_query(myconn_t *rec, char *targetserver) { struct ares_addr_node *srvr, *servers = NULL; struct ares_options options; int status, optmask; char *tdup, *tst; /* See what IP family we must use to communicate with the target DNS server */ srvr = malloc(sizeof(struct ares_addr_node)); append_addr_list(&servers, srvr); srvr->family = -1; #ifdef IPV4_SUPPORT if ((srvr->family == -1) && (inet_pton(AF_INET, targetserver, &srvr->addr.addr4) > 0)) srvr->family = AF_INET; #endif #ifdef IPV6_SUPPORT if ((srvr->family == -1) && (inet_pton(AF_INET6, targetserver, &srvr->addr.addr6) > 0)) srvr->family = AF_INET6; #endif if (srvr->family == -1) { errprintf("Unsupported IP family for DNS target IP %s, test %s\n", targetserver, rec->testspec); return 0; } /* Create a new ARES request channel */ rec->dnschannel = malloc(sizeof(ares_channel)); /* * The C-ARES timeout handling is a bit complicated. The timeout setting * here in the options only determines the timeout for the first query; * subsequent queries (up to the "tries" count) use a progressively * higher timeout setting. * So we cannot easily determine what combination of timeout/tries will * result in the full query timing out after the desired number of seconds. * Therefore, use a fixed set of values - the 2000 ms / 4 tries combination * results in a timeout after 23-24 seconds. */ optmask = ARES_OPT_FLAGS | ARES_OPT_SERVERS | ARES_OPT_TIMEOUTMS | ARES_OPT_TRIES; options.flags = ARES_FLAG_NOCHECKRESP; options.servers = NULL; options.nservers = 0; options.timeout = 2000; options.tries = 4; status = ares_init_options(rec->dnschannel, &options, optmask); if (status != ARES_SUCCESS) { errprintf("Cannot create ARES channel for DNS target %s, test %s\n", targetserver, rec->testspec); rec->dnsstatus = DNS_FINISHED; return 0; } /* Point the channel at the target server */ status = ares_set_servers(*((ares_channel *)rec->dnschannel), servers); destroy_addr_list(servers); if (status != ARES_SUCCESS) { errprintf("Cannot select ARES target DNS server %s, test %s\n", targetserver, rec->testspec); rec->dnsstatus = DNS_QUERY_COMPLETED; /* To reap the ARES channel later */ return 0; } /* Post the queries we want to perform */ tdup = strdup(rec->testspec); tst = strtok(tdup, ","); do { char *p, *tlookup; int atype = dns_atype; p = strchr(tst, ':'); tlookup = (p ? p+1 : tst); if (p) { *p = '\0'; atype = dns_name_type(tst); *p = ':'; } /* Use ares_query() here, since we dont want to get results from hosts file or other odd stuff. */ ares_query(*((ares_channel *)rec->dnschannel), tlookup, dns_aclass, atype, dns_query_callback, rec); tst = strtok(NULL, ","); } while (tst); xfree(tdup); rec->textlog = newstrbuffer(0); getntimer(&rec->dnsstarttime); rec->dnsstatus = DNS_QUERY_ACTIVE; return 1; }
static void search_callback(void *arg, int status, int timeouts, unsigned char *abuf, int alen) { struct search_query *squery = (struct search_query *) arg; ares_channel channel = squery->channel; char *s; squery->timeouts += timeouts; /* Stop searching unless we got a non-fatal error. */ if (status != ARES_ENODATA && status != ARES_ESERVFAIL && status != ARES_ENOTFOUND) end_squery(squery, status, abuf, alen); else { /* Save the status if we were trying as-is. */ if (squery->trying_as_is) squery->status_as_is = status; /* * If we ever get ARES_ENODATA along the way, record that; if the search * should run to the very end and we got at least one ARES_ENODATA, * then callers like ares_gethostbyname() may want to try a T_A search * even if the last domain we queried for T_AAAA resource records * returned ARES_ENOTFOUND. */ if (status == ARES_ENODATA) squery->ever_got_nodata = 1; if (squery->next_domain < channel->ndomains) { /* Try the next domain. */ status = cat_domain(squery->name, channel->domains[squery->next_domain], &s); if (status != ARES_SUCCESS) end_squery(squery, status, NULL, 0); else { squery->trying_as_is = 0; squery->next_domain++; ares_query(channel, s, squery->dnsclass, squery->type, search_callback, squery); free(s); } } else if (squery->status_as_is == -1) { /* Try the name as-is at the end. */ squery->trying_as_is = 1; ares_query(channel, squery->name, squery->dnsclass, squery->type, search_callback, squery); } else { if (squery->status_as_is == ARES_ENOTFOUND && squery->ever_got_nodata) { end_squery(squery, ARES_ENODATA, NULL, 0); } else end_squery(squery, squery->status_as_is, NULL, 0); } } }