SUNRPC: Make RPC portmapper use per-transport storage
[safe/jmp/linux-2.6] / net / sunrpc / pmap_clnt.c
1 /*
2  * linux/net/sunrpc/pmap.c
3  *
4  * Portmapper client.
5  *
6  * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
7  */
8
9 #include <linux/types.h>
10 #include <linux/socket.h>
11 #include <linux/kernel.h>
12 #include <linux/errno.h>
13 #include <linux/uio.h>
14 #include <linux/in.h>
15 #include <linux/sunrpc/clnt.h>
16 #include <linux/sunrpc/xprt.h>
17 #include <linux/sunrpc/sched.h>
18
19 #ifdef RPC_DEBUG
20 # define RPCDBG_FACILITY        RPCDBG_PMAP
21 #endif
22
23 #define PMAP_SET                1
24 #define PMAP_UNSET              2
25 #define PMAP_GETPORT            3
26
27 struct portmap_args {
28         u32                     pm_prog;
29         u32                     pm_vers;
30         u32                     pm_prot;
31         unsigned short          pm_port;
32         struct rpc_task *       pm_task;
33 };
34
35 static struct rpc_procinfo      pmap_procedures[];
36 static struct rpc_clnt *        pmap_create(char *, struct sockaddr_in *, int, int);
37 static void                     pmap_getport_done(struct rpc_task *, void *);
38 static struct rpc_program       pmap_program;
39
40 static void pmap_getport_prepare(struct rpc_task *task, void *calldata)
41 {
42         struct portmap_args *map = calldata;
43         struct rpc_message msg = {
44                 .rpc_proc       = &pmap_procedures[PMAP_GETPORT],
45                 .rpc_argp       = map,
46                 .rpc_resp       = &map->pm_port,
47         };
48
49         rpc_call_setup(task, &msg, 0);
50 }
51
52 static inline struct portmap_args *pmap_map_alloc(void)
53 {
54         return kmalloc(sizeof(struct portmap_args), GFP_NOFS);
55 }
56
57 static inline void pmap_map_free(struct portmap_args *map)
58 {
59         kfree(map);
60 }
61
62 static void pmap_map_release(void *data)
63 {
64         pmap_map_free(data);
65 }
66
67 static const struct rpc_call_ops pmap_getport_ops = {
68         .rpc_call_prepare       = pmap_getport_prepare,
69         .rpc_call_done          = pmap_getport_done,
70         .rpc_release            = pmap_map_release,
71 };
72
73 static inline void pmap_wake_portmap_waiters(struct rpc_xprt *xprt)
74 {
75         xprt_clear_binding(xprt);
76         rpc_wake_up(&xprt->binding);
77 }
78
79 /*
80  * Obtain the port for a given RPC service on a given host. This one can
81  * be called for an ongoing RPC request.
82  */
83 void
84 rpc_getport(struct rpc_task *task, struct rpc_clnt *clnt)
85 {
86         struct rpc_xprt *xprt = task->tk_xprt;
87         struct sockaddr_in *sap = &xprt->addr;
88         struct portmap_args *map;
89         struct rpc_clnt *pmap_clnt;
90         struct rpc_task *child;
91
92         dprintk("RPC: %4d rpc_getport(%s, %u, %u, %d)\n",
93                         task->tk_pid, clnt->cl_server,
94                         clnt->cl_prog, clnt->cl_vers, xprt->prot);
95
96         /* Autobind on cloned rpc clients is discouraged */
97         BUG_ON(clnt->cl_parent != clnt);
98
99         if (xprt_test_and_set_binding(xprt)) {
100                 task->tk_status = -EACCES;      /* tell caller to check again */
101                 rpc_sleep_on(&xprt->binding, task, NULL, NULL);
102                 return;
103         }
104
105         /* Someone else may have bound if we slept */
106         if (xprt_bound(xprt)) {
107                 task->tk_status = 0;
108                 goto bailout_nofree;
109         }
110
111         map = pmap_map_alloc();
112         if (!map) {
113                 task->tk_status = -ENOMEM;
114                 goto bailout_nofree;
115         }
116         map->pm_prog = clnt->cl_prog;
117         map->pm_vers = clnt->cl_vers;
118         map->pm_prot = xprt->prot;
119         map->pm_port = 0;
120         map->pm_task = task;
121
122         pmap_clnt = pmap_create(clnt->cl_server, sap, map->pm_prot, 0);
123         if (IS_ERR(pmap_clnt)) {
124                 task->tk_status = PTR_ERR(pmap_clnt);
125                 goto bailout;
126         }
127
128         child = rpc_run_task(pmap_clnt, RPC_TASK_ASYNC, &pmap_getport_ops, map);
129         if (IS_ERR(child)) {
130                 task->tk_status = -EIO;
131                 goto bailout;
132         }
133         rpc_release_task(child);
134
135         rpc_sleep_on(&xprt->binding, task, NULL, NULL);
136
137         task->tk_xprt->stat.bind_count++;
138         return;
139
140 bailout:
141         pmap_map_free(map);
142 bailout_nofree:
143         pmap_wake_portmap_waiters(xprt);
144 }
145
146 #ifdef CONFIG_ROOT_NFS
147 int
148 rpc_getport_external(struct sockaddr_in *sin, __u32 prog, __u32 vers, int prot)
149 {
150         struct portmap_args map = {
151                 .pm_prog        = prog,
152                 .pm_vers        = vers,
153                 .pm_prot        = prot,
154                 .pm_port        = 0
155         };
156         struct rpc_message msg = {
157                 .rpc_proc       = &pmap_procedures[PMAP_GETPORT],
158                 .rpc_argp       = &map,
159                 .rpc_resp       = &map.pm_port,
160         };
161         struct rpc_clnt *pmap_clnt;
162         char            hostname[32];
163         int             status;
164
165         dprintk("RPC:      rpc_getport_external(%u.%u.%u.%u, %d, %d, %d)\n",
166                         NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot);
167
168         sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(sin->sin_addr.s_addr));
169         pmap_clnt = pmap_create(hostname, sin, prot, 0);
170         if (IS_ERR(pmap_clnt))
171                 return PTR_ERR(pmap_clnt);
172
173         /* Setup the call info struct */
174         status = rpc_call_sync(pmap_clnt, &msg, 0);
175
176         if (status >= 0) {
177                 if (map.pm_port != 0)
178                         return map.pm_port;
179                 status = -EACCES;
180         }
181         return status;
182 }
183 #endif
184
185 static void
186 pmap_getport_done(struct rpc_task *child, void *data)
187 {
188         struct portmap_args *map = data;
189         struct rpc_task *task = map->pm_task;
190         struct rpc_xprt *xprt = task->tk_xprt;
191         int status = child->tk_status;
192
193         if (status < 0) {
194                 /* Portmapper not available */
195                 xprt->ops->set_port(xprt, 0);
196                 task->tk_status = status;
197         } else if (map->pm_port == 0) {
198                 /* Requested RPC service wasn't registered */
199                 xprt->ops->set_port(xprt, 0);
200                 task->tk_status = -EACCES;
201         } else {
202                 /* Succeeded */
203                 xprt->ops->set_port(xprt, map->pm_port);
204                 xprt_set_bound(xprt);
205                 task->tk_status = 0;
206         }
207
208         dprintk("RPC: %4d pmap_getport_done(status %d, port %u)\n",
209                         child->tk_pid, child->tk_status, map->pm_port);
210
211         pmap_wake_portmap_waiters(xprt);
212 }
213
214 /*
215  * Set or unset a port registration with the local portmapper.
216  * port == 0 means unregister, port != 0 means register.
217  */
218 int
219 rpc_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay)
220 {
221         struct sockaddr_in      sin = {
222                 .sin_family     = AF_INET,
223                 .sin_addr.s_addr = htonl(INADDR_LOOPBACK),
224         };
225         struct portmap_args     map = {
226                 .pm_prog        = prog,
227                 .pm_vers        = vers,
228                 .pm_prot        = prot,
229                 .pm_port        = port,
230         };
231         struct rpc_message msg = {
232                 .rpc_proc       = &pmap_procedures[port ? PMAP_SET : PMAP_UNSET],
233                 .rpc_argp       = &map,
234                 .rpc_resp       = okay,
235         };
236         struct rpc_clnt         *pmap_clnt;
237         int error = 0;
238
239         dprintk("RPC: registering (%d, %d, %d, %d) with portmapper.\n",
240                         prog, vers, prot, port);
241
242         pmap_clnt = pmap_create("localhost", &sin, IPPROTO_UDP, 1);
243         if (IS_ERR(pmap_clnt)) {
244                 error = PTR_ERR(pmap_clnt);
245                 dprintk("RPC: couldn't create pmap client. Error = %d\n", error);
246                 return error;
247         }
248
249         error = rpc_call_sync(pmap_clnt, &msg, 0);
250
251         if (error < 0) {
252                 printk(KERN_WARNING
253                         "RPC: failed to contact portmap (errno %d).\n",
254                         error);
255         }
256         dprintk("RPC: registration status %d/%d\n", error, *okay);
257
258         /* Client deleted automatically because cl_oneshot == 1 */
259         return error;
260 }
261
262 static struct rpc_clnt *
263 pmap_create(char *hostname, struct sockaddr_in *srvaddr, int proto, int privileged)
264 {
265         struct rpc_xprt *xprt;
266         struct rpc_clnt *clnt;
267
268         /* printk("pmap: create xprt\n"); */
269         xprt = xprt_create_proto(proto, srvaddr, NULL);
270         if (IS_ERR(xprt))
271                 return (struct rpc_clnt *)xprt;
272         xprt->ops->set_port(xprt, RPC_PMAP_PORT);
273         xprt_set_bound(xprt);
274         if (!privileged)
275                 xprt->resvport = 0;
276
277         /* printk("pmap: create clnt\n"); */
278         clnt = rpc_new_client(xprt, hostname,
279                                 &pmap_program, RPC_PMAP_VERSION,
280                                 RPC_AUTH_UNIX);
281         if (!IS_ERR(clnt)) {
282                 clnt->cl_softrtry = 1;
283                 clnt->cl_oneshot  = 1;
284         }
285         return clnt;
286 }
287
288 /*
289  * XDR encode/decode functions for PMAP
290  */
291 static int
292 xdr_encode_mapping(struct rpc_rqst *req, u32 *p, struct portmap_args *map)
293 {
294         dprintk("RPC: xdr_encode_mapping(%d, %d, %d, %d)\n",
295                 map->pm_prog, map->pm_vers, map->pm_prot, map->pm_port);
296         *p++ = htonl(map->pm_prog);
297         *p++ = htonl(map->pm_vers);
298         *p++ = htonl(map->pm_prot);
299         *p++ = htonl(map->pm_port);
300
301         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
302         return 0;
303 }
304
305 static int
306 xdr_decode_port(struct rpc_rqst *req, u32 *p, unsigned short *portp)
307 {
308         *portp = (unsigned short) ntohl(*p++);
309         return 0;
310 }
311
312 static int
313 xdr_decode_bool(struct rpc_rqst *req, u32 *p, unsigned int *boolp)
314 {
315         *boolp = (unsigned int) ntohl(*p++);
316         return 0;
317 }
318
319 static struct rpc_procinfo      pmap_procedures[] = {
320 [PMAP_SET] = {
321           .p_proc               = PMAP_SET,
322           .p_encode             = (kxdrproc_t) xdr_encode_mapping,      
323           .p_decode             = (kxdrproc_t) xdr_decode_bool,
324           .p_bufsiz             = 4,
325           .p_count              = 1,
326           .p_statidx            = PMAP_SET,
327           .p_name               = "SET",
328         },
329 [PMAP_UNSET] = {
330           .p_proc               = PMAP_UNSET,
331           .p_encode             = (kxdrproc_t) xdr_encode_mapping,      
332           .p_decode             = (kxdrproc_t) xdr_decode_bool,
333           .p_bufsiz             = 4,
334           .p_count              = 1,
335           .p_statidx            = PMAP_UNSET,
336           .p_name               = "UNSET",
337         },
338 [PMAP_GETPORT] = {
339           .p_proc               = PMAP_GETPORT,
340           .p_encode             = (kxdrproc_t) xdr_encode_mapping,
341           .p_decode             = (kxdrproc_t) xdr_decode_port,
342           .p_bufsiz             = 4,
343           .p_count              = 1,
344           .p_statidx            = PMAP_GETPORT,
345           .p_name               = "GETPORT",
346         },
347 };
348
349 static struct rpc_version       pmap_version2 = {
350         .number         = 2,
351         .nrprocs        = 4,
352         .procs          = pmap_procedures
353 };
354
355 static struct rpc_version *     pmap_version[] = {
356         NULL,
357         NULL,
358         &pmap_version2
359 };
360
361 static struct rpc_stat          pmap_stats;
362
363 static struct rpc_program       pmap_program = {
364         .name           = "portmap",
365         .number         = RPC_PMAP_PROGRAM,
366         .nrvers         = ARRAY_SIZE(pmap_version),
367         .version        = pmap_version,
368         .stats          = &pmap_stats,
369 };