X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fquery.c;h=aaadb219e8868134d2882fb36e5f99872949b2e4;hb=4fad263db72b6e675e82c84b56d81333240a7475;hp=c092a30c25a79a94837510691e5c5a8747767b46;hpb=679ff49d885968ad904592ce3a373106a10669e9;p=adns.git diff --git a/src/query.c b/src/query.c index c092a30..aaadb21 100644 --- a/src/query.c +++ b/src/query.c @@ -66,11 +66,11 @@ static adns_query query_alloc(adns_state ads, const typeinfo *typei, adns__vbuf_init(&qu->search_vb); qu->search_origlen= qu->search_pos= qu->search_doneabs= 0; - qu->id= 0; + qu->id= -2; /* will be overwritten with real id before we leave adns */ qu->flags= flags; - qu->udpretries= 0; + qu->retries= 0; qu->udpnextserver= 0; - qu->udpsent= qu->tcpfailed= 0; + qu->udpsent= 0; timerclear(&qu->timeout); qu->expires= now.tv_sec + MAXTTLBELIEVE; @@ -91,7 +91,7 @@ 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. + * and submits it. Cannot fail. Takes over the memory for qumsg_vb. */ qu->vb= *qumsg_vb; @@ -127,16 +127,24 @@ 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; + vbuf vb_new; int id; adns_status stat; - adns__vbuf_init(&vb); - - stat= adns__mkquery(ads,&vb,&id, owner,ol, typei,flags); - if (stat) { adns__query_fail(qu,stat); return; } + stat= adns__mkquery(ads,&qu->vb,&id, owner,ol, typei,flags); + if (stat) { + if (stat == adns_s_querydomaintoolong && (flags & adns_qf_search)) { + adns__search_next(ads,qu,now); + return; + } else { + adns__query_fail(qu,stat); + return; + } + } - query_submit(ads,qu, typei,&vb,id, flags,now); + vb_new= qu->vb; + adns__vbuf_init(&qu->vb); + query_submit(ads,qu, typei,&vb_new,id, flags,now); } void adns__search_next(adns_state ads, adns_query qu, struct timeval now) { @@ -195,7 +203,7 @@ static int save_owner(adns_query qu, const char *owner, int ol) { int adns_submit(adns_state ads, const char *owner, adns_rrtype type, - int flags, + adns_queryflags flags, void *context, adns_query *query_r) { int r, ol, ndots; @@ -225,6 +233,7 @@ int adns_submit(adns_state ads, if (ol>=1 && owner[ol-1]=='.' && (ol<2 || owner[ol-2]!='\\')) { flags &= ~adns_qf_search; + qu->flags= flags; ol--; } @@ -258,31 +267,53 @@ int adns_submit(adns_state ads, return r; } -int adns_submit_reverse(adns_state ads, - const struct sockaddr *addr, - adns_rrtype type, - int flags, - void *context, - adns_query *query_r) { +int adns_submit_reverse_any(adns_state ads, + const struct sockaddr *addr, + const char *zone, + adns_rrtype type, + adns_queryflags flags, + void *context, + adns_query *query_r) { const unsigned char *iaddr; - char buf[30]; + char *buf, *buf_free; + char shortbuf[100]; + int r, lreq; - 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]); + lreq= strlen(zone) + 4*4 + 1; + if (lreq > sizeof(shortbuf)) { + buf= malloc(strlen(zone) + 4*4 + 1); + if (!buf) return errno; + buf_free= buf; + } else { + buf= shortbuf; + buf_free= 0; + } + sprintf(buf, "%d.%d.%d.%d.%s", iaddr[3], iaddr[2], iaddr[1], iaddr[0], zone); - return adns_submit(ads,buf,type,flags,context,query_r); + r= adns_submit(ads,buf,type,flags,context,query_r); + free(buf_free); + 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) { + if (type != adns_r_ptr && type != adns_r_ptr_raw) return EINVAL; + return adns_submit_reverse_any(ads,addr,"in-addr.arpa",type,flags,context,query_r); } int adns_synchronous(adns_state ads, const char *owner, adns_rrtype type, - int flags, + adns_queryflags flags, adns_answer **answer_r) { adns_query qu; int r; @@ -389,6 +420,8 @@ static void free_query_allocs(adns_query 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) { @@ -398,10 +431,13 @@ void adns_cancel(adns_query qu) { adns__consistency(ads,qu,cc_entex); if (qu->parent) LIST_UNLINK_PART(qu->parent->children,qu,siblings.); switch (qu->state) { - case query_tosend: case query_tcpwait: case query_tcpsent: - LIST_UNLINK(ads->timew,qu); + case query_tosend: + LIST_UNLINK(ads->udpw,qu); + break; + case query_tcpw: + LIST_UNLINK(ads->tcpw,qu); break; - case query_child: + case query_childw: LIST_UNLINK(ads->childw,qu); break; case query_done: @@ -496,6 +532,7 @@ void adns__query_done(adns_query qu) { LIST_UNLINK(qu->ads->childw,parent); qu->ctx.callback(parent,qu); free_query_allocs(qu); + free(qu->answer); free(qu); } else { makefinal_query(qu);