1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/ceph/ceph_debug.h>
4 #include <linux/inet.h>
6 #include <linux/ceph/decode.h>
7 #include <linux/ceph/messenger.h> /* for ceph_pr_addr() */
10 ceph_decode_entity_addr_versioned(void **p
, void *end
,
11 struct ceph_entity_addr
*addr
)
15 u32 struct_len
, addr_len
;
18 ret
= ceph_start_decoding(p
, end
, 1, "entity_addr_t", &struct_v
,
24 struct_end
= *p
+ struct_len
;
26 ceph_decode_copy_safe(p
, end
, &addr
->type
, sizeof(addr
->type
), bad
);
28 ceph_decode_copy_safe(p
, end
, &addr
->nonce
, sizeof(addr
->nonce
), bad
);
30 ceph_decode_32_safe(p
, end
, addr_len
, bad
);
31 if (addr_len
> sizeof(addr
->in_addr
))
34 memset(&addr
->in_addr
, 0, sizeof(addr
->in_addr
));
36 ceph_decode_copy_safe(p
, end
, &addr
->in_addr
, addr_len
, bad
);
38 addr
->in_addr
.ss_family
=
39 le16_to_cpu((__force __le16
)addr
->in_addr
.ss_family
);
42 /* Advance past anything the client doesn't yet understand */
50 ceph_decode_entity_addr_legacy(void **p
, void *end
,
51 struct ceph_entity_addr
*addr
)
55 /* Skip rest of type field */
56 ceph_decode_skip_n(p
, end
, 3, bad
);
59 * Clients that don't support ADDR2 always send TYPE_NONE, change it
60 * to TYPE_LEGACY for forward compatibility.
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
);
75 ceph_decode_entity_addr(void **p
, void *end
, struct ceph_entity_addr
*addr
)
79 ceph_decode_8_safe(p
, end
, marker
, bad
);
81 return ceph_decode_entity_addr_versioned(p
, end
, addr
);
83 return ceph_decode_entity_addr_legacy(p
, end
, addr
);
87 EXPORT_SYMBOL(ceph_decode_entity_addr
);
90 * Return addr of desired type (MSGR2 or LEGACY) or error.
91 * Make sure there is only one match.
93 * Assume encoding with MSG_ADDR2.
95 int ceph_decode_entity_addrvec(void **p
, void *end
, bool msgr2
,
96 struct ceph_entity_addr
*addr
)
98 __le32 my_type
= msgr2
? CEPH_ENTITY_ADDR_TYPE_MSGR2
:
99 CEPH_ENTITY_ADDR_TYPE_LEGACY
;
100 struct ceph_entity_addr tmp_addr
;
107 ceph_decode_8_safe(p
, end
, marker
, e_inval
);
109 pr_err("bad addrvec marker %d\n", marker
);
113 ceph_decode_32_safe(p
, end
, addr_cnt
, e_inval
);
114 dout("%s addr_cnt %d\n", __func__
, addr_cnt
);
117 for (i
= 0; i
< addr_cnt
; i
++) {
118 ret
= ceph_decode_entity_addr(p
, end
, &tmp_addr
);
122 dout("%s i %d addr %s\n", __func__
, i
, ceph_pr_addr(&tmp_addr
));
123 if (tmp_addr
.type
== my_type
) {
125 pr_err("another match of type %d in addrvec\n",
126 le32_to_cpu(my_type
));
130 memcpy(addr
, &tmp_addr
, sizeof(*addr
));
139 return 0; /* normal -- e.g. unused OSD id/slot */
141 if (addr_cnt
== 1 && !memchr_inv(&tmp_addr
, 0, sizeof(tmp_addr
)))
142 return 0; /* weird but effectively the same as !addr_cnt */
144 pr_err("no match of type %d in addrvec\n", le32_to_cpu(my_type
));
150 EXPORT_SYMBOL(ceph_decode_entity_addrvec
);
152 static int get_sockaddr_encoding_len(sa_family_t family
)
156 struct sockaddr_in sin
;
157 struct sockaddr_in6 sin6
;
162 return sizeof(u
.sin
);
164 return sizeof(u
.sin6
);
170 int ceph_entity_addr_encoding_len(const struct ceph_entity_addr
*addr
)
172 sa_family_t family
= get_unaligned(&addr
->in_addr
.ss_family
);
173 int addr_len
= get_sockaddr_encoding_len(family
);
175 return 1 + CEPH_ENCODING_START_BLK_LEN
+ 4 + 4 + 4 + addr_len
;
178 void ceph_encode_entity_addr(void **p
, const struct ceph_entity_addr
*addr
)
180 sa_family_t family
= get_unaligned(&addr
->in_addr
.ss_family
);
181 int addr_len
= get_sockaddr_encoding_len(family
);
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
));
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
));