decode.h 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #ifndef __CEPH_DECODE_H
  3. #define __CEPH_DECODE_H
  4. #include <linux/err.h>
  5. #include <linux/bug.h>
  6. #include <linux/slab.h>
  7. #include <linux/time.h>
  8. #include <asm/unaligned.h>
  9. #include <linux/ceph/types.h>
  10. /*
  11. * in all cases,
  12. * void **p pointer to position pointer
  13. * void *end pointer to end of buffer (last byte + 1)
  14. */
  15. static inline u64 ceph_decode_64(void **p)
  16. {
  17. u64 v = get_unaligned_le64(*p);
  18. *p += sizeof(u64);
  19. return v;
  20. }
  21. static inline u32 ceph_decode_32(void **p)
  22. {
  23. u32 v = get_unaligned_le32(*p);
  24. *p += sizeof(u32);
  25. return v;
  26. }
  27. static inline u16 ceph_decode_16(void **p)
  28. {
  29. u16 v = get_unaligned_le16(*p);
  30. *p += sizeof(u16);
  31. return v;
  32. }
  33. static inline u8 ceph_decode_8(void **p)
  34. {
  35. u8 v = *(u8 *)*p;
  36. (*p)++;
  37. return v;
  38. }
  39. static inline void ceph_decode_copy(void **p, void *pv, size_t n)
  40. {
  41. memcpy(pv, *p, n);
  42. *p += n;
  43. }
  44. /*
  45. * bounds check input.
  46. */
  47. static inline bool ceph_has_room(void **p, void *end, size_t n)
  48. {
  49. return end >= *p && n <= end - *p;
  50. }
  51. #define ceph_decode_need(p, end, n, bad) \
  52. do { \
  53. if (!likely(ceph_has_room(p, end, n))) \
  54. goto bad; \
  55. } while (0)
  56. #define ceph_decode_64_safe(p, end, v, bad) \
  57. do { \
  58. ceph_decode_need(p, end, sizeof(u64), bad); \
  59. v = ceph_decode_64(p); \
  60. } while (0)
  61. #define ceph_decode_32_safe(p, end, v, bad) \
  62. do { \
  63. ceph_decode_need(p, end, sizeof(u32), bad); \
  64. v = ceph_decode_32(p); \
  65. } while (0)
  66. #define ceph_decode_16_safe(p, end, v, bad) \
  67. do { \
  68. ceph_decode_need(p, end, sizeof(u16), bad); \
  69. v = ceph_decode_16(p); \
  70. } while (0)
  71. #define ceph_decode_8_safe(p, end, v, bad) \
  72. do { \
  73. ceph_decode_need(p, end, sizeof(u8), bad); \
  74. v = ceph_decode_8(p); \
  75. } while (0)
  76. #define ceph_decode_copy_safe(p, end, pv, n, bad) \
  77. do { \
  78. ceph_decode_need(p, end, n, bad); \
  79. ceph_decode_copy(p, pv, n); \
  80. } while (0)
  81. /*
  82. * Allocate a buffer big enough to hold the wire-encoded string, and
  83. * decode the string into it. The resulting string will always be
  84. * terminated with '\0'. If successful, *p will be advanced
  85. * past the decoded data. Also, if lenp is not a null pointer, the
  86. * length (not including the terminating '\0') will be recorded in
  87. * *lenp. Note that a zero-length string is a valid return value.
  88. *
  89. * Returns a pointer to the newly-allocated string buffer, or a
  90. * pointer-coded errno if an error occurs. Neither *p nor *lenp
  91. * will have been updated if an error is returned.
  92. *
  93. * There are two possible failures:
  94. * - converting the string would require accessing memory at or
  95. * beyond the "end" pointer provided (-ERANGE)
  96. * - memory could not be allocated for the result (-ENOMEM)
  97. */
  98. static inline char *ceph_extract_encoded_string(void **p, void *end,
  99. size_t *lenp, gfp_t gfp)
  100. {
  101. u32 len;
  102. void *sp = *p;
  103. char *buf;
  104. ceph_decode_32_safe(&sp, end, len, bad);
  105. if (!ceph_has_room(&sp, end, len))
  106. goto bad;
  107. buf = kmalloc(len + 1, gfp);
  108. if (!buf)
  109. return ERR_PTR(-ENOMEM);
  110. if (len)
  111. memcpy(buf, sp, len);
  112. buf[len] = '\0';
  113. *p = (char *) *p + sizeof (u32) + len;
  114. if (lenp)
  115. *lenp = (size_t) len;
  116. return buf;
  117. bad:
  118. return ERR_PTR(-ERANGE);
  119. }
  120. /*
  121. * skip helpers
  122. */
  123. #define ceph_decode_skip_n(p, end, n, bad) \
  124. do { \
  125. ceph_decode_need(p, end, n, bad); \
  126. *p += n; \
  127. } while (0)
  128. #define ceph_decode_skip_64(p, end, bad) \
  129. ceph_decode_skip_n(p, end, sizeof(u64), bad)
  130. #define ceph_decode_skip_32(p, end, bad) \
  131. ceph_decode_skip_n(p, end, sizeof(u32), bad)
  132. #define ceph_decode_skip_16(p, end, bad) \
  133. ceph_decode_skip_n(p, end, sizeof(u16), bad)
  134. #define ceph_decode_skip_8(p, end, bad) \
  135. ceph_decode_skip_n(p, end, sizeof(u8), bad)
  136. #define ceph_decode_skip_string(p, end, bad) \
  137. do { \
  138. u32 len; \
  139. \
  140. ceph_decode_32_safe(p, end, len, bad); \
  141. ceph_decode_skip_n(p, end, len, bad); \
  142. } while (0)
  143. #define ceph_decode_skip_set(p, end, type, bad) \
  144. do { \
  145. u32 len; \
  146. \
  147. ceph_decode_32_safe(p, end, len, bad); \
  148. while (len--) \
  149. ceph_decode_skip_##type(p, end, bad); \
  150. } while (0)
  151. #define ceph_decode_skip_map(p, end, ktype, vtype, bad) \
  152. do { \
  153. u32 len; \
  154. \
  155. ceph_decode_32_safe(p, end, len, bad); \
  156. while (len--) { \
  157. ceph_decode_skip_##ktype(p, end, bad); \
  158. ceph_decode_skip_##vtype(p, end, bad); \
  159. } \
  160. } while (0)
  161. #define ceph_decode_skip_map_of_map(p, end, ktype1, ktype2, vtype2, bad) \
  162. do { \
  163. u32 len; \
  164. \
  165. ceph_decode_32_safe(p, end, len, bad); \
  166. while (len--) { \
  167. ceph_decode_skip_##ktype1(p, end, bad); \
  168. ceph_decode_skip_map(p, end, ktype2, vtype2, bad); \
  169. } \
  170. } while (0)
  171. /*
  172. * struct ceph_timespec <-> struct timespec64
  173. */
  174. static inline void ceph_decode_timespec64(struct timespec64 *ts,
  175. const struct ceph_timespec *tv)
  176. {
  177. /*
  178. * This will still overflow in year 2106. We could extend
  179. * the protocol to steal two more bits from tv_nsec to
  180. * add three more 136 year epochs after that the way ext4
  181. * does if necessary.
  182. */
  183. ts->tv_sec = (time64_t)le32_to_cpu(tv->tv_sec);
  184. ts->tv_nsec = (long)le32_to_cpu(tv->tv_nsec);
  185. }
  186. static inline void ceph_encode_timespec64(struct ceph_timespec *tv,
  187. const struct timespec64 *ts)
  188. {
  189. tv->tv_sec = cpu_to_le32((u32)ts->tv_sec);
  190. tv->tv_nsec = cpu_to_le32((u32)ts->tv_nsec);
  191. }
  192. /*
  193. * sockaddr_storage <-> ceph_sockaddr
  194. */
  195. #define CEPH_ENTITY_ADDR_TYPE_NONE 0
  196. #define CEPH_ENTITY_ADDR_TYPE_LEGACY __cpu_to_le32(1)
  197. #define CEPH_ENTITY_ADDR_TYPE_MSGR2 __cpu_to_le32(2)
  198. #define CEPH_ENTITY_ADDR_TYPE_ANY __cpu_to_le32(3)
  199. static inline void ceph_encode_banner_addr(struct ceph_entity_addr *a)
  200. {
  201. __be16 ss_family = htons(a->in_addr.ss_family);
  202. a->in_addr.ss_family = *(__u16 *)&ss_family;
  203. /* Banner addresses require TYPE_NONE */
  204. a->type = CEPH_ENTITY_ADDR_TYPE_NONE;
  205. }
  206. static inline void ceph_decode_banner_addr(struct ceph_entity_addr *a)
  207. {
  208. __be16 ss_family = *(__be16 *)&a->in_addr.ss_family;
  209. a->in_addr.ss_family = ntohs(ss_family);
  210. WARN_ON(a->in_addr.ss_family == 512);
  211. a->type = CEPH_ENTITY_ADDR_TYPE_LEGACY;
  212. }
  213. extern int ceph_decode_entity_addr(void **p, void *end,
  214. struct ceph_entity_addr *addr);
  215. int ceph_decode_entity_addrvec(void **p, void *end, bool msgr2,
  216. struct ceph_entity_addr *addr);
  217. int ceph_entity_addr_encoding_len(const struct ceph_entity_addr *addr);
  218. void ceph_encode_entity_addr(void **p, const struct ceph_entity_addr *addr);
  219. /*
  220. * encoders
  221. */
  222. static inline void ceph_encode_64(void **p, u64 v)
  223. {
  224. put_unaligned_le64(v, (__le64 *)*p);
  225. *p += sizeof(u64);
  226. }
  227. static inline void ceph_encode_32(void **p, u32 v)
  228. {
  229. put_unaligned_le32(v, (__le32 *)*p);
  230. *p += sizeof(u32);
  231. }
  232. static inline void ceph_encode_16(void **p, u16 v)
  233. {
  234. put_unaligned_le16(v, (__le16 *)*p);
  235. *p += sizeof(u16);
  236. }
  237. static inline void ceph_encode_8(void **p, u8 v)
  238. {
  239. *(u8 *)*p = v;
  240. (*p)++;
  241. }
  242. static inline void ceph_encode_copy(void **p, const void *s, int len)
  243. {
  244. memcpy(*p, s, len);
  245. *p += len;
  246. }
  247. /*
  248. * filepath, string encoders
  249. */
  250. static inline void ceph_encode_filepath(void **p, void *end,
  251. u64 ino, const char *path)
  252. {
  253. u32 len = path ? strlen(path) : 0;
  254. BUG_ON(*p + 1 + sizeof(ino) + sizeof(len) + len > end);
  255. ceph_encode_8(p, 1);
  256. ceph_encode_64(p, ino);
  257. ceph_encode_32(p, len);
  258. if (len)
  259. memcpy(*p, path, len);
  260. *p += len;
  261. }
  262. static inline void ceph_encode_string(void **p, void *end,
  263. const char *s, u32 len)
  264. {
  265. BUG_ON(*p + sizeof(len) + len > end);
  266. ceph_encode_32(p, len);
  267. if (len)
  268. memcpy(*p, s, len);
  269. *p += len;
  270. }
  271. /*
  272. * version and length starting block encoders/decoders
  273. */
  274. /* current code version (u8) + compat code version (u8) + len of struct (u32) */
  275. #define CEPH_ENCODING_START_BLK_LEN 6
  276. /**
  277. * ceph_start_encoding - start encoding block
  278. * @struct_v: current (code) version of the encoding
  279. * @struct_compat: oldest code version that can decode it
  280. * @struct_len: length of struct encoding
  281. */
  282. static inline void ceph_start_encoding(void **p, u8 struct_v, u8 struct_compat,
  283. u32 struct_len)
  284. {
  285. ceph_encode_8(p, struct_v);
  286. ceph_encode_8(p, struct_compat);
  287. ceph_encode_32(p, struct_len);
  288. }
  289. /**
  290. * ceph_start_decoding - start decoding block
  291. * @v: current version of the encoding that the code supports
  292. * @name: name of the struct (free-form)
  293. * @struct_v: out param for the encoding version
  294. * @struct_len: out param for the length of struct encoding
  295. *
  296. * Validates the length of struct encoding, so unsafe ceph_decode_*
  297. * variants can be used for decoding.
  298. */
  299. static inline int ceph_start_decoding(void **p, void *end, u8 v,
  300. const char *name, u8 *struct_v,
  301. u32 *struct_len)
  302. {
  303. u8 struct_compat;
  304. ceph_decode_need(p, end, CEPH_ENCODING_START_BLK_LEN, bad);
  305. *struct_v = ceph_decode_8(p);
  306. struct_compat = ceph_decode_8(p);
  307. if (v < struct_compat) {
  308. pr_warn("got struct_v %d struct_compat %d > %d of %s\n",
  309. *struct_v, struct_compat, v, name);
  310. return -EINVAL;
  311. }
  312. *struct_len = ceph_decode_32(p);
  313. ceph_decode_need(p, end, *struct_len, bad);
  314. return 0;
  315. bad:
  316. return -ERANGE;
  317. }
  318. #define ceph_encode_need(p, end, n, bad) \
  319. do { \
  320. if (!likely(ceph_has_room(p, end, n))) \
  321. goto bad; \
  322. } while (0)
  323. #define ceph_encode_64_safe(p, end, v, bad) \
  324. do { \
  325. ceph_encode_need(p, end, sizeof(u64), bad); \
  326. ceph_encode_64(p, v); \
  327. } while (0)
  328. #define ceph_encode_32_safe(p, end, v, bad) \
  329. do { \
  330. ceph_encode_need(p, end, sizeof(u32), bad); \
  331. ceph_encode_32(p, v); \
  332. } while (0)
  333. #define ceph_encode_16_safe(p, end, v, bad) \
  334. do { \
  335. ceph_encode_need(p, end, sizeof(u16), bad); \
  336. ceph_encode_16(p, v); \
  337. } while (0)
  338. #define ceph_encode_8_safe(p, end, v, bad) \
  339. do { \
  340. ceph_encode_need(p, end, sizeof(u8), bad); \
  341. ceph_encode_8(p, v); \
  342. } while (0)
  343. #define ceph_encode_copy_safe(p, end, pv, n, bad) \
  344. do { \
  345. ceph_encode_need(p, end, n, bad); \
  346. ceph_encode_copy(p, pv, n); \
  347. } while (0)
  348. #define ceph_encode_string_safe(p, end, s, n, bad) \
  349. do { \
  350. ceph_encode_need(p, end, n, bad); \
  351. ceph_encode_string(p, end, s, n); \
  352. } while (0)
  353. #endif