clnt4xdr.c 13 KB

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