Module: wine Branch: master Commit: 9addae9d663ec0cff1e748190c12c4203dbbf5d7 URL: http://source.winehq.org/git/wine.git/?a=commit;h=9addae9d663ec0cff1e748190c...
Author: Juan Lang juan.lang@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); }