ws2_32: Implement WSAIoctl for SIO_ROUTING_INTERFACE_QUERY.
This commit is contained in:
parent
da1ceb1154
commit
9addae9d66
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue