Changeset: 32cf70aec25e for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=32cf70aec25e
Modified Files:
        monetdb5/modules/mal/mal_mapi.c
        tools/merovingian/daemon/forkmserver.c
        tools/merovingian/utils/properties.c
Branch: ipv6
Log Message:

Added property "mapi_listenaddr". Mserver5 can now bind to a specific interface 
if this property is provided.


diffs (truncated from 433 to 300 lines):

diff --git a/monetdb5/modules/mal/mal_mapi.c b/monetdb5/modules/mal/mal_mapi.c
--- a/monetdb5/modules/mal/mal_mapi.c
+++ b/monetdb5/modules/mal/mal_mapi.c
@@ -523,6 +523,7 @@ SERVERlisten(int *Port, str *Usockfile, 
        char *usockfile;
        str buf;
        char host[128];
+       const char *listenaddr;
 #ifdef DEBUG_SERVER
        char msg[512], host[512];
        Client cntxt= mal_clients;
@@ -531,12 +532,17 @@ SERVERlisten(int *Port, str *Usockfile, 
        accept_any = GDKgetenv_istrue("mapi_open");
        bind_ipv6 = GDKgetenv_istrue("mapi_ipv6");
        autosense = GDKgetenv_istrue("mapi_autosense");
+       listenaddr = GDKgetenv("mapi_listenaddr");
 
        /* early way out, we do not want to listen on any port when running in 
embedded mode */
        if (GDKgetenv_istrue("mapi_disable")) {
                return MAL_SUCCEED;
        }
 
+       if (listenaddr && accept_any)
+               throw(ILLARG,"mal_mapi.listen", OPERATION_FAILED
+                                                                          ": 
mapi_open and mapi_listenaddr cannot be set at the same time");
+
        psock = GDKmalloc(sizeof(SOCKET) * 3);
        if (psock == NULL)
                throw(MAL,"mal_mapi.listen", SQLSTATE(HY001) MAL_MALLOC_FAIL);
@@ -574,117 +580,208 @@ SERVERlisten(int *Port, str *Usockfile, 
        }
 
        if (port > 0) {
-               sock = socket(bind_ipv6 ? AF_INET6 : AF_INET, SOCK_STREAM
+               if (listenaddr && *listenaddr) {
+                       int check = 0;
+                       char sport[16];
+                       struct addrinfo *result = NULL, *rp = NULL, hints = 
(struct addrinfo) {
+                               .ai_family = bind_ipv6 ? AF_INET6 : AF_INET,
+                               .ai_socktype = SOCK_STREAM,
+                               .ai_flags = AI_PASSIVE,
+                               .ai_protocol = IPPROTO_TCP,
+                       };
+
+                       do {
+                               bool ok = false;
+                               snprintf(sport, 16, "%d", port);
+                               check = getaddrinfo(listenaddr, sport, &hints, 
&result);
+                               if (check != 0) {
+                                       if (autosense && port <= 65535) {
+                                               port++;
+                                               continue;
+                                       }
+                                       GDKfree(psock);
+                                       GDKfree(usockfile);
+                                       throw(IO, "mal_mapi.listen", 
OPERATION_FAILED
+                                                         ": bind to stream 
socket on address %s and port %d failed: %s", listenaddr, port,
+                                                         gai_strerror(check));
+                               }
+
+                               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
-                                         , 0);
-               if (sock == INVALID_SOCKET) {
-                       GDKfree(psock);
-                       GDKfree(usockfile);
-                       throw(IO, "mal_mapi.listen",
-                                 OPERATION_FAILED ": creation of stream socket 
failed: %s",
-#ifdef _MSC_VER
-                                 wsaerror(WSAGetLastError())
-#else
-                                 strerror(errno)
-#endif
-                               );
-               }
-#if !defined(SOCK_CLOEXEC) && defined(HAVE_FCNTL)
-               (void) fcntl(sock, F_SETFD, FD_CLOEXEC);
+                                                                 , 
rp->ai_protocol);
+                                       if (sock == INVALID_SOCKET)
+                                               continue;
+#ifndef SOCK_CLOEXEC
+                                       (void) fcntl(sock, F_SETFD, FD_CLOEXEC);
 #endif
 
-               if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &on, 
sizeof on) == SOCKET_ERROR) {
-#ifdef _MSC_VER
-                       const char *err = wsaerror(WSAGetLastError());
-#else
-                       const char *err = strerror(errno);
-#endif
-                       GDKfree(psock);
-                       GDKfree(usockfile);
-                       closesocket(sock);
-                       throw(IO, "mal_mapi.listen", OPERATION_FAILED ": 
setsockptr failed %s", err);
-               }
+                                       if (setsockopt(sock, SOL_SOCKET, 
SO_REUSEADDR, (char *) &on, sizeof on) == SOCKET_ERROR) {
+                                               closesocket(sock);
+                                               continue;
+                                       }
 
-               if (bind_ipv6) {
-                       memset(&server_ipv6, 0, sizeof(server_ipv6));
-                       server_ipv6.sin6_family = AF_INET6;
-                       if (accept_any)
-                               server_ipv6.sin6_addr = ipv6_any_addr;
-                       else
-                               server_ipv6.sin6_addr = ipv6_loopback_addr;
-                       server = (struct sockaddr*) &server_ipv6;
-                       length = (SOCKLEN) sizeof(server_ipv6);
-               } else {
-                       server_ipv4.sin_family = AF_INET;
-                       if (accept_any)
-                               server_ipv4.sin_addr.s_addr = htonl(INADDR_ANY);
-                       else
-                               server_ipv4.sin_addr.s_addr = 
htonl(INADDR_LOOPBACK);
-                       for (i = 0; i < 8; i++)
-                               server_ipv4.sin_zero[i] = 0;
-                       server = (struct sockaddr*) &server_ipv4;
-                       length = (SOCKLEN) sizeof(server_ipv4);
-               }
-
-               do {
-                       if (bind_ipv6)
-                               server_ipv6.sin6_port = htons((unsigned short) 
((port) & 0xFFFF));
-                       else
-                               server_ipv4.sin_port = htons((unsigned short) 
((port) & 0xFFFF));
-
-                       if (bind(sock, server, length) == SOCKET_ERROR) {
-                               if (
+                                       if (bind(sock, rp->ai_addr, 
rp->ai_addrlen) != SOCKET_ERROR) {
+                                               ok = true;
+                                               break;
+                                       }
+                               }
+                               if (ok) {
+                                       if (result)
+                                               freeaddrinfo(result);
+                                       break;
+                               } else if (port > 65535) {
+                                       if (sock != -1)
+                                               closesocket(sock);
+                                       if (result)
+                                               freeaddrinfo(result);
+                                       GDKfree(psock);
+                                       GDKfree(usockfile);
+                                       throw(IO, "mal_mapi.listen", 
OPERATION_FAILED ": bind to stream socket port %d failed", port);
+                               } else {
+                                       if (
 #ifdef _MSC_VER
-                                       WSAGetLastError() == WSAEADDRINUSE &&
+                                               WSAGetLastError() == 
WSAEADDRINUSE &&
 #else
 #ifdef EADDRINUSE
-                                       errno == EADDRINUSE &&
+                                               errno == EADDRINUSE &&
 #else
 #endif
 #endif
-                                       autosense && port <= 65535)
-                               {
-                                       port++;
-                                       continue;
+                                               autosense && port <= 65535) {
+                                               closesocket(sock);
+                                               if (result)
+                                                       freeaddrinfo(result);
+                                               port++;
+                                               continue;
+                                       }
+                                       str err = createException(IO, 
"mal_mapi.listen",
+                                                                               
          OPERATION_FAILED ": bind to stream socket port %d failed: %s", port,
+#ifdef _MSC_VER
+                                                                               
          wsaerror(WSAGetLastError())
+#else
+                                                                               
          strerror(errno)
+#endif
+                                       );
+                                       closesocket(sock);
+                                       if (result)
+                                               freeaddrinfo(result);
+                                       GDKfree(psock);
+                                       GDKfree(usockfile);
+                                       return err;
                                }
-                               closesocket(sock);
+                       } while (1);
+               } else {
+                       sock = socket(bind_ipv6 ? AF_INET6 : AF_INET, 
SOCK_STREAM
+#ifdef SOCK_CLOEXEC
+                                                 | SOCK_CLOEXEC
+#endif
+                                                 , 0);
+                       if (sock == INVALID_SOCKET) {
                                GDKfree(psock);
                                GDKfree(usockfile);
-                               throw(IO, "mal_mapi.listen",
-                                         OPERATION_FAILED ": bind to stream 
socket port %d "
-                                         "failed: %s", port,
+                               throw(IO, "mal_mapi.listen", OPERATION_FAILED 
": creation of stream socket failed: %s",
 #ifdef _MSC_VER
                                          wsaerror(WSAGetLastError())
 #else
                                          strerror(errno)
 #endif
-                                       );
+                               );
+                       }
+#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) == SOCKET_ERROR) {
+#ifdef _MSC_VER
+                               const char *err = wsaerror(WSAGetLastError());
+#else
+                               const char *err = strerror(errno);
+#endif
+                               GDKfree(psock);
+                               GDKfree(usockfile);
+                               closesocket(sock);
+                               throw(IO, "mal_mapi.listen", OPERATION_FAILED 
": setsockptr failed %s", err);
+                       }
+
+                       if (bind_ipv6) {
+                               memset(&server_ipv6, 0, sizeof(server_ipv6));
+                               server_ipv6.sin6_family = AF_INET6;
+                               if (accept_any)
+                                       server_ipv6.sin6_addr = ipv6_any_addr;
+                               else
+                                       server_ipv6.sin6_addr = 
ipv6_loopback_addr;
+                               server = (struct sockaddr*) &server_ipv6;
+                               length = (SOCKLEN) sizeof(server_ipv6);
                        } else {
-                               break;
+                               server_ipv4.sin_family = AF_INET;
+                               if (accept_any)
+                                       server_ipv4.sin_addr.s_addr = 
htonl(INADDR_ANY);
+                               else
+                                       server_ipv4.sin_addr.s_addr = 
htonl(INADDR_LOOPBACK);
+                               for (i = 0; i < 8; i++)
+                                       server_ipv4.sin_zero[i] = 0;
+                               server = (struct sockaddr*) &server_ipv4;
+                               length = (SOCKLEN) sizeof(server_ipv4);
                        }
-               } while (1);
+
+                       do {
+                               if (bind_ipv6)
+                                       server_ipv6.sin6_port = htons((unsigned 
short) ((port) & 0xFFFF));
+                               else
+                                       server_ipv4.sin_port = htons((unsigned 
short) ((port) & 0xFFFF));
 
-               if (getsockname(sock, server, &length) == SOCKET_ERROR) {
+                               if (bind(sock, server, length) == SOCKET_ERROR) 
{
+                                       if (
+#ifdef _MSC_VER
+                                               WSAGetLastError() == 
WSAEADDRINUSE &&
+#else
+#ifdef EADDRINUSE
+                                               errno == EADDRINUSE &&
+#else
+#endif
+#endif
+                                               autosense && port <= 65535)
+                                       {
+                                               port++;
+                                               continue;
+                                       }
+                                       closesocket(sock);
+                                       GDKfree(psock);
+                                       GDKfree(usockfile);
+                                       throw(IO, "mal_mapi.listen", 
OPERATION_FAILED ": bind to stream socket port %d failed: %s", port,
+#ifdef _MSC_VER
+                                                 wsaerror(WSAGetLastError())
+#else
+                                                 strerror(errno)
+#endif
+                                       );
+                               } else {
+                                       break;
+                               }
+                       } while (1);
+
+                       if (getsockname(sock, server, &length) == SOCKET_ERROR) 
{
+                               closesocket(sock);
+                               GDKfree(psock);
+                               GDKfree(usockfile);
+                               throw(IO, "mal_mapi.listen", OPERATION_FAILED 
": failed getting socket name: %s",
+#ifdef _MSC_VER
+                                         wsaerror(WSAGetLastError())
+#else
+                                         strerror(errno)
+#endif
+                               );
+                       }
+               }
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to