1 // SPDX-License-Identifier: GPL-2.0 2 #include <linux/ceph/ceph_debug.h> 3 4 #include <linux/ceph/decode.h> 5 6 static int 7 ceph_decode_entity_addr_versioned(void **p, void *end, 8 struct ceph_entity_addr *addr) 9 { 10 int ret; 11 u8 struct_v; 12 u32 struct_len, addr_len; 13 void *struct_end; 14 15 ret = ceph_start_decoding(p, end, 1, "entity_addr_t", &struct_v, 16 &struct_len); 17 if (ret) 18 goto bad; 19 20 ret = -EINVAL; 21 struct_end = *p + struct_len; 22 23 ceph_decode_copy_safe(p, end, &addr->type, sizeof(addr->type), bad); 24 25 ceph_decode_copy_safe(p, end, &addr->nonce, sizeof(addr->nonce), bad); 26 27 ceph_decode_32_safe(p, end, addr_len, bad); 28 if (addr_len > sizeof(addr->in_addr)) 29 goto bad; 30 31 memset(&addr->in_addr, 0, sizeof(addr->in_addr)); 32 if (addr_len) { 33 ceph_decode_copy_safe(p, end, &addr->in_addr, addr_len, bad); 34 35 addr->in_addr.ss_family = 36 le16_to_cpu((__force __le16)addr->in_addr.ss_family); 37 } 38 39 /* Advance past anything the client doesn't yet understand */ 40 *p = struct_end; 41 ret = 0; 42 bad: 43 return ret; 44 } 45 46 static int 47 ceph_decode_entity_addr_legacy(void **p, void *end, 48 struct ceph_entity_addr *addr) 49 { 50 int ret = -EINVAL; 51 52 /* Skip rest of type field */ 53 ceph_decode_skip_n(p, end, 3, bad); 54 55 /* 56 * Clients that don't support ADDR2 always send TYPE_NONE, change it 57 * to TYPE_LEGACY for forward compatibility. 58 */ 59 addr->type = CEPH_ENTITY_ADDR_TYPE_LEGACY; 60 ceph_decode_copy_safe(p, end, &addr->nonce, sizeof(addr->nonce), bad); 61 memset(&addr->in_addr, 0, sizeof(addr->in_addr)); 62 ceph_decode_copy_safe(p, end, &addr->in_addr, 63 sizeof(addr->in_addr), bad); 64 addr->in_addr.ss_family = 65 be16_to_cpu((__force __be16)addr->in_addr.ss_family); 66 ret = 0; 67 bad: 68 return ret; 69 } 70 71 int 72 ceph_decode_entity_addr(void **p, void *end, struct ceph_entity_addr *addr) 73 { 74 u8 marker; 75 76 ceph_decode_8_safe(p, end, marker, bad); 77 if (marker == 1) 78 return ceph_decode_entity_addr_versioned(p, end, addr); 79 else if (marker == 0) 80 return ceph_decode_entity_addr_legacy(p, end, addr); 81 bad: 82 return -EINVAL; 83 } 84 EXPORT_SYMBOL(ceph_decode_entity_addr); 85 86 /* 87 * Return addr of desired type (MSGR2 or LEGACY) or error. 88 * Make sure there is only one match. 89 * 90 * Assume encoding with MSG_ADDR2. 91 */ 92 int ceph_decode_entity_addrvec(void **p, void *end, bool msgr2, 93 struct ceph_entity_addr *addr) 94 { 95 __le32 my_type = msgr2 ? CEPH_ENTITY_ADDR_TYPE_MSGR2 : 96 CEPH_ENTITY_ADDR_TYPE_LEGACY; 97 struct ceph_entity_addr tmp_addr; 98 int addr_cnt; 99 bool found; 100 u8 marker; 101 int ret; 102 int i; 103 104 ceph_decode_8_safe(p, end, marker, e_inval); 105 if (marker != 2) { 106 pr_err("bad addrvec marker %d\n", marker); 107 return -EINVAL; 108 } 109 110 ceph_decode_32_safe(p, end, addr_cnt, e_inval); 111 112 found = false; 113 for (i = 0; i < addr_cnt; i++) { 114 ret = ceph_decode_entity_addr(p, end, &tmp_addr); 115 if (ret) 116 return ret; 117 118 if (tmp_addr.type == my_type) { 119 if (found) { 120 pr_err("another match of type %d in addrvec\n", 121 le32_to_cpu(my_type)); 122 return -EINVAL; 123 } 124 125 memcpy(addr, &tmp_addr, sizeof(*addr)); 126 found = true; 127 } 128 } 129 if (!found && addr_cnt != 0) { 130 pr_err("no match of type %d in addrvec\n", 131 le32_to_cpu(my_type)); 132 return -ENOENT; 133 } 134 135 return 0; 136 137 e_inval: 138 return -EINVAL; 139 } 140 EXPORT_SYMBOL(ceph_decode_entity_addrvec); 141