int flg_ra, flg_rd, flg_tc, flg_qr, opcode;
int rrtype, rrclass, rdlength, rdstart;
int anstart, nsstart, arstart;
- int ownermatched, l, nrrs, place;
+ int ownermatched, l, nrrs;
const typeinfo *typei;
adns_query qu, nqu;
dns_rcode rcode;
adns_status st;
vbuf tempvb;
byte *newquery, *rrsdata;
+ parseinfo pai;
if (dglen<DNS_HDRSIZE) {
adns__diag(ads,serv,0,"received datagram too short for message header (%d)",dglen);
if (ads->iflags & adns_if_debug) {
adns__vbuf_init(&tempvb);
adns__debug(ads,serv,0,"reply not found, id %02x, query owner %s",
- id, adns__diag_domain(ads,serv,0,&tempvb,adns_qf_anyquote,
- dgram,dglen,DNS_HDRSIZE));
+ id, adns__diag_domain(ads,serv,0,&tempvb,dgram,dglen,DNS_HDRSIZE));
adns__vbuf_free(&tempvb);
}
return;
}
anstart= qu->query_dglen;
+ arstart= -1;
LIST_UNLINK(ads->timew,qu);
/* We're definitely going to do something with this query now */
break;
case rcode_formaterror:
adns__warn(ads,serv,qu,"server cannot understand our query (Format Error)");
- adns__query_fail(qu,adns_s_serverfaulty);
+ adns__query_fail(qu,adns_s_rcodeformaterror);
return;
case rcode_servfail:
- adns__query_fail(qu,adns_s_servfail);
+ adns__query_fail(qu,adns_s_rcodeservfail);
return;
case rcode_notimp:
adns__warn(ads,serv,qu,"server claims not to implement our query");
- adns__query_fail(qu,adns_s_notimplemented);
+ adns__query_fail(qu,adns_s_rcodenotimplemented);
return;
case rcode_refused:
adns__warn(ads,serv,qu,"server refused our query");
- adns__query_fail(qu,adns_s_refused);
+ adns__query_fail(qu,adns_s_rcoderefused);
return;
default:
adns__warn(ads,serv,qu,"server gave unknown response code %d",rcode);
- adns__query_fail(qu,adns_s_reasonunknown);
+ adns__query_fail(qu,adns_s_rcodeunknown);
return;
}
if (!ownermatched) {
if (ads->iflags & adns_if_debug) {
adns__debug(ads,serv,qu,"ignoring RR with an unexpected owner %s",
- adns__diag_domain(ads,serv,qu, &qu->vb,qu->flags,
- dgram,dglen,rrstart));
+ adns__diag_domain(ads,serv,qu, &qu->vb, dgram,dglen,rrstart));
}
continue;
}
if (rrtype == adns_r_cname && /* fixme - implement adns_qf_nocname */
(qu->typei->type & adns__rrt_typemask) != adns_r_cname) {
- if (!qu->cname_dgram) { /* Ignore second and subsequent CNAMEs */
+ if (qu->flags & adns_qf_cname_forbid) {
+ adns__query_fail(qu,adns_s_prohibitedcname);
+ return;
+ } else if (!qu->cname_dgram) { /* Ignore second and subsequent CNAMEs */
qu->cname_begin= rdstart;
qu->cname_dglen= dglen;
- st= adns__parse_domain(ads,serv,qu, &qu->vb,qu->flags,
+ st= adns__parse_domain(ads,serv,qu, &qu->vb,
+ qu->flags & adns_qf_quoteok_cname ? pdf_quoteok : 0,
dgram,dglen, &rdstart,rdstart+rdlength);
if (!qu->vb.used) goto x_truncated;
if (st) { adns__query_fail(qu,st); return; }
l= strlen(qu->vb.buf)+1;
qu->answer->cname= adns__alloc_interim(qu,l);
- if (!qu->answer->cname) { adns__query_fail(qu,adns_s_nolocalmem); return; }
+ if (!qu->answer->cname) { adns__query_fail(qu,adns_s_nomemory); return; }
qu->cname_dgram= adns__alloc_mine(qu,dglen);
memcpy(qu->cname_dgram,dgram,dglen);
*/
} else {
adns__debug(ads,serv,qu,"ignoring duplicate CNAME (%s, as well as %s)",
- adns__diag_domain(ads,serv,qu, &qu->vb,qu->flags,
- dgram,dglen,rdstart),
+ adns__diag_domain(ads,serv,qu, &qu->vb, dgram,dglen,rdstart),
qu->answer->cname);
}
} else if (rrtype == (qu->typei->type & adns__rrt_typemask)) {
adns__query_fail(qu,adns_s_norecurse);
} else {
adns__diag(ads,serv,qu,"server claims to do recursion, but gave us a referral");
- adns__query_fail(qu,adns_s_serverfaulty);
+ adns__query_fail(qu,adns_s_invalidresponse);
}
return;
}
/* Now, we have some RRs which we wanted. */
qu->answer->rrs.untyped= adns__alloc_interim(qu,qu->typei->rrsz*wantedrrs);
- if (!qu->answer->rrs.untyped) { adns__query_fail(qu,adns_s_nolocalmem); return; }
+ if (!qu->answer->rrs.untyped) { adns__query_fail(qu,adns_s_nomemory); return; }
typei= qu->typei;
cbyte= anstart;
- arstart= -1;
rrsdata= qu->answer->rrs.bytes;
-
- if (typei->diff_needswap) {
- if (!adns__vbuf_ensure(&qu->vb,typei->rrsz)) {
- adns__query_fail(qu,adns_s_nolocalmem);
- return;
- }
- }
- nrrs= 0;
-
- for (rri=0; rri<ancount; rri++) {
+
+ pai.ads= qu->ads;
+ pai.qu= qu;
+ pai.serv= serv;
+ pai.dgram= dgram;
+ pai.dglen= dglen;
+ pai.nsstart= nsstart;
+ pai.nscount= nscount;
+ pai.arcount= arcount;
+ pai.now= now;
+
+ for (rri=0, nrrs=0; rri<ancount; rri++) {
st= adns__findrr(qu,serv, dgram,dglen,&cbyte,
&rrtype,&rrclass,&rdlength,&rdstart,
&ownermatched);
rrtype != (qu->typei->type & adns__rrt_typemask) ||
!ownermatched)
continue;
- st= typei->parse(qu,serv, dgram,dglen, rdstart,rdstart+rdlength,
- rrsdata+nrrs*typei->rrsz);
+ st= typei->parse(&pai, rdstart,rdstart+rdlength, rrsdata+nrrs*typei->rrsz);
if (st) { adns__query_fail(qu,st); return; }
if (rdstart==-1) goto x_truncated;
-
- if (typei->diff_needswap) {
- for (place= nrrs;
- place>0 && typei->diff_needswap(rrsdata+(place-1)*typei->rrsz,
- rrsdata+nrrs*typei->rrsz);
- place--);
- if (place != nrrs) {
- memcpy(qu->vb.buf,rrsdata+nrrs*typei->rrsz,typei->rrsz);
- memmove(rrsdata+(place+1)*typei->rrsz,
- rrsdata+place*typei->rrsz,
- (nrrs-place)*typei->rrsz);
- memcpy(rrsdata+place*typei->rrsz,qu->vb.buf,typei->rrsz);
- }
- }
nrrs++;
}
assert(nrrs==wantedrrs);
if (!flg_tc) {
adns__diag(ads,serv,qu,"server sent datagram which points outside itself");
- adns__query_fail(qu,adns_s_serverfaulty);
+ adns__query_fail(qu,adns_s_invalidresponse);
return;
}
qu->flags |= adns_qf_usevc;
if (st) { adns__query_fail(qu,st); return; }
newquery= realloc(qu->query_dgram,qu->vb.used);
- if (!newquery) { adns__query_fail(qu,adns_s_nolocalmem); return; }
+ if (!newquery) { adns__query_fail(qu,adns_s_nomemory); return; }
qu->query_dgram= newquery;
qu->query_dglen= qu->vb.used;