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