summaryrefslogtreecommitdiffhomepage
path: root/adns-0.6/src/query.c
diff options
context:
space:
mode:
Diffstat (limited to 'adns-0.6/src/query.c')
-rw-r--r--adns-0.6/src/query.c540
1 files changed, 0 insertions, 540 deletions
diff --git a/adns-0.6/src/query.c b/adns-0.6/src/query.c
deleted file mode 100644
index 37306d1..0000000
--- a/adns-0.6/src/query.c
+++ /dev/null
@@ -1,540 +0,0 @@
-/*
- * query.c
- * - overall query management (allocation, completion)
- * - per-query memory management
- * - query submission and cancellation (user-visible and internal)
- */
-/*
- * This file is
- * Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
- *
- * It is part of adns, which is
- * Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
- * Copyright (C) 1999 Tony Finch <dot@dotat.at>
- *
- * 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
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include "internal.h"
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include <sys/time.h>
-
-#include "internal.h"
-
-static adns_query query_alloc(adns_state ads, const typeinfo *typei,
- adns_queryflags flags, struct timeval now) {
- /* Allocate a virgin query and return it. */
- adns_query qu;
-
- qu= malloc(sizeof(*qu)); if (!qu) return 0;
- qu->answer= malloc(sizeof(*qu->answer)); if (!qu->answer) { free(qu); return 0; }
-
- qu->ads= ads;
- qu->state= query_tosend;
- qu->back= qu->next= qu->parent= 0;
- LIST_INIT(qu->children);
- LINK_INIT(qu->siblings);
- LIST_INIT(qu->allocations);
- qu->interim_allocd= 0;
- qu->preserved_allocd= 0;
- qu->final_allocspace= 0;
-
- qu->typei= typei;
- qu->query_dgram= 0;
- qu->query_dglen= 0;
- adns__vbuf_init(&qu->vb);
-
- qu->cname_dgram= 0;
- qu->cname_dglen= qu->cname_begin= 0;
-
- adns__vbuf_init(&qu->search_vb);
- qu->search_origlen= qu->search_pos= qu->search_doneabs= 0;
-
- qu->id= 0;
- qu->flags= flags;
- qu->retries= 0;
- qu->udpnextserver= 0;
- qu->udpsent= 0;
- timerclear(&qu->timeout);
- qu->expires= now.tv_sec + MAXTTLBELIEVE;
-
- memset(&qu->ctx,0,sizeof(qu->ctx));
-
- qu->answer->status= adns_s_ok;
- qu->answer->cname= qu->answer->owner= 0;
- qu->answer->type= typei->type;
- qu->answer->expires= -1;
- qu->answer->nrrs= 0;
- qu->answer->rrs.untyped= 0;
- qu->answer->rrsz= typei->rrsz;
-
- return qu;
-}
-
-static void query_submit(adns_state ads, adns_query qu,
- const typeinfo *typei, vbuf *qumsg_vb, int id,
- adns_queryflags flags, struct timeval now) {
- /* Fills in the query message in for a previously-allocated query,
- * and submits it. Cannot fail. Takes over the memory for qumsg_vb.
- */
-
- qu->vb= *qumsg_vb;
- adns__vbuf_init(qumsg_vb);
-
- qu->query_dgram= malloc(qu->vb.used);
- if (!qu->query_dgram) { adns__query_fail(qu,adns_s_nomemory); return; }
-
- qu->id= id;
- qu->query_dglen= qu->vb.used;
- memcpy(qu->query_dgram,qu->vb.buf,qu->vb.used);
-
- adns__query_send(qu,now);
-}
-
-adns_status adns__internal_submit(adns_state ads, adns_query *query_r,
- const typeinfo *typei, vbuf *qumsg_vb, int id,
- adns_queryflags flags, struct timeval now,
- const qcontext *ctx) {
- adns_query qu;
-
- qu= query_alloc(ads,typei,flags,now);
- if (!qu) { adns__vbuf_free(qumsg_vb); return adns_s_nomemory; }
- *query_r= qu;
-
- memcpy(&qu->ctx,ctx,sizeof(qu->ctx));
- query_submit(ads,qu, typei,qumsg_vb,id,flags,now);
-
- return adns_s_ok;
-}
-
-static void query_simple(adns_state ads, adns_query qu,
- const char *owner, int ol,
- const typeinfo *typei, adns_queryflags flags,
- struct timeval now) {
- vbuf vb;
- int id;
- adns_status stat;
-
- vb= qu->vb;
-
- stat= adns__mkquery(ads,&vb,&id, owner,ol, typei,flags);
- if (stat) { adns__query_fail(qu,stat); return; }
-
- query_submit(ads,qu, typei,&vb,id, flags,now);
-}
-
-void adns__search_next(adns_state ads, adns_query qu, struct timeval now) {
- const char *nextentry;
- adns_status stat;
-
- if (qu->search_doneabs<0) {
- nextentry= 0;
- qu->search_doneabs= 1;
- } else {
- if (qu->search_pos >= ads->nsearchlist) {
- if (qu->search_doneabs) {
- stat= adns_s_nxdomain; goto x_fail;
- return;
- } else {
- nextentry= 0;
- qu->search_doneabs= 1;
- }
- } else {
- nextentry= ads->searchlist[qu->search_pos++];
- }
- }
-
- qu->search_vb.used= qu->search_origlen;
- if (nextentry) {
- if (!adns__vbuf_append(&qu->search_vb,".",1) ||
- !adns__vbuf_appendstr(&qu->search_vb,nextentry)) {
- stat= adns_s_nomemory; goto x_fail;
- }
- }
-
- free(qu->query_dgram);
- qu->query_dgram= 0; qu->query_dglen= 0;
-
- query_simple(ads,qu, qu->search_vb.buf, qu->search_vb.used, qu->typei, qu->flags, now);
- return;
-
-x_fail:
- adns__query_fail(qu,stat);
-}
-
-static int save_owner(adns_query qu, const char *owner, int ol) {
- /* Returns 1 if OK, otherwise there was no memory. */
- adns_answer *ans;
-
- ans= qu->answer;
- assert(!ans->owner);
-
- ans->owner= adns__alloc_preserved(qu,ol+1); if (!ans->owner) return 0;
-
- memcpy(ans->owner,owner,ol);
- ans->owner[ol]= 0;
- return 1;
-}
-
-int adns_submit(adns_state ads,
- const char *owner,
- adns_rrtype type,
- adns_queryflags flags,
- void *context,
- adns_query *query_r) {
- int r, ol, ndots;
- adns_status stat;
- const typeinfo *typei;
- struct timeval now;
- adns_query qu;
- const char *p;
-
- adns__consistency(ads,0,cc_entex);
-
- typei= adns__findtype(type);
- if (!typei) return ENOSYS;
-
- r= gettimeofday(&now,0); if (r) goto x_errno;
- qu= query_alloc(ads,typei,flags,now); if (!qu) goto x_errno;
-
- qu->ctx.ext= context;
- qu->ctx.callback= 0;
- memset(&qu->ctx.info,0,sizeof(qu->ctx.info));
-
- *query_r= qu;
-
- ol= strlen(owner);
- if (!ol) { stat= adns_s_querydomaininvalid; goto x_adnsfail; }
- if (ol>DNS_MAXDOMAIN+1) { stat= adns_s_querydomaintoolong; goto x_adnsfail; }
-
- if (ol>=1 && owner[ol-1]=='.' && (ol<2 || owner[ol-2]!='\\')) {
- flags &= ~adns_qf_search;
- qu->flags= flags;
- ol--;
- }
-
- if (flags & adns_qf_search) {
- r= adns__vbuf_append(&qu->search_vb,owner,ol);
- if (!r) { stat= adns_s_nomemory; goto x_adnsfail; }
-
- for (ndots=0, p=owner; (p= strchr(p,'.')); p++, ndots++);
- qu->search_doneabs= (ndots >= ads->searchndots) ? -1 : 0;
- qu->search_origlen= ol;
- adns__search_next(ads,qu,now);
- } else {
- if (flags & adns_qf_owner) {
- if (!save_owner(qu,owner,ol)) { stat= adns_s_nomemory; goto x_adnsfail; }
- }
- query_simple(ads,qu, owner,ol, typei,flags, now);
- }
- adns__autosys(ads,now);
- adns__consistency(ads,qu,cc_entex);
- return 0;
-
- x_adnsfail:
- adns__query_fail(qu,stat);
- adns__consistency(ads,qu,cc_entex);
- return 0;
-
- x_errno:
- r= errno;
- assert(r);
- adns__consistency(ads,0,cc_entex);
- return r;
-}
-
-int adns_submit_reverse(adns_state ads,
- const struct sockaddr *addr,
- adns_rrtype type,
- adns_queryflags flags,
- void *context,
- adns_query *query_r) {
- const unsigned char *iaddr;
- char buf[30];
-
- if (type != adns_r_ptr && type != adns_r_ptr_raw) return EINVAL;
- flags &= ~adns_qf_search;
-
- if (addr->sa_family != AF_INET) return ENOSYS;
- iaddr= (const unsigned char*) &(((const struct sockaddr_in*)addr) -> sin_addr);
-
- sprintf(buf, "%d.%d.%d.%d.in-addr.arpa",
- iaddr[3], iaddr[2], iaddr[1], iaddr[0]);
-
- return adns_submit(ads,buf,type,flags,context,query_r);
-}
-
-int adns_synchronous(adns_state ads,
- const char *owner,
- adns_rrtype type,
- adns_queryflags flags,
- adns_answer **answer_r) {
- adns_query qu;
- int r;
-
- r= adns_submit(ads,owner,type,flags,0,&qu);
- if (r) return r;
-
- r= adns_wait(ads,&qu,answer_r,0);
- if (r) adns_cancel(qu);
-
- return r;
-}
-
-static void *alloc_common(adns_query qu, size_t sz) {
- allocnode *an;
-
- if (!sz) return qu; /* Any old pointer will do */
- assert(!qu->final_allocspace);
- an= malloc(MEM_ROUND(MEM_ROUND(sizeof(*an)) + sz));
- if (!an) return 0;
- LIST_LINK_TAIL(qu->allocations,an);
- return (byte*)an + MEM_ROUND(sizeof(*an));
-}
-
-void *adns__alloc_interim(adns_query qu, size_t sz) {
- void *rv;
-
- sz= MEM_ROUND(sz);
- rv= alloc_common(qu,sz);
- if (!rv) return 0;
- qu->interim_allocd += sz;
- return rv;
-}
-
-void *adns__alloc_preserved(adns_query qu, size_t sz) {
- void *rv;
-
- sz= MEM_ROUND(sz);
- rv= adns__alloc_interim(qu,sz);
- if (!rv) return 0;
- qu->preserved_allocd += sz;
- return rv;
-}
-
-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;
-
- if (to->expires > from->expires) to->expires= from->expires;
-}
-
-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
- * bit.
- */
- void *rp;
-
- sz= MEM_ROUND(sz);
- rp= qu->final_allocspace;
- assert(rp);
- qu->interim_allocd -= sz;
- assert(qu->interim_allocd>=0);
- qu->final_allocspace= (byte*)rp + sz;
- return rp;
-}
-
-static void cancel_children(adns_query qu) {
- adns_query cqu, ncqu;
-
- for (cqu= qu->children.head; cqu; cqu= ncqu) {
- ncqu= cqu->siblings.next;
- adns_cancel(cqu);
- }
-}
-
-void adns__reset_preserved(adns_query qu) {
- assert(!qu->final_allocspace);
- cancel_children(qu);
- qu->answer->nrrs= 0;
- qu->answer->rrs.untyped= 0;
- qu->interim_allocd= qu->preserved_allocd;
-}
-
-static void free_query_allocs(adns_query qu) {
- allocnode *an, *ann;
-
- cancel_children(qu);
- for (an= qu->allocations.head; an; an= ann) { ann= an->next; free(an); }
- LIST_INIT(qu->allocations);
- adns__vbuf_free(&qu->vb);
- adns__vbuf_free(&qu->search_vb);
- free(qu->query_dgram);
-}
-
-void adns_cancel(adns_query qu) {
- adns_state ads;
-
- ads= qu->ads;
- adns__consistency(ads,qu,cc_entex);
- if (qu->parent) LIST_UNLINK_PART(qu->parent->children,qu,siblings.);
- switch (qu->state) {
- case query_tosend:
- LIST_UNLINK(ads->udpw,qu);
- break;
- case query_tcpw:
- LIST_UNLINK(ads->tcpw,qu);
- break;
- case query_childw:
- 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);
- adns__consistency(ads,0,cc_entex);
-}
-
-void adns__update_expires(adns_query qu, unsigned long ttl, struct timeval now) {
- time_t max;
-
- assert(ttl <= MAXTTLBELIEVE);
- max= now.tv_sec + ttl;
- if (qu->expires < max) return;
- qu->expires= max;
-}
-
-static void makefinal_query(adns_query qu) {
- adns_answer *ans;
- int rrn;
-
- ans= qu->answer;
-
- if (qu->interim_allocd) {
- ans= realloc(qu->answer, MEM_ROUND(MEM_ROUND(sizeof(*ans)) + qu->interim_allocd));
- if (!ans) goto x_nomem;
- qu->answer= ans;
- }
-
- qu->final_allocspace= (byte*)ans + MEM_ROUND(sizeof(*ans));
- adns__makefinal_str(qu,&ans->cname);
- adns__makefinal_str(qu,&ans->owner);
-
- if (ans->nrrs) {
- adns__makefinal_block(qu, &ans->rrs.untyped, ans->nrrs*ans->rrsz);
-
- for (rrn=0; rrn<ans->nrrs; rrn++)
- qu->typei->makefinal(qu, ans->rrs.bytes + rrn*ans->rrsz);
- }
-
- free_query_allocs(qu);
- return;
-
- x_nomem:
- qu->preserved_allocd= 0;
- qu->answer->cname= 0;
- qu->answer->owner= 0;
- adns__reset_preserved(qu); /* (but we just threw away the preserved stuff) */
-
- qu->answer->status= adns_s_nomemory;
- free_query_allocs(qu);
-}
-
-void adns__query_done(adns_query qu) {
- adns_answer *ans;
- adns_query parent;
-
- cancel_children(qu);
-
- qu->id= -1;
- ans= qu->answer;
-
- if (qu->flags & adns_qf_owner && qu->flags & adns_qf_search &&
- ans->status != adns_s_nomemory) {
- if (!save_owner(qu, qu->search_vb.buf, qu->search_vb.used)) {
- adns__query_fail(qu,adns_s_nomemory);
- return;
- }
- }
-
- if (ans->nrrs && qu->typei->diff_needswap) {
- if (!adns__vbuf_ensure(&qu->vb,qu->typei->rrsz)) {
- adns__query_fail(qu,adns_s_nomemory);
- return;
- }
- adns__isort(ans->rrs.bytes, ans->nrrs, ans->rrsz,
- qu->vb.buf,
- (int(*)(void*, const void*, const void*))qu->typei->diff_needswap,
- qu->ads);
- }
-
- ans->expires= qu->expires;
- parent= qu->parent;
- if (parent) {
- LIST_UNLINK_PART(parent->children,qu,siblings.);
- LIST_UNLINK(qu->ads->childw,parent);
- qu->ctx.callback(parent,qu);
- free_query_allocs(qu);
- free(qu->answer);
- free(qu);
- } else {
- makefinal_query(qu);
- LIST_LINK_TAIL(qu->ads->output,qu);
- qu->state= query_done;
- }
-}
-
-void adns__query_fail(adns_query qu, adns_status stat) {
- adns__reset_preserved(qu);
- qu->answer->status= stat;
- adns__query_done(qu);
-}
-
-void adns__makefinal_str(adns_query qu, char **strp) {
- int l;
- char *before, *after;
-
- before= *strp;
- if (!before) return;
- l= strlen(before)+1;
- after= adns__alloc_final(qu,l);
- memcpy(after,before,l);
- *strp= after;
-}
-
-void adns__makefinal_block(adns_query qu, void **blpp, size_t sz) {
- void *before, *after;
-
- before= *blpp;
- if (!before) return;
- after= adns__alloc_final(qu,sz);
- memcpy(after,before,sz);
- *blpp= after;
-}