void ares_query(ares_channel channel, const char *name, int dnsclass, int type, ares_callback callback, void *arg) { struct qquery *qquery; unsigned char *qbuf; int qlen, rd, status; /* Compose the query. */ rd = !(channel->flags & ARES_FLAG_NORECURSE); status = ares_create_query(name, dnsclass, type, channel->next_id, rd, &qbuf, &qlen, (channel->flags & ARES_FLAG_EDNS) ? channel->ednspsz : 0); if (status != ARES_SUCCESS) { if (qbuf != NULL) ares_free(qbuf); callback(arg, status, 0, NULL, 0); return; } channel->next_id = generate_unique_id(channel); /* Allocate and fill in the query structure. */ qquery = ares_malloc(sizeof(struct qquery)); if (!qquery) { ares_free_string(qbuf); callback(arg, ARES_ENOMEM, 0, NULL, 0); return; } qquery->callback = callback; qquery->arg = arg; /* Send it off. qcallback will be called when we get an answer. */ ares_send(channel, qbuf, qlen, qcallback, qquery); ares_free_string(qbuf); }
static const unsigned char *display_question(const unsigned char *aptr, const unsigned char *abuf, int alen) { char *name; int type, dnsclass, status; long len; /* Parse the question name. */ status = ares_expand_name(aptr, abuf, alen, &name, &len); if (status != ARES_SUCCESS) return NULL; aptr += len; /* Make sure there's enough data after the name for the fixed part * of the question. */ if (aptr + QFIXEDSZ > abuf + alen) { ares_free_string(name); return NULL; } /* Parse the question type and class. */ type = DNS_QUESTION_TYPE(aptr); dnsclass = DNS_QUESTION_CLASS(aptr); aptr += QFIXEDSZ; /* Display the question, in a format sort of similar to how we will * display RRs. */ printf("\t%-15s.\t", name); if (dnsclass != C_IN) printf("\t%s", class_name(dnsclass)); printf("\t%s\n", type_name(type)); ares_free_string(name); return aptr; }
int LLAres::expandName(const char *encoded, const char *abuf, size_t alen, std::string &s, size_t &enclen) { char *t; int ret; long e; ret = ares_expand_name((const unsigned char *) encoded, (const unsigned char *) abuf, alen, &t, &e); if (ret == ARES_SUCCESS) { s.assign(t); enclen = e; ares_free_string(t); } return ret; }
static const unsigned char *display_rr(const unsigned char *aptr, const unsigned char *abuf, int alen) { const unsigned char *p; int type, dnsclass, ttl, dlen, status; long len; char addr[46]; union { unsigned char * as_uchar; char * as_char; } name; /* Parse the RR name. */ status = ares_expand_name(aptr, abuf, alen, &name.as_char, &len); if (status != ARES_SUCCESS) return NULL; aptr += len; /* Make sure there is enough data after the RR name for the fixed * part of the RR. */ if (aptr + RRFIXEDSZ > abuf + alen) { ares_free_string(name.as_char); return NULL; } /* Parse the fixed part of the RR, and advance to the RR data * field. */ type = DNS_RR_TYPE(aptr); dnsclass = DNS_RR_CLASS(aptr); ttl = DNS_RR_TTL(aptr); dlen = DNS_RR_LEN(aptr); aptr += RRFIXEDSZ; if (aptr + dlen > abuf + alen) { ares_free_string(name.as_char); return NULL; } /* Display the RR name, class, and type. */ printf("\t%-15s.\t%d", name.as_char, ttl); if (dnsclass != C_IN) printf("\t%s", class_name(dnsclass)); printf("\t%s", type_name(type)); ares_free_string(name.as_char); /* Display the RR data. Don't touch aptr. */ switch (type) { case T_CNAME: case T_MB: case T_MD: case T_MF: case T_MG: case T_MR: case T_NS: case T_PTR: /* For these types, the RR data is just a domain name. */ status = ares_expand_name(aptr, abuf, alen, &name.as_char, &len); if (status != ARES_SUCCESS) return NULL; printf("\t%s.", name.as_char); ares_free_string(name.as_char); break; case T_HINFO: /* The RR data is two length-counted character strings. */ p = aptr; len = *p; if (p + len + 1 > aptr + dlen) return NULL; status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len); if (status != ARES_SUCCESS) return NULL; printf("\t%s", name.as_char); ares_free_string(name.as_char); p += len; len = *p; if (p + len + 1 > aptr + dlen) return NULL; status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len); if (status != ARES_SUCCESS) return NULL; printf("\t%s", name.as_char); ares_free_string(name.as_char); break; case T_MINFO: /* The RR data is two domain names. */ p = aptr; status = ares_expand_name(p, abuf, alen, &name.as_char, &len); if (status != ARES_SUCCESS) return NULL; printf("\t%s.", name.as_char); ares_free_string(name.as_char); p += len; status = ares_expand_name(p, abuf, alen, &name.as_char, &len); if (status != ARES_SUCCESS) return NULL; printf("\t%s.", name.as_char); ares_free_string(name.as_char); break; case T_MX: /* The RR data is two bytes giving a preference ordering, and * then a domain name. */ if (dlen < 2) return NULL; printf("\t%d", DNS__16BIT(aptr)); status = ares_expand_name(aptr + 2, abuf, alen, &name.as_char, &len); if (status != ARES_SUCCESS) return NULL; printf("\t%s.", name.as_char); ares_free_string(name.as_char); break; case T_SOA: /* The RR data is two domain names and then five four-byte * numbers giving the serial number and some timeouts. */ p = aptr; status = ares_expand_name(p, abuf, alen, &name.as_char, &len); if (status != ARES_SUCCESS) return NULL; printf("\t%s.\n", name.as_char); ares_free_string(name.as_char); p += len; status = ares_expand_name(p, abuf, alen, &name.as_char, &len); if (status != ARES_SUCCESS) return NULL; printf("\t\t\t\t\t\t%s.\n", name.as_char); ares_free_string(name.as_char); p += len; if (p + 20 > aptr + dlen) return NULL; printf("\t\t\t\t\t\t( %lu %lu %lu %lu %lu )", (unsigned long)DNS__32BIT(p), (unsigned long)DNS__32BIT(p+4), (unsigned long)DNS__32BIT(p+8), (unsigned long)DNS__32BIT(p+12), (unsigned long)DNS__32BIT(p+16)); break; case T_TXT: /* The RR data is one or more length-counted character * strings. */ p = aptr; while (p < aptr + dlen) { len = *p; if (p + len + 1 > aptr + dlen) return NULL; status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len); if (status != ARES_SUCCESS) return NULL; printf("\t%s", name.as_char); ares_free_string(name.as_char); p += len; } break; case T_A: /* The RR data is a four-byte Internet address. */ if (dlen != 4) return NULL; printf("\t%s", ares_inet_ntop(AF_INET,aptr,addr,sizeof(addr))); break; case T_AAAA: /* The RR data is a 16-byte IPv6 address. */ if (dlen != 16) return NULL; printf("\t%s", ares_inet_ntop(AF_INET6,aptr,addr,sizeof(addr))); break; case T_WKS: /* Not implemented yet */ break; case T_SRV: /* The RR data is three two-byte numbers representing the * priority, weight, and port, followed by a domain name. */ printf("\t%d", DNS__16BIT(aptr)); printf(" %d", DNS__16BIT(aptr + 2)); printf(" %d", DNS__16BIT(aptr + 4)); status = ares_expand_name(aptr + 6, abuf, alen, &name.as_char, &len); if (status != ARES_SUCCESS) return NULL; printf("\t%s.", name.as_char); ares_free_string(name.as_char); break; case T_NAPTR: printf("\t%d", DNS__16BIT(aptr)); /* order */ printf(" %d\n", DNS__16BIT(aptr + 2)); /* preference */ p = aptr + 4; status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len); if (status != ARES_SUCCESS) return NULL; printf("\t\t\t\t\t\t%s\n", name.as_char); ares_free_string(name.as_char); p += len; status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len); if (status != ARES_SUCCESS) return NULL; printf("\t\t\t\t\t\t%s\n", name.as_char); ares_free_string(name.as_char); p += len; status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len); if (status != ARES_SUCCESS) return NULL; printf("\t\t\t\t\t\t%s\n", name.as_char); ares_free_string(name.as_char); p += len; status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len); if (status != ARES_SUCCESS) return NULL; printf("\t\t\t\t\t\t%s", name.as_char); ares_free_string(name.as_char); break; default: printf("\t[Unknown RR; cannot parse]"); break; } printf("\n"); return aptr + dlen; }
inline static const unsigned char *CheckPatternAfterParseAnswer(struct DNSTask *dnstask, const unsigned char *aptr, const unsigned char *abuf, int alen) { const unsigned char *p; int type, dnsclass, ttl, dlen, status; long len; char addr[46]; /* if (task->LObjId == 1148) raise(SIGTRAP); */ union { unsigned char * as_uchar; char * as_char; } name; status = ares_expand_name(aptr, abuf, alen, &name.as_char, &len); if (status != ARES_SUCCESS) return NULL; aptr += len; if (aptr + RRFIXEDSZ > abuf + alen) { ares_free_string(name.as_char); return NULL; } type = DNS_RR_TYPE(aptr); dnsclass = DNS_RR_CLASS(aptr); ttl = DNS_RR_TTL(aptr); dlen = DNS_RR_LEN(aptr); aptr += RRFIXEDSZ; if (aptr + dlen > abuf + alen) { ares_free_string(name.as_char); return NULL; } ares_free_string(name.as_char); switch (type) { case T_CNAME: case T_MB: case T_MD: case T_MF: case T_MG: case T_MR: case T_NS: case T_PTR: status = ares_expand_name(aptr, abuf, alen, &name.as_char, &len); if (status != ARES_SUCCESS) { debug("error T_%s compare, %s andd ttl %d error - %d", type_name(type), dnstask->taskPattern, dnstask->taskTTL, status); return NULL; } debug("T_%s compare, %s:%08x on %s and ttl %d on %d", type_name(type), dnstask->taskPattern, dnstask->taskPattern, name.as_char, ttl, dnstask->taskTTL); if ((dnstask->taskPattern[0] == 0 or !memcmp(name.as_char, dnstask->taskPattern, dnstask->taskPatternLen)) and(dnstask->taskTTL == 0 or ttl == dnstask->taskTTL)) { dnstask->task->code = STATE_DONE; } ares_free_string(name.as_char); break; case T_HINFO: /* The RR data is two length-counted character strings. */ p = aptr; len = *p; if (p + len + 1 > aptr + dlen) return NULL; debug("\t%.*s", (int) len, p + 1); p += len + 1; len = *p; if (p + len + 1 > aptr + dlen) return NULL; debug("\t%.*s", (int) len, p + 1); break; case T_MINFO: /* The RR data is two domain names. */ p = aptr; status = ares_expand_name(p, abuf, alen, &name.as_char, &len); if (status != ARES_SUCCESS) return NULL; debug("\t%s.", name.as_char); ares_free_string(name.as_char); p += len; status = ares_expand_name(p, abuf, alen, &name.as_char, &len); if (status != ARES_SUCCESS) return NULL; debug("\t%s.", name.as_char); ares_free_string(name.as_char); break; case T_MX: if (dlen < 2) { return NULL; } status = ares_expand_name(aptr + 2, abuf, alen, &name.as_char, &len); if (status != ARES_SUCCESS) { return NULL; } debug("T_MX compare %s on %s and ttl %d on %d\n", dnstask->taskPattern, name.as_char, ttl, dnstask->taskTTL); if ((dnstask->taskPattern[0] = 0 or !memcmp(name.as_char, dnstask->taskPattern, dnstask->taskPatternLen)) and(dnstask->taskTTL == 0 or ttl == dnstask->taskTTL)) { dnstask->task->code = STATE_DONE; } ares_free_string(name.as_char); break; case T_SOA: /* The RR data is two domain names and then five four-byte * numbers giving the serial number and some timeouts. */ p = aptr; status = ares_expand_name(p, abuf, alen, &name.as_char, &len); if (status != ARES_SUCCESS) return NULL; debug("\t%s.", name.as_char); ares_free_string(name.as_char); p += len; status = ares_expand_name(p, abuf, alen, &name.as_char, &len); if (status != ARES_SUCCESS) return NULL; debug("\t\t\t\t\t\t%s.", name.as_char); ares_free_string(name.as_char); p += len; if (p + 20 > aptr + dlen) return NULL; debug("\t\t\t\t\t\t( %lu %lu %lu %lu %lu )", (unsigned long) DNS__32BIT(p), (unsigned long) DNS__32BIT(p + 4), (unsigned long) DNS__32BIT(p + 8), (unsigned long) DNS__32BIT(p + 12), (unsigned long) DNS__32BIT(p + 16)); break; case T_TXT: /* The RR data is one or more length-counted character * strings. */ p = aptr; while (p < aptr + dlen) { len = *p; if (p + len + 1 > aptr + dlen) return NULL; //printf("\t%.*s", (int) len, p + 1); debug("T_TXT compare %s on %s and ttl %d on %d", dnstask->taskPattern, p + 1, ttl, dnstask->taskTTL); if (!memcmp(p + 1, dnstask->taskPattern, dnstask->taskPatternLen) and ttl == dnstask->taskTTL) { dnstask->task->code = STATE_DONE; } p += len + 1; } break; case T_A: /* The RR data is a four-byte Internet address. */ inet_ntop(AF_INET, aptr, addr, sizeof (addr)); debug("T_A compare %s on %s (size %d) and ttl %d on %d", dnstask->taskPattern, addr, dnstask->taskPatternLen, ttl, dnstask->taskTTL); /* if (dnstask->task->LObjId == 1056) raise(SIGSEGV); */ if (dlen == 4 and(dnstask->taskPattern[0] == 0 or !memcmp(addr, dnstask->taskPattern, dnstask->taskPatternLen)) and(dnstask->taskTTL == 0 or ttl == dnstask->taskTTL)) { dnstask->task->code = STATE_DONE; } break; case T_AAAA: /* The RR data is a 16-byte IPv6 address. */ if (dlen != 16) return NULL; debug("\t%s", inet_ntop(AF_INET6, aptr, addr, sizeof (addr))); break; case T_WKS: /* Not implemented yet */ break; case T_SRV: /* The RR data is three two-byte numbers representing the * priority, weight, and port, followed by a domain name. */ printf("\t%d", DNS__16BIT(aptr)); printf(" %d", DNS__16BIT(aptr + 2)); printf(" %d", DNS__16BIT(aptr + 4)); status = ares_expand_name(aptr + 6, abuf, alen, &name.as_char, &len); if (status != ARES_SUCCESS) return NULL; printf("\t%s.", name.as_char); ares_free_string(name.as_char); break; case T_NAPTR: printf("\t%d", DNS__16BIT(aptr)); /* order */ printf(" %d\n", DNS__16BIT(aptr + 2)); /* preference */ p = aptr + 4; status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len); if (status != ARES_SUCCESS) return NULL; printf("\t\t\t\t\t\t%s\n", name.as_char); ares_free_string(name.as_char); p += len; status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len); if (status != ARES_SUCCESS) return NULL; printf("\t\t\t\t\t\t%s\n", name.as_char); ares_free_string(name.as_char); p += len; status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len); if (status != ARES_SUCCESS) return NULL; printf("\t\t\t\t\t\t%s\n", name.as_char); ares_free_string(name.as_char); p += len; status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len); if (status != ARES_SUCCESS) return NULL; printf("\t\t\t\t\t\t%s", name.as_char); ares_free_string(name.as_char); break; default: printf("\t[Unknown RR; cannot parse]"); break; } if (dnstask->task->code != STATE_DONE) { return aptr + dlen; } else { return NULL; } }