summaryrefslogtreecommitdiffstats
path: root/rpc/rpc-lib
diff options
context:
space:
mode:
authorSantosh Kumar Pradhan <spradhan@redhat.com>2014-06-06 12:22:04 +0530
committerNiels de Vos <ndevos@redhat.com>2014-06-25 00:41:52 -0700
commitd3f0de90d0c5166e63f5764d2f21703fd29ce976 (patch)
treebdfc1b91f4d34ce7a29a8ad9774ad513d24a8730 /rpc/rpc-lib
parent5740fd404827a70e6318b6fff5773a9d9234d704 (diff)
downloadglusterfs-d3f0de90d0c5166e63f5764d2f21703fd29ce976.tar.gz
glusterfs-d3f0de90d0c5166e63f5764d2f21703fd29ce976.tar.xz
glusterfs-d3f0de90d0c5166e63f5764d2f21703fd29ce976.zip
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.<volname>.allow" and "NFS subdir auth code" to remove code duplication. Change-Id: I26b0def52c22cda35ca11766afca3df5fd4360bf BUG: 1102293 Signed-off-by: Santosh Kumar Pradhan <spradhan@redhat.com> Reviewed-on: http://review.gluster.org/8048 Reviewed-by: Rajesh Joseph <rjoseph@redhat.com> Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Niels de Vos <ndevos@redhat.com>
Diffstat (limited to 'rpc/rpc-lib')
-rw-r--r--rpc/rpc-lib/src/rpcsvc.c45
1 files changed, 18 insertions, 27 deletions
diff --git a/rpc/rpc-lib/src/rpcsvc.c b/rpc/rpc-lib/src/rpcsvc.c
index 5241a265ce..814af05f7b 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;