+++ /dev/null
-
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include <sys/uio.h>
void **context_r);
/* Might return EINTR - if so, try again */
-void adns_cancel(adns_state ads, adns_query query);
+void adns_cancel(adns_query query);
int adns_finish(adns_state);
/* You may call this even if you have queries outstanding;
qu->tcpfailed |= (1<<serv);
if (qu->tcpfailed == (1<<ads->nservers)-1) {
LIST_UNLINK(ads->timew,qu);
- adns__query_fail(ads,qu,adns_s_allservfail);
+ adns__query_fail(qu,adns_s_allservfail);
}
}
nqu= qu->next;
if (qu->state == query_udp) continue;
assert (qu->state == query_tcpwait);
- adns__query_tcp(ads,qu,now);
+ adns__query_tcp(qu,now);
}
}
if (timercmp(&now,&qu->timeout,>)) {
LIST_UNLINK(ads->timew,qu);
if (qu->state != query_udp) {
- adns__query_fail(ads,qu,adns_s_timeout);
+ adns__query_fail(qu,adns_s_timeout);
} else {
- adns__query_udp(ads,qu,now);
+ adns__query_udp(qu,now);
}
} else {
inter_maxtoabs(tv_io,tvbuf,now,qu->timeout);
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
+#include <stdlib.h>
+
+#include <arpa/inet.h>
+
#include "internal.h"
/* Core diagnostic functions */
void adns__vdiag(adns_state ads, const char *pfx, adns_initflags prevent,
- int serv, const char *fmt, adns_query qu, va_list al) {
+ int serv, adns_query qu, const char *fmt, va_list al) {
const char *bef, *aft;
vbuf vb;
if (!(ads->iflags & adns_if_debug) && (!prevent || (ads->iflags & prevent))) return;
adns__vbuf_init(&vb);
fprintf(stderr,"%sQNAME=%s, QTYPE=%s",
bef,
- adns__diag_domain(ads,-1,0,&vb,qu->query_dgram,qu->query_dglen,DNS_HDRSIZE),
+ adns__diag_domain(qu->ads,-1,0, &vb,qu->flags,
+ qu->query_dgram,qu->query_dglen,DNS_HDRSIZE),
qu->typei ? qu->typei->name : "<unknown>");
bef=", "; aft=")\n";
}
int flags, const byte *dgram, int dglen, int cbyte) {
adns_status st;
- st= adns__parse_domain(ads,serv,vb,qu->flags, dgram,dglen, &cbyte,dglen);
- if (st == adns_s_nomemory) {
+ st= adns__parse_domain(ads,serv,qu,vb, flags,dgram,dglen,&cbyte,dglen);
+ if (st == adns_s_nolocalmem) {
return "<cannot report domain... out of memory>";
}
if (st) {
return "<cannot report bad format... out of memory>";
}
}
- if (!vb.used) {
+ if (!vb->used) {
adns__vbuf_appendstr(vb,"<truncated ...>");
adns__vbuf_append(vb,"",1);
}
const char *name;
int rrsz;
- adns_status (*parse)(adns_state ads, adns_query qu, int serv,
+ adns_status (*parse)(adns_query qu, int serv,
const byte *dgram, int dglen, int cbyte, int max,
void *store_r);
/* Parse one RR, in dgram of length dglen, starting at cbyte and
* *rdstart to -1; otherwise it may set it to anything else positive.
*/
- void (*makefinal)(adns_state ads, adns_query qu, void *data);
+ void (*makefinal)(adns_query qu, void *data);
/* Change memory management of *data.
* Previously, used alloc_interim, now use alloc_final.
*/
} data;
struct adns__query {
+ adns_state ads;
enum { query_udp, query_tcpwait, query_tcpsent, query_child, query_done } state;
adns_query back, next, parent;
struct { adns_query head, tail; } children;
byte *cname_dgram;
int cname_dglen, cname_begin;
+ /* If non-0, has been allocated using . */
int id, flags, udpretries;
int udpnextserver;
* printing it as. Never fails - if an error occurs, it will
* return some kind of string describing the error.
*
- * serv may be -1, qu may be 0. vb must have been initialised,
+ * serv may be -1 and qu may be 0. vb must have been initialised,
* and will be left in an arbitrary consistent state.
*
* Returns either vb->buf, or a pointer to a string literal. Do not modify
/* From transmit.c: */
-adns_status adns__mkquery(adns_state ads, vbuf *vb,
- const char *owner, int ol, int *id_r,
+adns_status adns__mkquery(adns_state ads, vbuf *vb, int *id_r,
+ const char *owner, int ol,
const typeinfo *typei, adns_queryflags flags);
/* Assembles a query packet in vb, and returns id at *id_r. */
-void adns__query_tcp(adns_state ads, adns_query qu, struct timeval now);
+void adns__query_tcp(adns_query qu, struct timeval now);
/* Query must be in state tcpwait/timew; it will be moved to a new state
* if possible and no further processing can be done on it for now.
* (Resulting state is one of tcpwait/timew (if server not connected),
* reestablishment and retry.
*/
-void adns__query_udp(adns_state ads, adns_query qu, struct timeval now);
+void adns__query_udp(adns_query qu, struct timeval now);
/* Query must be in state udp/NONE; it will be moved to a new state,
* and no further processing can be done on it for now.
* (Resulting state is one of udp/timew, tcpwait/timew (if server not connected),
/* From query.c: */
int adns__internal_submit(adns_state ads, adns_query *query_r,
- adns_rrtype type, vbuf *qumsg_vb, int id,
+ const typeinfo *typei, vbuf *qumsg_vb, int id,
adns_queryflags flags, struct timeval now,
adns_status failstat, const qcontext *ctx);
/* Submits a query (for internal use, called during external submits).
* so nothing more need be done with it.
*/
+void *adns__alloc_mine(adns_query qu, size_t sz);
+/* Like _interim, but does not record the length for later
+ * copying into the answer. This just ensures that the memory
+ * will be freed when we're done with the query.
+ */
+
void *adns__alloc_final(adns_query qu, size_t sz);
/* Cannot fail.
*/
void adns__makefinal_block(adns_query qu, void **blpp, size_t sz);
void adns__makefinal_str(adns_query qu, char **strp);
-void adns__reset_cnameonly(adns_state ads, adns_query qu);
+void adns__reset_cnameonly(adns_query qu);
/* Resets all of the memory management stuff etc. to
* take account of only the CNAME. Used when we find an error somewhere
* and want to just report the error (with perhaps CNAME info), and also
* need to retry the query.
*/
-void adns__query_done(adns_state ads, adns_query qu);
-void adns__query_fail(adns_state ads, adns_query qu, adns_status stat);
+void adns__query_done(adns_query qu);
+void adns__query_fail(adns_query qu, adns_status stat);
/* From reply.c: */
typedef struct {
adns_state ads;
+ adns_query qu;
int serv;
const byte *dgram;
int dglen, max, cbyte, namelen;
- int *dmend_rlater, *namelen_rlater;
+ int *dmend_r;
} findlabel_state;
-void adns__findlabel_start(findlabel_state *fls,
- adns_state ads, int serv,
+void adns__findlabel_start(findlabel_state *fls, adns_state ads,
+ int serv, adns_query qu,
const byte *dgram, int dglen, int max,
int dmbegin, int *dmend_rlater);
/* Finds labels in a domain in a datagram.
*
* Call this routine first.
- * endpoint_rlater may be null.
+ * dmend_rlater may be null. ads (and of course fls) may not be.
+ * serv may be -1, qu may be null - they are for error reporting.
*/
-adns_status adns__findlabel_next(findlabel_state *fls,
- int *lablen_r, int *labstart_r);
+adns_status adns__findlabel_next(findlabel_state *fls, int *lablen_r, int *labstart_r);
/* Then, call this one repeatedly.
*
* It will return adns_s_ok if all is well, and tell you the length
* Do not then call findlabel_next again.
*/
-adns_status adns__parse_domain(adns_state ads, int serv, vbuf *vb,
- const byte *dgram, int dglen,
- int *cbyte_io, int max);
+adns_status adns__parse_domain(adns_state ads, int serv, adns_query qu,
+ vbuf *vb, int flags,
+ const byte *dgram, int dglen, int *cbyte_io, int max);
/* vb must already have been initialised; it will be reset if necessary.
* If there is truncation, vb->used will be set to 0; otherwise
* (if there is no error) vb will be null-terminated.
* If there is an error vb and *cbyte_io may be left indeterminate.
+ *
+ * serv may be -1 and qu may be 0 - they are used for error reporting only.
*/
-adns_status adns__findrr(adns_state ads, int serv,
+adns_status adns__findrr(adns_query qu, int serv,
const byte *dgram, int dglen, int *cbyte_io,
int *type_r, int *class_r, int *rdlen_r, int *rdstart_r,
- const byte *eo_dgram, int eo_dglen, int eo_cbyte,
- int *eo_matched_r);
+ int *ownermatchedquery_r);
/* Finds the extent and some of the contents of an RR in a datagram
* and does some checks. The datagram is *dgram, length dglen, and
* the RR starts at *cbyte_io (which is updated afterwards to point
* the corresponding pointer variables are not null. type_r and
* class_r may not be null.
*
- * If the caller thinks they know what the owner of the RR ought to
- * be they can pass in details in eo_*: this is another (or perhaps
- * the same datagram), and a pointer to where the putative owner
- * starts in that datagram. In this case *eo_matched_r will be set
- * to 1 if the datagram matched or 0 if it did not. Either
- * both eo_dgram and eo_matched_r must both be non-null, or they
- * must both be null (in which case eo_dglen and eo_cbyte will be ignored).
- * The eo datagram and contained owner domain MUST be valid and
- * untruncated.
+ * If ownermatchedquery_r != 0 then the owner domain of this
+ * RR will be compared with that in the query (or, if the query
+ * has gone to a CNAME lookup, with the canonical name).
+ * In this case, *ownermatchedquery_r will be set to 0 or 1.
+ * The query datagram (or CNAME datagram) MUST be valid and not truncated.
*
* If there is truncation then *type_r will be set to -1 and
* *cbyte_io, *class_r, *rdlen_r, *rdstart_r and *eo_matched_r will be
* undefined.
*
+ * qu must obviously be non-null.
+ *
* If an error is returned then *type_r will be undefined too.
*/
return 1;
}
-void adns__findlabel_start(findlabel_state *fls,
- adns_state ads, int serv,
+void adns__findlabel_start(findlabel_state *fls, adns_state ads,
+ int serv, adns_query qu,
const byte *dgram, int dglen, int max,
int dmbegin, int *dmend_rlater) {
fls->ads= ads;
+ fls->qu= qu;
fls->serv= serv;
fls->dgram= dgram;
fls->dglen= dglen;
fls->cbyte= dmbegin;
fls->namelen= 0;
fls->dmend_r= dmend_rlater;
- fls->namelen_r= namelen_rlater;
}
-adns_status adns__findlabel_next(findlabel_state fls,
+adns_status adns__findlabel_next(findlabel_state *fls,
int *lablen_r, int *labstart_r) {
int lablen, jumped;
+ const char *dgram;
jumped= 0;
+ dgram= fls->dgram;
for (;;) {
- fls->cbyte += 2;
- if (fls->cbyte > fls->dglen) goto x_truncated;
- if (fls->cbyte > fls->max) goto x_serverfaulty;
- GET_W(fls->cbyte-2,lablen);
+ if (fls->cbyte+2 > fls->dglen) goto x_truncated;
+ if (fls->cbyte+2 > fls->max) goto x_serverfaulty;
+ GET_W(fls->cbyte,lablen);
if (!(lablen & 0x0c000)) break;
if ((lablen & 0x0c000) != 0x0c000) return adns_s_unknownreply;
if (jumped++) {
- adns__diag(ads,fls->serv,fls->qu,"compressed datagram contains loop");
+ adns__diag(fls->ads,fls->serv,fls->qu,"compressed datagram contains loop");
return adns_s_serverfaulty;
}
if (fls->dmend_r) *(fls->dmend_r)= fls->cbyte;
if (fls->cbyte > fls->max) goto x_serverfaulty;
} else {
if (fls->dmend_r) *(fls->dmend_r)= fls->cbyte;
- if (fls->namelen_r) *(fls->namelen_r)= fls->namelen;
}
if (labstart_r) *labstart_r= fls->cbyte;
*lablen_r= lablen;
return adns_s_ok;
x_serverfaulty:
- adns__diag(ads,fls->serv,fls->qu,"label in domain runs beyond end of domain");
+ adns__diag(fls->ads,fls->serv,fls->qu,"label in domain runs beyond end of domain");
return adns_s_serverfaulty;
}
-adns_status adns__parse_domain(adns_state ads, int serv, vbuf *vb, int flags,
- const byte *dgram, int dglen,
- int *cbyte_io, int max) {
+adns_status adns__parse_domain(adns_state ads, int serv, adns_query qu,
+ vbuf *vb, int flags,
+ const byte *dgram, int dglen, int *cbyte_io, int max) {
findlabel_state fls;
- int cbyte, lablen, labstart, namelen, i, ch;
+ int lablen, labstart, i, ch;
adns_status st;
- ands__findlabel_start(&fls,ads,serv, dgram,dglen,max, *cbyte_io,cbyte_io);
+ adns__findlabel_start(&fls,ads, serv,qu, dgram,dglen,max, *cbyte_io,cbyte_io);
vb->used= 0;
for (;;) {
st= adns__findlabel_next(&fls,&lablen,&labstart);
if (lablen<0) { vb->used=0; return adns_s_ok; }
if (!lablen) break;
if (vb->used)
- if (!adns__vbuf_append(&qu->ans,".",1)) return adns_s_nolocalmem;
+ if (!adns__vbuf_append(vb,".",1)) return adns_s_nolocalmem;
if (flags & adns_qf_anyquote) {
- if (!vbuf__append_quoted1035(&qu->ans,dgram+labstart,lablen))
+ if (!vbuf__append_quoted1035(vb,dgram+labstart,lablen))
return adns_s_nolocalmem;
} else {
if (!ctype_alpha(dgram[labstart])) return adns_s_invaliddomain;
if (ch != '-' && !ctype_alpha(ch) && !ctype_digit(ch))
return adns_s_invaliddomain;
}
- if (!adns__vbuf_append(&qu->ans,dgram+labstart,lablen))
+ if (!adns__vbuf_append(vb,dgram+labstart,lablen))
return adns_s_nolocalmem;
}
}
- if (!adns__vbuf_append(&qu->ans,"",1)) return adns_s_nolocalmem;
+ if (!adns__vbuf_append(vb,"",1)) return adns_s_nolocalmem;
return adns_s_ok;
}
-adns_status adns__findrr(adns_state ads, int serv,
- const byte *dgram, int dglen, int *cbyte_io,
- int *type_r, int *class_r, int *rdlen_r, int *rdstart_r,
- const byte *eo_dgram, int eo_dglen, int eo_cbyte,
- int *eo_matched_r) {
- /* Finds the extent and some of the contents of an RR in a datagram
- * and does some checks. The datagram is *dgram, length dglen, and
- * the RR starts at *cbyte_io (which is updated afterwards to point
- * to the end of the RR).
- *
- * The type, class and RRdata length and start are returned iff
- * the corresponding pointer variables are not null. type_r and
- * class_r may not be null.
+static adns_status findrr_intern(adns_query qu, int serv,
+ const byte *dgram, int dglen, int *cbyte_io,
+ int *type_r, int *class_r, int *rdlen_r, int *rdstart_r,
+ const byte *eo_dgram, int eo_dglen, int eo_cbyte,
+ int *eo_matched_r) {
+ /* Like adns__findrr_checked, except that the datagram to compare
+ * with can be specified explicitly.
*
* If the caller thinks they know what the owner of the RR ought to
* be they can pass in details in eo_*: this is another (or perhaps
* must both be null (in which case eo_dglen and eo_cbyte will be ignored).
* The eo datagram and contained owner domain MUST be valid and
* untruncated.
- *
- * If there is truncation then *type_r will be set to -1 and
- * *cbyte_io, *class_r, *rdlen_r, *rdstart_r and *eo_matched_r will be
- * undefined.
- *
- * If an error is returned then *type_r will be undefined too.
*/
findlabel_state fls, eo_fls;
int cbyte;
int tmp, rdlen, mismatch;
- int max, lablen, labstart, namelen, ch;
- int eo_max, eo_lablen, eo_labstart, eo_namelen, eo_ch;
+ int lablen, labstart, ch;
+ int eo_lablen, eo_labstart, eo_ch;
adns_status st;
cbyte= *cbyte_io;
- ands__findlabel_start(&fls,ads,serv, dgram,dglen,dglen,cbyte,&cbyte);
+ adns__findlabel_start(&fls,qu->ads, serv,qu, dgram,dglen,dglen,cbyte,&cbyte);
if (eo_dgram) {
- ands__findlabel_start(&eo_fls,ads,serv, eo_dgram,eo_dglen,eo_dglen,eo_cbyte,0);
+ adns__findlabel_start(&eo_fls,qu->ads, -1,0, eo_dgram,eo_dglen,eo_dglen,eo_cbyte,0);
mismatch= 0;
} else {
mismatch= 1;
*type_r= -1;
return 0;;
}
+
+adns_status adns__findrr(adns_query qu, int serv,
+ const byte *dgram, int dglen, int *cbyte_io,
+ int *type_r, int *class_r, int *rdlen_r, int *rdstart_r,
+ int *ownermatchedquery_r) {
+ if (!ownermatchedquery_r) {
+ return findrr_intern(qu,serv,
+ dgram,dglen,cbyte_io,
+ type_r,class_r,rdlen_r,rdstart_r,
+ 0,0,0, 0);
+ } else if (!qu->cname_dgram) {
+ return findrr_intern(qu,serv,
+ dgram,dglen,cbyte_io,
+ type_r,class_r,rdlen_r,rdstart_r,
+ qu->query_dgram,qu->query_dglen,DNS_HDRSIZE,
+ ownermatchedquery_r);
+ } else {
+ return findrr_intern(qu,serv,
+ dgram,dglen,cbyte_io,
+ type_r,class_r,rdlen_r,rdstart_r,
+ qu->cname_dgram,qu->cname_dglen,qu->cname_begin,
+ ownermatchedquery_r);
+ }
+}
#include "internal.h"
int adns__internal_submit(adns_state ads, adns_query *query_r,
- adns_rrtype type, vbuf *qumsg_vb, int id,
+ const typeinfo *typei, vbuf *qumsg_vb, int id,
adns_queryflags flags, struct timeval now,
adns_status failstat, const qcontext *ctx) {
adns_query qu;
- adns_status stat;
- int ol, id, r;
- struct timeval now;
- const typeinfo *typei;
- adns_query qu;
qu= malloc(sizeof(*qu)); if (!qu) goto x_nomemory;
qu->answer= malloc(sizeof(*qu->answer)); if (!qu->answer) goto x_freequ_nomemory;
+ qu->ads= ads;
qu->state= query_udp;
qu->back= qu->next= qu->parent= 0;
LIST_INIT(qu->children);
qu->siblings.next= qu->siblings.back= 0;
qu->allocations= 0;
qu->interim_allocd= 0;
- qu->perm_used= 0;
+ qu->final_allocspace= 0;
- qu->typei= adns__findtype(type);
+ qu->typei= typei;
adns__vbuf_init(&qu->vb);
qu->cname_dgram= 0;
qu->udpsent= qu->tcpfailed= 0;
timerclear(&qu->timeout);
memcpy(&qu->context,ctx,sizeof(qu->context));
- memcpy(qu->owner,owner,ol); qu->owner[ol]= 0;
qu->answer->status= adns_s_ok;
qu->answer->cname= 0;
- qu->answer->type= type;
+ qu->answer->type= typei->type;
qu->answer->nrrs= 0;
qu->answer->rrs= 0;
-
- if (qu->typei) {
- qu->answer->rrsz= qu->rrsz;
- } else {
- qu->answer->rrsz= -1;
- failstat= adns_s_notimplemented;
- }
+ qu->answer->rrsz= typei->rrsz;
*query_r= qu;
qu->query_dgram= malloc(qumsg_vb->used);
if (!qu->query_dgram) {
- adns__query_fail(ads,qu,adns_s_nomemory);
- return;
+ adns__query_fail(qu,adns_s_nolocalmem);
+ return adns_s_ok;
}
memcpy(qu->query_dgram,qumsg_vb->buf,qumsg_vb->used);
qu->vb= *qumsg_vb;
adns__vbuf_init(qumsg_vb);
if (failstat) {
- adns__query_fail(ads,qu,failstat);
- return;
+ adns__query_fail(qu,failstat);
+ return adns_s_ok;
}
- adns__query_udp(ads,qu,now);
+ adns__query_udp(qu,now);
adns__autosys(ads,now);
- return 0;
+ return adns_s_ok;
x_freequ_nomemory:
free(qu);
x_nomemory:
- free(query_dgram);
- return adns_s_nomemory;
+ adns__vbuf_free(qumsg_vb);
+ return adns_s_nolocalmem;
}
int adns_submit(adns_state ads,
void *context,
adns_query *query_r) {
qcontext ctx;
- int id;
+ int id, r, ol;
vbuf vb;
+ adns_status stat;
+ const typeinfo *typei;
+ struct timeval now;
+ typei= adns__findtype(type);
+ if (!typei) return adns_s_notimplemented;
+
ctx.ext= context;
r= gettimeofday(&now,0); if (r) return errno;
id= 0;
if (owner[ol-1]=='.' && owner[ol-2]!='\\') { flags &= ~adns_qf_search; ol--; }
- stat= adns__mkquery(ads,&vb, &id, owner,ol, typei,flags);
+ stat= adns__mkquery(ads,&vb,&id, owner,ol, typei,flags);
xit:
- return adns__internal_submit(ads,query_r, type,&vb,id, flags,now, stat,&ctx);
+ return adns__internal_submit(ads,query_r, typei,&vb,id, flags,now, stat,&ctx);
}
int adns_synchronous(adns_state ads,
do {
r= adns_wait(ads,&qu,answer_r,0);
} while (r==EINTR);
- if (r) adns_cancel(ads,qu);
+ if (r) adns_cancel(qu);
return r;
}
-void adns_cancel(adns_state ads, adns_query query) {
+void adns_cancel(adns_query query) {
abort(); /* fixme */
}
-void *adns__alloc_interim(adns_state ads, adns_query qu, size_t sz) {
+void *adns__alloc_interim(adns_query qu, size_t sz) {
allocnode *an;
assert(!qu->final_allocspace);
sz= MEM_ROUND(sz);
an= malloc(MEM_ROUND(MEM_ROUND(sizeof(*an)) + sz));
if (!an) {
- adns__query_fail(ads,qu,adns_s_nolocalmem);
+ adns__query_fail(qu,adns_s_nolocalmem);
return 0;
}
- qu->permalloclen += sz;
+ qu->interim_allocd += sz;
an->next= qu->allocations;
qu->allocations= an;
return (byte*)an + MEM_ROUND(sizeof(*an));
return rp;
}
-void adns__reset_cnameonly(adns_state ads, adns_query qu) {
+void adns__reset_cnameonly(adns_query qu) {
assert(qu->final_allocspace);
qu->answer->nrrs= 0;
qu->answer->rrs= 0;
qu->interim_allocd= qu->answer->cname ? MEM_ROUND(strlen(qu->answer->cname)+1) : 0;
}
-static void adns__query_done(adns_state ads, adns_query qu) {
+void adns__query_done(adns_query qu) {
adns_answer *ans;
allocnode *an, *ann;
int i;
if (ans->nrrs) {
adns__makefinal_block(qu,&ans->rrs.untyped,ans->rrsz*ans->nrrs);
for (i=0; i<ans->nrrs; i++)
- qu->typei->makefinal(ads,qu,ans->rrs.bytes+ans->rrsz*i);
+ qu->typei->makefinal(qu,ans->rrs.bytes+ans->rrsz*i);
}
for (an= qu->allocations; an; an= ann) { ann= an->next; free(an); }
adns__vbuf_free(&qu->vb);
qu->id= -1;
- LIST_LINK_TAIL(ads->output,qu);
+ LIST_LINK_TAIL(qu->ads->output,qu);
}
-void adns__query_fail(adns_state ads, adns_query qu, adns_status stat) {
- adns__reset_cnameonly(ads,qu);
+void adns__query_fail(adns_query qu, adns_status stat) {
+ adns__reset_cnameonly(qu);
qu->answer->status= stat;
- adns__query_done(ads,qu);
+ adns__query_done(qu);
}
void adns__makefinal_str(adns_query qu, char **strp) {
*strp= after;
}
-void adns__makefinal_block(adns__query qu, void **blpp, size_t sz) {
+void adns__makefinal_block(adns_query qu, void **blpp, size_t sz) {
void *after;
after= adns__alloc_final(qu,sz);
#include "internal.h"
-static void cname_recurse(adns_state ads, adns_query qu, adns_queryflags xflags) {
+static void cname_recurse(adns_query qu, adns_queryflags xflags) {
abort(); /* FIXME */
}
void adns__procdgram(adns_state ads, const byte *dgram, int dglen,
int serv, struct timeval now) {
int cbyte, rrstart, wantedrrs, rri, foundsoa, foundns;
- int id, f1, f2, qdcount, ancount, nscount, arcount, flg_ra, flg_rd, flg_tc, opcode;
- int rrtype, rrclass, rdlength, rdstart, ownermatched, ownerstart;
+ int id, f1, f2, qdcount, ancount, nscount, arcount;
+ int flg_ra, flg_rd, flg_tc, flg_qr, opcode;
+ int rrtype, rrclass, rdlength, rdstart, ownermatched, l;
int anstart, nsstart, arstart;
- int currentrrs;
adns_query qu, nqu;
dns_rcode rcode;
adns_status st;
if (dglen<DNS_HDRSIZE) {
- adns__diag(ads,serv,"received datagram too short for message header (%d)",dglen);
+ adns__diag(ads,serv,0,"received datagram too short for message header (%d)",dglen);
return;
}
GET_W(cbyte,id);
rcode= (f1&0x0f);
if (flg_qr) {
- adns__diag(ads,serv,"server sent us a query, not a response");
+ adns__diag(ads,serv,0,"server sent us a query, not a response");
return;
}
if (opcode) {
- adns__diag(ads,serv,"server sent us unknown opcode %d (wanted 0=QUERY)",opcode);
+ adns__diag(ads,serv,0,"server sent us unknown opcode %d (wanted 0=QUERY)",opcode);
return;
}
if (!qdcount) {
- adns__diag(ads,serv,"server sent reply without quoting our question");
+ adns__diag(ads,serv,0,"server sent reply without quoting our question");
return;
} else if (qdcount>1) {
- adns__diag(ads,serv,"server claimed to answer %d questions with one message",
+ adns__diag(ads,serv,0,"server claimed to answer %d questions with one message",
qdcount);
return;
}
for (qu= ads->timew.head; qu; qu= nqu) {
nqu= qu->next;
if (qu->id != id) continue;
- if (dglen < qu->querylen) continue;
- if (memcmp(qu->querymsg+DNS_HDRSIZE,dgram+DNS_HDRSIZE,qu->querylen-DNS_HDRSIZE))
+ if (dglen < qu->query_dglen) continue;
+ if (memcmp(qu->query_dgram+DNS_HDRSIZE,
+ dgram+DNS_HDRSIZE,
+ qu->query_dglen-DNS_HDRSIZE))
continue;
break;
}
- assert(qu->cnameoff == -1);
- anstart= qu->querylen;
+ anstart= qu->query_dglen;
if (!qu) {
- adns__debug(ads,serv,"reply not found (id=%02x)",id);
+ adns__debug(ads,serv,0,"reply not found (id=%02x)",id);
return;
}
break;
case rcode_formaterror:
adns__warn(ads,serv,qu,"server cannot understand our query (Format Error)");
- adns__query_fail(ads,qu,adns_s_serverfaulty);
+ adns__query_fail(qu,adns_s_serverfaulty);
return;
case rcode_servfail:
- adns__query_fail(ads,qu,adns_s_servfail);
+ adns__query_fail(qu,adns_s_servfail);
return;
case rcode_notimp:
adns__warn(ads,serv,qu,"server claims not to implement our query");
- adns__query_fail(ads,qu,adns_s_notimplemented);
+ adns__query_fail(qu,adns_s_notimplemented);
return;
case rcode_refused:
adns__warn(ads,serv,qu,"server refused our query");
- adns__query_fail(ads,qu,adns_s_refused);
+ adns__query_fail(qu,adns_s_refused);
return;
default:
adns__warn(ads,serv,qu,"server gave unknown response code %d",rcode);
- adns__query_fail(ads,qu,adns_s_reasonunknown);
+ adns__query_fail(qu,adns_s_reasonunknown);
return;
}
wantedrrs= 0;
for (rri= 0; rri<ancount; rri++) {
rrstart= cbyte;
- if (qu->cname_dgram >= 0) {
- st= adns__findrr(ads,serv, dgram,dglen,&cbyte,
- &rrtype,&rrclass,&rdlength,&rdstart,
- qu->cname_dgram,qu->cname_dglen,qu->cname_begin, &ownermatched);
- } else {
- st= adns__findrr(ads,serv, dgram,dglen,&cbyte,
- &rrtype,&rrclass,&rdlength,&rdstart,
- qu->querymsg,qu->querylen,DNS_HDRSIZE, &ownermatched);
- }
- if (st) adns__query_fail(ads,qu,st);
+ st= adns__findrr(qu,serv, dgram,dglen,&cbyte,
+ &rrtype,&rrclass,&rdlength,&rdstart,
+ &ownermatched);
+ if (st) adns__query_fail(qu,st);
if (rrtype == -1) goto x_truncated;
if (rrclass != DNS_CLASS_IN) {
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->vb,qu->flags,
- dgram,dglen,rrstart,dglen));
+ adns__diag_domain(ads,serv,qu, &qu->vb,qu->flags,
+ dgram,dglen,rrstart));
}
continue;
}
if (rrtype == adns_r_cname &&
(qu->typei->type & adns__rrt_typemask) != adns_r_cname) {
- if (!qu->cname_str) { /* Ignore second and subsequent CNAMEs */
+ if (!qu->cname_dgram) { /* Ignore second and subsequent CNAMEs */
+ qu->cname_dgram= adns__alloc_mine(qu,dglen);
+ if (!qu->cname_dgram) return;
qu->cname_begin= rdstart;
- qu->cname_dgram= dgram;
qu->cname_dglen= dglen;
- st= adns__parse_domain(ads,serv,&qu->vb,qu->flags,
+ st= adns__parse_domain(ads,serv,qu, &qu->vb,qu->flags,
dgram,dglen, &rdstart,rdstart+rdlength);
- if (!vb.used) goto x_truncated;
- if (st) { adns__query_fail(ads,qu,st); return; }
- qu->answer->cname= adns__savestring(qu);
+ 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) return;
+ memcpy(qu->answer->cname,qu->vb.buf,l);
/* 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
*/
} else {
adns__debug(ads,serv,qu,"ignoring duplicate CNAME (%s, as well as %s)",
- adns__diag_domain(ads,serv,&qu->vb,qu->flags,
- dgram,dglen, rdstart,rdstart+rdlength),
- qu->cname_str);
+ adns__diag_domain(ads,serv,qu, &qu->vb,qu->flags,
+ dgram,dglen,rdstart),
+ qu->answer->cname);
}
} else if (rrtype == (qu->typei->type & adns__rrt_typemask)) {
wantedrrs++;
/* Oops, NODATA or NXDOMAIN or perhaps a referral (which would be a problem) */
if (rcode == rcode_nxdomain) {
- adns__query_finish(ads,qu,adns_s_nxdomain);
+ adns__query_fail(qu,adns_s_nxdomain);
return;
}
foundsoa= 0; foundns= 0;
for (rri= 0; rri<nscount; rri++) {
rrstart= cbyte;
- st= adns__findrr(ads,serv, dgram,dglen,&cbyte,
- &rrtype,&rrclass,&rdlength,&rdstart,
- 0,0,0,0);
- if (st) { adns__query_fail(ads,qu,st); return; }
+ st= adns__findrr(qu,serv, dgram,dglen,&cbyte,
+ &rrtype,&rrclass,&rdlength,&rdstart, 0);
+ if (st) { adns__query_fail(qu,st); return; }
if (rrtype==-1) goto x_truncated;
if (rrclass != DNS_CLASS_IN) {
adns__diag(ads,serv,qu,
if (foundsoa || !foundns) {
/* Aha ! A NODATA response, good. */
- adns__query_finish(ads,qu,adns_s_nodata);
+ adns__query_fail(qu,adns_s_nodata);
return;
}
* a CNAME in this datagram then we should probably do our own CNAME
* lookup now in the hope that we won't get a referral again.
*/
- if (qu->cname_dgram == dgram) { cname_recurse(ads,qu,0); return; }
+ if (qu->cname_dgram == dgram) { cname_recurse(qu,0); return; }
/* Bloody hell, I thought we asked for recursion ? */
if (flg_rd) {
}
if (!flg_ra) {
adns__diag(ads,serv,qu,"server is not willing to do recursive lookups for us");
- adns__query_fail(ads,qu,adns_s_norecurse);
+ 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(ads,qu,adns_s_serverfaulty);
+ adns__query_fail(qu,adns_s_serverfaulty);
}
return;
}
/* Now, we have some RRs which we wanted. */
- qu->ans->rrs= adns__alloc_interim(qu,qu->typei->rrsz*wantedrrs);
- if (!qu->ans->rrs) return;
+ qu->answer->rrs.untyped= adns__alloc_interim(qu,qu->typei->rrsz*wantedrrs);
+ if (!qu->answer->rrs.untyped) return;
cbyte= anstart;
arstart= -1;
for (rri=0; rri<ancount; rri++) {
- if (qu->cname_dgram >= 0) {
- st= adns__findrr(ads,serv, dgram,dglen,&cbyte,
- &rrtype,&rrclass,&rdlength,&rdstart,
- qu->cname_dgram,qu->cname_dglen,qu->cname_begin, &ownermatched);
- } else {
- st= adns__findrr(ads,serv, dgram,dglen,&cbyte,
- &rrtype,&rrclass,&rdlength,&rdstart,
- qu->querymsg,qu->querylen,DNS_HDRSIZE, &ownermatched);
- }
+ st= adns__findrr(qu,serv, dgram,dglen,&cbyte,
+ &rrtype,&rrclass,&rdlength,&rdstart,
+ &ownermatched);
assert(!st); assert(rrtype != -1);
if (rrclass != DNS_CLASS_IN ||
rrtype != (qu->typei->type & adns__rrt_typemask) ||
!ownermatched)
continue;
- assert(qu->ans->nrrs<wantedrrs);
- st= qu->typei->parse(ads,qu,serv,
- dgram,dglen, &rdstart,rdstart+rdlength,
- qu->ans->rrs.bytes+qu->ans->nrrs*quj->typei->rrsz);
- if (st) { adns__query_fail(ads,qu,st); return; }
+ assert(qu->answer->nrrs<wantedrrs);
+ st= qu->typei->parse(qu,serv,
+ dgram,dglen, rdstart,rdstart+rdlength,
+ qu->answer->rrs.bytes+qu->answer->nrrs*qu->typei->rrsz);
+ if (st) { adns__query_fail(qu,st); return; }
if (rdstart==-1) goto x_truncated;
}
return;
}
- adns__query_finish(ads,qu,adns_s_ok);
+ adns__query_done(qu);
return;
x_truncated:
if (!flg_tc) {
adns__diag(ads,serv,qu,"server sent datagram which points outside itself");
- adns__query_fail(ads,qu,adns_s_serverfaulty);
+ adns__query_fail(qu,adns_s_serverfaulty);
return;
}
- if (qu->cname_dgram) { cname_recurse(ads,qu,adns_qf_usevc); return; }
- adns__reset_cnameonly(ads,qu);
+ if (qu->cname_dgram) { cname_recurse(qu,adns_qf_usevc); return; }
+ adns__reset_cnameonly(qu);
qu->flags |= adns_qf_usevc;
- adns__query_udp(ads,qu,now);
+ adns__query_udp(qu,now);
}
for (i=0; i<ads->nservers; i++) {
if (ads->servers[i].addr.s_addr == addr.s_addr) {
- adns__debug(ads,-1,"duplicate nameserver %s ignored",inet_ntoa(addr));
+ adns__debug(ads,-1,0,"duplicate nameserver %s ignored",inet_ntoa(addr));
return;
}
}
if (ads->nservers>=MAXSERVERS) {
- adns__diag(ads,-1,"too many nameservers, ignoring %s",inet_ntoa(addr));
+ adns__diag(ads,-1,0,"too many nameservers, ignoring %s",inet_ntoa(addr));
return;
}
configparseerr(ads,fn,lno,"invalid nameserver address `%s'",buf);
return;
}
- adns__debug(ads,-1,"using nameserver %s",inet_ntoa(ia));
+ adns__debug(ads,-1,0,"using nameserver %s",inet_ntoa(ia));
addserver(ads,ia);
}
static void ccf_search(adns_state ads, const char *fn, int lno, const char *buf) {
if (!buf) return;
- adns__diag(ads,-1,"warning - `search' ignored fixme");
+ adns__diag(ads,-1,0,"warning - `search' ignored fixme");
}
static void ccf_sortlist(adns_state ads, const char *fn, int lno, const char *buf) {
- adns__diag(ads,-1,"warning - `sortlist' ignored fixme");
+ adns__diag(ads,-1,0,"warning - `sortlist' ignored fixme");
}
static void ccf_options(adns_state ads, const char *fn, int lno, const char *buf) {
if (!buf) return;
- adns__diag(ads,-1,"warning - `options' ignored fixme");
+ adns__diag(ads,-1,0,"warning - `options' ignored fixme");
}
static void ccf_clearnss(adns_state ads, const char *fn, int lno, const char *buf) {
file= fopen(filename,"r");
if (!file) {
if (errno == ENOENT) {
- adns__debug(ads,-1,"configuration file `%s' does not exist",filename);
+ adns__debug(ads,-1,0,"configuration file `%s' does not exist",filename);
return;
}
- adns__diag(ads,-1,"cannot open configuration file `%s': %s",
+ adns__diag(ads,-1,0,"cannot open configuration file `%s': %s",
filename,strerror(errno));
return;
}
l= strlen(linebuf);
if (!l) continue;
if (linebuf[l-1] != '\n' && !feof(file)) {
- adns__diag(ads,-1,"%s:%d: line too long",filename,lno);
+ adns__diag(ads,-1,0,"%s:%d: line too long",filename,lno);
while ((c= getc(file)) != EOF && c != '\n') { }
if (c == EOF) break;
continue;
ccip->name && strncmp(ccip->name,p,q-p);
ccip++);
if (!ccip->name) {
- adns__diag(ads,-1,"%s:%d: unknown configuration directive `%.*s'",
+ adns__diag(ads,-1,0,"%s:%d: unknown configuration directive `%.*s'",
filename,lno,q-p,p);
continue;
}
ccip->fn(ads,filename,lno,q);
}
if (ferror(file)) {
- adns__diag(ads,-1,"%s:%d: read error: %s",filename,lno,strerror(errno));
+ adns__diag(ads,-1,0,"%s:%d: read error: %s",filename,lno,strerror(errno));
}
fclose(file);
}
const char *value;
value= getenv(envvar);
- if (!value) adns__debug(ads,-1,"environment variable %s not set",envvar);
- else adns__debug(ads,-1,"environment variable %s set to `%s'",envvar,value);
+ if (!value) adns__debug(ads,-1,0,"environment variable %s not set",envvar);
+ else adns__debug(ads,-1,0,"environment variable %s set to `%s'",envvar,value);
return value;
}
const char *filename;
if (ads->iflags & adns_if_noenv) {
- adns__debug(ads,-1,"not checking environment variable `%s'",envvar);
+ adns__debug(ads,-1,0,"not checking environment variable `%s'",envvar);
return;
}
filename= instrum_getenv(ads,envvar);
LIST_INIT(ads->output);
ads->nextid= 0x311f;
ads->udpsocket= ads->tcpsocket= -1;
- adns__vbuf_init(&ads->rqbuf);
adns__vbuf_init(&ads->tcpsend);
adns__vbuf_init(&ads->tcprecv);
ads->nservers= ads->tcpserver= 0;
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
+#include <errno.h>
+#include <string.h>
+
+#include <sys/uio.h>
+
#include "internal.h"
-adns_status adns__mkquery(adns_state ads, vbuf *vb,
- const char *owner, int ol, int *id_r,
+adns_status adns__mkquery(adns_state ads, vbuf *vb, int *id_r,
+ const char *owner, int ol,
const typeinfo *typei, adns_queryflags flags) {
int ll, c, nlabs, id;
byte label[255], *rqp;
return adns_s_ok;
}
-void adns__query_tcp(adns_state ads, adns_query qu, struct timeval now) {
+void adns__query_tcp(adns_query qu, struct timeval now) {
byte length[2];
struct iovec iov[2];
int wr, r;
+ adns_state ads;
- if (ads->tcpstate != server_ok) return;
+ if (qu->ads->tcpstate != server_ok) return;
length[0]= (qu->query_dglen&0x0ff00U) >>8;
length[1]= (qu->query_dglen&0x0ff);
-
+
+ ads= qu->ads;
if (!adns__vbuf_ensure(&ads->tcpsend,ads->tcpsend.used+qu->query_dglen+2)) return;
timevaladd(&now,TCPMS);
iov[0].iov_len= 2;
iov[1].iov_base= qu->query_dgram;
iov[1].iov_len= qu->query_dglen;
- wr= writev(ads->tcpsocket,iov,2);
+ wr= writev(qu->ads->tcpsocket,iov,2);
if (wr < 0) {
if (!(errno == EAGAIN || errno == EINTR || errno == ENOSPC ||
errno == ENOBUFS || errno == ENOMEM)) {
}
}
-static void query_usetcp(adns_state ads, adns_query qu, struct timeval now) {
+static void query_usetcp(adns_query qu, struct timeval now) {
timevaladd(&now,TCPMS);
qu->timeout= now;
qu->state= query_tcpwait;
- LIST_LINK_TAIL(ads->timew,qu);
- adns__query_tcp(ads,qu,now);
- adns__tcp_tryconnect(ads,now);
+ LIST_LINK_TAIL(qu->ads->timew,qu);
+ adns__query_tcp(qu,now);
+ adns__tcp_tryconnect(qu->ads,now);
}
-void adns__query_udp(adns_state ads, adns_query qu, struct timeval now) {
+void adns__query_udp(adns_query qu, struct timeval now) {
struct sockaddr_in servaddr;
int serv, r;
+ adns_state ads;
assert(qu->state == query_udp);
if ((qu->flags & adns_qf_usevc) || (qu->query_dglen > DNS_MAXUDP)) {
- query_usetcp(ads,qu,now);
+ query_usetcp(qu,now);
return;
}
if (qu->udpretries >= UDPMAXRETRIES) {
- adns__query_fail(ads,qu,adns_s_timeout);
+ adns__query_fail(qu,adns_s_timeout);
return;
}
serv= qu->udpnextserver;
memset(&servaddr,0,sizeof(servaddr));
+
+ ads= qu->ads;
servaddr.sin_family= AF_INET;
servaddr.sin_addr= ads->servers[serv].addr;
servaddr.sin_port= htons(DNS_PORT);
r= sendto(ads->udpsocket,qu->query_dgram,qu->query_dglen,0,&servaddr,sizeof(servaddr));
- if (r<0 && errno == EMSGSIZE) { query_usetcp(ads,qu,now); return; }
+ if (r<0 && errno == EMSGSIZE) { query_usetcp(qu,now); return; }
if (r<0) adns__warn(ads,serv,0,"sendto failed: %s",strerror(errno));
timevaladd(&now,UDPRETRYMS);