]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
msg: Fix Windows IPv6 support 47302/head
authorLucian Petrut <lpetrut@cloudbasesolutions.com>
Tue, 16 Nov 2021 13:53:37 +0000 (13:53 +0000)
committerLucian Petrut <lpetrut@cloudbasesolutions.com>
Thu, 25 Aug 2022 09:43:10 +0000 (09:43 +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 6e0ee1261de4d8917a04b3b76121d22b2787bbc0..a33545d916f3d51ed13592082bc72bea8b897d32 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;
 }
@@ -161,6 +166,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));
@@ -186,6 +199,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);
@@ -470,7 +490,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);
@@ -501,6 +525,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)) {