windows-nt/Source/XPSP1/NT/net/tcpip/apis/iphlpapi/dll/stack.c

3527 lines
84 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
Abstract:
Revision History:
Amritansh Raghav
--*/
#include "inc.h"
#pragma hdrstop
#include <ntddip.h>
#ifdef CHICAGO
LPWSCONTROL pWsControl = NULL;
HANDLE hWsock = NULL;
#endif
extern HANDLE g_hIPDriverHandle;
extern HANDLE g_hIPGetDriverHandle;
extern HANDLE ChangeNotificationHandle;
extern HANDLE g_hIP6DriverHandle;
extern HANDLE g_hIP6GetDriverHandle;
extern HANDLE Change6NotificationHandle;
#ifdef DBG
int trace = 1;
#endif
DWORD
OpenTCPDriver(
IN DWORD dwFamily
);
DWORD
OpenIPDriver(
IN DWORD dwFamily
);
DWORD
CloseIPDriver();
DWORD
CloseIP6Driver();
TDIEntityID*
GetTdiEntityCount(
PULONG pulNumEntities
);
DWORD
GetArpEntryCount(
OUT PDWORD pdwNumEntries
);
int
TCPQueryInformationEx(
DWORD Family,
void *InBuf,
ulong *InBufLen,
void *OutBuf,
ulong *OutBufLen
);
int
TCPSetInformationEx(
void *InBuf,
ULONG *InBufLen,
void *OutBuf,
ULONG *OutBufLen
);
DWORD
AccessIfEntryInStack(
IN DWORD dwAction,
IN DWORD dwInstance,
IN OUT PMIB_IFROW pIfEntry
);
int
TCPSendIoctl(
HANDLE hHandle,
ulong Ioctl,
void *InBuf,
ulong *InBufLen,
void *OutBuf,
ulong *OutBufLen
);
// ========================================================================
#ifdef CHICAGO
uint
ConvertTdiErrorToDosError(uint TdiErr)
{
switch (TdiErr) {
case TDI_INVALID_REQUEST:
case TDI_INVALID_QUERY:
return ERROR_INVALID_FUNCTION;
case TDI_BUFFER_TOO_SMALL:
return ERROR_INSUFFICIENT_BUFFER;
case TDI_BUFFER_OVERFLOW:
return ERROR_INSUFFICIENT_BUFFER;
case TDI_PENDING:
return ERROR_SIGNAL_PENDING;
default:
return ERROR_INVALID_PARAMETER;
}
}
#endif
DWORD
AllocateAndGetIfTableFromStack(
OUT MIB_IFTABLE **ppIfTable,
IN BOOL bOrder,
IN HANDLE hHeap,
IN DWORD dwFlags,
IN BOOL bForceUpdate
)
{
DWORD dwResult, dwCount, dwOutBufLen;
MIB_IPSTATS miStats;
*ppIfTable = NULL;
dwResult = GetIpStatsFromStack(&miStats);
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,
"AllocateAndGetIfTableFromStack: Couldnt get Ip Stats From stack. Error %d",
dwResult);
return dwResult;
}
dwCount = miStats.dwNumIf + OVERFLOW_COUNT;
dwOutBufLen = SIZEOF_IFTABLE(dwCount);
*ppIfTable = HeapAlloc(hHeap,
dwFlags,
dwOutBufLen);
if(*ppIfTable is NULL)
{
dwResult = ERROR_NOT_ENOUGH_MEMORY;
Trace1(ERR,
"AllocateAndGetIfTableFromStack: Couldnt allocate memory. Error %d",
dwResult);
return dwResult;
}
if(miStats.dwNumIf is 0)
{
(*ppIfTable)->dwNumEntries = 0;
return NO_ERROR;
}
EnterCriticalSection(&g_ifLock);
if (!bForceUpdate && miStats.dwNumIf != g_dwNumIf)
{
bForceUpdate = TRUE;
}
g_dwNumIf = miStats.dwNumIf;
LeaveCriticalSection(&g_ifLock);
dwResult = GetIfTableFromStack(*ppIfTable,
dwOutBufLen,
bOrder,
bForceUpdate);
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,
"AllocateAndGetIfTableFromStack: Error %d calling GetIfTableFromStack",
dwResult);
HeapFree(hHeap, dwFlags, *ppIfTable);
*ppIfTable = NULL;
}
return dwResult;
}
// ========================================================================
DWORD
GetIfTableFromStack(
OUT PMIB_IFTABLE pIfTable,
IN DWORD dwSize,
IN BOOL bOrder,
IN BOOL bForceUpdate
)
/*++
Routine Description
Locks
None needed on entry. It takes the If lock within the function
Arguments
Return Value
NO_ERROR
--*/
{
DWORD i, dwNumRows, dwCount, dwErr, dwResult;
PLIST_ENTRY pCurrentNode;
LPAIHASH lpAIBlock;
dwNumRows = (dwSize - FIELD_OFFSET(MIB_IFTABLE,table[0]))/sizeof(MIB_IFROW);
dwCount = 0;
dwErr = NO_ERROR;
CheckTcpipState();
if (!g_bIpConfigured)
{
return ERROR_NOT_SUPPORTED;
}
EnterCriticalSection(&g_ifLock);
if(bForceUpdate or
(g_dwLastIfUpdateTime is 0) or
((GetCurrentTime() - g_dwLastIfUpdateTime) > IF_CACHE_LIFE))
{
dwResult = UpdateAdapterToIFInstanceMapping();
Trace0(ERR, "Update the mapping \n");
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,
"GetIfTableFromStack: Couldnt update map. Error %d",
dwResult);
LeaveCriticalSection(&g_ifLock);
return ERROR_CAN_NOT_COMPLETE;
}
}
for(i = 0; i < MAP_HASH_SIZE; i ++)
{
for(pCurrentNode = g_pAdapterMappingTable[i].Flink;
pCurrentNode isnot &(g_pAdapterMappingTable[i]);
pCurrentNode = pCurrentNode->Flink)
{
lpAIBlock = CONTAINING_RECORD(pCurrentNode,AIHASH,leList);
Trace1(ERR,
"Instance %d \n", lpAIBlock->dwIFInstance);
if(lpAIBlock->dwIFInstance is INVALID_IF_INSTANCE)
{
continue;
}
//
// If there is no more space in the buffer, bail out
//
if(dwCount >= dwNumRows)
{
Trace2(ERR,
"return here dwCount %d dwNumRows %d \n", dwCount, dwNumRows);
dwErr = ERROR_MORE_DATA;
break;
}
dwResult = AccessIfEntryInStack(GET_IF_ENTRY,
lpAIBlock->dwIFInstance,
&(pIfTable->table[dwCount]));
if(dwResult isnot NO_ERROR)
{
Trace2(ERR,
"GetIfTableFromStack: Err %d getting row for inst %d",
dwResult, lpAIBlock->dwIFInstance);
// dwErr = ERROR_MORE_DATA;
// at this point the stack doesn't have the interface
continue;
g_dwLastIfUpdateTime = 0;
}
else
{
dwCount++;
}
}
}
g_dwNumIf = dwCount;
LeaveCriticalSection(&g_ifLock);
pIfTable->dwNumEntries = dwCount;
if(bOrder && (dwCount > 0))
{
qsort(pIfTable->table,
dwCount,
sizeof(MIB_IFROW),
CompareIfRow);
}
return dwErr;
}
// ========================================================================
DWORD
GetIfEntryFromStack(
OUT PMIB_IFROW pIfEntry,
IN DWORD dwAdapterIndex,
IN BOOL bForceUpdate
)
/*++
Routine Description
Locks
Arguments
Return Value
NO_ERROR
--*/
{
DWORD dwResult,dwInBufLen,dwOutBufLen,dwInstance;
TDIObjectID *ID;
BYTE *Context;
TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
if (pIfEntry == NULL) {
return ERROR_INVALID_PARAMETER;
}
CheckTcpipState();
if (!g_bIpConfigured)
{
return ERROR_NOT_SUPPORTED;
}
EnterCriticalSection(&g_ifLock);
if(bForceUpdate)
{
dwResult = UpdateAdapterToIFInstanceMapping();
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,
"GetIfEntryFromStack: Couldnt update map. Error %d",
dwResult);
LeaveCriticalSection(&g_ifLock);
return ERROR_CAN_NOT_COMPLETE;
}
dwInstance = GetIFInstanceFromAdapter(dwAdapterIndex);
}
else
{
dwInstance = GetIFInstanceFromAdapter(dwAdapterIndex);
if(dwInstance is INVALID_IF_INSTANCE)
{
Trace0(ERR,
"GetIfEntryFromStack: Couldnt map to instance - first try");
dwResult = UpdateAdapterToIFInstanceMapping();
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,
"GetIfEntryFromStack: Couldnt update map. Error %d",
dwResult);
LeaveCriticalSection(&g_ifLock);
return ERROR_CAN_NOT_COMPLETE;
}
dwInstance = GetIFInstanceFromAdapter(dwAdapterIndex);
}
}
LeaveCriticalSection(&g_ifLock);
if(dwInstance is INVALID_IF_INSTANCE)
{
Trace0(ERR,
"GetIfEntryFromStack: Couldnt map to instance second try!!!!");
return ERROR_INVALID_DATA;
}
ID = &(trqiInBuf.ID);
ID->toi_entity.tei_entity = IF_ENTITY;
ID->toi_class = INFO_CLASS_PROTOCOL;
ID->toi_type = INFO_TYPE_PROVIDER;
ID->toi_id = IF_MIB_STATS_ID;
ID->toi_entity.tei_instance = dwInstance;
dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
dwOutBufLen = sizeof(IFEntry);
Context = (BYTE *) &(trqiInBuf.Context[0]);
ZeroMemory( Context, CONTEXT_SIZE );
dwResult = AccessIfEntryInStack(GET_IF_ENTRY,
dwInstance,
pIfEntry);
return dwResult;
}
// ========================================================================
DWORD
SetIfEntryToStack(
IN MIB_IFROW *pIfEntry,
IN BOOL bForceUpdate
)
/*++
Routine Description
Locks
Arguments
Return Value
NO_ERROR
--*/
{
DWORD dwResult,dwInstance;
CheckTcpipState();
if (!g_bIpConfigured)
{
return ERROR_NOT_SUPPORTED;
}
EnterCriticalSection(&g_ifLock);
if(bForceUpdate)
{
dwResult = UpdateAdapterToIFInstanceMapping();
if(dwResult isnot NO_ERROR)
{
LeaveCriticalSection(&g_ifLock);
Trace1(ERR,
"SetIfEntryToStack: Couldnt update map. Error %d",
dwResult);
return ERROR_CAN_NOT_COMPLETE;
}
dwInstance = GetIFInstanceFromAdapter(pIfEntry->dwIndex);
}
else
{
dwInstance = GetIFInstanceFromAdapter(pIfEntry->dwIndex);
if(dwInstance is INVALID_IF_INSTANCE)
{
Trace0(ERR,
"SetIfEntryToStack: Couldnt map to instance - first try");
dwResult = UpdateAdapterToIFInstanceMapping();
if(dwResult isnot NO_ERROR)
{
LeaveCriticalSection(&g_ifLock);
Trace1(ERR,
"SetIfEntryToStack: Couldnt update map. Error %d",
dwResult);
return ERROR_CAN_NOT_COMPLETE;
}
dwInstance = GetIFInstanceFromAdapter(pIfEntry->dwIndex);
}
}
if(dwInstance is INVALID_IF_INSTANCE)
{
LeaveCriticalSection(&g_ifLock);
Trace0(ERR,
"SetIfEntryToStack: Couldnt map to instance");
return ERROR_INVALID_DATA;
}
dwResult = AccessIfEntryInStack(SET_IF_ENTRY,
dwInstance,
pIfEntry);
LeaveCriticalSection(&g_ifLock);
return dwResult;
}
// ========================================================================
/*++
Routine Description
Arguments
dwAction Can be SET_IF or GET_IF
picb the Interface Control Block
lpOutBuf
Return Value
DWORD: NO_ERROR or some error code
--*/
DWORD
AccessIfEntryInStack(
IN DWORD dwAction,
IN DWORD dwInstance,
IN OUT PMIB_IFROW pIfEntry
)
{
DWORD dwResult;
DWORD dwInBufLen,dwOutBufLen;
TDIObjectID *ID;
BYTE *Context;
switch(dwAction)
{
case GET_IF_ENTRY:
{
TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
ID = &(trqiInBuf.ID);
Context = (BYTE *) &(trqiInBuf.Context[0]);
ID->toi_entity.tei_entity = IF_ENTITY;
ID->toi_class = INFO_CLASS_PROTOCOL;
ID->toi_type = INFO_TYPE_PROVIDER;
ID->toi_id = IF_MIB_STATS_ID;
dwOutBufLen = sizeof(MIB_IFROW) - FIELD_OFFSET(MIB_IFROW, dwIndex);
ID->toi_entity.tei_instance = dwInstance;
ZeroMemory( Context, CONTEXT_SIZE );
dwResult = TCPQueryInformationEx(AF_INET,
&trqiInBuf,
&dwInBufLen,
&(pIfEntry->dwIndex),
&dwOutBufLen);
break;
}
case SET_IF_ENTRY:
{
TCP_REQUEST_SET_INFORMATION_EX *lptrsiInBuf;
IFEntry *pifeSetInfo;
dwInBufLen = sizeof(TCP_REQUEST_SET_INFORMATION_EX) + sizeof(IFEntry) - 1;
lptrsiInBuf = HeapAlloc(g_hPrivateHeap,0,dwInBufLen);
if(lptrsiInBuf is NULL)
{
dwResult = ERROR_NOT_ENOUGH_MEMORY;
Trace1(ERR,
"AccessIfEntryInStack: Error %d allocating memory",
dwResult);
return dwResult;
}
ID = &lptrsiInBuf->ID;
ID->toi_class = INFO_CLASS_PROTOCOL;
ID->toi_type = INFO_TYPE_PROVIDER;
ID->toi_entity.tei_entity = IF_ENTITY;
ID->toi_id = IF_MIB_STATS_ID;
ID->toi_entity.tei_instance = dwInstance;
lptrsiInBuf->BufferSize = sizeof(IFEntry);
dwOutBufLen = 0;
pifeSetInfo = (IFEntry*)lptrsiInBuf->Buffer;
*pifeSetInfo = *(IFEntry*)(&(pIfEntry->dwIndex));
dwResult = TCPSetInformationEx((PVOID) lptrsiInBuf,
&dwInBufLen,
NULL,
&dwOutBufLen);
HeapFree(g_hPrivateHeap,0,lptrsiInBuf);
break;
}
}
return dwResult;
}
DWORD
NhpGetInterfaceIndexFromStack(
IN PWCHAR pwszIfName,
OUT PDWORD pdwIfIndex
)
/*++
Routine Description
Gets the interface index from IP
Locks
None
Arguments
pwszIfName NULL terminated unique name for interface
dwIfIndex [OUT] Interface Index
Return Value
NO_ERROR
ERROR_INVALID_PARAMETER
--*/
{
DWORD rgdwBuffer[255], dwStatus, dwInSize, dwOutSize;
PIP_GET_IF_INDEX_INFO pInfo;
#ifdef _WIN95_
return ERROR_NOT_SUPPORTED;
#else
CheckTcpipState();
if (!g_bIpConfigured)
{
return ERROR_NOT_SUPPORTED;
}
//
// The if name should be NULL terminated and should fit in the buffer
// above
//
if((FIELD_OFFSET(IP_GET_IF_INDEX_INFO, Name[0]) +
((wcslen(pwszIfName) + 1) * sizeof(WCHAR))) > sizeof(rgdwBuffer))
{
return ERROR_INVALID_PARAMETER;
}
pInfo = (PIP_GET_IF_INDEX_INFO)rgdwBuffer;
ZeroMemory(rgdwBuffer,
sizeof(rgdwBuffer));
wcscpy(pInfo->Name,
pwszIfName);
dwInSize = FIELD_OFFSET(IP_GET_IF_INDEX_INFO, Name[0]) +
((wcslen(pwszIfName) + 1) * sizeof(WCHAR));
dwOutSize = dwInSize;
dwStatus = TCPSendIoctl(g_hIPGetDriverHandle,
IOCTL_IP_GET_IF_INDEX,
pInfo,
&dwInSize,
pInfo,
&dwOutSize);
*pdwIfIndex = pInfo->Index;
return dwStatus;
#endif
}
DWORD
NhpAllocateAndGetInterfaceInfoFromStack(
OUT IP_INTERFACE_NAME_INFO **ppTable,
OUT PDWORD pdwCount,
IN BOOL bOrder,
IN HANDLE hHeap,
IN DWORD dwFlags
)
/*++
Routine Description
Internal no fuss routine for getting the interface info.
This is not an optimal routine when there are many interfaces in the
stack, since the allocations become huge
Locks
None
Arguments
ppTable Allocated table
pdwCount Number of entries in the allocated table
bOrder If TRUE, the table is ordered
hHeap Handle of heap to allocate from
dwFlags Flags to use for allocation
Return Value
NO_ERROR
--*/
{
MIB_IPSTATS miStats;
PIP_GET_IF_NAME_INFO pInfo;
DWORD i, dwResult, dwOutSize, dwInSize, dwCount;
*ppTable = NULL;
*pdwCount = 0;
dwResult = GetIpStatsFromStack(&miStats);
if(dwResult isnot NO_ERROR)
{
return dwResult;
}
dwCount = miStats.dwNumIf + OVERFLOW_COUNT;
dwOutSize = FIELD_OFFSET(IP_GET_IF_NAME_INFO, Info) +
(dwCount * sizeof(IP_INTERFACE_NAME_INFO));
dwInSize = FIELD_OFFSET(IP_GET_IF_NAME_INFO, Info);
pInfo = HeapAlloc(g_hPrivateHeap,
0,
dwOutSize);
if(pInfo is NULL)
{
return ERROR_NOT_ENOUGH_MEMORY;
}
pInfo->Context = 0;
dwResult = TCPSendIoctl(g_hIPGetDriverHandle,
IOCTL_IP_GET_IF_NAME,
pInfo,
&dwInSize,
pInfo,
&dwOutSize);
if(dwResult isnot NO_ERROR)
{
HeapFree(g_hPrivateHeap,
0,
pInfo);
return dwResult;
}
#if DBG
dwCount = (dwOutSize - FIELD_OFFSET(IP_GET_IF_NAME_INFO, Info))/sizeof(IP_INTERFACE_NAME_INFO);
ASSERT(dwCount is pInfo->Count);
#endif
if(pInfo->Count is 0)
{
HeapFree(g_hPrivateHeap,
0,
pInfo);
return ERROR_NO_DATA;
}
//
// Allocate for the user and copy out the info
//
dwOutSize = pInfo->Count * sizeof(IP_INTERFACE_NAME_INFO);
*ppTable = HeapAlloc(hHeap,
dwFlags,
dwOutSize);
if(*ppTable is NULL)
{
HeapFree(g_hPrivateHeap,
0,
pInfo);
return ERROR_NOT_ENOUGH_MEMORY;
}
//
// Copy out the info
//
for(i = 0; i < pInfo->Count; i++)
{
//
// Structure copy
//
(*ppTable)[i] = pInfo->Info[i];
}
if(pInfo->Count and bOrder)
{
qsort(*ppTable,
pInfo->Count,
sizeof(IP_INTERFACE_NAME_INFO),
NhiCompareIfInfoRow);
}
*pdwCount = pInfo->Count;
HeapFree(g_hPrivateHeap,
0,
pInfo);
return NO_ERROR;
}
// ========================================================================
DWORD
AllocateAndGetIpAddrTableFromStack(
OUT MIB_IPADDRTABLE **ppIpAddrTable,
IN BOOL bOrder,
IN HANDLE hHeap,
IN DWORD dwFlags
)
{
DWORD dwResult,dwCount;
DWORD dwOutBufLen;
MIB_IPSTATS IpSnmpInfo;
*ppIpAddrTable = NULL;
//
// Find out the number of entries the stack has. It returns this as part of
// the IP Stats
//
dwResult = GetIpStatsFromStack(&IpSnmpInfo);
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,
"AllocateAndGetIpAddrTableFromStack: Couldnt get Ip Stats From stack. Error %d",
dwResult);
return dwResult;
}
//
// Add extra to take care of increase between the two calls
//
dwCount = IpSnmpInfo.dwNumAddr + OVERFLOW_COUNT;
dwOutBufLen = SIZEOF_IPADDRTABLE(dwCount);
*ppIpAddrTable = HeapAlloc(hHeap,
dwFlags,
dwOutBufLen);
if(*ppIpAddrTable is NULL)
{
dwResult = ERROR_NOT_ENOUGH_MEMORY;
Trace1(ERR,
"AllocateAndGetIpAddrTableFromStack: Couldnt allocate memory. Error %d",
dwResult);
return dwResult;
}
if(IpSnmpInfo.dwNumAddr is 0)
{
//
// Just return an empty table.
// We do this because there is some code in MIB-II agent that
// expects to get a table back, even if there are not entries in
// it.
//
(*ppIpAddrTable)->dwNumEntries = 0;
return NO_ERROR;
}
dwResult = GetIpAddrTableFromStack(*ppIpAddrTable,
dwOutBufLen,
bOrder);
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,
"AllocateAndGetIpAddrTableFromStack: Error %d GetIpAddrTableFromStack",
dwResult);
HeapFree(hHeap, dwFlags, *ppIpAddrTable);
*ppIpAddrTable = NULL;
}
return dwResult;
}
// ========================================================================
DWORD
GetIpAddrTableFromStack(
OUT PMIB_IPADDRTABLE pIpAddrTable,
IN DWORD dwSize,
IN BOOL bOrder
)
{
DWORD dwOutBufLen, dwInBufLen, dwResult;
BYTE *Context;
TDIObjectID *ID;
TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
CheckTcpipState();
if (!g_bIpConfigured)
{
return ERROR_NOT_SUPPORTED;
}
ID = &(trqiInBuf.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 = IP_MIB_ADDRTABLE_ENTRY_ID;
Context = (BYTE *) &(trqiInBuf.Context[0]);
ZeroMemory(Context,CONTEXT_SIZE);
dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
dwOutBufLen = dwSize - FIELD_OFFSET(MIB_IPADDRTABLE, table[0]);
dwResult = TCPQueryInformationEx(AF_INET,
&trqiInBuf,
&dwInBufLen,
(PVOID)(pIpAddrTable->table),
&dwOutBufLen);
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,
"GetIpAddrTableFromStack: Couldnt Query information from stack. Error %x",
dwResult);
return (dwResult);
}
pIpAddrTable->dwNumEntries = (dwOutBufLen / sizeof(MIB_IPADDRROW));
//
// Now sort the address table. Key is IP address.
//
if((pIpAddrTable->dwNumEntries > 0) and bOrder)
{
qsort(pIpAddrTable->table,
pIpAddrTable->dwNumEntries,
sizeof(MIB_IPADDRROW),
CompareIpAddrRow);
}
return NO_ERROR;
}
// ========================================================================
DWORD
AllocateAndGetTcpTableFromStack(
OUT MIB_TCPTABLE **ppTcpTable,
IN BOOL bOrder,
IN HANDLE hHeap,
IN DWORD dwFlags
)
{
DWORD dwResult,dwCount;
DWORD dwOutBufLen;
MIB_TCPSTATS TcpInfo;
*ppTcpTable = NULL;
//
// Find out the number of entries the stack has. It returns this as part of
// the Tcp Stats
//
dwResult = GetTcpStatsFromStack(&TcpInfo);
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,
"AllocateAndGetTcpTableFromStack: Couldnt get Tcp Stats From stack. Error %d",
dwResult);
return dwResult;
}
dwCount = TcpInfo.dwNumConns + OVERFLOW_COUNT;
dwOutBufLen = SIZEOF_TCPTABLE(dwCount);
*ppTcpTable = HeapAlloc(hHeap,
dwFlags,
dwOutBufLen);
if(*ppTcpTable is NULL)
{
dwResult = ERROR_NOT_ENOUGH_MEMORY;
Trace1(ERR,
"AllocateAndGetTcpTableFromStack: Couldnt allocate memory. Error %d",
dwResult);
return dwResult;
}
if(TcpInfo.dwNumConns is 0)
{
(*ppTcpTable)->dwNumEntries = 0;
return NO_ERROR;
}
dwResult = GetTcpTableFromStack(*ppTcpTable,
dwOutBufLen,
bOrder);
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,
"AllocateAndGetTcpTableFromStack: Error %d GetTcpTableFromStack",
dwResult);
HeapFree(hHeap, dwFlags, *ppTcpTable);
*ppTcpTable = NULL;
}
return dwResult;
}
// ========================================================================
DWORD
GetTcpTableFromStack(
OUT PMIB_TCPTABLE pTcpTable,
IN DWORD dwSize,
IN BOOL bOrder
)
{
DWORD dwInBufLen, dwOutBufLen, dwResult;
TDIObjectID *ID;
BYTE *Context;
TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
CheckTcpipState();
if (!g_bIpConfigured)
{
return ERROR_NOT_SUPPORTED;
}
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_MIB_TABLE_ID;
Context = (BYTE *) &(trqiInBuf.Context[0]);
ZeroMemory( Context, CONTEXT_SIZE );
dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
dwOutBufLen = dwSize - FIELD_OFFSET(MIB_TCPTABLE, table[0]);
dwResult = TCPQueryInformationEx(AF_INET,
&trqiInBuf,
&dwInBufLen,
(PVOID)(pTcpTable->table),
&dwOutBufLen);
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,
"GetTcpTableFromStack: Couldnt query stack. Error %x",
dwResult);
return dwResult;
}
pTcpTable->dwNumEntries = (dwOutBufLen/sizeof(MIB_TCPROW));
if((pTcpTable->dwNumEntries > 0) and bOrder)
{
qsort(pTcpTable->table,
pTcpTable->dwNumEntries,
sizeof(MIB_TCPROW),
CompareTcpRow);
}
return NO_ERROR;
}
// ========================================================================
DWORD
SetTcpEntryToStack(
IN PMIB_TCPROW pTcpRow
)
{
TCP_REQUEST_SET_INFORMATION_EX *ptrsiInBuf;
TDIObjectID *ID;
MIB_TCPROW *copyInfo;
DWORD dwInBufLen,dwOutBufLen,dwResult;
#define REQ_SIZE sizeof(TCP_REQUEST_SET_INFORMATION_EX) + \
sizeof(MIB_TCPROW) - 1
BYTE rgbyBuffer[REQ_SIZE + 4]; // +4 to avoid any alignment problems
ptrsiInBuf = (TCP_REQUEST_SET_INFORMATION_EX *)rgbyBuffer;
dwInBufLen = REQ_SIZE;
#undef REQ_SIZE
CheckTcpipState();
if (!g_bIpConfigured)
{
return ERROR_NOT_SUPPORTED;
}
ID = &ptrsiInBuf->ID;
ID->toi_class = INFO_CLASS_PROTOCOL;
ID->toi_type = INFO_TYPE_PROVIDER;
ID->toi_entity.tei_entity = CO_TL_ENTITY;
ID->toi_id = TCP_MIB_TABLE_ID;
ID->toi_entity.tei_instance = 0;
copyInfo = (MIB_TCPROW*)ptrsiInBuf->Buffer;
*copyInfo = *pTcpRow;
ptrsiInBuf->BufferSize = sizeof(TCPConnTableEntry);
dwResult = TCPSetInformationEx((PVOID)ptrsiInBuf,
&dwInBufLen,
NULL,
&dwOutBufLen);
return dwResult;
}
// ========================================================================
DWORD
AllocateAndGetUdpTableFromStack(
OUT MIB_UDPTABLE **ppUdpTable,
IN BOOL bOrder,
IN HANDLE hHeap,
IN DWORD dwFlags
)
{
DWORD dwResult, dwCount, dwOutBufLen;
MIB_UDPSTATS UdpInfo;
*ppUdpTable = NULL;
//
// Find out the number of entries the stack has. It returns this as part of
// the Tcp Stats
//
dwResult = GetUdpStatsFromStack(&UdpInfo);
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,
"AllocateAndGetUdpTableFromStack: Couldnt get Udp Stats From stack. Error %d",
dwResult);
return dwResult;
}
dwCount = UdpInfo.dwNumAddrs + OVERFLOW_COUNT;
dwOutBufLen = SIZEOF_UDPTABLE(dwCount);
*ppUdpTable = HeapAlloc(hHeap,
dwFlags,
dwOutBufLen);
if(*ppUdpTable is NULL)
{
dwResult = ERROR_NOT_ENOUGH_MEMORY;
Trace1(ERR,
"AllocateAndGetUdpTableFromStack: Couldnt allocate memory. Error %d",
dwResult);
return dwResult;
}
if(UdpInfo.dwNumAddrs is 0)
{
(*ppUdpTable)->dwNumEntries = 0;
return NO_ERROR;
}
dwResult = GetUdpTableFromStack(*ppUdpTable,
dwOutBufLen,
bOrder);
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,
"AllocateAndGetUdpTableFromStack: Error %d GetUdpTableFromStack",
dwResult);
HeapFree(hHeap, dwFlags, *ppUdpTable);
*ppUdpTable = NULL;
}
return dwResult;
}
// ========================================================================
DWORD
GetUdpTableFromStack(
OUT PMIB_UDPTABLE pUdpTable,
IN DWORD dwSize,
IN BOOL bOrder
)
{
DWORD dwInBufLen, dwOutBufLen, dwResult;
BYTE *Context;
TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
TDIObjectID *ID;
CheckTcpipState();
if (!g_bIpConfigured)
{
return ERROR_NOT_SUPPORTED;
}
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_MIB_TABLE_ID;
Context = (BYTE *) &(trqiInBuf.Context[0]);
ZeroMemory( Context, CONTEXT_SIZE );
dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
dwOutBufLen = dwSize - FIELD_OFFSET(MIB_UDPTABLE, table[0]);
dwResult = TCPQueryInformationEx(AF_INET,
&trqiInBuf,
&dwInBufLen,
(PVOID)(pUdpTable->table),
&dwOutBufLen);
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,
"GetUdpTableFromStack: Couldnt query TCP information. Error %d",
dwResult);
return dwResult;
}
pUdpTable->dwNumEntries = (dwOutBufLen / sizeof(MIB_UDPROW));
//
// Now sort the UDP connection table. Keys are: local address, and local
// port.
//
if((pUdpTable->dwNumEntries > 0) and bOrder)
{
qsort(pUdpTable->table,
pUdpTable->dwNumEntries,
sizeof(MIB_UDPROW),
CompareUdpRow);
}
TraceLeave("GetUdpTableFromStack");
return NO_ERROR;
}
// ========================================================================
DWORD
AllocateAndGetIpForwardTableFromStack(
OUT MIB_IPFORWARDTABLE **ppForwardTable,
IN BOOL bOrder,
IN HANDLE hHeap,
IN DWORD dwFlags
)
{
DWORD dwResult,dwCount,dwOutBufLen;
MIB_IPSTATS IpInfo;
DWORD dwLoops;
TraceEnter("AllocateAndGetIpForwardTableFromStack");
*ppForwardTable = NULL;
dwLoops = 0;
while(dwLoops <= 1)
{
//
// Find out the number of entries the stack has. It returns this as
// part of the IP Stats
//
dwResult = GetIpStatsFromStack(&IpInfo);
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,"Couldnt get Ip Stats From stack. Error %d",
dwResult);
return dwResult;
}
dwCount = IpInfo.dwNumRoutes + ROUTE_OVERFLOW_COUNT + (dwLoops * 50);
dwOutBufLen = SIZEOF_IPFORWARDTABLE(dwCount);
*ppForwardTable = HeapAlloc(hHeap,
dwFlags,
dwOutBufLen);
if(*ppForwardTable is NULL)
{
dwResult = ERROR_NOT_ENOUGH_MEMORY;
Trace1(ERR,
"AllocateAndGetIpForwardTableFromStack: Couldnt allocate memory. Error %d",
dwResult);
return dwResult;
}
if(IpInfo.dwNumRoutes is 0)
{
(*ppForwardTable)->dwNumEntries = 0;
TraceLeave("AllocateAndGetIPForwardTableFromStack");
return NO_ERROR;
}
dwResult = GetIpForwardTableFromStack(*ppForwardTable,
dwOutBufLen,
bOrder);
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,
"AllocateAndGetIpForwardTableFromStack: Error %d GetIpForwardTableFromStack",
dwResult);
HeapFree(hHeap,
dwFlags,
*ppForwardTable);
*ppForwardTable = NULL;
}
if(dwResult is ERROR_MORE_DATA)
{
dwLoops++;
}
else
{
break;
}
}
return dwResult;
}
// ========================================================================
DWORD
GetIpForwardTableFromStack(
OUT PMIB_IPFORWARDTABLE pForwardTable,
IN DWORD dwSize,
IN BOOL bOrder
)
{
DWORD dwInBufLen, dwOutBufLen, dwNumRoutes;
DWORD i, dwCount, dwResult;
UCHAR *Context;
TDIObjectID *ID;
MIB_IPSTATS IpInfo;
IPRouteEntry *pTempTable;
TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
//
// How many routes can the input buffer hold?
//
dwNumRoutes = (dwSize - FIELD_OFFSET(MIB_IPFORWARDTABLE,table[0]))/sizeof(MIB_IPFORWARDROW);
//
// Find out the number of entries the stack has. It returns this as part of
// the IP Stats
//
dwResult = GetIpStatsFromStack(&IpInfo);
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,"Couldnt get Ip Stats From stack. Error %d",
dwResult);
return dwResult;
}
dwCount = IpInfo.dwNumRoutes + ROUTE_OVERFLOW_COUNT;
dwOutBufLen = dwCount * sizeof(IPRouteEntry);
pTempTable = HeapAlloc(g_hPrivateHeap,
0,
dwOutBufLen);
if(pTempTable is NULL)
{
dwResult = ERROR_NOT_ENOUGH_MEMORY;
Trace1(ERR,
"Couldnt allocate memory for temporary table. Error %d",
dwResult);
return dwResult;
}
ID = &(trqiInBuf.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 = IP_MIB_RTTABLE_ENTRY_ID;
Context = (BYTE *) &(trqiInBuf.Context[0]);
ZeroMemory(Context,
CONTEXT_SIZE );
dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
dwResult = TCPQueryInformationEx(AF_INET,
&trqiInBuf,
&dwInBufLen,
(PVOID)pTempTable,
&dwOutBufLen );
if(dwResult isnot NO_ERROR)
{
HeapFree(g_hPrivateHeap,
0,
pTempTable);
Trace1(ERR,"Couldnt query stack. Error %x",
dwResult);
TraceLeave("GetIpForwardTableFromStack");
return dwResult;
}
dwCount = (dwOutBufLen / sizeof(IPRouteEntry));
if(dwNumRoutes >= dwCount)
{
//
// There is space for all the entries returned by the stack
//
pForwardTable->dwNumEntries = dwCount;
}
else
{
//
// Take the first dwNumRoute entries
//
pForwardTable->dwNumEntries = dwNumRoutes;
dwResult = ERROR_MORE_DATA;
}
for (i = 0; i < pForwardTable->dwNumEntries; i++ )
{
ConvertRouteToForward(&(pTempTable[i]),
&(pForwardTable->table[i]));
}
HeapFree(g_hPrivateHeap,
0,
pTempTable);
if((pForwardTable->dwNumEntries > 0) and bOrder)
{
qsort(pForwardTable->table,
pForwardTable->dwNumEntries,
sizeof(MIB_IPFORWARDROW),
CompareIpForwardRow);
}
TraceLeave("GetIPForwardTableFromStack");
return dwResult;
}
// ========================================================================
DWORD
AllocateAndGetIpNetTableFromStack(
OUT MIB_IPNETTABLE **ppNetTable,
IN BOOL bOrder,
IN HANDLE hHeap,
IN DWORD dwFlags,
IN BOOL bForceUpdate
)
{
DWORD dwResult, dwOutBufLen, dwNetEntryCount;
DWORD dwCount;
TraceEnter("AllocateAndGetIpNetTableFromStack");
CheckTcpipState();
if (!g_bIpConfigured)
{
return ERROR_NOT_SUPPORTED;
}
*ppNetTable = NULL;
EnterCriticalSection(&g_ipNetLock);
dwResult = GetArpEntryCount(&dwNetEntryCount);
LeaveCriticalSection(&g_ipNetLock);
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,
"AllocateAndGetIpNetTableFromStack: Couldnt query Information from stack. Error %x",
dwResult);
TraceLeave("AllocateAndGetIpNetTableFromStack");
return dwResult;
}
//
// This is generally a memory hog
//
dwCount = dwNetEntryCount + (g_dwNumArpEntEntries) * OVERFLOW_COUNT;
dwOutBufLen = SIZEOF_IPNETTABLE(dwCount);
*ppNetTable = HeapAlloc(hHeap,
dwFlags,
dwOutBufLen);
if(*ppNetTable is NULL)
{
dwResult = ERROR_NOT_ENOUGH_MEMORY;
Trace1(ERR,
"AllocateAndGetIpNetTableFromStack: Couldnt allocate memory. Error %d",
dwResult);
TraceLeave("AllocateAndGetIpNetTableFromStack");
return dwResult;
}
if(dwNetEntryCount is 0)
{
(*ppNetTable)->dwNumEntries = 0;
TraceLeave("AllocateAndGetIpNetTableFromStack");
return NO_ERROR;
}
dwResult = GetIpNetTableFromStack(*ppNetTable,
dwOutBufLen,
bOrder,
bForceUpdate);
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,
"AllocateAndGetIpNetTableFromStack: Error %d GetIpNetTableFromStack",
dwResult);
HeapFree(hHeap, dwFlags, *ppNetTable);
*ppNetTable = NULL;
}
TraceLeave("AllocateAndGetIpNetTableFromStack");
return dwResult;
}
// ========================================================================
DWORD
GetIpNetTableFromStack(
OUT PMIB_IPNETTABLE pNetTable,
IN DWORD dwSize,
IN BOOL bOrder,
IN BOOL bForceUpdate
)
{
TDIObjectID *ID;
PBYTE pbyEnd, pbyStart, Context;
DWORD dwNumAdded,dwValidNetEntries;
DWORD dwInBufLen,dwOutBufLen;
DWORD dwResult, dwErr, i;
TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
CheckTcpipState();
if (!g_bIpConfigured)
{
return ERROR_NOT_SUPPORTED;
}
dwValidNetEntries = 0;
dwErr = NO_ERROR;
//
// Now query the stack for the IpNet tables of each of the arp entities
//
Context = (BYTE *) &(trqiInBuf.Context[0]);
ZeroMemory( Context, CONTEXT_SIZE );
ID = &(trqiInBuf.ID);
ID->toi_entity.tei_entity = AT_ENTITY;
ID->toi_type = INFO_TYPE_PROVIDER;
ID->toi_class = INFO_CLASS_PROTOCOL;
ID->toi_id = AT_MIB_ADDRXLAT_ENTRY_ID;
dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
pbyStart = (PBYTE)(pNetTable->table);
pbyEnd = (PBYTE)((PBYTE)pNetTable + dwSize);
EnterCriticalSection(&g_ipNetLock);
if(bForceUpdate or
(g_dwLastArpUpdateTime is 0) or
((GetCurrentTime() - g_dwLastArpUpdateTime) > ARP_CACHE_LIFE))
{
dwResult = UpdateAdapterToATInstanceMapping();
if(dwResult isnot NO_ERROR)
{
LeaveCriticalSection(&g_ipNetLock);
Trace1(ERR,
"GetIpNetTableFromStack: Couldnt update AT Map. Error %d",
dwResult);
TraceLeave("GetIpNetTableFromStack");
return ERROR_CAN_NOT_COMPLETE;
}
}
for(i = 0; i < g_dwNumArpEntEntries; i++ )
{
//
// If the current buffer wont hold even one row, stop
//
dwOutBufLen = (DWORD)(pbyEnd - pbyStart);
if(dwOutBufLen < sizeof(MIB_IPNETROW))
{
dwErr = ERROR_MORE_DATA;
break;
}
ID->toi_entity.tei_instance = g_pdwArpEntTable[i];
ZeroMemory(Context, CONTEXT_SIZE);
dwResult = TCPQueryInformationEx(AF_INET,
&trqiInBuf,
&dwInBufLen,
(PVOID)pbyStart,
&dwOutBufLen);
if (dwResult isnot NO_ERROR)
{
Trace1(ERR,"Query to Arp Entity id %d for ARP Table failed. Error %d",
dwResult);
dwErr = ERROR_MORE_DATA;
continue;
}
dwNumAdded = dwOutBufLen/(sizeof(MIB_IPNETROW));
pbyStart += dwOutBufLen;
dwValidNetEntries += dwNumAdded;
}
pNetTable->dwNumEntries = dwValidNetEntries;
//
// Now sort the net table. Keys are IF index and address
//
if((dwValidNetEntries > 0) and bOrder)
{
qsort(pNetTable->table,
dwValidNetEntries,
sizeof(MIB_IPNETROW),
CompareIpNetRow);
}
LeaveCriticalSection(&g_ipNetLock);
TraceLeave("GetIpNetTableFromStack");
return dwErr;
}
// ========================================================================
DWORD
GetIpStatsFromStackEx(
OUT PMIB_IPSTATS pIpStats,
IN DWORD dwFamily
)
{
DWORD dwResult, dwInBufLen, dwOutBufLen;
TDIObjectID *ID;
BYTE *Context;
TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
TraceEnter("GetIpStatsFromStackEx");
if ((dwFamily != AF_INET) && (dwFamily != AF_INET6))
{
return ERROR_INVALID_PARAMETER;
}
CheckTcpipState();
if (((dwFamily == AF_INET) && !g_bIpConfigured) ||
((dwFamily == AF_INET6) && !g_bIp6Configured))
{
return ERROR_NOT_SUPPORTED;
}
dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
dwOutBufLen = sizeof(MIB_IPSTATS);
ID = &(trqiInBuf.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 = IP_MIB_STATS_ID;
Context = (BYTE *) &(trqiInBuf.Context[0]);
ZeroMemory(Context, CONTEXT_SIZE);
dwResult = TCPQueryInformationEx(dwFamily,
&trqiInBuf,
&dwInBufLen,
(PVOID)pIpStats,
&dwOutBufLen);
if (dwResult isnot NO_ERROR)
{
Trace1(ERR,"Couldnt query stack. Error %d",
dwResult);
TraceLeave("GetIpStatsFromStackEx");
return dwResult;
}
TraceLeave("GetIpStatsFromStackEx");
return NO_ERROR;
}
// ========================================================================
DWORD
GetIpStatsFromStack(
OUT PMIB_IPSTATS pIpStats
)
{
return GetIpStatsFromStackEx(pIpStats, AF_INET);
}
// ========================================================================
DWORD
SetIpStatsToStack(
IN PMIB_IPSTATS pIpStats
)
{
TCP_REQUEST_SET_INFORMATION_EX *ptrsiInBuf;
TDIObjectID *ID;
MIB_IPSTATS *copyInfo;
DWORD dwInBufLen,dwOutBufLen,dwResult;
#define REQ_SIZE sizeof(TCP_REQUEST_SET_INFORMATION_EX) + \
sizeof(MIB_IPSTATS) - 1
BYTE rgbyBuffer[REQ_SIZE + 4]; // +4 to avoid any alignment problems
ptrsiInBuf = (TCP_REQUEST_SET_INFORMATION_EX *)rgbyBuffer;
dwInBufLen = REQ_SIZE;
#undef REQ_SIZE
TraceEnter("SetIpStatsToStack");
CheckTcpipState();
if (!g_bIpConfigured)
{
return ERROR_NOT_SUPPORTED;
}
ID = &ptrsiInBuf->ID;
ID->toi_class = INFO_CLASS_PROTOCOL;
ID->toi_type = INFO_TYPE_PROVIDER;
ID->toi_entity.tei_entity = CL_NL_ENTITY;
ID->toi_id = IP_MIB_STATS_ID;
ID->toi_entity.tei_instance = 0;
copyInfo = (MIB_IPSTATS*)ptrsiInBuf->Buffer;
*copyInfo = *pIpStats;
ptrsiInBuf->BufferSize = sizeof(IPSNMPInfo);
dwResult = TCPSetInformationEx((PVOID)ptrsiInBuf,
&dwInBufLen,
NULL,
&dwOutBufLen);
TraceLeave("SetIpStatsToStack");
return dwResult;
}
// ========================================================================
DWORD
GetIcmpStatsFromStackEx(
OUT PVOID pIcmpStats,
IN DWORD dwFamily
)
{
DWORD dwResult;
DWORD dwInBufLen;
DWORD dwOutBufLen;
TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
TDIObjectID *ID;
BYTE *Context;
TraceEnter("GetIcmpStatsFromStackEx");
if ((dwFamily != AF_INET) && (dwFamily != AF_INET6))
{
return ERROR_INVALID_PARAMETER;
}
CheckTcpipState();
if (((dwFamily == AF_INET) && !g_bIpConfigured) ||
((dwFamily == AF_INET6) && !g_bIp6Configured))
{
return ERROR_NOT_SUPPORTED;
}
dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
ID = &(trqiInBuf.ID);
ID->toi_entity.tei_instance = 0;
ID->toi_class = INFO_CLASS_PROTOCOL;
ID->toi_type = INFO_TYPE_PROVIDER;
if (dwFamily == AF_INET)
{
ID->toi_entity.tei_entity = ER_ENTITY;
ID->toi_id = ICMP_MIB_STATS_ID;
dwOutBufLen = sizeof(MIB_ICMP);
}
else
{
ID->toi_entity.tei_entity = CL_NL_ENTITY;
ID->toi_id = ICMP6_MIB_STATS_ID;
dwOutBufLen = sizeof(ICMPv6SNMPInfo);
}
Context = (BYTE *) &(trqiInBuf.Context[0]);
ZeroMemory(Context,CONTEXT_SIZE);
dwResult = TCPQueryInformationEx(dwFamily,
&trqiInBuf,
&dwInBufLen,
(PVOID)pIcmpStats,
&dwOutBufLen);
if (dwResult isnot NO_ERROR)
{
Trace1(ERR,"Couldnt query stack. Error %x",
dwResult);
TraceLeave("GetIcmpStatsFromStackEx");
return dwResult;
}
TraceLeave("GetIcmpStatsFromStackEx");
return NO_ERROR;
}
// ========================================================================
DWORD
GetIcmpStatsFromStack(
OUT PMIB_ICMP pIcmpStats
)
{
return GetIcmpStatsFromStackEx(pIcmpStats, AF_INET);
}
// ========================================================================
DWORD
GetUdpStatsFromStackEx(
OUT PMIB_UDPSTATS pUdpStats,
IN DWORD dwFamily
)
{
DWORD dwResult;
DWORD dwInBufLen;
DWORD dwOutBufLen;
TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
TDIObjectID *ID;
BYTE *Context;
TraceEnter("GetUdpStatsFromStack");
if ((dwFamily != AF_INET) && (dwFamily != AF_INET6))
{
return ERROR_INVALID_PARAMETER;
}
CheckTcpipState();
if (((dwFamily == AF_INET) && !g_bIpConfigured) ||
((dwFamily == AF_INET6) && !g_bIp6Configured))
{
return ERROR_NOT_SUPPORTED;
}
dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
dwOutBufLen = sizeof(MIB_UDPSTATS);
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_MIB_STAT_ID;
Context = (BYTE *) &(trqiInBuf.Context[0]);
ZeroMemory( Context, CONTEXT_SIZE );
dwResult = TCPQueryInformationEx(dwFamily,
&trqiInBuf,
&dwInBufLen,
(PVOID)pUdpStats,
&dwOutBufLen );
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,"Couldnt query stack. Error %x",
dwResult);
TraceLeave("GetUdpStatsFromStack");
return dwResult;
}
TraceLeave("GetUdpStatsFromStack");
return NO_ERROR;
}
// ========================================================================
DWORD
GetUdpStatsFromStack(
OUT PMIB_UDPSTATS pUdpStats
)
{
return GetUdpStatsFromStackEx(pUdpStats, AF_INET);
}
// ========================================================================
DWORD
GetTcpStatsFromStackEx(
OUT PMIB_TCPSTATS pTcpStats,
IN DWORD dwFamily
)
{
DWORD dwResult;
DWORD dwInBufLen;
DWORD dwOutBufLen;
TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
TDIObjectID *ID;
BYTE *Context;
TraceEnter("GetTcpStatsFromStack");
if ((dwFamily != AF_INET) && (dwFamily != AF_INET6))
{
return ERROR_INVALID_PARAMETER;
}
CheckTcpipState();
if (((dwFamily == AF_INET) && !g_bIpConfigured) ||
((dwFamily == AF_INET6) && !g_bIp6Configured))
{
return ERROR_NOT_SUPPORTED;
}
dwInBufLen = sizeof( TCP_REQUEST_QUERY_INFORMATION_EX );
dwOutBufLen = sizeof( MIB_TCPSTATS );
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_MIB_STAT_ID;
Context = (BYTE *) &(trqiInBuf.Context[0]);
ZeroMemory(Context,CONTEXT_SIZE);
dwResult = TCPQueryInformationEx(dwFamily,
&trqiInBuf,
&dwInBufLen,
(PVOID)pTcpStats,
&dwOutBufLen );
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,"Couldnt query stack. Error %x",
dwResult);
TraceLeave("GetTcpStatsFromStack");
return dwResult;
}
TraceLeave("GetTcpStatsFromStack");
return NO_ERROR;
}
// ========================================================================
DWORD
GetTcpStatsFromStack(
OUT PMIB_TCPSTATS pTcpStats
)
{
return GetTcpStatsFromStackEx(pTcpStats, AF_INET);
}
// ========================================================================
DWORD
SetIpNetEntryToStack(
IN MIB_IPNETROW *pNetRow,
IN BOOL bForceUpdate
)
{
TCP_REQUEST_SET_INFORMATION_EX *ptrsiInBuf;
TDIObjectID *ID;
MIB_IPNETROW *copyInfo;
DWORD dwInBufLen,dwOutBufLen,dwResult;
DWORD dwInstance;
#define REQ_SIZE sizeof(TCP_REQUEST_SET_INFORMATION_EX) + \
sizeof(MIB_IPNETROW) - 1
BYTE rgbyBuffer[REQ_SIZE + 4]; // +4 to avoid any alignment problems
ptrsiInBuf = (TCP_REQUEST_SET_INFORMATION_EX *)rgbyBuffer;
dwInBufLen = REQ_SIZE;
#undef REQ_SIZE
TraceEnter("SetIpNetEntryToStack");
CheckTcpipState();
if (!g_bIpConfigured)
{
return ERROR_NOT_SUPPORTED;
}
EnterCriticalSection(&g_ipNetLock);
if(bForceUpdate or
(g_dwLastArpUpdateTime is 0) or
((GetCurrentTime() - g_dwLastArpUpdateTime) < ARP_CACHE_LIFE))
{
dwResult = UpdateAdapterToATInstanceMapping();
if(dwResult isnot NO_ERROR)
{
LeaveCriticalSection(&g_ipNetLock);
Trace1(ERR,"Couldnt update AT Map. Error %d",dwResult);
TraceLeave("SetIpNetEntryToStack");
return ERROR_CAN_NOT_COMPLETE;
}
}
dwInstance = GetATInstanceFromAdapter(pNetRow->dwIndex);
if(dwInstance is INVALID_AT_INSTANCE)
{
dwResult = UpdateAdapterToATInstanceMapping();
if(dwResult isnot NO_ERROR)
{
LeaveCriticalSection(&g_ipNetLock);
Trace1(ERR,"Couldnt update AT Map. Error %d",dwResult);
return ERROR_CAN_NOT_COMPLETE;
}
}
LeaveCriticalSection(&g_ipNetLock);
ID = &ptrsiInBuf->ID;
ID->toi_class = INFO_CLASS_PROTOCOL;
ID->toi_entity.tei_entity = AT_ENTITY;
ID->toi_type = INFO_TYPE_PROVIDER;
ID->toi_id = AT_MIB_ADDRXLAT_ENTRY_ID;
ID->toi_entity.tei_instance = dwInstance;
//
// Since MIB_IPNETROW is a fixed size structure
//
copyInfo = (MIB_IPNETROW*)ptrsiInBuf->Buffer;
*copyInfo = *pNetRow;
dwOutBufLen = 0;
ptrsiInBuf->BufferSize = sizeof(IPNetToMediaEntry);
dwResult = TCPSetInformationEx((PVOID)ptrsiInBuf,
&dwInBufLen,
NULL,
&dwOutBufLen);
TraceLeave("SetIpNetEntryToStack");
return dwResult;
}
DWORD
FlushIpNetTableFromStack(
IN DWORD dwIfIndex
)
{
#ifdef _WIN95_
return ERROR_NOT_SUPPORTED;
#else
DWORD status;
DWORD requestBufferSize = sizeof(DWORD);
DWORD OutBufLen= 0;
CheckTcpipState();
if (!g_bIpConfigured)
{
return ERROR_NOT_SUPPORTED;
}
status = TCPSendIoctl(g_hIPDriverHandle,
IOCTL_IP_FLUSH_ARP_TABLE,
&dwIfIndex,
&requestBufferSize,
NULL,
&OutBufLen);
#endif
return(status);
}
DWORD
SetProxyArpEntryToStack(
DWORD dwAddress,
DWORD dwMask,
DWORD dwAdapterIndex,
BOOL bAddEntry,
BOOL bForceUpdate
)
{
DWORD dwResult, dwATInstance, dwInBufLen, dwOutBufLen;
ProxyArpEntry *pEntry;
TDIObjectID *pID;
PTCP_REQUEST_SET_INFORMATION_EX ptrsiInBuf;
#define REQ_SIZE sizeof(TCP_REQUEST_SET_INFORMATION_EX) + \
sizeof(ProxyArpEntry) - 1
BYTE rgbyBuffer[REQ_SIZE + 4]; // +4 to avoid any alignment problems
ptrsiInBuf = (TCP_REQUEST_SET_INFORMATION_EX *)rgbyBuffer;
dwInBufLen = REQ_SIZE;
#undef REQ_SIZE
TraceEnter("SetProxyArpEntryToStack");
CheckTcpipState();
if (!g_bIpConfigured)
{
return ERROR_NOT_SUPPORTED;
}
EnterCriticalSection(&g_ipNetLock);
if(bForceUpdate or
(g_dwLastArpUpdateTime is 0) or
((GetCurrentTime() - g_dwLastArpUpdateTime) < ARP_CACHE_LIFE))
{
dwResult = UpdateAdapterToATInstanceMapping();
if(dwResult isnot NO_ERROR)
{
LeaveCriticalSection(&g_ipNetLock);
Trace1(ERR,"Couldnt update AT Map. Error %d",dwResult);
TraceLeave("SetProxyArpEntryToStack");
return ERROR_CAN_NOT_COMPLETE;
}
}
dwATInstance = GetATInstanceFromAdapter(dwAdapterIndex);
if(dwATInstance is INVALID_IF_INSTANCE)
{
LeaveCriticalSection(&g_ipNetLock);
Trace1(ERR,
"SetProxyArpEntryToStacki: Couldnt get AT instance for %d",
dwAdapterIndex);
TraceLeave("SetProxyArpEntryToStack");
return ERROR_INVALID_PARAMETER;
}
LeaveCriticalSection(&g_ipNetLock);
pID = &ptrsiInBuf->ID;
pID->toi_entity.tei_entity = AT_ENTITY;
pID->toi_entity.tei_instance = dwATInstance;
pID->toi_type = INFO_TYPE_PROVIDER;
pID->toi_class = INFO_CLASS_IMPLEMENTATION;
pID->toi_id = AT_ARP_PARP_ENTRY_ID;
//
// Fill in the set entry, and pass it down.
//
pEntry = (ProxyArpEntry *)ptrsiInBuf->Buffer;
pEntry->pae_status = (bAddEntry ? PAE_STATUS_VALID : PAE_STATUS_INVALID);
pEntry->pae_addr = dwAddress;
pEntry->pae_mask = dwMask;
ptrsiInBuf->BufferSize = sizeof(ProxyArpEntry);
dwOutBufLen = 0;
dwResult = TCPSetInformationEx((PVOID)ptrsiInBuf,
&dwInBufLen,
NULL,
&dwOutBufLen);
TraceLeave("SetProxyArpEntryToStack");
return dwResult;
}
// ========================================================================
DWORD
GetArpEntryCount(
OUT PDWORD pdwNumEntries
)
{
DWORD dwResult, i;
DWORD dwInBufLen, dwOutBufLen;
TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
TDIObjectID *ID;
UCHAR *Context;
AddrXlatInfo AXI;
*pdwNumEntries = 0;
Context = (BYTE *) &(trqiInBuf.Context[0]);
ZeroMemory( Context, CONTEXT_SIZE );
ID = &(trqiInBuf.ID);
ID->toi_entity.tei_entity = AT_ENTITY;
ID->toi_type = INFO_TYPE_PROVIDER;
dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
for (i = 0; i < g_dwNumArpEntEntries; i++ )
{
//
// First add up the AXI counts
//
ID->toi_class = INFO_CLASS_PROTOCOL;
ID->toi_id = AT_MIB_ADDRXLAT_INFO_ID;
ID->toi_entity.tei_instance = g_pdwArpEntTable[i];
dwOutBufLen = sizeof(AXI);
ZeroMemory(Context, CONTEXT_SIZE);
dwResult = TCPQueryInformationEx(AF_INET,
&trqiInBuf,
&dwInBufLen,
&AXI,
&dwOutBufLen);
if (dwResult == ERROR_INVALID_FUNCTION)
{
Trace0(ERR, "GetArpEntryCount: ERROR_INVALID_FUNCTION, axi_count = 0");
AXI.axi_count = 0;
}
else if(dwResult isnot NO_ERROR)
{
Trace1(ERR,"GetArpEntryCount: Couldnt query Information from stack. Error %x",
dwResult);
return dwResult;
}
//
// Increment the total number of entries
//
*pdwNumEntries += AXI.axi_count;
}
return NO_ERROR;
}
// ========================================================================
DWORD
AllocateAndGetArpEntTableFromStack(
OUT PDWORD *ppdwArpEntTable,
OUT PDWORD pdwNumEntries,
IN HANDLE hHeap,
IN DWORD dwAllocFlags,
IN DWORD dwReAllocFlags
)
{
DWORD dwResult;
DWORD dwInBufLen;
DWORD dwOutBufLen;
TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
DWORD dwATType;
UCHAR *Context;
TDIObjectID *ID;
TDIEntityID *pEntTable;
DWORD dwNumEntities,dwCurrEntries;
DWORD i,dwCount ;
TraceEnter("GetArpEntTableFromStack");
CheckTcpipState();
if (!g_bIpConfigured)
{
return ERROR_NOT_SUPPORTED;
}
*ppdwArpEntTable = NULL;
*pdwNumEntries = 0;
pEntTable = GetTdiEntityCount(&dwNumEntities);
if (!pEntTable)
{
return ERROR_NOT_ENOUGH_MEMORY;
}
//
// Create a table that will hold 16 entries
//
dwCurrEntries = 16;
*ppdwArpEntTable = HeapAlloc(hHeap,
dwAllocFlags,
dwCurrEntries*sizeof(DWORD));
if(*ppdwArpEntTable is NULL)
{
dwResult = ERROR_NOT_ENOUGH_MEMORY;
Trace1(ERR,"GetArpEntTableFromStack: Couldnt allocate memory. Error %d",
dwResult);
HeapFree(g_hPrivateHeap,0,pEntTable);
return dwResult;
}
dwCount = 0;
Trace1(ERR, "Numberofentities %d \n", dwNumEntities);
for(i = 0; i < dwNumEntities; i++)
{
//
// See which ones are AT
//
if(pEntTable[i].tei_entity is AT_ENTITY)
{
//
// Query the entity to see if it supports ARP
//
ID = &(trqiInBuf.ID);
ID->toi_entity.tei_entity = AT_ENTITY;
ID->toi_class = INFO_CLASS_GENERIC;
ID->toi_type = INFO_TYPE_PROVIDER;
ID->toi_id = ENTITY_TYPE_ID;
ID->toi_entity.tei_instance = pEntTable[i].tei_instance;
Trace1(ERR,
"Querying for instance %d \n", pEntTable[i].tei_instance);
dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
dwOutBufLen = sizeof(dwATType);
Context = (BYTE *) &(trqiInBuf.Context[0]);
ZeroMemory(Context,CONTEXT_SIZE);
dwResult = TCPQueryInformationEx(AF_INET,
&trqiInBuf,
&dwInBufLen,
(PVOID)&dwATType,
&dwOutBufLen );
if(dwResult is ERROR_INVALID_FUNCTION)
{
//
// Doesnt support ARP
//
continue;
}
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,"GetArpEntTableFromStack: Couldnt query information. Error %x",
dwResult);
HeapFree(hHeap,0,*ppdwArpEntTable);
HeapFree(g_hPrivateHeap,0,pEntTable);
return dwResult;
}
if(dwATType is AT_ARP)
{
//
// The entity is an AT_ENTITY that supports ARP. Add the instance
// to the arp entity table. If the current count >= current size of
// table, means we have run out of space, so reallocate and get double
// the space
//
if(dwCount is dwCurrEntries)
{
PDWORD pdwNewTable;
pdwNewTable = HeapReAlloc(hHeap,
dwReAllocFlags,
(PVOID)*ppdwArpEntTable,
((dwCurrEntries)<<1)*sizeof(DWORD));
if(pdwNewTable is NULL)
{
dwResult = GetLastError();
Trace1(ERR,"GetArpEntTableFromStack: Couldnt reallocate memory. Error %d",
dwResult);
HeapFree(hHeap,0,*ppdwArpEntTable);
HeapFree(g_hPrivateHeap,0,pEntTable);
return dwResult;
}
*ppdwArpEntTable = pdwNewTable;
dwCurrEntries = dwCurrEntries<<1;
}
(*ppdwArpEntTable)[dwCount] = pEntTable[i].tei_instance;
dwCount++;
}
}
}
HeapFree(g_hPrivateHeap,0,pEntTable);
*pdwNumEntries = dwCount;
return NO_ERROR;
}
// ========================================================================
DWORD
SetIpForwardEntryToStack(
IN PMIB_IPFORWARDROW pForwardRow
)
{
IPRouteEntry route;
CheckTcpipState();
if (!g_bIpConfigured)
{
return ERROR_NOT_SUPPORTED;
}
ConvertForwardToRoute((&route),pForwardRow);
return SetIpRouteEntryToStack(&route);
}
// ========================================================================
DWORD
SetIpRouteEntryToStack(
IN IPRouteEntry *pRoute
)
{
TDIObjectID *pObject;
DWORD dwOutBufLen, dwInBufLen, dwResult;
TCP_REQUEST_SET_INFORMATION_EX *ptrsiBuffer;
IPRouteEntry *copyInfo;
#define REQ_SIZE sizeof(TCP_REQUEST_SET_INFORMATION_EX) + sizeof(IPRouteEntry) - 1
BYTE rgbyBuffer[REQ_SIZE + 4]; // +4 to avoid any alignment problems
ptrsiBuffer = (TCP_REQUEST_SET_INFORMATION_EX *)rgbyBuffer;
dwInBufLen = REQ_SIZE;
#undef REQ_SIZE
CheckTcpipState();
if (!g_bIpConfigured)
{
return ERROR_NOT_SUPPORTED;
}
ptrsiBuffer->BufferSize = sizeof(IPRouteEntry);
pObject = &ptrsiBuffer->ID;
pObject->toi_id = IP_MIB_RTTABLE_ENTRY_ID;
pObject->toi_type = INFO_TYPE_PROVIDER;
pObject->toi_class = INFO_CLASS_PROTOCOL;
pObject->toi_entity.tei_entity = CL_NL_ENTITY;
pObject->toi_entity.tei_instance = 0;
dwOutBufLen = 0;
copyInfo = (IPRouteEntry *)ptrsiBuffer->Buffer;
*copyInfo = *pRoute;
dwResult = TCPSetInformationEx((PVOID)ptrsiBuffer,
&dwInBufLen,
NULL,
&dwOutBufLen);
return dwResult;
}
DWORD
SetIpMultihopRouteEntryToStack(
IN IPMultihopRouteEntry *RouteEntry
)
{
ULONG inpbuflen;
ULONG outbuflen;
CheckTcpipState();
if (!g_bIpConfigured)
{
return ERROR_NOT_SUPPORTED;
}
inpbuflen = sizeof(IPMultihopRouteEntry);
if (RouteEntry->imre_numnexthops > 2)
{
inpbuflen += (RouteEntry->imre_numnexthops - 2) *
sizeof(IPRouteNextHopEntry);
}
if (IsBadReadPtr(RouteEntry, inpbuflen)) {
return ERROR_INVALID_PARAMETER;
}
return (TCPSendIoctl(
g_hIPDriverHandle,
IOCTL_IP_SET_MULTIHOPROUTE,
RouteEntry,
&inpbuflen,
NULL,
&outbuflen
));
}
DWORD
GetBestInterfaceFromStack(
DWORD dwDestAddress,
PDWORD pdwBestIfIndex
)
{
#ifdef _WIN95_
return ERROR_NOT_SUPPORTED;
#else
DWORD status;
DWORD requestBufferSize = sizeof(DWORD);
DWORD OutBufLen= sizeof(DWORD);
CheckTcpipState();
if (!g_bIpConfigured)
{
return ERROR_NOT_SUPPORTED;
}
status = TCPSendIoctl(g_hIPGetDriverHandle,
IOCTL_IP_GET_BEST_INTERFACE,
&dwDestAddress,
&requestBufferSize,
pdwBestIfIndex,
&OutBufLen);
return(status);
#endif
}
// ========================================================================
//* TCPQueryInformationEx
//
// Description: Get information from the stack.
//
// Parameters: HANDLE hHandle: handle to the stack.
// TDIObjectID *ID: pointer to TDIObjectID info.
// void *Buffer: buffer to receive data from the stack.
// ulong *Bufferlen: IN: tells stack size of available buffer,
// OUT: tells us how much data is available.
// CONTEXT *Context: allows queries spanning more than one call.
//
// Returns: int:
//
//*
int
TCPQueryInformationEx(
DWORD Family,
void *InBuf,
ulong *InBufLen,
void *OutBuf,
ulong *OutBufLen
)
{
#ifdef CHICAGO
//
// This section is obsolete code
//
DWORD result;
if( ! pWsControl ) {
OpenTCPDriver(AF_INET);
}
if( ! pWsControl || (Family != AF_INET)) {
DEBUG_PRINT(("TCPQueryInformationEx: !pWsControl.\n"));
return ERROR_NOT_SUPPORTED;
}
assert( pWsControl );
result = (
(*pWsControl)(
IPPROTO_TCP,
WSCNTL_TCPIP_QUERY_INFO,
InBuf,
InBufLen ,
OutBuf,
OutBufLen
) );
if( result ){
return ConvertTdiErrorToDosError(result);
}
return NO_ERROR;
#else
NTSTATUS Status;
IO_STATUS_BLOCK IoStatusBlock;
HANDLE hEvent;
HANDLE hDriver = (Family == AF_INET)? g_hTCPDriverGetHandle :
g_hTCP6DriverGetHandle;
hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
if( NULL == hEvent ) return GetLastError();
Status = NtDeviceIoControlFile(hDriver,
hEvent,
NULL,
NULL,
&IoStatusBlock,
IOCTL_TCP_QUERY_INFORMATION_EX,
InBuf,
*InBufLen,
OutBuf,
*OutBufLen );
if ( Status == STATUS_PENDING )
{
Status = NtWaitForSingleObject(hEvent, FALSE, NULL );
Status = IoStatusBlock.Status;
}
CloseHandle(hEvent);
if ( !NT_SUCCESS( Status ) )
{
Trace1(ERR,"Device IOCTL failed in TCPQuery %x",Status);
*OutBufLen = 0;
return ( RtlNtStatusToDosError(Status) );
}
//
// Tell caller how much was written
//
*OutBufLen = (ULONG)IoStatusBlock.Information;
return ( NO_ERROR );
#endif
}
// ========================================================================
//* TCPSendIoctl
//
// Description: Get information from the stack.
//
// Parameters: HANDLE hHandle: handle to the stack.
// TDIObjectID *ID: pointer to TDIObjectID info.
// void *Buffer: buffer to receive data from the stack.
// ulong *Bufferlen: IN: tells stack size of available buffer,
// OUT: tells us how much data is available.
// CONTEXT *Context: allows queries spanning more than one call.
//
// Returns: int:
//
//*
int
TCPSendIoctl( HANDLE hHandle,
ulong Ioctl,
void *InBuf,
ulong *InBufLen,
void *OutBuf,
ulong *OutBufLen)
{
#ifdef CHICAGO
// OVERLAPPED overlap;
uint ok;
ok = DeviceIoControl( hHandle, Ioctl,
InBuf, *InBufLen,
OutBuf, *OutBufLen, OutBufLen,
NULL // &overlap
);
if( !ok ){
int err = GetLastError();
DEBUG_PRINT(("TCPSendIoctl: DeviceIoControl err %d\n", err ));
return err;
}
return NO_ERROR;
#else
NTSTATUS Status;
IO_STATUS_BLOCK IoStatusBlock;
HANDLE hEvent;
hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
if( NULL == hEvent ) return GetLastError();
ZeroMemory(&IoStatusBlock, sizeof(IoStatusBlock));
Status = NtDeviceIoControlFile(hHandle,
hEvent,
NULL,
NULL,
&IoStatusBlock,
Ioctl,
InBuf,
*InBufLen,
OutBuf,
*OutBufLen );
if ( Status == STATUS_PENDING )
{
Status = NtWaitForSingleObject( hEvent, FALSE, NULL );
Status = IoStatusBlock.Status;
}
CloseHandle(hEvent);
if ( !NT_SUCCESS( Status ) )
{
Trace1(ERR,"Device IOCTL failed in TCPSendIoctl %x",Status);
if (OutBufLen)
*OutBufLen = (ULONG)IoStatusBlock.Information;
return ( RtlNtStatusToDosError(Status) );
}
//
// Tell caller how much was written
//
if (OutBufLen)
*OutBufLen = (ULONG)IoStatusBlock.Information;
return ( NO_ERROR );
#endif
}
// ========================================================================
//* TCPSetInformationEx()
//
// Description: Send information to the stack
//
// Parameters: HANDLE hHandle: handle to the stack.
// TDIObjectID *ID: pointer to TDIObjectID info.
// void *Buffer: buffer to receive data from the stack.
// ulong Bufferlen: tells stack size of available buffer,
//
// Returns: int:
//
//*
int
TCPSetInformationEx(
void *InBuf,
ULONG *InBufLen,
void *OutBuf,
ULONG *OutBufLen
)
{
#ifdef CHICAGO
DWORD result;
if( ! pWsControl )
OpenTCPDriver(AF_INET);
if( ! pWsControl ){
DEBUG_PRINT(("TCPQueryInformationEx: !pWsControl.\n"));
return 0;
}
assert( pWsControl );
result = (
(*pWsControl)(
IPPROTO_TCP,
WSCNTL_TCPIP_SET_INFO,
InBuf,
InBufLen,
OutBuf,
OutBufLen
) );
if( result ){
return ConvertTdiErrorToDosError(result);
}
return NO_ERROR;
#else
NTSTATUS Status;
IO_STATUS_BLOCK IoStatusBlock;
if(g_hTCPDriverSetHandle is NULL)
{
return ERROR_NETWORK_ACCESS_DENIED;
}
Status = NtDeviceIoControlFile(g_hTCPDriverSetHandle,
NULL,
NULL,
NULL,
&IoStatusBlock,
IOCTL_TCP_SET_INFORMATION_EX,
InBuf,
*InBufLen,
OutBuf,
*OutBufLen );
if ( Status == STATUS_PENDING )
{
Status = NtWaitForSingleObject(g_hTCPDriverSetHandle, FALSE, NULL );
Status = IoStatusBlock.Status;
}
if ( !NT_SUCCESS( Status ) )
{
return ( RtlNtStatusToDosError(Status) );
}
return ( NO_ERROR );
#endif
}
// ========================================================================
// SYNOPSIS: opens handles to tcpip driver.
//
// returns
// 0 == NO_ERROR == STATUS_SUCCESS on success.
// err or 1 on failure.
//
// - MohsinA, 02-Jul-97.
//
DWORD
OpenTCPDriver(
IN DWORD dwFamily
)
{
#ifdef CHICAGO
int err = 0;
if (dwFamily != AF_INET) {
return ERROR_INVALID_PARAMETER;
}
hWsock = LoadLibrary(TEXT("wsock32.dll"));
if(! hWsock ){
err = GetLastError();
DEBUG_PRINT(("RTStartup: can't load wsock32.dll, %d\n", err ));
DEBUG_PRINT(("OpenTcp: !hWsock\n"));
return err? err: 1;
}
pWsControl = (LPWSCONTROL) GetProcAddress(hWsock, "WsControl");
if (! pWsControl ){
err = GetLastError();
DEBUG_PRINT((
"RTStartup: GetProcAddress(wsock32,WsControl) failed %d\n",
GetLastError()));
return err? err: 1;
}
// open the handle to VIP
g_hIPDriverHandle = NULL;
g_hIPGetDriverHandle = NULL;
#ifndef _WIN95_
g_hIPDriverHandle = OsOpenVxdHandle( "VIP", VIP_Device_ID );
if( ! g_hIPDriverHandle ){
err = GetLastError();
DEBUG_PRINT(("no ip handle, err %d\n", err ));
return err? err : 1;
}
g_hIPGetDriverHandle = g_hIPDriverHandle;
#endif
return NO_ERROR;
#else
NTSTATUS status;
UNICODE_STRING nameString;
IO_STATUS_BLOCK ioStatusBlock;
OBJECT_ATTRIBUTES objectAttributes;
PWCHAR pwszDdDeviceName;
HANDLE *pDriverGetHandle, *pDriverSetHandle;
switch (dwFamily) {
case AF_INET:
pwszDdDeviceName = DD_TCP_DEVICE_NAME;
pDriverGetHandle = &g_hTCPDriverGetHandle;
pDriverSetHandle = &g_hTCPDriverSetHandle;
break;
case AF_INET6:
pwszDdDeviceName = DD_TCPV6_DEVICE_NAME;
pDriverGetHandle = &g_hTCP6DriverGetHandle;
pDriverSetHandle = &g_hTCP6DriverSetHandle;
break;
default:
return ERROR_INVALID_PARAMETER;
}
RtlInitUnicodeString(&nameString, pwszDdDeviceName);
InitializeObjectAttributes(&objectAttributes, &nameString,
OBJ_CASE_INSENSITIVE, NULL, NULL);
status = NtCreateFile(pDriverGetHandle,
GENERIC_EXECUTE,
&objectAttributes,
&ioStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_OPEN_IF,
0,
NULL,
0);
if(status isnot STATUS_SUCCESS)
{
return ERROR_OPEN_FAILED;
}
RtlInitUnicodeString(&nameString, pwszDdDeviceName);
InitializeObjectAttributes(&objectAttributes, &nameString,
OBJ_CASE_INSENSITIVE, NULL, NULL);
NtCreateFile(pDriverSetHandle,
GENERIC_WRITE,
&objectAttributes,
&ioStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_OPEN_IF,
0,
NULL,
0);
OpenIPDriver(dwFamily);
return NO_ERROR;
#endif
}
// ========================================================================
DWORD
CloseTCPDriver()
{
#ifdef CHICAGO
if( hWsock )
FreeLibrary( hWsock );
hWsock = NULL;
pWsControl = NULL;
if (g_hIPDriverHandle)
OsCloseVxdHandle( g_hIPDriverHandle );
g_hIPDriverHandle = NULL;
g_hIPGetDriverHandle = NULL;
#else
if(g_hTCPDriverGetHandle isnot NULL)
{
CloseHandle (g_hTCPDriverGetHandle) ;
}
if(g_hTCPDriverSetHandle isnot NULL)
{
CloseHandle (g_hTCPDriverSetHandle) ;
}
CloseIPDriver();
#endif
return NO_ERROR ;
}
DWORD
CloseTCP6Driver()
{
if(g_hTCP6DriverGetHandle isnot NULL)
{
CloseHandle (g_hTCP6DriverGetHandle) ;
}
if(g_hTCP6DriverSetHandle isnot NULL)
{
CloseHandle (g_hTCP6DriverSetHandle) ;
}
CloseIP6Driver();
return NO_ERROR ;
}
#ifndef CHICAGO
DWORD
OpenIPDriver(
IN DWORD dwFamily
)
{
NTSTATUS status;
UNICODE_STRING nameString;
IO_STATUS_BLOCK ioStatusBlock;
OBJECT_ATTRIBUTES objectAttributes;
PWCHAR pwszDdDeviceName;
LPCTSTR ptszWinDeviceName;
HANDLE *pDriverHandle, *pGetDriverHandle, *pChangeHandle;
switch (dwFamily) {
case AF_INET:
pwszDdDeviceName = DD_IP_DEVICE_NAME;
ptszWinDeviceName = TEXT ("\\\\.\\Ip");
pDriverHandle = &g_hIPDriverHandle;
pGetDriverHandle = &g_hIPGetDriverHandle;
pChangeHandle = &ChangeNotificationHandle;
break;
case AF_INET6:
pwszDdDeviceName = DD_IPV6_DEVICE_NAME;
ptszWinDeviceName = TEXT ("\\\\.\\Ip6");;
pDriverHandle = &g_hIP6GetDriverHandle;
pGetDriverHandle = &g_hIP6GetDriverHandle;
pChangeHandle = &Change6NotificationHandle;
break;
default:
return ERROR_INVALID_PARAMETER;
}
RtlInitUnicodeString(&nameString, pwszDdDeviceName);
InitializeObjectAttributes(&objectAttributes, &nameString,
OBJ_CASE_INSENSITIVE, NULL, NULL);
status = NtCreateFile(pGetDriverHandle,
GENERIC_EXECUTE,
&objectAttributes, &ioStatusBlock, NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_OPEN_IF, 0, NULL, 0);
if (status == STATUS_SUCCESS) {
RtlInitUnicodeString(&nameString, pwszDdDeviceName);
InitializeObjectAttributes(&objectAttributes, &nameString,
OBJ_CASE_INSENSITIVE, NULL, NULL);
NtCreateFile(pDriverHandle,
SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
&objectAttributes, &ioStatusBlock, NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_OPEN_IF, 0, NULL, 0);
*pChangeHandle = CreateFile(ptszWinDeviceName,
GENERIC_EXECUTE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
NULL);
}
return (NO_ERROR);
}
DWORD
CloseIPDriver()
{
if(g_hIPDriverHandle isnot NULL)
{
CloseHandle (g_hIPDriverHandle) ;
}
if(g_hIPGetDriverHandle isnot NULL)
{
CloseHandle (g_hIPGetDriverHandle) ;
}
if (ChangeNotificationHandle isnot NULL)
{
CloseHandle (ChangeNotificationHandle);
}
return NO_ERROR ;
}
DWORD
CloseIP6Driver()
{
if(g_hIP6DriverHandle isnot NULL)
{
CloseHandle (g_hIP6DriverHandle) ;
}
if(g_hIP6GetDriverHandle isnot NULL)
{
CloseHandle (g_hIP6GetDriverHandle) ;
}
if (Change6NotificationHandle isnot NULL)
{
CloseHandle (Change6NotificationHandle);
}
return NO_ERROR ;
}
#endif
DWORD
GetBestRouteFromStack(
IN DWORD dwDestAddr,
IN DWORD dwSrcAddr, OPTIONAL
OUT PMIB_IPFORWARDROW pBestRoute
)
{
DWORD dwResult;
DWORD dwInBufLen, dwOutBufLen;
TDIObjectID *ID;
BYTE *Context;
IPRouteEntry Route;
PIPRouteLookupData pLookup;
PTCP_REQUEST_QUERY_INFORMATION_EX ptrqiInBuf;
#define REQ_SIZE sizeof(TCP_REQUEST_QUERY_INFORMATION_EX) + \
sizeof(IPRouteLookupData) - 1
BYTE rgbyBuffer[REQ_SIZE + 4]; // +4 to avoid any alignment problems
ptrqiInBuf = (PTCP_REQUEST_QUERY_INFORMATION_EX)rgbyBuffer;
dwInBufLen = REQ_SIZE;
#undef REQ_SIZE
CheckTcpipState();
if (!g_bIpConfigured)
{
return ERROR_NOT_SUPPORTED;
}
ID = &(ptrqiInBuf->ID);
pLookup = (PIPRouteLookupData)(ptrqiInBuf->Context);
pLookup->Version = 1;
pLookup->DestAdd = dwDestAddr;
pLookup->SrcAdd = dwSrcAddr;
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 = IP_MIB_SINGLE_RT_ENTRY_ID;
dwOutBufLen = sizeof(IPRouteEntry);
dwResult = TCPQueryInformationEx(AF_INET,
ptrqiInBuf,
&dwInBufLen,
&Route,
&dwOutBufLen);
ConvertRouteToForward(&Route, pBestRoute);
return dwResult;
}
TDIEntityID*
GetTdiEntityCount(
PULONG pulNumEntities
)
{
DWORD dwResult;
DWORD dwInBufLen;
DWORD dwOutBufLen;
TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
UCHAR *Context;
TDIObjectID *ID;
TDIEntityID *pEntTable = NULL;
TraceEnter("GetTdiEntityCount");
*pulNumEntities = 0;
dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
dwOutBufLen = sizeof(TDIEntityID) * MAX_TDI_ENTITIES;
pEntTable = (TDIEntityID*)HeapAlloc(g_hPrivateHeap,0,dwOutBufLen);
if (!pEntTable) {
Trace1(ERR,"GetTdiEntityCount: Couldnt allocate memory of size %d",
dwOutBufLen);
return NULL;
}
ID = &(trqiInBuf.ID);
ID->toi_entity.tei_entity = GENERIC_ENTITY;
ID->toi_entity.tei_instance = 0;
ID->toi_class = INFO_CLASS_GENERIC;
ID->toi_type = INFO_TYPE_PROVIDER;
ID->toi_id = ENTITY_LIST_ID;
Context = (BYTE *) &(trqiInBuf.Context[0]);
ZeroMemory(Context, CONTEXT_SIZE);
dwResult = TCPQueryInformationEx(AF_INET,
&trqiInBuf,
&dwInBufLen,
(PVOID)pEntTable,
&dwOutBufLen);
if(dwResult isnot NO_ERROR)
{
Trace1(ERR,"GetTdiEntityCount: Couldnt query information. Error %x",
dwResult);
HeapFree(g_hPrivateHeap,0,pEntTable);
return NULL;
}
//
// Now we have all the TDI entities
//
*pulNumEntities = dwOutBufLen / sizeof(TDIEntityID);
return pEntTable;
}