Commit 9addae9d authored by Juan Lang's avatar Juan Lang Committed by Alexandre Julliard

ws2_32: Implement WSAIoctl for SIO_ROUTING_INTERFACE_QUERY.

parent da1ceb11
......@@ -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;
......
......@@ -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);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment