1/* 2 * linux/net/sunrpc/svc.c 3 * 4 * High-level RPC service routines 5 * 6 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> 7 */ 8 9#define __KERNEL_SYSCALLS__ 10#include <linux/linkage.h> 11#include <linux/sched.h> 12#include <linux/errno.h> 13#include <linux/net.h> 14#include <linux/in.h> 15#include <linux/unistd.h> 16 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> 22 23#define RPCDBG_FACILITY RPCDBG_SVCDSP 24#define RPC_PARANOIA 1 25 26/* 27 * Create an RPC service 28 */ 29struct svc_serv * 30svc_create(struct svc_program *prog, unsigned int bufsize, unsigned int xdrsize) 31{ 32 struct svc_serv *serv; 33 34 if (!(serv = (struct svc_serv *) kmalloc(sizeof(*serv), GFP_KERNEL))) 35 return NULL; 36 37 memset(serv, 0, sizeof(*serv)); 38 serv->sv_program = prog; 39 serv->sv_nrthreads = 1; 40 serv->sv_stats = prog->pg_stats; 41 serv->sv_bufsz = bufsize? bufsize : 4096; 42 serv->sv_xdrsize = xdrsize; 43 INIT_LIST_HEAD(&serv->sv_threads); 44 INIT_LIST_HEAD(&serv->sv_sockets); 45 INIT_LIST_HEAD(&serv->sv_tempsocks); 46 INIT_LIST_HEAD(&serv->sv_permsocks); 47 spin_lock_init(&serv->sv_lock); 48 49 serv->sv_name = prog->pg_name; 50 51 /* Remove any stale portmap registrations */ 52 svc_register(serv, 0, 0); 53 54 return serv; 55} 56 57/* 58 * Destroy an RPC service 59 */ 60void 61svc_destroy(struct svc_serv *serv) 62{ 63 struct svc_sock *svsk; 64 65 dprintk("RPC: svc_destroy(%s, %d)\n", 66 serv->sv_program->pg_name, 67 serv->sv_nrthreads); 68 69 if (serv->sv_nrthreads) { 70 if (--(serv->sv_nrthreads) != 0) { 71 svc_sock_update_bufs(serv); 72 return; 73 } 74 } else 75 printk("svc_destroy: no threads for serv=%p!\n", serv); 76 77 while (!list_empty(&serv->sv_tempsocks)) { 78 svsk = list_entry(serv->sv_tempsocks.next, 79 struct svc_sock, 80 sk_list); 81 svc_delete_socket(svsk); 82 } 83 while (!list_empty(&serv->sv_permsocks)) { 84 svsk = list_entry(serv->sv_permsocks.next, 85 struct svc_sock, 86 sk_list); 87 svc_delete_socket(svsk); 88 } 89 90 /* Unregister service with the portmapper */ 91 svc_register(serv, 0, 0); 92 kfree(serv); 93} 94 95/* 96 * Allocate an RPC server buffer 97 * Later versions may do nifty things by allocating multiple pages 98 * of memory directly and putting them into the bufp->iov. 99 */ 100int 101svc_init_buffer(struct svc_buf *bufp, unsigned int size) 102{ 103 if (!(bufp->area = (u32 *) kmalloc(size, GFP_KERNEL))) 104 return 0; 105 bufp->base = bufp->area; 106 bufp->buf = bufp->area; 107 bufp->len = 0; 108 bufp->buflen = size >> 2; 109 110 bufp->iov[0].iov_base = bufp->area; 111 bufp->iov[0].iov_len = size; 112 bufp->nriov = 1; 113 114 return 1; 115} 116 117/* 118 * Release an RPC server buffer 119 */ 120void 121svc_release_buffer(struct svc_buf *bufp) 122{ 123 kfree(bufp->area); 124 bufp->area = 0; 125} 126 127/* 128 * Create a server thread 129 */ 130int 131svc_create_thread(svc_thread_fn func, struct svc_serv *serv) 132{ 133 struct svc_rqst *rqstp; 134 int error = -ENOMEM; 135 136 rqstp = kmalloc(sizeof(*rqstp), GFP_KERNEL); 137 if (!rqstp) 138 goto out; 139 140 memset(rqstp, 0, sizeof(*rqstp)); 141 init_waitqueue_head(&rqstp->rq_wait); 142 143 if (!(rqstp->rq_argp = (u32 *) kmalloc(serv->sv_xdrsize, GFP_KERNEL)) 144 || !(rqstp->rq_resp = (u32 *) kmalloc(serv->sv_xdrsize, GFP_KERNEL)) 145 || !svc_init_buffer(&rqstp->rq_defbuf, serv->sv_bufsz)) 146 goto out_thread; 147 148 serv->sv_nrthreads++; 149 rqstp->rq_server = serv; 150 error = kernel_thread((int (*)(void *)) func, rqstp, 0); 151 if (error < 0) 152 goto out_thread; 153 svc_sock_update_bufs(serv); 154 error = 0; 155out: 156 return error; 157 158out_thread: 159 svc_exit_thread(rqstp); 160 goto out; 161} 162 163/* 164 * Destroy an RPC server thread 165 */ 166void 167svc_exit_thread(struct svc_rqst *rqstp) 168{ 169 struct svc_serv *serv = rqstp->rq_server; 170 171 svc_release_buffer(&rqstp->rq_defbuf); 172 if (rqstp->rq_resp) 173 kfree(rqstp->rq_resp); 174 if (rqstp->rq_argp) 175 kfree(rqstp->rq_argp); 176 kfree(rqstp); 177 178 /* Release the server */ 179 if (serv) 180 svc_destroy(serv); 181} 182 183/* 184 * Register an RPC service with the local portmapper. 185 * To unregister a service, call this routine with 186 * proto and port == 0. 187 */ 188int 189svc_register(struct svc_serv *serv, int proto, unsigned short port) 190{ 191 struct svc_program *progp; 192 unsigned long flags; 193 int i, error = 0, dummy; 194 195 progp = serv->sv_program; 196 197 dprintk("RPC: svc_register(%s, %s, %d)\n", 198 progp->pg_name, proto == IPPROTO_UDP? "udp" : "tcp", port); 199 200 if (!port) 201 current->sigpending = 0; 202 203 for (i = 0; i < progp->pg_nvers; i++) { 204 if (progp->pg_vers[i] == NULL) 205 continue; 206 error = rpc_register(progp->pg_prog, i, proto, port, &dummy); 207 if (error < 0) 208 break; 209 if (port && !dummy) { 210 error = -EACCES; 211 break; 212 } 213 } 214 215 if (!port) { 216 spin_lock_irqsave(¤t->sigmask_lock, flags); 217 recalc_sigpending(current); 218 spin_unlock_irqrestore(¤t->sigmask_lock, flags); 219 } 220 221 return error; 222} 223 224/* 225 * Process the RPC request. 226 */ 227int 228svc_process(struct svc_serv *serv, struct svc_rqst *rqstp) 229{ 230 struct svc_program *progp; 231 struct svc_version *versp = NULL; /* compiler food */ 232 struct svc_procedure *procp = NULL; 233 struct svc_buf * argp = &rqstp->rq_argbuf; 234 struct svc_buf * resp = &rqstp->rq_resbuf; 235 kxdrproc_t xdr; 236 u32 *bufp, *statp; 237 u32 dir, prog, vers, proc, 238 auth_stat, rpc_stat; 239 240 rpc_stat = rpc_success; 241 bufp = argp->buf; 242 243 if (argp->len < 5) 244 goto err_short_len; 245 246 dir = ntohl(*bufp++); 247 vers = ntohl(*bufp++); 248 249 /* First words of reply: */ 250 svc_putlong(resp, xdr_one); /* REPLY */ 251 svc_putlong(resp, xdr_zero); /* ACCEPT */ 252 253 if (dir != 0) /* direction != CALL */ 254 goto err_bad_dir; 255 if (vers != 2) /* RPC version number */ 256 goto err_bad_rpc; 257 258 rqstp->rq_prog = prog = ntohl(*bufp++); /* program number */ 259 rqstp->rq_vers = vers = ntohl(*bufp++); /* version number */ 260 rqstp->rq_proc = proc = ntohl(*bufp++); /* procedure number */ 261 262 argp->buf += 5; 263 argp->len -= 5; 264 265 /* Used by nfsd to only allow the NULL procedure for amd. */ 266 if (rqstp->rq_auth && !rqstp->rq_client && proc) { 267 auth_stat = rpc_autherr_badcred; 268 goto err_bad_auth; 269 } 270 271 /* 272 * Decode auth data, and add verifier to reply buffer. 273 * We do this before anything else in order to get a decent 274 * auth verifier. 275 */ 276 svc_authenticate(rqstp, &rpc_stat, &auth_stat); 277 278 if (rpc_stat != rpc_success) 279 goto err_garbage; 280 281 if (auth_stat != rpc_auth_ok) 282 goto err_bad_auth; 283 284 progp = serv->sv_program; 285 if (prog != progp->pg_prog) 286 goto err_bad_prog; 287 288 if (vers >= progp->pg_nvers || 289 !(versp = progp->pg_vers[vers])) 290 goto err_bad_vers; 291 292 procp = versp->vs_proc + proc; 293 if (proc >= versp->vs_nproc || !procp->pc_func) 294 goto err_bad_proc; 295 rqstp->rq_server = serv; 296 rqstp->rq_procinfo = procp; 297 298 /* Syntactic check complete */ 299 serv->sv_stats->rpccnt++; 300 301 /* Build the reply header. */ 302 statp = resp->buf; 303 svc_putlong(resp, rpc_success); /* RPC_SUCCESS */ 304 305 /* Bump per-procedure stats counter */ 306 procp->pc_count++; 307 308 /* Initialize storage for argp and resp */ 309 memset(rqstp->rq_argp, 0, procp->pc_argsize); 310 memset(rqstp->rq_resp, 0, procp->pc_ressize); 311 312 /* un-reserve some of the out-queue now that we have a 313 * better idea of reply size 314 */ 315 if (procp->pc_xdrressize) 316 svc_reserve(rqstp, procp->pc_xdrressize<<2); 317 318 /* Call the function that processes the request. */ 319 if (!versp->vs_dispatch) { 320 /* Decode arguments */ 321 xdr = procp->pc_decode; 322 if (xdr && !xdr(rqstp, rqstp->rq_argbuf.buf, rqstp->rq_argp)) 323 goto err_garbage; 324 325 *statp = procp->pc_func(rqstp, rqstp->rq_argp, rqstp->rq_resp); 326 327 /* Encode reply */ 328 if (*statp == rpc_success && (xdr = procp->pc_encode) 329 && !xdr(rqstp, rqstp->rq_resbuf.buf, rqstp->rq_resp)) { 330 dprintk("svc: failed to encode reply\n"); 331 /* serv->sv_stats->rpcsystemerr++; */ 332 *statp = rpc_system_err; 333 } 334 } else { 335 dprintk("svc: calling dispatcher\n"); 336 if (!versp->vs_dispatch(rqstp, statp)) 337 goto dropit; 338 } 339 340 /* Check RPC status result */ 341 if (*statp != rpc_success) 342 resp->len = statp + 1 - resp->base; 343 344 /* Release reply info */ 345 if (procp->pc_release) 346 procp->pc_release(rqstp, NULL, rqstp->rq_resp); 347 348 if (procp->pc_encode == NULL) 349 goto dropit; 350sendit: 351 return svc_send(rqstp); 352 353dropit: 354 dprintk("svc: svc_process dropit\n"); 355 svc_drop(rqstp); 356 return 0; 357 358err_short_len: 359#ifdef RPC_PARANOIA 360 printk("svc: short len %d, dropping request\n", argp->len); 361#endif 362 goto dropit; /* drop request */ 363 364err_bad_dir: 365#ifdef RPC_PARANOIA 366 printk("svc: bad direction %d, dropping request\n", dir); 367#endif 368 serv->sv_stats->rpcbadfmt++; 369 goto dropit; /* drop request */ 370 371err_bad_rpc: 372 serv->sv_stats->rpcbadfmt++; 373 resp->buf[-1] = xdr_one; /* REJECT */ 374 svc_putlong(resp, xdr_zero); /* RPC_MISMATCH */ 375 svc_putlong(resp, xdr_two); /* Only RPCv2 supported */ 376 svc_putlong(resp, xdr_two); 377 goto sendit; 378 379err_bad_auth: 380 dprintk("svc: authentication failed (%d)\n", ntohl(auth_stat)); 381 serv->sv_stats->rpcbadauth++; 382 resp->buf[-1] = xdr_one; /* REJECT */ 383 svc_putlong(resp, xdr_one); /* AUTH_ERROR */ 384 svc_putlong(resp, auth_stat); /* status */ 385 goto sendit; 386 387err_bad_prog: 388#ifdef RPC_PARANOIA 389 if (prog != 100227 || progp->pg_prog != 100003) 390 printk("svc: unknown program %d (me %d)\n", prog, progp->pg_prog); 391 /* else it is just a Solaris client seeing if ACLs are supported */ 392#endif 393 serv->sv_stats->rpcbadfmt++; 394 svc_putlong(resp, rpc_prog_unavail); 395 goto sendit; 396 397err_bad_vers: 398#ifdef RPC_PARANOIA 399 printk("svc: unknown version (%d)\n", vers); 400#endif 401 serv->sv_stats->rpcbadfmt++; 402 svc_putlong(resp, rpc_prog_mismatch); 403 svc_putlong(resp, htonl(progp->pg_lovers)); 404 svc_putlong(resp, htonl(progp->pg_hivers)); 405 goto sendit; 406 407err_bad_proc: 408#ifdef RPC_PARANOIA 409 printk("svc: unknown procedure (%d)\n", proc); 410#endif 411 serv->sv_stats->rpcbadfmt++; 412 svc_putlong(resp, rpc_proc_unavail); 413 goto sendit; 414 415err_garbage: 416#ifdef RPC_PARANOIA 417 printk("svc: failed to decode args\n"); 418#endif 419 serv->sv_stats->rpcbadfmt++; 420 svc_putlong(resp, rpc_garbage_args); 421 goto sendit; 422} 423