]>
Commit | Line | Data |
---|---|---|
1da177e4 | 1 | /* |
19207231 | 2 | * In-kernel MOUNT protocol client |
1da177e4 LT |
3 | * |
4 | * Copyright (C) 1997, Olaf Kirch <[email protected]> | |
5 | */ | |
6 | ||
7 | #include <linux/types.h> | |
8 | #include <linux/socket.h> | |
9 | #include <linux/kernel.h> | |
10 | #include <linux/errno.h> | |
11 | #include <linux/uio.h> | |
12 | #include <linux/net.h> | |
13 | #include <linux/in.h> | |
14 | #include <linux/sunrpc/clnt.h> | |
1da177e4 LT |
15 | #include <linux/sunrpc/sched.h> |
16 | #include <linux/nfs_fs.h> | |
17 | ||
18 | #ifdef RPC_DEBUG | |
3ea97309 | 19 | # define NFSDBG_FACILITY NFSDBG_MOUNT |
1da177e4 LT |
20 | #endif |
21 | ||
1da177e4 LT |
22 | static struct rpc_program mnt_program; |
23 | ||
24 | struct mnt_fhstatus { | |
19207231 CL |
25 | u32 status; |
26 | struct nfs_fh *fh; | |
1da177e4 LT |
27 | }; |
28 | ||
3ea97309 CL |
29 | /** |
30 | * nfs_mount - Obtain an NFS file handle for the given host and path | |
31 | * @addr: pointer to server's address | |
32 | * @len: size of server's address | |
33 | * @hostname: name of server host, or NULL | |
34 | * @path: pointer to string containing export path to mount | |
35 | * @version: mount version to use for this request | |
36 | * @protocol: transport protocol to use for thie request | |
37 | * @fh: pointer to location to place returned file handle | |
38 | * | |
39 | * Uses default timeout parameters specified by underlying transport. | |
1da177e4 | 40 | */ |
3ea97309 CL |
41 | int nfs_mount(struct sockaddr *addr, size_t len, char *hostname, char *path, |
42 | int version, int protocol, struct nfs_fh *fh) | |
1da177e4 | 43 | { |
1da177e4 LT |
44 | struct mnt_fhstatus result = { |
45 | .fh = fh | |
46 | }; | |
dead28da CL |
47 | struct rpc_message msg = { |
48 | .rpc_argp = path, | |
49 | .rpc_resp = &result, | |
50 | }; | |
3ea97309 CL |
51 | struct rpc_create_args args = { |
52 | .protocol = protocol, | |
53 | .address = addr, | |
54 | .addrsize = len, | |
55 | .servername = hostname, | |
56 | .program = &mnt_program, | |
57 | .version = version, | |
58 | .authflavor = RPC_AUTH_UNIX, | |
150030b7 | 59 | .flags = 0, |
3ea97309 CL |
60 | }; |
61 | struct rpc_clnt *mnt_clnt; | |
1da177e4 | 62 | int status; |
1da177e4 | 63 | |
3ea97309 CL |
64 | dprintk("NFS: sending MNT request for %s:%s\n", |
65 | (hostname ? hostname : "server"), path); | |
1da177e4 | 66 | |
3ea97309 | 67 | mnt_clnt = rpc_create(&args); |
1da177e4 | 68 | if (IS_ERR(mnt_clnt)) |
013a8c1a | 69 | goto out_clnt_err; |
1da177e4 | 70 | |
dead28da CL |
71 | if (version == NFS_MNT3_VERSION) |
72 | msg.rpc_proc = &mnt_clnt->cl_procinfo[MOUNTPROC3_MNT]; | |
73 | else | |
74 | msg.rpc_proc = &mnt_clnt->cl_procinfo[MNTPROC_MNT]; | |
75 | ||
76 | status = rpc_call_sync(mnt_clnt, &msg, 0); | |
90c5755f | 77 | rpc_shutdown_client(mnt_clnt); |
013a8c1a CL |
78 | |
79 | if (status < 0) | |
80 | goto out_call_err; | |
81 | if (result.status != 0) | |
82 | goto out_mnt_err; | |
83 | ||
84 | dprintk("NFS: MNT request succeeded\n"); | |
85 | status = 0; | |
86 | ||
87 | out: | |
88 | return status; | |
89 | ||
90 | out_clnt_err: | |
91 | status = PTR_ERR(mnt_clnt); | |
92 | dprintk("NFS: failed to create RPC client, status=%d\n", status); | |
93 | goto out; | |
94 | ||
95 | out_call_err: | |
96 | dprintk("NFS: failed to start MNT request, status=%d\n", status); | |
97 | goto out; | |
98 | ||
99 | out_mnt_err: | |
100 | dprintk("NFS: MNT server returned result %d\n", result.status); | |
101 | status = -EACCES; | |
102 | goto out; | |
1da177e4 LT |
103 | } |
104 | ||
1da177e4 LT |
105 | /* |
106 | * XDR encode/decode functions for MOUNT | |
107 | */ | |
19207231 CL |
108 | static int xdr_encode_dirpath(struct rpc_rqst *req, __be32 *p, |
109 | const char *path) | |
1da177e4 LT |
110 | { |
111 | p = xdr_encode_string(p, path); | |
112 | ||
113 | req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); | |
114 | return 0; | |
115 | } | |
116 | ||
19207231 CL |
117 | static int xdr_decode_fhstatus(struct rpc_rqst *req, __be32 *p, |
118 | struct mnt_fhstatus *res) | |
1da177e4 LT |
119 | { |
120 | struct nfs_fh *fh = res->fh; | |
121 | ||
122 | if ((res->status = ntohl(*p++)) == 0) { | |
123 | fh->size = NFS2_FHSIZE; | |
124 | memcpy(fh->data, p, NFS2_FHSIZE); | |
125 | } | |
126 | return 0; | |
127 | } | |
128 | ||
19207231 CL |
129 | static int xdr_decode_fhstatus3(struct rpc_rqst *req, __be32 *p, |
130 | struct mnt_fhstatus *res) | |
1da177e4 LT |
131 | { |
132 | struct nfs_fh *fh = res->fh; | |
b7e24457 | 133 | unsigned size; |
1da177e4 LT |
134 | |
135 | if ((res->status = ntohl(*p++)) == 0) { | |
b7e24457 TM |
136 | size = ntohl(*p++); |
137 | if (size <= NFS3_FHSIZE && size != 0) { | |
1da177e4 LT |
138 | fh->size = size; |
139 | memcpy(fh->data, p, size); | |
140 | } else | |
141 | res->status = -EBADHANDLE; | |
142 | } | |
143 | return 0; | |
144 | } | |
145 | ||
146 | #define MNT_dirpath_sz (1 + 256) | |
147 | #define MNT_fhstatus_sz (1 + 8) | |
2bea90d4 | 148 | #define MNT_fhstatus3_sz (1 + 16) |
1da177e4 | 149 | |
19207231 CL |
150 | static struct rpc_procinfo mnt_procedures[] = { |
151 | [MNTPROC_MNT] = { | |
152 | .p_proc = MNTPROC_MNT, | |
153 | .p_encode = (kxdrproc_t) xdr_encode_dirpath, | |
154 | .p_decode = (kxdrproc_t) xdr_decode_fhstatus, | |
155 | .p_arglen = MNT_dirpath_sz, | |
156 | .p_replen = MNT_fhstatus_sz, | |
157 | .p_statidx = MNTPROC_MNT, | |
158 | .p_name = "MOUNT", | |
1da177e4 LT |
159 | }, |
160 | }; | |
161 | ||
162 | static struct rpc_procinfo mnt3_procedures[] = { | |
19207231 CL |
163 | [MOUNTPROC3_MNT] = { |
164 | .p_proc = MOUNTPROC3_MNT, | |
165 | .p_encode = (kxdrproc_t) xdr_encode_dirpath, | |
166 | .p_decode = (kxdrproc_t) xdr_decode_fhstatus3, | |
167 | .p_arglen = MNT_dirpath_sz, | |
168 | .p_replen = MNT_fhstatus3_sz, | |
169 | .p_statidx = MOUNTPROC3_MNT, | |
170 | .p_name = "MOUNT", | |
1da177e4 LT |
171 | }, |
172 | }; | |
173 | ||
174 | ||
19207231 CL |
175 | static struct rpc_version mnt_version1 = { |
176 | .number = 1, | |
177 | .nrprocs = 2, | |
178 | .procs = mnt_procedures, | |
1da177e4 LT |
179 | }; |
180 | ||
19207231 CL |
181 | static struct rpc_version mnt_version3 = { |
182 | .number = 3, | |
183 | .nrprocs = 2, | |
184 | .procs = mnt3_procedures, | |
1da177e4 LT |
185 | }; |
186 | ||
19207231 | 187 | static struct rpc_version *mnt_version[] = { |
1da177e4 LT |
188 | NULL, |
189 | &mnt_version1, | |
190 | NULL, | |
191 | &mnt_version3, | |
192 | }; | |
193 | ||
19207231 | 194 | static struct rpc_stat mnt_stats; |
1da177e4 | 195 | |
19207231 | 196 | static struct rpc_program mnt_program = { |
1da177e4 LT |
197 | .name = "mount", |
198 | .number = NFS_MNT_PROGRAM, | |
e8c96f8c | 199 | .nrvers = ARRAY_SIZE(mnt_version), |
1da177e4 LT |
200 | .version = mnt_version, |
201 | .stats = &mnt_stats, | |
202 | }; |