From b0e8338ab13a968e398e8db4e81d5022af2059a2 Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Sat, 24 May 2014 14:00:03 +0100 Subject: [PATCH] src/, client/: Use the new adns_text2addr/addr2text functions. The sortlist is now IPv6 aware. The nameserver configuration could cope with IPv6 addresses, but the transport machinery can't, so we pick them out by hand. PTR reverse-query handling still doesn't do anything special, because we don't have AAAA query support yet. I've also hacked adnshost's `-i' and `--reverse' options to use the new functions, and they'll accept IPv6 addresses, but the underlying adns_submit_reverse machinery will reject them still. Signed-off-by: Mark Wooding --- client/adh-query.c | 30 ++++++++++++----------- src/addrfam.c | 11 +++++++++ src/general.c | 4 ++-- src/internal.h | 5 ++++ src/setup.c | 60 +++++++++++++++++++++++++++++++++------------- src/types.c | 38 ++++++++++++++++++++--------- 6 files changed, 104 insertions(+), 44 deletions(-) diff --git a/client/adh-query.c b/client/adh-query.c index 63b63f4..90598fe 100644 --- a/client/adh-query.c +++ b/client/adh-query.c @@ -96,20 +96,26 @@ static void prep_query(struct query_node **qun_r, int *quflags_r) { *qun_r= qun; } + +static void sockaddr_aton(const char *text, adns_rr_addr *a) { + int err; + + a->len= sizeof(a->addr); + err= adns_text2addr(text,0,adns_qf_addrlit_scope_forbid, + &a->addr.sa,&a->len); + if (err == EINVAL) usageerr("invalid IP address %s",text); + else if (err) sysfail("adns_text2addr",err); +} void of_ptr(const struct optioninfo *oi, const char *arg, const char *arg2) { struct query_node *qun; int quflags, r; - struct sockaddr_in sa; - - memset(&sa,0,sizeof(sa)); - sa.sin_family= AF_INET; - if (!inet_aton(arg,&sa.sin_addr)) usageerr("invalid IP address %s",arg); + adns_rr_addr a; + sockaddr_aton(arg,&a); prep_query(&qun,&quflags); qun->owner= xstrsave(arg); - r= adns_submit_reverse(ads, - (struct sockaddr*)&sa, + r= adns_submit_reverse(ads, &a.addr.sa, ov_type == adns_r_none ? adns_r_ptr : ov_type, quflags, qun, @@ -122,17 +128,13 @@ void of_ptr(const struct optioninfo *oi, const char *arg, const char *arg2) { void of_reverse(const struct optioninfo *oi, const char *arg, const char *arg2) { struct query_node *qun; int quflags, r; - struct sockaddr_in sa; - - memset(&sa,0,sizeof(sa)); - sa.sin_family= AF_INET; - if (!inet_aton(arg,&sa.sin_addr)) usageerr("invalid IP address %s",arg); + adns_rr_addr a; + sockaddr_aton(arg,&a); prep_query(&qun,&quflags); qun->owner= xmalloc(strlen(arg) + strlen(arg2) + 2); sprintf(qun->owner, "%s %s", arg,arg2); - r= adns_submit_reverse_any(ads, - (struct sockaddr*)&sa, arg2, + r= adns_submit_reverse_any(ads, &a.addr.sa,arg2, ov_type == adns_r_none ? adns_r_txt : ov_type, quflags, qun, diff --git a/src/addrfam.c b/src/addrfam.c index 8a49d5b..28bf128 100644 --- a/src/addrfam.c +++ b/src/addrfam.c @@ -444,3 +444,14 @@ int adns_addr2text(const struct sockaddr *sa, adns_queryflags flags, if (port_r) *port_r= ntohs(port); return 0; } + +char *adns__sockaddr_ntoa(const struct sockaddr *sa, char *buf) { + int err; + int len= ADNS_ADDR2TEXT_BUFLEN; + + err= adns_addr2text(sa, 0, buf, &len, 0); + if (err == EIO) + err= adns_addr2text(sa, adns_qf_addrlit_scope_numeric, buf, &len, 0); + assert(!err); + return buf; +} diff --git a/src/general.c b/src/general.c index 052c7e1..75262a6 100644 --- a/src/general.c +++ b/src/general.c @@ -50,6 +50,7 @@ void adns__lprintf(adns_state ads, const char *fmt, ...) { void adns__vdiag(adns_state ads, const char *pfx, adns_initflags prevent, int serv, adns_query qu, const char *fmt, va_list al) { + char buf[ADNS_ADDR2TEXT_BUFLEN]; const char *bef, *aft; vbuf vb; @@ -83,9 +84,8 @@ void adns__vdiag(adns_state ads, const char *pfx, adns_initflags prevent, } if (serv>=0) { - assert(ads->servers[serv].addr.sa.sa_family==AF_INET); adns__lprintf(ads,"%sNS=%s",bef, - inet_ntoa(ads->servers[serv].addr.inet.sin_addr)); + adns__sockaddr_ntoa(&ads->servers[serv].addr.sa, buf)); bef=", "; aft=")\n"; } diff --git a/src/internal.h b/src/internal.h index 9a55519..6c6a77e 100644 --- a/src/internal.h +++ b/src/internal.h @@ -433,6 +433,11 @@ extern void adns__sockaddr_inject(const union gen_addr *a, int port, * byte-order). Assumes that sa->sa_family is already set correctly. */ +char *adns__sockaddr_ntoa(const struct sockaddr *sa, char *buf); +/* Convert sa to a string, and write it to buf, which must be at least + * ADNS_ADDR2TEXT_BUFLEN bytes long (unchecked). Return buf; can't fail. + */ + /* From setup.c: */ int adns__setnonblock(adns_state ads, int fd); /* => errno value */ diff --git a/src/setup.c b/src/setup.c index 03d737e..36f9213 100644 --- a/src/setup.c +++ b/src/setup.c @@ -44,22 +44,25 @@ static void readconfig(adns_state ads, const char *filename, int warnmissing); static void addserver(adns_state ads, const struct sockaddr *sa, int n) { int i; adns_rr_addr *ss; - const struct sockaddr_in *sin; + char buf[ADNS_ADDR2TEXT_BUFLEN]; - assert(sa->sa_family==AF_INET); /* for inet_ntoa */ - sin= (const void *)sa; + if (sa->sa_family != AF_INET) { + adns__debug(ads,-1,0,"non-IPv4 nameserver %s ignored", + adns__sockaddr_ntoa(sa, buf)); + return; + } for (i=0; inservers; i++) { if (adns__sockaddr_equal_p(sa, &ads->servers[i].addr.sa)) { adns__debug(ads,-1,0,"duplicate nameserver %s ignored", - inet_ntoa(sin->sin_addr)); + adns__sockaddr_ntoa(sa, buf)); return; } } if (ads->nservers>=MAXSERVERS) { adns__diag(ads,-1,0,"too many nameservers, ignoring %s", - inet_ntoa(sin->sin_addr)); + adns__sockaddr_ntoa(sa, buf)); return; } @@ -113,17 +116,26 @@ static int nextword(const char **bufp_io, const char **word_r, int *l_r) { static void ccf_nameserver(adns_state ads, const char *fn, int lno, const char *buf) { - struct sockaddr_in sin; - - memset(&sin,0,sizeof(sin)); - sin.sin_family= AF_INET; - sin.sin_port= htons(DNS_PORT); - if (!inet_aton(buf,&sin.sin_addr)) { + adns_rr_addr a; + char addrbuf[ADNS_ADDR2TEXT_BUFLEN]; + int err; + + a.len= sizeof(a.addr); + err= adns_text2addr(buf,DNS_PORT, 0, &a.addr.sa,&a.len); + switch (err) { + case 0: + break; + case EINVAL: configparseerr(ads,fn,lno,"invalid nameserver address `%s'",buf); return; + default: + configparseerr(ads,fn,lno,"failed to parse nameserver address `%s': %s", + buf,strerror(err)); + return; } - adns__debug(ads,-1,0,"using nameserver %s",inet_ntoa(sin.sin_addr)); - addserver(ads,(const struct sockaddr *)&sin,sizeof(sin)); + adns__debug(ads,-1,0,"using nameserver %s", + adns__sockaddr_ntoa(&a.addr.sa, addrbuf)); + addserver(ads,&a.addr.sa,a.len); } static void ccf_search(adns_state ads, const char *fn, @@ -159,6 +171,20 @@ static void ccf_search(adns_state ads, const char *fn, ads->searchlist= newptrs; } +static int gen_pton(const char *text, int *af_io, union gen_addr *a) { + adns_rr_addr addr; + int err; + + addr.len= sizeof(addr.addr); + err= adns_text2addr(text,0, adns_qf_addrlit_scope_forbid, + &addr.addr.sa, &addr.len); + if (err) { assert(err == EINVAL); return 0; } + if (*af_io == AF_UNSPEC) *af_io= addr.addr.sa.sa_family; + else if (*af_io != addr.addr.sa.sa_family) return 0; + adns__sockaddr_extract(&addr.addr.sa, a, 0); + return 1; +} + static void ccf_sortlist(adns_state ads, const char *fn, int lno, const char *buf) { const char *word; @@ -166,7 +192,7 @@ static void ccf_sortlist(adns_state ads, const char *fn, const char *maskwhat; struct sortlist *sl; int l; - int af= AF_UNSPEC; + int af; int initial= -1; if (!buf) return; @@ -189,16 +215,16 @@ static void ccf_sortlist(adns_state ads, const char *fn, if (slash) *slash++= 0; sl= &ads->sortlist[ads->nsortlist]; - if (!inet_aton(tbuf, &sl->base.v4)) { + af= AF_UNSPEC; + if (!gen_pton(tbuf, &af, &sl->base)) { configparseerr(ads,fn,lno,"invalid address `%s' in sortlist",tbuf); continue; } - af= AF_INET; if (slash) { if (slash[strspn(slash, "0123456789")]) { maskwhat = "mask"; - if (!inet_aton(slash, &sl->mask.v4)) { + if (!gen_pton(slash,&af,&sl->mask)) { configparseerr(ads,fn,lno,"invalid mask `%s' in sortlist",slash); continue; } diff --git a/src/types.c b/src/types.c index e0ff9e2..17cb910 100644 --- a/src/types.c +++ b/src/types.c @@ -47,7 +47,8 @@ * _intstr (mf,csp,cs) * _manyistr (mf,cs) * _txt (pa) - * _inaddr (pa,di,cs +search_sortlist, dip_genaddr) + * _inaddr (pa,di,cs + * +search_sortlist, dip_genaddr, csp_genaddr) * _addr (pa,di,div,csp,cs,gsz * +search_sortlist_sa, dip_sockaddr) * _domain (pap,csp,cs) @@ -244,7 +245,7 @@ static adns_status cs_hinfo(vbuf *vb, const void *datap) { } /* - * _inaddr (pa,di,cs +search_sortlist, dip_genaddr) + * _inaddr (pa,di,cs +search_sortlist, dip_genaddr, csp_genaddr) */ static adns_status pa_inaddr(const parseinfo *pai, int cbyte, @@ -282,15 +283,24 @@ static int di_inaddr(adns_state ads, return dip_genaddr(ads,AF_INET,datap_a,datap_b); } -static adns_status cs_inaddr(vbuf *vb, const void *datap) { - const struct in_addr *rrp= datap, rr= *rrp; - const char *ia; +static adns_status csp_genaddr(vbuf *vb, int af, const void *p) { + char buf[ADNS_ADDR2TEXT_BUFLEN]; + int len= sizeof(buf); + adns_rr_addr a; + int err; - ia= inet_ntoa(rr); assert(ia); - CSP_ADDSTR(ia); + memset(&a, 0, sizeof(a)); + a.addr.sa.sa_family= af; + adns__sockaddr_inject(p, 0, &a.addr.sa); + err= adns_addr2text(&a.addr.sa,0, buf,&len, 0); assert(!err); + CSP_ADDSTR(buf); return adns_s_ok; } +static adns_status cs_inaddr(vbuf *vb, const void *datap) { + return csp_genaddr(vb, AF_INET,datap); +} + /* * _addr (pa,di,div,csp,cs,gsz +search_sortlist_sa, dip_sockaddr) */ @@ -333,14 +343,20 @@ static int div_addr(void *context, const void *datap_a, const void *datap_b) { } static adns_status csp_addr(vbuf *vb, const adns_rr_addr *rrp) { - const char *ia; - char buf[30]; + char buf[ADNS_ADDR2TEXT_BUFLEN]; + int len= sizeof(buf); + int err; switch (rrp->addr.inet.sin_family) { case AF_INET: CSP_ADDSTR("INET "); - ia= inet_ntoa(rrp->addr.inet.sin_addr); assert(ia); - CSP_ADDSTR(ia); + goto a2t; + case AF_INET6: + CSP_ADDSTR("INET6 "); + goto a2t; + a2t: + err= adns_addr2text(&rrp->addr.sa,0, buf,&len, 0); assert(!err); + CSP_ADDSTR(buf); break; default: sprintf(buf,"AF=%u",rrp->addr.sa.sa_family); -- 2.30.2