From 551ff40f1e8eab858f07ea0c0d5217da70837751 Mon Sep 17 00:00:00 2001 From: ian Date: Sun, 15 Nov 1998 21:22:29 +0000 Subject: [PATCH] Does further A lookups and uses answers. --- src/adns.h | 6 ++-- src/internal.h | 29 +++++++++++++----- src/query.c | 83 ++++++++++++++++++++++++++++++++++---------------- src/types.c | 36 ++++++++++++++-------- 4 files changed, 106 insertions(+), 48 deletions(-) diff --git a/src/adns.h b/src/adns.h index 938fb18..a87767a 100644 --- a/src/adns.h +++ b/src/adns.h @@ -133,13 +133,13 @@ typedef struct { struct sockaddr sa; struct sockaddr_in inet; } addr; -} adns_addr; +} adns_rr_addr; typedef struct { char *host; adns_status astatus; int naddrs; /* temp fail => -1, perm fail => 0, s_ok => >0 */ - adns_addr *addrs; + adns_rr_addr *addrs; } adns_rr_hostaddr; typedef struct { @@ -176,7 +176,7 @@ typedef struct { unsigned char *bytes; char *(*str); /* ns_raw, cname, ptr, ptr_raw */ adns_rr_intstr *(*manyistr); /* txt (list of strings ends with i=-1, str=0) */ - adns_addr *addr; /* addr */ + adns_rr_addr *addr; /* addr */ struct in_addr *inaddr; /* a */ adns_rr_hostaddr *hostaddr; /* ns */ adns_rr_strpair *strpair; /* hinfo ??fixme, rp, rp_raw */ diff --git a/src/internal.h b/src/internal.h index f1f4d96..33086f6 100644 --- a/src/internal.h +++ b/src/internal.h @@ -77,7 +77,12 @@ typedef struct { typedef union { void *ext; - adns_rr_hostaddr *hostaddr; + struct { + void (*callback)(adns_query parent, adns_query child); + union { + adns_rr_hostaddr *hostaddr; + } info; + } intern; } qcontext; typedef struct { @@ -125,7 +130,7 @@ typedef struct { } typeinfo; typedef struct allocnode { - struct allocnode *next; + struct allocnode *next, *back; } allocnode; union maxalign { @@ -143,7 +148,7 @@ struct adns__query { adns_query back, next, parent; struct { adns_query head, tail; } children; struct { adns_query back, next; } siblings; - struct allocnode *allocations; + struct { allocnode *head, *tail; } allocations; int interim_allocd; void *final_allocspace; @@ -358,6 +363,16 @@ void *adns__alloc_interim(adns_query qu, size_t sz); * but it will not necessarily return a distinct pointer each time. */ +void adns__transfer_interim(adns_query from, adns_query to, void *block, size_t sz); +/* Transfers an interim allocation from one query to another, so that + * the `to' query will have room for the data when we get to makefinal + * and so that the free will happen when the `to' query is freed + * rather than the `from' query. + * + * It is legal to call adns__transfer_interim with a null pointer; this + * has no effect. + */ + 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 @@ -538,10 +553,10 @@ static inline int ctype_alpha(int c) { #define LIST_UNLINK_PART(list,node,part) \ do { \ - if ((node)->back) (node)->back->part next= (node)->part next; \ - else (list).head= (node)->part next; \ - if ((node)->next) (node)->next->part back= (node)->part back; \ - else (list).tail= (node)->part back; \ + if ((node)->part back) (node)->part back->part next= (node)->part next; \ + else (list).head= (node)->part next; \ + if ((node)->part next) (node)->part next->part back= (node)->part back; \ + else (list).tail= (node)->part back; \ } while(0) #define LIST_LINK_TAIL_PART(list,node,part) \ diff --git a/src/query.c b/src/query.c index 8c39caa..7c15a5b 100644 --- a/src/query.c +++ b/src/query.c @@ -46,7 +46,7 @@ int adns__internal_submit(adns_state ads, adns_query *query_r, qu->back= qu->next= qu->parent= 0; LIST_INIT(qu->children); qu->siblings.next= qu->siblings.back= 0; - qu->allocations= 0; + LIST_INIT(qu->allocations); qu->interim_allocd= 0; qu->final_allocspace= 0; @@ -160,8 +160,7 @@ static void *alloc_common(adns_query qu, size_t sz) { assert(!qu->final_allocspace); an= malloc(MEM_ROUND(MEM_ROUND(sizeof(*an)) + sz)); if (!an) return 0; - an->next= qu->allocations; - qu->allocations= an; + LIST_LINK_TAIL(qu->allocations,an); return (byte*)an + MEM_ROUND(sizeof(*an)); } @@ -175,6 +174,22 @@ void *adns__alloc_mine(adns_query qu, size_t sz) { return alloc_common(qu,MEM_ROUND(sz)); } +void adns__transfer_interim(adns_query from, adns_query to, void *block, size_t sz) { + allocnode *an; + + if (!block) return; + an= (void*)((byte*)block - MEM_ROUND(sizeof(*an))); + + assert(!to->final_allocspace); + assert(!from->final_allocspace); + + LIST_UNLINK(from->allocations,an); + LIST_LINK_TAIL(to->allocations,an); + + from->interim_allocd -= sz; + to->interim_allocd += sz; +} + void *adns__alloc_final(adns_query qu, size_t sz) { /* When we're in the _final stage, we _subtract_ from interim_alloc'd * each allocation, and use final_allocspace to point to the next free @@ -207,7 +222,7 @@ static void free_query_allocs(adns_query qu) { ncqu= cqu->siblings.next; adns_cancel(cqu); } - for (an= qu->allocations; an; an= ann) { ann= an->next; free(an); } + for (an= qu->allocations.head; an; an= ann) { ann= an->next; free(an); } adns__vbuf_free(&qu->vb); } @@ -229,26 +244,16 @@ void adns_cancel(adns_query qu) { free(qu->answer); free(qu); } - -void adns__query_done(adns_query qu) { + +static void makefinal_query(adns_query qu) { adns_answer *ans; int rrn; 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); - return; - } + if (!ans) goto x_nomem; qu->answer= ans; } @@ -260,19 +265,45 @@ void adns__query_done(adns_query qu) { for (rrn=0; rrnnrrs; rrn++) qu->typei->makefinal(qu, ans->rrs.bytes + rrn*ans->rrsz); - - 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); + return; + x_nomem: + qu->answer->status= adns_s_nolocalmem; + qu->answer->cname= 0; + adns__reset_cnameonly(qu); + free_query_allocs(qu); +} + +void adns__query_done(adns_query qu) { + adns_answer *ans; + adns_query parent; + qu->id= -1; - LIST_LINK_TAIL(qu->ads->output,qu); + ans= qu->answer; + + if (ans->nrrs && qu->typei->diff_needswap) { + if (!adns__vbuf_ensure(&qu->vb,qu->typei->rrsz)) { + adns__query_fail(qu,adns_s_nolocalmem); + return; + } + adns__isort(ans->rrs.bytes, ans->nrrs, ans->rrsz, + qu->vb.buf, qu->typei->diff_needswap); + } - assert(!qu->parent); - /* fixme: do something with the answers to internally-generated queries. */ + parent= qu->parent; + if (parent) { + LIST_UNLINK_PART(parent->children,qu,siblings.); + qu->context.intern.callback(parent,qu); + free_query_allocs(qu); + free(qu); + if (!parent->children.head) adns__query_done(parent); + } else { + makefinal_query(qu); + LIST_LINK_TAIL(qu->ads->output,qu); + } } void adns__query_fail(adns_query qu, adns_status stat) { diff --git a/src/types.c b/src/types.c index e494ab3..0050b77 100644 --- a/src/types.c +++ b/src/types.c @@ -228,7 +228,7 @@ static adns_status cs_inaddr(vbuf *vb, const void *datap) { */ static adns_status pa_addr(const parseinfo *pai, int cbyte, int max, void *datap) { - adns_addr *storeto= datap; + adns_rr_addr *storeto= datap; const byte *dgram= pai->dgram; if (max-cbyte != 4) return adns_s_invaliddata; @@ -241,13 +241,13 @@ static adns_status pa_addr(const parseinfo *pai, int cbyte, int max, void *datap } static int di_addr(const void *datap_a, const void *datap_b) { - const adns_addr *ap= datap_a, *bp= datap_b; + const adns_rr_addr *ap= datap_a, *bp= datap_b; assert(ap->addr.sa.sa_family == AF_INET); return dip_inaddr(ap->addr.inet.sin_addr,bp->addr.inet.sin_addr); } -static adns_status csp_addr(vbuf *vb, const adns_addr *rrp) { +static adns_status csp_addr(vbuf *vb, const adns_rr_addr *rrp) { const char *ia; static char buf[30]; @@ -266,7 +266,7 @@ static adns_status csp_addr(vbuf *vb, const adns_addr *rrp) { } static adns_status cs_addr(vbuf *vb, const void *datap) { - const adns_addr *rrp= datap; + const adns_rr_addr *rrp= datap; return csp_addr(vb,rrp); } @@ -312,7 +312,7 @@ static adns_status pa_host_raw(const parseinfo *pai, int cbyte, int max, void *d } /* - * _hostaddr (pap,pa,dip,di,mfp,mf,csp,cs +pap_findaddrs) + * _hostaddr (pap,pa,dip,di,mfp,mf,csp,cs +icb_hostaddr, pap_findaddrs) */ static adns_status pap_findaddrs(const parseinfo *pai, adns_rr_hostaddr *ha, @@ -332,23 +332,34 @@ static adns_status pap_findaddrs(const parseinfo *pai, adns_rr_hostaddr *ha, if (naddrs == -1) { naddrs= 0; } - if (!adns__vbuf_ensure(&pai->qu->vb, (naddrs+1)*sizeof(adns_addr))) R_NOMEM; - st= pa_addr(pai, rdstart,rdstart+rdlen, pai->qu->vb.buf + naddrs*sizeof(adns_addr)); + if (!adns__vbuf_ensure(&pai->qu->vb, (naddrs+1)*sizeof(adns_rr_addr))) R_NOMEM; + st= pa_addr(pai, rdstart,rdstart+rdlen, + pai->qu->vb.buf + naddrs*sizeof(adns_rr_addr)); if (st) return st; naddrs++; } if (naddrs >= 0) { - ha->addrs= adns__alloc_interim(pai->qu, naddrs*sizeof(adns_addr)); + ha->addrs= adns__alloc_interim(pai->qu, naddrs*sizeof(adns_rr_addr)); if (!ha->addrs) R_NOMEM; - memcpy(ha->addrs, pai->qu->vb.buf, naddrs*sizeof(adns_addr)); + memcpy(ha->addrs, pai->qu->vb.buf, naddrs*sizeof(adns_rr_addr)); ha->naddrs= naddrs; ha->astatus= adns_s_ok; - adns__isort(ha->addrs, naddrs, sizeof(adns_addr), pai->qu->vb.buf, di_addr); + adns__isort(ha->addrs, naddrs, sizeof(adns_rr_addr), pai->qu->vb.buf, di_addr); } return adns_s_ok; } +static void icb_hostaddr(adns_query parent, adns_query child) { + adns_rr_hostaddr *rrp= child->context.intern.info.hostaddr; + adns_answer *cans= child->answer; + + rrp->astatus= cans->status; + rrp->naddrs= cans->nrrs; + rrp->addrs= cans->rrs.addr; + adns__transfer_interim(child, parent, rrp->addrs, rrp->naddrs*sizeof(adns_rr_addr)); +} + static adns_status pap_hostaddr(const parseinfo *pai, int *cbyte_io, int max, adns_rr_hostaddr *rrp) { adns_status st; @@ -381,8 +392,9 @@ static adns_status pap_hostaddr(const parseinfo *pai, int *cbyte_io, pai->dgram, pai->dglen, dmstart, adns_r_addr, adns_qf_quoteok_query); if (st) return st; - - ctx.hostaddr= rrp; + + ctx.intern.callback= icb_hostaddr; + ctx.intern.info.hostaddr= rrp; st= adns__internal_submit(pai->ads, &nqu, adns__findtype(adns_r_addr), &pai->qu->vb, id, adns_qf_quoteok_query, pai->now, 0, &ctx); -- 2.30.2