diff options
-rw-r--r-- | libglusterfs/src/common-utils.c | 71 | ||||
-rw-r--r-- | libglusterfs/src/common-utils.h | 1 | ||||
-rw-r--r-- | rpc/rpc-lib/src/rpcsvc.c | 20 | ||||
-rw-r--r-- | xlators/nfs/server/src/mount3.c | 4 |
4 files changed, 96 insertions, 0 deletions
diff --git a/libglusterfs/src/common-utils.c b/libglusterfs/src/common-utils.c index 22f13861451..75b97722513 100644 --- a/libglusterfs/src/common-utils.c +++ b/libglusterfs/src/common-utils.c @@ -2337,3 +2337,74 @@ gf_ports_reserved (char *blocked_port, gf_boolean_t *ports) out: return result; } + +/* Takes in client ip{v4,v6} and returns associated hostname, if any + * Also, allocates memory for the hostname. + * Returns: 0 for success, -1 for failure + */ +int +gf_get_hostname_from_ip (char *client_ip, char **hostname) +{ + int ret = -1; + struct sockaddr *client_sockaddr = NULL; + struct sockaddr_in client_sock_in = {0}; + struct sockaddr_in6 client_sock_in6 = {0}; + char client_hostname[NI_MAXHOST] = {0}; + char *client_ip_copy = NULL; + char *tmp = NULL; + char *ip = NULL; + + /* if ipv4, reverse lookup the hostname to + * allow FQDN based rpc authentication + */ + if (valid_ipv4_address (client_ip, strlen (client_ip), 0) == _gf_false) { + /* most times, we get a.b.c.d:port form, so check that */ + client_ip_copy = gf_strdup (client_ip); + if (!client_ip_copy) + goto out; + + ip = strtok_r (client_ip_copy, ":", &tmp); + } else { + ip = client_ip; + } + + if (valid_ipv4_address (ip, strlen (ip), 0) == _gf_true) { + client_sockaddr = (struct sockaddr *)&client_sock_in; + client_sock_in.sin_family = AF_INET; + ret = inet_pton (AF_INET, ip, + (void *)&client_sock_in.sin_addr.s_addr); + + } else if (valid_ipv6_address (ip, strlen (ip), 0) == _gf_true) { + client_sockaddr = (struct sockaddr *) &client_sock_in6; + + client_sock_in6.sin6_family = AF_INET6; + ret = inet_pton (AF_INET6, ip, + (void *)&client_sock_in6.sin6_addr); + } else { + goto out; + } + + if (ret != 1) { + ret = -1; + goto out; + } + + ret = getnameinfo (client_sockaddr, + sizeof (*client_sockaddr), + client_hostname, sizeof (client_hostname), + NULL, 0, 0); + if (ret) { + gf_log ("common-utils", GF_LOG_ERROR, + "Could not lookup hostname of %s : %s", + client_ip, gai_strerror (ret)); + ret = -1; + goto out; + } + + *hostname = gf_strdup ((char *)client_hostname); + out: + if (client_ip_copy) + GF_FREE (client_ip_copy); + + return ret; +} diff --git a/libglusterfs/src/common-utils.h b/libglusterfs/src/common-utils.h index b89a988c62c..bbafd1fb039 100644 --- a/libglusterfs/src/common-utils.h +++ b/libglusterfs/src/common-utils.h @@ -575,5 +575,6 @@ char *generate_glusterfs_ctx_id (void); char *gf_get_reserved_ports(); int gf_process_reserved_ports (gf_boolean_t ports[]); gf_boolean_t gf_ports_reserved (char *blocked_port, gf_boolean_t *ports); +int gf_get_hostname_from_ip (char *client_ip, char **hostname); #endif /* _COMMON_UTILS_H */ diff --git a/rpc/rpc-lib/src/rpcsvc.c b/rpc/rpc-lib/src/rpcsvc.c index 7cb89db0946..c8595ee8ed1 100644 --- a/rpc/rpc-lib/src/rpcsvc.c +++ b/rpc/rpc-lib/src/rpcsvc.c @@ -1925,10 +1925,13 @@ rpcsvc_transport_peer_check_search (dict_t *options, char *pattern, char *clstr) char *addrstr = NULL; char *dup_addrstr = NULL; char *svptr = NULL; + char *fqdn = NULL; if ((!options) || (!clstr)) return -1; + ret = dict_get_str (options, "client.fqdn", &fqdn); + if (!dict_get (options, pattern)) return -1; @@ -1956,6 +1959,17 @@ rpcsvc_transport_peer_check_search (dict_t *options, char *pattern, char *clstr) if (ret == 0) goto err; + /* compare hostnames if applicable */ + if (fqdn) { +#ifdef FNM_CASEFOLD + ret = fnmatch (addrtok, fqdn, FNM_CASEFOLD); +#else + ret = fnmatch (addrtok, fqdn, 0); +#endif + if (ret == 0) + goto err; + } + addrtok = strtok_r (NULL, ",", &svptr); } @@ -2174,6 +2188,7 @@ rpcsvc_transport_peer_check_name (dict_t *options, char *volname, int aret = RPCSVC_AUTH_REJECT; int rjret = RPCSVC_AUTH_REJECT; char clstr[RPCSVC_PEER_STRLEN]; + char *hostname = NULL; if (!trans) return ret; @@ -2186,6 +2201,11 @@ rpcsvc_transport_peer_check_name (dict_t *options, char *volname, goto err; } + ret = gf_get_hostname_from_ip (clstr, &hostname); + if (!ret) + ret = dict_set_dynstr (options, "client.fqdn", + hostname); + aret = rpcsvc_transport_peer_check_allow (options, volname, clstr); rjret = rpcsvc_transport_peer_check_reject (options, volname, clstr); diff --git a/xlators/nfs/server/src/mount3.c b/xlators/nfs/server/src/mount3.c index efd74aa58ac..255310fa800 100644 --- a/xlators/nfs/server/src/mount3.c +++ b/xlators/nfs/server/src/mount3.c @@ -1856,6 +1856,8 @@ rpcsvc_actor_t mnt3svc_actors[MOUNT3_PROC_COUNT] = { /* Static init parts are assigned here, dynamic ones are done in * mnt3svc_init and mnt3_init_state. + * Making MOUNT3 a synctask so that the blocking DNS calls during rpc auth + * gets offloaded to syncenv, keeping the main/poll thread unblocked */ rpcsvc_program_t mnt3prog = { .progname = "MOUNT3", @@ -1865,6 +1867,7 @@ rpcsvc_program_t mnt3prog = { .actors = mnt3svc_actors, .numactors = MOUNT3_PROC_COUNT, .min_auth = AUTH_NULL, + .synctask = _gf_true, }; @@ -1953,6 +1956,7 @@ rpcsvc_program_t mnt1prog = { .actors = mnt1svc_actors, .numactors = MOUNT1_PROC_COUNT, .min_auth = AUTH_NULL, + .synctask = _gf_true, }; |