Fix dual IPv4/IPv6 binding of daemons on SL6 and other platforms.
authorFrantišek Dvořák <valtri@civ.zcu.cz>
Fri, 2 Dec 2011 14:27:40 +0000 (14:27 +0000)
committerFrantišek Dvořák <valtri@civ.zcu.cz>
Fri, 2 Dec 2011 14:27:40 +0000 (14:27 +0000)
getaddrinfo() returns AF_INET family first on SL6, but to support IPv6, we need to prefer AF_INET6. For IPv4 is used mapped IPv4 on AF_INET6 sockets, now enabled explicitely.

org.glite.lb.client/src/notification.c
org.glite.lb.harvester/src/harvester.c
org.glite.lb.logger/src/logd_proto.c
org.glite.lb.server/src/bkserverd.c

index a1427f6..b20663d 100644 (file)
@@ -54,6 +54,7 @@ static const char* const request_headers[] = {
        NULL
 };
 
+static int zero = 0;
 
 
 
@@ -94,58 +95,74 @@ static void get_name_and_port(const char *address, char **name, int *port)
 }      
 
 
-static int my_bind(edg_wll_Context ctx, const char *name, int port, int *fd)
-{
-       int             sock;
-       int             ret;
-       struct addrinfo *ai;
-       struct addrinfo hints;
-       char            *portstr = NULL;
-
-       asprintf(&portstr, "%d", port);
-       if (portstr == NULL) {
-               return edg_wll_SetError(ctx, ENOMEM, "my_bind(): ENOMEM converting port number");
-       }
+static int daemon_listen(edg_wll_Context ctx, const char *name, char *port, int *conn_out) {
+       struct  addrinfo *ai;
+       struct  addrinfo hints;
+       int     conn;
+       int     gaie;
 
        memset (&hints, '\0', sizeof (hints));
        hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV | AI_PASSIVE | AI_ADDRCONFIG;
        hints.ai_socktype = SOCK_STREAM;
+       hints.ai_family = AF_INET6;
 
-       ret = getaddrinfo (name, portstr, &hints, &ai);
-       free(portstr);
-       if (ret != 0) {
-               return edg_wll_SetError(ctx, EADDRNOTAVAIL, gai_strerror(ret));
+       gaie = getaddrinfo (name, port, &hints, &ai);
+       if (gaie != 0 || ai == NULL) {
+               hints.ai_family = 0;
+               gaie = getaddrinfo (NULL, port, &hints, &ai);
+       }
+
+       gaie = getaddrinfo (name, port, &hints, &ai);
+       if (gaie != 0) {
+               return edg_wll_SetError(ctx, EADDRNOTAVAIL, gai_strerror(gaie));
        }
        if (ai == NULL) {
                return edg_wll_SetError(ctx, EADDRNOTAVAIL, "no result from getaddrinfo");
        }
 
-       sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
-       if (sock == -1) { 
+       conn = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+       if ( conn < 0 ) { 
                freeaddrinfo(ai);
-               return  edg_wll_SetError(ctx, errno, "socket() failed");
+               return edg_wll_SetError(ctx, errno, "socket() failed");
        }
+       //setsockopt(conn, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
+       if (ai->ai_family == AF_INET6)
+               setsockopt(conn, IPPROTO_IPV6, IPV6_V6ONLY, &zero, sizeof(zero));
 
-//     setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
-       ret = bind(sock, ai->ai_addr, ai->ai_addrlen);
-       if (ret == -1) { 
+       if ( bind(conn, ai->ai_addr, ai->ai_addrlen) )
+       {
                edg_wll_SetError(ctx, errno, "bind() failed");
-               close(sock); 
+               close(conn); 
                freeaddrinfo(ai);
                return edg_wll_Error(ctx, NULL, NULL);
        }
-       freeaddrinfo(ai);
 
-       ret = listen(sock, CON_QUEUE);
-       if (ret == -1) { 
+       if ( listen(conn, CON_QUEUE) ) { 
                edg_wll_SetError(ctx, errno, "listen() failed");
-               close(sock); 
+               close(conn); 
                return edg_wll_Error(ctx, NULL, NULL);
        }
 
-       *fd = sock;
-       
-       return edg_wll_Error(ctx,NULL,NULL);
+       freeaddrinfo(ai);
+
+       *conn_out = conn;
+       return 0;
+}
+
+
+static int my_bind(edg_wll_Context ctx, const char *name, int port, int *fd)
+{
+       int             ret;
+       char            *portstr = NULL;
+
+       asprintf(&portstr, "%d", port);
+       if (portstr == NULL) {
+               return edg_wll_SetError(ctx, ENOMEM, "my_bind(): ENOMEM converting port number");
+       }
+       ret = daemon_listen(ctx, name, portstr, fd);
+       free(portstr);
+
+       return ret;
 }
        
 
index a578c37..b23b447 100644 (file)
@@ -77,6 +77,8 @@ limitations under the License.
 
 #define RTM_SUMMARY_JOBS 100
 
+#define CON_QUEUE 10
+
 #define RTM_DB_TABLE_JOBS "jobs"
 #define RTM_DB_TABLE_LBS "lb20"
 #define DBPAR(N) ("$" (N))
@@ -1629,6 +1631,69 @@ void db_free_notifs() {
 }
 
 
+static int daemon_listen(thread_t *t, const char *name, char *port, int *conn_out) {
+       struct  addrinfo *ai;
+       struct  addrinfo hints;
+       char    pretty_addr[256];
+       int     conn;
+       int     gaie;
+       const int       zero = 0;
+       const int       one = 1;
+
+       memset (&hints, '\0', sizeof (hints));
+       hints.ai_flags = AI_NUMERICSERV | AI_PASSIVE | AI_ADDRCONFIG;
+       hints.ai_socktype = SOCK_STREAM;
+       hints.ai_family = AF_INET6;
+
+       gaie = getaddrinfo (name, port, &hints, &ai);
+       if (gaie != 0 || ai == NULL) {
+               hints.ai_family = 0;
+               gaie = getaddrinfo (NULL, port, &hints, &ai);
+       }
+
+       gaie = getaddrinfo (name, port, &hints, &ai);
+       if (gaie != 0) {
+               lprintf(t, ERR, "getaddrinfo: %s", gai_strerror (gaie));
+               return 1;
+       }
+       if (ai == NULL) {
+               lprintf(t, ERR, "getaddrinfo: no result");
+               return 1;
+       }
+
+       conn = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+       if ( conn < 0 ) {
+               lprintf(t, ERR, "socket(): %s", strerror(errno));
+               freeaddrinfo(ai);
+               return 1; 
+       }
+       lprintf(t, DBG, "socket created: %d", conn);
+       setsockopt(conn, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
+       if (ai->ai_family == AF_INET6)
+               setsockopt(conn, IPPROTO_IPV6, IPV6_V6ONLY, &zero, sizeof(zero));
+
+       if ( bind(conn, ai->ai_addr, ai->ai_addrlen) )
+       {
+               lprintf(t, ERR, "bind(%s): %s", port, strerror(errno));
+               close(conn);
+               freeaddrinfo(ai);
+               return 1;
+       }
+
+       if ( listen(conn, CON_QUEUE) ) {
+               lprintf(t, ERR, "listen(): %s", strerror(errno));
+               close(conn);
+               freeaddrinfo(ai);
+               return 1; 
+       }
+
+       freeaddrinfo(ai);
+
+       *conn_out = conn;
+       return 0;
+}
+
+
 void *notify_thread(void *thread_data) {
        int i, j, err;
        time_t now, bootstrap;
@@ -1641,10 +1706,7 @@ void *notify_thread(void *thread_data) {
        thread_t *t = (thread_t *)thread_data;
        edg_wll_Context ctx = NULL;
        int flags = 0;
-       struct addrinfo *ai = NULL;
-       struct addrinfo hints;
        char *portstr;
-       const int       one = 1;
 
        lprintf(t, DBG, "thread started");
 
@@ -1659,41 +1721,13 @@ void *notify_thread(void *thread_data) {
        if (config.key) edg_wll_SetParam(ctx, EDG_WLL_PARAM_X509_KEY, config.key);
 
        // listen
-       memset(&hints, 0, sizeof hints);
-       hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV | AI_PASSIVE | AI_ADDRCONFIG;
-       hints.ai_socktype = SOCK_STREAM;
        asprintf(&portstr, "%d", listen_port ? (listen_port + t->id) : 0);
        if (!portstr) {
                lprintf(t, ERR, "can't convert port number: ENOMEM");
                goto exit;
        }
-       err = getaddrinfo(NULL, portstr, &hints, &ai);
-       free(portstr); portstr = NULL;
-       if (err != 0) {
-               lprintf(t, ERR, "getaddrinfo() failed: %s", gai_strerror(err));
-               goto exit;
-       }
-       if (!ai) {
-               lprintf(t, ERR, "no result from getaddrinfo()");
+       if (daemon_listen(t, NULL, portstr, &sock) != 0)
                goto exit;
-       }
-       if ((sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol)) < 0) {
-               lprintf(t, ERR, "can't create socket: %s", strerror(errno));
-               goto exit;
-       }
-       lprintf(t, DBG, "socket created: %d", sock);
-
-       setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
-
-       if (bind(sock, ai->ai_addr, ai->ai_addrlen) != 0) {
-               lprintf(t, ERR, "can't bind socket: %s, port = %d", strerror(errno), listen_port ? listen_port + t->id : -1);
-               goto exit;
-       }
-       if (listen(sock, 10) != 0) {
-               lprintf(t, ERR, "can't listen on socket: %s", strerror(errno));
-               goto exit;
-       }
-       freeaddrinfo(ai); ai = NULL;
 
 #ifdef WITH_LBU_DB
        if (db_init(t, &t->dbctx) == 0)
@@ -2032,7 +2066,6 @@ cont:
 
 exit:  
        if (sock != -1) close(sock);
-       if (ai) freeaddrinfo(ai);
 //     for (i = 0; conditions[i]; i++) free(conditions[i]);
        if (t->nservers && quit != RTM_QUIT_PRESERVE && quit != RTM_QUIT_RELOAD) {
                for (i = 0; i < t->nservers; i++) {
index 8d88f26..8eca13a 100644 (file)
@@ -39,6 +39,9 @@ limitations under the License.
 
 #include "logd_proto.h"
 
+#define CON_QUEUE 5
+
+static const int zero = 0;
 static const int one = 1;
 
 extern char* socket_path;
@@ -131,6 +134,64 @@ static int send_answer_back(edg_wll_GssConnection *con, int answer, struct timev
        }
 }
 
+static int daemon_listen(const char *name, char *port, int *conn_out) {
+       struct  addrinfo *ai;
+       struct  addrinfo hints;
+       int     conn;
+       int     gaie;
+
+       memset (&hints, '\0', sizeof (hints));
+       hints.ai_flags = AI_NUMERICSERV | AI_PASSIVE | AI_ADDRCONFIG;
+       hints.ai_socktype = SOCK_STREAM;
+       hints.ai_family = AF_INET6;
+
+       gaie = getaddrinfo (name, port, &hints, &ai);
+       if (gaie != 0 || ai == NULL) {
+               hints.ai_family = 0;
+               gaie = getaddrinfo (NULL, port, &hints, &ai);
+       }
+
+       gaie = getaddrinfo (name, port, &hints, &ai);
+       if (gaie != 0) {
+               glite_common_log(LOG_CATEGORY_CONTROL, LOG_PRIORITY_FATAL, "getaddrinfo: %s", gai_strerror (gaie));
+               return 1;
+       }
+       if (ai == NULL) {
+               glite_common_log(LOG_CATEGORY_CONTROL, LOG_PRIORITY_FATAL, "getaddrinfo: no result");
+               return 1;
+       }
+
+       conn = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+       if ( conn < 0 ) { 
+               glite_common_log(LOG_CATEGORY_CONTROL, LOG_PRIORITY_FATAL, "socket(): %s", strerror(errno));
+               freeaddrinfo(ai);
+               return 1; 
+       }
+       setsockopt(conn, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
+       if (ai->ai_family == AF_INET6)
+               setsockopt(conn, IPPROTO_IPV6, IPV6_V6ONLY, &zero, sizeof(zero));
+
+       if ( bind(conn, ai->ai_addr, ai->ai_addrlen) )
+       {
+               glite_common_log(LOG_CATEGORY_CONTROL, LOG_PRIORITY_FATAL, "bind(%s): %s", port, strerror(errno));
+               close(conn);
+               freeaddrinfo(ai);
+               return 1;
+       }
+
+       if ( listen(conn, CON_QUEUE) ) { 
+               glite_common_log(LOG_CATEGORY_CONTROL, LOG_PRIORITY_FATAL, "listen(): %s", strerror(errno));
+               close(conn);
+               freeaddrinfo(ai);
+               return 1; 
+       }
+
+       freeaddrinfo(ai);
+
+       *conn_out = conn;
+       return 0;
+}
+
 /*
  *----------------------------------------------------------------------
  *
@@ -259,8 +320,6 @@ int do_listen(int port)
 {
        int                ret;
        int                sock;
-       struct addrinfo *ai;
-       struct addrinfo hints;
        char            *portstr = NULL;
 
        asprintf(&portstr, "%d", port);
@@ -269,45 +328,8 @@ int do_listen(int port)
                return -1;
        }
 
-       memset (&hints, '\0', sizeof (hints));
-       hints.ai_flags = AI_NUMERICSERV | AI_PASSIVE | AI_ADDRCONFIG;
-       hints.ai_socktype = SOCK_STREAM;
-
-       ret = getaddrinfo (NULL, portstr, &hints, &ai);
-       if (ret != 0) {
-               glite_common_log(LOG_CATEGORY_CONTROL, LOG_PRIORITY_FATAL, "getaddrinfo: %s", gai_strerror (ret));
-               return -1;
-       }
-       if (ai == NULL) {
-               glite_common_log(LOG_CATEGORY_CONTROL, LOG_PRIORITY_FATAL, "getaddrinfo: no return");
+       if (daemon_listen(NULL, portstr, &sock) != 0)
                return -1;
-       }
-
-       sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
-       if (sock == -1) { 
-               glite_common_log_SYS_ERROR("socket"); 
-               glite_common_log(LOG_CATEGORY_ACCESS,LOG_PRIORITY_ERROR,"do_listen(): error creating socket\n");
-               freeaddrinfo(ai);
-               return -1; 
-       }
-
-       setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
-       ret = bind(sock, ai->ai_addr, ai->ai_addrlen);
-       if (ret == -1) { 
-               glite_common_log_SYS_ERROR("bind"); 
-               glite_common_log(LOG_CATEGORY_ACCESS,LOG_PRIORITY_ERROR,"do_listen(): error binding socket\n");
-               freeaddrinfo(ai);
-               return -1; 
-       }
-       freeaddrinfo(ai);
-
-       ret = listen(sock, 5);
-       if (ret == -1) { 
-               glite_common_log_SYS_ERROR("listen"); 
-               glite_common_log(LOG_CATEGORY_ACCESS,LOG_PRIORITY_ERROR,"do_listen(): error listening on socket\n");
-               close(sock); 
-               return -1; 
-       }
 
        return sock;
 }
index a600125..802972f 100644 (file)
@@ -140,6 +140,7 @@ int                                 enable_lcas = 0;
 int                                            debug  = 0;
 int                                            rgma_export = 0;
 static const int               one = 1;
+static const int               zero = 0;
 static int                             noAuth = 0;
 static int                             noIndex = 0;
 static int                             strict_locking = 0;
@@ -304,6 +305,7 @@ static int asyn_gethostbyaddr(char **, char **, const struct sockaddr *, int, st
 static int add_root(edg_wll_Context, char *, authz_action);
 static int parse_limits(char *, int *, int *, int *);
 static int check_mkdir(const char *);
+static int daemon_listen(const char *name, char *port, int *conn_out);
 
 
 /*
@@ -387,10 +389,7 @@ struct clnt_data_t {
 int main(int argc, char *argv[])
 {
        int                     i;
-       struct addrinfo *ai;
-       struct addrinfo hints;
        char *portstr = NULL;
-       int     gaie;
        int                                     opt, pidfile_forced = 0;
        char                            pidfile[PATH_MAX] = EDG_BKSERVERD_PIDFILE,
                                           *name;
@@ -644,97 +643,21 @@ int main(int argc, char *argv[])
                glite_common_log(LOG_CATEGORY_CONTROL, LOG_PRIORITY_INFO, "Server address: %s:%d", fake_host, fake_port);
        }
 
-       memset (&hints, '\0', sizeof (hints));
-       hints.ai_flags = AI_NUMERICSERV | AI_PASSIVE | AI_ADDRCONFIG;
-       hints.ai_socktype = SOCK_STREAM;
-
        if ((mode & SERVICE_SERVER)) {
-               gaie = getaddrinfo (NULL, port, &hints, &ai);
-               if (gaie != 0) {
-                       glite_common_log(LOG_CATEGORY_CONTROL, LOG_PRIORITY_FATAL, "getaddrinfo: %s", gai_strerror (gaie));
-                       return 1;
-               }
-               if (ai == NULL) {
-                       glite_common_log(LOG_CATEGORY_CONTROL, LOG_PRIORITY_FATAL, "getaddrinfo: no return");
+               if (daemon_listen(NULL, port, &service_table[SRV_SERVE].conn) != 0) {
                        return 1;
                }
-               service_table[SRV_SERVE].conn = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
-               if ( service_table[SRV_SERVE].conn < 0 ) { 
-                       glite_common_log(LOG_CATEGORY_CONTROL, LOG_PRIORITY_FATAL, "socket()");
-                       freeaddrinfo(ai);
-                       return 1; 
-               }
-               setsockopt(service_table[SRV_SERVE].conn, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
-               if ( bind(service_table[SRV_SERVE].conn, ai->ai_addr, ai->ai_addrlen) )
-               { 
-                       glite_common_log(LOG_CATEGORY_CONTROL, LOG_PRIORITY_FATAL, "bind(%s)", port);
-                       freeaddrinfo(ai);
-                       return 1;
-               }
-               freeaddrinfo(ai);
-               if ( listen(service_table[SRV_SERVE].conn, CON_QUEUE) ) { 
-                       glite_common_log(LOG_CATEGORY_CONTROL, LOG_PRIORITY_FATAL, "listen()");
-                       return 1; 
-               }
 
                asprintf(&portstr, "%d", atoi(port)+1);
-               gaie = getaddrinfo (NULL, portstr, &hints, &ai);
-               if (gaie != 0) {
-                       glite_common_log(LOG_CATEGORY_CONTROL, LOG_PRIORITY_FATAL, "getaddrinfo: %s", gai_strerror (gaie));
+               if (daemon_listen(NULL, portstr, &service_table[SRV_STORE].conn) != 0) {
+                       free(portstr);
                        return 1;
                }
-               if (ai == NULL) {
-                       glite_common_log(LOG_CATEGORY_CONTROL, LOG_PRIORITY_FATAL, "getaddrinfo: no return");
-                       return 1;
-               }
-               service_table[SRV_STORE].conn = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
-               if ( service_table[SRV_STORE].conn < 0 ) { 
-                       freeaddrinfo(ai);
-                       glite_common_log(LOG_CATEGORY_CONTROL, LOG_PRIORITY_FATAL, "socket()");
-                       return 1; 
-               }
-               setsockopt(service_table[SRV_STORE].conn, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
-               if ( bind(service_table[SRV_STORE].conn, ai->ai_addr, ai->ai_addrlen) )
-               { 
-                       glite_common_log(LOG_CATEGORY_CONTROL, LOG_PRIORITY_FATAL, "bind(%s)", portstr);
-                       freeaddrinfo(ai);
-                       return 1;
-               }
-               freeaddrinfo(ai);
-               if ( listen(service_table[SRV_STORE].conn, CON_QUEUE) ) { 
-                       glite_common_log(LOG_CATEGORY_CONTROL, LOG_PRIORITY_FATAL, "listen()");
-                       return 1; 
-               }
                free(portstr); portstr = NULL;
 
 #ifdef GLITE_LB_SERVER_WITH_WS
-               gaie = getaddrinfo (NULL, ws_port, &hints, &ai);
-               if (gaie != 0) {
-                       glite_common_log(LOG_CATEGORY_CONTROL, LOG_PRIORITY_FATAL, "getaddrinfo: %s", gai_strerror (gaie));
-                       return 1;
-               }
-               if (ai == NULL) {
-                       glite_common_log(LOG_CATEGORY_CONTROL, LOG_PRIORITY_FATAL, "getaddrinfo: no return");
-                       return 1;
-               }
-               service_table[SRV_WS].conn = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
-               if ( service_table[SRV_WS].conn < 0 ) { 
-                       glite_common_log(LOG_CATEGORY_CONTROL, LOG_PRIORITY_FATAL, "socket()");
-                       freeaddrinfo(ai);
-                       return 1; 
-               }
-               setsockopt(service_table[SRV_WS].conn, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
-               if ( bind(service_table[SRV_WS].conn, ai->ai_addr, ai->ai_addrlen) )
-               { 
-                       glite_common_log(LOG_CATEGORY_CONTROL, LOG_PRIORITY_FATAL, "bind(%s)",ws_port);
-                       freeaddrinfo(ai);
+               if (daemon_listen(NULL, ws_port, &service_table[SRV_WS].conn) != 0)
                        return 1;
-               }
-               freeaddrinfo(ai);
-               if ( listen(service_table[SRV_WS].conn, CON_QUEUE) ) { 
-                       glite_common_log(LOG_CATEGORY_CONTROL, LOG_PRIORITY_FATAL, "listen()");
-                       return 1; 
-               }
 #endif /* GLITE_LB_SERVER_WITH_WS */
 
                if (!server_cert || !server_key)
@@ -2034,3 +1957,60 @@ static int decrement_timeout(struct timeval *timeout, struct timeval before, str
         else return(0);
 }
 
+static int daemon_listen(const char *name, char *port, int *conn_out) {
+       struct  addrinfo *ai;
+       struct  addrinfo hints;
+       int     conn;
+       int     gaie;
+
+       memset (&hints, '\0', sizeof (hints));
+       hints.ai_flags = AI_NUMERICSERV | AI_PASSIVE | AI_ADDRCONFIG;
+       hints.ai_socktype = SOCK_STREAM;
+       hints.ai_family = AF_INET6;
+
+       gaie = getaddrinfo (name, port, &hints, &ai);
+       if (gaie != 0 || ai == NULL) {
+               hints.ai_family = 0;
+               gaie = getaddrinfo (NULL, port, &hints, &ai);
+       }
+
+       gaie = getaddrinfo (name, port, &hints, &ai);
+       if (gaie != 0) {
+               glite_common_log(LOG_CATEGORY_CONTROL, LOG_PRIORITY_FATAL, "getaddrinfo: %s", gai_strerror (gaie));
+               return 1;
+       }
+       if (ai == NULL) {
+               glite_common_log(LOG_CATEGORY_CONTROL, LOG_PRIORITY_FATAL, "getaddrinfo: no result");
+               return 1;
+       }
+
+       conn = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+       if ( conn < 0 ) { 
+               glite_common_log(LOG_CATEGORY_CONTROL, LOG_PRIORITY_FATAL, "socket(): %s", strerror(errno));
+               freeaddrinfo(ai);
+               return 1; 
+       }
+       setsockopt(conn, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
+       if (ai->ai_family == AF_INET6)
+               setsockopt(conn, IPPROTO_IPV6, IPV6_V6ONLY, &zero, sizeof(zero));
+
+       if ( bind(conn, ai->ai_addr, ai->ai_addrlen) )
+       {
+               glite_common_log(LOG_CATEGORY_CONTROL, LOG_PRIORITY_FATAL, "bind(%s): %s", port, strerror(errno));
+               close(conn);
+               freeaddrinfo(ai);
+               return 1;
+       }
+
+       if ( listen(conn, CON_QUEUE) ) { 
+               glite_common_log(LOG_CATEGORY_CONTROL, LOG_PRIORITY_FATAL, "listen(): %s", strerror(errno));
+               close(conn);
+               freeaddrinfo(ai);
+               return 1; 
+       }
+
+       freeaddrinfo(ai);
+
+       *conn_out = conn;
+       return 0;
+}