From: František Dvořák Date: Fri, 2 Dec 2011 14:27:40 +0000 (+0000) Subject: Fix dual IPv4/IPv6 binding of daemons on SL6 and other platforms. X-Git-Tag: merge_30_head_take2_src~9 X-Git-Url: http://scientific.zcu.cz/git/?a=commitdiff_plain;h=ff6efc70edb774585358423f49b7be1db7f32967;p=jra1mw.git Fix dual IPv4/IPv6 binding of daemons on SL6 and other platforms. 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. --- diff --git a/org.glite.lb.client/src/notification.c b/org.glite.lb.client/src/notification.c index a1427f6..b20663d 100644 --- a/org.glite.lb.client/src/notification.c +++ b/org.glite.lb.client/src/notification.c @@ -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; } diff --git a/org.glite.lb.harvester/src/harvester.c b/org.glite.lb.harvester/src/harvester.c index a578c37..b23b447 100644 --- a/org.glite.lb.harvester/src/harvester.c +++ b/org.glite.lb.harvester/src/harvester.c @@ -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++) { diff --git a/org.glite.lb.logger/src/logd_proto.c b/org.glite.lb.logger/src/logd_proto.c index 8d88f26..8eca13a 100644 --- a/org.glite.lb.logger/src/logd_proto.c +++ b/org.glite.lb.logger/src/logd_proto.c @@ -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; } diff --git a/org.glite.lb.server/src/bkserverd.c b/org.glite.lb.server/src/bkserverd.c index a600125..802972f 100644 --- a/org.glite.lb.server/src/bkserverd.c +++ b/org.glite.lb.server/src/bkserverd.c @@ -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; +}