From 4353a5c47b202786905257e520fe570a570e67bc Mon Sep 17 00:00:00 2001 From: ian Date: Sun, 4 Oct 1998 16:11:22 +0000 Subject: [PATCH] Compiles again. --- client/adnstest.c | 11 +- src/Makefile | 8 +- src/Makefile.in | 8 +- src/adns.c | 17 --- src/adns.h | 69 ++++++++---- src/event.c | 280 +++++++++++++++++++++++++--------------------- src/internal.h | 79 ++++++++----- src/query.c | 88 ++++++++------- src/reply.c | 8 ++ src/setup.c | 111 ++++++++++-------- src/submit.c | 56 ++++++---- 11 files changed, 430 insertions(+), 305 deletions(-) delete mode 100644 src/adns.c create mode 100644 src/reply.c diff --git a/client/adnstest.c b/client/adnstest.c index 2ad2cc0..95f89b7 100644 --- a/client/adnstest.c +++ b/client/adnstest.c @@ -8,13 +8,22 @@ int main(void) { adns_state ads; adns_query qu; + adns_answer *ans; int r; - r= adns_init(&ads,adns_if_debug|adns_if_noautosys); + r= adns_init(&ads,adns_if_debug|adns_if_noautosys,0); if (r) { perror("init"); exit(2); } r= adns_submit(ads,"anarres.greenend.org.uk",adns_r_a,0,0,&qu); if (r) { perror("submit"); exit(2); } + + r= adns_wait(ads,&qu,&ans,0); + if (r) { perror("wait"); exit(2); } + + if (!ans) { fputs("no answer\n",stderr); exit(2); } + fprintf(stderr,"answer status %d type %d rrs %d cname %s\n", + ans->status,ans->type,ans->nrrs, + ans->cname ? ans->cname : "-"); exit(0); } diff --git a/src/Makefile b/src/Makefile index 23d901a..46b6be9 100644 --- a/src/Makefile +++ b/src/Makefile @@ -7,6 +7,10 @@ WERROR=-Werror all: dtest -dtest: dtest.o event.o query.o setup.o submit.o +dtest: dtest.o event.o query.o setup.o submit.o reply.o + +clean: + rm -f dtest *.o + +dtest.o event.o query.o setup.o submit.o reply.o: internal.h adns.h -%.o: adns-internal.h adns.h diff --git a/src/Makefile.in b/src/Makefile.in index 23d901a..46b6be9 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -7,6 +7,10 @@ WERROR=-Werror all: dtest -dtest: dtest.o event.o query.o setup.o submit.o +dtest: dtest.o event.o query.o setup.o submit.o reply.o + +clean: + rm -f dtest *.o + +dtest.o event.o query.o setup.o submit.o reply.o: internal.h adns.h -%.o: adns-internal.h adns.h diff --git a/src/adns.c b/src/adns.c deleted file mode 100644 index 6c4a7cf..0000000 --- a/src/adns.c +++ /dev/null @@ -1,17 +0,0 @@ -/**/ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "adns-internal.h" diff --git a/src/adns.h b/src/adns.h index f749f6e..90b166b 100644 --- a/src/adns.h +++ b/src/adns.h @@ -3,6 +3,8 @@ #ifndef ADNS_H_INCLUDED #define ADNS_H_INCLUDED +#include + #include #include @@ -34,39 +36,39 @@ typedef enum { adns_r_none= 0, adns_r_a= 1, - adns_r_a_mf= adns_r_a|adns__qtf_mf, + adns_r_a_mf= adns_r_a|adns__qtf_masterfmt, adns_r_ns_raw= 2, adns_r_ns= adns_r_ns_raw|adns__qtf_deref, - adns_r_ns_mf= adns_r_ns_raw|adns__qtf_mf, + adns_r_ns_mf= adns_r_ns_raw|adns__qtf_masterfmt, adns_r_cname= 5, - adns_r_cname_mf= adns_r_cname|adns__qtf_mf, + adns_r_cname_mf= adns_r_cname|adns__qtf_masterfmt, adns_r_soa_raw= 6, adns_r_soa= adns_r_soa_raw|adns__qtf_mail822, - adns_r_soa_mf= adns_r_soa_raw|adns__qtf_mf, + adns_r_soa_mf= adns_r_soa_raw|adns__qtf_masterfmt, adns_r_null= 10, - adns_r_null_mf= adns_r_null|adns__qtf_mf, + adns_r_null_mf= adns_r_null|adns__qtf_masterfmt, adns_r_ptr_raw= 12, adns_r_ptr= adns_r_ptr_raw|adns__qtf_deref, - adns_r_ptr_mf= adns_r_ptr_raw|adns__qtf_mf, + adns_r_ptr_mf= adns_r_ptr_raw|adns__qtf_masterfmt, adns_r_hinfo= 13, - adns_r_hinfo_mf= adns_r_hinfo|adns__qtf_mf, + adns_r_hinfo_mf= adns_r_hinfo|adns__qtf_masterfmt, adns_r_mx_raw= 15, adns_r_mx= adns_r_mx_raw|adns__qtf_deref, - adns_r_mx_mf= adns_r_mx_raw|adns__qtf_mf, + adns_r_mx_mf= adns_r_mx_raw|adns__qtf_masterfmt, adns_r_txt= 16, - adns_r_txt_mf= adns_r_txt|adns__qtf_mf, + adns_r_txt_mf= adns_r_txt|adns__qtf_masterfmt, adns_r_rp_raw= 17, - adns_r_rp= adns_r_rp_raw|adns__qtf_mail822 - adns_r_rp_mf= adns_r_rp_raw|adns__qtf_mf, + adns_r_rp= adns_r_rp_raw|adns__qtf_mail822, + adns_r_rp_mf= adns_r_rp_raw|adns__qtf_masterfmt } adns_rrtype; @@ -95,7 +97,7 @@ typedef enum { adns_s_max_tempfail= 99, adns_s_inconsistent, /* PTR gives domain whose A does not match */ adns_s_cname, /* CNAME found where data eg A expected (not if _qf_loosecname) */ - adns_s_max_misconfig= 199; + adns_s_max_misconfig= 199, adns_s_nxdomain, adns_s_norecord, adns_s_invaliddomain @@ -106,7 +108,26 @@ typedef struct { adns_status astatus; int naddrs; /* temp fail => -1, perm fail => 0, s_ok => >0 */ struct in_addr *addrs; -} adns_dmaddr; +} adns_rr_dmaddr; + +typedef struct { + char *a, *b; +} adns_rr_strpair; + +typedef struct { + int i; + adns_rr_dmaddr dmaddr; +} adns_rr_intdmaddr; + +typedef struct { + int i; + char *str; +} adns_rr_intstr; + +typedef struct { + char *ns0, *rp; + unsigned long serial, refresh, retry, expire, minimum; +} adns_rr_soa; typedef struct { adns_status status; @@ -114,16 +135,13 @@ typedef struct { adns_rrtype type; int nrrs; union { - struct in_addr inaddr[1]; /* a */ - char (*str)[1]; /* ns_raw, cname, ptr, ptr_raw, txt, _mf */ - adns_dmaddr dmaddr[1]; /* ns */ - struct { char *a, *b; } strpair[1]; /* hinfo, rp, rp_raw */ - struct { int pref; adns_dmaddrs dmaddr; } intdmaddr[1]; /* mx */ - struct { int pref; char *str; } intstr[1]; /* mx_raw */ - struct { - char *ns0, *rp; - unsigned long serial, refresh, retry, expire, minimum; - } soa[1]; /* soa, soa_raw */ + struct in_addr *inaddr; /* a */ + char *(*str); /* ns_raw, cname, ptr, ptr_raw, txt, _mf */ + adns_rr_dmaddr *dmaddr; /* ns */ + adns_rr_strpair *strpair; /* hinfo, rp, rp_raw */ + adns_rr_intdmaddr *intdmaddr; /* mx */ + adns_rr_intstr *intstr; /* mx_raw */ + adns_rr_soa *soa; /* soa, soa_raw */ /* NULL is empty */ } rrs; } adns_answer; @@ -131,7 +149,8 @@ typedef struct { /* Memory management: * adns_state and adns_query are actually pointers to malloc'd state; * On submission questions are copied, including the owner domain; - * Answers are malloc'd as a single piece of memory. + * Answers are malloc'd as a single piece of memory; pointers in the + * answer struct point into further memory in the answer. * query_io: * Must always be non-null pointer; * If *query_io is 0 to start with then any query may be returned; @@ -195,6 +214,8 @@ int adns_callback(adns_state, int maxfd, const fd_set *readfds, const fd_set *wr * Other fd's may be in the fd_sets, and will be ignored. * _callback returns how many adns fd's were in the various sets, so * you can tell if your select handling code has missed something and is going awol. + * + * May also return -1 if a critical syscall failed, setting errno. */ void adns_interest(adns_state, int *maxfd_io, fd_set *readfds_io, diff --git a/src/event.c b/src/event.c index 81e8d4a..14ce1b0 100644 --- a/src/event.c +++ b/src/event.c @@ -1,37 +1,47 @@ /**/ -#include "adns-internal.h" +#include +#include +#include + +#include +#include + +#include "internal.h" /* TCP connection management */ void adns__tcp_broken(adns_state ads, const char *what, const char *why) { int serv; + adns_query qu, nqu; assert(ads->tcpstate == server_connecting || ads->tcpstate == server_ok); serv= ads->tcpserver; - warn("TCP connection lost: %s: %s",serv,why); + adns__warn(ads,serv,"TCP connection lost: %s: %s",what,why); close(ads->tcpsocket); ads->tcpstate= server_disconnected; - for (qu= ads->timew; qu; qu= nqu) { + for (qu= ads->timew.head; qu; qu= nqu) { nqu= qu->next; if (qu->state == query_udp) continue; assert(qu->state == query_tcpwait || qu->state == query_tcpsent); qu->state= query_tcpwait; qu->tcpfailed |= (1<tcpfailed == (1<nservers)-1) { - DLIST_UNLINK(ads->timew,qu); + LIST_UNLINK(ads->timew,qu); adns__query_fail(ads,qu,adns_s_allservfail); } } - ads->tcpbuf.used= 0; + ads->tcprecv.used= ads->tcpsend.used= 0; ads->tcpserver= (serv+1)%ads->nservers; } static void tcp_connected(adns_state ads, struct timeval now) { - debug("TCP connected",ads->tcpserver); - ads->tcpstate= server_connected; + adns_query qu, nqu; + + adns__debug(ads,ads->tcpserver,"TCP connected"); + ads->tcpstate= server_ok; for (qu= ads->timew.head; qu; qu= nqu) { nqu= qu->next; if (qu->state == query_udp) continue; @@ -42,19 +52,29 @@ static void tcp_connected(adns_state ads, struct timeval now) { void adns__tcp_tryconnect(adns_state ads, struct timeval now) { int r, fd, tries; - sockaddr_in addr; + struct sockaddr_in addr; + struct protoent *proto; /* fixme: single TCP timeout, not once per server */ for (tries=0; triesnservers; tries++) { if (ads->tcpstate == server_connecting || ads->tcpstate == server_ok) return; assert(ads->tcpstate == server_disconnected); - assert(!ads->tcpbuf.used); + assert(!ads->tcpsend.used); + assert(!ads->tcprecv.used); proto= getprotobyname("tcp"); - if (!proto) { diag(ads,"unable to find protocol number for TCP !",-1); return; } + if (!proto) { adns__diag(ads,-1,"unable to find protocol no. for TCP !"); return; } fd= socket(AF_INET,SOCK_STREAM,proto->p_proto); - if (fd<0) { diag(ads,"cannot create TCP socket: %s",-1,strerror(errno)); return; } - if (!adns__setnonblock(fd)) return; + if (fd<0) { + adns__diag(ads,-1,"cannot create TCP socket: %s",strerror(errno)); + return; + } + r= adns__setnonblock(ads,fd); + if (r) { + adns__diag(ads,-1,"cannot make TCP socket nonblocking: %s",strerror(r)); + close(fd); + return; + } memset(&addr,0,sizeof(addr)); addr.sin_family= AF_INET; addr.sin_port= htons(NSPORT); @@ -62,12 +82,97 @@ void adns__tcp_tryconnect(adns_state ads, struct timeval now) { r= connect(fd,&addr,sizeof(addr)); ads->tcpsocket= fd; ads->tcpstate= server_connecting; - if (r==0) { tcp_connected(ads); continue; } + if (r==0) { tcp_connected(ads,now); continue; } if (errno == EWOULDBLOCK || errno == EINPROGRESS) return; adns__tcp_broken(ads,"connect",strerror(errno)); } } +/* `Interest' functions - find out which fd's we might be interested in, + * and when we want to be called back for a timeout. + */ + +static void inter_maxto(struct timeval **tv_io, struct timeval *tvbuf, + struct timeval maxto) { + struct timeval *rbuf; + + if (!tv_io) return; + rbuf= *tv_io; + if (!rbuf) { *tvbuf= maxto; *tv_io= tvbuf; return; } + if (timercmp(rbuf,&maxto,>)) *rbuf= maxto; +} + +static void inter_maxtoabs(struct timeval **tv_io, struct timeval *tvbuf, + struct timeval now, struct timeval maxtime) { + ldiv_t dr; + + if (!tv_io) return; + maxtime.tv_sec -= (now.tv_sec-1); + maxtime.tv_usec += (1000-now.tv_usec); + dr= ldiv(maxtime.tv_usec,1000); + maxtime.tv_sec += dr.quot; + maxtime.tv_usec -= dr.rem; + inter_maxto(tv_io,tvbuf,maxtime); +} + +static void inter_addfd(int *maxfd, fd_set *fds, int fd) { + if (!maxfd || !fds) return; + if (fd>=*maxfd) *maxfd= fd+1; + FD_SET(fd,fds); +} + +static void checktimeouts(adns_state ads, struct timeval now, + struct timeval **tv_io, struct timeval *tvbuf) { + adns_query qu, nqu; + + for (qu= ads->timew.head; qu; qu= nqu) { + nqu= qu->next; + if (timercmp(&now,&qu->timeout,>)) { + LIST_UNLINK(ads->timew,qu); + if (qu->state != query_udp) { + adns__query_fail(ads,qu,adns_s_timeout); + } else { + adns__query_udp(ads,qu,now); + } + } else { + inter_maxtoabs(tv_io,tvbuf,now,qu->timeout); + } + } +} + +void adns_interest(adns_state ads, int *maxfd, + fd_set *readfds, fd_set *writefds, fd_set *exceptfds, + struct timeval **tv_io, struct timeval *tvbuf) { + struct timeval now; + struct timeval tvto_lr; + int r; + + r= gettimeofday(&now,0); + if (r) { + adns__warn(ads,-1,"gettimeofday failed - will sleep for a bit: %s",strerror(errno)); + timerclear(&tvto_lr); timevaladd(&tvto_lr,LOCALRESOURCEMS); + inter_maxto(tv_io, tvbuf, tvto_lr); + } else { + checktimeouts(ads,now,tv_io,tvbuf); + } + + inter_addfd(maxfd,readfds,ads->udpsocket); + + switch (ads->tcpstate) { + case server_disconnected: + break; + case server_connecting: + inter_addfd(maxfd,writefds,ads->tcpsocket); + break; + case server_ok: + inter_addfd(maxfd,readfds,ads->tcpsocket); + inter_addfd(maxfd,exceptfds,ads->tcpsocket); + if (ads->tcpsend.used) inter_addfd(maxfd,writefds,ads->tcpsocket); + default: + abort(); + } +} + /* Callback procedures - these do the real work of reception and timeout, etc. */ static int callb_checkfd(int maxfd, const fd_set *fds, int fd) { @@ -77,10 +182,10 @@ static int callb_checkfd(int maxfd, const fd_set *fds, int fd) { static int internal_callback(adns_state ads, int maxfd, const fd_set *readfds, const fd_set *writefds, - const fd_set *exceptfds) { - int skip, dgramlen, count, udpaddrlen, oldtcpsocket; - enum adns__tcpstate oldtcpstate; - unsigned char udpbuf[UDPMAXDGRAM]; + const fd_set *exceptfds, + struct timeval now) { + int skip, want, dgramlen, count, udpaddrlen, r, serv; + byte udpbuf[MAXUDPDGRAM]; struct sockaddr_in udpaddr; count= 0; @@ -92,15 +197,15 @@ static int internal_callback(adns_state ads, int maxfd, if (callb_checkfd(maxfd,writefds,ads->tcpsocket)) { count++; assert(ads->tcprecv.used==0); - vbuf_ensure(&ads->tcprecv,1); + adns__vbuf_ensure(&ads->tcprecv,1); if (ads->tcprecv.buf) { r= read(ads->tcpsocket,&ads->tcprecv.buf,1); if (r==0 || (r<0 && (errno==EAGAIN || errno==EWOULDBLOCK))) { - tcpserver_connected(ads); + tcp_connected(ads,now); } else if (r>0) { - tcpserver_broken(ads,"connect/read","sent data before first request"); + adns__tcp_broken(ads,"connect/read","sent data before first request"); } else if (errno!=EINTR) { - tcpserver_broken(ads,"connect/read",strerror(errno)); + adns__tcp_broken(ads,"connect/read",strerror(errno)); } } } @@ -119,13 +224,13 @@ static int internal_callback(adns_state ads, int maxfd, if (ads->tcprecv.usedtcprecv.buf+skip+2,dgramlen,ads->tcpserver); + adns__procdgram(ads,ads->tcprecv.buf+skip+2,dgramlen,ads->tcpserver); skip+= 2+dgramlen; continue; } } ads->tcprecv.used -= skip; memmove(ads->tcprecv.buf,ads->tcprecv.buf+skip,ads->tcprecv.used); - vbuf_ensure(&ads->tcprecv,want); + adns__vbuf_ensure(&ads->tcprecv,want); if (ads->tcprecv.used >= ads->tcprecv.avail) break; r= read(ads->tcpsocket, ads->tcprecv.buf+ads->tcprecv.used, @@ -137,17 +242,17 @@ static int internal_callback(adns_state ads, int maxfd, if (errno==EAGAIN || errno==EWOULDBLOCK || errno==ENOMEM) break; if (errno==EINTR) continue; } - tcpserver_broken(ads->tcpserver,"read",r?strerror(errno):"closed"); + adns__tcp_broken(ads,"read",r?strerror(errno):"closed"); break; } } } else if (callb_checkfd(maxfd,exceptfds,ads->tcpsocket)) { - tcpserver_broken(ads->tcpserver,"select","exceptional condition detected"); + adns__tcp_broken(ads,"select","exceptional condition detected"); } else if (ads->tcpsend.used && callb_checkfd(maxfd,writefds,ads->tcpsocket)) { r= write(ads->tcpsocket,ads->tcpsend.buf,ads->tcpsend.used); if (r<0) { if (errno!=EAGAIN && errno!=EWOULDBLOCK && errno!=ENOMEM && errno!=EINTR) { - tcpserver_broken(ads->tcpserver,"write",strerror(errno)); + adns__tcp_broken(ads,"write",strerror(errno)); } } else if (r>0) { ads->tcpsend.used -= r; @@ -166,22 +271,22 @@ static int internal_callback(adns_state ads, int maxfd, if (r<0) { if (!(errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR || errno == ENOMEM || errno == ENOBUFS)) - warn("datagram receive error: %s",strerror(errno)); + adns__warn(ads,-1,"datagram receive error: %s",strerror(errno)); break; } if (udpaddrlen != sizeof(udpaddr)) { - diag("datagram received with wrong address length %d (expected %d)", - udpaddrlen,sizeof(udpaddr)); + adns__diag(ads,-1,"datagram received with wrong address length %d (expected %d)", + udpaddrlen,sizeof(udpaddr)); continue; } if (udpaddr.sin_family != AF_INET) { - diag("datagram received with wrong protocol family %u (expected %u)", - udpaddr.sin_family,AF_INET); + adns__diag(ads,-1,"datagram received with wrong protocol family" + " %u (expected %u)",udpaddr.sin_family,AF_INET); continue; } if (ntohs(udpaddr.sin_port) != NSPORT) { - diag("datagram received from wrong port %u (expected %u)", - ntohs(udpaddr.sin_port),NSPORT); + adns__diag(ads,-1,"datagram received from wrong port %u (expected %u)", + ntohs(udpaddr.sin_port),NSPORT); continue; } for (serv= 0; @@ -189,111 +294,30 @@ static int internal_callback(adns_state ads, int maxfd, ads->servers[serv].addr.s_addr != udpaddr.sin_addr.s_addr; serv++); if (serv >= ads->nservers) { - warn("datagram received from unknown nameserver %s",inet_ntoa(udpaddr.sin_addr)); + adns__warn(ads,-1,"datagram received from unknown nameserver %s", + inet_ntoa(udpaddr.sin_addr)); continue; } - procdgram(ads,udpbuf,r,serv); + adns__procdgram(ads,udpbuf,r,serv); } } + return count; } -static void checktimeouts(adns_state ads, struct timeval now, - struct timeval **tv_io, struct timeval *tvbuf) { - for (qu= ads->timew; qu; qu= nqu) { - nqu= qu->next; - if (timercmp(&now,qu->timeout,>)) { - DLIST_UNLINK(ads->timew,qu); - if (qu->state != state_udp) { - query_fail(ads,qu,adns_s_notresponding); - } else { - adns__query_udp(ads,qu,now); - } - } else { - inter_maxtoabs(tv_io,tvbuf,now,qu->timeout); - } - } -} - int adns_callback(adns_state ads, int maxfd, const fd_set *readfds, const fd_set *writefds, const fd_set *exceptfds) { struct timeval now; - - r= gettimeofday(&now,0); - if (!r) checktimeouts(ads,now,0,0); - return internal_callback(ads,maxfd,readfds,writefds,exceptfds); -} - -/* `Interest' functions - find out which fd's we might be interested in, - * and when we want to be called back for a timeout. - */ - -static void inter_maxto(struct timeval **tv_io, struct timeval *tvbuf, - struct timeval maxto) { - struct timeval rbuf; - - if (!tv_io) return; - rbuf= *tv_io; - if (!rbuf) { *tvbuf= maxto; *tv_io= tvbuf; return; } - if (timercmp(rbuf,&maxto,>)) *rbuf= maxto; -} - -static void inter_maxtoabs(struct timeval **tv_io, struct timeval *tvbuf, - struct timeval now, struct timeval maxtime) { - ldiv_t dr; - - if (!tv_io) return; - maxtime.tv_sec -= (now.tv_sec-1); - maxtime.tv_usec += (1000-now.tv_usec); - dr= ldiv(maxtime.tv_usec,1000); - maxtime.tv_sec += dr.quot; - maxtime.tv_usec -= dr.rem; - inter_maxto(tv_io,tvbuf,maxtime); -} - -static void inter_addfd(int *maxfd, fd_set *fds, int fd) { - if (!maxfd || !fds) return; - if (fd>=*maxfd) *maxfd= fd+1; - FD_SET(fd,fds); -} - -void adns_interest(adns_state ads, int *maxfd, - fd_set *readfds, fd_set *writefds, fd_set *exceptfds, - struct timeval **tv_io, struct timeval *tvbuf) { - struct timeval now; - struct timeval tvto_lr; - adns_query qu; int r; - - r= gettimeofday(&now,0); - if (r) { - warn(ads,"gettimeofday failed - will sleep for a bit: %s",-1,strerror(errno)); - timerclear(&tvto_lr); timevaladd(&tvto_lr,LOCALRESOURCEMS); - inter_maxto(tv_io, tvbuf, tvto_lr); - } else { - checktimeouts(ads,now,tv_io,tvbuf); - } - - inter_addfd(maxfd,readfds,ads->udpsocket); - switch (ads->tcpstate) { - case server_disc: - break; - case server_connecting: - inter_addfd(maxfd,writefds,ads->tcpsocket); - break; - case server_connected: - inter_addfd(maxfd,readfds,ads->tcpsocket); - inter_addfd(maxfd,exceptfds,ads->tcpsocket); - if (ads->opbufused) inter_addfd(maxfd,writefds,ads->tcpsocket); - default: - abort(); - } + r= gettimeofday(&now,0); if (r) return -1; + checktimeouts(ads,now,0,0); + return internal_callback(ads,maxfd,readfds,writefds,exceptfds,now); } /* User-visible functions and their implementation. */ -static void autosys(adns_state ads, struct timeval now) { +void adns__autosys(adns_state ads, struct timeval now) { if (ads->iflags & adns_if_noautosys) return; adns_callback(ads,-1,0,0,0); } @@ -312,8 +336,8 @@ static int internal_check(adns_state ads, if (qu->id>=0) return EWOULDBLOCK; } LIST_UNLINK(ads->output,qu); - *answer= qu->answer; - if (context_r) *context_r= qu->context; + *answer= (adns_answer*)qu->answer.buf; + if (context_r) *context_r= qu->context.ext; free(qu); return 0; } @@ -334,7 +358,7 @@ int adns_wait(adns_state ads, adns_interest(ads,&maxfd,&readfds,&writefds,&exceptfds,&tvp,&tvbuf); rsel= select(maxfd,&readfds,&writefds,&exceptfds,tvp); if (rsel==-1) return r; - rcb= internal_callback(ads,maxfd,&readfds,&writefds,&exceptfds); + rcb= adns_callback(ads,maxfd,&readfds,&writefds,&exceptfds); assert(rcb==rsel); } } @@ -343,6 +367,10 @@ int adns_check(adns_state ads, adns_query *query_io, adns_answer **answer_r, void **context_r) { - autosys(ads); + struct timeval now; + int r; + + r= gettimeofday(&now,0); if (r) return errno; + adns__autosys(ads,now); return internal_check(ads,query_io,answer_r,context_r); } diff --git a/src/internal.h b/src/internal.h index eaa3a6d..b652f23 100644 --- a/src/internal.h +++ b/src/internal.h @@ -3,6 +3,13 @@ #ifndef ADNS_INTERNAL_H_INCLUDED #define ADNS_INTERNAL_H_INCLUDED +#define PRINTFFORMAT(a,b) __attribute__((format(printf,a,b))) +typedef unsigned char byte; + +#include +#include +#include + #include #include "adns.h" @@ -14,39 +21,48 @@ #define UDPRETRYMS 2000 #define TCPMS 30000 #define LOCALRESOURCEMS 20 -#define UDPMAXDGRAM 512 +#define MAXUDPDGRAM 512 #define NSPORT 53 +#define MAXDNAME 255 /* Shared data structures */ -union adns__align { +typedef union { adns_status status; char *cp; adns_rrtype type; - int int; + int i; struct in_addr ia; unsigned long ul; -}; +} rr_align; + +typedef struct { + int used, avail; + byte *buf; +} vbuf; + +typedef union { + void *ext; + int dmaddr_index; +} qcontext; struct adns__query { /* FIXME: make sure this is all init'd properly */ enum { query_udp, query_tcpwait, query_tcpsent, query_child, query_done } state; - adns_query back, next; - adns_query parent; + adns_query back, next, parent; struct { adns_query head, tail; } children; struct { adns_query back, next; } siblings; adns_rrtype type; - adns_answer *answer; - size_t ansalloc; ansused; + vbuf answer; int id, flags, udpretries; - int nextudpserver; - unsigned long sentudp, failedtcp; /* bitmap indexed by server */ + int udpnextserver; + unsigned long udpsent, tcpfailed; /* bitmap indexed by server */ struct timeval timeout; - void *context; - unsigned char *querymsg; + byte *querymsg; int querylen; + qcontext context; char owner[1]; - /* After the owner name and nul comes the query message */ + /* After the owner name and nul comes the query message, pointed to by querymsg */ /* Possible states: * @@ -101,21 +117,14 @@ struct adns__query { */ }; -typedef struct { - size_t used, avail; - unsigned char *buf; -} adns__vbuf; - struct adns__state { - /* FIXME: make sure this is all init'd properly */ adns_initflags iflags; FILE *diagfile; struct { adns_query head, tail; } timew, childw, output; - int nextid, udpsocket; - adns_vbuf rqbuf, tcpsend, tcprecv; + int nextid, udpsocket, tcpsocket; + vbuf rqbuf, tcpsend, tcprecv; int nservers, tcpserver; enum adns__tcpstate { server_disconnected, server_connecting, server_ok } tcpstate; - int tcpsocket; struct timeval tcptimeout; struct server { struct in_addr addr; @@ -124,19 +133,23 @@ struct adns__state { /* From setup.c: */ -void adns__vdiag(adns_state ads, adns_initflags prevent, const char *pfx, +void adns__vdiag(adns_state ads, const char *pfx, adns_initflags prevent, int serv, const char *fmt, va_list al); void adns__debug(adns_state ads, int serv, const char *fmt, ...) PRINTFFORMAT(3,4); void adns__warn(adns_state ads, int serv, const char *fmt, ...) PRINTFFORMAT(3,4); void adns__diag(adns_state ads, int serv, const char *fmt, ...) PRINTFFORMAT(3,4); -static inline int adns__vbuf_ensure(adns__vbuf *vb, size_t want); -int adns__vbuf_append(adns__vbuf *vb, const byte *data, size_t len); -int adns__vbuf_appendq(adns__vbuf *vb, const byte *data, size_t len); +int adns__vbuf_ensure(vbuf *vb, int want); +int adns__vbuf_append(vbuf *vb, const byte *data, int len); /* 1=>success, 0=>realloc failed */ +void adns__vbuf_appendq(vbuf *vb, const byte *data, int len); +void adns__vbuf_init(vbuf *vb); + +int adns__setnonblock(adns_state ads, int fd); /* => errno value */ /* From submit.c: */ +void adns__query_nomem(adns_state ads, adns_query qu); void adns__query_fail(adns_state ads, adns_query qu, adns_status stat); /* From query.c: */ @@ -144,11 +157,17 @@ void adns__query_fail(adns_state ads, adns_query qu, adns_status stat); void adns__query_udp(adns_state ads, adns_query qu, struct timeval now); void adns__query_tcp(adns_state ads, adns_query qu, struct timeval now); adns_status adns__mkquery(adns_state ads, const char *owner, int ol, int id, - adns_rrtype type, adns_queryflags flags, int *qml_r); + adns_rrtype type, adns_queryflags flags); + +/* From reply.c: */ + +void adns__procdgram(adns_state ads, const byte *dgram, int len, int serv); /* From event.c: */ + void adns__tcp_broken(adns_state ads, const char *what, const char *why); -void adns__tcp_tryconnect(adns_state ads); +void adns__tcp_tryconnect(adns_state ads, struct timeval now); +void adns__autosys(adns_state ads, struct timeval now); /* Useful static inline functions: */ @@ -167,6 +186,8 @@ static inline int ctype_digit(int c) { return c>='0' && c<='9'; } /* Useful macros */ +#define LIST_INIT(list) ((list).head= (list).tail= 0) + #define LIST_UNLINK_PART(list,node,part) \ do { \ if ((node)->back) (node)->back->part next= (node)->part next; \ @@ -184,6 +205,6 @@ static inline int ctype_digit(int c) { return c>='0' && c<='9'; } } while(0) #define LIST_UNLINK(list,node) LIST_UNLINK_PART(list,node,) -#define LIST_LINK_TAIL_PART(list,node) LIST_LINK_TAIL(list,node,) +#define LIST_LINK_TAIL(list,node) LIST_LINK_TAIL_PART(list,node,) #endif diff --git a/src/query.c b/src/query.c index bd7af8a..8aef532 100644 --- a/src/query.c +++ b/src/query.c @@ -1,18 +1,23 @@ /**/ +#include +#include + +#include + #include "internal.h" adns_status adns__mkquery(adns_state ads, const char *owner, int ol, int id, adns_rrtype type, adns_queryflags flags) { /* Assembles a query packet in ads->rqbuf. */ int ll, c, nlabs; - unsigned char label[255], *rqp; + byte label[255], *rqp; const char *p, *pe; #define MKQUERY_ADDB(b) *rqp++= (b) #define MKQUERY_ADDW(w) (MKQUERY_ADDB(((w)>>8)&0x0ff), MKQUERY_ADDB((w)&0x0ff)) - if (!vbuf_ensure(&ads->rqbuf,12+strlen(owner)+3)) return adns_s_nolocalmem; + if (!adns__vbuf_ensure(&ads->rqbuf,12+strlen(owner)+3)) return adns_s_nolocalmem; rqp= ads->rqbuf.buf; MKQUERY_ADDW(id); @@ -29,7 +34,7 @@ adns_status adns__mkquery(adns_state ads, const char *owner, int ol, int id, ll= 0; while (p!=pe && (c= *p++)!='.') { if (c=='\\') { - if (!(flags & adns_f_anyquote)) return adns_s_invaliddomain; + if (!(flags & adns_qf_anyquote)) return adns_s_invaliddomain; if (ctype_digit(p[0])) { if (ctype_digit(p[1]) && ctype_digit(p[2])) { c= (*p++ - '0')*100 + (*p++ - '0')*10 + (*p++ - '0'); @@ -41,7 +46,7 @@ adns_status adns__mkquery(adns_state ads, const char *owner, int ol, int id, return adns_s_invaliddomain; } } - if (!(flags & adns_f_anyquote)) { + if (!(flags & adns_qf_anyquote)) { if (ctype_digit(c) || c == '-') { if (!ll) return adns_s_invaliddomain; } else if ((c < 'a' || c > 'z') && (c < 'A' && c > 'Z')) { @@ -61,13 +66,13 @@ adns_status adns__mkquery(adns_state ads, const char *owner, int ol, int id, MKQUERY_ADDW(type & adns__rrt_typemask); /* QTYPE */ MKQUERY_ADDW(1); /* QCLASS=IN */ - ads->rqbuf.used= rqp - ads->rqbuf.used; + ads->rqbuf.used= rqp - ads->rqbuf.buf; assert(ads->rqbuf.used < ads->rqbuf.avail); return adns_s_ok; } -void adns__query_tcp(adns_state ads, adns_query qu) { +void adns__query_tcp(adns_state ads, adns_query qu, struct timeval now) { /* Query must be in state tcpwait/timew; it will be moved to a new state * if possible and no further processing can be done on it for now. * (Resulting state is one of tcpwait/timew (if server not connected), @@ -78,27 +83,28 @@ void adns__query_tcp(adns_state ads, adns_query qu) { * may break. If the conn list lost then the caller is responsible for any * reestablishment and retry. */ - unsigned char length[2]; + byte length[2]; struct iovec iov[2]; + int wr, r; if (ads->tcpstate != server_ok) return; length[0]= (qu->querylen&0x0ff00U) >>8; length[1]= (qu->querylen&0x0ff); - if (!vbuf_ensure(&ads->tcpsend,ads->tcpsend.used+qu->querylen+2)) return; + if (!adns__vbuf_ensure(&ads->tcpsend,ads->tcpsend.used+qu->querylen+2)) return; timevaladd(&now,TCPMS); qu->timeout= now; - qu->senttcpserver= ads->tcpserver; - DLIST_LINKTAIL(ads->timew,qu); + qu->state= query_tcpsent; + LIST_LINK_TAIL(ads->timew,qu); - if (ads->opbufused) { + if (ads->tcpsend.used) { wr= 0; } else { - iov[0].iovbase= length; + iov[0].iov_base= length; iov[0].iov_len= 2; - iov[1].iovbase= qu->querymsg; + iov[1].iov_base= qu->querymsg; iov[1].iov_len= qu->querylen; wr= writev(ads->tcpsocket,iov,2); if (wr < 0) { @@ -112,13 +118,13 @@ void adns__query_tcp(adns_state ads, adns_query qu) { } if (wr<2) { - r= vbuf_append(&ads->tcpsend,length,2-wr); assert(r); + r= adns__vbuf_append(&ads->tcpsend,length,2-wr); assert(r); wr= 0; - } esle { + } else { wr-= 2; } if (wrquerylen) { - r= vbuf_append(&ads->tcpsend,qu->querymsg+wr,qu->querylen-wr); assert(r); + r= adns__vbuf_append(&ads->tcpsend,qu->querymsg+wr,qu->querylen-wr); assert(r); } } @@ -126,9 +132,9 @@ static void query_usetcp(adns_state ads, adns_query qu, struct timeval now) { timevaladd(&now,TCPMS); qu->timeout= now; qu->state= query_tcpwait; - DLIST_LINKTAIL(ads->timew,qu); - adns__query_tcp(ads,qu); - adns__tcp_tryconnect(ads); + LIST_LINK_TAIL(ads->timew,qu); + adns__query_tcp(ads,qu,now); + adns__tcp_tryconnect(ads,now); } void adns__query_udp(adns_state ads, adns_query qu, struct timeval now) { @@ -138,21 +144,20 @@ void adns__query_udp(adns_state ads, adns_query qu, struct timeval now) { * tcpsent/timew, child/childw or done/output.) */ struct sockaddr_in servaddr; - int serv; + int serv, r; assert(qu->state == query_udp); - if ((qu->flags & adns_f_usevc) || - (qu->querylen > UDPMAXDGRAM)) { + if ((qu->flags & adns_qf_usevc) || (qu->querylen > MAXUDPDGRAM)) { query_usetcp(ads,qu,now); return; } - if (qu->udpretries >= UDPMAXRETRIES) { - query_fail(ads,qu,adns_s_notresponding); + if (qu->udpretries >= MAXUDPRETRIES) { + adns__query_fail(ads,qu,adns_s_timeout); return; } - serv= qu->nextudpserver; + serv= qu->udpnextserver; memset(&servaddr,0,sizeof(servaddr)); servaddr.sin_family= AF_INET; servaddr.sin_addr= ads->servers[serv].addr; @@ -160,28 +165,35 @@ void adns__query_udp(adns_state ads, adns_query qu, struct timeval now) { r= sendto(ads->udpsocket,qu->querymsg,qu->querylen,0,&servaddr,sizeof(servaddr)); if (r<0 && errno == EMSGSIZE) { query_usetcp(ads,qu,now); return; } - if (r<0) warn("sendto %s failed: %s",inet_ntoa(servaddr.sin_addr),strerror(errno)); + if (r<0) adns__warn(ads,serv,"sendto failed: %s",strerror(errno)); timevaladd(&now,UDPRETRYMS); qu->timeout= now; - qu->sentudp |= (1<nextudpserver= (serv+1)%ads->nservers; + qu->udpsent |= (1<udpnextserver= (serv+1)%ads->nservers; qu->udpretries++; - DLIST_LINKTAIL(ads->timew,qu); + LIST_LINK_TAIL(ads->timew,qu); +} + +void adns__query_nomem(adns_state ads, adns_query qu) { + qu->answer.used= 0; + qu->id= -1; + LIST_LINK_TAIL(ads->output,qu); } void adns__query_fail(adns_state ads, adns_query qu, adns_status stat) { adns_answer *ans; - - ans= qu->answer; - if (!ans) ans= malloc(sizeof(*qu->answer)); - if (ans) { - ans->status= stat; - ans->cname= 0; - ans->type= qu->type; - ans->nrrs= 0; + + if (!adns__vbuf_ensure(&qu->answer,sizeof(adns_answer))) { + adns__query_nomem(ads,qu); + return; } - qu->answer= ans; + ans= (adns_answer*)qu->answer.buf; + ans->status= stat; + ans->cname= 0; + ans->type= qu->type; + ans->nrrs= 0; + qu->answer.used= sizeof(adns_answer); qu->id= -1; LIST_LINK_TAIL(ads->output,qu); } diff --git a/src/reply.c b/src/reply.c new file mode 100644 index 0000000..63b7033 --- /dev/null +++ b/src/reply.c @@ -0,0 +1,8 @@ +/**/ + +#include "internal.h" + +void adns__procdgram(adns_state ads, const byte *dgram, int len, int serv) { + /* FIXME do something with incoming datagrams */ + adns__diag(ads,serv,"received datagram size %d",len); +} diff --git a/src/setup.c b/src/setup.c index f1c2145..463779d 100644 --- a/src/setup.c +++ b/src/setup.c @@ -1,9 +1,18 @@ /**/ -#include "adns-internal.h" +#include +#include +#include +#include +#include -void adns__vdiag(adns_state ads, adns_initflags prevent, const char *pfx, - int serv, const char *fmt, va_list al) { +#include +#include + +#include "internal.h" + +void adns__vdiag(adns_state ads, const char *pfx, adns_initflags prevent, + int serv, const char *fmt, va_list al) { if (!(ads->iflags & adns_if_debug) && (!prevent || (ads->iflags & prevent))) return; if (serv>=0) { fprintf(stderr,"adns%s: nameserver %s: ",pfx,inet_ntoa(ads->servers[serv].addr)); @@ -18,15 +27,15 @@ void adns__debug(adns_state ads, int serv, const char *fmt, ...) { va_list al; va_start(al,fmt); - vdiag(ads," debug",0,serv,fmt,al); + adns__vdiag(ads," debug",0,serv,fmt,al); va_end(al); } -void adns__swarn(adns_state ads, int serv, const char *fmt, ...) { +void adns__warn(adns_state ads, int serv, const char *fmt, ...) { va_list al; va_start(al,fmt); - vdiag(ads," warning",adns_if_noerrprint|adns_if_noserverwarn,serv,fmt,al); + adns__vdiag(ads," warning",adns_if_noerrprint|adns_if_noserverwarn,serv,fmt,al); va_end(al); } @@ -34,31 +43,33 @@ void adns__diag(adns_state ads, int serv, const char *fmt, ...) { va_list al; va_start(al,fmt); - vdiag(ads,"",adns_if_noerrprint,serv,fmt,al); + adns__vdiag(ads,"",adns_if_noerrprint,serv,fmt,al); va_end(al); } -/* FIXME: unsigned char -> byte everywhere */ - + +void adns__vbuf_init(vbuf *vb) { + vb->used= vb->avail= 0; vb->buf= 0; +} -int adns__vbuf_ensure(adns__vbuf *vb, size_t want) { - byte *nb; +int adns__vbuf_ensure(vbuf *vb, int want) { + void *nb; - if (vb->avail >= want) return; + if (vb->avail >= want) return 1; nb= realloc(vb->buf,want); if (!nb) return 0; vb->buf= nb; vb->avail= want; return 1; } -void adns__vbuf_appendq(adns__vbuf *vb, const byte *data, size_t len) { +void adns__vbuf_appendq(vbuf *vb, const byte *data, int len) { memcpy(vb->buf+vb->used,data,len); vb->used+= len; } -int adns__vbuf_append(adns__vbuf *vb, const byte *data, size_t len) { - size_t newlen, newalloc; - byte *nb; +int adns__vbuf_append(vbuf *vb, const byte *data, int len) { + int newlen; + void *nb; newlen= vb->used+len; if (vb->avail < newlen) { @@ -73,26 +84,25 @@ int adns__vbuf_append(adns__vbuf *vb, const byte *data, size_t len) { return 1; } + static void addserver(adns_state ads, struct in_addr addr) { int i; struct server *ss; for (i=0; inservers; i++) { if (ads->servers[i].addr.s_addr == addr.s_addr) { - debug(ads,"duplicate nameserver %s ignored",inet_ntoa(addr)); + adns__debug(ads,-1,"duplicate nameserver %s ignored",inet_ntoa(addr)); return; } } if (ads->nservers>=MAXSERVERS) { - diag(ads,"too many nameservers, ignoring %s",inet_ntoa(addr)); + adns__diag(ads,-1,"too many nameservers, ignoring %s",inet_ntoa(addr)); return; } ss= ads->servers+ads->nservers; ss->addr= addr; - ss->state= server_disc; - ss->connw.head= ss->connw.tail= 0; ads->nservers++; } @@ -116,22 +126,22 @@ static void ccf_nameserver(adns_state ads, const char *fn, int lno, const char * configparseerr(ads,fn,lno,"invalid nameserver address `%s'",buf); return; } - debug(ads,"using nameserver %s",inet_ntoa(ia)); + adns__debug(ads,-1,"using nameserver %s",inet_ntoa(ia)); addserver(ads,ia); } static void ccf_search(adns_state ads, const char *fn, int lno, const char *buf) { if (!buf) return; - diag(ads,"warning - `search' ignored FIXME"); + adns__diag(ads,-1,"warning - `search' ignored FIXME"); } static void ccf_sortlist(adns_state ads, const char *fn, int lno, const char *buf) { - diag(ads,"warning - `sortlist' ignored FIXME"); + adns__diag(ads,-1,"warning - `sortlist' ignored FIXME"); } static void ccf_options(adns_state ads, const char *fn, int lno, const char *buf) { if (!buf) return; - diag(ads,"warning - `options' ignored FIXME"); + adns__diag(ads,-1,"warning - `options' ignored FIXME"); } static void ccf_clearnss(adns_state ads, const char *fn, int lno, const char *buf) { @@ -160,10 +170,11 @@ static void readconfig(adns_state ads, const char *filename) { file= fopen(filename,"r"); if (!file) { if (errno == ENOENT) { - debug(ads,"configuration file `%s' does not exist",filename); + adns__debug(ads,-1,"configuration file `%s' does not exist",filename); return; } - diag(ads,"cannot open configuration file `%s': %s",filename,strerror(errno)); + adns__diag(ads,-1,"cannot open configuration file `%s': %s", + filename,strerror(errno)); return; } @@ -171,7 +182,7 @@ static void readconfig(adns_state ads, const char *filename) { l= strlen(linebuf); if (!l) continue; if (linebuf[l-1] != '\n' && !feof(file)) { - diag(ads,"%s:%d: line too long",filename,lno); + adns__diag(ads,-1,"%s:%d: line too long",filename,lno); while ((c= getc(file)) != EOF && c != '\n') { } if (c == EOF) break; continue; @@ -187,14 +198,15 @@ static void readconfig(adns_state ads, const char *filename) { ccip->name && strncmp(ccip->name,p,q-p); ccip++); if (!ccip->name) { - diag(ads,"%s:%d: unknown configuration directive `%.*s'",filename,lno,q-p,p); + adns__diag(ads,-1,"%s:%d: unknown configuration directive `%.*s'", + filename,lno,q-p,p); continue; } while (ctype_whitespace(*q)) q++; ccip->fn(ads,filename,lno,q); } if (ferror(file)) { - diag(ads,"%s:%d: read error: %s",filename,lno,strerror(errno)); + adns__diag(ads,-1,"%s:%d: read error: %s",filename,lno,strerror(errno)); } fclose(file); } @@ -203,8 +215,8 @@ static const char *instrum_getenv(adns_state ads, const char *envvar) { const char *value; value= getenv(envvar); - if (!value) debug(ads,"environment variable %s not set",envvar); - else debug(ads,"environment variable %s set to `%s'",envvar,value); + if (!value) adns__debug(ads,-1,"environment variable %s not set",envvar); + else adns__debug(ads,-1,"environment variable %s set to `%s'",envvar,value); return value; } @@ -212,32 +224,43 @@ static void readconfigenv(adns_state ads, const char *envvar) { const char *filename; if (ads->iflags & adns_if_noenv) { - debug(ads,"not checking environment variable `%s'",envvar); + adns__debug(ads,-1,"not checking environment variable `%s'",envvar); return; } filename= instrum_getenv(ads,envvar); if (filename) readconfig(ads,filename); } + + +int adns__setnonblock(adns_state ads, int fd) { + int r; -int adns_init(adns_state *ads_r, adns_initflags flags) { + r= fcntl(fd,F_GETFL,0); if (r<0) return errno; + r |= O_NONBLOCK; + r= fcntl(fd,F_SETFL,r); if (r<0) return errno; + return 0; +} + +int adns_init(adns_state *ads_r, adns_initflags flags, FILE *diagfile) { adns_state ads; const char *res_options, *adns_res_options; struct protoent *proto; int r; ads= malloc(sizeof(*ads)); if (!ads) return errno; - ads->timew.head= ads->timew.tail= 0; - ads->childw.head= ads->childw.tail= 0; - ads->output.head= ads->output.tail= 0; - ads->nextid= 0x311f; - ads->udpsocket= -1; - ads->qbufavail= 0; - ads->qbuf= 0; - ads->tcpbufavail= ads->tcpbufused= ads->tcpbufdone= 0; - ads->tcpbuf= 0; - ads->iflags= flags; - ads->nservers= 0; ads->iflags= flags; + ads->diagfile= diagfile ? diagfile : stderr; + LIST_INIT(ads->timew); + LIST_INIT(ads->childw); + LIST_INIT(ads->output); + ads->nextid= 0x311f; + ads->udpsocket= ads->tcpsocket= -1; + adns__vbuf_init(&ads->rqbuf); + adns__vbuf_init(&ads->tcpsend); + adns__vbuf_init(&ads->tcprecv); + ads->nservers= ads->tcpserver= 0; + ads->tcpstate= server_disconnected; + timerclear(&ads->tcptimeout); res_options= instrum_getenv(ads,"RES_OPTIONS"); adns_res_options= instrum_getenv(ads,"ADNS_RES_OPTIONS"); diff --git a/src/submit.c b/src/submit.c index b1fd51e..ea10ab8 100644 --- a/src/submit.c +++ b/src/submit.c @@ -1,39 +1,48 @@ /**/ -#include "adns-internal.h" +#include +#include +#include + +#include + +#include "internal.h" static adns_query allocquery(adns_state ads, const char *owner, int ol, - int qml, int id, adns_rrtype type, - adns_queryflags flags, void *context) { + int id, adns_rrtype type, + adns_queryflags flags, const qcontext *ctx) { + /* Query message used is the one assembled in ads->rqbuf */ adns_query qu; - unsigned char *qm; - qu= malloc(sizeof(*qu)+ol+1+qml); if (!qu) return 0; + qu= malloc(sizeof(*qu)+ol+1+ads->rqbuf.used); if (!qu) return 0; + qu->state= query_udp; qu->next= qu->back= qu->parent= 0; - qu->children.head= qu->children.tail= 0; + LIST_INIT(qu->children); qu->siblings.next= qu->siblings.back= 0; - qu->id= id; qu->type= type; - qu->answer= 0; + adns__vbuf_init(&qu->answer); + qu->id= id; qu->flags= flags; - qu->context= context; qu->udpretries= 0; - qu->sentudp= qu->senttcp= 0; - qu->nextserver= 0; + qu->udpnextserver= 0; + qu->udpsent= qu->tcpfailed= 0; + timerclear(&qu->timeout); + memcpy(&qu->context,ctx,sizeof(qu->context)); memcpy(qu->owner,owner,ol); qu->owner[ol]= 0; - qu->querymsg= qm= qu->owner+ol+1; - memcpy(qm,ads->qbuf,qml); - qu->querylen= qml; + qu->querymsg= qu->owner+ol+1; + memcpy(qu->owner+ol+1,ads->rqbuf.buf,ads->rqbuf.used); + qu->querylen= ads->rqbuf.used; return qu; } -static int failsubmit(adns_state ads, void *context, adns_query *query_r, +static int failsubmit(adns_state ads, const qcontext *ctx, adns_query *query_r, adns_rrtype type, adns_queryflags flags, int id, adns_status stat) { adns_query qu; - qu= allocquery(ads,0,0,0,id,type,flags,context); if (!qu) return errno; - query_fail(ads,qu,stat); + ads->rqbuf.used= 0; + qu= allocquery(ads,0,0,id,type,flags,ctx); if (!qu) return errno; + adns__query_fail(ads,qu,stat); *query_r= qu; return 0; } @@ -46,8 +55,11 @@ int adns_submit(adns_state ads, adns_query *query_r) { adns_query qu; adns_status stat; - int ol, id, qml; + int ol, id, r; + qcontext ctx; + struct timeval now; + ctx.ext= context; id= ads->nextid++; r= gettimeofday(&now,0); if (r) return errno; @@ -55,14 +67,14 @@ int adns_submit(adns_state ads, ol= strlen(owner); if (ol<=1 || ol>MAXDNAME+1) return failsubmit(ads,context,query_r,type,flags,id,adns_s_invaliddomain); - if (owner[ol-1]=='.' && owner[ol-2]!='\\') { flags &= ~adns_f_search; ol--; } + if (owner[ol-1]=='.' && owner[ol-2]!='\\') { flags &= ~adns_qf_search; ol--; } - stat= adns__mkquery(ads,owner,ol,id,type,flags,&qml); + stat= adns__mkquery(ads,owner,ol,id,type,flags); if (stat) return failsubmit(ads,context,query_r,type,flags,id,stat); - qu= allocquery(ads,owner,ol,qml,id,type,flags,context); if (!qu) return errno; + qu= allocquery(ads,owner,ol,id,type,flags,context); if (!qu) return errno; adns__query_udp(ads,qu,now); - autosys(ads,now); + adns__autosys(ads,now); *query_r= qu; return 0; -- 2.30.2