aboutsummaryrefslogtreecommitdiff
path: root/contrib/unbound/smallapp/unbound-control.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/unbound/smallapp/unbound-control.c')
-rw-r--r--contrib/unbound/smallapp/unbound-control.c105
1 files changed, 92 insertions, 13 deletions
diff --git a/contrib/unbound/smallapp/unbound-control.c b/contrib/unbound/smallapp/unbound-control.c
index 3fe6068be560..a02140646b01 100644
--- a/contrib/unbound/smallapp/unbound-control.c
+++ b/contrib/unbound/smallapp/unbound-control.c
@@ -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)
@@ -164,6 +167,9 @@ usage(void)
printf(" view_local_data_remove view name remove local-data in view\n");
printf(" view_local_datas_remove view remove list of local-data from view\n");
printf(" one entry per line read from stdin\n");
+ printf(" rpz_enable zone Enable the RPZ zone if it had previously\n");
+ printf(" been disabled\n");
+ printf(" rpz_disable zone Disable the RPZ zone\n");
printf("Version %s\n", PACKAGE_VERSION);
printf("BSD licensed, see LICENSE in source package for details.\n");
printf("Report bugs to %s\n", PACKAGE_BUGREPORT);
@@ -545,6 +551,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 +628,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);
+#ifdef EINPROGRESS
+ if(errno != EINPROGRESS) {
+ checkconnecterr(errno, svr, &addr,
+ addrlen, statuscmd, useport);
}
+#endif
#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);
+ 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;
}