18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci 38c2ecf20Sopenharmony_ci#include <linux/ceph/decode.h> 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_cistatic int 68c2ecf20Sopenharmony_ciceph_decode_entity_addr_versioned(void **p, void *end, 78c2ecf20Sopenharmony_ci struct ceph_entity_addr *addr) 88c2ecf20Sopenharmony_ci{ 98c2ecf20Sopenharmony_ci int ret; 108c2ecf20Sopenharmony_ci u8 struct_v; 118c2ecf20Sopenharmony_ci u32 struct_len, addr_len; 128c2ecf20Sopenharmony_ci void *struct_end; 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci ret = ceph_start_decoding(p, end, 1, "entity_addr_t", &struct_v, 158c2ecf20Sopenharmony_ci &struct_len); 168c2ecf20Sopenharmony_ci if (ret) 178c2ecf20Sopenharmony_ci goto bad; 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci ret = -EINVAL; 208c2ecf20Sopenharmony_ci struct_end = *p + struct_len; 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci ceph_decode_copy_safe(p, end, &addr->type, sizeof(addr->type), bad); 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci ceph_decode_copy_safe(p, end, &addr->nonce, sizeof(addr->nonce), bad); 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci ceph_decode_32_safe(p, end, addr_len, bad); 278c2ecf20Sopenharmony_ci if (addr_len > sizeof(addr->in_addr)) 288c2ecf20Sopenharmony_ci goto bad; 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci memset(&addr->in_addr, 0, sizeof(addr->in_addr)); 318c2ecf20Sopenharmony_ci if (addr_len) { 328c2ecf20Sopenharmony_ci ceph_decode_copy_safe(p, end, &addr->in_addr, addr_len, bad); 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci addr->in_addr.ss_family = 358c2ecf20Sopenharmony_ci le16_to_cpu((__force __le16)addr->in_addr.ss_family); 368c2ecf20Sopenharmony_ci } 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci /* Advance past anything the client doesn't yet understand */ 398c2ecf20Sopenharmony_ci *p = struct_end; 408c2ecf20Sopenharmony_ci ret = 0; 418c2ecf20Sopenharmony_cibad: 428c2ecf20Sopenharmony_ci return ret; 438c2ecf20Sopenharmony_ci} 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_cistatic int 468c2ecf20Sopenharmony_ciceph_decode_entity_addr_legacy(void **p, void *end, 478c2ecf20Sopenharmony_ci struct ceph_entity_addr *addr) 488c2ecf20Sopenharmony_ci{ 498c2ecf20Sopenharmony_ci int ret = -EINVAL; 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci /* Skip rest of type field */ 528c2ecf20Sopenharmony_ci ceph_decode_skip_n(p, end, 3, bad); 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci /* 558c2ecf20Sopenharmony_ci * Clients that don't support ADDR2 always send TYPE_NONE, change it 568c2ecf20Sopenharmony_ci * to TYPE_LEGACY for forward compatibility. 578c2ecf20Sopenharmony_ci */ 588c2ecf20Sopenharmony_ci addr->type = CEPH_ENTITY_ADDR_TYPE_LEGACY; 598c2ecf20Sopenharmony_ci ceph_decode_copy_safe(p, end, &addr->nonce, sizeof(addr->nonce), bad); 608c2ecf20Sopenharmony_ci memset(&addr->in_addr, 0, sizeof(addr->in_addr)); 618c2ecf20Sopenharmony_ci ceph_decode_copy_safe(p, end, &addr->in_addr, 628c2ecf20Sopenharmony_ci sizeof(addr->in_addr), bad); 638c2ecf20Sopenharmony_ci addr->in_addr.ss_family = 648c2ecf20Sopenharmony_ci be16_to_cpu((__force __be16)addr->in_addr.ss_family); 658c2ecf20Sopenharmony_ci ret = 0; 668c2ecf20Sopenharmony_cibad: 678c2ecf20Sopenharmony_ci return ret; 688c2ecf20Sopenharmony_ci} 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ciint 718c2ecf20Sopenharmony_ciceph_decode_entity_addr(void **p, void *end, struct ceph_entity_addr *addr) 728c2ecf20Sopenharmony_ci{ 738c2ecf20Sopenharmony_ci u8 marker; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci ceph_decode_8_safe(p, end, marker, bad); 768c2ecf20Sopenharmony_ci if (marker == 1) 778c2ecf20Sopenharmony_ci return ceph_decode_entity_addr_versioned(p, end, addr); 788c2ecf20Sopenharmony_ci else if (marker == 0) 798c2ecf20Sopenharmony_ci return ceph_decode_entity_addr_legacy(p, end, addr); 808c2ecf20Sopenharmony_cibad: 818c2ecf20Sopenharmony_ci return -EINVAL; 828c2ecf20Sopenharmony_ci} 838c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ceph_decode_entity_addr); 848c2ecf20Sopenharmony_ci 85