From f930c455a13d7d30ee94bdbfc460bc6227cda111 Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Tue, 3 Jun 2014 10:27:38 +0100 Subject: [PATCH] src/: Fix internals to carry around address families. This is preparatory work for IPv6 support, but there isn't any yet. The code still acts directly on address structures (having asserted that the family is AF_INET); switching on the address family is for later. [ No functional change intended in this commit. -iwj ] Signed-off-by: Mark Wooding --- src/check.c | 11 ++++++++-- src/event.c | 15 ++++++------- src/general.c | 4 +++- src/internal.h | 16 +++++++++----- src/setup.c | 56 ++++++++++++++++++++++++++++++++---------------- src/transmit.c | 12 ++++------- src/types.c | 58 ++++++++++++++++++++++++++++++-------------------- 7 files changed, 107 insertions(+), 65 deletions(-) diff --git a/src/check.c b/src/check.c index 41cdde5..44f52b9 100644 --- a/src/check.c +++ b/src/check.c @@ -75,12 +75,19 @@ static void checkc_notcpbuf(adns_state ads) { } static void checkc_global(adns_state ads) { + const struct sortlist *sl; int i; assert(ads->udpsocket >= 0); - for (i=0; insortlist; i++) - assert(!(ads->sortlist[i].base.s_addr & ~ads->sortlist[i].mask.s_addr)); + for (i=0; insortlist; i++) { + assert(ads->sortlist[i].af==AF_INET); + assert(!(ads->sortlist[i].base.v4.s_addr & + ~ads->sortlist[i].mask.v4.s_addr)); + sl= &ads->sortlist[i]; + assert(sl->af==AF_INET); + assert(!(sl->base.v4.s_addr & ~sl->mask.v4.s_addr)); + } assert(ads->tcpserver >= 0 && ads->tcpserver < ads->nservers); diff --git a/src/event.c b/src/event.c index e22a8d1..ee4e5f7 100644 --- a/src/event.c +++ b/src/event.c @@ -96,7 +96,7 @@ static void tcp_broken_events(adns_state ads) { void adns__tcp_tryconnect(adns_state ads, struct timeval now) { int r, fd, tries; - struct sockaddr_in addr; + adns_rr_addr *addr; struct protoent *proto; for (tries=0; triesnservers; tries++) { @@ -120,7 +120,8 @@ void adns__tcp_tryconnect(adns_state ads, struct timeval now) { adns__diag(ads,-1,0,"unable to find protocol no. for TCP !"); return; } - fd= socket(AF_INET,SOCK_STREAM,proto->p_proto); + addr = &ads->servers[ads->tcpserver]; + fd= socket(addr->addr.sa.sa_family, SOCK_STREAM, proto->p_proto); if (fd<0) { adns__diag(ads,-1,0,"cannot create TCP socket: %s",strerror(errno)); return; @@ -132,11 +133,7 @@ void adns__tcp_tryconnect(adns_state ads, struct timeval now) { close(fd); return; } - memset(&addr,0,sizeof(addr)); - addr.sin_family= AF_INET; - addr.sin_port= htons(DNS_PORT); - addr.sin_addr= ads->servers[ads->tcpserver].addr; - r= connect(fd,(const struct sockaddr*)&addr,sizeof(addr)); + r= connect(fd,&addr->addr.sa,addr->len); ads->tcpsocket= fd; ads->tcpstate= server_connecting; if (r==0) { tcp_connected(ads,now); return; } @@ -418,7 +415,9 @@ int adns_processreadable(adns_state ads, int fd, const struct timeval *now) { } for (serv= 0; serv < ads->nservers && - ads->servers[serv].addr.s_addr != udpaddr.sin_addr.s_addr; + (assert(ads->servers[serv].addr.sa.sa_family==AF_INET), + ads->servers[serv].addr.inet.sin_addr.s_addr != + udpaddr.sin_addr.s_addr); serv++); if (serv >= ads->nservers) { adns__warn(ads,-1,0,"datagram received from unknown nameserver %s", diff --git a/src/general.c b/src/general.c index 6ef2cb3..052c7e1 100644 --- a/src/general.c +++ b/src/general.c @@ -83,7 +83,9 @@ void adns__vdiag(adns_state ads, const char *pfx, adns_initflags prevent, } if (serv>=0) { - adns__lprintf(ads,"%sNS=%s",bef,inet_ntoa(ads->servers[serv].addr)); + 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)); bef=", "; aft=")\n"; } diff --git a/src/internal.h b/src/internal.h index 7ad6daa..97af49e 100644 --- a/src/internal.h +++ b/src/internal.h @@ -124,6 +124,13 @@ typedef struct { struct timeval now; } parseinfo; +union gen_addr { + struct in_addr v4; + struct in6_addr v6; +}; + +struct af_addr { int af; union gen_addr addr; }; + union checklabel_state { struct { byte ipv[4]; } ptr; }; @@ -134,7 +141,7 @@ typedef struct { union { struct { - struct in_addr addr; + struct af_addr addr; } ptr; } tinfo; /* type-specific state for the query itself: zero-init if you * don't know better. */ @@ -358,11 +365,10 @@ struct adns__state { struct sigaction stdsigpipe; sigset_t stdsigmask; struct pollfd pollfds_buf[MAX_POLLFDS]; - struct server { - struct in_addr addr; - } servers[MAXSERVERS]; + adns_rr_addr servers[MAXSERVERS]; struct sortlist { - struct in_addr base, mask; + int af; + union gen_addr base, mask; } sortlist[MAXSORTLIST]; char **searchlist; unsigned short rand48xsubi[3]; diff --git a/src/setup.c b/src/setup.c index f73926c..ce44055 100644 --- a/src/setup.c +++ b/src/setup.c @@ -41,24 +41,33 @@ static void readconfig(adns_state ads, const char *filename, int warnmissing); -static void addserver(adns_state ads, struct in_addr addr) { +static void addserver(adns_state ads, const struct sockaddr *sa, int n) { int i; - struct server *ss; + adns_rr_addr *ss; + const struct sockaddr_in *sin; + + assert(sa->sa_family==AF_INET); assert(n>=sizeof(*sin)); + sin= (const void *)sa; for (i=0; inservers; i++) { - if (ads->servers[i].addr.s_addr == addr.s_addr) { - adns__debug(ads,-1,0,"duplicate nameserver %s ignored",inet_ntoa(addr)); + assert(ads->servers[i].addr.sa.sa_family==AF_INET); + if (ads->servers[i].addr.inet.sin_addr.s_addr == sin->sin_addr.s_addr) { + adns__debug(ads,-1,0,"duplicate nameserver %s ignored", + inet_ntoa(sin->sin_addr)); return; } } if (ads->nservers>=MAXSERVERS) { - adns__diag(ads,-1,0,"too many nameservers, ignoring %s",inet_ntoa(addr)); + adns__diag(ads,-1,0,"too many nameservers, ignoring %s", + inet_ntoa(sin->sin_addr)); return; } ss= ads->servers+ads->nservers; - ss->addr= addr; + assert(n <= sizeof(ss->addr)); + ss->len = n; + memcpy(&ss->addr, sa, n); ads->nservers++; } @@ -105,14 +114,17 @@ 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 in_addr ia; - - if (!inet_aton(buf,&ia)) { + 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)) { configparseerr(ads,fn,lno,"invalid nameserver address `%s'",buf); return; } - adns__debug(ads,-1,0,"using nameserver %s",inet_ntoa(ia)); - addserver(ads,ia); + adns__debug(ads,-1,0,"using nameserver %s",inet_ntoa(sin.sin_addr)); + addserver(ads,(const struct sockaddr *)&sin,sizeof(sin)); } static void ccf_search(adns_state ads, const char *fn, @@ -221,8 +233,9 @@ static void ccf_sortlist(adns_state ads, const char *fn, continue; } - ads->sortlist[ads->nsortlist].base= base; - ads->sortlist[ads->nsortlist].mask= mask; + ads->sortlist[ads->nsortlist].af= AF_INET; + ads->sortlist[ads->nsortlist].base.v4= base; + ads->sortlist[ads->nsortlist].mask.v4= mask; ads->nsortlist++; } } @@ -548,17 +561,24 @@ static int init_begin(adns_state *ads_r, adns_initflags flags, } static int init_finish(adns_state ads) { - struct in_addr ia; + struct sockaddr_in sin; struct protoent *proto; - int r; + int i, r; if (!ads->nservers) { if (ads->logfn && ads->iflags & adns_if_debug) - adns__lprintf(ads,"adns: no nameservers, using localhost\n"); - ia.s_addr= htonl(INADDR_LOOPBACK); - addserver(ads,ia); + adns__lprintf(ads,"adns: no nameservers, using IPv4 localhost\n"); + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_port = htons(DNS_PORT); + sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + addserver(ads,(struct sockaddr *)&sin, sizeof(sin)); } + /* we can't cope with multiple transport address families yet */ + for (i=0; inservers; i++) + assert(ads->servers[i].addr.sa.sa_family==AF_INET); + proto= getprotobyname("udp"); if (!proto) { r= ENOPROTOOPT; goto x_free; } ads->udpsocket= socket(AF_INET,SOCK_DGRAM,proto->p_proto); if (ads->udpsocket<0) { r= errno; goto x_free; } diff --git a/src/transmit.c b/src/transmit.c index 56140b4..ecea891 100644 --- a/src/transmit.c +++ b/src/transmit.c @@ -243,9 +243,9 @@ static void query_usetcp(adns_query qu, struct timeval now) { } void adns__query_send(adns_query qu, struct timeval now) { - struct sockaddr_in servaddr; int serv, r; adns_state ads; + adns_rr_addr *addr; assert(qu->state == query_tosend); if ((qu->flags & adns_qf_usevc) || (qu->query_dglen > DNS_MAXUDP)) { @@ -258,16 +258,12 @@ void adns__query_send(adns_query qu, struct timeval now) { return; } - serv= qu->udpnextserver; - memset(&servaddr,0,sizeof(servaddr)); - ads= qu->ads; - servaddr.sin_family= AF_INET; - servaddr.sin_addr= ads->servers[serv].addr; - servaddr.sin_port= htons(DNS_PORT); + serv= qu->udpnextserver; + addr= &ads->servers[serv]; r= sendto(ads->udpsocket,qu->query_dgram,qu->query_dglen,0, - (const struct sockaddr*)&servaddr,sizeof(servaddr)); + &addr->addr.sa,addr->len); if (r<0 && errno == EMSGSIZE) { qu->retries= 0; query_usetcp(qu,now); diff --git a/src/types.c b/src/types.c index 606435b..431fe19 100644 --- a/src/types.c +++ b/src/types.c @@ -47,8 +47,9 @@ * _intstr (mf,csp,cs) * _manyistr (mf,cs) * _txt (pa) - * _inaddr (pa,dip,di,cs +search_sortlist) - * _addr (pa,di,div,csp,cs,gsz) + * _inaddr (pa,di,cs +search_sortlist, dip_genaddr) + * _addr (pa,di,div,csp,cs,gsz + * +search_sortlist_sa, dip_sockaddr) * _domain (pap,csp,cs) * _dom_raw (pa) * _host_raw (pa) @@ -243,7 +244,7 @@ static adns_status cs_hinfo(vbuf *vb, const void *datap) { } /* - * _inaddr (pa,dip,di,cs +search_sortlist) + * _inaddr (pa,di,cs +search_sortlist, dip_genaddr) */ static adns_status pa_inaddr(const parseinfo *pai, int cbyte, @@ -255,32 +256,34 @@ static adns_status pa_inaddr(const parseinfo *pai, int cbyte, return adns_s_ok; } -static int search_sortlist(adns_state ads, struct in_addr ad) { +static int search_sortlist(adns_state ads, int af, const void *ad) { const struct sortlist *slp; + const struct in_addr *a4; int i; + assert(af==AF_INET); + a4= ad; for (i=0, slp=ads->sortlist; insortlist && - !((ad.s_addr & slp->mask.s_addr) == slp->base.s_addr); + (assert(slp->af==AF_INET), + !((a4->s_addr & slp->mask.v4.s_addr) == slp->base.v4.s_addr)); i++, slp++); return i; } -static int dip_inaddr(adns_state ads, struct in_addr a, struct in_addr b) { +static int dip_genaddr(adns_state ads, int af, const void *a, const void *b) { int ai, bi; if (!ads->nsortlist) return 0; - ai= search_sortlist(ads,a); - bi= search_sortlist(ads,b); + ai= search_sortlist(ads,af,a); + bi= search_sortlist(ads,af,b); return bisa_family == AF_INET); + return search_sortlist(ads, sa->sa_family, + &((const struct sockaddr_in *)sa)->sin_addr); +} +static int dip_sockaddr(adns_state ads, + const struct sockaddr *sa, + const struct sockaddr *sb) { + if (!ads->sortlist) return 0; + return search_sortlist_sa(ads, sa) > search_sortlist_sa(ads, sb); +} + static int di_addr(adns_state ads, const void *datap_a, const void *datap_b) { const adns_rr_addr *ap= datap_a, *bp= datap_b; - - assert(ap->addr.sa.sa_family == AF_INET); - return dip_inaddr(ads, ap->addr.inet.sin_addr, bp->addr.inet.sin_addr); + return dip_sockaddr(ads, &ap->addr.sa, &bp->addr.sa); } static int div_addr(void *context, const void *datap_a, const void *datap_b) { @@ -552,11 +565,7 @@ static int dip_hostaddr(adns_state ads, if (ap->astatus != bp->astatus) return ap->astatus; if (ap->astatus) return 0; - assert(ap->addrs[0].addr.sa.sa_family == AF_INET); - assert(bp->addrs[0].addr.sa.sa_family == AF_INET); - return dip_inaddr(ads, - ap->addrs[0].addr.inet.sin_addr, - bp->addrs[0].addr.inet.sin_addr); + return dip_sockaddr(ads, &ap->addrs[0].addr.sa, &bp->addrs[0].addr.sa); } static int di_hostaddr(adns_state ads, @@ -739,7 +748,8 @@ static adns_status ckl_ptr(adns_state ads, adns_queryflags flags, if (lablen != l || memcmp(label, ed, l)) return adns_s_querydomainwrong; } else { if (lablen) return adns_s_querydomainwrong; - ctx->tinfo.ptr.addr.s_addr= + ctx->tinfo.ptr.addr.af= AF_INET; + ctx->tinfo.ptr.addr.addr.v4.s_addr= htonl((cls->ptr.ipv[0]<<24) | (cls->ptr.ipv[1]<<16) | (cls->ptr.ipv[2]<< 8) | (cls->ptr.ipv[3])); } @@ -748,7 +758,7 @@ static adns_status ckl_ptr(adns_state ads, adns_queryflags flags, static void icb_ptr(adns_query parent, adns_query child) { adns_answer *cans= child->answer; - const struct in_addr *queried; + const struct af_addr *queried; const unsigned char *found; adns_state ads= parent->ads; int i; @@ -762,8 +772,10 @@ static void icb_ptr(adns_query parent, adns_query child) { } queried= &parent->ctx.tinfo.ptr.addr; + assert(queried->af == AF_INET); + assert(cans->type == adns_r_a); for (i=0, found=cans->rrs.bytes; inrrs; i++, found+=cans->rrsz) { - if (!memcmp(queried,found,cans->rrsz)) { + if (queried->addr.v4.s_addr == ((const struct in_addr *)found)->s_addr) { if (!parent->children.head) { adns__query_done(parent); return; -- 2.30.2