From 6d1a4e15ae8065e7aa8faf57e4dc63dd6ddf3bb4 Mon Sep 17 00:00:00 2001 From: Lucian Petrut Date: Tue, 16 Nov 2021 13:53:37 +0000 Subject: [PATCH] msg: Fix Windows IPv6 support The Windows AF_INET6 definition doesn't match the Linux one, thus sockaddr structures must be converted when being sent over the wire. Otherwise, Linux hosts will not be able to recognize the address family and reject Windows client connections: handle_client_ident peer is trying to reach v2:(unrecognized address family 23)/0 which is not us Note that this isn't the case with AF_INET, which has the same definition on both platforms. Signed-off-by: Lucian Petrut (cherry picked from commit 475e7a6910ed761d298670b34442d0c963937daf) --- src/msg/msg_types.h | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/src/msg/msg_types.h b/src/msg/msg_types.h index 4c0d77e1f5a..f1f0c5e5c13 100644 --- a/src/msg/msg_types.h +++ b/src/msg/msg_types.h @@ -26,6 +26,11 @@ #define MAX_PORT_NUMBER 65535 +#ifdef _WIN32 +// ceph_sockaddr_storage matches the Linux format. +#define AF_INET6_LINUX 10 +#endif + namespace ceph { class Formatter; } @@ -192,6 +197,14 @@ static inline void encode(const sockaddr_storage& a, ceph::buffer::list& bl) { (unsigned char*)(&ss + 1) - dst); ::memcpy(dst, src, copy_size); encode(ss, bl); +#elif defined(_WIN32) + ceph_sockaddr_storage ss{}; + ::memcpy(&ss, &a, std::min(sizeof(ss), sizeof(a))); + // The Windows AF_INET6 definition doesn't match the Linux one. + if (a.ss_family == AF_INET6) { + ss.ss_family = AF_INET6_LINUX; + } + encode(ss, bl); #else ceph_sockaddr_storage ss; ::memset(&ss, '\0', sizeof(ss)); @@ -217,6 +230,13 @@ static inline void decode(sockaddr_storage& a, auto const copy_size = std::min((unsigned char*)(&ss + 1) - src, (unsigned char*)(&a + 1) - dst); ::memcpy(dst, src, copy_size); +#elif defined(_WIN32) + ceph_sockaddr_storage ss{}; + decode(ss, bl); + ::memcpy(&a, &ss, std::min(sizeof(ss), sizeof(a))); + if (a.ss_family == AF_INET6_LINUX) { + a.ss_family = AF_INET6; + } #else ceph_sockaddr_storage ss{}; decode(ss, bl); @@ -501,7 +521,11 @@ struct entity_addr_t { encode(elen, bl); if (elen) { uint16_t ss_family = u.sa.sa_family; - +#if defined(_WIN32) + if (ss_family == AF_INET6) { + ss_family = AF_INET6_LINUX; + } +#endif encode(ss_family, bl); elen -= sizeof(u.sa.sa_family); bl.append(u.sa.sa_data, elen); @@ -532,6 +556,11 @@ struct entity_addr_t { throw ceph::buffer::malformed_input("elen smaller than family len"); } decode(ss_family, bl); +#if defined(_WIN32) + if (ss_family == AF_INET6_LINUX) { + ss_family = AF_INET6; + } +#endif u.sa.sa_family = ss_family; elen -= sizeof(ss_family); if (elen > get_sockaddr_len() - sizeof(u.sa.sa_family)) { -- 2.47.3