mirror of
https://github.com/NLnetLabs/unbound.git
synced 2025-12-20 23:00:56 -05:00
- Fix #371: unbound-control timeout when Unbound is not running.
This commit is contained in:
parent
b49cc2e667
commit
a4fc32809c
2 changed files with 94 additions and 15 deletions
|
|
@ -1,3 +1,6 @@
|
|||
11 December 2020: Wouter
|
||||
- Fix #371: unbound-control timeout when Unbound is not running.
|
||||
|
||||
3 December 2020: Wouter
|
||||
- make depend.
|
||||
- iana portlist updated.
|
||||
|
|
|
|||
|
|
@ -82,6 +82,9 @@ static void usage(void) ATTR_NORETURN;
|
|||
static void ssl_err(const char* s) ATTR_NORETURN;
|
||||
static void ssl_path_err(const char* s, const char *path) ATTR_NORETURN;
|
||||
|
||||
/** timeout to wait for connection over stream, in msec */
|
||||
#define UNBOUND_CONTROL_CONNECT_TIMEOUT 5000
|
||||
|
||||
/** Give unbound-control usage, and exit (1). */
|
||||
static void
|
||||
usage(void)
|
||||
|
|
@ -545,6 +548,30 @@ setup_ctx(struct config_file* cfg)
|
|||
return ctx;
|
||||
}
|
||||
|
||||
/** check connect error */
|
||||
static void
|
||||
checkconnecterr(int err, const char* svr, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, int statuscmd, int useport)
|
||||
{
|
||||
#ifndef USE_WINSOCK
|
||||
if(!useport) log_err("connect: %s for %s", strerror(err), svr);
|
||||
else log_err_addr("connect", strerror(err), addr, addrlen);
|
||||
if(err == ECONNREFUSED && statuscmd) {
|
||||
printf("unbound is stopped\n");
|
||||
exit(3);
|
||||
}
|
||||
#else
|
||||
int wsaerr = err;
|
||||
if(!useport) log_err("connect: %s for %s", wsa_strerror(wsaerr), svr);
|
||||
else log_err_addr("connect", wsa_strerror(wsaerr), addr, addrlen);
|
||||
if(wsaerr == WSAECONNREFUSED && statuscmd) {
|
||||
printf("unbound is stopped\n");
|
||||
exit(3);
|
||||
}
|
||||
#endif
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/** contact the server with TCP connect */
|
||||
static int
|
||||
contact_server(const char* svr, struct config_file* cfg, int statuscmd)
|
||||
|
|
@ -598,26 +625,75 @@ contact_server(const char* svr, struct config_file* cfg, int statuscmd)
|
|||
if(fd == -1) {
|
||||
fatal_exit("socket: %s", sock_strerror(errno));
|
||||
}
|
||||
fd_set_nonblock(fd);
|
||||
if(connect(fd, (struct sockaddr*)&addr, addrlen) < 0) {
|
||||
#ifndef USE_WINSOCK
|
||||
int err = errno;
|
||||
if(!useport) log_err("connect: %s for %s", strerror(err), svr);
|
||||
else log_err_addr("connect", strerror(err), &addr, addrlen);
|
||||
if(err == ECONNREFUSED && statuscmd) {
|
||||
printf("unbound is stopped\n");
|
||||
exit(3);
|
||||
}
|
||||
#else
|
||||
int wsaerr = WSAGetLastError();
|
||||
if(!useport) log_err("connect: %s for %s", wsa_strerror(wsaerr), svr);
|
||||
else log_err_addr("connect", wsa_strerror(wsaerr), &addr, addrlen);
|
||||
if(wsaerr == WSAECONNREFUSED && statuscmd) {
|
||||
printf("unbound is stopped\n");
|
||||
exit(3);
|
||||
#ifdef EINPROGRESS
|
||||
if(errno != EINPROGRESS) {
|
||||
checkconnecterr(errno, svr, &addr,
|
||||
addrlen, statuscmd, useport);
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
if(WSAGetLastError() != WSAEINPROGRESS &&
|
||||
WSAGetLastError() != WSAEWOULDBLOCK) {
|
||||
checkconnecterr(WSAGetLastError(), svr, &addr,
|
||||
addrlen, statuscmd, useport);
|
||||
}
|
||||
#endif
|
||||
exit(1);
|
||||
}
|
||||
while(1) {
|
||||
fd_set rset, wset, eset;
|
||||
struct timeval tv;
|
||||
FD_ZERO(&rset);
|
||||
FD_SET(FD_SET_T fd, &rset);
|
||||
FD_ZERO(&wset);
|
||||
FD_SET(FD_SET_T fd, &wset);
|
||||
FD_ZERO(&eset);
|
||||
FD_SET(FD_SET_T fd, &eset);
|
||||
tv.tv_sec = UNBOUND_CONTROL_CONNECT_TIMEOUT/1000;
|
||||
tv.tv_usec= (UNBOUND_CONTROL_CONNECT_TIMEOUT%1000)*1000;
|
||||
if(select(fd+1, &rset, &wset, &eset, &tv) == -1) {
|
||||
fatal_exit("select: %s", sock_strerror(errno));
|
||||
}
|
||||
if(!FD_ISSET(fd, &rset) && !FD_ISSET(fd, &wset) &&
|
||||
!FD_ISSET(fd, &eset)) {
|
||||
fatal_exit("timeout: could not connect to server");
|
||||
} else {
|
||||
/* check nonblocking connect error */
|
||||
int error = 0;
|
||||
socklen_t len = (socklen_t)sizeof(error);
|
||||
if(getsockopt(fd, SOL_SOCKET, SO_ERROR, (void*)&error,
|
||||
&len) < 0) {
|
||||
#ifndef USE_WINSOCK
|
||||
error = errno; /* on solaris errno is error */
|
||||
#else
|
||||
error = WSAGetLastError();
|
||||
#endif
|
||||
}
|
||||
if(error != 0) {
|
||||
#ifndef USE_WINSOCK
|
||||
#ifdef EINPROGRESS
|
||||
if(error == EINPROGRESS)
|
||||
continue; /* try again later */
|
||||
#endif
|
||||
#ifdef EWOULDBLOCK
|
||||
if(error == EWOULDBLOCK)
|
||||
continue; /* try again later */
|
||||
#endif
|
||||
#else
|
||||
if(error == WSAEINPROGRESS)
|
||||
continue; /* try again later */
|
||||
if(error == WSAEWOULDBLOCK)
|
||||
continue; /* try again later */
|
||||
#endif
|
||||
checkconnecterr(error, svr, &addr, addrlen,
|
||||
statuscmd, useport);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
fd_set_block(fd);
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue