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

Reply via email to