diff options
author | Bipin Kunal <bkunal@redhat.com> | 2016-06-07 18:30:16 +0530 |
---|---|---|
committer | Niels de Vos <ndevos@redhat.com> | 2016-06-09 11:40:25 -0700 |
commit | 3bd4b1529817d4ce40c2b9654044e6230cbf7233 (patch) | |
tree | b095f2ed5e5f14992cec6f977d9ca39d672f88e7 /xlators/nfs | |
parent | ab88bad8fe40bd9a9106b02857abfdc51a3284cd (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')
-rw-r--r-- | xlators/nfs/server/src/mount3.c | 84 |
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; |