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

Allow monetdbd to use TCP connections on IPv6.


diffs (297 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
@@ -815,7 +815,7 @@ SERVERlisten(int *Port, str *Usockfile, 
                                gethostname(host, sizeof(host));
                                host[sizeof(host) - 1] = '\0';
                        } else {
-                               
sprintf(host,"%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
+                               snprintf(host, 
sizeof(host),"%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
                                                
(int)server_ipv6.sin6_addr.s6_addr[0],  (int)server_ipv6.sin6_addr.s6_addr[1],
                                                
(int)server_ipv6.sin6_addr.s6_addr[2],  (int)server_ipv6.sin6_addr.s6_addr[3],
                                                
(int)server_ipv6.sin6_addr.s6_addr[4],  (int)server_ipv6.sin6_addr.s6_addr[5],
@@ -834,7 +834,7 @@ SERVERlisten(int *Port, str *Usockfile, 
                                 * give trouble on windowz
                                host = inet_ntoa(addr);
                                 */
-                               sprintf(host, "%u.%u.%u.%u",
+                               snprintf(host, sizeof(host), "%u.%u.%u.%u",
                                                (unsigned) 
((ntohl(server_ipv4.sin_addr.s_addr) >> 24) & 0xff),
                                                (unsigned) 
((ntohl(server_ipv4.sin_addr.s_addr) >> 16) & 0xff),
                                                (unsigned) 
((ntohl(server_ipv4.sin_addr.s_addr) >> 8) & 0xff),
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
@@ -23,74 +23,146 @@
 #include "merovingian.h"
 #include "connections.h"
 
+static struct in6_addr ipv6_any_addr = IN6ADDR_ANY_INIT;
+
 err
-openConnectionTCP(int *ret, const char *bindaddr, unsigned short port, FILE 
*log)
+openConnectionTCP(int *ret, bool bind_ipv6, const char *bindaddr, unsigned 
short port, FILE *log)
 {
-       struct sockaddr_in server;
-       int sock = -1;
+       struct sockaddr_in server_ipv4;
+       struct sockaddr_in6 server_ipv6;
+       struct addrinfo *rp = NULL;
+       int sock = -1, check = 0;
        socklen_t length = 0;
        int on = 1;
        int i = 0;
        struct hostent *hoste;
-       char *host;
+       char *host = NULL;
+       char sport[16];
        char hostip[24];
+       char ghost[512];
 
-       sock = socket(AF_INET, SOCK_STREAM
+       snprintf(sport, 16, "%hu", port);
+       if (bindaddr) {
+               struct addrinfo *result;
+               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,
+                       .ai_canonname = NULL,
+                       .ai_addr = NULL,
+                       .ai_next = NULL,
+               };
+
+               check = getaddrinfo(bindaddr, sport, &hints, &result);
+               if (check != 0)
+                       return newErr("cannot find host %s with error: %s", 
bindaddr, strerror(errno));
+
+               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 == -1)
-               return(newErr("creation of stream socket failed: %s",
-                                       strerror(errno)));
+                                       , rp->ai_protocol);
+                       if (sock == -1)
+                               continue;
 #ifndef SOCK_CLOEXEC
-       (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) 
< 0) {
-               closesocket(sock);
-               return newErr("setsockopt unexpectedly failed: %s",
-                                         strerror(errno));
+                       if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) 
&on, sizeof on) < 0) {
+                               closesocket(sock);
+                               return newErr("setsockopt unexpectedly failed: 
%s", strerror(errno));
+                       }
+
+                       if (bind(sock, rp->ai_addr, rp->ai_addrlen) != -1)
+                               break; /* working */
+               }
+               if (rp == NULL) {
+                       if (sock != -1)
+                               closesocket(sock);
+                       return newErr("cannot bind to host %s", bindaddr);
+               }
+       } 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.sin6_family = AF_INET6;
+                       server_ipv6.sin6_flowinfo = 0;
+                       server_ipv6.sin6_scope_id = 0;
+                       length = (socklen_t) sizeof(server_ipv6);
+                       server_ipv6.sin6_port = htons((unsigned short) ((port) 
& 0xFFFF));
+                       memcpy(server_ipv6.sin6_addr.s6_addr, &ipv6_any_addr, 
sizeof(struct in6_addr));
+               } else {
+                       server_ipv4.sin_family = AF_INET;
+                       for (i = 0; i < 8; i++)
+                               server_ipv4.sin_zero[i] = 0;
+                       length = (socklen_t) sizeof(server_ipv4);
+                       server_ipv4.sin_port = htons((unsigned short) ((port) & 
0xFFFF));
+                       server_ipv4.sin_addr.s_addr = htonl(INADDR_ANY);
+               }
+
+#ifndef SOCK_CLOEXEC
+               (void) fcntl(sock, F_SETFD, FD_CLOEXEC);
+#endif
+               if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &on, 
sizeof on) < 0) {
+                       closesocket(sock);
+                       return newErr("setsockopt unexpectedly failed: %s", 
strerror(errno));
+               }
+
+               if (bind(sock, bind_ipv6 ? (SOCKPTR) &server_ipv6 : (SOCKPTR) 
&server_ipv4, length) == -1) {
+                       closesocket(sock);
+                       return(newErr("binding to stream socket port %hu 
failed: %s", port, strerror(errno)));
+               }
+
+               if (getsockname(sock, bind_ipv6 ? (SOCKPTR) &server_ipv6 : 
(SOCKPTR) &server_ipv4, &length) == -1) {
+                       closesocket(sock);
+                       return(newErr("failed getting socket name: %s", 
strerror(errno)));
+               }
        }
 
-       server.sin_family = AF_INET;
        if (bindaddr) {
-               hoste = gethostbyname(bindaddr);
-               if (hoste == NULL) {
+               if (getnameinfo(rp->ai_addr, rp->ai_addrlen, ghost, 
sizeof(ghost), sport, sizeof(sport), NI_NUMERICSERV) != 0) {
                        closesocket(sock);
-                       return newErr("cannot find host %s", bindaddr);
+                       return(newErr("failed getting socket name: %s", 
strerror(errno)));
                }
-               memcpy(&server.sin_addr.s_addr, *(hoste->h_addr_list),
-                               sizeof(server.sin_addr.s_addr));
+               host = ghost;
        } else {
-               server.sin_addr.s_addr = htonl(INADDR_ANY);
-       }
-       for (i = 0; i < 8; i++)
-               server.sin_zero[i] = 0;
-       length = (socklen_t) sizeof(server);
-
-       server.sin_port = htons((unsigned short) ((port) & 0xFFFF));
-       if (bind(sock, (SOCKPTR) &server, length) == -1) {
-               closesocket(sock);
-               return(newErr("binding to stream socket port %hu failed: %s",
-                               port, strerror(errno)));
-       }
-
-       if (getsockname(sock, (SOCKPTR) &server, &length) == -1) {
-               closesocket(sock);
-               return(newErr("failed getting socket name: %s",
-                               strerror(errno)));
-       }
-       hoste = gethostbyaddr(&server.sin_addr.s_addr, 4, server.sin_family);
-       if (hoste == NULL) {
-               snprintf(hostip, sizeof(hostip), "%u.%u.%u.%u",
-                               (unsigned) ((ntohl(server.sin_addr.s_addr) >> 
24) & 0xff),
-                               (unsigned) ((ntohl(server.sin_addr.s_addr) >> 
16) & 0xff),
-                               (unsigned) ((ntohl(server.sin_addr.s_addr) >> 
8) & 0xff),
-                               (unsigned) (ntohl(server.sin_addr.s_addr) & 
0xff));
-               host = hostip;
-       } else {
-               host = hoste->h_name;
+               if (bind_ipv6)
+                       hoste = gethostbyaddr(&server_ipv6.sin6_addr.s6_addr, 
sizeof(server_ipv6.sin6_addr.s6_addr),
+                                                                 
server_ipv6.sin6_family);
+               else
+                       hoste = gethostbyaddr(&server_ipv4.sin_addr.s_addr, 
sizeof(server_ipv4.sin_addr.s_addr),
+                                                                 
server_ipv4.sin_family);
+               if (hoste == NULL) {
+                       if (bind_ipv6) {
+                               snprintf(hostip, sizeof(hostip),
+                                               
"%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
+                                                
(int)server_ipv6.sin6_addr.s6_addr[0],  (int)server_ipv6.sin6_addr.s6_addr[1],
+                                                
(int)server_ipv6.sin6_addr.s6_addr[2],  (int)server_ipv6.sin6_addr.s6_addr[3],
+                                                
(int)server_ipv6.sin6_addr.s6_addr[4],  (int)server_ipv6.sin6_addr.s6_addr[5],
+                                                
(int)server_ipv6.sin6_addr.s6_addr[6],  (int)server_ipv6.sin6_addr.s6_addr[7],
+                                                
(int)server_ipv6.sin6_addr.s6_addr[8],  (int)server_ipv6.sin6_addr.s6_addr[9],
+                                                
(int)server_ipv6.sin6_addr.s6_addr[10], (int)server_ipv6.sin6_addr.s6_addr[11],
+                                                
(int)server_ipv6.sin6_addr.s6_addr[12], (int)server_ipv6.sin6_addr.s6_addr[13],
+                                                
(int)server_ipv6.sin6_addr.s6_addr[14], (int)server_ipv6.sin6_addr.s6_addr[15]);
+                       } else {
+                               snprintf(hostip, sizeof(hostip), "%u.%u.%u.%u",
+                                                (unsigned) 
((ntohl(server_ipv4.sin_addr.s_addr) >> 24) & 0xff),
+                                                (unsigned) 
((ntohl(server_ipv4.sin_addr.s_addr) >> 16) & 0xff),
+                                                (unsigned) 
((ntohl(server_ipv4.sin_addr.s_addr) >> 8) & 0xff),
+                                                (unsigned) 
(ntohl(server_ipv4.sin_addr.s_addr) & 0xff));
+                       }
+                       host = hostip;
+               } else {
+                       host = hoste->h_name;
+               }
        }
 
        /* keep queue of 5 */
@@ -99,7 +171,7 @@ openConnectionTCP(int *ret, const char *
                return(newErr("failed setting socket to listen: %s", 
strerror(errno)));
        }
 
-       Mfprintf(log, "accepting connections on TCP socket %s:%hu\n", host, 
port);
+       Mfprintf(log, "accepting connections on TCP socket %s:%s\n", host, 
sport);
 
        *ret = sock;
        return(NO_ERR);
diff --git a/tools/merovingian/daemon/connections.h 
b/tools/merovingian/daemon/connections.h
--- a/tools/merovingian/daemon/connections.h
+++ b/tools/merovingian/daemon/connections.h
@@ -11,7 +11,7 @@
 
 #include "merovingian.h"
 
-err openConnectionTCP(int *ret, const char *bindaddr, unsigned short port, 
FILE *log);
+err openConnectionTCP(int *ret, bool use_ipv6, const char *bindaddr, unsigned 
short port, FILE *log);
 err openConnectionUDP(int *ret, const char *bindaddr, unsigned short port);
 err openConnectionUNIX(int *ret, const char *path, int mode, FILE *log);
 
diff --git a/tools/merovingian/daemon/merovingian.c 
b/tools/merovingian/daemon/merovingian.c
--- a/tools/merovingian/daemon/merovingian.c
+++ b/tools/merovingian/daemon/merovingian.c
@@ -303,6 +303,7 @@ main(int argc, char *argv[])
        FILE *oerr = NULL;
        int thret;
        char merodontfork = 0;
+       bool use_ipv6 = false;
        confkeyval ckv[] = {
                {"logfile",       strdup("merovingian.log"), 0,                
STR},
                {"pidfile",       strdup("merovingian.pid"), 0,                
STR},
@@ -310,6 +311,7 @@ main(int argc, char *argv[])
                {"sockdir",       strdup("/tmp"),          0,                  
STR},
                {"listenaddr",    strdup("localhost"),     0,                  
STR},
                {"port",          strdup(MERO_PORT),       atoi(MERO_PORT),    
INT},
+               {"ipv6",          strdup("false"),         0,                  
BOOLEAN},
 
                {"exittimeout",   strdup("60"),            60,                 
INT},
                {"forward",       strdup("proxy"),         0,                  
OTHER},
@@ -364,6 +366,8 @@ main(int argc, char *argv[])
        kv->val = strdup("no");
        kv = findConfKey(_mero_db_props, "embedc");
        kv->val = strdup("no");
+       kv = findConfKey(_mero_db_props, "ipv6");
+       kv->val = strdup("no");
        kv = findConfKey(_mero_db_props, "nclients");
        kv->val = strdup("64");
        kv = findConfKey(_mero_db_props, "type");
@@ -579,6 +583,7 @@ main(int argc, char *argv[])
        }
        _mero_props = ckv;
 
+       use_ipv6 = getConfNum(_mero_props, "ipv6") == 1;
        pidfilename = getConfVal(_mero_props, "pidfile");
 
        p = getConfVal(_mero_props, "forward");
@@ -896,7 +901,7 @@ main(int argc, char *argv[])
        Mfprintf(stdout, "monitoring dbfarm %s\n", dbfarm);
 
        /* open up connections */
-       if ((e = openConnectionTCP(&sock, host, port, stdout)) == NO_ERR &&
+       if ((e = openConnectionTCP(&sock, use_ipv6, host, port, stdout)) == 
NO_ERR &&
                (e = openConnectionUNIX(&socku, mapi_usock, 0, stdout)) == 
NO_ERR &&
                (discovery == 0 || (e = openConnectionUDP(&discsock, host, 
port)) == NO_ERR) &&
                (e = openConnectionUNIX(&unsock, control_usock, S_IRWXO, 
_mero_ctlout)) == NO_ERR) {
diff --git a/tools/merovingian/utils/properties.c 
b/tools/merovingian/utils/properties.c
--- a/tools/merovingian/utils/properties.c
+++ b/tools/merovingian/utils/properties.c
@@ -34,6 +34,7 @@ static const confkeyval _internal_prop_k
        {"embedpy",  NULL, 0, BOOLEAN},
        {"embedpy3", NULL, 0, BOOLEAN},
        {"embedc",   NULL, 0, BOOLEAN},
+       {"ipv6",     NULL, 0, BOOLEAN},
        {"nclients", NULL, 0, INT},
        {"mfunnel",  NULL, 0, STR},
        {"dbextra",  NULL, 0, STR},
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to