From c0ec02b59a25b13bb6a04abd518d0d2da0fefc88 Mon Sep 17 00:00:00 2001 Message-Id: From: Mark Wooding Date: Tue, 3 Jun 2014 10:27:38 +0100 Subject: [PATCH] src/: Fix internals to carry around address families. Organization: Straylight/Edgeware From: Mark Wooding 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. 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 8839895..67a55b4 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; -- [mdw]