static const unsigned char *display_question(const unsigned char *aptr, const unsigned char *abuf, int alen, dns_resp_t *response) { 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) { xfree(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. */ sprintf(msg, "\t%-15s.\t", name); addtobuffer(response->msgbuf, msg); if (dnsclass != C_IN) { sprintf(msg, "\t%s", class_name(dnsclass)); addtobuffer(response->msgbuf, msg); } sprintf(msg, "\t%s\n", type_name(type)); addtobuffer(response->msgbuf, msg); xfree(name); return aptr; }
/* parse reply record */ int evdns_parse_reply(unsigned char *buf, int nbuf, HOSTENT *hostent) { unsigned char *p = NULL, *end = NULL, *s = NULL, *ps = NULL; int i = 0, qdcount = 0, ancount = 0, nscount = 0, arcount = 0, qr = 0, opcode = 0, aa = 0, tc = 0, rd = 0, ra = 0, rcode = 0, type = 0, dnsclass = 0, ttl = 0, rrlen = 0; if(buf && nbuf > HFIXEDSZ) { hostent->naddrs = 0; hostent->nalias = 0; p = buf; end = buf + nbuf; hostent->qid = DNS_HEADER_QID(p); qr = DNS_HEADER_QR(p); opcode = DNS_HEADER_OPCODE(p); aa = DNS_HEADER_AA(p); tc = DNS_HEADER_TC(p); rd = DNS_HEADER_RD(p); ra = DNS_HEADER_RA(p); rcode = DNS_HEADER_RCODE(p); qdcount = DNS_HEADER_QDCOUNT(p); ancount = DNS_HEADER_ANCOUNT(p); nscount = DNS_HEADER_NSCOUNT(p); arcount = DNS_HEADER_ARCOUNT(p); p += HFIXEDSZ; /* Display the answer header. */ /* printf("id: %d\n", id); printf("flags: %s%s%s%s%s\n", qr ? "qr " : "", aa ? "aa " : "", tc ? "tc " : "", rd ? "rd " : "", ra ? "ra " : ""); printf("opcode: %s\n", opcodes[opcode]); printf("rcode: %s\n", rcodes[rcode]); fprintf(stdout, "qdcount:%d\nancount:%d\nnscount:%d\narcount:%d\n", qdcount, ancount, nscount, arcount); */ /* parse question */ for(i = 0; i < qdcount; i++) { ps = (unsigned char *)hostent->name; p = evdns_expand_name(p, buf, end, ps); /* Parse the question type and class. */ type = DNS_QUESTION_TYPE(p); dnsclass = DNS_QUESTION_CLASS(p); p += QFIXEDSZ; /* fprintf(stdout, "qname:%-15s", name); fprintf(stdout, "\tqtype:%d", type); fprintf(stdout, "\tqclass:%d\r\n", dnsclass); */ } /* parse A name */ for(i = 0; i < ancount; i++) { ps = (unsigned char *)hostent->alias[hostent->nalias++]; p = evdns_expand_name(p, buf, end, ps); type = DNS_RR_TYPE(p); dnsclass = DNS_RR_CLASS(p); ttl = DNS_RR_TTL(p); rrlen = DNS_RR_LEN(p); p += RRFIXEDSZ; /* fprintf(stdout, "name:%s type:%d dnsclass:%d ttl:%d rrlen:%d ", name, type, dnsclass, ttl, rrlen); */ /* addr name */ if(type == TYPE_ANAME) { hostent->addrs[hostent->naddrs++] = *((int *)p); } /* Canonical name */ else if(type == TYPE_CNAME) { ps = (unsigned char *)hostent->alias[hostent->nalias++]; s = evdns_expand_name(p, buf, end, ps); //fprintf(stdout, "cname:%s ", cname); } /* pointer */ else if(type == TYPE_PTR) { ps = (unsigned char *)hostent->alias[hostent->nalias++]; s = evdns_expand_name(p, buf, end, ps); //fprintf(stdout, "pointer:%s ", cname); } //fprintf(stdout, "\r\n"); p += rrlen; } return 0; } return -1; }
static int same_questions(const unsigned char *qbuf, int qlen, const unsigned char *abuf, int alen) { struct { const unsigned char *p; int qdcount; char *name; long int namelen; int type; int dnsclass; } q, a; int i, j; if (qlen < HFIXEDSZ || alen < HFIXEDSZ) return 0; /* Extract qdcount from the request and reply buffers and compare them. */ q.qdcount = DNS_HEADER_QDCOUNT(qbuf); a.qdcount = DNS_HEADER_QDCOUNT(abuf); if (q.qdcount != a.qdcount) return 0; /* For each question in qbuf, find it in abuf. */ q.p = qbuf + HFIXEDSZ; for (i = 0; i < q.qdcount; i++) { /* Decode the question in the query. */ if (ares_expand_name(q.p, qbuf, qlen, &q.name, &q.namelen) != ARES_SUCCESS) return 0; q.p += q.namelen; if (q.p + QFIXEDSZ > qbuf + qlen) { free(q.name); return 0; } q.type = DNS_QUESTION_TYPE(q.p); q.dnsclass = DNS_QUESTION_CLASS(q.p); q.p += QFIXEDSZ; /* Search for this question in the answer. */ a.p = abuf + HFIXEDSZ; for (j = 0; j < a.qdcount; j++) { /* Decode the question in the answer. */ if (ares_expand_name(a.p, abuf, alen, &a.name, &a.namelen) != ARES_SUCCESS) { free(q.name); return 0; } a.p += a.namelen; if (a.p + QFIXEDSZ > abuf + alen) { free(q.name); free(a.name); return 0; } a.type = DNS_QUESTION_TYPE(a.p); a.dnsclass = DNS_QUESTION_CLASS(a.p); a.p += QFIXEDSZ; /* Compare the decoded questions. */ if (strcasecmp(q.name, a.name) == 0 && q.type == a.type && q.dnsclass == a.dnsclass) { free(a.name); break; } free(a.name); } free(q.name); if (j == a.qdcount) return 0; } return 1; }