From 8837244370251f16e8f41097d4cbe5ef0058038c Mon Sep 17 00:00:00 2001 From: ian Date: Sat, 14 Nov 1998 15:24:55 +0000 Subject: [PATCH] General improvements; add cancel routine. --- src/Makefile | 4 +-- src/Makefile.in | 4 +-- src/adns.h | 3 +- src/event.c | 5 +++- src/general.c | 17 +++++++++++ src/internal.h | 16 ++++++++-- src/query.c | 78 +++++++++++++++++++++++++++++++++++-------------- src/reply.c | 27 ++--------------- src/types.c | 14 ++++----- 9 files changed, 106 insertions(+), 62 deletions(-) diff --git a/src/Makefile b/src/Makefile index acce334..7c36a84 100644 --- a/src/Makefile +++ b/src/Makefile @@ -21,7 +21,7 @@ WARNS= -Wall -Wmissing-prototypes -Wwrite-strings -Wstrict-prototypes \ -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 @@ -31,5 +31,5 @@ dtest: $(ALLOBJS) clean: rm -f dtest *.o -dtest.o: adns.h $(LIBOBJS): adns.h internal.h +dtest.o: adns.h diff --git a/src/Makefile.in b/src/Makefile.in index acce334..7c36a84 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -21,7 +21,7 @@ WARNS= -Wall -Wmissing-prototypes -Wwrite-strings -Wstrict-prototypes \ -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 @@ -31,5 +31,5 @@ dtest: $(ALLOBJS) clean: rm -f dtest *.o -dtest.o: adns.h $(LIBOBJS): adns.h internal.h +dtest.o: adns.h diff --git a/src/adns.h b/src/adns.h index afcb6b4..5b7aa03 100644 --- a/src/adns.h +++ b/src/adns.h @@ -39,6 +39,7 @@ typedef enum { 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 { @@ -215,7 +216,6 @@ int adns_synchronous(adns_state ads, 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 @@ -238,7 +238,6 @@ int adns_wait(adns_state ads, adns_query *query_io, adns_answer **answer_r, void **context_r); -/* Might return EINTR - if so, try again */ void adns_cancel(adns_query query); diff --git a/src/event.c b/src/event.c index a61b8dd..8f3fb4c 100644 --- a/src/event.c +++ b/src/event.c @@ -394,7 +394,10 @@ int adns_wait(adns_state ads, 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); } diff --git a/src/general.c b/src/general.c index 8311dd7..211b6d2 100644 --- a/src/general.c +++ b/src/general.c @@ -22,6 +22,7 @@ */ #include +#include #include @@ -238,3 +239,19 @@ const char *adns_strerror(adns_status st) { 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; i0 && 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); + } + } +} diff --git a/src/internal.h b/src/internal.h index 19adb4f..09ba2fe 100644 --- a/src/internal.h +++ b/src/internal.h @@ -99,7 +99,7 @@ typedef struct { 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. * @@ -107,10 +107,14 @@ typedef struct { * * 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; @@ -271,6 +275,14 @@ const char *adns__diag_domain(adns_state ads, int serv, adns_query qu, * 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, diff --git a/src/query.c b/src/query.c index 41aaf5f..9c7fffe 100644 --- a/src/query.c +++ b/src/query.c @@ -147,15 +147,10 @@ int adns_synchronous(adns_state ads, 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) { @@ -197,22 +192,58 @@ void *adns__alloc_final(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); @@ -220,18 +251,22 @@ void adns__query_done(adns_query qu) { } 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; inrrs; 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; rrnnrrs; 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); @@ -264,4 +299,3 @@ void adns__makefinal_block(adns_query qu, void **blpp, size_t sz) { memcpy(after,before,sz); *blpp= after; } - diff --git a/src/reply.c b/src/reply.c index 3b46e21..c0772b9 100644 --- a/src/reply.c +++ b/src/reply.c @@ -32,7 +32,7 @@ void adns__procdgram(adns_state ads, const byte *dgram, int dglen, 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; @@ -99,6 +99,7 @@ void adns__procdgram(adns_state ads, const byte *dgram, int dglen, return; } anstart= qu->query_dglen; + arstart= -1; LIST_UNLINK(ads->timew,qu); /* We're definitely going to do something with this query now */ @@ -256,17 +257,9 @@ void adns__procdgram(adns_state ads, const byte *dgram, int dglen, 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; rriparse(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); diff --git a/src/types.c b/src/types.c index 94b79d2..0f5e547 100644 --- a/src/types.c +++ b/src/types.c @@ -34,7 +34,7 @@ static int dip_inaddr(struct in_addr a, struct in_addr b) { 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; @@ -58,7 +58,7 @@ static adns_status cs_inaddr(vbuf *vb, const void *datap) { 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; @@ -117,7 +117,7 @@ static adns_status pap_domain(adns_query qu, int serv, parsedomain_flags flags, 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; @@ -132,7 +132,7 @@ static adns_status pa_host_raw(adns_query qu, int serv, 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; @@ -159,7 +159,7 @@ static int di_mx_raw(const void *datap_a, const void *datap_b) { 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; @@ -320,8 +320,8 @@ static const typeinfo typeinfos[] = { #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 }; -- 2.30.2