1 #ifndef __CEPH_DECODE_H 2 #define __CEPH_DECODE_H 3 4 #include <asm/unaligned.h> 5 #include <linux/time.h> 6 7 #include "types.h" 8 9 /* 10 * in all cases, 11 * void **p pointer to position pointer 12 * void *end pointer to end of buffer (last byte + 1) 13 */ 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 /* 46 * bounds check input. 47 */ 48 static inline int ceph_has_room(void **p, void *end, size_t n) 49 { 50 return end >= *p && n <= end - *p; 51 } 52 53 #define ceph_decode_need(p, end, n, bad) \ 54 do { \ 55 if (!likely(ceph_has_room(p, end, n))) \ 56 goto bad; \ 57 } while (0) 58 59 #define ceph_decode_64_safe(p, end, v, bad) \ 60 do { \ 61 ceph_decode_need(p, end, sizeof(u64), bad); \ 62 v = ceph_decode_64(p); \ 63 } while (0) 64 #define ceph_decode_32_safe(p, end, v, bad) \ 65 do { \ 66 ceph_decode_need(p, end, sizeof(u32), bad); \ 67 v = ceph_decode_32(p); \ 68 } while (0) 69 #define ceph_decode_16_safe(p, end, v, bad) \ 70 do { \ 71 ceph_decode_need(p, end, sizeof(u16), bad); \ 72 v = ceph_decode_16(p); \ 73 } while (0) 74 #define ceph_decode_8_safe(p, end, v, bad) \ 75 do { \ 76 ceph_decode_need(p, end, sizeof(u8), bad); \ 77 v = ceph_decode_8(p); \ 78 } while (0) 79 80 #define ceph_decode_copy_safe(p, end, pv, n, bad) \ 81 do { \ 82 ceph_decode_need(p, end, n, bad); \ 83 ceph_decode_copy(p, pv, n); \ 84 } while (0) 85 86 /* 87 * struct ceph_timespec <-> struct timespec 88 */ 89 static inline void ceph_decode_timespec(struct timespec *ts, 90 const struct ceph_timespec *tv) 91 { 92 ts->tv_sec = le32_to_cpu(tv->tv_sec); 93 ts->tv_nsec = le32_to_cpu(tv->tv_nsec); 94 } 95 static inline void ceph_encode_timespec(struct ceph_timespec *tv, 96 const struct timespec *ts) 97 { 98 tv->tv_sec = cpu_to_le32(ts->tv_sec); 99 tv->tv_nsec = cpu_to_le32(ts->tv_nsec); 100 } 101 102 /* 103 * sockaddr_storage <-> ceph_sockaddr 104 */ 105 static inline void ceph_encode_addr(struct ceph_entity_addr *a) 106 { 107 __be16 ss_family = htons(a->in_addr.ss_family); 108 a->in_addr.ss_family = *(__u16 *)&ss_family; 109 } 110 static inline void ceph_decode_addr(struct ceph_entity_addr *a) 111 { 112 __be16 ss_family = *(__be16 *)&a->in_addr.ss_family; 113 a->in_addr.ss_family = ntohs(ss_family); 114 WARN_ON(a->in_addr.ss_family == 512); 115 } 116 117 /* 118 * encoders 119 */ 120 static inline void ceph_encode_64(void **p, u64 v) 121 { 122 put_unaligned_le64(v, (__le64 *)*p); 123 *p += sizeof(u64); 124 } 125 static inline void ceph_encode_32(void **p, u32 v) 126 { 127 put_unaligned_le32(v, (__le32 *)*p); 128 *p += sizeof(u32); 129 } 130 static inline void ceph_encode_16(void **p, u16 v) 131 { 132 put_unaligned_le16(v, (__le16 *)*p); 133 *p += sizeof(u16); 134 } 135 static inline void ceph_encode_8(void **p, u8 v) 136 { 137 *(u8 *)*p = v; 138 (*p)++; 139 } 140 static inline void ceph_encode_copy(void **p, const void *s, int len) 141 { 142 memcpy(*p, s, len); 143 *p += len; 144 } 145 146 /* 147 * filepath, string encoders 148 */ 149 static inline void ceph_encode_filepath(void **p, void *end, 150 u64 ino, const char *path) 151 { 152 u32 len = path ? strlen(path) : 0; 153 BUG_ON(*p + sizeof(ino) + sizeof(len) + len > end); 154 ceph_encode_8(p, 1); 155 ceph_encode_64(p, ino); 156 ceph_encode_32(p, len); 157 if (len) 158 memcpy(*p, path, len); 159 *p += len; 160 } 161 162 static inline void ceph_encode_string(void **p, void *end, 163 const char *s, u32 len) 164 { 165 BUG_ON(*p + sizeof(len) + len > end); 166 ceph_encode_32(p, len); 167 if (len) 168 memcpy(*p, s, len); 169 *p += len; 170 } 171 172 #define ceph_encode_need(p, end, n, bad) \ 173 do { \ 174 if (!likely(ceph_has_room(p, end, n))) \ 175 goto bad; \ 176 } while (0) 177 178 #define ceph_encode_64_safe(p, end, v, bad) \ 179 do { \ 180 ceph_encode_need(p, end, sizeof(u64), bad); \ 181 ceph_encode_64(p, v); \ 182 } while (0) 183 #define ceph_encode_32_safe(p, end, v, bad) \ 184 do { \ 185 ceph_encode_need(p, end, sizeof(u32), bad); \ 186 ceph_encode_32(p, v); \ 187 } while (0) 188 #define ceph_encode_16_safe(p, end, v, bad) \ 189 do { \ 190 ceph_encode_need(p, end, sizeof(u16), bad); \ 191 ceph_encode_16(p, v); \ 192 } while (0) 193 194 #define ceph_encode_copy_safe(p, end, pv, n, bad) \ 195 do { \ 196 ceph_encode_need(p, end, n, bad); \ 197 ceph_encode_copy(p, pv, n); \ 198 } while (0) 199 #define ceph_encode_string_safe(p, end, s, n, bad) \ 200 do { \ 201 ceph_encode_need(p, end, n, bad); \ 202 ceph_encode_string(p, end, s, n); \ 203 } while (0) 204 205 206 #endif 207