Changeset: 3774f390d145 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=3774f390d145
Added Files:
        monetdb5/tools/Tests/mserver5-ipv6.py
        monetdb5/tools/Tests/mserver5-ipv6.stable.err
        monetdb5/tools/Tests/mserver5-ipv6.stable.out
Modified Files:
        clients/mapilib/mapi.c
        common/options/monet_options.c
        monetdb5/modules/mal/mal_mapi.c
        monetdb5/modules/mal/remote.c
        monetdb5/tools/Tests/All
        sql/server/rel_remote.c
        testing/Mtest.py.in
        testing/process.py
        tools/merovingian/client/monetdb.1
        tools/merovingian/daemon/client.c
        tools/merovingian/daemon/connections.c
        tools/merovingian/daemon/connections.h
        tools/merovingian/daemon/controlrunner.c
        tools/merovingian/daemon/discoveryrunner.c
        tools/merovingian/daemon/discoveryrunner.h
        tools/merovingian/daemon/forkmserver.c
        tools/merovingian/daemon/merovingian.c
        tools/merovingian/daemon/merovingian.h
        tools/merovingian/daemon/monetdbd.1.in
        tools/merovingian/daemon/proxy.c
        tools/merovingian/utils/control.c
        tools/merovingian/utils/properties.c
Branch: default
Log Message:

Merged ipv6 branch into default.


diffs (truncated from 1405 to 300 lines):

diff --git a/clients/mapilib/mapi.c b/clients/mapilib/mapi.c
--- a/clients/mapilib/mapi.c
+++ b/clients/mapilib/mapi.c
@@ -1975,9 +1975,16 @@ mapi_mapiuri(const char *url, const char
                dbname = NULL;
                query = uri;
        } else {
-               char *p;
-
-               if ((p = strchr(uri, ':')) == NULL) {
+               char *p = uri;
+
+               if (*p == '[') {
+                       if ((p = strchr(p, ']')) == NULL) {
+                               free(uri);
+                               mapi_setError(mid, "URI contains an invalid 
IPv6 address", "mapi_mapiuri", MERROR);
+                               return mid;
+                       }
+               }
+               if ((p = strchr(p, ':')) == NULL) {
                        free(uri);
                        mapi_setError(mid,
                                      "URI must contain a port number after "
@@ -2829,6 +2836,14 @@ mapi_reconnect(Mapi mid)
                                red += 15; /* "mapi:monetdb://" */
                                p = red;
                                q = NULL;
+                               if (*red == '[') {
+                                       if ((red = strchr(red, ']')) == NULL) {
+                                               mapi_close_handle(hdl);
+                                               mapi_setError(mid, "invalid 
IPv6 hostname", "mapi_reconnect", MERROR);
+                                               close_connection(mid);
+                                               return mid->error;
+                                       }
+                               }
                                if ((red = strchr(red, ':')) != NULL) {
                                        *red++ = '\0';
                                        q = red;
diff --git a/common/options/monet_options.c b/common/options/monet_options.c
--- a/common/options/monet_options.c
+++ b/common/options/monet_options.c
@@ -219,7 +219,7 @@ mo_builtin_settings(opt **Set)
        if (Set == NULL)
                return 0;
 
-#define N_OPTIONS      8       /*MUST MATCH # OPTIONS BELOW */
+#define N_OPTIONS      9       /*MUST MATCH # OPTIONS BELOW */
        set = malloc(sizeof(opt) * N_OPTIONS);
        if (set == NULL)
                return 0;
@@ -246,6 +246,10 @@ mo_builtin_settings(opt **Set)
        set[i].value = strdup("false");
        i++;
        set[i].kind = opt_builtin;
+       set[i].name = strdup("mapi_ipv6");
+       set[i].value = strdup("false");
+       i++;
+       set[i].kind = opt_builtin;
        set[i].name = strdup("mapi_autosense");
        set[i].value = strdup("false");
        i++;
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
@@ -502,55 +502,19 @@ error:
                closesocket(usock);
 }
 
-/**
- * Small utility function to call the sabaoth marchConnection function
- * with the right arguments.  If the socket is bound to 0.0.0.0 the
- * hostname address is used, to make the info usable for servers outside
- * localhost.
- */
-static void SERVERannounce(struct in_addr addr, int port, str usockfile) {
-       str buf;
-       char host[128];
+static const struct in6_addr ipv6_loopback_addr = IN6ADDR_LOOPBACK_INIT;
 
-       if (port > 0) {
-               if (addr.s_addr == INADDR_ANY) {
-                       gethostname(host, sizeof(host));
-                       host[sizeof(host) - 1] = '\0';
-               } else {
-                       /* avoid doing this, it requires some includes that 
probably
-                        * give trouble on windowz
-                       host = inet_ntoa(addr);
-                        */
-                       sprintf(host, "%u.%u.%u.%u",
-                                       (unsigned) ((ntohl(addr.s_addr) >> 24) 
& 0xff),
-                                       (unsigned) ((ntohl(addr.s_addr) >> 16) 
& 0xff),
-                                       (unsigned) ((ntohl(addr.s_addr) >> 8) & 
0xff),
-                                       (unsigned) (ntohl(addr.s_addr) & 0xff));
-               }
-               if ((buf = msab_marchConnection(host, port)) != NULL)
-                       free(buf);
-               else
-                       /* announce that we're now reachable */
-                       printf("# Listening for connection requests on "
-                                       "mapi:monetdb://%s:%i/\n", host, port);
-       }
-       if (usockfile != NULL) {
-               port = 0;
-               if ((buf = msab_marchConnection(usockfile, port)) != NULL)
-                       free(buf);
-               else
-                       /* announce that we're now reachable */
-                       printf("# Listening for UNIX domain connection requests 
on "
-                                       "mapi:monetdb://%s\n", usockfile);
-       }
-}
+static const struct in6_addr ipv6_any_addr = IN6ADDR_ANY_INIT;
 
 static str
 SERVERlisten(int *Port, const char *Usockfile, int *Maxusers)
 {
-       struct sockaddr_in server;
+       struct sockaddr* server = NULL;
+       struct sockaddr_in server_ipv4;
+       struct sockaddr_in6 server_ipv6;
        SOCKET sock = INVALID_SOCKET;
        SOCKET *psock;
+       bool bind_ipv6 = false;
        bool accept_any = false;
        bool autosense = false;
 #ifdef HAVE_SYS_UN_H
@@ -564,19 +528,28 @@ SERVERlisten(int *Port, const char *Usoc
        int port;
        int maxusers;
        char *usockfile;
+       str buf;
+       char host[128];
+       const char *listenaddr;
 #ifdef DEBUG_SERVER
        char msg[512], host[512];
        Client cntxt= mal_clients;
 #endif
 
        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);
@@ -614,69 +587,102 @@ SERVERlisten(int *Port, const char *Usoc
        }
 
        if (port > 0) {
-               sock = socket(AF_INET, SOCK_STREAM
+               if (listenaddr && *listenaddr) {
+                       int check = 0, e = errno;
+                       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 {
+                               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) 
{
+                                       int bind_check;
+                                       sock = socket(rp->ai_family, 
rp->ai_socktype
 #ifdef SOCK_CLOEXEC
-                                         | SOCK_CLOEXEC
+                                                                 | SOCK_CLOEXEC
 #endif
-                                         , 0);
-               if (sock == INVALID_SOCKET) {
-                       int e = errno;
-                       GDKfree(psock);
-                       GDKfree(usockfile);
-                       errno = e;
-                       throw(IO, "mal_mapi.listen",
-                                 OPERATION_FAILED ": creation of stream socket 
failed: %s",
-#ifdef _MSC_VER
-                                 wsaerror(WSAGetLastError())
-#else
-                                 strerror(errno)
-#endif
-                               );
-               }
+                                                                 , 
rp->ai_protocol);
+                                       if (sock == INVALID_SOCKET) {
+                                               e = errno;
+                                               continue;
+                                       }
 #if !defined(SOCK_CLOEXEC) && defined(HAVE_FCNTL)
-               (void) fcntl(sock, F_SETFD, FD_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) {
+                                               e = errno;
+                                               closesocket(sock);
+                                               continue;
+                                       }
 
-               server.sin_family = AF_INET;
-               if (accept_any)
-                       server.sin_addr.s_addr = htonl(INADDR_ANY);
-               else
-                       server.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-               for (i = 0; i < 8; i++)
-                       server.sin_zero[i] = 0;
-               length = (SOCKLEN) sizeof(server);
+                                       bind_check = bind(sock, (SOCKPTR) 
rp->ai_addr, (socklen_t) rp->ai_addrlen);
+                                       e = errno;
+                                       if (bind_check == SOCKET_ERROR) {
+                                               closesocket(sock);
+                                               continue;
+                                       } else
+                                               break;
+                               }
+                               if (result)
+                                       freeaddrinfo(result);
+                               errno = e;
+                               if (errno == 0 && sock != INVALID_SOCKET)
+                                       break;
 
-               for (;;) {
-                       server.sin_port = htons((unsigned short) ((port) & 
0xFFFF));
-                       if (bind(sock, (SOCKPTR) &server, length) == 
SOCKET_ERROR) {
-                               int e = errno;
-                               if (
+                               if (port > 65535) {
+                                       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) {
+                                                               port++;
+                                                               continue;
                                }
-                               closesocket(sock);
+                               GDKfree(psock);
+                               GDKfree(usockfile);
+                               errno = e;
+                               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
+                               );
+                       } while (1);
+               } else {
+                       sock = socket(bind_ipv6 ? AF_INET6 : AF_INET, 
SOCK_STREAM
+#ifdef SOCK_CLOEXEC
+                                                 | SOCK_CLOEXEC
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to