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