[PATCH v3] ws2_32:Succeed IPV6_V6ONLY setsockopt for AF_INET sockets ignoring it

Anton Romanov theli.ua at gmail.com
Thu Jan 12 11:03:26 CST 2017


Fixes https://bugs.winehq.org/show_bug.cgi?id=42194
(Magic The Gathering Online not able to login)

Signed-off-by: Anton Romanov <theli.ua at gmail.com>
---
 dlls/ws2_32/socket.c     | 25 +++++++++++++++++++++++-
 dlls/ws2_32/tests/sock.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 73 insertions(+), 2 deletions(-)

diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index 6bf3c9da93..8e45a1a7f6 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -6016,7 +6016,6 @@ int WINAPI WS_setsockopt(SOCKET s, int level, int optname,
         case WS_IPV6_MULTICAST_HOPS:
         case WS_IPV6_MULTICAST_LOOP:
         case WS_IPV6_UNICAST_HOPS:
-        case WS_IPV6_V6ONLY:
 #ifdef IPV6_UNICAST_IF
         case WS_IPV6_UNICAST_IF:
 #endif
@@ -6027,6 +6026,30 @@ int WINAPI WS_setsockopt(SOCKET s, int level, int optname,
         case WS_IPV6_PROTECTION_LEVEL:
             FIXME("IPV6_PROTECTION_LEVEL is ignored!\n");
             return 0;
+        case WS_IPV6_V6ONLY:
+        {
+            union generic_unix_sockaddr uaddr;
+            socklen_t uaddrlen;
+            int bound;
+
+            fd = get_sock_fd( s, 0, NULL );
+            if (fd == -1) return SOCKET_ERROR;
+
+            bound = is_fd_bound(fd, &uaddr, &uaddrlen);
+            release_sock_fd( s, fd );
+            if (uaddr.addr.sa_family == AF_INET && bound == 0)
+            {
+                /* Changing IPV6_V6ONLY succeeds on AF_INET (IPv4) socket
+                 * on Windows (with IPv6 support) if the socket is unbound.
+                 * It is essentially a noop, though Windows does store the value
+                 */
+                FIXME("Silently ignoring IPPROTO_IPV6+IPV6_V6ONLY on AF_INET socket\n");
+                return 0;
+            }
+            level = IPPROTO_IPV6;
+            optname = IPV6_V6ONLY;
+            break;
+        }
         default:
             FIXME("Unknown IPPROTO_IPV6 optname 0x%08x\n", optname);
             return SOCKET_ERROR;
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c
index ba755a5d2f..585671823c 100644
--- a/dlls/ws2_32/tests/sock.c
+++ b/dlls/ws2_32/tests/sock.c
@@ -6189,12 +6189,60 @@ static void test_ipv6only(void)
     }
 
     v4 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
-    ok(v4 != INVALID_SOCKET, "Could not create IPv6 socket (LastError: %d)\n", WSAGetLastError());
+    ok(v4 != INVALID_SOCKET, "Could not create IPv4 socket (LastError: %d)\n", WSAGetLastError());
+
+todo_wine {
+    enabled = 2;
+    ret = getsockopt(v4, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&enabled, &len);
+    ok(!ret, "getsockopt(IPV6_ONLY) failed (LastError: %d)\n", WSAGetLastError());
+    ok(enabled == 1, "expected 1, got %d\n", enabled);
+}
+
+    enabled = 0;
+    len = sizeof(enabled);
+    ret = setsockopt(v4, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&enabled, len);
+    ok(!ret, "setsockopt(IPV6_ONLY) failed (LastError: %d)\n", WSAGetLastError());
+
+todo_wine {
+    enabled = 2;
+    ret = getsockopt(v4, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&enabled, &len);
+    ok(!ret, "getsockopt(IPV6_ONLY) failed (LastError: %d)\n", WSAGetLastError());
+    ok(!enabled, "expected 0, got %d\n", enabled);
+}
+
+    enabled = 1;
+    len = sizeof(enabled);
+    ret = setsockopt(v4, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&enabled, len);
+    ok(!ret, "setsockopt(IPV6_ONLY) failed (LastError: %d)\n", WSAGetLastError());
 
     /* bind on IPv4 socket should succeed - IPV6_V6ONLY is enabled by default */
     ret = bind(v4, (struct sockaddr*)&sin4, sizeof(sin4));
     ok(!ret, "Could not bind IPv4 address (LastError: %d)\n", WSAGetLastError());
 
+todo_wine {
+    enabled = 2;
+    ret = getsockopt(v4, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&enabled, &len);
+    ok(!ret, "getsockopt(IPV6_ONLY) failed (LastError: %d)\n", WSAGetLastError());
+    ok(enabled == 1, "expected 1, got %d\n", enabled);
+}
+
+    enabled = 0;
+    len = sizeof(enabled);
+    ret = setsockopt(v4, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&enabled, len);
+    ok(ret, "setsockopt(IPV6_ONLY) succeeded (LastError: %d)\n", WSAGetLastError());
+
+todo_wine {
+    enabled = 0;
+    ret = getsockopt(v4, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&enabled, &len);
+    ok(!ret, "getsockopt(IPV6_ONLY) failed (LastError: %d)\n", WSAGetLastError());
+    ok(enabled == 1, "expected 1, got %d\n", enabled);
+}
+
+    enabled = 1;
+    len = sizeof(enabled);
+    ret = setsockopt(v4, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&enabled, len);
+    ok(ret, "setsockopt(IPV6_ONLY) succeeded (LastError: %d)\n", WSAGetLastError());
+
     closesocket(v4);
     closesocket(v6);
 
-- 
2.11.0




More information about the wine-patches mailing list