X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fquery.c;h=1fa26f87cbf673868a0b1421ba336fcbfdb1ec8b;hb=34a2240e6d24d133cd1ca0ab1845c57e28e9e9e5;hp=640d10ceeee8d25144f615ceb107a728c726dfd1;hpb=e563872a2a813d371753ad7efeb2c25808664a01;p=adns.git diff --git a/src/query.c b/src/query.c index 640d10c..1fa26f8 100644 --- a/src/query.c +++ b/src/query.c @@ -66,7 +66,7 @@ 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->retries= 0; qu->udpnextserver= 0; @@ -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) { @@ -259,25 +267,47 @@ int adns_submit(adns_state ads, 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) { +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, @@ -390,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) { @@ -469,6 +501,7 @@ void adns__query_done(adns_query qu) { adns_answer *ans; adns_query parent; + assert(!qu->ads->bug_if_query_done_now); cancel_children(qu); qu->id= -1; @@ -500,6 +533,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); @@ -509,6 +543,7 @@ void adns__query_done(adns_query qu) { } void adns__query_fail(adns_query qu, adns_status stat) { + assert(!qu->ads->bug_if_query_done_now); adns__reset_preserved(qu); qu->answer->status= stat; adns__query_done(qu);