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 #define ceph_decode_need(p, end, n, bad) \ 49 do { \ 50 if (unlikely(*(p) + (n) > (end))) \ 51 goto bad; \ 52 } while (0) 53 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 75 #define ceph_decode_copy_safe(p, end, pv, n, bad) \ 76 do { \ 77 ceph_decode_need(p, end, n, bad); \ 78 ceph_decode_copy(p, pv, n); \ 79 } while (0) 80 81 /* 82 * struct ceph_timespec <-> struct timespec 83 */ 84 static inline void ceph_decode_timespec(struct timespec *ts, 85 const struct ceph_timespec *tv) 86 { 87 ts->tv_sec = le32_to_cpu(tv->tv_sec); 88 ts->tv_nsec = le32_to_cpu(tv->tv_nsec); 89 } 90 static inline void ceph_encode_timespec(struct ceph_timespec *tv, 91 const struct timespec *ts) 92 { 93 tv->tv_sec = cpu_to_le32(ts->tv_sec); 94 tv->tv_nsec = cpu_to_le32(ts->tv_nsec); 95 } 96 97 /* 98 * sockaddr_storage <-> ceph_sockaddr 99 */ 100 static inline void ceph_encode_addr(struct ceph_entity_addr *a) 101 { 102 __be16 ss_family = htons(a->in_addr.ss_family); 103 a->in_addr.ss_family = *(__u16 *)&ss_family; 104 } 105 static inline void ceph_decode_addr(struct ceph_entity_addr *a) 106 { 107 __be16 ss_family = *(__be16 *)&a->in_addr.ss_family; 108 a->in_addr.ss_family = ntohs(ss_family); 109 WARN_ON(a->in_addr.ss_family == 512); 110 } 111 112 /* 113 * encoders 114 */ 115 static inline void ceph_encode_64(void **p, u64 v) 116 { 117 put_unaligned_le64(v, (__le64 *)*p); 118 *p += sizeof(u64); 119 } 120 static inline void ceph_encode_32(void **p, u32 v) 121 { 122 put_unaligned_le32(v, (__le32 *)*p); 123 *p += sizeof(u32); 124 } 125 static inline void ceph_encode_16(void **p, u16 v) 126 { 127 put_unaligned_le16(v, (__le16 *)*p); 128 *p += sizeof(u16); 129 } 130 static inline void ceph_encode_8(void **p, u8 v) 131 { 132 *(u8 *)*p = v; 133 (*p)++; 134 } 135 static inline void ceph_encode_copy(void **p, const void *s, int len) 136 { 137 memcpy(*p, s, len); 138 *p += len; 139 } 140 141 /* 142 * filepath, string encoders 143 */ 144 static inline void ceph_encode_filepath(void **p, void *end, 145 u64 ino, const char *path) 146 { 147 u32 len = path ? strlen(path) : 0; 148 BUG_ON(*p + sizeof(ino) + sizeof(len) + len > end); 149 ceph_encode_8(p, 1); 150 ceph_encode_64(p, ino); 151 ceph_encode_32(p, len); 152 if (len) 153 memcpy(*p, path, len); 154 *p += len; 155 } 156 157 static inline void ceph_encode_string(void **p, void *end, 158 const char *s, u32 len) 159 { 160 BUG_ON(*p + sizeof(len) + len > end); 161 ceph_encode_32(p, len); 162 if (len) 163 memcpy(*p, s, len); 164 *p += len; 165 } 166 167 #define ceph_encode_need(p, end, n, bad) \ 168 do { \ 169 if (unlikely(*(p) + (n) > (end))) \ 170 goto bad; \ 171 } while (0) 172 173 #define ceph_encode_64_safe(p, end, v, bad) \ 174 do { \ 175 ceph_encode_need(p, end, sizeof(u64), bad); \ 176 ceph_encode_64(p, v); \ 177 } while (0) 178 #define ceph_encode_32_safe(p, end, v, bad) \ 179 do { \ 180 ceph_encode_need(p, end, sizeof(u32), bad); \ 181 ceph_encode_32(p, v); \ 182 } while (0) 183 #define ceph_encode_16_safe(p, end, v, bad) \ 184 do { \ 185 ceph_encode_need(p, end, sizeof(u16), bad); \ 186 ceph_encode_16(p, v); \ 187 } while (0) 188 189 #define ceph_encode_copy_safe(p, end, pv, n, bad) \ 190 do { \ 191 ceph_encode_need(p, end, n, bad); \ 192 ceph_encode_copy(p, pv, n); \ 193 } while (0) 194 #define ceph_encode_string_safe(p, end, s, n, bad) \ 195 do { \ 196 ceph_encode_need(p, end, n, bad); \ 197 ceph_encode_string(p, end, s, n); \ 198 } while (0) 199 200 201 #endif 202