Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.15.
  1// SPDX-License-Identifier: GPL-2.0
  2#include <linux/ceph/ceph_debug.h>
  3
  4#include <linux/inet.h>
  5
  6#include <linux/ceph/decode.h>
  7#include <linux/ceph/messenger.h>  /* for ceph_pr_addr() */
  8
  9static int
 10ceph_decode_entity_addr_versioned(void **p, void *end,
 11				  struct ceph_entity_addr *addr)
 12{
 13	int ret;
 14	u8 struct_v;
 15	u32 struct_len, addr_len;
 16	void *struct_end;
 17
 18	ret = ceph_start_decoding(p, end, 1, "entity_addr_t", &struct_v,
 19				  &struct_len);
 20	if (ret)
 21		goto bad;
 22
 23	ret = -EINVAL;
 24	struct_end = *p + struct_len;
 25
 26	ceph_decode_copy_safe(p, end, &addr->type, sizeof(addr->type), bad);
 27
 28	ceph_decode_copy_safe(p, end, &addr->nonce, sizeof(addr->nonce), bad);
 29
 30	ceph_decode_32_safe(p, end, addr_len, bad);
 31	if (addr_len > sizeof(addr->in_addr))
 32		goto bad;
 33
 34	memset(&addr->in_addr, 0, sizeof(addr->in_addr));
 35	if (addr_len) {
 36		ceph_decode_copy_safe(p, end, &addr->in_addr, addr_len, bad);
 37
 38		addr->in_addr.ss_family =
 39			le16_to_cpu((__force __le16)addr->in_addr.ss_family);
 40	}
 41
 42	/* Advance past anything the client doesn't yet understand */
 43	*p = struct_end;
 44	ret = 0;
 45bad:
 46	return ret;
 47}
 48
 49static int
 50ceph_decode_entity_addr_legacy(void **p, void *end,
 51			       struct ceph_entity_addr *addr)
 52{
 53	int ret = -EINVAL;
 54
 55	/* Skip rest of type field */
 56	ceph_decode_skip_n(p, end, 3, bad);
 57
 58	/*
 59	 * Clients that don't support ADDR2 always send TYPE_NONE, change it
 60	 * to TYPE_LEGACY for forward compatibility.
 61	 */
 62	addr->type = CEPH_ENTITY_ADDR_TYPE_LEGACY;
 63	ceph_decode_copy_safe(p, end, &addr->nonce, sizeof(addr->nonce), bad);
 64	memset(&addr->in_addr, 0, sizeof(addr->in_addr));
 65	ceph_decode_copy_safe(p, end, &addr->in_addr,
 66			      sizeof(addr->in_addr), bad);
 67	addr->in_addr.ss_family =
 68			be16_to_cpu((__force __be16)addr->in_addr.ss_family);
 69	ret = 0;
 70bad:
 71	return ret;
 72}
 73
 74int
 75ceph_decode_entity_addr(void **p, void *end, struct ceph_entity_addr *addr)
 76{
 77	u8 marker;
 78
 79	ceph_decode_8_safe(p, end, marker, bad);
 80	if (marker == 1)
 81		return ceph_decode_entity_addr_versioned(p, end, addr);
 82	else if (marker == 0)
 83		return ceph_decode_entity_addr_legacy(p, end, addr);
 84bad:
 85	return -EINVAL;
 86}
 87EXPORT_SYMBOL(ceph_decode_entity_addr);
 88
 89/*
 90 * Return addr of desired type (MSGR2 or LEGACY) or error.
 91 * Make sure there is only one match.
 92 *
 93 * Assume encoding with MSG_ADDR2.
 94 */
 95int ceph_decode_entity_addrvec(void **p, void *end, bool msgr2,
 96			       struct ceph_entity_addr *addr)
 97{
 98	__le32 my_type = msgr2 ? CEPH_ENTITY_ADDR_TYPE_MSGR2 :
 99				 CEPH_ENTITY_ADDR_TYPE_LEGACY;
100	struct ceph_entity_addr tmp_addr;
101	int addr_cnt;
102	bool found;
103	u8 marker;
104	int ret;
105	int i;
106
107	ceph_decode_8_safe(p, end, marker, e_inval);
108	if (marker != 2) {
109		pr_err("bad addrvec marker %d\n", marker);
110		return -EINVAL;
111	}
112
113	ceph_decode_32_safe(p, end, addr_cnt, e_inval);
114	dout("%s addr_cnt %d\n", __func__, addr_cnt);
115
116	found = false;
117	for (i = 0; i < addr_cnt; i++) {
118		ret = ceph_decode_entity_addr(p, end, &tmp_addr);
119		if (ret)
120			return ret;
121
122		dout("%s i %d addr %s\n", __func__, i, ceph_pr_addr(&tmp_addr));
123		if (tmp_addr.type == my_type) {
124			if (found) {
125				pr_err("another match of type %d in addrvec\n",
126				       le32_to_cpu(my_type));
127				return -EINVAL;
128			}
129
130			memcpy(addr, &tmp_addr, sizeof(*addr));
131			found = true;
132		}
133	}
134
135	if (found)
136		return 0;
137
138	if (!addr_cnt)
139		return 0;  /* normal -- e.g. unused OSD id/slot */
140
141	if (addr_cnt == 1 && !memchr_inv(&tmp_addr, 0, sizeof(tmp_addr)))
142		return 0;  /* weird but effectively the same as !addr_cnt */
143
144	pr_err("no match of type %d in addrvec\n", le32_to_cpu(my_type));
145	return -ENOENT;
146
147e_inval:
148	return -EINVAL;
149}
150EXPORT_SYMBOL(ceph_decode_entity_addrvec);
151
152static int get_sockaddr_encoding_len(sa_family_t family)
153{
154	union {
155		struct sockaddr sa;
156		struct sockaddr_in sin;
157		struct sockaddr_in6 sin6;
158	} u;
159
160	switch (family) {
161	case AF_INET:
162		return sizeof(u.sin);
163	case AF_INET6:
164		return sizeof(u.sin6);
165	default:
166		return sizeof(u);
167	}
168}
169
170int ceph_entity_addr_encoding_len(const struct ceph_entity_addr *addr)
171{
172	sa_family_t family = get_unaligned(&addr->in_addr.ss_family);
173	int addr_len = get_sockaddr_encoding_len(family);
174
175	return 1 + CEPH_ENCODING_START_BLK_LEN + 4 + 4 + 4 + addr_len;
176}
177
178void ceph_encode_entity_addr(void **p, const struct ceph_entity_addr *addr)
179{
180	sa_family_t family = get_unaligned(&addr->in_addr.ss_family);
181	int addr_len = get_sockaddr_encoding_len(family);
182
183	ceph_encode_8(p, 1);  /* marker */
184	ceph_start_encoding(p, 1, 1, sizeof(addr->type) +
185				     sizeof(addr->nonce) +
186				     sizeof(u32) + addr_len);
187	ceph_encode_copy(p, &addr->type, sizeof(addr->type));
188	ceph_encode_copy(p, &addr->nonce, sizeof(addr->nonce));
189
190	ceph_encode_32(p, addr_len);
191	ceph_encode_16(p, family);
192	ceph_encode_copy(p, addr->in_addr.__data, addr_len - sizeof(family));
193}