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