From d3f0de90d0c5166e63f5764d2f21703fd29ce976 Mon Sep 17 00:00:00 2001 From: Santosh Kumar Pradhan Date: Fri, 6 Jun 2014 12:22:04 +0530 Subject: gNFS: Fix multi-homed m/c issue in NFS subdir auth NFS subdir authentication doesn't correctly handle multi-homed (host with multiple NIC having multiple IP addr) OR multi-protocol (IPv4 and IPv6) network addresses. When user/admin sets HOSTNAME in gluster CLI for NFS subdir auth, mnt3_verify_auth() routine does not iterate over all the resolved n/w addrs returned by getaddrinfo() n/w API. Instead, it just tests with the one returned first. 1. Iterate over all the n/w addrs (linked list) returned by getaddrinfo(). 2. Move the n/w mask calculation part to mnt3_export_fill_hostspec() instead of doing it in mnt3_verify_auth() i.e. calculating for each mount request. It does not change for MOUNT req. 3. Integrate "subnet support code rpc-auth.addr..allow" and "NFS subdir auth code" to remove code duplication. Change-Id: I26b0def52c22cda35ca11766afca3df5fd4360bf BUG: 1102293 Signed-off-by: Santosh Kumar Pradhan Reviewed-on: http://review.gluster.org/8048 Reviewed-by: Rajesh Joseph Tested-by: Gluster Build System Reviewed-by: Niels de Vos --- rpc/rpc-lib/src/rpcsvc.c | 45 ++++++++++++++++++--------------------------- 1 file changed, 18 insertions(+), 27 deletions(-) (limited to 'rpc/rpc-lib/src') diff --git a/rpc/rpc-lib/src/rpcsvc.c b/rpc/rpc-lib/src/rpcsvc.c index 5241a265ce8..814af05f7b6 100644 --- a/rpc/rpc-lib/src/rpcsvc.c +++ b/rpc/rpc-lib/src/rpcsvc.c @@ -61,7 +61,7 @@ rpcsvc_notify (rpc_transport_t *trans, void *mydata, rpc_transport_event_t event, void *data, ...); static int -match_subnet_v4 (const char *addrtok, const char *ipaddr); +rpcsvc_match_subnet_v4 (const char *addrtok, const char *ipaddr); rpcsvc_notify_wrapper_t * rpcsvc_notify_wrapper_alloc (void) @@ -2265,9 +2265,9 @@ rpcsvc_transport_peer_check_search (dict_t *options, char *pattern, goto err; } - /* Compare IPv4 subnetwork */ + /* Compare IPv4 subnetwork, TODO: IPv6 subnet support */ if (strchr (addrtok, '/')) { - ret = match_subnet_v4 (addrtok, ip); + ret = rpcsvc_match_subnet_v4 (addrtok, ip); if (ret == 0) goto err; } @@ -2565,9 +2565,9 @@ out: } /* - * match_subnet_v4() takes subnetwork address pattern and checks - * if the target IPv4 address has the same network address with - * the help of network mask. + * rpcsvc_match_subnet_v4() takes subnetwork address pattern and checks + * if the target IPv4 address has the same network address with the help + * of network mask. * * Returns 0 for SUCCESS and -1 otherwise. * @@ -2575,12 +2575,12 @@ out: * as it's already being done at the time of CLI SET. */ static int -match_subnet_v4 (const char *addrtok, const char *ipaddr) +rpcsvc_match_subnet_v4 (const char *addrtok, const char *ipaddr) { char *slash = NULL; char *netaddr = NULL; - long prefixlen = -1; int ret = -1; + uint32_t prefixlen = 0; uint32_t shift = 0; struct sockaddr_in sin1 = {0, }; struct sockaddr_in sin2 = {0, }; @@ -2602,28 +2602,19 @@ match_subnet_v4 (const char *addrtok, const char *ipaddr) goto out; /* - * Find the network mask in network byte order. - * NB: 32 : Max len of IPv4 address. + * Find the IPv4 network mask in network byte order. + * IMP: String slash+1 is already validated, it cant have value + * more than IPv4_ADDR_SIZE (32). */ - prefixlen = atoi (slash + 1); - shift = 32 - (uint32_t)prefixlen; + prefixlen = (uint32_t) atoi (slash + 1); + shift = IPv4_ADDR_SIZE - prefixlen; mask.sin_addr.s_addr = htonl ((uint32_t)~0 << shift); - /* - * Check if both have same network address. - * Extract the network address from the IP addr by applying the - * network mask. If they match, return SUCCESS. i.e. - * - * (x == y) <=> (x ^ y == 0) - * (x & y) ^ (x & z) <=> x & (y ^ z) - * - * ((ip1 & mask) == (ip2 & mask)) <=> ((mask & (ip1 ^ ip2)) == 0) - */ - if (((mask.sin_addr.s_addr) & - (sin1.sin_addr.s_addr ^ sin2.sin_addr.s_addr)) != 0) - goto out; - - ret = 0; /* SUCCESS */ + if (mask_match (sin1.sin_addr.s_addr, + sin2.sin_addr.s_addr, + mask.sin_addr.s_addr)) { + ret = 0; /* SUCCESS */ + } out: GF_FREE (netaddr); return ret; -- cgit