-Wcast-qual -Wpointer-arith
WERROR=-Werror
-LIBOBJS= event.o query.o setup.o transmit.o general.o reply.o parse.o types.o
+LIBOBJS= event.o types.o reply.o query.o setup.o transmit.o parse.o general.o
ALLOBJS= $(LIBOBJS) dtest.o
all: dtest
clean:
rm -f dtest *.o
-dtest.o: adns.h
$(LIBOBJS): adns.h internal.h
+dtest.o: adns.h
-Wcast-qual -Wpointer-arith
WERROR=-Werror
-LIBOBJS= event.o query.o setup.o transmit.o general.o reply.o parse.o types.o
+LIBOBJS= event.o types.o reply.o query.o setup.o transmit.o parse.o general.o
ALLOBJS= $(LIBOBJS) dtest.o
all: dtest
clean:
rm -f dtest *.o
-dtest.o: adns.h
$(LIBOBJS): adns.h internal.h
+dtest.o: adns.h
* Copyright (C)1998 Ian Jackson.
* This version provided for review and comment only.
*
- * $Id: adns.h,v 1.28 1998/11/14 14:21:50 ian Exp $
+ * $Id: adns.h,v 1.29 1998/11/14 15:24:56 ian Exp $
*/
/*
* This file is part of adns, which is Copyright (C) 1997, 1998 Ian Jackson
adns_if_noserverwarn= 0x0004, /* do not warn to stderr about duff nameservers etc */
adns_if_debug= 0x0008, /* enable all output to stderr plus debug msgs */
adns_if_noautosys= 0x0010, /* do not make syscalls at every opportunity */
+ adns_if_eintr= 0x0020, /* allow _wait and _synchronous to return EINTR */
} adns_initflags;
typedef enum {
adns_rrtype type,
adns_queryflags flags,
adns_answer **answer_r);
-/* Will not return EINTR. */
/* NB: if you set adns_if_noautosys then _submit and _check do not
* make any system calls; you must use adns_callback (possibly after
adns_query *query_io,
adns_answer **answer_r,
void **context_r);
-/* Might return EINTR - if so, try again */
void adns_cancel(adns_query query);
FD_ZERO(&readfds); FD_ZERO(&writefds); FD_ZERO(&exceptfds);
adns_interest(ads,&maxfd,&readfds,&writefds,&exceptfds,&tvp,&tvbuf);
rsel= select(maxfd,&readfds,&writefds,&exceptfds,tvp);
- if (rsel==-1) return r;
+ if (rsel==-1) {
+ if (errno == EINTR && !(ads->iflags & adns_if_eintr)) continue;
+ return errno;
+ }
rcb= adns_callback(ads,maxfd,&readfds,&writefds,&exceptfds);
assert(rcb==rsel);
}
*/
#include <stdlib.h>
+#include <string.h>
#include <arpa/inet.h>
snprintf(buf,sizeof(buf),"code %d",st);
return buf;
}
+
+void adns__isort(void *array, int nobjs, int sz, void *tempbuf,
+ int (*needswap)(const void *a, const void *b)) {
+ byte *data= array;
+ int i, place;
+
+ for (i=0; i<nobjs; i++) {
+ for (place= i; place>0 && needswap(data + (place-1)*sz, data + i*sz); place--);
+
+ if (place != i) {
+ memcpy(tempbuf, data + i*sz, sz);
+ memmove(data + (place+1)*sz, data + place*sz, (i-place)*sz);
+ memcpy(data + place*sz, tempbuf, sz);
+ }
+ }
+}
adns_status (*parse)(adns_query qu, int serv,
const byte *dgram, int dglen, int cbyte, int max,
- void *store_r);
+ int nsstart, int *arstart_io, void *store_r);
/* Parse one RR, in dgram of length dglen, starting at cbyte and
* extending until at most max.
*
*
* If there is an overrun which might indicate truncation, it should set
* *rdstart to -1; otherwise it may set it to anything else positive.
+ *
+ * nsstart is the offset of the authority section; *arstart_io is
+ * -1 or the offset of the additional section; if it is -1 then
+ * parse may set it to the correct offset.
*/
int (*diff_needswap)(const void *datap_a, const void *datap_b);
- /* Returns >0 if RR a should be strictly after RR b in the sort order,
+ /* Returns !0 if RR a should be strictly after RR b in the sort order,
* 0 otherwise. Must not fail.
*/
} typeinfo;
* vb before using the return value.
*/
+void adns__isort(void *array, int nobjs, int sz, void *tempbuf,
+ int (*needswap)(const void *a, const void *b));
+/* Does an insertion sort of array which must contain nobjs objects
+ * each sz bytes long. tempbuf must point to a buffer at least
+ * sz bytes long. needswap should return !0 if a>b (strictly, ie
+ * wrong order) 0 if a<=b (ie, order is fine).
+ */
+
/* From transmit.c: */
adns_status adns__mkquery(adns_state ads, vbuf *vb, int *id_r,
r= adns_submit(ads,owner,type,flags,0,&qu);
if (r) return r;
- do {
- r= adns_wait(ads,&qu,answer_r,0);
- } while (r==EINTR);
+ r= adns_wait(ads,&qu,answer_r,0);
if (r) adns_cancel(qu);
- return r;
-}
-void adns_cancel(adns_query query) {
- abort(); /* fixme */
+ return r;
}
static void *alloc_common(adns_query qu, size_t sz) {
}
void adns__reset_cnameonly(adns_query qu) {
+ /* fixme: cancel children */
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 free_query_allocs(adns_query qu) {
+ allocnode *an, *ann;
+ adns_query cqu, ncqu;
+
+ for (cqu= qu->children.head; cqu; cqu= ncqu) {
+ ncqu= cqu->siblings.next;
+ adns_cancel(cqu);
+ }
+ for (an= qu->allocations; an; an= ann) { ann= an->next; free(an); }
+ adns__vbuf_free(&qu->vb);
+}
+
+void adns_cancel(adns_query query) {
+ switch (qu->state) {
+ case query_udp: case query_tcpwait: case query_tcpsent:
+ LIST_UNLINK(ads->timew,qu);
+ break;
+ case query_child:
+ LIST_UNLINK(ads->childw,qu);
+ break;
+ case query_done:
+ LIST_UNLINK(ads->output,qu);
+ break;
+ default:
+ abort();
+ }
+ free_query_allocs(qu);
+ free(qu->answer);
+ free(qu);
+}
+
void adns__query_done(adns_query qu) {
adns_answer *ans;
- allocnode *an, *ann;
- int i;
+ int rrn;
- if (qu->answer->status == adns_s_nolocalmem && !qu->interim_allocd) {
- ans= qu->answer;
- } else {
- ans= realloc(qu->answer,
- MEM_ROUND(MEM_ROUND(sizeof(*ans)) + qu->interim_allocd));
+ ans= qu->answer;
+
+ if (qu->interim_allocd) {
+ if (qu->answer->nrrs && qu->typei->diff_needswap) {
+ if (!adns__vbuf_ensure(&qu->vb,qu->typei->rrsz)) {
+ adns__query_fail(qu,adns_s_nolocalmem);
+ return;
+ }
+ }
+ ans= realloc(qu->answer, MEM_ROUND(MEM_ROUND(sizeof(*ans)) + qu->interim_allocd));
if (!ans) {
qu->answer->cname= 0;
adns__query_fail(qu, adns_s_nolocalmem);
}
qu->answer= ans;
}
- qu->final_allocspace= (byte*)ans + MEM_ROUND(sizeof(*ans));
+ qu->final_allocspace= (byte*)ans + MEM_ROUND(sizeof(*ans));
adns__makefinal_str(qu,&ans->cname);
+
if (ans->nrrs) {
- adns__makefinal_block(qu,&ans->rrs.untyped,ans->rrsz*ans->nrrs);
- for (i=0; i<ans->nrrs; i++)
- qu->typei->makefinal(qu,ans->rrs.bytes+ans->rrsz*i);
- }
+ adns__makefinal_block(qu, &ans->rrs.untyped, ans->nrrs*ans->rrsz);
- for (an= qu->allocations; an; an= ann) { ann= an->next; free(an); }
+ for (rrn=0; rrn<ans->nrrs; rrn++)
+ qu->typei->makefinal(qu, ans->rrs.bytes + rrn*ans->rrsz);
- adns__vbuf_free(&qu->vb);
+ if (qu->typei->diff_needswap)
+ adns__isort(ans->rrs.bytes, ans->nrrs, ans->rrsz,
+ qu->vb.buf, qu->typei->diff_needswap);
+ }
+
+ free_query_allocs(qu);
qu->id= -1;
LIST_LINK_TAIL(qu->ads->output,qu);
memcpy(after,before,sz);
*blpp= after;
}
-
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;
return;
}
anstart= qu->query_dglen;
+ arstart= -1;
LIST_UNLINK(ads->timew,qu);
/* We're definitely going to do something with this query now */
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++) {
st= adns__findrr(qu,serv, dgram,dglen,&cbyte,
&rrtype,&rrclass,&rdlength,&rdstart,
!ownermatched)
continue;
st= typei->parse(qu,serv, dgram,dglen, rdstart,rdstart+rdlength,
- rrsdata+nrrs*typei->rrsz);
+ nsstart,&arstart, 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);
static adns_status pa_inaddr(adns_query qu, int serv,
const byte *dgram, int dglen, int cbyte, int max,
- void *datap) {
+ int nsstart, int *arstart_io, void *datap) {
struct in_addr *storeto= datap;
if (max-cbyte != 4) return adns_s_invaliddata;
static adns_status pa_addr(adns_query qu, int serv,
const byte *dgram, int dglen, int cbyte, int max,
- void *datap) {
+ int nsstart, int *arstart_io, void *datap) {
adns_addr *storeto= datap;
if (max-cbyte != 4) return adns_s_invaliddata;
static adns_status pa_host_raw(adns_query qu, int serv,
const byte *dgram, int dglen, int cbyte, int max,
- void *datap) {
+ int nsstart, int *arstart_io, void *datap) {
char **rrp= datap;
adns_status st;
static adns_status pa_mx_raw(adns_query qu, int serv,
const byte *dgram, int dglen, int cbyte, int max,
- void *datap) {
+ int nsstart, int *arstart_io, void *datap) {
adns_rr_intstr *rrp= datap;
adns_status st;
int pref;
static adns_status pa_txt(adns_query qu, int serv,
const byte *dgram, int dglen, int startbyte, int max,
- void *datap) {
+ int nsstart, int *arstart_io, void *datap) {
adns_rr_intstr **rrp= datap, *table, *te;
int ti, tc, cbyte, l;
#endif
#if 0 /*fixme*/
- { adns_r_soa, "SOA", "822", DEEP_MEMB(soa), pa_soa, 0 },
- { adns_r_rp, "RP", "822", DEEP_MEMB(strpair), pa_rp, 0 },
+ { adns_r_soa, "SOA","822", DEEP_MEMB(soa), pa_soa, 0 },
+ { adns_r_rp, "RP", "822", DEEP_MEMB(strpair), pa_rp, 0 },
#endif
};