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; }
int ares_get_servers_ports(ares_channel channel, struct ares_addr_port_node **servers) { struct ares_addr_port_node *srvr_head = NULL; struct ares_addr_port_node *srvr_last = NULL; struct ares_addr_port_node *srvr_curr; int status = ARES_SUCCESS; int i; if (!channel) return ARES_ENODATA; for (i = 0; i < channel->nservers; i++) { /* Allocate storage for this server node appending it to the list */ srvr_curr = ares_malloc_data(ARES_DATATYPE_ADDR_PORT_NODE); if (!srvr_curr) { status = ARES_ENOMEM; break; } if (srvr_last) { srvr_last->next = srvr_curr; } else { srvr_head = srvr_curr; } srvr_last = srvr_curr; /* Fill this server node data */ srvr_curr->family = channel->servers[i].addr.family; srvr_curr->udp_port = ntohs((unsigned short)channel->servers[i].addr.udp_port); srvr_curr->tcp_port = ntohs((unsigned short)channel->servers[i].addr.tcp_port); if (srvr_curr->family == AF_INET) memcpy(&srvr_curr->addrV4, &channel->servers[i].addr.addrV4, sizeof(srvr_curr->addrV4)); else memcpy(&srvr_curr->addrV6, &channel->servers[i].addr.addrV6, sizeof(srvr_curr->addrV6)); } if (status != ARES_SUCCESS) { if (srvr_head) { ares_free_data(srvr_head); srvr_head = NULL; } } *servers = srvr_head; return status; }
static void cert_query_cb(void *arg, int status, int timeouts, unsigned char *abuf, int alen) { Bincert *bincert = NULL; ProxyContext *proxy_context = arg; struct ares_txt_reply *txt_out; struct ares_txt_reply *txt_out_current; (void) timeouts; DNSCRYPT_PROXY_CERTS_UPDATE_RECEIVED(); if (status != ARES_SUCCESS || ares_parse_txt_reply(abuf, alen, &txt_out) != ARES_SUCCESS) { logger_noformat(proxy_context, LOG_ERR, "Unable to retrieve server certificates"); cert_reschedule_query_after_failure(proxy_context); DNSCRYPT_PROXY_CERTS_UPDATE_ERROR_COMMUNICATION(); return; } txt_out_current = txt_out; while (txt_out_current != NULL) { cert_open_bincert(proxy_context, (const SignedBincert *) txt_out_current->txt, txt_out_current->length, &bincert); txt_out_current = txt_out_current->next; } ares_free_data(txt_out); if (bincert == NULL) { logger_noformat(proxy_context, LOG_ERR, "No useable certificates found"); cert_reschedule_query_after_failure(proxy_context); DNSCRYPT_PROXY_CERTS_UPDATE_ERROR_NOCERTS(); return; } COMPILER_ASSERT(sizeof proxy_context->resolver_publickey == sizeof bincert->server_publickey); memcpy(proxy_context->resolver_publickey, bincert->server_publickey, sizeof proxy_context->resolver_publickey); COMPILER_ASSERT(sizeof proxy_context->dnscrypt_magic_query == sizeof bincert->magic_query); memcpy(proxy_context->dnscrypt_magic_query, bincert->magic_query, sizeof proxy_context->dnscrypt_magic_query); cert_print_server_key(proxy_context); dnscrypt_client_init_magic_query(&proxy_context->dnscrypt_client, bincert->magic_query); memset(bincert, 0, sizeof *bincert); free(bincert); dnscrypt_client_init_nmkey(&proxy_context->dnscrypt_client, proxy_context->resolver_publickey); dnscrypt_proxy_start_listeners(proxy_context); proxy_context->cert_updater.query_retry_step = 0U; cert_reschedule_query_after_success(proxy_context); DNSCRYPT_PROXY_CERTS_UPDATE_DONE((unsigned char *) proxy_context->resolver_publickey); }
/* ares_dup() duplicates a channel handle with all its options and returns a new channel handle */ int ares_dup(ares_channel *dest, ares_channel src) { struct ares_options opts; struct ares_addr_node *servers; int ipv6_nservers = 0; int i, rc; int optmask; *dest = NULL; /* in case of failure return NULL explicitly */ /* First get the options supported by the old ares_save_options() function, which is most of them */ rc = ares_save_options(src, &opts, &optmask); if(rc) return rc; /* Then create the new channel with those options */ rc = ares_init_options(dest, &opts, optmask); /* destroy the options copy to not leak any memory */ ares_destroy_options(&opts); if(rc) return rc; /* Now clone the options that ares_save_options() doesn't support. */ (*dest)->sock_create_cb = src->sock_create_cb; (*dest)->sock_create_cb_data = src->sock_create_cb_data; strncpy((*dest)->local_dev_name, src->local_dev_name, sizeof(src->local_dev_name)); (*dest)->local_ip4 = src->local_ip4; memcpy((*dest)->local_ip6, src->local_ip6, sizeof(src->local_ip6)); /* Full name server cloning required when not all are IPv4 */ for (i = 0; i < src->nservers; i++) { if (src->servers[i].addr.family != AF_INET) { ipv6_nservers++; break; } } if (ipv6_nservers) { rc = ares_get_servers(src, &servers); if (rc != ARES_SUCCESS) return rc; rc = ares_set_servers(*dest, servers); ares_free_data(servers); if (rc != ARES_SUCCESS) return rc; } return ARES_SUCCESS; /* everything went fine */ }
static struct ph_dns_query_response *make_srv_resp(unsigned char *abuf, int alen) { struct ph_dns_query_response *resp; uint32_t size; struct ares_srv_reply *srv, *tmp; uint32_t nres = 0, i; if (ares_parse_srv_reply(abuf, alen, &srv) != ARES_SUCCESS) { return NULL; } for (nres = 0, tmp = srv; tmp; tmp = tmp->next) { nres++; } size = sizeof(*resp) + ((nres - 1) * sizeof(resp->answer[0])); resp = ph_mem_alloc_size(mt.aresp, size); if (!resp) { ares_free_data(srv); return NULL; } resp->num_answers = nres; for (tmp = srv, i = 0; tmp; tmp = tmp->next, i++) { resp->answer[i].name = ph_mem_strdup(mt.string, tmp->host); resp->answer[i].priority = tmp->priority; resp->answer[i].weight = tmp->weight; resp->answer[i].port = tmp->port; } // Sort in priority order qsort(resp->answer, nres, sizeof(resp->answer[0]), compare_mx_ent); ares_free_data(srv); return resp; }
void DeleteSmtpOutMsg(void *v) { SmtpOutMsg *Msg = v; AsyncIO *IO = &Msg->IO; EV_syslog(LOG_DEBUG, "%s Exit\n", __FUNCTION__); /* these are kept in our own space and free'd below */ Msg->IO.ConnectMe = NULL; ares_free_data(Msg->AllMX); if (Msg->HostLookup.VParsedDNSReply != NULL) Msg->HostLookup.DNSReplyFree(Msg->HostLookup.VParsedDNSReply); FreeURL(&Msg->Relay); FreeStrBuf(&Msg->msgtext); FreeStrBuf(&Msg->MultiLineBuf); FreeAsyncIOContents(&Msg->IO); memset (Msg, 0, sizeof(SmtpOutMsg)); /* just to be shure... */ free(Msg); }
int ares_parse_mx_reply (const unsigned char *abuf, int alen, struct ares_mx_reply **mx_out) { unsigned int qdcount, ancount, i; const unsigned char *aptr, *vptr; int status, rr_type, rr_class, rr_len; long len; char *hostname = NULL, *rr_name = NULL; struct ares_mx_reply *mx_head = NULL; struct ares_mx_reply *mx_last = NULL; struct ares_mx_reply *mx_curr; /* Set *mx_out to NULL for all failure cases. */ *mx_out = NULL; /* Give up if abuf doesn't have room for a header. */ if (alen < HFIXEDSZ) return ARES_EBADRESP; /* Fetch the question and answer count from the header. */ qdcount = DNS_HEADER_QDCOUNT (abuf); ancount = DNS_HEADER_ANCOUNT (abuf); if (qdcount != 1) return ARES_EBADRESP; if (ancount == 0) return ARES_ENODATA; /* Expand the name from the question, and skip past the question. */ aptr = abuf + HFIXEDSZ; status = ares_expand_name (aptr, abuf, alen, &hostname, &len); if (status != ARES_SUCCESS) return status; if (aptr + len + QFIXEDSZ > abuf + alen) { free (hostname); return ARES_EBADRESP; } aptr += len + QFIXEDSZ; /* Examine each answer resource record (RR) in turn. */ for (i = 0; i < ancount; i++) { /* Decode the RR up to the data field. */ status = ares_expand_name (aptr, abuf, alen, &rr_name, &len); if (status != ARES_SUCCESS) { break; } aptr += len; if (aptr + RRFIXEDSZ > abuf + alen) { status = ARES_EBADRESP; break; } rr_type = DNS_RR_TYPE (aptr); rr_class = DNS_RR_CLASS (aptr); rr_len = DNS_RR_LEN (aptr); aptr += RRFIXEDSZ; /* Check if we are really looking at a MX record */ if (rr_class == C_IN && rr_type == T_MX) { /* parse the MX record itself */ if (rr_len < 2) { status = ARES_EBADRESP; break; } /* Allocate storage for this MX answer appending it to the list */ mx_curr = ares_malloc_data(ARES_DATATYPE_MX_REPLY); if (!mx_curr) { status = ARES_ENOMEM; break; } if (mx_last) { mx_last->next = mx_curr; } else { mx_head = mx_curr; } mx_last = mx_curr; vptr = aptr; mx_curr->priority = DNS__16BIT(vptr); vptr += sizeof(unsigned short); status = ares_expand_name (vptr, abuf, alen, &mx_curr->host, &len); if (status != ARES_SUCCESS) break; } /* Don't lose memory in the next iteration */ free (rr_name); rr_name = NULL; /* Move on to the next record */ aptr += rr_len; } if (hostname) free (hostname); if (rr_name) free (rr_name); /* clean up on error */ if (status != ARES_SUCCESS) { if (mx_head) ares_free_data (mx_head); return status; } /* everything looks fine, return the data */ *mx_out = mx_head; return ARES_SUCCESS; }
static void query_naptr_cb(void *arg, int status,int timeouts, unsigned char *answer_buf, int answer_len) { PyGILState_STATE gstate = PyGILState_Ensure(); int parse_status; struct ares_naptr_reply *naptr_reply, *naptr_ptr; PyObject *dns_result, *errorno, *tmp, *result, *callback; naptr_reply = NULL; callback = (PyObject *)arg; ASSERT(callback); if (status != ARES_SUCCESS) { errorno = PyInt_FromLong((long)status); dns_result = Py_None; Py_INCREF(Py_None); goto callback; } parse_status = ares_parse_naptr_reply(answer_buf, answer_len, &naptr_reply); if (parse_status != ARES_SUCCESS) { errorno = PyInt_FromLong((long)parse_status); dns_result = Py_None; Py_INCREF(Py_None); goto callback; } dns_result = PyList_New(0); if (!dns_result) { PyErr_NoMemory(); PyErr_WriteUnraisable(Py_None); errorno = PyInt_FromLong((long)ARES_ENOMEM); dns_result = Py_None; Py_INCREF(Py_None); goto callback; } for (naptr_ptr = naptr_reply; naptr_ptr != NULL; naptr_ptr = naptr_ptr->next) { tmp = PyStructSequence_New(&AresQueryNAPTRResultType); if (tmp == NULL) { break; } PyStructSequence_SET_ITEM(tmp, 0, PyInt_FromLong((long)naptr_ptr->order)); PyStructSequence_SET_ITEM(tmp, 1, PyInt_FromLong((long)naptr_ptr->preference)); PyStructSequence_SET_ITEM(tmp, 2, Py_BuildValue("s", (char *)naptr_ptr->flags)); PyStructSequence_SET_ITEM(tmp, 3, Py_BuildValue("s", (char *)naptr_ptr->service)); PyStructSequence_SET_ITEM(tmp, 4, Py_BuildValue("s", (char *)naptr_ptr->regexp)); PyStructSequence_SET_ITEM(tmp, 5, Py_BuildValue("s", naptr_ptr->replacement)); PyList_Append(dns_result, tmp); Py_DECREF(tmp); } errorno = Py_None; Py_INCREF(Py_None); callback: result = PyObject_CallFunctionObjArgs(callback, dns_result, errorno, NULL); if (result == NULL) { PyErr_WriteUnraisable(callback); } Py_XDECREF(result); Py_DECREF(dns_result); Py_DECREF(errorno); if (naptr_reply) { ares_free_data(naptr_reply); } Py_DECREF(callback); PyGILState_Release(gstate); }
static void query_srv_cb(void *arg, int status,int timeouts, unsigned char *answer_buf, int answer_len) { PyGILState_STATE gstate = PyGILState_Ensure(); int parse_status; struct ares_srv_reply *srv_reply, *srv_ptr; PyObject *dns_result, *errorno, *tmp, *result, *callback; srv_reply = NULL; callback = (PyObject *)arg; ASSERT(callback); if (status != ARES_SUCCESS) { errorno = PyInt_FromLong((long)status); dns_result = Py_None; Py_INCREF(Py_None); goto callback; } parse_status = ares_parse_srv_reply(answer_buf, answer_len, &srv_reply); if (parse_status != ARES_SUCCESS) { errorno = PyInt_FromLong((long)parse_status); dns_result = Py_None; Py_INCREF(Py_None); goto callback; } dns_result = PyList_New(0); if (!dns_result) { PyErr_NoMemory(); PyErr_WriteUnraisable(Py_None); errorno = PyInt_FromLong((long)ARES_ENOMEM); dns_result = Py_None; Py_INCREF(Py_None); goto callback; } for (srv_ptr = srv_reply; srv_ptr != NULL; srv_ptr = srv_ptr->next) { tmp = PyStructSequence_New(&AresQuerySRVResultType); if (tmp == NULL) { break; } PyStructSequence_SET_ITEM(tmp, 0, Py_BuildValue("s", srv_ptr->host)); PyStructSequence_SET_ITEM(tmp, 1, PyInt_FromLong((long)srv_ptr->port)); PyStructSequence_SET_ITEM(tmp, 2, PyInt_FromLong((long)srv_ptr->priority)); PyStructSequence_SET_ITEM(tmp, 3, PyInt_FromLong((long)srv_ptr->weight)); PyList_Append(dns_result, tmp); Py_DECREF(tmp); } errorno = Py_None; Py_INCREF(Py_None); callback: result = PyObject_CallFunctionObjArgs(callback, dns_result, errorno, NULL); if (result == NULL) { PyErr_WriteUnraisable(callback); } Py_XDECREF(result); Py_DECREF(dns_result); Py_DECREF(errorno); if (srv_reply) { ares_free_data(srv_reply); } Py_DECREF(callback); PyGILState_Release(gstate); }
static void query_soa_cb(void *arg, int status,int timeouts, unsigned char *answer_buf, int answer_len) { PyGILState_STATE gstate = PyGILState_Ensure(); int parse_status; struct ares_soa_reply *soa_reply = NULL; PyObject *dns_result, *errorno, *result, *callback; callback = (PyObject *)arg; ASSERT(callback); if (status != ARES_SUCCESS) { errorno = PyInt_FromLong((long)status); dns_result = Py_None; Py_INCREF(Py_None); goto callback; } parse_status = ares_parse_soa_reply(answer_buf, answer_len, &soa_reply); if (parse_status != ARES_SUCCESS) { errorno = PyInt_FromLong((long)parse_status); dns_result = Py_None; Py_INCREF(Py_None); goto callback; } dns_result = PyStructSequence_New(&AresQuerySOAResultType); if (!dns_result) { PyErr_NoMemory(); PyErr_WriteUnraisable(Py_None); errorno = PyInt_FromLong((long)ARES_ENOMEM); dns_result = Py_None; Py_INCREF(Py_None); goto callback; } PyStructSequence_SET_ITEM(dns_result, 0, Py_BuildValue("s", soa_reply->nsname)); PyStructSequence_SET_ITEM(dns_result, 1, Py_BuildValue("s", soa_reply->hostmaster)); PyStructSequence_SET_ITEM(dns_result, 2, PyInt_FromLong((long)soa_reply->serial)); PyStructSequence_SET_ITEM(dns_result, 3, PyInt_FromLong((long)soa_reply->refresh)); PyStructSequence_SET_ITEM(dns_result, 4, PyInt_FromLong((long)soa_reply->retry)); PyStructSequence_SET_ITEM(dns_result, 5, PyInt_FromLong((long)soa_reply->expire)); PyStructSequence_SET_ITEM(dns_result, 6, PyInt_FromLong((long)soa_reply->minttl)); errorno = Py_None; Py_INCREF(Py_None); callback: result = PyObject_CallFunctionObjArgs(callback, dns_result, errorno, NULL); if (result == NULL) { PyErr_WriteUnraisable(callback); } Py_XDECREF(result); Py_DECREF(dns_result); Py_DECREF(errorno); if (soa_reply) { ares_free_data(soa_reply); } Py_DECREF(callback); PyGILState_Release(gstate); }
static void query_txt_cb(void *arg, int status,int timeouts, unsigned char *answer_buf, int answer_len) { PyGILState_STATE gstate = PyGILState_Ensure(); int parse_status; struct ares_txt_reply *txt_reply, *txt_ptr; PyObject *dns_result, *errorno, *tmp, *result, *callback; txt_reply = NULL; callback = (PyObject *)arg; ASSERT(callback); if (status != ARES_SUCCESS) { errorno = PyInt_FromLong((long)status); dns_result = Py_None; Py_INCREF(Py_None); goto callback; } parse_status = ares_parse_txt_reply(answer_buf, answer_len, &txt_reply); if (parse_status != ARES_SUCCESS) { errorno = PyInt_FromLong((long)parse_status); dns_result = Py_None; Py_INCREF(Py_None); goto callback; } dns_result = PyList_New(0); if (!dns_result) { PyErr_NoMemory(); PyErr_WriteUnraisable(Py_None); errorno = PyInt_FromLong((long)ARES_ENOMEM); dns_result = Py_None; Py_INCREF(Py_None); goto callback; } for (txt_ptr = txt_reply; txt_ptr != NULL; txt_ptr = txt_ptr->next) { tmp = Py_BuildValue("s", (const char *)txt_ptr->txt); if (tmp == NULL) { break; } PyList_Append(dns_result, tmp); Py_DECREF(tmp); } errorno = Py_None; Py_INCREF(Py_None); callback: result = PyObject_CallFunctionObjArgs(callback, dns_result, errorno, NULL); if (result == NULL) { PyErr_WriteUnraisable(callback); } Py_XDECREF(result); Py_DECREF(dns_result); Py_DECREF(errorno); if (txt_reply) { ares_free_data(txt_reply); } Py_DECREF(callback); PyGILState_Release(gstate); }
int ares_parse_txt_reply (const unsigned char *abuf, int alen, struct ares_txt_reply **txt_out) { size_t substr_len; unsigned int qdcount, ancount, i; const unsigned char *aptr; const unsigned char *strptr; int status, rr_type, rr_class, rr_len; long len; char *hostname = NULL, *rr_name = NULL; struct ares_txt_reply *txt_head = NULL; struct ares_txt_reply *txt_last = NULL; struct ares_txt_reply *txt_curr; /* Set *txt_out to NULL for all failure cases. */ *txt_out = NULL; /* Give up if abuf doesn't have room for a header. */ if (alen < HFIXEDSZ) return ARES_EBADRESP; /* Fetch the question and answer count from the header. */ qdcount = DNS_HEADER_QDCOUNT (abuf); ancount = DNS_HEADER_ANCOUNT (abuf); if (qdcount != 1) return ARES_EBADRESP; if (ancount == 0) return ARES_ENODATA; /* Expand the name from the question, and skip past the question. */ aptr = abuf + HFIXEDSZ; status = ares_expand_name (aptr, abuf, alen, &hostname, &len); if (status != ARES_SUCCESS) return status; if (aptr + len + QFIXEDSZ > abuf + alen) { free (hostname); return ARES_EBADRESP; } aptr += len + QFIXEDSZ; /* Examine each answer resource record (RR) in turn. */ for (i = 0; i < ancount; i++) { /* Decode the RR up to the data field. */ status = ares_expand_name (aptr, abuf, alen, &rr_name, &len); if (status != ARES_SUCCESS) { break; } aptr += len; if (aptr + RRFIXEDSZ > abuf + alen) { status = ARES_EBADRESP; break; } rr_type = DNS_RR_TYPE (aptr); rr_class = DNS_RR_CLASS (aptr); rr_len = DNS_RR_LEN (aptr); aptr += RRFIXEDSZ; if (aptr + rr_len > abuf + alen) { status = ARES_EBADRESP; break; } /* Check if we are really looking at a TXT record */ if (rr_class == C_IN && rr_type == T_TXT) { /* * There may be multiple substrings in a single TXT record. Each * substring may be up to 255 characters in length, with a * "length byte" indicating the size of the substring payload. * RDATA contains both the length-bytes and payloads of all * substrings contained therein. */ strptr = aptr; while (strptr < (aptr + rr_len)) { substr_len = (unsigned char)*strptr; if (strptr + substr_len + 1 > aptr + rr_len) { status = ARES_EBADRESP; break; } /* Allocate storage for this TXT answer appending it to the list */ txt_curr = ares_malloc_data(ARES_DATATYPE_TXT_REPLY); if (!txt_curr) { status = ARES_ENOMEM; break; } if (txt_last) { txt_last->next = txt_curr; } else { txt_head = txt_curr; } txt_last = txt_curr; txt_curr->record_start = strptr == aptr; txt_curr->length = substr_len; txt_curr->txt = malloc (substr_len + 1/* Including null byte */); if (txt_curr->txt == NULL) { status = ARES_ENOMEM; break; } ++strptr; memcpy ((char *) txt_curr->txt, strptr, substr_len); /* Make sure we NULL-terminate */ txt_curr->txt[substr_len] = 0; strptr += substr_len; } } /* Don't lose memory in the next iteration */ free (rr_name); rr_name = NULL; /* Move on to the next record */ aptr += rr_len; } if (hostname) free (hostname); if (rr_name) free (rr_name); /* clean up on error */ if (status != ARES_SUCCESS) { if (txt_head) ares_free_data (txt_head); return status; } /* everything looks fine, return the data */ *txt_out = txt_head; return ARES_SUCCESS; }
int ares_parse_soa_reply(const unsigned char *abuf, int alen, struct ares_soa_reply **soa_out) { const unsigned char *aptr; long len; char *qname = NULL, *rr_name = NULL; struct ares_soa_reply *soa = NULL; int qdcount, ancount; int status; if (alen < HFIXEDSZ) return ARES_EBADRESP; /* parse message header */ qdcount = DNS_HEADER_QDCOUNT(abuf); ancount = DNS_HEADER_ANCOUNT(abuf); if (qdcount != 1 || ancount != 1) return ARES_EBADRESP; aptr = abuf + HFIXEDSZ; /* query name */ status = ares__expand_name_for_response(aptr, abuf, alen, &qname, &len); if (status != ARES_SUCCESS) goto failed_stat; aptr += len; /* skip qtype & qclass */ if (aptr + QFIXEDSZ > abuf + alen) goto failed; aptr += QFIXEDSZ; /* rr_name */ status = ares__expand_name_for_response(aptr, abuf, alen, &rr_name, &len); if (status != ARES_SUCCESS) goto failed_stat; aptr += len; /* skip rr_type, rr_class, rr_ttl, rr_rdlen */ if (aptr + RRFIXEDSZ > abuf + alen) goto failed; aptr += RRFIXEDSZ; /* allocate result struct */ soa = ares_malloc_data(ARES_DATATYPE_SOA_REPLY); if (!soa) { status = ARES_ENOMEM; goto failed_stat; } /* nsname */ status = ares__expand_name_for_response(aptr, abuf, alen, &soa->nsname, &len); if (status != ARES_SUCCESS) goto failed_stat; aptr += len; /* hostmaster */ status = ares__expand_name_for_response(aptr, abuf, alen, &soa->hostmaster, &len); if (status != ARES_SUCCESS) goto failed_stat; aptr += len; /* integer fields */ if (aptr + 5 * 4 > abuf + alen) goto failed; soa->serial = DNS__32BIT(aptr + 0 * 4); soa->refresh = DNS__32BIT(aptr + 1 * 4); soa->retry = DNS__32BIT(aptr + 2 * 4); soa->expire = DNS__32BIT(aptr + 3 * 4); soa->minttl = DNS__32BIT(aptr + 4 * 4); free(qname); free(rr_name); *soa_out = soa; return ARES_SUCCESS; failed: status = ARES_EBADRESP; failed_stat: ares_free_data(soa); if (qname) free(qname); if (rr_name) free(rr_name); return status; }
static void query_srv_cb(void *arg, int status,int timeouts, unsigned char *answer_buf, int answer_len) { PyGILState_STATE gstate = PyGILState_Ensure(); int parse_status; struct ares_srv_reply *srv_reply, *srv_ptr; ares_cb_data_t *data; DNSResolver *self; PyObject *dns_result, *errorno, *tmp, *result, *callback; ASSERT(arg); data = (ares_cb_data_t*)arg; self = data->resolver; callback = data->cb; ASSERT(self); /* Object could go out of scope in the callback, increase refcount to avoid it */ Py_INCREF(self); if (status != ARES_SUCCESS) { errorno = PyInt_FromLong((long)status); dns_result = Py_None; Py_INCREF(Py_None); goto callback; } parse_status = ares_parse_srv_reply(answer_buf, answer_len, &srv_reply); if (parse_status != ARES_SUCCESS) { errorno = PyInt_FromLong((long)parse_status); dns_result = Py_None; Py_INCREF(Py_None); goto callback; } dns_result = PyList_New(0); if (!dns_result) { PyErr_NoMemory(); PyErr_WriteUnraisable(Py_None); errorno = PyInt_FromLong((long)ARES_ENOMEM); dns_result = Py_None; Py_INCREF(Py_None); goto callback; } for (srv_ptr = srv_reply; srv_ptr != NULL; srv_ptr = srv_ptr->next) { tmp = PyTuple_New(4); if (tmp == NULL) { break; } PyTuple_SET_ITEM(tmp, 0, PyString_FromString(srv_ptr->host)); PyTuple_SET_ITEM(tmp, 1, PyInt_FromLong((long)srv_ptr->port)); PyTuple_SET_ITEM(tmp, 2, PyInt_FromLong((long)srv_ptr->priority)); PyTuple_SET_ITEM(tmp, 3, PyInt_FromLong((long)srv_ptr->weight)); PyList_Append(dns_result, tmp); Py_DECREF(tmp); } ares_free_data(srv_reply); errorno = Py_None; Py_INCREF(Py_None); callback: result = PyObject_CallFunctionObjArgs(callback, self, dns_result, errorno, NULL); if (result == NULL) { PyErr_WriteUnraisable(callback); } Py_XDECREF(result); Py_DECREF(callback); PyMem_Free(data); Py_DECREF(self); PyGILState_Release(gstate); }