windows-nt/Source/XPSP1/NT/net/tcpip/apis/iphlpapi/dll/stackex.c
2020-09-26 16:20:57 +08:00

412 lines
10 KiB
C

/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
stackex.c
Abstract:
Ex versions of GetTcpTableFromStack and GetUdpTableFromStack.
These are used to get the owning process id associated with connections
from the stack.
Author:
Shaun Cox (shaunco) 19-Feb-2000
Revision History:
--*/
#include "inc.h"
#pragma hdrstop
int
TCPQueryInformationEx(
DWORD Family,
void *InBuf,
ulong *InBufLen,
void *OutBuf,
ulong *OutBufLen
);
DWORD
GetTcpExTableFromStack(
OUT TCP_EX_TABLE *pTcpTable,
IN DWORD dwSize,
IN BOOL bOrder,
IN DWORD dwFamily
)
{
DWORD dwInBufLen, dwOutBufLen, dwResult, dwEntryLen;
TDIObjectID *ID;
BYTE *Context;
int (_cdecl *pfnCompare)(CONST VOID *pvElem1, CONST VOID *pvElem2);
TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
CheckTcpipState();
if (dwFamily == AF_INET)
{
if (!g_bIpConfigured)
{
return ERROR_NOT_SUPPORTED;
}
dwEntryLen = sizeof(TCPConnTableEntryEx);
pfnCompare = CompareTcpRow;
dwOutBufLen = dwSize - FIELD_OFFSET(TCP_EX_TABLE, table[0]);
}
else if (dwFamily == AF_INET6)
{
if (!g_bIp6Configured)
{
return ERROR_NOT_SUPPORTED;
}
dwEntryLen = sizeof(TCP6ConnTableEntry);
pfnCompare = CompareTcp6Row;
dwOutBufLen = dwSize - FIELD_OFFSET(TCP6_EX_TABLE, table[0]);
}
else
{
return ERROR_INVALID_PARAMETER;
}
ID = &(trqiInBuf.ID);
ID->toi_entity.tei_entity = CO_TL_ENTITY;
ID->toi_entity.tei_instance = 0;
ID->toi_class = INFO_CLASS_PROTOCOL;
ID->toi_type = INFO_TYPE_PROVIDER;
ID->toi_id = TCP_EX_TABLE_ID;
Context = (BYTE *) &(trqiInBuf.Context[0]);
ZeroMemory( Context, CONTEXT_SIZE );
dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
dwResult = TCPQueryInformationEx(dwFamily,
&trqiInBuf,
&dwInBufLen,
(PVOID)(pTcpTable->table),
&dwOutBufLen);
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,
"GetTcpExTableFromStack: Couldnt query stack. Error %x",
dwResult);
return dwResult;
}
pTcpTable->dwNumEntries = (dwOutBufLen / dwEntryLen);
if((pTcpTable->dwNumEntries > 0) and bOrder)
{
qsort(pTcpTable->table,
pTcpTable->dwNumEntries,
dwEntryLen,
pfnCompare);
}
return NO_ERROR;
}
DWORD
AllocateAndGetTcpExTableFromStack(
OUT TCP_EX_TABLE **ppTcpTable,
IN BOOL bOrder,
IN HANDLE hHeap,
IN DWORD dwFlags,
IN DWORD dwFamily
)
{
DWORD dwResult, dwCount, dwOutBufLen;
MIB_TCPSTATS TcpInfo;
DWORD dwEntryLen;
*ppTcpTable = NULL;
//
// Find out the number of entries the stack has. It returns this as part of
// the Tcp Stats. Also validate the dwFamily parameter.
//
dwResult = GetTcpStatsFromStackEx(&TcpInfo, dwFamily);
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,
"AllocateAndGetTcpExTableFromStack: Couldnt get Tcp Stats From stack. Error %d",
dwResult);
return dwResult;
}
dwCount = TcpInfo.dwNumConns + OVERFLOW_COUNT;
if (dwFamily == AF_INET)
{
dwEntryLen = sizeof(TCPConnTableEntryEx);
dwOutBufLen = FIELD_OFFSET(TCP_EX_TABLE, table[0])
+ (dwCount * dwEntryLen)
+ ALIGN_SIZE;
}
else
{
dwEntryLen = sizeof(TCP6ConnTableEntry);
dwOutBufLen = FIELD_OFFSET(TCP6_EX_TABLE, table[0])
+ (dwCount * dwEntryLen)
+ ALIGN_SIZE;
}
*ppTcpTable = HeapAlloc(hHeap, dwFlags, dwOutBufLen);
if(*ppTcpTable is NULL)
{
dwResult = ERROR_NOT_ENOUGH_MEMORY;
Trace1(ERR,
"AllocateAndGetTcpExTableFromStack: Couldnt allocate memory. Error %d",
dwResult);
return dwResult;
}
if(TcpInfo.dwNumConns is 0)
{
(*ppTcpTable)->dwNumEntries = 0;
return NO_ERROR;
}
dwResult = GetTcpExTableFromStack(*ppTcpTable, dwOutBufLen, bOrder,
dwFamily);
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,
"AllocateAndGetTcpExTableFromStack: Error %d GetTcpExTableFromStack",
dwResult);
}
return dwResult;
}
DWORD
GetUdpExTableFromStack(
OUT UDP_EX_TABLE *pUdpTable,
IN DWORD dwSize,
IN BOOL bOrder,
IN DWORD dwFamily
)
{
DWORD dwInBufLen, dwOutBufLen, dwResult;
BYTE *Context;
DWORD dwEntryLen;
int (__cdecl *pfnCompare)(CONST VOID *pvElem1, CONST VOID *pvElem2);
TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
TDIObjectID *ID;
CheckTcpipState();
if (dwFamily == AF_INET)
{
if (!g_bIpConfigured)
{
return ERROR_NOT_SUPPORTED;
}
dwEntryLen = sizeof(UDPEntryEx);
pfnCompare = CompareUdpRow;
}
else if (dwFamily == AF_INET6)
{
if (!g_bIp6Configured)
{
return ERROR_NOT_SUPPORTED;
}
dwEntryLen = sizeof(UDP6ListenerEntry);
pfnCompare = CompareUdp6Row;
}
else
{
return ERROR_INVALID_PARAMETER;
}
ID = &(trqiInBuf.ID);
ID->toi_entity.tei_entity = CL_TL_ENTITY;
ID->toi_entity.tei_instance = 0;
ID->toi_class = INFO_CLASS_PROTOCOL;
ID->toi_type = INFO_TYPE_PROVIDER;
ID->toi_id = UDP_EX_TABLE_ID;
Context = (BYTE *) &(trqiInBuf.Context[0]);
ZeroMemory( Context, CONTEXT_SIZE );
dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
dwOutBufLen = dwSize - FIELD_OFFSET(UDP6_LISTENER_TABLE, table[0]);
dwResult = TCPQueryInformationEx(dwFamily,
&trqiInBuf,
&dwInBufLen,
(PVOID)(pUdpTable->table),
&dwOutBufLen);
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,
"GetUdpExTableFromStack: Couldnt query TCP information. Error %d",
dwResult);
return dwResult;
}
pUdpTable->dwNumEntries = (dwOutBufLen / dwEntryLen);
//
// Now sort the UDP connection table. Keys are: local address, and local
// port.
//
if((pUdpTable->dwNumEntries > 0) and bOrder)
{
qsort(pUdpTable->table,
pUdpTable->dwNumEntries,
dwEntryLen,
pfnCompare);
}
TraceLeave("GetUdpExTableFromStack");
return NO_ERROR;
}
DWORD
AllocateAndGetUdpExTableFromStack(
OUT UDP_EX_TABLE **ppUdpTable,
IN BOOL bOrder,
IN HANDLE hHeap,
IN DWORD dwFlags,
IN DWORD dwFamily
)
{
DWORD dwResult, dwCount, dwOutBufLen;
MIB_UDPSTATS UdpInfo;
UDP6_LISTENER_TABLE **ppUdp6Table;
*ppUdpTable = NULL;
//
// Find out the number of entries the stack has. It returns this as part of
// the Tcp Stats. Also validate the dwFamily parameter.
//
dwResult = GetUdpStatsFromStackEx(&UdpInfo, dwFamily);
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,
"AllocateAndGetUdpExTableFromStack: Couldnt get Udp Stats From stack. Error %d",
dwResult);
return dwResult;
}
dwCount = UdpInfo.dwNumAddrs + OVERFLOW_COUNT;
if (dwFamily == AF_INET)
{
dwOutBufLen = FIELD_OFFSET(UDP_EX_TABLE, table[0])
+ (dwCount * sizeof(UDPEntryEx))
+ ALIGN_SIZE;
}
else
{
dwOutBufLen = FIELD_OFFSET(UDP6_LISTENER_TABLE, table[0])
+ (dwCount * sizeof(UDP6ListenerEntry))
+ ALIGN_SIZE;
}
*ppUdpTable = HeapAlloc(hHeap, dwFlags, dwOutBufLen);
if(*ppUdpTable is NULL)
{
dwResult = ERROR_NOT_ENOUGH_MEMORY;
Trace1(ERR,
"AllocateAndGetUdpExTableFromStack: Couldnt allocate memory. Error %d",
dwResult);
return dwResult;
}
if(UdpInfo.dwNumAddrs is 0)
{
(*ppUdpTable)->dwNumEntries = 0;
return NO_ERROR;
}
dwResult = GetUdpExTableFromStack(*ppUdpTable, dwOutBufLen, bOrder,
dwFamily);
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,
"AllocateAndGetUdpExTableFromStack: Error %d GetUdpExTableFromStack",
dwResult);
}
return dwResult;
}
DWORD
GetBestInterfaceFromIpv6Stack(
IN LPSOCKADDR_IN6 pSockAddr,
OUT PDWORD pdwBestIfIndex
)
{
DWORD dwOutBufLen, dwInBufLen, dwResult;
CHAR byBuffer[FIELD_OFFSET(TCP_REQUEST_QUERY_INFORMATION_EX, Context) +
sizeof(TDI_ADDRESS_IP6)];
TCP_REQUEST_QUERY_INFORMATION_EX *ptrqiInBuf = (TCP_REQUEST_QUERY_INFORMATION_EX *)byBuffer;
IP6RouteEntry Ire;
TDIObjectID *ID;
BYTE *Context;
ID = &(ptrqiInBuf->ID);
ID->toi_entity.tei_entity = CL_NL_ENTITY;
ID->toi_entity.tei_instance = 0;
ID->toi_class = INFO_CLASS_PROTOCOL;
ID->toi_type = INFO_TYPE_PROVIDER;
ID->toi_id = IP6_GET_BEST_ROUTE_ID;
RtlCopyMemory((PVOID)ptrqiInBuf->Context, &pSockAddr->sin6_port,
TDI_ADDRESS_LENGTH_IP6);
dwInBufLen = sizeof(byBuffer);
dwOutBufLen = sizeof(Ire);
dwResult = TCPQueryInformationEx(AF_INET6,
ptrqiInBuf,
&dwInBufLen,
(PVOID)&Ire,
&dwOutBufLen);
if (dwResult isnot NO_ERROR)
{
Trace1(ERR,"Couldn't query IPv6 stack. Error %d", dwResult);
TraceLeave("GetBestInterfaceEx");
return dwResult;
}
*pdwBestIfIndex = Ire.ire_IfIndex;
return dwResult;
}