Changeset: b42c28655a58 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=b42c28655a58 Modified Files: tools/merovingian/daemon/connections.c Branch: listenaddr Log Message:
Simplify (deduplicate) code, and listen to IPv4 also when listening to IPv6. diffs (173 lines): diff --git a/tools/merovingian/daemon/connections.c b/tools/merovingian/daemon/connections.c --- a/tools/merovingian/daemon/connections.c +++ b/tools/merovingian/daemon/connections.c @@ -27,126 +27,73 @@ err openConnectionTCP(int *ret, bool bind_ipv6, const char *bindaddr, unsigned short port, FILE *log) { - struct sockaddr *server; - struct sockaddr_in server_ipv4; - struct sockaddr_in6 server_ipv6; struct addrinfo *result = NULL, *rp = NULL; int sock = -1, check = 0; - socklen_t length = 0; int on = 1; char sport[16]; + int e = 0; snprintf(sport, 16, "%hu", port); - if (bindaddr) { - struct addrinfo hints = (struct addrinfo) { - .ai_family = bind_ipv6 ? AF_INET6 : AF_INET, - .ai_socktype = SOCK_STREAM, - .ai_flags = AI_PASSIVE, - .ai_protocol = IPPROTO_TCP, - }; + + struct addrinfo hints = (struct addrinfo) { + .ai_family = bind_ipv6 ? AF_INET6 : AF_INET, + .ai_socktype = SOCK_STREAM, + .ai_flags = AI_PASSIVE, + .ai_protocol = IPPROTO_TCP, + }; - check = getaddrinfo(bindaddr, sport, &hints, &result); - if (check != 0) - return newErr("cannot find host %s with error: %s", bindaddr, gai_strerror(check)); + check = getaddrinfo(bindaddr, sport, &hints, &result); + if (check != 0) + return newErr("cannot find host %s with error: %s", bindaddr ? bindaddr : "any", gai_strerror(check)); - for (rp = result; rp != NULL; rp = rp->ai_next) { - sock = socket(rp->ai_family, rp->ai_socktype + for (rp = result; rp != NULL; rp = rp->ai_next) { + sock = socket(rp->ai_family, rp->ai_socktype #ifdef SOCK_CLOEXEC - | SOCK_CLOEXEC + | SOCK_CLOEXEC #endif - , rp->ai_protocol); - if (sock == -1) - continue; -#if !defined(SOCK_CLOEXEC) && defined(HAVE_FCNTL) - (void) fcntl(sock, F_SETFD, FD_CLOEXEC); -#endif - - if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof on) < 0) { - closesocket(sock); - continue; - } -#ifdef SO_EXCLUSIVEADDRUSE - (void) setsockopt(sock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char *) &on, sizeof on); -#endif -#ifdef SO_EXCLBIND - (void) setsockopt(sock, SOL_SOCKET, SO_EXCLBIND, (char *) &on, sizeof on); -#endif - - if (bind(sock, rp->ai_addr, rp->ai_addrlen) != -1) - break; /* working */ - closesocket(sock); + , rp->ai_protocol); + if (sock == -1) { + e = errno; + continue; } - if (rp == NULL) { - int e = errno; - freeaddrinfo(result); - if (result) { /* results found, tried socket, setsockopt and bind calls */ - errno = e; - return newErr("binding to stream socket port %hu failed: %s", port, strerror(errno)); - } else { /* no results found, could not translate address */ - return newErr("cannot translate host %s", bindaddr); - } - } - server = rp->ai_addr; - length = rp->ai_addrlen; - freeaddrinfo(result); - } else { - sock = socket(bind_ipv6 ? AF_INET6 : AF_INET, SOCK_STREAM -#ifdef SOCK_CLOEXEC - | SOCK_CLOEXEC -#endif - , 0); - if (sock == -1) - return(newErr("creation of stream socket failed: %s", strerror(errno))); - - if (bind_ipv6) { - server_ipv6 = (struct sockaddr_in6) { - .sin6_family = AF_INET6, - .sin6_port = htons((unsigned short) (port & 0xFFFF)), - .sin6_addr = ipv6_any_addr, - }; - length = (socklen_t) sizeof(server_ipv6); - server = (struct sockaddr*) &server_ipv6; - } else { - server_ipv4 = (struct sockaddr_in) { - .sin_family = AF_INET, - .sin_port = htons((unsigned short) (port & 0xFFFF)), - .sin_addr.s_addr = htonl(INADDR_ANY), - }; - length = (socklen_t) sizeof(server_ipv4); - server = (struct sockaddr*) &server_ipv4; - } - #if !defined(SOCK_CLOEXEC) && defined(HAVE_FCNTL) (void) fcntl(sock, F_SETFD, FD_CLOEXEC); #endif + + if (rp->ai_family == AF_INET6) + (void) setsockopt(sock, SOL_IPV6, IPV6_V6ONLY, &(int){0}, sizeof(int)); + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof on) < 0) { - int e = errno; - closesocket(sock); - errno = e; - return newErr("setsockopt unexpectedly failed: %s", strerror(errno)); - } - - if (bind(sock, server, length) == -1) { - int e = errno; + e = errno; closesocket(sock); - errno = e; - return(newErr("binding to stream socket port %hu failed: %s", port, strerror(errno))); + continue; } +#ifdef SO_EXCLUSIVEADDRUSE + (void) setsockopt(sock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char *) &on, sizeof on); +#endif +#ifdef SO_EXCLBIND + (void) setsockopt(sock, SOL_SOCKET, SO_EXCLBIND, (char *) &on, sizeof on); +#endif - if (getsockname(sock, server, &length) == -1) { - int e = errno; - closesocket(sock); - errno = e; - return(newErr("failed getting socket name: %s", strerror(errno))); + if (bind(sock, rp->ai_addr, rp->ai_addrlen) != -1) + break; /* working */ + e = errno; + closesocket(sock); + } + freeaddrinfo(result); + if (rp == NULL) { + if (e != 0) { /* results found, tried socket, setsockopt and bind calls */ + return newErr("binding to stream socket port %hu failed: %s", port, strerror(e)); + } else { /* no results found, could not translate address */ + return newErr("cannot translate host %s", bindaddr ? bindaddr : "any"); } } /* keep queue of 5 */ if (listen(sock, 5) == -1) { - int e = errno; + e = errno; closesocket(sock); - errno = e; - return(newErr("failed setting socket to listen: %s", strerror(errno))); + return(newErr("failed setting socket to listen: %s", strerror(e))); } Mfprintf(log, "accepting connections on TCP socket %s:%hu\n", bindaddr, port); _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list