Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/net/ceph/decode.c
26282 views
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
9
static int
10
ceph_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;
45
bad:
46
return ret;
47
}
48
49
static int
50
ceph_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;
70
bad:
71
return ret;
72
}
73
74
int
75
ceph_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);
84
bad:
85
return -EINVAL;
86
}
87
EXPORT_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
*/
95
int 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
147
e_inval:
148
return -EINVAL;
149
}
150
EXPORT_SYMBOL(ceph_decode_entity_addrvec);
151
152
static 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
170
int 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
178
void 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
}
194
195