13 #include <linux/nfs_fs.h>
14 #include <linux/slab.h>
15 #include <linux/string.h>
23 #define NFSDBG_FACILITY NFSDBG_VFS
30 static inline char *nfs4_pathname_string(
const struct nfs4_pathname *
pathname,
39 n = pathname->ncomponents;
42 buflen -= component->
len + 1;
45 end -= component->
len;
60 static char *nfs_path_component(
const char *nfspath,
const char *
end)
64 if (*nfspath ==
'[') {
67 if (p !=
NULL && ++p < end && *p ==
':')
72 if (p !=
NULL && p < end)
87 char *path_component = nfs_path_component(path, limit);
89 return path_component;
98 static int nfs4_validate_fspath(
struct dentry *dentry,
99 const struct nfs4_fs_locations *locations,
100 char *
page,
char *page2)
104 path = nfs4_path(dentry, page,
PAGE_SIZE);
106 return PTR_ERR(path);
108 fs_path = nfs4_pathname_string(&locations->fs_path, page2,
PAGE_SIZE);
110 return PTR_ERR(fs_path);
113 dprintk(
"%s: path %s does not begin with fsroot %s\n",
114 __func__, path, fs_path);
121 static size_t nfs_parse_server_name(
char *
string,
size_t len,
127 ret =
rpc_pton(net,
string, len, sa, salen);
138 struct gss_api_mech *mech;
139 struct xdr_netobj oid;
141 rpc_authflavor_t pseudoflavor = RPC_AUTH_UNIX;
143 for (i = 0; i < flavors->num_flavors; i++) {
144 struct nfs4_secinfo_flavor *flavor;
145 flavor = &flavors->flavors[
i];
147 if (flavor->flavor == RPC_AUTH_NULL || flavor->flavor == RPC_AUTH_UNIX) {
148 pseudoflavor = flavor->flavor;
150 }
else if (flavor->flavor == RPC_AUTH_GSS) {
151 oid.len = flavor->gss.sec_oid4.len;
152 oid.data = flavor->gss.sec_oid4.data;
165 static rpc_authflavor_t nfs4_negotiate_security(
struct inode *
inode,
struct qstr *
name)
168 struct nfs4_secinfo_flavors *flavors;
169 rpc_authflavor_t flavor;
196 rpc_authflavor_t flavor;
198 flavor = nfs4_negotiate_security(inode, name);
200 return ERR_PTR((
int)flavor);
206 char *page,
char *page2,
207 const struct nfs4_fs_location *
location)
212 unsigned int maxbuflen;
215 mnt_path = nfs4_pathname_string(&location->rootpath, page2,
PAGE_SIZE);
216 if (IS_ERR(mnt_path))
217 return ERR_CAST(mnt_path);
219 maxbuflen = mnt_path - 1 - page2;
225 for (s = 0; s < location->nservers; s++) {
228 if (buf->
len <= 0 || buf->
len >= maxbuflen)
235 mountdata->
addr, addr_bufsize,
236 NFS_SB(mountdata->
sb));
243 page2[buf->
len] =
'\0';
264 static struct vfsmount *nfs_follow_referral(
struct dentry *dentry,
265 const struct nfs4_fs_locations *locations)
271 .authflavor = NFS_SB(dentry->
d_sb)->client->cl_auth->au_flavor,
276 if (locations ==
NULL || locations->nlocations <= 0)
279 dprintk(
"%s: referral at %s/%s\n", __func__,
291 error = nfs4_validate_fspath(dentry, locations, page, page2);
293 mnt = ERR_PTR(error);
297 for (loc = 0; loc < locations->nlocations; loc++) {
298 const struct nfs4_fs_location *location = &locations->locations[
loc];
300 if (location ==
NULL || location->nservers <= 0 ||
301 location->rootpath.ncomponents == 0)
304 mnt = try_location(&mountdata, page, page2, location);
312 dprintk(
"%s: done\n", __func__);
325 struct nfs4_fs_locations *fs_locations =
NULL;
330 dprintk(
"%s: enter\n", __func__);
337 if (fs_locations ==
NULL)
344 dprintk(
"%s: getting locations for %s/%s\n",
350 fs_locations->nlocations <= 0 ||
351 fs_locations->fs_path.ncomponents <= 0)
354 mnt = nfs_follow_referral(dentry, fs_locations);
359 dprintk(
"%s: done\n", __func__);
374 return ERR_CAST(client);
377 mnt = nfs_do_refmount(client, dentry);