summaryrefslogtreecommitdiffstats
path: root/xlators/nfs/server/src/mount3.c
diff options
context:
space:
mode:
authorBipin Kunal <bkunal@redhat.com>2016-06-10 17:03:35 +0530
committerNiels de Vos <ndevos@redhat.com>2016-07-03 04:15:35 -0700
commit6a1559ff8057e5c2a992a990cfb630932e6928d2 (patch)
treed5711061b7af7667f5078ab8f586662cd786067c /xlators/nfs/server/src/mount3.c
parente6d45abffb861570f9591811c77f0d3d8316f637 (diff)
nfs: build exportlist with multiple groupnodes
The EXPORT procedure of the MOUNT protocol does not correctly create structures for the 'groupnodes' in the reply. Each 'groupnode' should be a single entry in the 'nfs.rpc-auth-allow' volume option. Because the value is handled as a single string, the encoding of the groupnode->gr_name fails when the value of the volume option is longer than 255 characters. In the error case, encoding the EXPORTS reply fails, and the waiting 'showmount' command will not receive a reply and times out. Splitting the allowed entries and creating a groupnode for each one prevents the too long ->gr_name. This is following the structures for the EXPORTS reply in the MOUNT protocol more correctly as well. Note that the contents of ->gr_name is expected to be server dependent. This is backport of below mainline fix - http://review.gluster.org/#/c/14667/ Change-Id: Ibbabad581cc9aa00feb80fbbc851a1b10b28383d BUG: 1343290 Signed-off-by: Niels de Vos <ndevos@redhat.com> Signed-off-by: Bipin Kunal <bkunal@redhat.com> Reviewed-on: http://review.gluster.org/14698 Smoke: Gluster Build System <jenkins@build.gluster.org> NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org> CentOS-regression: Gluster Build System <jenkins@build.gluster.org>
Diffstat (limited to 'xlators/nfs/server/src/mount3.c')
-rw-r--r--xlators/nfs/server/src/mount3.c84
1 files changed, 66 insertions, 18 deletions
diff --git a/xlators/nfs/server/src/mount3.c b/xlators/nfs/server/src/mount3.c
index c10232e20e0..bf4ba0f25c7 100644
--- a/xlators/nfs/server/src/mount3.c
+++ b/xlators/nfs/server/src/mount3.c
@@ -2632,27 +2632,75 @@ mnt3_xlchildren_to_exports (rpcsvc_t *svc, struct mount3_state *ms)
}
strcpy (elist->ex_dir, ent->expname);
- addrstr = rpcsvc_volume_allowed (svc->options,
- ent->vol->name);
- elist->ex_groups = GF_CALLOC (1, sizeof (struct groupnode),
- gf_nfs_mt_groupnode);
- if (!elist->ex_groups) {
- gf_msg (GF_MNT, GF_LOG_ERROR, ENOMEM,
- NFS_MSG_NO_MEMORY, "Memory allocation failed");
- goto free_list;
- }
- /*This check has to be done after checking
- * elist->ex_groups allocation check to avoid resource leak;
- */
- if (addrstr)
- addrstr = gf_strdup (addrstr);
- else
+ addrstr = rpcsvc_volume_allowed (svc->options, ent->vol->name);
+ if (addrstr) {
+ /* create a groupnode per allowed client */
+ char *pos = NULL;
+ char *addr = NULL;
+ char *addrs = NULL;
+ struct groupnode *group = NULL;
+ struct groupnode *prev_group = NULL;
+
+ /* strtok_r() modifies the string, dup it */
+ addrs = gf_strdup (addrstr);
+ if (!addrs)
+ goto free_list;
+
+ while (1) {
+ /* only pass addrs on the 1st call */
+ addr = strtok_r (group ? NULL : addrs, ",",
+ &pos);
+ if (addr == NULL)
+ /* no mode clients */
+ break;
+
+ group = GF_CALLOC (1, sizeof (struct groupnode),
+ gf_nfs_mt_groupnode);
+ if (!group) {
+ gf_msg (GF_MNT, GF_LOG_ERROR, ENOMEM,
+ NFS_MSG_NO_MEMORY, "Memory "
+ "allocation failed");
+ GF_FREE (addrs);
+ goto free_list;
+ }
+
+ group->gr_name = gf_strdup (addr);
+ if (!group->gr_name) {
+ gf_msg (GF_MNT, GF_LOG_ERROR, ENOMEM,
+ NFS_MSG_NO_MEMORY, "Memory "
+ "allocation failed");
+ GF_FREE (group);
+ GF_FREE (addrs);
+ goto free_list;
+ }
+
+ /* chain the groups together */
+ if (!elist->ex_groups)
+ elist->ex_groups = group;
+ else
+ prev_group->gr_next = group;
+ prev_group = group;
+ }
+
+ GF_FREE (addrs);
+ } else {
+ elist->ex_groups = GF_CALLOC (1,
+ sizeof (struct groupnode),
+ gf_nfs_mt_groupnode);
+ if (!elist->ex_groups) {
+ gf_msg (GF_MNT, GF_LOG_ERROR, ENOMEM,
+ NFS_MSG_NO_MEMORY, "Memory allocation "
+ "failed");
+ goto free_list;
+ }
+
addrstr = gf_strdup ("No Access");
+ if (!addrstr)
+ goto free_list;
- if (!addrstr) {
- goto free_list;
+ elist->ex_groups->gr_name = addrstr;
}
- elist->ex_groups->gr_name = addrstr;
+
if (prev) {
prev->ex_next = elist;
prev = elist;