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