*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#include "internal.h"
void adns__procdgram(adns_state ads, const byte *dgram, int dglen,
#include "internal.h"
void adns__procdgram(adns_state ads, const byte *dgram, int dglen,
int cbyte, rrstart, wantedrrs, rri, foundsoa, foundns, cname_here;
int id, f1, f2, qdcount, ancount, nscount, arcount;
int flg_ra, flg_rd, flg_tc, flg_qr, opcode;
int rrtype, rrclass, rdlength, rdstart;
int anstart, nsstart, arstart;
int ownermatched, l, nrrs;
int cbyte, rrstart, wantedrrs, rri, foundsoa, foundns, cname_here;
int id, f1, f2, qdcount, ancount, nscount, arcount;
int flg_ra, flg_rd, flg_tc, flg_qr, opcode;
int rrtype, rrclass, rdlength, rdstart;
int anstart, nsstart, arstart;
int ownermatched, l, nrrs;
for (rri= 0; rri<ancount; rri++) {
rrstart= cbyte;
st= adns__findrr(qu,serv, dgram,dglen,&cbyte,
for (rri= 0; rri<ancount; rri++) {
rrstart= cbyte;
st= adns__findrr(qu,serv, dgram,dglen,&cbyte,
- &rrtype,&rrclass,&rdlength,&rdstart,
+ &rrtype,&rrclass,&ttl, &rdlength,&rdstart,
&ownermatched);
if (st) { adns__query_fail(qu,st); return; }
if (rrtype == -1) goto x_truncated;
&ownermatched);
if (st) { adns__query_fail(qu,st); return; }
if (rrtype == -1) goto x_truncated;
(qu->typei->type & adns__rrt_typemask) != adns_r_cname) {
if (qu->flags & adns_qf_cname_forbid) {
adns__query_fail(qu,adns_s_prohibitedcname);
(qu->typei->type & adns__rrt_typemask) != adns_r_cname) {
if (qu->flags & adns_qf_cname_forbid) {
adns__query_fail(qu,adns_s_prohibitedcname);
if (!qu->vb.used) goto x_truncated;
if (st) { adns__query_fail(qu,st); return; }
l= strlen(qu->vb.buf)+1;
if (!qu->vb.used) goto x_truncated;
if (st) { adns__query_fail(qu,st); return; }
l= strlen(qu->vb.buf)+1;
if (!qu->answer->cname) { adns__query_fail(qu,adns_s_nomemory); return; }
qu->cname_dgram= adns__alloc_mine(qu,dglen);
if (!qu->answer->cname) { adns__query_fail(qu,adns_s_nomemory); return; }
qu->cname_dgram= adns__alloc_mine(qu,dglen);
/* If we find the answer section truncated after this point we restart
* the query at the CNAME; if beforehand then we obviously have to use
* TCP. If there is no truncation we can use the whole answer if
/* If we find the answer section truncated after this point we restart
* the query at the CNAME; if beforehand then we obviously have to use
* TCP. If there is no truncation we can use the whole answer if
for (rri= 0; rri<nscount; rri++) {
rrstart= cbyte;
st= adns__findrr(qu,serv, dgram,dglen,&cbyte,
for (rri= 0; rri<nscount; rri++) {
rrstart= cbyte;
st= adns__findrr(qu,serv, dgram,dglen,&cbyte,
- &rrtype,&rrclass,&rdlength,&rdstart, 0);
+ &rrtype,&rrclass,&ttl, &rdlength,&rdstart, 0);
if (st) { adns__query_fail(qu,st); return; }
if (rrtype==-1) goto x_truncated;
if (rrclass != DNS_CLASS_IN) {
if (st) { adns__query_fail(qu,st); return; }
if (rrtype==-1) goto x_truncated;
if (rrclass != DNS_CLASS_IN) {
+
+ if (rcode == rcode_nxdomain) {
+ /* We still wanted to look for the SOA so we could find the TTL. */
+ adns__update_expires(qu,soattl,now);
+
+ if (qu->flags & adns_qf_search) {
+ adns__search_next(ads,qu,now);
+ } else {
+ adns__query_fail(qu,adns_s_nxdomain);
+ }
+ return;
+ }
if (foundsoa || !foundns) {
/* Aha ! A NODATA response, good. */
if (foundsoa || !foundns) {
/* Aha ! A NODATA response, good. */
for (rri=0, nrrs=0; rri<ancount; rri++) {
st= adns__findrr(qu,serv, dgram,dglen,&cbyte,
for (rri=0, nrrs=0; rri<ancount; rri++) {
st= adns__findrr(qu,serv, dgram,dglen,&cbyte,
- &rrtype,&rrclass,&rdlength,&rdstart,
+ &rrtype,&rrclass,&ttl, &rdlength,&rdstart,
&ownermatched);
assert(!st); assert(rrtype != -1);
if (rrclass != DNS_CLASS_IN ||
rrtype != (qu->typei->type & adns__rrt_typemask) ||
!ownermatched)
continue;
&ownermatched);
assert(!st); assert(rrtype != -1);
if (rrclass != DNS_CLASS_IN ||
rrtype != (qu->typei->type & adns__rrt_typemask) ||
!ownermatched)
continue;
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;
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 (qu->cname_dgram) {
st= adns__mkquery_frdgram(qu->ads,&qu->vb,&qu->id,
qu->cname_dgram, qu->cname_dglen, qu->cname_begin,
if (qu->cname_dgram) {
st= adns__mkquery_frdgram(qu->ads,&qu->vb,&qu->id,
qu->cname_dgram, qu->cname_dglen, qu->cname_begin,
- adns__reset_cnameonly(qu);
- adns__query_udp(qu,now);
+ if (qu->state == query_tcpsent) qu->state= query_tosend;
+ adns__reset_preserved(qu);
+ adns__query_send(qu,now);