X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?a=blobdiff_plain;f=resolver.c;h=a39e9fcde510dea5e96bf81dcf05aad079ea982d;hb=ba703386fd742f46f83430a7c48a9bfe53167eae;hp=b8a7a34289aa13b99e635f829e6e898ebfcb2cb7;hpb=a32d56fb47ceff7404072e49a21290fc7314a7c3;p=secnet.git diff --git a/resolver.c b/resolver.c index b8a7a34..a39e9fc 100644 --- a/resolver.c +++ b/resolver.c @@ -20,6 +20,7 @@ struct adns { struct query { void *cst; + const char *name; int port; struct comm_if *comm; resolve_answer_fn *answer; @@ -34,22 +35,43 @@ static bool_t resolve_request(void *sst, cstring_t name, struct adns *st=sst; struct query *q; int rv; - const int maxlitlen=50; - + const int maxlitlen= +#ifdef CONFIG_IPV6 + ADNS_ADDR2TEXT_BUFLEN*2 +#else + 50 +#endif + ; ssize_t l=strlen(name); if (name[0]=='[' && l2 && name[l-1]==']') { char trimmed[maxlitlen+1]; memcpy(trimmed,name+1,l-2); trimmed[l-2]=0; struct comm_addr ca; - FILLZERO(ca); ca.comm=comm; + ca.ix=-1; +#ifdef CONFIG_IPV6 + socklen_t salen=sizeof(ca.ia); + rv=adns_text2addr(trimmed, port, adns_qf_addrlit_ipv4_quadonly, + &ca.ia.sa, &salen); + assert(rv!=ENOSPC); + if (rv) { + char msg[250]; + snprintf(msg,sizeof(msg),"invalid address literal: %s", + strerror(rv)); + msg[sizeof(msg)-1]=0; + cb(cst,0,0,0,name,msg); + } else { + cb(cst,&ca,1,1,name,0); + } +#else ca.ia.sin.sin_family=AF_INET; ca.ia.sin.sin_port=htons(port); if (inet_aton(trimmed,&ca.ia.sin.sin_addr)) - cb(cst,&ca,1,1); + cb(cst,&ca,1,1,name,0); else - cb(cst,0,0,0); + cb(cst,0,0,0,name,"invalid IP address"); +#endif return True; } @@ -57,6 +79,7 @@ static bool_t resolve_request(void *sst, cstring_t name, q->cst=cst; q->comm=comm; q->port=port; + q->name=name; q->answer=cb; rv=adns_submit(st->ast, name, adns_r_addr, 0, q, &q->query); @@ -95,14 +118,13 @@ static void resolver_afterpoll(void *sst, struct pollfd *fds, int nfds) if (rv==0) { q=qp; if (ans->status!=adns_s_ok) { - q->answer(q->cst,NULL,0,0); /* Failure */ + q->answer(q->cst,NULL,0,0,q->name,adns_strerror(ans->status)); free(q); free(ans); } else { int rslot, wslot, total; int ca_len=MIN(ans->nrrs,MAX_PEER_ADDRS); struct comm_addr ca_buf[ca_len]; - FILLZERO(ca_buf); for (rslot=0, wslot=0, total=0; rslotnrrs; rslot++) { @@ -111,20 +133,24 @@ static void resolver_afterpoll(void *sst, struct pollfd *fds, int nfds) adns_rr_addr *ra=&ans->rrs.addr[rslot]; struct comm_addr *ca=&ca_buf[wslot]; ca->comm=q->comm; - /* copy fields individually so we leave holes zeroed: */ + ca->ix=-1; switch (ra->addr.sa.sa_family) { case AF_INET: assert(ra->len == sizeof(ca->ia.sin)); - ca->ia.sin.sin_family=ra->addr.inet.sin_family; - ca->ia.sin.sin_addr= ra->addr.inet.sin_addr; - ca->ia.sin.sin_port= htons(q->port); - wslot++; break; - default: +#ifdef CONFIG_IPV6 + case AF_INET6: + assert(ra->len == sizeof(ca->ia.sin6)); break; +#endif /*CONFIG_IPV6*/ + default: + /* silently skip unexpected AFs from adns */ + continue; } + memcpy(&ca->ia,&ra->addr,ra->len); + wslot++; } - q->answer(q->cst,ca_buf,wslot,total); + q->answer(q->cst,ca_buf,wslot,total,q->name,0); free(q); free(ans); } @@ -174,7 +200,7 @@ static list_t *adnsresolver_apply(closure_t *self, struct cloc loc, } register_for_poll(st, resolver_beforepoll, resolver_afterpoll, - ADNS_POLLFDS_RECOMMENDED+5,"resolver"); + "resolver"); return new_closure(&st->cl); }