decode.h 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. #ifndef __CEPH_DECODE_H
  2. #define __CEPH_DECODE_H
  3. #include <linux/err.h>
  4. #include <linux/bug.h>
  5. #include <linux/time.h>
  6. #include <asm/unaligned.h>
  7. #include <linux/ceph/types.h>
  8. /*
  9. * in all cases,
  10. * void **p pointer to position pointer
  11. * void *end pointer to end of buffer (last byte + 1)
  12. */
  13. static inline u64 ceph_decode_64(void **p)
  14. {
  15. u64 v = get_unaligned_le64(*p);
  16. *p += sizeof(u64);
  17. return v;
  18. }
  19. static inline u32 ceph_decode_32(void **p)
  20. {
  21. u32 v = get_unaligned_le32(*p);
  22. *p += sizeof(u32);
  23. return v;
  24. }
  25. static inline u16 ceph_decode_16(void **p)
  26. {
  27. u16 v = get_unaligned_le16(*p);
  28. *p += sizeof(u16);
  29. return v;
  30. }
  31. static inline u8 ceph_decode_8(void **p)
  32. {
  33. u8 v = *(u8 *)*p;
  34. (*p)++;
  35. return v;
  36. }
  37. static inline void ceph_decode_copy(void **p, void *pv, size_t n)
  38. {
  39. memcpy(pv, *p, n);
  40. *p += n;
  41. }
  42. /*
  43. * bounds check input.
  44. */
  45. static inline int ceph_has_room(void **p, void *end, size_t n)
  46. {
  47. return end >= *p && n <= end - *p;
  48. }
  49. #define ceph_decode_need(p, end, n, bad) \
  50. do { \
  51. if (!likely(ceph_has_room(p, end, n))) \
  52. goto bad; \
  53. } while (0)
  54. #define ceph_decode_64_safe(p, end, v, bad) \
  55. do { \
  56. ceph_decode_need(p, end, sizeof(u64), bad); \
  57. v = ceph_decode_64(p); \
  58. } while (0)
  59. #define ceph_decode_32_safe(p, end, v, bad) \
  60. do { \
  61. ceph_decode_need(p, end, sizeof(u32), bad); \
  62. v = ceph_decode_32(p); \
  63. } while (0)
  64. #define ceph_decode_16_safe(p, end, v, bad) \
  65. do { \
  66. ceph_decode_need(p, end, sizeof(u16), bad); \
  67. v = ceph_decode_16(p); \
  68. } while (0)
  69. #define ceph_decode_8_safe(p, end, v, bad) \
  70. do { \
  71. ceph_decode_need(p, end, sizeof(u8), bad); \
  72. v = ceph_decode_8(p); \
  73. } while (0)
  74. #define ceph_decode_copy_safe(p, end, pv, n, bad) \
  75. do { \
  76. ceph_decode_need(p, end, n, bad); \
  77. ceph_decode_copy(p, pv, n); \
  78. } while (0)
  79. /*
  80. * Allocate a buffer big enough to hold the wire-encoded string, and
  81. * decode the string into it. The resulting string will always be
  82. * terminated with '\0'. If successful, *p will be advanced
  83. * past the decoded data. Also, if lenp is not a null pointer, the
  84. * length (not including the terminating '\0') will be recorded in
  85. * *lenp. Note that a zero-length string is a valid return value.
  86. *
  87. * Returns a pointer to the newly-allocated string buffer, or a
  88. * pointer-coded errno if an error occurs. Neither *p nor *lenp
  89. * will have been updated if an error is returned.
  90. *
  91. * There are two possible failures:
  92. * - converting the string would require accessing memory at or
  93. * beyond the "end" pointer provided (-ERANGE)
  94. * - memory could not be allocated for the result (-ENOMEM)
  95. */
  96. static inline char *ceph_extract_encoded_string(void **p, void *end,
  97. size_t *lenp, gfp_t gfp)
  98. {
  99. u32 len;
  100. void *sp = *p;
  101. char *buf;
  102. ceph_decode_32_safe(&sp, end, len, bad);
  103. if (!ceph_has_room(&sp, end, len))
  104. goto bad;
  105. buf = kmalloc(len + 1, gfp);
  106. if (!buf)
  107. return ERR_PTR(-ENOMEM);
  108. if (len)
  109. memcpy(buf, sp, len);
  110. buf[len] = '\0';
  111. *p = (char *) *p + sizeof (u32) + len;
  112. if (lenp)
  113. *lenp = (size_t) len;
  114. return buf;
  115. bad:
  116. return ERR_PTR(-ERANGE);
  117. }
  118. /*
  119. * struct ceph_timespec <-> struct timespec
  120. */
  121. static inline void ceph_decode_timespec(struct timespec *ts,
  122. const struct ceph_timespec *tv)
  123. {
  124. ts->tv_sec = (__kernel_time_t)le32_to_cpu(tv->tv_sec);
  125. ts->tv_nsec = (long)le32_to_cpu(tv->tv_nsec);
  126. }
  127. static inline void ceph_encode_timespec(struct ceph_timespec *tv,
  128. const struct timespec *ts)
  129. {
  130. tv->tv_sec = cpu_to_le32((u32)ts->tv_sec);
  131. tv->tv_nsec = cpu_to_le32((u32)ts->tv_nsec);
  132. }
  133. /*
  134. * sockaddr_storage <-> ceph_sockaddr
  135. */
  136. static inline void ceph_encode_addr(struct ceph_entity_addr *a)
  137. {
  138. __be16 ss_family = htons(a->in_addr.ss_family);
  139. a->in_addr.ss_family = *(__u16 *)&ss_family;
  140. }
  141. static inline void ceph_decode_addr(struct ceph_entity_addr *a)
  142. {
  143. __be16 ss_family = *(__be16 *)&a->in_addr.ss_family;
  144. a->in_addr.ss_family = ntohs(ss_family);
  145. WARN_ON(a->in_addr.ss_family == 512);
  146. }
  147. /*
  148. * encoders
  149. */
  150. static inline void ceph_encode_64(void **p, u64 v)
  151. {
  152. put_unaligned_le64(v, (__le64 *)*p);
  153. *p += sizeof(u64);
  154. }
  155. static inline void ceph_encode_32(void **p, u32 v)
  156. {
  157. put_unaligned_le32(v, (__le32 *)*p);
  158. *p += sizeof(u32);
  159. }
  160. static inline void ceph_encode_16(void **p, u16 v)
  161. {
  162. put_unaligned_le16(v, (__le16 *)*p);
  163. *p += sizeof(u16);
  164. }
  165. static inline void ceph_encode_8(void **p, u8 v)
  166. {
  167. *(u8 *)*p = v;
  168. (*p)++;
  169. }
  170. static inline void ceph_encode_copy(void **p, const void *s, int len)
  171. {
  172. memcpy(*p, s, len);
  173. *p += len;
  174. }
  175. /*
  176. * filepath, string encoders
  177. */
  178. static inline void ceph_encode_filepath(void **p, void *end,
  179. u64 ino, const char *path)
  180. {
  181. u32 len = path ? strlen(path) : 0;
  182. BUG_ON(*p + 1 + sizeof(ino) + sizeof(len) + len > end);
  183. ceph_encode_8(p, 1);
  184. ceph_encode_64(p, ino);
  185. ceph_encode_32(p, len);
  186. if (len)
  187. memcpy(*p, path, len);
  188. *p += len;
  189. }
  190. static inline void ceph_encode_string(void **p, void *end,
  191. const char *s, u32 len)
  192. {
  193. BUG_ON(*p + sizeof(len) + len > end);
  194. ceph_encode_32(p, len);
  195. if (len)
  196. memcpy(*p, s, len);
  197. *p += len;
  198. }
  199. #define ceph_encode_need(p, end, n, bad) \
  200. do { \
  201. if (!likely(ceph_has_room(p, end, n))) \
  202. goto bad; \
  203. } while (0)
  204. #define ceph_encode_64_safe(p, end, v, bad) \
  205. do { \
  206. ceph_encode_need(p, end, sizeof(u64), bad); \
  207. ceph_encode_64(p, v); \
  208. } while (0)
  209. #define ceph_encode_32_safe(p, end, v, bad) \
  210. do { \
  211. ceph_encode_need(p, end, sizeof(u32), bad); \
  212. ceph_encode_32(p, v); \
  213. } while (0)
  214. #define ceph_encode_16_safe(p, end, v, bad) \
  215. do { \
  216. ceph_encode_need(p, end, sizeof(u16), bad); \
  217. ceph_encode_16(p, v); \
  218. } while (0)
  219. #define ceph_encode_8_safe(p, end, v, bad) \
  220. do { \
  221. ceph_encode_need(p, end, sizeof(u8), bad); \
  222. ceph_encode_8(p, v); \
  223. } while (0)
  224. #define ceph_encode_copy_safe(p, end, pv, n, bad) \
  225. do { \
  226. ceph_encode_need(p, end, n, bad); \
  227. ceph_encode_copy(p, pv, n); \
  228. } while (0)
  229. #define ceph_encode_string_safe(p, end, s, n, bad) \
  230. do { \
  231. ceph_encode_need(p, end, n, bad); \
  232. ceph_encode_string(p, end, s, n); \
  233. } while (0)
  234. #endif