From: ian Date: Sat, 3 Oct 1998 23:28:13 +0000 (+0000) Subject: Some more fiddlings. X-Git-Tag: abandon.1998-10-04.rrtypenoenum~5 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=adns.git;a=commitdiff_plain;h=8402e34c7df0adad223cf1fa1328bb524a15d99f;hp=37e28fde2d1d358ca0b887fc131f0ca108318b2a Some more fiddlings. --- diff --git a/src/adns.h b/src/adns.h index 23c71ef..ae0a742 100644 --- a/src/adns.h +++ b/src/adns.h @@ -64,6 +64,7 @@ typedef enum { adns_s_timeout, adns_s_unknownqtype, adns_s_nolocalmem, + adns_s_connlost, adns_s_max_tempfail= 99, adns_s_inconsistent, /* PTR gives domain whose A does not match */ adns_s_badcname, /* CNAME found where actual record expected */ diff --git a/src/event.c b/src/event.c index 68abb3c..3007a95 100644 --- a/src/event.c +++ b/src/event.c @@ -12,14 +12,55 @@ static int callb_checkfd(int maxfd, const fd_set *fds, int fd) { fdtcpstate == server_connecting || ads->tcpstate == server_connected); +void adns__tcp_broken(adns_state ads, const char *what, const char *why) { + int serv; + + assert(ads->tcpstate == server_connecting || ads->tcpstate == server_ok); warn("nameserver %s TCP connection lost: %s: %s", inet_ntoa(ads->servers[tcpserver].addr,what,why)); close(ads->tcpsocket); ads->tcpstate= server_disconnected; + serv= ads->tcpserver; - + for (qu= ads->timew; qu; qu= nqu) { + nqu= qu->next; + if (qu->senttcpserver == -1) continue; + assert(qu->senttcpserver == serv); + DLIST_UNLINK(ads->timew,qu); + adns__query_fail(ads,qu,adns_s_connlost); /* wishlist: send to other servers ? */ + } + + ads->tcpbuf.used= 0; + ads->tcpserver= (serv+1)%ads->nservers; +} + +void adns__tcp_tryconnect(adns_state ads) { + int r, fd, tries; + sockaddr_in addr; + + for (tries=0; triesnservers; tries++) { + if (ads->tcpstate == server_connecting || ads->tcpstate == server_ok) return; + assert(ads->tcpstate == server_disconnected); + assert(!ads->tcpbuf.used); + + proto= getprotobyname("tcp"); + if (!proto) { diag(ads,"unable to find protocol number for TCP !",-1); 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; + memset(&addr,0,sizeof(addr)); + addr.sin_family= AF_INET; + addr.sin_port= htons(NSPORT); + addr.sin_addr= ads->servers[ads->tcpserver].addr; + r= connect(fd,&addr,sizeof(addr)); + ads->tcpsocket= fd; + ads->tcpstate= server_connecting; + if (r==0) { ads->tcpstate= server_ok; return; } + if (errno == EWOULDBLOCK || errno == EINPROGRESS) return; + tcpserver_broken(ads,"connect",strerror(errno)); + } +} + int adns_callback(adns_state ads, int maxfd, const fd_set *readfds, const fd_set *writefds, const fd_set *exceptfds) { @@ -45,7 +86,7 @@ int adns_callback(adns_state ads, int maxfd, } else if (r>0) { tcpserver_broken(ads,"connect/read","sent data before first request"); } else if (errno!=EINTR) { - tcpserver_broken(ads,"connect",strerror(errno)); + tcpserver_broken(ads,"connect/read",strerror(errno)); } } } diff --git a/src/internal.h b/src/internal.h index 2cdafbf..eb8cd5d 100644 --- a/src/internal.h +++ b/src/internal.h @@ -38,8 +38,8 @@ struct adns__query { adns_answer *answer; size_t ansalloc; ansused; int id, flags, udpretries; /* udpretries==-1 => _f_usevc or too big for UDP */ - int nextudpserver; - unsigned long sentudp, senttcp; /* bitmaps indexed by server */ + int nextudpserver, senttcpserver; + unsigned long sentudp; /* bitmap indexed by server */ struct timeval timeout; void *context; unsigned char *querymsg; @@ -67,7 +67,7 @@ struct adns__state { int nextid, udpsocket; adns_vbuf rqbuf, tcpsend, tcprecv; int nservers, tcpserver; - enum adns__tcpstate { server_disc, server_connecting, server_ok } tcpstate; + enum adns__tcpstate { server_disconnected, server_connecting, server_ok } tcpstate; int tcpsocket; struct timeval tcptimeout; struct server { @@ -79,9 +79,9 @@ struct adns__state { void adns__vdiag(adns_state ads, adns_initflags prevent, const char *pfx, int serv, const char *fmt, va_list al); -void adns__debug(adns_state ads, int serv, const char *fmt, ...) PRINTFFORMAT(2,3); -void adns__warn(adns_state ads, int serv, const char *fmt, ...) PRINTFFORMAT(2,3); -void adns__diag(adns_state ads, int serv, const char *fmt, ...) PRINTFFORMAT(2,3); +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); /* From submit.c: */ @@ -89,7 +89,11 @@ void adns__query_fail(adns_state ads, adns_query qu, adns_status stat); /* From query.c: */ -void adns__quproc_tosend(adns_state ads, adns_query qu, struct timeval now) { +void adns__quproc_tosend(adns_state ads, adns_query qu, struct timeval now); + +/* From event.c: */ +void adns__tcp_broken(adns_state ads, const char *what, const char *why); +void adns__tcp_tryconnect(adns_state ads); /* Useful static inline functions: */ diff --git a/src/query.c b/src/query.c index c9ad8fd..81acb61 100644 --- a/src/query.c +++ b/src/query.c @@ -108,6 +108,8 @@ void adns__quproc_tosend(adns_state ads, adns_query qu, struct timeval now) { /* fixme: TCP queries preceded by length */ for (;;) { + adns__tcp_tryconnect(ads); + /* fixme: make this work properly */ serv= tcpserver_get(ads); if (serv<0) { r=0; break; } if (ads->opbufused) { r=0; break; } diff --git a/src/setup.c b/src/setup.c index 8939ac6..7daea9b 100644 --- a/src/setup.c +++ b/src/setup.c @@ -230,13 +230,11 @@ int adns_init(adns_state *ads_r, adns_initflags flags) { proto= getprotobyname("udp"); if (!proto) { r= ENOPROTOOPT; goto x_free; } ads->udpsocket= socket(AF_INET,SOCK_DGRAM,proto->p_proto); - if (!ads->udpsocket) { r= errno; goto x_closeudp; } + if (ads->udpsocket<0) { r= errno; goto x_free; } *ads_r= ads; return 0; - x_closeudp: - close(ads->udpsocket); x_free: free(ads); return r;