1 /* 2 * linux/fs/lockd/xdr4.c 3 * 4 * XDR support for lockd and the lock client. 5 * 6 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> 7 * Copyright (C) 1999, Trond Myklebust <trond.myklebust@fys.uio.no> 8 */ 9 10 #include <linux/types.h> 11 #include <linux/sched.h> 12 #include <linux/utsname.h> 13 #include <linux/nfs.h> 14 15 #include <linux/sunrpc/xdr.h> 16 #include <linux/sunrpc/clnt.h> 17 #include <linux/sunrpc/svc.h> 18 #include <linux/sunrpc/stats.h> 19 #include <linux/lockd/lockd.h> 20 #include <linux/lockd/sm_inter.h> 21 22 #define NLMDBG_FACILITY NLMDBG_XDR 23 24 static inline loff_t 25 s64_to_loff_t(__s64 offset) 26 { 27 return (loff_t)offset; 28 } 29 30 31 static inline s64 32 loff_t_to_s64(loff_t offset) 33 { 34 s64 res; 35 if (offset > NLM4_OFFSET_MAX) 36 res = NLM4_OFFSET_MAX; 37 else if (offset < -NLM4_OFFSET_MAX) 38 res = -NLM4_OFFSET_MAX; 39 else 40 res = offset; 41 return res; 42 } 43 44 /* 45 * XDR functions for basic NLM types 46 */ 47 static __be32 * 48 nlm4_decode_cookie(__be32 *p, struct nlm_cookie *c) 49 { 50 unsigned int len; 51 52 len = ntohl(*p++); 53 54 if(len==0) 55 { 56 c->len=4; 57 memset(c->data, 0, 4); /* hockeypux brain damage */ 58 } 59 else if(len<=NLM_MAXCOOKIELEN) 60 { 61 c->len=len; 62 memcpy(c->data, p, len); 63 p+=XDR_QUADLEN(len); 64 } 65 else 66 { 67 dprintk("lockd: bad cookie size %d (only cookies under " 68 "%d bytes are supported.)\n", 69 len, NLM_MAXCOOKIELEN); 70 return NULL; 71 } 72 return p; 73 } 74 75 static __be32 * 76 nlm4_encode_cookie(__be32 *p, struct nlm_cookie *c) 77 { 78 *p++ = htonl(c->len); 79 memcpy(p, c->data, c->len); 80 p+=XDR_QUADLEN(c->len); 81 return p; 82 } 83 84 static __be32 * 85 nlm4_decode_fh(__be32 *p, struct nfs_fh *f) 86 { 87 memset(f->data, 0, sizeof(f->data)); 88 f->size = ntohl(*p++); 89 if (f->size > NFS_MAXFHSIZE) { 90 dprintk("lockd: bad fhandle size %d (should be <=%d)\n", 91 f->size, NFS_MAXFHSIZE); 92 return NULL; 93 } 94 memcpy(f->data, p, f->size); 95 return p + XDR_QUADLEN(f->size); 96 } 97 98 static __be32 * 99 nlm4_encode_fh(__be32 *p, struct nfs_fh *f) 100 { 101 *p++ = htonl(f->size); 102 if (f->size) p[XDR_QUADLEN(f->size)-1] = 0; /* don't leak anything */ 103 memcpy(p, f->data, f->size); 104 return p + XDR_QUADLEN(f->size); 105 } 106 107 /* 108 * Encode and decode owner handle 109 */ 110 static __be32 * 111 nlm4_decode_oh(__be32 *p, struct xdr_netobj *oh) 112 { 113 return xdr_decode_netobj(p, oh); 114 } 115 116 static __be32 * 117 nlm4_encode_oh(__be32 *p, struct xdr_netobj *oh) 118 { 119 return xdr_encode_netobj(p, oh); 120 } 121 122 static __be32 * 123 nlm4_decode_lock(__be32 *p, struct nlm_lock *lock) 124 { 125 struct file_lock *fl = &lock->fl; 126 __u64 len, start; 127 __s64 end; 128 129 if (!(p = xdr_decode_string_inplace(p, &lock->caller, 130 &lock->len, NLM_MAXSTRLEN)) 131 || !(p = nlm4_decode_fh(p, &lock->fh)) 132 || !(p = nlm4_decode_oh(p, &lock->oh))) 133 return NULL; 134 lock->svid = ntohl(*p++); 135 136 locks_init_lock(fl); 137 fl->fl_owner = current->files; 138 fl->fl_pid = (pid_t)lock->svid; 139 fl->fl_flags = FL_POSIX; 140 fl->fl_type = F_RDLCK; /* as good as anything else */ 141 p = xdr_decode_hyper(p, &start); 142 p = xdr_decode_hyper(p, &len); 143 end = start + len - 1; 144 145 fl->fl_start = s64_to_loff_t(start); 146 147 if (len == 0 || end < 0) 148 fl->fl_end = OFFSET_MAX; 149 else 150 fl->fl_end = s64_to_loff_t(end); 151 return p; 152 } 153 154 /* 155 * Encode a lock as part of an NLM call 156 */ 157 static __be32 * 158 nlm4_encode_lock(__be32 *p, struct nlm_lock *lock) 159 { 160 struct file_lock *fl = &lock->fl; 161 __s64 start, len; 162 163 if (!(p = xdr_encode_string(p, lock->caller)) 164 || !(p = nlm4_encode_fh(p, &lock->fh)) 165 || !(p = nlm4_encode_oh(p, &lock->oh))) 166 return NULL; 167 168 if (fl->fl_start > NLM4_OFFSET_MAX 169 || (fl->fl_end > NLM4_OFFSET_MAX && fl->fl_end != OFFSET_MAX)) 170 return NULL; 171 172 *p++ = htonl(lock->svid); 173 174 start = loff_t_to_s64(fl->fl_start); 175 if (fl->fl_end == OFFSET_MAX) 176 len = 0; 177 else 178 len = loff_t_to_s64(fl->fl_end - fl->fl_start + 1); 179 180 p = xdr_encode_hyper(p, start); 181 p = xdr_encode_hyper(p, len); 182 183 return p; 184 } 185 186 /* 187 * Encode result of a TEST/TEST_MSG call 188 */ 189 static __be32 * 190 nlm4_encode_testres(__be32 *p, struct nlm_res *resp) 191 { 192 s64 start, len; 193 194 dprintk("xdr: before encode_testres (p %p resp %p)\n", p, resp); 195 if (!(p = nlm4_encode_cookie(p, &resp->cookie))) 196 return NULL; 197 *p++ = resp->status; 198 199 if (resp->status == nlm_lck_denied) { 200 struct file_lock *fl = &resp->lock.fl; 201 202 *p++ = (fl->fl_type == F_RDLCK)? xdr_zero : xdr_one; 203 *p++ = htonl(resp->lock.svid); 204 205 /* Encode owner handle. */ 206 if (!(p = xdr_encode_netobj(p, &resp->lock.oh))) 207 return NULL; 208 209 start = loff_t_to_s64(fl->fl_start); 210 if (fl->fl_end == OFFSET_MAX) 211 len = 0; 212 else 213 len = loff_t_to_s64(fl->fl_end - fl->fl_start + 1); 214 215 p = xdr_encode_hyper(p, start); 216 p = xdr_encode_hyper(p, len); 217 dprintk("xdr: encode_testres (status %u pid %d type %d start %Ld end %Ld)\n", 218 resp->status, (int)resp->lock.svid, fl->fl_type, 219 (long long)fl->fl_start, (long long)fl->fl_end); 220 } 221 222 dprintk("xdr: after encode_testres (p %p resp %p)\n", p, resp); 223 return p; 224 } 225 226 227 /* 228 * First, the server side XDR functions 229 */ 230 int 231 nlm4svc_decode_testargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp) 232 { 233 u32 exclusive; 234 235 if (!(p = nlm4_decode_cookie(p, &argp->cookie))) 236 return 0; 237 238 exclusive = ntohl(*p++); 239 if (!(p = nlm4_decode_lock(p, &argp->lock))) 240 return 0; 241 if (exclusive) 242 argp->lock.fl.fl_type = F_WRLCK; 243 244 return xdr_argsize_check(rqstp, p); 245 } 246 247 int 248 nlm4svc_encode_testres(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp) 249 { 250 if (!(p = nlm4_encode_testres(p, resp))) 251 return 0; 252 return xdr_ressize_check(rqstp, p); 253 } 254 255 int 256 nlm4svc_decode_lockargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp) 257 { 258 u32 exclusive; 259 260 if (!(p = nlm4_decode_cookie(p, &argp->cookie))) 261 return 0; 262 argp->block = ntohl(*p++); 263 exclusive = ntohl(*p++); 264 if (!(p = nlm4_decode_lock(p, &argp->lock))) 265 return 0; 266 if (exclusive) 267 argp->lock.fl.fl_type = F_WRLCK; 268 argp->reclaim = ntohl(*p++); 269 argp->state = ntohl(*p++); 270 argp->monitor = 1; /* monitor client by default */ 271 272 return xdr_argsize_check(rqstp, p); 273 } 274 275 int 276 nlm4svc_decode_cancargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp) 277 { 278 u32 exclusive; 279 280 if (!(p = nlm4_decode_cookie(p, &argp->cookie))) 281 return 0; 282 argp->block = ntohl(*p++); 283 exclusive = ntohl(*p++); 284 if (!(p = nlm4_decode_lock(p, &argp->lock))) 285 return 0; 286 if (exclusive) 287 argp->lock.fl.fl_type = F_WRLCK; 288 return xdr_argsize_check(rqstp, p); 289 } 290 291 int 292 nlm4svc_decode_unlockargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp) 293 { 294 if (!(p = nlm4_decode_cookie(p, &argp->cookie)) 295 || !(p = nlm4_decode_lock(p, &argp->lock))) 296 return 0; 297 argp->lock.fl.fl_type = F_UNLCK; 298 return xdr_argsize_check(rqstp, p); 299 } 300 301 int 302 nlm4svc_decode_shareargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp) 303 { 304 struct nlm_lock *lock = &argp->lock; 305 306 memset(lock, 0, sizeof(*lock)); 307 locks_init_lock(&lock->fl); 308 lock->svid = ~(u32) 0; 309 lock->fl.fl_pid = (pid_t)lock->svid; 310 311 if (!(p = nlm4_decode_cookie(p, &argp->cookie)) 312 || !(p = xdr_decode_string_inplace(p, &lock->caller, 313 &lock->len, NLM_MAXSTRLEN)) 314 || !(p = nlm4_decode_fh(p, &lock->fh)) 315 || !(p = nlm4_decode_oh(p, &lock->oh))) 316 return 0; 317 argp->fsm_mode = ntohl(*p++); 318 argp->fsm_access = ntohl(*p++); 319 return xdr_argsize_check(rqstp, p); 320 } 321 322 int 323 nlm4svc_encode_shareres(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp) 324 { 325 if (!(p = nlm4_encode_cookie(p, &resp->cookie))) 326 return 0; 327 *p++ = resp->status; 328 *p++ = xdr_zero; /* sequence argument */ 329 return xdr_ressize_check(rqstp, p); 330 } 331 332 int 333 nlm4svc_encode_res(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp) 334 { 335 if (!(p = nlm4_encode_cookie(p, &resp->cookie))) 336 return 0; 337 *p++ = resp->status; 338 return xdr_ressize_check(rqstp, p); 339 } 340 341 int 342 nlm4svc_decode_notify(struct svc_rqst *rqstp, __be32 *p, struct nlm_args *argp) 343 { 344 struct nlm_lock *lock = &argp->lock; 345 346 if (!(p = xdr_decode_string_inplace(p, &lock->caller, 347 &lock->len, NLM_MAXSTRLEN))) 348 return 0; 349 argp->state = ntohl(*p++); 350 return xdr_argsize_check(rqstp, p); 351 } 352 353 int 354 nlm4svc_decode_reboot(struct svc_rqst *rqstp, __be32 *p, struct nlm_reboot *argp) 355 { 356 if (!(p = xdr_decode_string_inplace(p, &argp->mon, &argp->len, SM_MAXSTRLEN))) 357 return 0; 358 argp->state = ntohl(*p++); 359 /* Preserve the address in network byte order */ 360 argp->addr = *p++; 361 return xdr_argsize_check(rqstp, p); 362 } 363 364 int 365 nlm4svc_decode_res(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp) 366 { 367 if (!(p = nlm4_decode_cookie(p, &resp->cookie))) 368 return 0; 369 resp->status = *p++; 370 return xdr_argsize_check(rqstp, p); 371 } 372 373 int 374 nlm4svc_decode_void(struct svc_rqst *rqstp, __be32 *p, void *dummy) 375 { 376 return xdr_argsize_check(rqstp, p); 377 } 378 379 int 380 nlm4svc_encode_void(struct svc_rqst *rqstp, __be32 *p, void *dummy) 381 { 382 return xdr_ressize_check(rqstp, p); 383 } 384 385 /* 386 * Now, the client side XDR functions 387 */ 388 #ifdef NLMCLNT_SUPPORT_SHARES 389 static int 390 nlm4clt_decode_void(struct rpc_rqst *req, __be32 *p, void *ptr) 391 { 392 return 0; 393 } 394 #endif 395 396 static int 397 nlm4clt_encode_testargs(struct rpc_rqst *req, __be32 *p, nlm_args *argp) 398 { 399 struct nlm_lock *lock = &argp->lock; 400 401 if (!(p = nlm4_encode_cookie(p, &argp->cookie))) 402 return -EIO; 403 *p++ = (lock->fl.fl_type == F_WRLCK)? xdr_one : xdr_zero; 404 if (!(p = nlm4_encode_lock(p, lock))) 405 return -EIO; 406 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 407 return 0; 408 } 409 410 static int 411 nlm4clt_decode_testres(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp) 412 { 413 if (!(p = nlm4_decode_cookie(p, &resp->cookie))) 414 return -EIO; 415 resp->status = *p++; 416 if (resp->status == nlm_lck_denied) { 417 struct file_lock *fl = &resp->lock.fl; 418 u32 excl; 419 __u64 start, len; 420 __s64 end; 421 422 memset(&resp->lock, 0, sizeof(resp->lock)); 423 locks_init_lock(fl); 424 excl = ntohl(*p++); 425 resp->lock.svid = ntohl(*p++); 426 fl->fl_pid = (pid_t)resp->lock.svid; 427 if (!(p = nlm4_decode_oh(p, &resp->lock.oh))) 428 return -EIO; 429 430 fl->fl_flags = FL_POSIX; 431 fl->fl_type = excl? F_WRLCK : F_RDLCK; 432 p = xdr_decode_hyper(p, &start); 433 p = xdr_decode_hyper(p, &len); 434 end = start + len - 1; 435 436 fl->fl_start = s64_to_loff_t(start); 437 if (len == 0 || end < 0) 438 fl->fl_end = OFFSET_MAX; 439 else 440 fl->fl_end = s64_to_loff_t(end); 441 } 442 return 0; 443 } 444 445 446 static int 447 nlm4clt_encode_lockargs(struct rpc_rqst *req, __be32 *p, nlm_args *argp) 448 { 449 struct nlm_lock *lock = &argp->lock; 450 451 if (!(p = nlm4_encode_cookie(p, &argp->cookie))) 452 return -EIO; 453 *p++ = argp->block? xdr_one : xdr_zero; 454 *p++ = (lock->fl.fl_type == F_WRLCK)? xdr_one : xdr_zero; 455 if (!(p = nlm4_encode_lock(p, lock))) 456 return -EIO; 457 *p++ = argp->reclaim? xdr_one : xdr_zero; 458 *p++ = htonl(argp->state); 459 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 460 return 0; 461 } 462 463 static int 464 nlm4clt_encode_cancargs(struct rpc_rqst *req, __be32 *p, nlm_args *argp) 465 { 466 struct nlm_lock *lock = &argp->lock; 467 468 if (!(p = nlm4_encode_cookie(p, &argp->cookie))) 469 return -EIO; 470 *p++ = argp->block? xdr_one : xdr_zero; 471 *p++ = (lock->fl.fl_type == F_WRLCK)? xdr_one : xdr_zero; 472 if (!(p = nlm4_encode_lock(p, lock))) 473 return -EIO; 474 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 475 return 0; 476 } 477 478 static int 479 nlm4clt_encode_unlockargs(struct rpc_rqst *req, __be32 *p, nlm_args *argp) 480 { 481 struct nlm_lock *lock = &argp->lock; 482 483 if (!(p = nlm4_encode_cookie(p, &argp->cookie))) 484 return -EIO; 485 if (!(p = nlm4_encode_lock(p, lock))) 486 return -EIO; 487 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 488 return 0; 489 } 490 491 static int 492 nlm4clt_encode_res(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp) 493 { 494 if (!(p = nlm4_encode_cookie(p, &resp->cookie))) 495 return -EIO; 496 *p++ = resp->status; 497 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 498 return 0; 499 } 500 501 static int 502 nlm4clt_encode_testres(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp) 503 { 504 if (!(p = nlm4_encode_testres(p, resp))) 505 return -EIO; 506 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 507 return 0; 508 } 509 510 static int 511 nlm4clt_decode_res(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp) 512 { 513 if (!(p = nlm4_decode_cookie(p, &resp->cookie))) 514 return -EIO; 515 resp->status = *p++; 516 return 0; 517 } 518 519 #if (NLMCLNT_OHSIZE > XDR_MAX_NETOBJ) 520 # error "NLM host name cannot be larger than XDR_MAX_NETOBJ!" 521 #endif 522 523 #if (NLMCLNT_OHSIZE > NLM_MAXSTRLEN) 524 # error "NLM host name cannot be larger than NLM's maximum string length!" 525 #endif 526 527 /* 528 * Buffer requirements for NLM 529 */ 530 #define NLM4_void_sz 0 531 #define NLM4_cookie_sz 1+XDR_QUADLEN(NLM_MAXCOOKIELEN) 532 #define NLM4_caller_sz 1+XDR_QUADLEN(NLMCLNT_OHSIZE) 533 #define NLM4_owner_sz 1+XDR_QUADLEN(NLMCLNT_OHSIZE) 534 #define NLM4_fhandle_sz 1+XDR_QUADLEN(NFS3_FHSIZE) 535 #define NLM4_lock_sz 5+NLM4_caller_sz+NLM4_owner_sz+NLM4_fhandle_sz 536 #define NLM4_holder_sz 6+NLM4_owner_sz 537 538 #define NLM4_testargs_sz NLM4_cookie_sz+1+NLM4_lock_sz 539 #define NLM4_lockargs_sz NLM4_cookie_sz+4+NLM4_lock_sz 540 #define NLM4_cancargs_sz NLM4_cookie_sz+2+NLM4_lock_sz 541 #define NLM4_unlockargs_sz NLM4_cookie_sz+NLM4_lock_sz 542 543 #define NLM4_testres_sz NLM4_cookie_sz+1+NLM4_holder_sz 544 #define NLM4_res_sz NLM4_cookie_sz+1 545 #define NLM4_norep_sz 0 546 547 /* 548 * For NLM, a void procedure really returns nothing 549 */ 550 #define nlm4clt_decode_norep NULL 551 552 #define PROC(proc, argtype, restype) \ 553 [NLMPROC_##proc] = { \ 554 .p_proc = NLMPROC_##proc, \ 555 .p_encode = (kxdrproc_t) nlm4clt_encode_##argtype, \ 556 .p_decode = (kxdrproc_t) nlm4clt_decode_##restype, \ 557 .p_arglen = NLM4_##argtype##_sz, \ 558 .p_replen = NLM4_##restype##_sz, \ 559 .p_statidx = NLMPROC_##proc, \ 560 .p_name = #proc, \ 561 } 562 563 static struct rpc_procinfo nlm4_procedures[] = { 564 PROC(TEST, testargs, testres), 565 PROC(LOCK, lockargs, res), 566 PROC(CANCEL, cancargs, res), 567 PROC(UNLOCK, unlockargs, res), 568 PROC(GRANTED, testargs, res), 569 PROC(TEST_MSG, testargs, norep), 570 PROC(LOCK_MSG, lockargs, norep), 571 PROC(CANCEL_MSG, cancargs, norep), 572 PROC(UNLOCK_MSG, unlockargs, norep), 573 PROC(GRANTED_MSG, testargs, norep), 574 PROC(TEST_RES, testres, norep), 575 PROC(LOCK_RES, res, norep), 576 PROC(CANCEL_RES, res, norep), 577 PROC(UNLOCK_RES, res, norep), 578 PROC(GRANTED_RES, res, norep), 579 #ifdef NLMCLNT_SUPPORT_SHARES 580 PROC(SHARE, shareargs, shareres), 581 PROC(UNSHARE, shareargs, shareres), 582 PROC(NM_LOCK, lockargs, res), 583 PROC(FREE_ALL, notify, void), 584 #endif 585 }; 586 587 struct rpc_version nlm_version4 = { 588 .number = 4, 589 .nrprocs = 24, 590 .procs = nlm4_procedures, 591 }; 592