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
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list