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, ...@@ -3257,6 +3257,86 @@ INT WINAPI WSAIoctl(SOCKET s,
release_sock_fd(s, fd); release_sock_fd(s, fd);
break; 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: case WS_SIO_UDP_CONNRESET:
FIXME("WS_SIO_UDP_CONNRESET stub\n"); FIXME("WS_SIO_UDP_CONNRESET stub\n");
break; break;
......
...@@ -4290,17 +4290,14 @@ static void test_sioRoutingInterfaceQuery(void) ...@@ -4290,17 +4290,14 @@ static void test_sioRoutingInterfaceQuery(void)
} }
ret = WSAIoctl(sock, SIO_ROUTING_INTERFACE_QUERY, NULL, 0, NULL, 0, NULL, ret = WSAIoctl(sock, SIO_ROUTING_INTERFACE_QUERY, NULL, 0, NULL, 0, NULL,
NULL, NULL); NULL, NULL);
todo_wine
ok(ret == SOCKET_ERROR && WSAGetLastError() == WSAEFAULT, ok(ret == SOCKET_ERROR && WSAGetLastError() == WSAEFAULT,
"expected WSAEFAULT, got %d\n", WSAGetLastError()); "expected WSAEFAULT, got %d\n", WSAGetLastError());
ret = WSAIoctl(sock, SIO_ROUTING_INTERFACE_QUERY, &sin, sizeof(sin), ret = WSAIoctl(sock, SIO_ROUTING_INTERFACE_QUERY, &sin, sizeof(sin),
NULL, 0, NULL, NULL, NULL); NULL, 0, NULL, NULL, NULL);
todo_wine
ok(ret == SOCKET_ERROR && WSAGetLastError() == WSAEFAULT, ok(ret == SOCKET_ERROR && WSAGetLastError() == WSAEFAULT,
"expected WSAEFAULT, got %d\n", WSAGetLastError()); "expected WSAEFAULT, got %d\n", WSAGetLastError());
ret = WSAIoctl(sock, SIO_ROUTING_INTERFACE_QUERY, &sin, sizeof(sin), ret = WSAIoctl(sock, SIO_ROUTING_INTERFACE_QUERY, &sin, sizeof(sin),
NULL, 0, &bytesReturned, NULL, NULL); NULL, 0, &bytesReturned, NULL, NULL);
todo_wine
ok(ret == SOCKET_ERROR && ok(ret == SOCKET_ERROR &&
(WSAGetLastError() == WSAEFAULT /* Win98 */ || (WSAGetLastError() == WSAEFAULT /* Win98 */ ||
WSAGetLastError() == WSAEINVAL /* NT4 */|| WSAGetLastError() == WSAEINVAL /* NT4 */||
...@@ -4310,7 +4307,6 @@ static void test_sioRoutingInterfaceQuery(void) ...@@ -4310,7 +4307,6 @@ static void test_sioRoutingInterfaceQuery(void)
sin.sin_family = AF_INET; sin.sin_family = AF_INET;
ret = WSAIoctl(sock, SIO_ROUTING_INTERFACE_QUERY, &sin, sizeof(sin), ret = WSAIoctl(sock, SIO_ROUTING_INTERFACE_QUERY, &sin, sizeof(sin),
NULL, 0, &bytesReturned, NULL, NULL); NULL, 0, &bytesReturned, NULL, NULL);
todo_wine
ok(ret == SOCKET_ERROR && ok(ret == SOCKET_ERROR &&
(WSAGetLastError() == WSAEFAULT /* Win98 */ || (WSAGetLastError() == WSAEFAULT /* Win98 */ ||
WSAGetLastError() == WSAEINVAL), WSAGetLastError() == WSAEINVAL),
...@@ -4318,24 +4314,23 @@ static void test_sioRoutingInterfaceQuery(void) ...@@ -4318,24 +4314,23 @@ static void test_sioRoutingInterfaceQuery(void)
sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
ret = WSAIoctl(sock, SIO_ROUTING_INTERFACE_QUERY, &sin, sizeof(sin), ret = WSAIoctl(sock, SIO_ROUTING_INTERFACE_QUERY, &sin, sizeof(sin),
NULL, 0, &bytesReturned, NULL, NULL); NULL, 0, &bytesReturned, NULL, NULL);
todo_wine
ok(ret == SOCKET_ERROR && ok(ret == SOCKET_ERROR &&
(WSAGetLastError() == WSAEINVAL /* NT4 */ || (WSAGetLastError() == WSAEINVAL /* NT4 */ ||
WSAGetLastError() == WSAEFAULT), WSAGetLastError() == WSAEFAULT),
"expected WSAEINVAL or WSAEFAULT, got %d\n", WSAGetLastError()); "expected WSAEINVAL or WSAEFAULT, got %d\n", WSAGetLastError());
ret = WSAIoctl(sock, SIO_ROUTING_INTERFACE_QUERY, &sin, sizeof(sin), ret = WSAIoctl(sock, SIO_ROUTING_INTERFACE_QUERY, &sin, sizeof(sin),
&sout, sizeof(sout), &bytesReturned, NULL, NULL); &sout, sizeof(sout), &bytesReturned, NULL, NULL);
todo_wine
ok(!ret || broken(WSAGetLastError() == WSAEINVAL /* NT4 */), ok(!ret || broken(WSAGetLastError() == WSAEINVAL /* NT4 */),
"WSAIoctl failed: %d\n", WSAGetLastError()); "WSAIoctl failed: %d\n", WSAGetLastError());
if (!ret) if (!ret)
{ {
ok(sout.sin_family == AF_INET, "expected AF_INET, got %d\n", ok(sout.sin_family == AF_INET, "expected AF_INET, got %d\n",
sout.sin_family); sout.sin_family);
if (sout.sin_family == AF_INET) /* We expect the source address to be INADDR_LOOPBACK as well, but
ok(sout.sin_addr.s_addr == htonl(INADDR_LOOPBACK), * there's no guarantee that a route to the loopback address exists,
"expected %08x, got %08x\n", htonl(INADDR_LOOPBACK), * so rather than introduce spurious test failures we do not test the
htonl(sout.sin_addr.s_addr)); * source address.
*/
} }
closesocket(sock); 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