Changeset: 5a29d1f5dd74 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=5a29d1f5dd74
Modified Files:
        monetdb5/modules/mal/mal_mapi.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/merovingian.c
        tools/merovingian/daemon/merovingian.h
Branch: ipv6
Log Message:

Allow monetdbd to use UDP connections over IPv6 as well.

The discovery service is performed with broadcast on IPv4, however in IPv6 
broadcast is not available. The solution is to multicast to address ff02::1 
(all nodes on the local network) instead.


diffs (truncated from 367 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
@@ -495,9 +495,9 @@ error:
        fprintf(stderr, "!mal_mapi.listen: %s, terminating listener\n", msg);
 }
 
-static struct in6_addr ipv6_loopback_addr = IN6ADDR_LOOPBACK_INIT;
+static const struct in6_addr ipv6_loopback_addr = IN6ADDR_LOOPBACK_INIT;
 
-static struct in6_addr ipv6_any_addr = IN6ADDR_ANY_INIT;
+static const struct in6_addr ipv6_any_addr = IN6ADDR_ANY_INIT;
 
 static str
 SERVERlisten(int *Port, str *Usockfile, int *Maxusers)
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,14 +23,12 @@
 #include "merovingian.h"
 #include "connections.h"
 
-static struct in6_addr ipv6_any_addr = IN6ADDR_ANY_INIT;
-
 err
 openConnectionTCP(int *ret, bool bind_ipv6, const char *bindaddr, unsigned 
short port, FILE *log)
 {
        struct sockaddr_in server_ipv4;
        struct sockaddr_in6 server_ipv6;
-       struct addrinfo *rp = NULL;
+       struct addrinfo *result = NULL, *rp = NULL;
        int sock = -1, check = 0;
        socklen_t length = 0;
        int on = 1;
@@ -43,7 +41,6 @@ openConnectionTCP(int *ret, bool bind_ip
 
        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,
@@ -56,7 +53,7 @@ openConnectionTCP(int *ret, bool bind_ip
 
                check = getaddrinfo(bindaddr, sport, &hints, &result);
                if (check != 0)
-                       return newErr("cannot find host %s with error: %s", 
bindaddr, strerror(errno));
+                       return newErr("cannot find host %s with error: %s", 
bindaddr, gai_strerror(check));
 
                for (rp = result; rp != NULL; rp = rp->ai_next) {
                        sock = socket(rp->ai_family, rp->ai_socktype
@@ -72,13 +69,15 @@ openConnectionTCP(int *ret, bool bind_ip
 
                        if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) 
&on, sizeof on) < 0) {
                                closesocket(sock);
-                               return newErr("setsockopt unexpectedly failed: 
%s", strerror(errno));
+                               continue;
                        }
 
                        if (bind(sock, rp->ai_addr, rp->ai_addrlen) != -1)
                                break; /* working */
                }
                if (rp == NULL) {
+                       if (result)
+                               freeaddrinfo(result);
                        if (sock != -1)
                                closesocket(sock);
                        return newErr("cannot bind to host %s", bindaddr);
@@ -128,7 +127,9 @@ openConnectionTCP(int *ret, bool bind_ip
        }
 
        if (bindaddr) {
-               if (getnameinfo(rp->ai_addr, rp->ai_addrlen, ghost, 
sizeof(ghost), sport, sizeof(sport), NI_NUMERICSERV) != 0) {
+               int res = getnameinfo(rp->ai_addr, rp->ai_addrlen, ghost, 
sizeof(ghost), sport, sizeof(sport), NI_NUMERICSERV);
+               freeaddrinfo(result);
+               if (res != 0) {
                        closesocket(sock);
                        return(newErr("failed getting socket name: %s", 
strerror(errno)));
                }
@@ -178,7 +179,7 @@ openConnectionTCP(int *ret, bool bind_ip
 }
 
 err
-openConnectionUDP(int *ret, const char *bindaddr, unsigned short port)
+openConnectionUDP(int *ret, bool bind_ipv6, const char *bindaddr, unsigned 
short port)
 {
        struct addrinfo hints;
        struct addrinfo *result, *rp;
@@ -188,7 +189,7 @@ openConnectionUDP(int *ret, const char *
        char host[512];
 
        hints = (struct addrinfo) {
-               .ai_family = AF_INET,      /* Allow IPv4 only (broadcasting) */
+               .ai_family = bind_ipv6 ? AF_INET6 : AF_INET,
                .ai_socktype = SOCK_DGRAM, /* Datagram socket */
                .ai_flags = AI_PASSIVE,    /* For wildcard IP address */
                .ai_protocol = 0,          /* Any protocol */
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
@@ -12,7 +12,7 @@
 #include "merovingian.h"
 
 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 openConnectionUDP(int *ret, bool bind_ipv6, const char *bindaddr, unsigned 
short port);
 err openConnectionUNIX(int *ret, const char *path, int mode, FILE *log);
 
 #endif
diff --git a/tools/merovingian/daemon/controlrunner.c 
b/tools/merovingian/daemon/controlrunner.c
--- a/tools/merovingian/daemon/controlrunner.c
+++ b/tools/merovingian/daemon/controlrunner.c
@@ -48,7 +48,7 @@ leavedb(char *name)
                        "LEAV %s mapi:monetdb://%s:%u/",
                        name, _mero_hostname,
                        (unsigned int)getConfNum(_mero_props, "port"));
-       broadcast(buf);
+       difuse(buf);
 }
 
 static void
@@ -103,7 +103,7 @@ anncdbS(sabdb *stats)
                                _mero_hostname,
                                (unsigned int)getConfNum(_mero_props, "port"),
                                getConfNum(_mero_props, "discoveryttl") + 60);
-               broadcast(buf);
+               difuse(buf);
        }
        freeConfFile(props);
        free(props);
diff --git a/tools/merovingian/daemon/discoveryrunner.c 
b/tools/merovingian/daemon/discoveryrunner.c
--- a/tools/merovingian/daemon/discoveryrunner.c
+++ b/tools/merovingian/daemon/discoveryrunner.c
@@ -30,16 +30,20 @@ remotedb _mero_remotedbs = NULL;
 pthread_mutex_t _mero_remotedb_lock = PTHREAD_MUTEX_INITIALIZER;
 
 void
-broadcast(char *msg)
+difuse(char *msg)
 {
-       int len = strlen(msg) + 1;
+       ssize_t sent;
+       size_t len = strlen(msg) + 1;
        if (_mero_broadcastsock < 0)
                return;
-       if (sendto(_mero_broadcastsock, msg, len, 0,
-                               (struct sockaddr *)&_mero_broadcastaddr,
-                               sizeof(_mero_broadcastaddr)) != len)
-               Mfprintf(_mero_discerr, "error while sending broadcast "
-                               "message: %s\n", strerror(errno));
+       sent = sendto(_mero_broadcastsock, msg, len, 0, _mero_broadcastaddr, 
sizeof(*_mero_broadcastaddr));
+       if (sent == -1) {
+               Mfprintf(_mero_discerr, "error while sending %s message: %s\n",
+                                _mero_broadcastaddr->sa_family == AF_INET ? 
"broadcast" : "multicast", strerror(errno));
+       } else if (sent < (ssize_t) len) {
+               Mfprintf(_mero_discerr, "a %s message was not sent entirely\n",
+                                _mero_broadcastaddr->sa_family == AF_INET ? 
"broadcast" : "multicast");
+       }
 }
 
 static int
@@ -306,7 +310,7 @@ discoveryRunner(void *d)
        /* start shouting around that we're here ;) request others to tell
         * what databases they have */
        snprintf(buf, 512, "HELO %s", _mero_hostname);
-       broadcast(buf);
+       difuse(buf);
 
        ckv = getDefaultProps();
        discttl = findConfKey(_mero_props, "discoveryttl");
@@ -344,7 +348,7 @@ discoveryRunner(void *d)
                                                        stats->dbname, val[0] 
== '\0' ? "" : "/", val,
                                                        _mero_hostname, 
(unsigned int)getConfNum(_mero_props, "port"),
                                                        discttl->ival + 60);
-                                       broadcast(buf);
+                                       difuse(buf);
                                }
                                freeConfFile(ckv);
                        }
@@ -358,7 +362,7 @@ discoveryRunner(void *d)
                                                _mero_hostname, (unsigned 
int)getConfNum(_mero_props, "port"),
                                                discttl->ival + 60);
                                /* coverity[string_null] */
-                               broadcast(buf);
+                               difuse(buf);
                        }
                }
 
@@ -523,7 +527,7 @@ discoveryRunner(void *d)
                        snprintf(buf, 512, "LEAV %s mapi:monetdb://%s:%u/",
                                        stats->dbname, _mero_hostname,
                                        (unsigned int)getConfNum(_mero_props, 
"port"));
-                       broadcast(buf);
+                       difuse(buf);
                }
                freeConfFile(ckv);
                stats = stats->next;
@@ -536,7 +540,7 @@ discoveryRunner(void *d)
        if (getConfNum(_mero_props, "control") != 0) {
                snprintf(buf, 512, "LEAV * %s:%u",
                                _mero_hostname, (unsigned 
int)getConfNum(_mero_props, "port"));
-               broadcast(buf);
+               difuse(buf);
        }
 
        free(ckv);
diff --git a/tools/merovingian/daemon/discoveryrunner.h 
b/tools/merovingian/daemon/discoveryrunner.h
--- a/tools/merovingian/daemon/discoveryrunner.h
+++ b/tools/merovingian/daemon/discoveryrunner.h
@@ -11,7 +11,7 @@
 
 #include "msabaoth.h"
 
-void broadcast(char *msg);
+void difuse(char *msg);
 void registerMessageTap(int fd);
 void unregisterMessageTap(int fd);
 void *discoveryRunner(void *d);
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
@@ -116,8 +116,12 @@ FILE *_mero_ctlout = NULL;
 FILE *_mero_ctlerr = NULL;
 /* broadcast socket for announcements */
 int _mero_broadcastsock = -1;
-/* broadcast address/port */
-struct sockaddr_in _mero_broadcastaddr;
+/* ipv6 global any bind address constant */
+const struct in6_addr ipv6_any_addr = IN6ADDR_ANY_INIT;
+/* broadcast/multicast address/port */
+struct sockaddr_in server_ipv4;
+struct sockaddr_in6 server_ipv6;
+struct sockaddr *_mero_broadcastaddr;
 /* hostname of this machine */
 char _mero_hostname[128];
 /* default options read from config file */
@@ -903,36 +907,97 @@ main(int argc, char *argv[])
        /* open up connections */
        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) &&
+               (discovery == 0 || (e = openConnectionUDP(&discsock, use_ipv6, 
host, port)) == NO_ERR) &&
                (e = openConnectionUNIX(&unsock, control_usock, S_IRWXO, 
_mero_ctlout)) == NO_ERR) {
                pthread_t ctid = 0;
                pthread_t dtid = 0;
 
                if (discovery == 1) {
-                       _mero_broadcastsock = socket(AF_INET, SOCK_DGRAM
+                       if (use_ipv6) { //as ipv6 does not support broadcast, 
we will use multicast instead
+                               int check = -1;
+                               socklen_t length = 0;
+                               struct ipv6_mreq mreq;
+                               struct addrinfo *multi, hints = (struct 
addrinfo) {
+                                       .ai_family = AF_INET6,
+                                       .ai_socktype = SOCK_DGRAM,
+                                       .ai_flags = AI_PASSIVE,
+                                       .ai_protocol = 0,
+                                       .ai_canonname = NULL,
+                                       .ai_addr = NULL,
+                                       .ai_next = NULL,
+                               };
+
+                               _mero_broadcastaddr = (struct sockaddr*) 
&server_ipv6;
+                               server_ipv6.sin6_family = AF_INET6;
+                               server_ipv6.sin6_flowinfo = 0;
+                               server_ipv6.sin6_scope_id = 0;
+                               server_ipv6.sin6_port = htons(port);
+                               memcpy(server_ipv6.sin6_addr.s6_addr, 
&ipv6_any_addr, sizeof(struct in6_addr));
+                               length = (socklen_t) sizeof(server_ipv6);
+
+                               _mero_broadcastsock = socket(AF_INET6, 
SOCK_DGRAM
 #ifdef SOCK_CLOEXEC
-                                                                               
 | SOCK_CLOEXEC
+                                                                               
        | SOCK_CLOEXEC
 #endif
-                                                                               
 , 0);
-                       ret = 1;
-                       if (_mero_broadcastsock == -1 ||
-                               setsockopt(_mero_broadcastsock,
-                                                  SOL_SOCKET, SO_BROADCAST, 
&ret, sizeof(ret)) == -1)
-                       {
-                               Mfprintf(stderr, "cannot create broadcast 
package, "
-                                               "discovery services 
disabled\n");
-                               closesocket(discsock);
-                               discsock = -1;
+                                               , 0);
+                               if (_mero_broadcastsock == -1 || 
bind(_mero_broadcastsock, (SOCKPTR) &server_ipv6,
+                                                length) != 0) {
+                                       Mfprintf(stderr, "cannot create 
multicast package: %s\n", strerror(errno));
+                                       closesocket(discsock);
+                                       if (_mero_broadcastsock >= 0)
+                                               
closesocket(_mero_broadcastsock);
+                                       discsock = -1;
+                               } else if ((check = getaddrinfo("ff02::1", 
NULL, &hints, &multi)) != 0) {
+                                       //ipv6 multicast all nodes on the local 
network segment
+                                       Mfprintf(stderr, "cannot create 
multicast package: %s\n", gai_strerror(check));
+                                       closesocket(discsock);
+                                       closesocket(_mero_broadcastsock);
+                                       discsock = -1;
+                               }
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to