2 * linux/net/sunrpc/svc.c
4 * High-level RPC service routines
6 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
9 #define __KERNEL_SYSCALLS__
10 #include <linux/linkage.h>
11 #include <linux/sched.h>
12 #include <linux/errno.h>
13 #include <linux/net.h>
15 #include <linux/unistd.h>
17 #include <linux/sunrpc/types.h>
18 #include <linux/sunrpc/xdr.h>
19 #include <linux/sunrpc/stats.h>
20 #include <linux/sunrpc/svcsock.h>
21 #include <linux/sunrpc/clnt.h>
23 #define RPCDBG_FACILITY RPCDBG_SVCDSP
24 #define RPC_PARANOIA 1
27 * Create an RPC service
30 svc_create(struct svc_program
*prog
, unsigned int bufsize
, unsigned int xdrsize
)
32 struct svc_serv
*serv
;
36 rpc_register_sysctl();
39 if (!(serv
= (struct svc_serv
*) kmalloc(sizeof(*serv
), GFP_KERNEL
)))
42 memset(serv
, 0, sizeof(*serv
));
43 serv
->sv_program
= prog
;
44 serv
->sv_nrthreads
= 1;
45 serv
->sv_stats
= prog
->pg_stats
;
46 serv
->sv_bufsz
= bufsize
? bufsize
: 4096;
47 serv
->sv_xdrsize
= xdrsize
;
48 spin_lock_init(&serv
->sv_lock
);
50 serv
->sv_name
= prog
->pg_name
;
52 /* Remove any stale portmap registrations */
53 svc_register(serv
, 0, 0);
59 * Destroy an RPC service
62 svc_destroy(struct svc_serv
*serv
)
64 struct svc_sock
*svsk
;
66 dprintk("RPC: svc_destroy(%s, %d)\n",
67 serv
->sv_program
->pg_name
,
70 if (serv
->sv_nrthreads
) {
71 if (--(serv
->sv_nrthreads
) != 0)
74 printk("svc_destroy: no threads for serv=%p!\n", serv
);
76 while ((svsk
= serv
->sv_allsocks
) != NULL
)
77 svc_delete_socket(svsk
);
79 /* Unregister service with the portmapper */
80 svc_register(serv
, 0, 0);
85 * Allocate an RPC server buffer
86 * Later versions may do nifty things by allocating multiple pages
87 * of memory directly and putting them into the bufp->iov.
90 svc_init_buffer(struct svc_buf
*bufp
, unsigned int size
)
92 if (!(bufp
->area
= (u32
*) kmalloc(size
, GFP_KERNEL
)))
94 bufp
->base
= bufp
->area
;
95 bufp
->buf
= bufp
->area
;
97 bufp
->buflen
= size
>> 2;
99 bufp
->iov
[0].iov_base
= bufp
->area
;
100 bufp
->iov
[0].iov_len
= size
;
107 * Release an RPC server buffer
110 svc_release_buffer(struct svc_buf
*bufp
)
117 * Create a server thread
120 svc_create_thread(svc_thread_fn func
, struct svc_serv
*serv
)
122 struct svc_rqst
*rqstp
;
125 rqstp
= kmalloc(sizeof(*rqstp
), GFP_KERNEL
);
129 memset(rqstp
, 0, sizeof(*rqstp
));
130 init_waitqueue_head(&rqstp
->rq_wait
);
132 if (!(rqstp
->rq_argp
= (u32
*) kmalloc(serv
->sv_xdrsize
, GFP_KERNEL
))
133 || !(rqstp
->rq_resp
= (u32
*) kmalloc(serv
->sv_xdrsize
, GFP_KERNEL
))
134 || !svc_init_buffer(&rqstp
->rq_defbuf
, serv
->sv_bufsz
))
137 serv
->sv_nrthreads
++;
138 rqstp
->rq_server
= serv
;
139 error
= kernel_thread((int (*)(void *)) func
, rqstp
, 0);
147 svc_exit_thread(rqstp
);
152 * Destroy an RPC server thread
155 svc_exit_thread(struct svc_rqst
*rqstp
)
157 struct svc_serv
*serv
= rqstp
->rq_server
;
159 svc_release_buffer(&rqstp
->rq_defbuf
);
161 kfree(rqstp
->rq_resp
);
163 kfree(rqstp
->rq_argp
);
166 /* Release the server */
172 * Register an RPC service with the local portmapper.
173 * To unregister a service, call this routine with
174 * proto and port == 0.
177 svc_register(struct svc_serv
*serv
, int proto
, unsigned short port
)
179 struct svc_program
*progp
;
181 int i
, error
= 0, dummy
;
183 progp
= serv
->sv_program
;
185 dprintk("RPC: svc_register(%s, %s, %d)\n",
186 progp
->pg_name
, proto
== IPPROTO_UDP
? "udp" : "tcp", port
);
189 current
->sigpending
= 0;
191 for (i
= 0; i
< progp
->pg_nvers
; i
++) {
192 if (progp
->pg_vers
[i
] == NULL
)
194 error
= rpc_register(progp
->pg_prog
, i
, proto
, port
, &dummy
);
197 if (port
&& !dummy
) {
204 spin_lock_irqsave(¤t
->sigmask_lock
, flags
);
205 recalc_sigpending(current
);
206 spin_unlock_irqrestore(¤t
->sigmask_lock
, flags
);
213 * Process the RPC request.
216 svc_process(struct svc_serv
*serv
, struct svc_rqst
*rqstp
)
218 struct svc_program
*progp
;
219 struct svc_version
*versp
= NULL
; /* compiler food */
220 struct svc_procedure
*procp
= NULL
;
221 struct svc_buf
* argp
= &rqstp
->rq_argbuf
;
222 struct svc_buf
* resp
= &rqstp
->rq_resbuf
;
225 u32 dir
, prog
, vers
, proc
,
228 rpc_stat
= rpc_success
;
234 dir
= ntohl(*bufp
++);
235 vers
= ntohl(*bufp
++);
237 /* First words of reply: */
238 svc_putlong(resp
, xdr_one
); /* REPLY */
239 svc_putlong(resp
, xdr_zero
); /* ACCEPT */
241 if (dir
!= 0) /* direction != CALL */
243 if (vers
!= 2) /* RPC version number */
246 rqstp
->rq_prog
= prog
= ntohl(*bufp
++); /* program number */
247 rqstp
->rq_vers
= vers
= ntohl(*bufp
++); /* version number */
248 rqstp
->rq_proc
= proc
= ntohl(*bufp
++); /* procedure number */
253 /* Used by nfsd to only allow the NULL procedure for amd. */
254 if (rqstp
->rq_auth
&& !rqstp
->rq_client
&& proc
) {
255 auth_stat
= rpc_autherr_badcred
;
260 * Decode auth data, and add verifier to reply buffer.
261 * We do this before anything else in order to get a decent
264 svc_authenticate(rqstp
, &rpc_stat
, &auth_stat
);
266 if (rpc_stat
!= rpc_success
)
269 if (auth_stat
!= rpc_auth_ok
)
272 progp
= serv
->sv_program
;
273 if (prog
!= progp
->pg_prog
)
276 if (vers
>= progp
->pg_nvers
||
277 !(versp
= progp
->pg_vers
[vers
]))
280 procp
= versp
->vs_proc
+ proc
;
281 if (proc
>= versp
->vs_nproc
|| !procp
->pc_func
)
283 rqstp
->rq_server
= serv
;
284 rqstp
->rq_procinfo
= procp
;
286 /* Syntactic check complete */
287 serv
->sv_stats
->rpccnt
++;
289 /* Build the reply header. */
291 svc_putlong(resp
, rpc_success
); /* RPC_SUCCESS */
293 /* Bump per-procedure stats counter */
296 /* Initialize storage for argp and resp */
297 memset(rqstp
->rq_argp
, 0, procp
->pc_argsize
);
298 memset(rqstp
->rq_resp
, 0, procp
->pc_ressize
);
300 /* Call the function that processes the request. */
301 if (!versp
->vs_dispatch
) {
302 /* Decode arguments */
303 xdr
= procp
->pc_decode
;
304 if (xdr
&& !xdr(rqstp
, rqstp
->rq_argbuf
.buf
, rqstp
->rq_argp
))
307 *statp
= procp
->pc_func(rqstp
, rqstp
->rq_argp
, rqstp
->rq_resp
);
310 if (*statp
== rpc_success
&& (xdr
= procp
->pc_encode
)
311 && !xdr(rqstp
, rqstp
->rq_resbuf
.buf
, rqstp
->rq_resp
)) {
312 dprintk("svc: failed to encode reply\n");
313 /* serv->sv_stats->rpcsystemerr++; */
314 *statp
= rpc_system_err
;
317 dprintk("svc: calling dispatcher\n");
318 if (!versp
->vs_dispatch(rqstp
, statp
))
322 /* Check RPC status result */
323 if (*statp
!= rpc_success
)
324 resp
->len
= statp
+ 1 - resp
->base
;
326 /* Release reply info */
327 if (procp
->pc_release
)
328 procp
->pc_release(rqstp
, NULL
, rqstp
->rq_resp
);
330 if (procp
->pc_encode
== NULL
)
333 return svc_send(rqstp
);
336 dprintk("svc: svc_process dropit\n");
342 printk("svc: short len %d, dropping request\n", argp
->len
);
344 goto dropit
; /* drop request */
348 printk("svc: bad direction %d, dropping request\n", dir
);
350 serv
->sv_stats
->rpcbadfmt
++;
351 goto dropit
; /* drop request */
354 serv
->sv_stats
->rpcbadfmt
++;
355 resp
->buf
[-1] = xdr_one
; /* REJECT */
356 svc_putlong(resp
, xdr_zero
); /* RPC_MISMATCH */
357 svc_putlong(resp
, xdr_two
); /* Only RPCv2 supported */
358 svc_putlong(resp
, xdr_two
);
362 dprintk("svc: authentication failed (%d)\n", ntohl(auth_stat
));
363 serv
->sv_stats
->rpcbadauth
++;
364 resp
->buf
[-1] = xdr_one
; /* REJECT */
365 svc_putlong(resp
, xdr_one
); /* AUTH_ERROR */
366 svc_putlong(resp
, auth_stat
); /* status */
371 printk("svc: unknown program %d (me %d)\n", prog
, progp
->pg_prog
);
373 serv
->sv_stats
->rpcbadfmt
++;
374 svc_putlong(resp
, rpc_prog_unavail
);
379 printk("svc: unknown version (%d)\n", vers
);
381 serv
->sv_stats
->rpcbadfmt
++;
382 svc_putlong(resp
, rpc_prog_mismatch
);
383 svc_putlong(resp
, htonl(progp
->pg_lovers
));
384 svc_putlong(resp
, htonl(progp
->pg_hivers
));
389 printk("svc: unknown procedure (%d)\n", proc
);
391 serv
->sv_stats
->rpcbadfmt
++;
392 svc_putlong(resp
, rpc_proc_unavail
);
397 printk("svc: failed to decode args\n");
399 serv
->sv_stats
->rpcbadfmt
++;
400 svc_putlong(resp
, rpc_garbage_args
);