summaryrefslogtreecommitdiffstats
path: root/rpc/rpc-lib
diff options
context:
space:
mode:
authorNiels de Vos <ndevos@redhat.com>2014-06-29 16:30:30 +0200
committerNiels de Vos <ndevos@redhat.com>2014-07-02 00:53:18 -0700
commitcacc1311626aa8b2dfe9f937cf1b14bb534a8937 (patch)
tree63369e3f37d058444f2ce93640684af0f407ecae /rpc/rpc-lib
parentcf5a5ab1a81bb61bb66982757ccd301d015ac16e (diff)
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. Cherry-picked from commit d3f0de90d0c5166e63f5764d2f21703fd29ce976: > 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> Change-Id: Ie92a8ac602bec2cd77268acb7b23ad8ba3c52f5f BUG: 1112980 Signed-off-by: Niels de Vos <ndevos@redhat.com> Reviewed-on: http://review.gluster.org/8198 Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Santosh Pradhan <spradhan@redhat.com>
Diffstat (limited to 'rpc/rpc-lib')
-rw-r--r--rpc/rpc-lib/src/rpcsvc.c66
1 files changed, 66 insertions, 0 deletions
diff --git a/rpc/rpc-lib/src/rpcsvc.c b/rpc/rpc-lib/src/rpcsvc.c
index 9374ee7328f..a751330a7c9 100644
--- a/rpc/rpc-lib/src/rpcsvc.c
+++ b/rpc/rpc-lib/src/rpcsvc.c
@@ -60,6 +60,9 @@ int
rpcsvc_notify (rpc_transport_t *trans, void *mydata,
rpc_transport_event_t event, void *data, ...);
+static int
+rpcsvc_match_subnet_v4 (const char *addrtok, const char *ipaddr);
+
rpcsvc_notify_wrapper_t *
rpcsvc_notify_wrapper_alloc (void)
{
@@ -2236,6 +2239,13 @@ rpcsvc_transport_peer_check_search (dict_t *options, char *pattern,
goto err;
}
+ /* Compare IPv4 subnetwork, TODO: IPv6 subnet support */
+ if (strchr (addrtok, '/')) {
+ ret = rpcsvc_match_subnet_v4 (addrtok, ip);
+ if (ret == 0)
+ goto err;
+ }
+
addrtok = strtok_r (NULL, ",", &svptr);
}
@@ -2516,6 +2526,62 @@ out:
return addrstr;
}
+/*
+ * 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.
+ *
+ * NB: Validation of subnetwork address pattern is not required
+ * as it's already being done at the time of CLI SET.
+ */
+static int
+rpcsvc_match_subnet_v4 (const char *addrtok, const char *ipaddr)
+{
+ char *slash = NULL;
+ char *netaddr = NULL;
+ int ret = -1;
+ uint32_t prefixlen = 0;
+ uint32_t shift = 0;
+ struct sockaddr_in sin1 = {0, };
+ struct sockaddr_in sin2 = {0, };
+ struct sockaddr_in mask = {0, };
+
+ /* Copy the input */
+ netaddr = gf_strdup (addrtok);
+ if (netaddr == NULL) /* ENOMEM */
+ goto out;
+
+ /* Find the network socket addr of target */
+ if (inet_pton (AF_INET, ipaddr, &sin1.sin_addr) == 0)
+ goto out;
+
+ /* Find the network socket addr of subnet pattern */
+ slash = strchr (netaddr, '/');
+ *slash = '\0';
+ if (inet_pton (AF_INET, netaddr, &sin2.sin_addr) == 0)
+ goto out;
+
+ /*
+ * 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 = (uint32_t) atoi (slash + 1);
+ shift = IPv4_ADDR_SIZE - prefixlen;
+ mask.sin_addr.s_addr = htonl ((uint32_t)~0 << shift);
+
+ 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;
+}
+
rpcsvc_actor_t gluster_dump_actors[] = {
[GF_DUMP_NULL] = {"NULL", GF_DUMP_NULL, NULL, NULL, 0, DRC_NA},