Add a way to decode an entity_addr_t. Once CEPH_FEATURE_MSG_ADDR2 is enabled, the server daemons will start encoding entity_addr_t differently. Add a new helper function that can handle either format. Signed-off-by: Jeff Layton <jlayton@xxxxxxxxxx> --- include/linux/ceph/decode.h | 2 + net/ceph/Makefile | 2 +- net/ceph/decode.c | 75 +++++++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 net/ceph/decode.c diff --git a/include/linux/ceph/decode.h b/include/linux/ceph/decode.h index a6c2a48d42e0..1c0a665bfc03 100644 --- a/include/linux/ceph/decode.h +++ b/include/linux/ceph/decode.h @@ -230,6 +230,8 @@ static inline void ceph_decode_addr(struct ceph_entity_addr *a) WARN_ON(a->in_addr.ss_family == 512); } +extern int ceph_decode_entity_addr(void **p, void *end, + struct ceph_entity_addr *addr); /* * encoders */ diff --git a/net/ceph/Makefile b/net/ceph/Makefile index db09defe27d0..59d0ba2072de 100644 --- a/net/ceph/Makefile +++ b/net/ceph/Makefile @@ -5,7 +5,7 @@ obj-$(CONFIG_CEPH_LIB) += libceph.o libceph-y := ceph_common.o messenger.o msgpool.o buffer.o pagelist.o \ - mon_client.o \ + mon_client.o decode.o \ cls_lock_client.o \ osd_client.o osdmap.o crush/crush.o crush/mapper.o crush/hash.o \ striper.o \ diff --git a/net/ceph/decode.c b/net/ceph/decode.c new file mode 100644 index 000000000000..27edf5d341ec --- /dev/null +++ b/net/ceph/decode.c @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <linux/ceph/decode.h> + +int +ceph_decode_entity_addr(void **p, void *end, struct ceph_entity_addr *addr) +{ + u8 marker, v, compat; + u32 len; + + ceph_decode_8_safe(p, end, marker, bad); + if (marker == 1) { + ceph_decode_8_safe(p, end, v, bad); + ceph_decode_8_safe(p, end, compat, bad); + if (!v || compat != 1) + goto bad; + /* FIXME: sanity check? */ + ceph_decode_32_safe(p, end, len, bad); + /* type is __le32, so we must copy into place as-is */ + ceph_decode_copy_safe(p, end, &addr->type, + sizeof(addr->type), bad); + + /* + * TYPE_NONE == 0 + * TYPE_LEGACY == 1 + * + * Clients that don't support ADDR2 always send TYPE_NONE. + * For now, since all we support is msgr1, just set this to 0 + * when we get a TYPE_LEGACY type. + */ + if (addr->type == cpu_to_le32(1)) + addr->type = 0; + } else if (marker == 0) { + addr->type = 0; + /* Skip rest of type field */ + ceph_decode_skip_n(p, end, 3, bad); + } else { + goto bad; + } + + ceph_decode_need(p, end, sizeof(addr->nonce), bad); + ceph_decode_copy(p, &addr->nonce, sizeof(addr->nonce)); + + /* addr length */ + if (marker == 1) { + ceph_decode_32_safe(p, end, len, bad); + if (len > sizeof(addr->in_addr)) + goto bad; + } else { + len = sizeof(addr->in_addr); + } + + memset(&addr->in_addr, 0, sizeof(addr->in_addr)); + + if (len) { + ceph_decode_need(p, end, len, bad); + ceph_decode_copy(p, &addr->in_addr, len); + + /* + * Fix up sa_family. Legacy encoding sends it in BE, addr2 + * encoding uses LE. + */ + if (marker == 1) + addr->in_addr.ss_family = + le16_to_cpu((__force __le16)addr->in_addr.ss_family); + else + addr->in_addr.ss_family = + be16_to_cpu((__force __be16)addr->in_addr.ss_family); + } + return 0; +bad: + return -EINVAL; +} +EXPORT_SYMBOL(ceph_decode_entity_addr); + -- 2.21.0