diff options
Diffstat (limited to 'rpc/rpc-transport/socket/src/name.c')
| -rw-r--r-- | rpc/rpc-transport/socket/src/name.c | 180 |
1 files changed, 92 insertions, 88 deletions
diff --git a/rpc/rpc-transport/socket/src/name.c b/rpc/rpc-transport/socket/src/name.c index 8be29163e..1647d5b6b 100644 --- a/rpc/rpc-transport/socket/src/name.c +++ b/rpc/rpc-transport/socket/src/name.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com> + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> This file is part of GlusterFS. - GlusterFS is free software; you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #include <sys/types.h> @@ -24,18 +15,13 @@ #include <netdb.h> #include <string.h> -#ifdef CLIENT_PORT_CEILING -#undef CLIENT_PORT_CEILING -#endif - -#define CLIENT_PORT_CEILING 1024 - #ifndef AF_INET_SDP #define AF_INET_SDP 27 #endif #include "rpc-transport.h" #include "socket.h" +#include "common-utils.h" int32_t gf_resolve_ip6 (const char *hostname, @@ -48,9 +34,17 @@ static int32_t af_inet_bind_to_port_lt_ceiling (int fd, struct sockaddr *sockaddr, socklen_t sockaddr_len, int ceiling) { - int32_t ret = -1; - /* struct sockaddr_in sin = {0, }; */ - uint16_t port = ceiling - 1; + int32_t ret = -1; + uint16_t port = ceiling - 1; + // by default assume none of the ports are blocked and all are available + gf_boolean_t ports[1024] = {_gf_false,}; + int i = 0; + + ret = gf_process_reserved_ports (ports); + if (ret != 0) { + for (i = 0; i < 1024; i++) + ports[i] = _gf_false; + } while (port) { @@ -65,7 +59,11 @@ af_inet_bind_to_port_lt_ceiling (int fd, struct sockaddr *sockaddr, ((struct sockaddr_in *)sockaddr)->sin_port = htons (port); break; } - + // ignore the reserved ports + if (ports[port] == _gf_true) { + port--; + continue; + } ret = bind (fd, sockaddr, sockaddr_len); if (ret == 0) @@ -95,7 +93,7 @@ af_unix_client_bind (rpc_transport_t *this, char *path = data_to_str (path_data); if (!path || strlen (path) > UNIX_PATH_MAX) { gf_log (this->name, GF_LOG_TRACE, - "bind-path not specfied for unix socket, " + "bind-path not specified for unix socket, " "letting connect to assign default value"); goto err; } @@ -111,7 +109,7 @@ af_unix_client_bind (rpc_transport_t *this, } } else { gf_log (this->name, GF_LOG_TRACE, - "bind-path not specfied for unix socket, " + "bind-path not specified for unix socket, " "letting connect to assign default value"); } @@ -126,6 +124,8 @@ client_fill_address_family (rpc_transport_t *this, sa_family_t *sa_family) int32_t ret = -1; if (sa_family == NULL) { + gf_log_callingfn ("", GF_LOG_WARNING, + "sa_family argument is NULL"); goto out; } @@ -140,24 +140,24 @@ client_fill_address_family (rpc_transport_t *this, sa_family_t *sa_family) if (!(remote_host_data || connect_path_data) || (remote_host_data && connect_path_data)) { gf_log (this->name, GF_LOG_ERROR, - "transport.address-family not specified and " - "not able to determine the " - "same from other options (remote-host:%s and " - "transport.unix.connect-path:%s)", + "transport.address-family not specified. " + "Could not guess default value from (remote-host:%s or " + "transport.unix.connect-path:%s) options", data_to_str (remote_host_data), data_to_str (connect_path_data)); + *sa_family = AF_UNSPEC; goto out; } if (remote_host_data) { gf_log (this->name, GF_LOG_DEBUG, "address-family not specified, guessing it " - "to be inet/inet6"); - *sa_family = AF_UNSPEC; + "to be inet from (remote-host: %s)", data_to_str (remote_host_data)); + *sa_family = AF_INET; } else { gf_log (this->name, GF_LOG_DEBUG, "address-family not specified, guessing it " - "to be unix"); + "to be unix from (transport.unix.connect-path: %s)", data_to_str (connect_path_data)); *sa_family = AF_UNIX; } @@ -171,13 +171,11 @@ client_fill_address_family (rpc_transport_t *this, sa_family_t *sa_family) *sa_family = AF_INET6; } else if (!strcasecmp (address_family, "inet-sdp")) { *sa_family = AF_INET_SDP; - } else if (!strcasecmp (address_family, "inet/inet6") - || !strcasecmp (address_family, "inet6/inet")) { - *sa_family = AF_UNSPEC; } else { gf_log (this->name, GF_LOG_ERROR, "unknown address-family (%s) specified", address_family); + *sa_family = AF_UNSPEC; goto out; } } @@ -353,7 +351,7 @@ af_inet_server_get_local_sockaddr (rpc_transport_t *this, struct sockaddr *addr, socklen_t *addr_len) { - struct addrinfo hints, *res = 0; + struct addrinfo hints, *res = 0, *rp = NULL; data_t *listen_port_data = NULL, *listen_host_data = NULL; uint16_t listen_port = -1; char service[NI_MAXSERV], *listen_host = NULL; @@ -378,20 +376,20 @@ af_inet_server_get_local_sockaddr (rpc_transport_t *this, { listen_host = data_to_str (listen_host_data); } else { - if (addr->sa_family == AF_INET6) { - struct sockaddr_in6 *in = (struct sockaddr_in6 *) addr; - in->sin6_addr = in6addr_any; - in->sin6_port = htons(listen_port); - *addr_len = sizeof(struct sockaddr_in6); + if (addr->sa_family == AF_INET6) { + struct sockaddr_in6 *in = (struct sockaddr_in6 *) addr; + in->sin6_addr = in6addr_any; + in->sin6_port = htons(listen_port); + *addr_len = sizeof(struct sockaddr_in6); goto out; - } else if (addr->sa_family == AF_INET) { - struct sockaddr_in *in = (struct sockaddr_in *) addr; - in->sin_addr.s_addr = htonl(INADDR_ANY); - in->sin_port = htons(listen_port); - *addr_len = sizeof(struct sockaddr_in); - goto out; - } - } + } else if (addr->sa_family == AF_INET) { + struct sockaddr_in *in = (struct sockaddr_in *) addr; + in->sin_addr.s_addr = htonl(INADDR_ANY); + in->sin_port = htons(listen_port); + *addr_len = sizeof(struct sockaddr_in); + goto out; + } + } memset (service, 0, sizeof (service)); sprintf (service, "%d", listen_port); @@ -399,7 +397,7 @@ af_inet_server_get_local_sockaddr (rpc_transport_t *this, memset (&hints, 0, sizeof (hints)); hints.ai_family = addr->sa_family; hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE; + hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; ret = getaddrinfo(listen_host, service, &hints, &res); if (ret != 0) { @@ -409,9 +407,20 @@ af_inet_server_get_local_sockaddr (rpc_transport_t *this, ret = -1; goto out; } + /* IPV6 server can handle both ipv4 and ipv6 clients */ + for (rp = res; rp != NULL; rp = rp->ai_next) { + if (rp->ai_addr == NULL) + continue; + if (rp->ai_family == AF_INET6) { + memcpy (addr, rp->ai_addr, rp->ai_addrlen); + *addr_len = rp->ai_addrlen; + } + } - memcpy (addr, res->ai_addr, res->ai_addrlen); - *addr_len = res->ai_addrlen; + if (!(*addr_len)) { + memcpy (addr, res->ai_addr, res->ai_addrlen); + *addr_len = res->ai_addrlen; + } freeaddrinfo (res); @@ -435,12 +444,14 @@ client_bind (rpc_transport_t *this, *sockaddr_len = sizeof (struct sockaddr_in); case AF_INET6: - ret = af_inet_bind_to_port_lt_ceiling (sock, sockaddr, - *sockaddr_len, CLIENT_PORT_CEILING); + if (!this->bind_insecure) { + ret = af_inet_bind_to_port_lt_ceiling (sock, sockaddr, + *sockaddr_len, GF_CLIENT_PORT_CEILING); + } if (ret == -1) { - gf_log (this->name, GF_LOG_WARNING, + gf_log (this->name, GF_LOG_DEBUG, "cannot bind inet socket (%d) to port less than %d (%s)", - sock, CLIENT_PORT_CEILING, strerror (errno)); + sock, GF_CLIENT_PORT_CEILING, strerror (errno)); ret = 0; } break; @@ -469,12 +480,9 @@ socket_client_get_remote_sockaddr (rpc_transport_t *this, { int32_t ret = 0; - if ((sockaddr == NULL) || (sockaddr_len == NULL) - || (sa_family == NULL)) { - ret = -1; - goto err; - } - + GF_VALIDATE_OR_GOTO ("socket", sockaddr, err); + GF_VALIDATE_OR_GOTO ("socket", sockaddr_len, err); + GF_VALIDATE_OR_GOTO ("socket", sa_family, err); ret = client_fill_address_family (this, &sockaddr->sa_family); if (ret) { @@ -522,9 +530,7 @@ server_fill_address_family (rpc_transport_t *this, sa_family_t *sa_family) data_t *address_family_data = NULL; int32_t ret = -1; - if (sa_family == NULL) { - goto out; - } + GF_VALIDATE_OR_GOTO ("socket", sa_family, out); address_family_data = dict_get (this->options, "transport.address-family"); @@ -540,18 +546,16 @@ server_fill_address_family (rpc_transport_t *this, sa_family_t *sa_family) *sa_family = AF_INET_SDP; } else if (!strcasecmp (address_family, "unix")) { *sa_family = AF_UNIX; - } else if (!strcasecmp (address_family, "inet/inet6") - || !strcasecmp (address_family, "inet6/inet")) { - *sa_family = AF_UNSPEC; } else { gf_log (this->name, GF_LOG_ERROR, "unknown address family (%s) specified", address_family); + *sa_family = AF_UNSPEC; goto out; } } else { gf_log (this->name, GF_LOG_DEBUG, - "option address-family not specified, defaulting to inet/inet6"); - *sa_family = AF_UNSPEC; + "option address-family not specified, defaulting to inet"); + *sa_family = AF_INET; } ret = 0; @@ -566,9 +570,9 @@ socket_server_get_local_sockaddr (rpc_transport_t *this, struct sockaddr *addr, { int32_t ret = -1; - if ((addr == NULL) || (addr_len == NULL) || (sa_family == NULL)) { - goto err; - } + GF_VALIDATE_OR_GOTO ("socket", sa_family, err); + GF_VALIDATE_OR_GOTO ("socket", addr, err); + GF_VALIDATE_OR_GOTO ("socket", addr_len, err); ret = server_fill_address_family (this, &addr->sa_family); if (ret == -1) { @@ -605,7 +609,7 @@ int32_t fill_inet6_inet_identifiers (rpc_transport_t *this, struct sockaddr_storage *addr, int32_t addr_len, char *identifier) { - struct sockaddr_storage tmpaddr; + union gf_sock_union sock_union; char service[NI_MAXSERV] = {0,}; char host[NI_MAXHOST] = {0,}; @@ -617,26 +621,26 @@ fill_inet6_inet_identifiers (rpc_transport_t *this, struct sockaddr_storage *add int16_t eight_to_ten = 0; int16_t ten_to_twelve = 0; - memset (&tmpaddr, 0, sizeof (tmpaddr)); - tmpaddr = *addr; + memset (&sock_union, 0, sizeof (sock_union)); + sock_union.storage = *addr; tmpaddr_len = addr_len; - if (((struct sockaddr *) &tmpaddr)->sa_family == AF_INET6) { - one_to_four = ((struct sockaddr_in6 *) &tmpaddr)->sin6_addr.s6_addr32[0]; - four_to_eight = ((struct sockaddr_in6 *) &tmpaddr)->sin6_addr.s6_addr32[1]; + if (sock_union.sa.sa_family == AF_INET6) { + one_to_four = sock_union.sin6.sin6_addr.s6_addr32[0]; + four_to_eight = sock_union.sin6.sin6_addr.s6_addr32[1]; #ifdef GF_SOLARIS_HOST_OS - eight_to_ten = S6_ADDR16(((struct sockaddr_in6 *) &tmpaddr)->sin6_addr)[4]; + eight_to_ten = S6_ADDR16(sock_union.sin6.sin6_addr)[4]; #else - eight_to_ten = ((struct sockaddr_in6 *) &tmpaddr)->sin6_addr.s6_addr16[4]; + eight_to_ten = sock_union.sin6.sin6_addr.s6_addr16[4]; #endif #ifdef GF_SOLARIS_HOST_OS - ten_to_twelve = S6_ADDR16(((struct sockaddr_in6 *) &tmpaddr)->sin6_addr)[5]; + ten_to_twelve = S6_ADDR16(sock_union.sin6.sin6_addr)[5]; #else - ten_to_twelve = ((struct sockaddr_in6 *) &tmpaddr)->sin6_addr.s6_addr16[5]; + ten_to_twelve = sock_union.sin6.sin6_addr.s6_addr16[5]; #endif - twelve_to_sixteen = ((struct sockaddr_in6 *) &tmpaddr)->sin6_addr.s6_addr32[3]; + twelve_to_sixteen = sock_union.sin6.sin6_addr.s6_addr32[3]; /* ipv4 mapped ipv6 address has bits 0-80: 0 @@ -648,8 +652,8 @@ fill_inet6_inet_identifiers (rpc_transport_t *this, struct sockaddr_storage *add four_to_eight == 0 && eight_to_ten == 0 && ten_to_twelve == -1) { - struct sockaddr_in *in_ptr = (struct sockaddr_in *)&tmpaddr; - memset (&tmpaddr, 0, sizeof (tmpaddr)); + struct sockaddr_in *in_ptr = &sock_union.sin; + memset (&sock_union, 0, sizeof (sock_union)); in_ptr->sin_family = AF_INET; in_ptr->sin_port = ((struct sockaddr_in6 *)addr)->sin6_port; @@ -658,7 +662,7 @@ fill_inet6_inet_identifiers (rpc_transport_t *this, struct sockaddr_storage *add } } - ret = getnameinfo ((struct sockaddr *) &tmpaddr, + ret = getnameinfo (&sock_union.sa, tmpaddr_len, host, sizeof (host), service, sizeof (service), |
