summaryrefslogtreecommitdiffstats
path: root/xlators/nfs/server/src/mount3.c
diff options
context:
space:
mode:
authorBipin Kunal <bkunal@redhat.com>2016-06-07 18:30:16 +0530
committerNiels de Vos <ndevos@redhat.com>2016-06-09 11:40:25 -0700
commit3bd4b1529817d4ce40c2b9654044e6230cbf7233 (patch)
treeb095f2ed5e5f14992cec6f977d9ca39d672f88e7 /xlators/nfs/server/src/mount3.c
parentab88bad8fe40bd9a9106b02857abfdc51a3284cd (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. Change-Id: Ibbabad581cc9aa00feb80fbbc851a1b10b28383d BUG: 1343286 Signed-off-by: Niels de Vos <ndevos@redhat.com> Reviewed-on: http://review.gluster.org/14667 Smoke: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: bipin kunal <kunalbipin@gmail.com> NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org> Reviewed-by: jiffin tony Thottan <jthottan@redhat.com> CentOS-regression: Gluster Build System <jenkins@build.gluster.com>
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 cb8b9a1af2f..580f92af4b7 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;