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 <mdw@distorted.org.uk>
}
static void checkc_global(adns_state ads) {
}
static void checkc_global(adns_state ads) {
+ const struct sortlist *sl;
int i;
assert(ads->udpsocket >= 0);
int i;
assert(ads->udpsocket >= 0);
- for (i=0; i<ads->nsortlist; i++)
- assert(!(ads->sortlist[i].base.s_addr & ~ads->sortlist[i].mask.s_addr));
+ for (i=0; i<ads->nsortlist; 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);
assert(ads->tcpserver >= 0 && ads->tcpserver < ads->nservers);
void adns__tcp_tryconnect(adns_state ads, struct timeval now) {
int r, fd, tries;
void adns__tcp_tryconnect(adns_state ads, struct timeval now) {
int r, fd, tries;
- struct sockaddr_in addr;
struct protoent *proto;
for (tries=0; tries<ads->nservers; tries++) {
struct protoent *proto;
for (tries=0; tries<ads->nservers; tries++) {
adns__diag(ads,-1,0,"unable to find protocol no. for TCP !");
return;
}
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;
if (fd<0) {
adns__diag(ads,-1,0,"cannot create TCP socket: %s",strerror(errno));
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; }
ads->tcpsocket= fd;
ads->tcpstate= server_connecting;
if (r==0) { tcp_connected(ads,now); return; }
}
for (serv= 0;
serv < ads->nservers &&
}
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",
serv++);
if (serv >= ads->nservers) {
adns__warn(ads,-1,0,"datagram received from unknown nameserver %s",
- 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));
struct timeval now;
} parseinfo;
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;
};
union checklabel_state {
struct { byte ipv[4]; } ptr;
};
} ptr;
} tinfo; /* type-specific state for the query itself: zero-init if you
* don't know better. */
} ptr;
} tinfo; /* type-specific state for the query itself: zero-init if you
* don't know better. */
struct sigaction stdsigpipe;
sigset_t stdsigmask;
struct pollfd pollfds_buf[MAX_POLLFDS];
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 in_addr base, mask;
+ int af;
+ union gen_addr base, mask;
} sortlist[MAXSORTLIST];
char **searchlist;
unsigned short rand48xsubi[3];
} sortlist[MAXSORTLIST];
char **searchlist;
unsigned short rand48xsubi[3];
static void readconfig(adns_state ads, const char *filename, int warnmissing);
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) {
+ 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; i<ads->nservers; i++) {
for (i=0; i<ads->nservers; 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) {
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;
return;
}
ss= ads->servers+ads->nservers;
+ assert(n <= sizeof(ss->addr));
+ ss->len = n;
+ memcpy(&ss->addr, sa, n);
static void ccf_nameserver(adns_state ads, const char *fn,
int lno, const char *buf) {
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;
}
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,
}
static void ccf_search(adns_state ads, const char *fn,
- 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;
}
static int init_finish(adns_state ads) {
}
static int init_finish(adns_state ads) {
+ struct sockaddr_in sin;
if (!ads->nservers) {
if (ads->logfn && ads->iflags & adns_if_debug)
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; i<ads->nservers; 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; }
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; }
}
void adns__query_send(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;
int serv, r;
adns_state ads;
assert(qu->state == query_tosend);
if ((qu->flags & adns_qf_usevc) || (qu->query_dglen > DNS_MAXUDP)) {
assert(qu->state == query_tosend);
if ((qu->flags & adns_qf_usevc) || (qu->query_dglen > DNS_MAXUDP)) {
- serv= qu->udpnextserver;
- memset(&servaddr,0,sizeof(servaddr));
-
- 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,
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);
if (r<0 && errno == EMSGSIZE) {
qu->retries= 0;
query_usetcp(qu,now);
* _intstr (mf,csp,cs)
* _manyistr (mf,cs)
* _txt (pa)
* _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)
* _domain (pap,csp,cs)
* _dom_raw (pa)
* _host_raw (pa)
- * _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,
*/
static adns_status pa_inaddr(const parseinfo *pai, int cbyte,
-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 sortlist *slp;
+ const struct in_addr *a4;
+ assert(af==AF_INET);
+ a4= ad;
for (i=0, slp=ads->sortlist;
i<ads->nsortlist &&
for (i=0, slp=ads->sortlist;
i<ads->nsortlist &&
- !((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));
-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;
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 bi<ai;
}
static int di_inaddr(adns_state ads,
const void *datap_a, const void *datap_b) {
return bi<ai;
}
static int di_inaddr(adns_state ads,
const void *datap_a, const void *datap_b) {
- const struct in_addr *ap= datap_a, *bp= datap_b;
-
- return dip_inaddr(ads,*ap,*bp);
+ return dip_genaddr(ads,AF_INET,datap_a,datap_b);
}
static adns_status cs_inaddr(vbuf *vb, const void *datap) {
}
static adns_status cs_inaddr(vbuf *vb, const void *datap) {
- * _addr (pa,di,div,csp,cs,gsz)
+ * _addr (pa,di,div,csp,cs,gsz +search_sortlist_sa, dip_sockaddr)
*/
static adns_status pa_addr(const parseinfo *pai, int cbyte,
*/
static adns_status pa_addr(const parseinfo *pai, int cbyte,
+static int search_sortlist_sa(adns_state ads, const struct sockaddr *sa) {
+ assert(sa->sa_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;
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) {
}
static int div_addr(void *context, const void *datap_a, const void *datap_b) {
if (ap->astatus != bp->astatus) return ap->astatus;
if (ap->astatus) return 0;
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,
}
static int di_hostaddr(adns_state ads,
if (lablen != l || memcmp(label, ed, l)) return adns_s_querydomainwrong;
} else {
if (lablen) return adns_s_querydomainwrong;
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]));
}
htonl((cls->ptr.ipv[0]<<24) | (cls->ptr.ipv[1]<<16) |
(cls->ptr.ipv[2]<< 8) | (cls->ptr.ipv[3]));
}
static void icb_ptr(adns_query parent, adns_query child) {
adns_answer *cans= child->answer;
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;
const unsigned char *found;
adns_state ads= parent->ads;
int i;
}
queried= &parent->ctx.tinfo.ptr.addr;
}
queried= &parent->ctx.tinfo.ptr.addr;
+ assert(queried->af == AF_INET);
+ assert(cans->type == adns_r_a);
for (i=0, found=cans->rrs.bytes; i<cans->nrrs; i++, found+=cans->rrsz) {
for (i=0, found=cans->rrs.bytes; i<cans->nrrs; 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;
if (!parent->children.head) {
adns__query_done(parent);
return;