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