/*++ Copyright (c) 1995 Microsoft Corporation Module Name: Abstract: Revision History: Amritansh Raghav --*/ #include "inc.h" #pragma hdrstop #include #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; }