diff options
Diffstat (limited to 'xlators/nfs/server/src')
| -rw-r--r-- | xlators/nfs/server/src/mount3.c | 60 | ||||
| -rw-r--r-- | xlators/nfs/server/src/mount3.h | 7 | ||||
| -rw-r--r-- | xlators/nfs/server/src/nfs-common.c | 25 | ||||
| -rw-r--r-- | xlators/nfs/server/src/nfs3.c | 69 | 
4 files changed, 99 insertions, 62 deletions
diff --git a/xlators/nfs/server/src/mount3.c b/xlators/nfs/server/src/mount3.c index 12f52e4f5d0..2eaaea5c639 100644 --- a/xlators/nfs/server/src/mount3.c +++ b/xlators/nfs/server/src/mount3.c @@ -945,7 +945,7 @@ err:   * we need to strip out the volume name first.   */  char * -__volume_subdir (char *dirpath, char **volname) +mnt3_get_volume_subdir (char *dirpath, char **volname)  {          char    *subdir = NULL;          int     volname_len = 0; @@ -1024,10 +1024,6 @@ mnt3_resolve_subdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                           struct iatt *buf, dict_t *xattr,                           struct iatt *postparent); -int -mnt3_parse_dir_exports (rpcsvc_request_t *req, struct mount3_state *ms, -                        char *subdir); -  int32_t  mnt3_readlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                     int32_t op_ret, int32_t op_errno, const char *path, @@ -1310,7 +1306,8 @@ mnt3_readlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this,          /* After the resolving the symlink , parsing should be done           * for the populated mount path           */ -        ret = mnt3_parse_dir_exports (mres->req, mres->mstate, real_loc); +        ret = mnt3_parse_dir_exports (mres->req, mres->mstate, real_loc, +                                      _gf_true);          if (ret) {                  gf_msg (GF_MNT, GF_LOG_ERROR, 0, NFS_MSG_RESOLVE_ERROR, @@ -1518,7 +1515,8 @@ mnt3_verify_auth (struct sockaddr_in *client_addr, struct mnt3_export *export)  int  mnt3_resolve_subdir (rpcsvc_request_t *req, struct mount3_state *ms, -                     struct mnt3_export *exp, char *subdir) +                     struct mnt3_export *exp, char *subdir, +                     gf_boolean_t send_reply)  {          mnt3_resolve_t        *mres = NULL;          int                   ret = -EFAULT; @@ -1541,6 +1539,10 @@ mnt3_resolve_subdir (rpcsvc_request_t *req, struct mount3_state *ms,                  }          } +        /* no reply is needed (WebNFS permissions checking), just return */ +        if (!send_reply) +                return 0; /* no error, mnt3_verify_auth() allowed it */ +          mres = GF_CALLOC (1, sizeof (mnt3_resolve_t), gf_nfs_mt_mnt3_resolve);          if (!mres) {                  gf_msg (GF_MNT, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY, @@ -1585,11 +1587,11 @@ mnt3_resolve_export_subdir (rpcsvc_request_t *req, struct mount3_state *ms,          if ((!req) || (!ms) || (!exp))                  return ret; -        volume_subdir = __volume_subdir (exp->expname, NULL); +        volume_subdir = mnt3_get_volume_subdir (exp->expname, NULL);          if (!volume_subdir)                  goto err; -        ret = mnt3_resolve_subdir (req, ms, exp, volume_subdir); +        ret = mnt3_resolve_subdir (req, ms, exp, volume_subdir, _gf_true);          if (ret < 0) {                  gf_msg (GF_MNT, GF_LOG_ERROR, ret, NFS_MSG_RESOLVE_SUBDIR_FAIL,                          "Failed to resolve export dir: %s", exp->expname); @@ -1686,7 +1688,7 @@ err:          return ret;  } -static int +int  mnt3_check_client_net_tcp (rpcsvc_request_t *req, char *volname)  {          rpcsvc_t                *svc = NULL; @@ -1772,25 +1774,41 @@ err:  int  mnt3_parse_dir_exports (rpcsvc_request_t *req, struct mount3_state *ms, -                        char *subdir) +                        char *path, gf_boolean_t send_reply)  {          char                    volname[1024] = {0, };          struct mnt3_export      *exp = NULL;          char                    *volname_ptr = NULL; +        char                    *subdir = NULL;          int                     ret = -ENOENT;          struct nfs_state        *nfs = NULL; -        if ((!ms) || (!subdir)) +        if ((!ms) || (!path))                  return -1;          volname_ptr = volname; -        subdir = __volume_subdir (subdir, &volname_ptr); -        if (!subdir) +        subdir = mnt3_get_volume_subdir (path, &volname_ptr); +        if (!subdir) { +                gf_msg_trace (GF_MNT, 0, "Could not parse volname/subdir from " +                              "%s", path);                  goto err; +        } -        exp = mnt3_mntpath_to_export (ms, volname, _gf_false); -        if (!exp) -                goto err; +        /* first try to match the full export/subdir */ +        exp = mnt3_mntpath_to_export (ms, path, _gf_false); +        if (!exp) { +                gf_msg_trace (GF_MNT, 0, "Could not find exact matching export " +                              "for path=%s", path); +                /* if no exact match is found, look for a fallback */ +                exp = mnt3_mntpath_to_export (ms, volname, _gf_true); +                if (!exp) { +                        gf_msg_trace (GF_MNT, 0, "Could not find export for " +                                      "volume %s", volname); +                        goto err; +                } +        } +        gf_msg_trace (GF_MNT, 0, "volume %s and export %s will be used for " +                      "path %s", exp->vol->name, exp->expname, path);          nfs = (struct nfs_state *)ms->nfsx->private;          if (!nfs) @@ -1809,7 +1827,7 @@ mnt3_parse_dir_exports (rpcsvc_request_t *req, struct mount3_state *ms,                  goto err;          } -        ret = mnt3_resolve_subdir (req, ms, exp, subdir); +        ret = mnt3_resolve_subdir (req, ms, exp, subdir, send_reply);          if (ret < 0) {                  gf_msg (GF_MNT, GF_LOG_ERROR, ret, NFS_MSG_RESOLVE_SUBDIR_FAIL,                          "Failed to resolve export dir: %s", subdir); @@ -1852,7 +1870,7 @@ mnt3_find_export (rpcsvc_request_t *req, char *path, struct mnt3_export **e)                  goto err;          } -        ret = mnt3_parse_dir_exports (req, ms, path); +        ret = mnt3_parse_dir_exports (req, ms, path, _gf_true);  err:          return ret; @@ -2939,7 +2957,7 @@ nfs3_rootfh (struct svc_req *req, xlator_t *nfsx,           * 3. If a subdir is exported using nfs.export-dir,           *      then the mount type would be MNT3_EXPTYPE_DIR,           *      so make sure to find the proper path to be -         *      resolved using __volume_subdir() +         *      resolved using mnt3_get_volume_subdir()           * 3. Make sure subdir export is allowed.           */          ms = __mnt3udp_get_mstate(nfsx); @@ -2962,7 +2980,7 @@ nfs3_rootfh (struct svc_req *req, xlator_t *nfsx,                          return NULL;                  } -                path = __volume_subdir (path, &volptr); +                path = mnt3_get_volume_subdir (path, &volptr);                  if (exp == NULL)                          exp = mnt3_mntpath_to_export (ms, volname , _gf_false);          } diff --git a/xlators/nfs/server/src/mount3.h b/xlators/nfs/server/src/mount3.h index ce01a6c543d..8868aec787a 100644 --- a/xlators/nfs/server/src/mount3.h +++ b/xlators/nfs/server/src/mount3.h @@ -178,4 +178,11 @@ struct mount3_resolve_state {  typedef struct mount3_resolve_state mnt3_resolve_t; +int +mnt3_parse_dir_exports (rpcsvc_request_t *req, struct mount3_state *ms, +                        char *subdir, gf_boolean_t send_reply); + +char* +mnt3_get_volume_subdir (char *path, char **volname); +  #endif diff --git a/xlators/nfs/server/src/nfs-common.c b/xlators/nfs/server/src/nfs-common.c index 526918872d7..2f742d44366 100644 --- a/xlators/nfs/server/src/nfs-common.c +++ b/xlators/nfs/server/src/nfs-common.c @@ -73,8 +73,8 @@ nfs_xlator_to_xlid (xlator_list_t *cl, xlator_t *xl)  xlator_t *  nfs_mntpath_to_xlator (xlator_list_t *cl, char *path)  { -        char            *volname  = NULL; -        char            *volptr   = NULL; +        char            *volname  = NULL; /* volume name only */ +        char            *volptr   = NULL; /* ptr to original volname */          size_t           pathlen  = -1;          xlator_t        *targetxl = NULL;          int              i        = 0; @@ -82,14 +82,16 @@ nfs_mntpath_to_xlator (xlator_list_t *cl, char *path)          if ((!cl) || (!path))                  return NULL; -        volname = strdupa (path); -        pathlen = strlen (volname);          gf_msg_trace (GF_NFS, 0, "Subvolume search: %s", path); + +        volname = volptr = gf_strdup (path); +        if (!volname) +                return NULL; +          if (volname[0] == '/') -                volptr = &volname[1]; -        else -                volptr = &volname[0]; +                volname++; +        pathlen = strlen (volname);          for (i = 0; i < pathlen; i++) {                  if (volname[i] == '/') {                          volname[i] = '\0'; @@ -98,10 +100,10 @@ nfs_mntpath_to_xlator (xlator_list_t *cl, char *path)          }          while (cl) { -                gf_msg_trace (GF_NFS, 0, "Volptr: %s and cl->xlator->name: %s", -                              volptr, cl->xlator->name); +                gf_msg_trace (GF_NFS, 0, "Volname: %s and cl->xlator->name: %s", +                              volname, cl->xlator->name); -                if (strcmp (volptr, cl->xlator->name) == 0) { +                if (strcmp (volname, cl->xlator->name) == 0) {                          targetxl = cl->xlator;                          break;                  } @@ -109,8 +111,9 @@ nfs_mntpath_to_xlator (xlator_list_t *cl, char *path)                  cl = cl->next;          } -        return targetxl; +        GF_FREE (volptr); +        return targetxl;  } diff --git a/xlators/nfs/server/src/nfs3.c b/xlators/nfs/server/src/nfs3.c index 7da412d0a35..836428f8111 100644 --- a/xlators/nfs/server/src/nfs3.c +++ b/xlators/nfs/server/src/nfs3.c @@ -349,44 +349,51 @@ out:  } -static enum nfsstat3 -nfs3_funge_webnfs_zerolen_fh (struct nfs3_state *nfs3st, struct nfs3_fh *fhd, -                               char *name) +static int +nfs3_funge_webnfs_zerolen_fh (rpcsvc_request_t *req, struct nfs3_state *nfs3st, +                              struct nfs3_fh *fhd, char *name)  { -        xlator_t        *fungexl  = NULL; -        glfs_t          *fs       = NULL; -        loc_t            loc      = { 0, }; -        enum nfsstat3    nfsstat  = NFS3ERR_SERVERFAULT; -        int              ret      = -1; -        size_t           namelen  = -1; +        xlator_t           *fungexl           = NULL; +        struct nfs_state   *nfs               = NULL; +        glfs_t             *fs                = NULL; +        loc_t               loc               = { 0, }; +        int                 ret               = -1; +        char               *subdir            = NULL; +        char                volname[NAME_MAX] = { 0, };          fungexl = nfs_mntpath_to_xlator (nfs3st->exportslist, name);          if (!fungexl) { -                nfsstat = NFS3ERR_NOENT; +                gf_msg_trace (GF_NFS3, 0, "failed to find xlator for volume"); +                ret = -ENOENT; +                goto out; +        } +        /* fungexl is valid, set for nfs3_request_xlator_deviceid() */ +        rpcsvc_request_set_private (req, fungexl); + +        /* Permission checks are done through mnt3_parse_dir_exports(). The +         * "nfs.export-dir" option gets checked as well. */ +        nfs = nfs_state (nfs3st->nfsx); +        ret = mnt3_parse_dir_exports (req, nfs->mstate, name, _gf_false); +        if (ret) { +                gf_msg_trace (GF_NFS3, -ret, "mounting not possible");                  goto out;          }          /* glfs_resolve_at copied from UDP MNT support */          fs = glfs_new_from_ctx (fungexl->ctx);          if (!fs) { -                nfsstat = NFS3ERR_NOENT; +                gf_msg_trace (GF_NFS3, 0, "failed to create glfs instance"); +                ret = -ENOENT;                  goto out;          } -        /* strip volname/ from 'name' */ -        namelen = strlen(name); -        while (namelen != 0) { -                name++; -                if (name[0] == '/') { -                        break; -                } -                namelen--; -        } -        gf_msg_debug (GF_NFS, 0, "NAME :%s ", name); +        /* split name "volname/sub/dir/s" into pieces */ +        subdir = mnt3_get_volume_subdir (name, (char**) &volname); -        ret = glfs_resolve_at (fs, fungexl, NULL, name, &loc, NULL, 1, 0); +        ret = glfs_resolve_at (fs, fungexl, NULL, subdir, &loc, NULL, 1, 0);          if (ret != 0) { -                nfsstat = NFS3ERR_NOENT; +                gf_msg_trace (GF_NFS3, 0, "failed to resolve %s", subdir); +                ret = -ENOENT;                  goto out;          } @@ -399,17 +406,17 @@ nfs3_funge_webnfs_zerolen_fh (struct nfs3_state *nfs3st, struct nfs3_fh *fhd,                                                          fungexl);          else {                  if (__nfs3_get_volume_id (nfs3st, fungexl, fhd->exportid) < 0) { -                        nfsstat = NFS3ERR_STALE; +                        ret = -ESTALE;                          goto out;                  }          } -        nfsstat = NFS3_OK; +        ret = 0;  out:          if (fs)                  glfs_free_from_ctx (fs); -        return nfsstat; +        return ret;  } @@ -513,8 +520,10 @@ nfs3_solaris_zerolen_fh (struct nfs3_fh *fh, int fhlen)          if (nfs3_fh_validate (fh))                  return 0; -        if (fhlen == 0) +        if (fhlen == 0) { +                gf_msg_trace (GF_NFS3, 0, "received WebNFS request");                  return 1; +        }          return 0;  } @@ -1593,8 +1602,8 @@ nfs3_lookup (rpcsvc_request_t *req, struct nfs3_fh *fh, int fhlen, char *name)                                  name);          nfs3_validate_nfs3_state (req, nfs3, stat, nfs3err, ret);          if (nfs3_solaris_zerolen_fh (fh, fhlen)) { -                stat = nfs3_funge_webnfs_zerolen_fh (nfs3, fh, name); -                if (stat != NFS3_OK) +                ret = nfs3_funge_webnfs_zerolen_fh (req, nfs3, fh, name); +                if (ret < 0)                          goto nfs3err;                  /* this fh means we're doing a mount, name is no more useful */ @@ -1614,11 +1623,11 @@ nfs3_lookup (rpcsvc_request_t *req, struct nfs3_fh *fh, int fhlen, char *name)                  gf_msg (GF_NFS, GF_LOG_ERROR, -ret,                          NFS_MSG_HARD_RESOLVE_FAIL,                          "failed to start hard resolve"); -                stat = nfs3_errno_to_nfsstat3 (-ret);          }  nfs3err:          if (ret < 0) { +                stat = nfs3_errno_to_nfsstat3 (-ret);                  nfs3_log_common_res (rpcsvc_request_xid (req),                                       NFS3_LOOKUP, stat, -ret,                                       cs ? cs->resolvedloc.path : NULL);  | 
