/*++ Copyright (c) 1995 Microsoft Corporation Module Name: Abstract: Revision History: Amritansh Raghav --*/ #include "allinc.h" // // Definitions // //***************************************************************************** // // Name: GetIpAddrTableFromStack // // Description: // // Parameters: IPAddrEntry *lpipaeTable, LPDWORD lpdwNumEntries, BOOL bOrder // // Returns: DWORD: NO_ERROR or some error code. // // History: // //***************************************************************************** DWORD GetIpAddrTableFromStack(IPAddrEntry *lpipaeTable, LPDWORD lpdwNumEntries, BOOL bOrder, BOOL bMap) { DWORD dwResult; DWORD dwInBufLen; DWORD dwOutBufLen; DWORD i,j; TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf; TDIObjectID *ID; BYTE *Context; TraceEnter("GetIpAddrTableFromStack"); dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX); dwOutBufLen = (*lpdwNumEntries) * sizeof( IPAddrEntry ); 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 = &(trqiInBuf.Context[0]); ZeroMemory( Context, CONTEXT_SIZE ); dwResult = TCPQueryInformationEx(g_hTcpDevice, &trqiInBuf, &dwInBufLen, (LPVOID)lpipaeTable, &dwOutBufLen ); if (dwResult isnot NO_ERROR) { Trace1(ERR, "GetIpAddrTableFromStack: NtStatus %x querying IpAddrTable from stack", dwResult); TraceLeave("GetIpAddrTableFromStack"); return dwResult; } *lpdwNumEntries =(dwOutBufLen / sizeof(IPAddrEntry)); // // Now sort the address table. Key is IP address. // if(*lpdwNumEntries > 0) { if(bMap) { for (i = 0; i < (*lpdwNumEntries); i++ ) { lpipaeTable[i].iae_index = GetInterfaceFromAdapter(lpipaeTable[i].iae_index); } } if(bOrder) { for (i = 0; i < (*lpdwNumEntries) - 1; i++ ) { IPAddrEntry tempEntry; DWORD min; LONG lCompare; min = i; for (j = i + 1; j < *lpdwNumEntries; j++ ) { if(InetCmp(lpipaeTable[min].iae_addr,lpipaeTable[j].iae_addr,lCompare) > 0) { min = j; } } if(min isnot i) { tempEntry = lpipaeTable[min]; lpipaeTable[min] = lpipaeTable[i]; lpipaeTable[i] = tempEntry; } } } } TraceLeave("GetIpAddrTableFromStack"); return NO_ERROR; } //***************************************************************************** // // Name: GetTcpConnTableFromStack // // Description: Reads and sorts the route table from the stack. // // Parameters: TCPConnTableEntry *lptcteTable, LPDWORD lpdwNumEntries, BOOL bOrder // // Returns: DWORD: NO_ERROR or some error code. // // History: // //***************************************************************************** DWORD GetTcpTableFromStack(TCPConnTableEntry *lptcteTable, LPDWORD lpdwNumEntries, BOOL bOrder) { DWORD dwResult; DWORD dwInBufLen; DWORD dwOutBufLen; DWORD i,j; TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf; TDIObjectID *ID; BYTE *Context; TCPStats TcpInfo; DWORD NumConn; DWORD *IndTab; LONG CmpResult; TraceEnter("GetTcpTableFromStack"); dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX); dwOutBufLen = (*lpdwNumEntries) * sizeof(TCPConnTableEntry); 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 = &(trqiInBuf.Context[0]); ZeroMemory( Context, CONTEXT_SIZE ); dwResult = TCPQueryInformationEx(g_hTcpDevice, &trqiInBuf, &dwInBufLen, (LPVOID)lptcteTable, &dwOutBufLen); if (dwResult isnot NO_ERROR ) { Trace1(ERR, "GetTcpTableFromStack: NtStatus %x querying TcpConnTable from stack", dwResult); TraceLeave("GetTcpTableFromStack"); return dwResult; } *lpdwNumEntries = (dwOutBufLen/sizeof(TCPConnTableEntry)); // // Now sort the TCP connection table. Keys are: local address, local // port, remote address, and remote port. // if((*lpdwNumEntries > 0) and bOrder) { for ( i = 0; i < (*lpdwNumEntries) - 1 ; i++ ) { TCPConnTableEntry tempEntry; DWORD min; min = i; for ( j = i+1; j < *lpdwNumEntries ; j++ ) { if(TcpCmp(lptcteTable[min].tct_localaddr,lptcteTable[min].tct_localport, lptcteTable[min].tct_remoteaddr,lptcteTable[min].tct_remoteport, lptcteTable[j].tct_localaddr,lptcteTable[j].tct_localport, lptcteTable[j].tct_remoteaddr,lptcteTable[j].tct_remoteport) > 0) { min = j; } } if(min isnot i) { tempEntry = lptcteTable[min]; lptcteTable[min] = lptcteTable[i]; lptcteTable[i] = tempEntry; } } } TraceLeave("GetTcpTableFromStack"); return NO_ERROR; } DWORD SetTcpRowToStack(TCPConnTableEntry *tcpRow) { TCP_REQUEST_SET_INFORMATION_EX *lptrsiInBuf; TDIObjectID *ID; UCHAR *Context; TCPConnTableEntry *copyInfo; DWORD dwInBufLen,dwOutBufLen,dwResult; TraceEnter("SetTcpRowToStack"); dwInBufLen = sizeof(TCP_REQUEST_SET_INFORMATION_EX) + sizeof(TCPConnTableEntry) - 1; lptrsiInBuf = HeapAlloc(GetProcessHeap(),0,dwInBufLen); if(lptrsiInBuf is NULL) { dwResult = GetLastError(); Trace1(ERR, "SetTcpRowToStack: Error %d allocating memory", dwResult); TraceLeave("SetTcpRowToStack"); return dwResult; } ID = &lptrsiInBuf->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; lptrsiInBuf->BufferSize = sizeof(TCPConnTableEntry); copyInfo = (TCPConnTableEntry*)lptrsiInBuf->Buffer; *copyInfo = *tcpRow; dwResult = TCPSetInformationEx(g_hTcpDevice, (LPVOID)lptrsiInBuf, &dwInBufLen, NULL, &dwOutBufLen); HeapFree(GetProcessHeap(),0,lptrsiInBuf); TraceLeave("SetTcpRowToStack"); return dwResult; } //***************************************************************************** // // Name: GetUdpConnTableFromStack // // Description: Reads and sorts the route table from the stack. // // Parameters: UDPEntry *lpueTable, LPDWORD lpdwNumEntries, BOOL bOrder // // Returns: DWORD: NO_ERROR or some error code. // // History: // //***************************************************************************** DWORD GetUdpTableFromStack(UDPEntry *lpueTable, LPDWORD lpdwNumEntries, BOOL bOrder) { DWORD dwResult; DWORD dwInBufLen; DWORD dwOutBufLen; DWORD i,j; TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf; TDIObjectID *ID; BYTE *Context; TraceEnter("GetUdpTableFromStack"); // // Determine number of connections via the UDPStats structure // dwInBufLen = sizeof( TCP_REQUEST_QUERY_INFORMATION_EX ); dwOutBufLen = (*lpdwNumEntries) * sizeof(UDPEntry); 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 = &(trqiInBuf.Context[0]); ZeroMemory( Context, CONTEXT_SIZE ); dwResult = TCPQueryInformationEx(g_hTcpDevice, &trqiInBuf, &dwInBufLen, (LPVOID)lpueTable, &dwOutBufLen ); if(dwResult isnot NO_ERROR) { Trace1(ERR, "GetUdpTableFromStack: NtStatus %x querying UdpTable from stack", dwResult); TraceLeave("GetUdpTableFromStack"); return dwResult; } *lpdwNumEntries =(dwOutBufLen / sizeof(UDPEntry)); // // Now sort the UDP connection table. Keys are: local address, and local // port. // if((*lpdwNumEntries > 0) and bOrder) { for ( i = 0; i < (*lpdwNumEntries) - 1; i++ ) { UDPEntry tempEntry; DWORD min; min = i; for ( j = i + 1; j < (*lpdwNumEntries) ; j++ ) { if(UdpCmp(lpueTable[min].ue_localaddr, lpueTable[min].ue_localport, lpueTable[j].ue_localaddr, lpueTable[j].ue_localport) > 0) { min = j; } } if(min isnot i) { tempEntry = lpueTable[min]; lpueTable[min] = lpueTable[i]; lpueTable[i] = tempEntry; } } } TraceLeave("GetUdpTableFromStack"); return NO_ERROR; } //***************************************************************************** // // Name: GetIpStatsFromStack // // Description: Read the IPSNMPInfo structure from the stack. // // Parameters: IPSNMPInfo *IPSnmpInfo // // Returns: DWORD: NO_ERROR or some error code. // // History: // //***************************************************************************** DWORD GetIpStatsFromStack(IPSNMPInfo *IPSnmpInfo) { DWORD dwResult; DWORD dwInBufLen; DWORD dwOutBufLen; TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf; TDIObjectID *ID; BYTE *Context; TraceEnter("GetIpStatsFromStack"); dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX); dwOutBufLen = sizeof(IPSNMPInfo); 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 = &(trqiInBuf.Context[0]); ZeroMemory(Context, CONTEXT_SIZE); dwResult = TCPQueryInformationEx(g_hTcpDevice, &trqiInBuf, &dwInBufLen, IPSnmpInfo, &dwOutBufLen); if (dwResult isnot NO_ERROR) { Trace1(ERR, "GetIpStatsFromStack: NtStatus %x querying IpStats from stack", dwResult); TraceLeave("GetIpStatsFromStack"); return dwResult; } TraceLeave("GetIpStatsFromStack"); return NO_ERROR; } DWORD SetIpInfoToStack(IPSNMPInfo *ipsiInfo) { TCP_REQUEST_SET_INFORMATION_EX *lptrsiInBuf; TDIObjectID *ID; UCHAR *Context; IPSNMPInfo *copyInfo; DWORD dwInBufLen,dwOutBufLen,dwResult; TraceEnter("SetIpInfoToStack"); dwInBufLen = sizeof(TCP_REQUEST_SET_INFORMATION_EX) + sizeof(IPSNMPInfo) - 1; lptrsiInBuf = HeapAlloc(GetProcessHeap(),0,dwInBufLen); if(lptrsiInBuf is NULL) { dwResult = GetLastError(); Trace1(ERR, "SetIpInfoToStack: Error %d allocating memory", dwResult); TraceLeave("SetIpInfoToStack"); return dwResult; } ID = &lptrsiInBuf->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 = (IPSNMPInfo*)lptrsiInBuf->Buffer; *copyInfo = *ipsiInfo; dwResult = TCPSetInformationEx(g_hTcpDevice, (LPVOID)lptrsiInBuf, &dwInBufLen, NULL, &dwOutBufLen); TraceLeave("SetIpInfoToStack"); return dwResult; } //***************************************************************************** // // Name: GetIcmpStatsFromStack // // Description: Read the ICMPSNMPInfo structure from the stack. // // Parameters: ICMPSNMPInfo *ICMPSnmpInfo // // Returns: DWORD: NO_ERROR or some error code. // // History: // //***************************************************************************** DWORD GetIcmpStatsFromStack( ICMPSNMPInfo *ICMPSnmpInfo ) { DWORD dwResult; DWORD dwInBufLen; DWORD dwOutBufLen; TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf; TDIObjectID *ID; BYTE *Context; TraceEnter("GetIcmpStatsFromStack"); dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX); dwOutBufLen = sizeof(ICMPSNMPInfo); ID = &(trqiInBuf.ID); ID->toi_entity.tei_entity = ER_ENTITY; ID->toi_entity.tei_instance = 0; ID->toi_class = INFO_CLASS_PROTOCOL; ID->toi_type = INFO_TYPE_PROVIDER; ID->toi_id = ICMP_MIB_STATS_ID; Context = &(trqiInBuf.Context[0]); ZeroMemory(Context,CONTEXT_SIZE); dwResult = TCPQueryInformationEx(g_hTcpDevice, &trqiInBuf, &dwInBufLen, ICMPSnmpInfo, &dwOutBufLen ); if (dwResult isnot NO_ERROR) { Trace1(ERR, "GetIcmpStatsFromStack: NtStatus %x querying IcmpStats from stack", dwResult); TraceLeave("GetIcmpStatsFromStack"); return dwResult; } TraceLeave("GetIcmpStatsFromStack"); return NO_ERROR; } //***************************************************************************** // // Name: GetUdpStatsFromStack // // Description: Read the UDPStats structure from the stack. // // Parameters: UDPStats *UdpInfo // // Returns: DWORD: NO_ERROR or some error code. // // History: // //***************************************************************************** DWORD GetUdpStatsFromStack(UDPStats *UdpInfo) { DWORD dwResult; DWORD dwInBufLen; DWORD dwOutBufLen; TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf; TDIObjectID *ID; BYTE *Context; TraceEnter("GetUdpStatsFromStack"); dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX); dwOutBufLen = sizeof(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 = &(trqiInBuf.Context[0]); ZeroMemory( Context, CONTEXT_SIZE ); dwResult = TCPQueryInformationEx(g_hTcpDevice, &trqiInBuf, &dwInBufLen, UdpInfo, &dwOutBufLen ); if(dwResult isnot NO_ERROR) { Trace1(ERR, "GetUdpStatsFromStack: NtStatus %x querying UdpStats from stack", dwResult); TraceLeave("GetUdpStatsFromStack"); return dwResult; } TraceLeave("GetUdpStatsFromStack"); return NO_ERROR; } //***************************************************************************** // // Name: GetTCPStats // // Description: Read the TCPStats structure from the stack. // // Parameters: // // Returns: DWORD: NO_ERROR or some error code. // // History: // //***************************************************************************** DWORD GetTcpStatsFromStack(TCPStats *TcpInfo) { DWORD dwResult; DWORD dwInBufLen; DWORD dwOutBufLen; TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf; TDIObjectID *ID; BYTE *Context; TraceEnter("GetTcpStatsFromStack"); dwInBufLen = sizeof( TCP_REQUEST_QUERY_INFORMATION_EX ); dwOutBufLen = sizeof( 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 = &(trqiInBuf.Context[0]); ZeroMemory(Context,CONTEXT_SIZE); dwResult = TCPQueryInformationEx(g_hTcpDevice, &trqiInBuf, &dwInBufLen, TcpInfo, &dwOutBufLen ); if(dwResult isnot NO_ERROR) { Trace1(ERR, "GetTcpStatsFromStack: NtStatus %x querying TcpStats from stack", dwResult); TraceLeave("GetTcpStatsFromStack"); return dwResult; } TraceLeave("GetTcpStatsFromStack"); return NO_ERROR; } //***************************************************************************** // // Name: GetRouteTableFromStack // // Description: Reads all the routes from the stack. This is needed because the ICMP redirect // routes are only kept in the stack and cant be queried from RTM // // Parameters: // // Returns: DWORD: NO_ERROR or some error code. // // History: // //***************************************************************************** DWORD GetIpRouteTableFromStack(IPRouteEntry *lpireTable,LPDWORD lpdwNumEntries, BOOL bOrder) { DWORD dwResult; DWORD dwInBufLen; DWORD dwOutBufLen; UCHAR *Context; TDIObjectID *ID; TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf; IPSNMPInfo ipsiInfo; TraceEnter("GetIpRouteTableFromStack"); dwInBufLen = sizeof( TCP_REQUEST_QUERY_INFORMATION_EX ); dwOutBufLen = *lpdwNumEntries * sizeof(IPRouteEntry); 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 = &(trqiInBuf.Context[0]); ZeroMemory( Context, CONTEXT_SIZE ); dwResult = TCPQueryInformationEx(g_hTcpDevice, &trqiInBuf, &dwInBufLen, (LPVOID)lpireTable, &dwOutBufLen ); if(dwResult isnot NO_ERROR) { Trace1(ERR, "GetIpRouteTableFromStack: NtStatus %x querying IpRouteTable from stack", dwResult); TraceLeave("GetIpRouteTableFromStack"); return dwResult; } *lpdwNumEntries = (dwOutBufLen / sizeof( IPRouteEntry )); if((*lpdwNumEntries > 0) and bOrder) { DWORD i,j; for (i = 0; i < (*lpdwNumEntries) - 1; i++ ) { IPRouteEntry tempEntry; DWORD min; LONG lCompare; min = i; for (j = i + 1; j < *lpdwNumEntries; j++ ) { if(InetCmp(lpireTable[min].ire_dest,lpireTable[j].ire_dest,lCompare) > 0) { min = j; } } if(min isnot i) { tempEntry = lpireTable[min]; lpireTable[min] = lpireTable[i]; lpireTable[i] = tempEntry; } } } TraceLeave("GetIpRouteTableFromStack"); return NO_ERROR; } //***************************************************************************** // // Name: GetARPEntityTable // // Description: Builds a list of AT entities. that support ARP. Keeps it in the global // entity table // // Parameters: // // Returns: DWORD: NO_ERROR or some error code. // // History: // //***************************************************************************** DWORD GetArpEntTableFromStack(DWORD **lpArpEntTable, LPDWORD lpdwSize, LPDWORD lpdwValid, HANDLE hHeap) { DWORD dwResult; DWORD dwInBufLen; DWORD dwOutBufLen; TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf; DWORD dwATType; UCHAR *Context; TDIObjectID *ID; LPVOID lpOutBuf; TDIEntityID *lpEntTable; DWORD dwNumEntities; DWORD i,dwCount ; TraceEnter("GetArpEntTableFromStack"); dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX); dwOutBufLen = MAX_TDI_ENTITIES * sizeof(TDIEntityID); lpOutBuf = HeapAlloc(GetProcessHeap(),0,dwOutBufLen); 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 = &(trqiInBuf.Context[0]); ZeroMemory(Context, CONTEXT_SIZE); if(lpOutBuf is NULL) { dwResult = GetLastError(); Trace1(ERR,"GetArpEntTableFromStack: Error %d allocating memory", dwResult); TraceLeave("GetArpEntTableFromStack"); return dwResult; } dwResult = TCPQueryInformationEx(g_hTcpDevice, &trqiInBuf, &dwInBufLen, lpOutBuf, &dwOutBufLen); if ( dwResult != NO_ERROR ) { Trace1(ERR, "GetArpEntTableFromStack: NtStatus %x querying TDI Entities from stack", dwResult); HeapFree(GetProcessHeap(),0,lpOutBuf); TraceLeave("GetArpEntTableFromStack"); return dwResult; } // // Now we have all the entities // dwNumEntities = dwOutBufLen / sizeof( TDIEntityID ); dwCount = 0; lpEntTable = (TDIEntityID*)lpOutBuf; for(i = 0; i < dwNumEntities; i++) { // // See which ones are AT // if(lpEntTable[i].tei_entity is AT_ENTITY) { // // Query the entity to see if it supports ARP // 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 = lpEntTable[i].tei_instance; dwOutBufLen = sizeof(dwATType); ZeroMemory(Context,CONTEXT_SIZE); dwResult = TCPQueryInformationEx(g_hTcpDevice, &trqiInBuf, &dwInBufLen, (LPVOID)&dwATType, &dwOutBufLen ); if(dwResult is STATUS_INVALID_DEVICE_REQUEST) { continue; } if(dwResult isnot NO_ERROR) { HeapFree(GetProcessHeap(),0,lpOutBuf); return dwResult; } if(dwATType is AT_ARP) { if(dwCount is *lpdwSize) { // // Realloc more memory // *lpArpEntTable = (LPDWORD)HeapReAlloc(hHeap, 0, (LPVOID)*lpArpEntTable, ((*lpdwSize)<<1)*sizeof(DWORD)); if(*lpArpEntTable is NULL) { dwResult = GetLastError(); Trace1(ERR, "GetArpEntTableFromStack: Error %d reallocating memory", dwResult); TraceLeave("GetArpEntTableFromStack"); return dwResult; } *lpdwSize = (*lpdwSize)<<1; } (*lpArpEntTable)[dwCount++] = lpEntTable[i].tei_instance; } } } *lpdwValid = dwCount; HeapFree(GetProcessHeap(),0,lpOutBuf); TraceLeave("GetArpEntTableFromStack"); return NO_ERROR; } // Called only if you are a IPNET reader DWORD UpdateAdapterToATInstanceMap() { DWORD dwResult; DWORD dwInBufLen; DWORD i; TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf; TDIObjectID *ID; UCHAR *Context; DWORD dwSize; AddrXlatInfo AXI; TraceEnter("UpdateAdapterToATInstanceMap"); dwInBufLen = sizeof( TCP_REQUEST_QUERY_INFORMATION_EX ); Context = &(trqiInBuf.Context[0]); ID = &(trqiInBuf.ID); // // Maybe we should first clear out all the mappings // for (i = 0; i < g_IpInfo.dwValidArpEntEntries; i++ ) { 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_INFO_ID; ID->toi_entity.tei_instance = g_IpInfo.arpEntTable[i]; dwSize = sizeof(AXI); ZeroMemory(Context, CONTEXT_SIZE); dwResult = TCPQueryInformationEx(g_hTcpDevice, &trqiInBuf, &dwInBufLen, &AXI, &dwSize ); if(dwResult isnot NO_ERROR) { Trace1(ERR, "UpdateAdapterToATInstanceMap: NtStatus %x querying ArpInfo from stack", dwResult); TraceLeave("UpdateAdapterToATInstanceMap"); return dwResult; } StoreAdapterToATInstanceMap(AXI.axi_index,g_IpInfo.arpEntTable[i]); } TraceLeave("UpdateAdapterToATInstanceMap"); return NO_ERROR; } DWORD GetIpNetTableFromStackEx(LPDWORD arpEntTable, DWORD dwValidArpEntEntries, IPNetToMediaEntry **lpNetTable, LPDWORD lpdwTotalEntries, LPDWORD lpdwValidEntries, BOOL bOrder, HANDLE hHeap) { DWORD dwResult; DWORD dwInBufLen; DWORD dwOutBufLen; DWORD i,j; TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf; TDIObjectID *ID; UCHAR *Context; DWORD dwNetEntryCount,dwNumAdded,dwValidNetEntries; DWORD dwSize,dwNeed; AddrXlatInfo AXI; IPNetToMediaEntry *lpOutBuf,tempEntry; dwInBufLen = sizeof( TCP_REQUEST_QUERY_INFORMATION_EX ); Context = &(trqiInBuf.Context[0]); ZeroMemory( Context, CONTEXT_SIZE ); ID = &(trqiInBuf.ID); ID->toi_entity.tei_entity = AT_ENTITY; ID->toi_type = INFO_TYPE_PROVIDER; dwNetEntryCount = 0; for (i = 0; i < dwValidArpEntEntries; 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 = arpEntTable[i]; dwSize = sizeof(AXI); ZeroMemory(Context, CONTEXT_SIZE); dwResult = TCPQueryInformationEx(g_hTcpDevice, &trqiInBuf, &dwInBufLen, &AXI, &dwSize ); if(dwResult isnot NO_ERROR) { Trace1(ERR, "GetIpNetTableFromStackEx: NtStatus %x querying information from stack", dwResult); TraceLeave("GetIpNetTableFromStackEx"); return dwResult; } // // At this point map the index to the instance - the index is the adapter // index though the instance is not the same as IFInstance // StoreAdapterToATInstanceMap(AXI.axi_index,arpEntTable[i]); dwNetEntryCount += AXI.axi_count; } // // This is generally a memory hog // dwNeed = dwNetEntryCount + (dwValidArpEntEntries) * SPILLOVER; if(dwNeed > *lpdwTotalEntries) { if(*lpdwTotalEntries) { HeapFree(hHeap,0,*lpNetTable); } dwNeed += MAX_DIFF; // // Serialize the heap ??? // *lpNetTable = (IPNetToMediaEntry*)HeapAlloc(hHeap,0, dwNeed*sizeof(IPNetToMediaEntry)); if(*lpNetTable is NULL) { dwResult = GetLastError(); Trace1(ERR, "GetIpNetTableFromStackEx: Error %d allocating memory for IpNetTable", dwResult); return ERROR_NOT_ENOUGH_MEMORY; } *lpdwTotalEntries = dwNeed; } else { dwNeed = *lpdwTotalEntries; } lpOutBuf = *lpNetTable; dwOutBufLen = dwNeed * sizeof(IPNetToMediaEntry); dwValidNetEntries = 0; for(i = 0; i < dwValidArpEntEntries; i++ ) { ID->toi_class = INFO_CLASS_PROTOCOL; ID->toi_id = AT_MIB_ADDRXLAT_ENTRY_ID; ID->toi_entity.tei_instance = arpEntTable[i]; ZeroMemory( Context, CONTEXT_SIZE ); dwResult = TCPQueryInformationEx(g_hTcpDevice, &trqiInBuf, &dwInBufLen, (LPVOID)lpOutBuf, &dwOutBufLen); if ( dwResult isnot NO_ERROR ) { Trace1(ERR, "GetIpNetTableFromStackEx: Error %x getting AT Entry", dwResult); continue; } dwNumAdded = dwOutBufLen/(sizeof(IPNetToMediaEntry)); lpOutBuf += dwNumAdded; dwValidNetEntries += dwNumAdded; dwOutBufLen = (dwNeed - dwValidNetEntries) * sizeof(IPNetToMediaEntry); } dwResult = NO_ERROR; *lpdwValidEntries = dwValidNetEntries; // // Now sort the net table // if(dwValidNetEntries > 0) { for(i = 0; i < dwValidNetEntries; i++) { (*lpNetTable)[i].inme_index = GetInterfaceFromAdapter((*lpNetTable)[i].inme_index); } if(bOrder) { for(i = 0; i < dwValidNetEntries - 1; i++) { DWORD min = i; for(j = i + 1; j < dwValidNetEntries; j++) { if(IpNetCmp((*lpNetTable)[min].inme_index,(*lpNetTable)[min].inme_addr, (*lpNetTable)[j].inme_index,(*lpNetTable)[j].inme_addr) > 0) { min = j; } } if(min isnot i) { tempEntry = (*lpNetTable)[min]; (*lpNetTable)[min] = (*lpNetTable)[i]; (*lpNetTable)[i] = tempEntry; } } } } TraceLeave("GetIpNetTableFromStackEx"); return dwResult; } DWORD SetIpNetEntryToStack(IPNetToMediaEntry *inmeEntry, DWORD dwInstance) { TCP_REQUEST_SET_INFORMATION_EX *lptrsiInBuf; TDIObjectID *ID; UCHAR *Context; IPNetToMediaEntry *copyInfo; DWORD dwInBufLen,dwOutBufLen,dwResult; TraceEnter("SetIpNetEntryToStack"); dwInBufLen = sizeof(TCP_REQUEST_SET_INFORMATION_EX) + sizeof(IPNetToMediaEntry) - 1; lptrsiInBuf = HeapAlloc(GetProcessHeap(),0,dwInBufLen); if(lptrsiInBuf is NULL) { dwResult = GetLastError(); Trace1(ERR, "SetIpNetEntryToStack: Error %d allocating memory", dwResult); return dwResult; } ID = &lptrsiInBuf->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 IPNetToMediaEntry is a fixed size structure // copyInfo = (IPNetToMediaEntry*)lptrsiInBuf->Buffer; *copyInfo = *inmeEntry; dwResult = TCPSetInformationEx(g_hTcpDevice, (LPVOID)lptrsiInBuf, &dwInBufLen, NULL, &dwOutBufLen); TraceLeave("SetIpNetEntryToStack"); return dwResult; } DWORD UpdateAdapterToIFInstanceMap() { IPSNMPInfo ipsiInfo; DWORD dwResult; DWORD dwOutBufLen; DWORD dwInBufLen; TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf; TDIObjectID *ID; IFEntry *maxIfEntry; BYTE *Context; DWORD dwCount,i; TraceEnter("UpdateAdapterToIFInstanceMap"); dwResult = GetIpStatsFromStack(&ipsiInfo); if(dwResult isnot NO_ERROR) { Trace1(ERR, "UpdateAdapterToIFInstanceMap: NtStatus %x querying IpSnmpInfo from stack to determine number if interface", dwResult); TraceLeave("UpdateAdapterToIFInstanceMap"); return dwResult; } dwOutBufLen = sizeof(MIB_IFROW) - FIELD_OFFSET(MIB_IFROW, dwIndex); if((maxIfEntry = (IFEntry*)HeapAlloc(GetProcessHeap(), 0, dwOutBufLen)) is NULL) { dwResult = GetLastError(); Trace1(ERR, "UpdateAdapterToIFInstanceMap: Error %d allocating memory", dwResult); TraceLeave("UpdateAdapterToIFInstanceMap"); return ERROR_NOT_ENOUGH_MEMORY; } dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX); ID = &(trqiInBuf.ID); Context = &(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; // // Read the interface entry items // for ( i = 0; i < ipsiInfo.ipsi_numif ; i++ ) { dwOutBufLen = sizeof(MIB_IFROW) - FIELD_OFFSET(MIB_IFROW, dwIndex); ID->toi_entity.tei_instance = i; ZeroMemory(Context,CONTEXT_SIZE); dwResult = TCPQueryInformationEx(g_hTcpDevice, &trqiInBuf, &dwInBufLen, (LPVOID)maxIfEntry, &dwOutBufLen); if (dwResult isnot NO_ERROR) { Trace1(ERR, "UpdateAdapterToIFInstanceMap: NtStatus %x getting IFRow from stack", dwResult); continue; } StoreAdapterToIFInstanceMap(maxIfEntry->if_index,i); } HeapFree(GetProcessHeap(),0,maxIfEntry); TraceLeave("UpdateAdapterToIFInstanceMap"); return NO_ERROR; } //* 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( HANDLE hHandle, void *InBuf, ulong *InBufLen, void *OutBuf, ulong *OutBufLen ) { NTSTATUS Status; IO_STATUS_BLOCK IoStatusBlock; TraceEnter("TCPQueryInformationEx"); Status = NtDeviceIoControlFile( hHandle, NULL, NULL, NULL, &IoStatusBlock, IOCTL_TCP_QUERY_INFORMATION_EX, InBuf, *InBufLen, OutBuf, *OutBufLen ); if ( Status == STATUS_PENDING ) { Status = NtWaitForSingleObject( hHandle, FALSE, NULL ); Status = IoStatusBlock.Status; } if ( !NT_SUCCESS( Status ) ) { Trace1(ERR, "TCPQueryInformationEx: NtStatus %x from NtDeviceIoControlFile", Status); *OutBufLen = 0; TraceLeave("TCPQueryInformationEx"); return Status; } // // Tell caller how much was written // *OutBufLen = IoStatusBlock.Information; TraceLeave("TCPQueryInformationEx"); return NO_ERROR; } //* 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(HANDLE hHandle, void *InBuf, ULONG *InBufLen, void *OutBuf, ULONG *OutBufLen ) { NTSTATUS Status; IO_STATUS_BLOCK IoStatusBlock; TraceEnter("TCPSetInformationEx"); Status = NtDeviceIoControlFile(hHandle, NULL, NULL, NULL, &IoStatusBlock, IOCTL_TCP_SET_INFORMATION_EX, InBuf, *InBufLen, OutBuf, *OutBufLen ); if ( Status == STATUS_PENDING ) { Status = NtWaitForSingleObject(hHandle, FALSE, NULL ); Status = IoStatusBlock.Status; } if ( !NT_SUCCESS( Status ) ) { Trace1(ERR, "TCPSetInformationEx: NtStatus %x from NtDeviceIoControlFile", Status); TraceLeave("TCPSetInformationEx"); return Status; } TraceLeave("TCPSetInformationEx"); return NO_ERROR; }