1 // SPDX-License-Identifier: GPL-2.0 2 3 #include <linux/ceph/decode.h> 4 5 static int 6 ceph_decode_entity_addr_versioned(void **p, void *end, 7 struct ceph_entity_addr *addr) 8 { 9 int ret; 10 u8 struct_v; 11 u32 struct_len, addr_len; 12 void *struct_end; 13 14 ret = ceph_start_decoding(p, end, 1, "entity_addr_t", &struct_v, 15 &struct_len); 16 if (ret) 17 goto bad; 18 19 ret = -EINVAL; 20 struct_end = *p + struct_len; 21 22 ceph_decode_copy_safe(p, end, &addr->type, sizeof(addr->type), bad); 23 24 ceph_decode_copy_safe(p, end, &addr->nonce, sizeof(addr->nonce), bad); 25 26 ceph_decode_32_safe(p, end, addr_len, bad); 27 if (addr_len > sizeof(addr->in_addr)) 28 goto bad; 29 30 memset(&addr->in_addr, 0, sizeof(addr->in_addr)); 31 if (addr_len) { 32 ceph_decode_copy_safe(p, end, &addr->in_addr, addr_len, bad); 33 34 addr->in_addr.ss_family = 35 le16_to_cpu((__force __le16)addr->in_addr.ss_family); 36 } 37 38 /* Advance past anything the client doesn't yet understand */ 39 *p = struct_end; 40 ret = 0; 41 bad: 42 return ret; 43 } 44 45 static int 46 ceph_decode_entity_addr_legacy(void **p, void *end, 47 struct ceph_entity_addr *addr) 48 { 49 int ret = -EINVAL; 50 51 /* Skip rest of type field */ 52 ceph_decode_skip_n(p, end, 3, bad); 53 54 /* 55 * Clients that don't support ADDR2 always send TYPE_NONE, change it 56 * to TYPE_LEGACY for forward compatibility. 57 */ 58 addr->type = CEPH_ENTITY_ADDR_TYPE_LEGACY; 59 ceph_decode_copy_safe(p, end, &addr->nonce, sizeof(addr->nonce), bad); 60 memset(&addr->in_addr, 0, sizeof(addr->in_addr)); 61 ceph_decode_copy_safe(p, end, &addr->in_addr, 62 sizeof(addr->in_addr), bad); 63 addr->in_addr.ss_family = 64 be16_to_cpu((__force __be16)addr->in_addr.ss_family); 65 ret = 0; 66 bad: 67 return ret; 68 } 69 70 int 71 ceph_decode_entity_addr(void **p, void *end, struct ceph_entity_addr *addr) 72 { 73 u8 marker; 74 75 ceph_decode_8_safe(p, end, marker, bad); 76 if (marker == 1) 77 return ceph_decode_entity_addr_versioned(p, end, addr); 78 else if (marker == 0) 79 return ceph_decode_entity_addr_legacy(p, end, addr); 80 bad: 81 return -EINVAL; 82 } 83 EXPORT_SYMBOL(ceph_decode_entity_addr); 84 85