Juan Lang : ws2_32: Implement WSAIoctl for SIO_ROUTING_INTERFACE_QUERY.

Alexandre Julliard julliard at winehq.org
Wed Sep 29 12:00:13 CDT 2010


Module: wine
Branch: master
Commit: 9addae9d663ec0cff1e748190c12c4203dbbf5d7
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=9addae9d663ec0cff1e748190c12c4203dbbf5d7

Author: Juan Lang <juan.lang at gmail.com>
Date:   Tue Sep 28 13:18:12 2010 -0700

ws2_32: Implement WSAIoctl for SIO_ROUTING_INTERFACE_QUERY.

---

 dlls/ws2_32/socket.c     |   80 ++++++++++++++++++++++++++++++++++++++++++++++
 dlls/ws2_32/tests/sock.c |   15 +++------
 2 files changed, 85 insertions(+), 10 deletions(-)

diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index f605d0d..22e6138 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -3257,6 +3257,86 @@ INT WINAPI WSAIoctl(SOCKET s,
         release_sock_fd(s, fd);
         break;
    }
+   case WS_SIO_ROUTING_INTERFACE_QUERY:
+   {
+       struct WS_sockaddr *daddr = (struct WS_sockaddr *)lpvInBuffer;
+       struct WS_sockaddr_in *daddr_in = (struct WS_sockaddr_in *)daddr;
+       struct WS_sockaddr_in *saddr_in = (struct WS_sockaddr_in *)lpbOutBuffer;
+       MIB_IPFORWARDROW row;
+       PMIB_IPADDRTABLE ipAddrTable = NULL;
+       DWORD size, i, found_index;
+
+       TRACE("-> WS_SIO_ROUTING_INTERFACE_QUERY request\n");
+
+       if (!lpvInBuffer)
+       {
+           WSASetLastError(WSAEFAULT);
+           return SOCKET_ERROR;
+       }
+       if (cbInBuffer < sizeof(struct WS_sockaddr))
+       {
+           WSASetLastError(WSAEFAULT);
+           return SOCKET_ERROR;
+       }
+       if (!lpbOutBuffer)
+       {
+           WSASetLastError(WSAEFAULT);
+           return SOCKET_ERROR;
+       }
+       if (!lpcbBytesReturned)
+       {
+           WSASetLastError(WSAEFAULT);
+           return SOCKET_ERROR;
+       }
+       if (daddr->sa_family != AF_INET)
+       {
+           FIXME("unsupported address family %d\n", daddr->sa_family);
+           WSASetLastError(WSAEAFNOSUPPORT);
+           return SOCKET_ERROR;
+       }
+       if (cbOutBuffer < sizeof(struct WS_sockaddr_in))
+       {
+           WSASetLastError(WSAEFAULT);
+           return SOCKET_ERROR;
+       }
+       if (GetBestRoute(daddr_in->sin_addr.S_un.S_addr, 0, &row) != NOERROR)
+       {
+           WSASetLastError(WSAEFAULT);
+           return SOCKET_ERROR;
+       }
+       if (GetIpAddrTable(NULL, &size, FALSE) != ERROR_INSUFFICIENT_BUFFER)
+       {
+           WSASetLastError(WSAEFAULT);
+           return SOCKET_ERROR;
+       }
+       ipAddrTable = HeapAlloc(GetProcessHeap(), 0, size);
+       if (GetIpAddrTable(ipAddrTable, &size, FALSE))
+       {
+           HeapFree(GetProcessHeap(), 0, ipAddrTable);
+           WSASetLastError(WSAEFAULT);
+           return SOCKET_ERROR;
+       }
+       for (i = 0, found_index = ipAddrTable->dwNumEntries;
+            i < ipAddrTable->dwNumEntries; i++)
+       {
+           if (ipAddrTable->table[i].dwIndex == row.dwForwardIfIndex)
+               found_index = i;
+       }
+       if (found_index == ipAddrTable->dwNumEntries)
+       {
+           ERR("no matching IP address for interface %d\n",
+               row.dwForwardIfIndex);
+           HeapFree(GetProcessHeap(), 0, ipAddrTable);
+           WSASetLastError(WSAEFAULT);
+           return SOCKET_ERROR;
+       }
+       saddr_in->sin_family = AF_INET;
+       saddr_in->sin_addr.S_un.S_addr = ipAddrTable->table[found_index].dwAddr;
+       saddr_in->sin_port = 0;
+       *lpcbBytesReturned = sizeof(struct WS_sockaddr_in);
+       HeapFree(GetProcessHeap(), 0, ipAddrTable);
+       return 0;
+   }
    case WS_SIO_UDP_CONNRESET:
        FIXME("WS_SIO_UDP_CONNRESET stub\n");
        break;
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c
index abe0934..25bda61 100644
--- a/dlls/ws2_32/tests/sock.c
+++ b/dlls/ws2_32/tests/sock.c
@@ -4290,17 +4290,14 @@ static void test_sioRoutingInterfaceQuery(void)
     }
     ret = WSAIoctl(sock, SIO_ROUTING_INTERFACE_QUERY, NULL, 0, NULL, 0, NULL,
                    NULL, NULL);
-    todo_wine
     ok(ret == SOCKET_ERROR && WSAGetLastError() == WSAEFAULT,
        "expected WSAEFAULT, got %d\n", WSAGetLastError());
     ret = WSAIoctl(sock, SIO_ROUTING_INTERFACE_QUERY, &sin, sizeof(sin),
                    NULL, 0, NULL, NULL, NULL);
-    todo_wine
     ok(ret == SOCKET_ERROR && WSAGetLastError() == WSAEFAULT,
        "expected WSAEFAULT, got %d\n", WSAGetLastError());
     ret = WSAIoctl(sock, SIO_ROUTING_INTERFACE_QUERY, &sin, sizeof(sin),
                    NULL, 0, &bytesReturned, NULL, NULL);
-    todo_wine
     ok(ret == SOCKET_ERROR &&
        (WSAGetLastError() == WSAEFAULT /* Win98 */ ||
         WSAGetLastError() == WSAEINVAL /* NT4 */||
@@ -4310,7 +4307,6 @@ static void test_sioRoutingInterfaceQuery(void)
     sin.sin_family = AF_INET;
     ret = WSAIoctl(sock, SIO_ROUTING_INTERFACE_QUERY, &sin, sizeof(sin),
                    NULL, 0, &bytesReturned, NULL, NULL);
-    todo_wine
     ok(ret == SOCKET_ERROR &&
        (WSAGetLastError() == WSAEFAULT /* Win98 */ ||
         WSAGetLastError() == WSAEINVAL),
@@ -4318,24 +4314,23 @@ static void test_sioRoutingInterfaceQuery(void)
     sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
     ret = WSAIoctl(sock, SIO_ROUTING_INTERFACE_QUERY, &sin, sizeof(sin),
                    NULL, 0, &bytesReturned, NULL, NULL);
-    todo_wine
     ok(ret == SOCKET_ERROR &&
        (WSAGetLastError() == WSAEINVAL /* NT4 */ ||
         WSAGetLastError() == WSAEFAULT),
        "expected WSAEINVAL or WSAEFAULT, got %d\n", WSAGetLastError());
     ret = WSAIoctl(sock, SIO_ROUTING_INTERFACE_QUERY, &sin, sizeof(sin),
                    &sout, sizeof(sout), &bytesReturned, NULL, NULL);
-    todo_wine
     ok(!ret || broken(WSAGetLastError() == WSAEINVAL /* NT4 */),
        "WSAIoctl failed: %d\n", WSAGetLastError());
     if (!ret)
     {
         ok(sout.sin_family == AF_INET, "expected AF_INET, got %d\n",
            sout.sin_family);
-        if (sout.sin_family == AF_INET)
-            ok(sout.sin_addr.s_addr == htonl(INADDR_LOOPBACK),
-               "expected %08x, got %08x\n", htonl(INADDR_LOOPBACK),
-               htonl(sout.sin_addr.s_addr));
+        /* We expect the source address to be INADDR_LOOPBACK as well, but
+         * there's no guarantee that a route to the loopback address exists,
+         * so rather than introduce spurious test failures we do not test the
+         * source address.
+         */
     }
     closesocket(sock);
 }




More information about the wine-cvs mailing list