1 /* 2 * linux/fs/lockd/clnt4xdr.c 3 * 4 * XDR functions to encode/decode NLM version 4 RPC arguments and results. 5 * 6 * NLM client-side only. 7 * 8 * Copyright (C) 2010, Oracle. All rights reserved. 9 */ 10 11 #include <linux/types.h> 12 #include <linux/sunrpc/xdr.h> 13 #include <linux/sunrpc/clnt.h> 14 #include <linux/sunrpc/stats.h> 15 #include <linux/lockd/lockd.h> 16 17 #define NLMDBG_FACILITY NLMDBG_XDR 18 19 #if (NLMCLNT_OHSIZE > XDR_MAX_NETOBJ) 20 # error "NLM host name cannot be larger than XDR_MAX_NETOBJ!" 21 #endif 22 23 #if (NLMCLNT_OHSIZE > NLM_MAXSTRLEN) 24 # error "NLM host name cannot be larger than NLM's maximum string length!" 25 #endif 26 27 /* 28 * Declare the space requirements for NLM arguments and replies as 29 * number of 32bit-words 30 */ 31 #define NLM4_void_sz (0) 32 #define NLM4_cookie_sz (1+(NLM_MAXCOOKIELEN>>2)) 33 #define NLM4_caller_sz (1+(NLMCLNT_OHSIZE>>2)) 34 #define NLM4_owner_sz (1+(NLMCLNT_OHSIZE>>2)) 35 #define NLM4_fhandle_sz (1+(NFS3_FHSIZE>>2)) 36 #define NLM4_lock_sz (5+NLM4_caller_sz+NLM4_owner_sz+NLM4_fhandle_sz) 37 #define NLM4_holder_sz (6+NLM4_owner_sz) 38 39 #define NLM4_testargs_sz (NLM4_cookie_sz+1+NLM4_lock_sz) 40 #define NLM4_lockargs_sz (NLM4_cookie_sz+4+NLM4_lock_sz) 41 #define NLM4_cancargs_sz (NLM4_cookie_sz+2+NLM4_lock_sz) 42 #define NLM4_unlockargs_sz (NLM4_cookie_sz+NLM4_lock_sz) 43 44 #define NLM4_testres_sz (NLM4_cookie_sz+1+NLM4_holder_sz) 45 #define NLM4_res_sz (NLM4_cookie_sz+1) 46 #define NLM4_norep_sz (0) 47 48 49 static s64 loff_t_to_s64(loff_t offset) 50 { 51 s64 res; 52 53 if (offset >= NLM4_OFFSET_MAX) 54 res = NLM4_OFFSET_MAX; 55 else if (offset <= -NLM4_OFFSET_MAX) 56 res = -NLM4_OFFSET_MAX; 57 else 58 res = offset; 59 return res; 60 } 61 62 static void nlm4_compute_offsets(const struct nlm_lock *lock, 63 u64 *l_offset, u64 *l_len) 64 { 65 const struct file_lock *fl = &lock->fl; 66 67 BUG_ON(fl->fl_start > NLM4_OFFSET_MAX); 68 BUG_ON(fl->fl_end > NLM4_OFFSET_MAX && 69 fl->fl_end != OFFSET_MAX); 70 71 *l_offset = loff_t_to_s64(fl->fl_start); 72 if (fl->fl_end == OFFSET_MAX) 73 *l_len = 0; 74 else 75 *l_len = loff_t_to_s64(fl->fl_end - fl->fl_start + 1); 76 } 77 78 /* 79 * Handle decode buffer overflows out-of-line. 80 */ 81 static void print_overflow_msg(const char *func, const struct xdr_stream *xdr) 82 { 83 dprintk("lockd: %s prematurely hit the end of our receive buffer. " 84 "Remaining buffer length is %tu words.\n", 85 func, xdr->end - xdr->p); 86 } 87 88 89 /* 90 * Encode/decode NLMv4 basic data types 91 * 92 * Basic NLMv4 data types are defined in Appendix II, section 6.1.4 93 * of RFC 1813: "NFS Version 3 Protocol Specification" and in Chapter 94 * 10 of X/Open's "Protocols for Interworking: XNFS, Version 3W". 95 * 96 * Not all basic data types have their own encoding and decoding 97 * functions. For run-time efficiency, some data types are encoded 98 * or decoded inline. 99 */ 100 101 static void encode_bool(struct xdr_stream *xdr, const int value) 102 { 103 __be32 *p; 104 105 p = xdr_reserve_space(xdr, 4); 106 *p = value ? xdr_one : xdr_zero; 107 } 108 109 static void encode_int32(struct xdr_stream *xdr, const s32 value) 110 { 111 __be32 *p; 112 113 p = xdr_reserve_space(xdr, 4); 114 *p = cpu_to_be32(value); 115 } 116 117 /* 118 * typedef opaque netobj<MAXNETOBJ_SZ> 119 */ 120 static void encode_netobj(struct xdr_stream *xdr, 121 const u8 *data, const unsigned int length) 122 { 123 __be32 *p; 124 125 BUG_ON(length > XDR_MAX_NETOBJ); 126 p = xdr_reserve_space(xdr, 4 + length); 127 xdr_encode_opaque(p, data, length); 128 } 129 130 static int decode_netobj(struct xdr_stream *xdr, 131 struct xdr_netobj *obj) 132 { 133 u32 length; 134 __be32 *p; 135 136 p = xdr_inline_decode(xdr, 4); 137 if (unlikely(p == NULL)) 138 goto out_overflow; 139 length = be32_to_cpup(p++); 140 if (unlikely(length > XDR_MAX_NETOBJ)) 141 goto out_size; 142 obj->len = length; 143 obj->data = (u8 *)p; 144 return 0; 145 out_size: 146 dprintk("NFS: returned netobj was too long: %u\n", length); 147 return -EIO; 148 out_overflow: 149 print_overflow_msg(__func__, xdr); 150 return -EIO; 151 } 152 153 /* 154 * netobj cookie; 155 */ 156 static void encode_cookie(struct xdr_stream *xdr, 157 const struct nlm_cookie *cookie) 158 { 159 BUG_ON(cookie->len > NLM_MAXCOOKIELEN); 160 encode_netobj(xdr, (u8 *)&cookie->data, cookie->len); 161 } 162 163 static int decode_cookie(struct xdr_stream *xdr, 164 struct nlm_cookie *cookie) 165 { 166 u32 length; 167 __be32 *p; 168 169 p = xdr_inline_decode(xdr, 4); 170 if (unlikely(p == NULL)) 171 goto out_overflow; 172 length = be32_to_cpup(p++); 173 /* apparently HPUX can return empty cookies */ 174 if (length == 0) 175 goto out_hpux; 176 if (length > NLM_MAXCOOKIELEN) 177 goto out_size; 178 p = xdr_inline_decode(xdr, length); 179 if (unlikely(p == NULL)) 180 goto out_overflow; 181 cookie->len = length; 182 memcpy(cookie->data, p, length); 183 return 0; 184 out_hpux: 185 cookie->len = 4; 186 memset(cookie->data, 0, 4); 187 return 0; 188 out_size: 189 dprintk("NFS: returned cookie was too long: %u\n", length); 190 return -EIO; 191 out_overflow: 192 print_overflow_msg(__func__, xdr); 193 return -EIO; 194 } 195 196 /* 197 * netobj fh; 198 */ 199 static void encode_fh(struct xdr_stream *xdr, const struct nfs_fh *fh) 200 { 201 BUG_ON(fh->size > NFS3_FHSIZE); 202 encode_netobj(xdr, (u8 *)&fh->data, fh->size); 203 } 204 205 /* 206 * enum nlm4_stats { 207 * NLM4_GRANTED = 0, 208 * NLM4_DENIED = 1, 209 * NLM4_DENIED_NOLOCKS = 2, 210 * NLM4_BLOCKED = 3, 211 * NLM4_DENIED_GRACE_PERIOD = 4, 212 * NLM4_DEADLCK = 5, 213 * NLM4_ROFS = 6, 214 * NLM4_STALE_FH = 7, 215 * NLM4_FBIG = 8, 216 * NLM4_FAILED = 9 217 * }; 218 * 219 * struct nlm4_stat { 220 * nlm4_stats stat; 221 * }; 222 * 223 * NB: we don't swap bytes for the NLM status values. The upper 224 * layers deal directly with the status value in network byte 225 * order. 226 */ 227 static void encode_nlm4_stat(struct xdr_stream *xdr, 228 const __be32 stat) 229 { 230 __be32 *p; 231 232 BUG_ON(be32_to_cpu(stat) > NLM_FAILED); 233 p = xdr_reserve_space(xdr, 4); 234 *p = stat; 235 } 236 237 static int decode_nlm4_stat(struct xdr_stream *xdr, __be32 *stat) 238 { 239 __be32 *p; 240 241 p = xdr_inline_decode(xdr, 4); 242 if (unlikely(p == NULL)) 243 goto out_overflow; 244 if (unlikely(*p > nlm4_failed)) 245 goto out_bad_xdr; 246 *stat = *p; 247 return 0; 248 out_bad_xdr: 249 dprintk("%s: server returned invalid nlm4_stats value: %u\n", 250 __func__, be32_to_cpup(p)); 251 return -EIO; 252 out_overflow: 253 print_overflow_msg(__func__, xdr); 254 return -EIO; 255 } 256 257 /* 258 * struct nlm4_holder { 259 * bool exclusive; 260 * int32 svid; 261 * netobj oh; 262 * uint64 l_offset; 263 * uint64 l_len; 264 * }; 265 */ 266 static void encode_nlm4_holder(struct xdr_stream *xdr, 267 const struct nlm_res *result) 268 { 269 const struct nlm_lock *lock = &result->lock; 270 u64 l_offset, l_len; 271 __be32 *p; 272 273 encode_bool(xdr, lock->fl.fl_type == F_RDLCK); 274 encode_int32(xdr, lock->svid); 275 encode_netobj(xdr, lock->oh.data, lock->oh.len); 276 277 p = xdr_reserve_space(xdr, 4 + 4); 278 nlm4_compute_offsets(lock, &l_offset, &l_len); 279 p = xdr_encode_hyper(p, l_offset); 280 xdr_encode_hyper(p, l_len); 281 } 282 283 static int decode_nlm4_holder(struct xdr_stream *xdr, struct nlm_res *result) 284 { 285 struct nlm_lock *lock = &result->lock; 286 struct file_lock *fl = &lock->fl; 287 u64 l_offset, l_len; 288 u32 exclusive; 289 int error; 290 __be32 *p; 291 s32 end; 292 293 memset(lock, 0, sizeof(*lock)); 294 locks_init_lock(fl); 295 296 p = xdr_inline_decode(xdr, 4 + 4); 297 if (unlikely(p == NULL)) 298 goto out_overflow; 299 exclusive = be32_to_cpup(p++); 300 lock->svid = be32_to_cpup(p); 301 fl->fl_pid = (pid_t)lock->svid; 302 303 error = decode_netobj(xdr, &lock->oh); 304 if (unlikely(error)) 305 goto out; 306 307 p = xdr_inline_decode(xdr, 8 + 8); 308 if (unlikely(p == NULL)) 309 goto out_overflow; 310 311 fl->fl_flags = FL_POSIX; 312 fl->fl_type = exclusive != 0 ? F_WRLCK : F_RDLCK; 313 p = xdr_decode_hyper(p, &l_offset); 314 xdr_decode_hyper(p, &l_len); 315 end = l_offset + l_len - 1; 316 317 fl->fl_start = (loff_t)l_offset; 318 if (l_len == 0 || end < 0) 319 fl->fl_end = OFFSET_MAX; 320 else 321 fl->fl_end = (loff_t)end; 322 error = 0; 323 out: 324 return error; 325 out_overflow: 326 print_overflow_msg(__func__, xdr); 327 return -EIO; 328 } 329 330 /* 331 * string caller_name<LM_MAXSTRLEN>; 332 */ 333 static void encode_caller_name(struct xdr_stream *xdr, const char *name) 334 { 335 /* NB: client-side does not set lock->len */ 336 u32 length = strlen(name); 337 __be32 *p; 338 339 BUG_ON(length > NLM_MAXSTRLEN); 340 p = xdr_reserve_space(xdr, 4 + length); 341 xdr_encode_opaque(p, name, length); 342 } 343 344 /* 345 * struct nlm4_lock { 346 * string caller_name<LM_MAXSTRLEN>; 347 * netobj fh; 348 * netobj oh; 349 * int32 svid; 350 * uint64 l_offset; 351 * uint64 l_len; 352 * }; 353 */ 354 static void encode_nlm4_lock(struct xdr_stream *xdr, 355 const struct nlm_lock *lock) 356 { 357 u64 l_offset, l_len; 358 __be32 *p; 359 360 encode_caller_name(xdr, lock->caller); 361 encode_fh(xdr, &lock->fh); 362 encode_netobj(xdr, lock->oh.data, lock->oh.len); 363 364 p = xdr_reserve_space(xdr, 4 + 8 + 8); 365 *p++ = cpu_to_be32(lock->svid); 366 367 nlm4_compute_offsets(lock, &l_offset, &l_len); 368 p = xdr_encode_hyper(p, l_offset); 369 xdr_encode_hyper(p, l_len); 370 } 371 372 373 /* 374 * NLMv4 XDR encode functions 375 * 376 * NLMv4 argument types are defined in Appendix II of RFC 1813: 377 * "NFS Version 3 Protocol Specification" and Chapter 10 of X/Open's 378 * "Protocols for Interworking: XNFS, Version 3W". 379 */ 380 381 /* 382 * struct nlm4_testargs { 383 * netobj cookie; 384 * bool exclusive; 385 * struct nlm4_lock alock; 386 * }; 387 */ 388 static void nlm4_xdr_enc_testargs(struct rpc_rqst *req, 389 struct xdr_stream *xdr, 390 const struct nlm_args *args) 391 { 392 const struct nlm_lock *lock = &args->lock; 393 394 encode_cookie(xdr, &args->cookie); 395 encode_bool(xdr, lock->fl.fl_type == F_WRLCK); 396 encode_nlm4_lock(xdr, lock); 397 } 398 399 /* 400 * struct nlm4_lockargs { 401 * netobj cookie; 402 * bool block; 403 * bool exclusive; 404 * struct nlm4_lock alock; 405 * bool reclaim; 406 * int state; 407 * }; 408 */ 409 static void nlm4_xdr_enc_lockargs(struct rpc_rqst *req, 410 struct xdr_stream *xdr, 411 const struct nlm_args *args) 412 { 413 const struct nlm_lock *lock = &args->lock; 414 415 encode_cookie(xdr, &args->cookie); 416 encode_bool(xdr, args->block); 417 encode_bool(xdr, lock->fl.fl_type == F_WRLCK); 418 encode_nlm4_lock(xdr, lock); 419 encode_bool(xdr, args->reclaim); 420 encode_int32(xdr, args->state); 421 } 422 423 /* 424 * struct nlm4_cancargs { 425 * netobj cookie; 426 * bool block; 427 * bool exclusive; 428 * struct nlm4_lock alock; 429 * }; 430 */ 431 static void nlm4_xdr_enc_cancargs(struct rpc_rqst *req, 432 struct xdr_stream *xdr, 433 const struct nlm_args *args) 434 { 435 const struct nlm_lock *lock = &args->lock; 436 437 encode_cookie(xdr, &args->cookie); 438 encode_bool(xdr, args->block); 439 encode_bool(xdr, lock->fl.fl_type == F_WRLCK); 440 encode_nlm4_lock(xdr, lock); 441 } 442 443 /* 444 * struct nlm4_unlockargs { 445 * netobj cookie; 446 * struct nlm4_lock alock; 447 * }; 448 */ 449 static void nlm4_xdr_enc_unlockargs(struct rpc_rqst *req, 450 struct xdr_stream *xdr, 451 const struct nlm_args *args) 452 { 453 const struct nlm_lock *lock = &args->lock; 454 455 encode_cookie(xdr, &args->cookie); 456 encode_nlm4_lock(xdr, lock); 457 } 458 459 /* 460 * struct nlm4_res { 461 * netobj cookie; 462 * nlm4_stat stat; 463 * }; 464 */ 465 static void nlm4_xdr_enc_res(struct rpc_rqst *req, 466 struct xdr_stream *xdr, 467 const struct nlm_res *result) 468 { 469 encode_cookie(xdr, &result->cookie); 470 encode_nlm4_stat(xdr, result->status); 471 } 472 473 /* 474 * union nlm4_testrply switch (nlm4_stats stat) { 475 * case NLM4_DENIED: 476 * struct nlm4_holder holder; 477 * default: 478 * void; 479 * }; 480 * 481 * struct nlm4_testres { 482 * netobj cookie; 483 * nlm4_testrply test_stat; 484 * }; 485 */ 486 static void nlm4_xdr_enc_testres(struct rpc_rqst *req, 487 struct xdr_stream *xdr, 488 const struct nlm_res *result) 489 { 490 encode_cookie(xdr, &result->cookie); 491 encode_nlm4_stat(xdr, result->status); 492 if (result->status == nlm_lck_denied) 493 encode_nlm4_holder(xdr, result); 494 } 495 496 497 /* 498 * NLMv4 XDR decode functions 499 * 500 * NLMv4 argument types are defined in Appendix II of RFC 1813: 501 * "NFS Version 3 Protocol Specification" and Chapter 10 of X/Open's 502 * "Protocols for Interworking: XNFS, Version 3W". 503 */ 504 505 /* 506 * union nlm4_testrply switch (nlm4_stats stat) { 507 * case NLM4_DENIED: 508 * struct nlm4_holder holder; 509 * default: 510 * void; 511 * }; 512 * 513 * struct nlm4_testres { 514 * netobj cookie; 515 * nlm4_testrply test_stat; 516 * }; 517 */ 518 static int decode_nlm4_testrply(struct xdr_stream *xdr, 519 struct nlm_res *result) 520 { 521 int error; 522 523 error = decode_nlm4_stat(xdr, &result->status); 524 if (unlikely(error)) 525 goto out; 526 if (result->status == nlm_lck_denied) 527 error = decode_nlm4_holder(xdr, result); 528 out: 529 return error; 530 } 531 532 static int nlm4_xdr_dec_testres(struct rpc_rqst *req, 533 struct xdr_stream *xdr, 534 struct nlm_res *result) 535 { 536 int error; 537 538 error = decode_cookie(xdr, &result->cookie); 539 if (unlikely(error)) 540 goto out; 541 error = decode_nlm4_testrply(xdr, result); 542 out: 543 return error; 544 } 545 546 /* 547 * struct nlm4_res { 548 * netobj cookie; 549 * nlm4_stat stat; 550 * }; 551 */ 552 static int nlm4_xdr_dec_res(struct rpc_rqst *req, 553 struct xdr_stream *xdr, 554 struct nlm_res *result) 555 { 556 int error; 557 558 error = decode_cookie(xdr, &result->cookie); 559 if (unlikely(error)) 560 goto out; 561 error = decode_nlm4_stat(xdr, &result->status); 562 out: 563 return error; 564 } 565 566 567 /* 568 * For NLM, a void procedure really returns nothing 569 */ 570 #define nlm4_xdr_dec_norep NULL 571 572 #define PROC(proc, argtype, restype) \ 573 [NLMPROC_##proc] = { \ 574 .p_proc = NLMPROC_##proc, \ 575 .p_encode = (kxdreproc_t)nlm4_xdr_enc_##argtype, \ 576 .p_decode = (kxdrdproc_t)nlm4_xdr_dec_##restype, \ 577 .p_arglen = NLM4_##argtype##_sz, \ 578 .p_replen = NLM4_##restype##_sz, \ 579 .p_statidx = NLMPROC_##proc, \ 580 .p_name = #proc, \ 581 } 582 583 static struct rpc_procinfo nlm4_procedures[] = { 584 PROC(TEST, testargs, testres), 585 PROC(LOCK, lockargs, res), 586 PROC(CANCEL, cancargs, res), 587 PROC(UNLOCK, unlockargs, res), 588 PROC(GRANTED, testargs, res), 589 PROC(TEST_MSG, testargs, norep), 590 PROC(LOCK_MSG, lockargs, norep), 591 PROC(CANCEL_MSG, cancargs, norep), 592 PROC(UNLOCK_MSG, unlockargs, norep), 593 PROC(GRANTED_MSG, testargs, norep), 594 PROC(TEST_RES, testres, norep), 595 PROC(LOCK_RES, res, norep), 596 PROC(CANCEL_RES, res, norep), 597 PROC(UNLOCK_RES, res, norep), 598 PROC(GRANTED_RES, res, norep), 599 }; 600 601 struct rpc_version nlm_version4 = { 602 .number = 4, 603 .nrprocs = ARRAY_SIZE(nlm4_procedures), 604 .procs = nlm4_procedures, 605 }; 606