mirror of
https://github.com/NLnetLabs/unbound.git
synced 2025-12-23 08:10:30 -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
|
3 December 2020: Wouter
|
||||||
- make depend.
|
- make depend.
|
||||||
- iana portlist updated.
|
- 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_err(const char* s) ATTR_NORETURN;
|
||||||
static void ssl_path_err(const char* s, const char *path) 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). */
|
/** Give unbound-control usage, and exit (1). */
|
||||||
static void
|
static void
|
||||||
usage(void)
|
usage(void)
|
||||||
|
|
@ -545,6 +548,30 @@ setup_ctx(struct config_file* cfg)
|
||||||
return ctx;
|
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 */
|
/** contact the server with TCP connect */
|
||||||
static int
|
static int
|
||||||
contact_server(const char* svr, struct config_file* cfg, int statuscmd)
|
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) {
|
if(fd == -1) {
|
||||||
fatal_exit("socket: %s", sock_strerror(errno));
|
fatal_exit("socket: %s", sock_strerror(errno));
|
||||||
}
|
}
|
||||||
|
fd_set_nonblock(fd);
|
||||||
if(connect(fd, (struct sockaddr*)&addr, addrlen) < 0) {
|
if(connect(fd, (struct sockaddr*)&addr, addrlen) < 0) {
|
||||||
#ifndef USE_WINSOCK
|
#ifndef USE_WINSOCK
|
||||||
int err = errno;
|
#ifdef EINPROGRESS
|
||||||
if(!useport) log_err("connect: %s for %s", strerror(err), svr);
|
if(errno != EINPROGRESS) {
|
||||||
else log_err_addr("connect", strerror(err), &addr, addrlen);
|
checkconnecterr(errno, svr, &addr,
|
||||||
if(err == ECONNREFUSED && statuscmd) {
|
addrlen, statuscmd, useport);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
exit(1);
|
#else
|
||||||
|
if(WSAGetLastError() != WSAEINPROGRESS &&
|
||||||
|
WSAGetLastError() != WSAEWOULDBLOCK) {
|
||||||
|
checkconnecterr(WSAGetLastError(), svr, &addr,
|
||||||
|
addrlen, statuscmd, useport);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
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;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue