]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
msg: Fix Windows IPv6 support 47303/head
authorLucian Petrut <lpetrut@cloudbasesolutions.com>
Tue, 16 Nov 2021 13:53:37 +0000 (13:53 +0000)
committerLucian Petrut <lpetrut@cloudbasesolutions.com>
Wed, 27 Jul 2022 12:59:06 +0000 (12:59 +0000)
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 <lpetrut@cloudbasesolutions.com>
(cherry picked from commit 475e7a6910ed761d298670b34442d0c963937daf)

src/msg/msg_types.h

index 4c0d77e1f5a7d75d183c3b3a326c516b82c5fbce..f1f0c5e5c13bdec33f3d0326325ce167f32ec76e 100644 (file)
 
 #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)) {