1012 lines
31 KiB
C
1012 lines
31 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1994-1997 Microsoft Corporation
|
|||
|
|
|||
|
Module Name: //KERNEL/RAZZLE3/src/sockets/tcpcmd/ipconfig/adaptlst.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module contains functions for retrieving adapter information from
|
|||
|
TCP/IP device driver
|
|||
|
|
|||
|
Contents:
|
|||
|
GetAdapterList
|
|||
|
GetAdapterList2
|
|||
|
AddIpAddress
|
|||
|
AddIpAddressString
|
|||
|
ConvertIpAddressToString
|
|||
|
CopyString
|
|||
|
(CleanDescription)
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Richard L Firth (rfirth) 20-May-1994
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
20-May-1994 rfirth Created
|
|||
|
30-Apr-97 MohsinA Cleaned Up.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "precomp.h"
|
|||
|
#pragma hdrstop
|
|||
|
|
|||
|
#define OVERFLOW_COUNT 10
|
|||
|
|
|||
|
//
|
|||
|
// prototypes
|
|||
|
//
|
|||
|
|
|||
|
void CleanDescription(LPSTR);
|
|||
|
extern PIP_ADAPTER_ORDER_MAP APIENTRY GetAdapterOrderMap();
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// functions
|
|||
|
//
|
|||
|
|
|||
|
/*******************************************************************************
|
|||
|
*
|
|||
|
* GetAdapterList
|
|||
|
*
|
|||
|
* Returns a linked list of IP_ADAPTER_INFO structures. The adapter info is
|
|||
|
* queried from the TCP/IP stack. Only those instances corresponding to
|
|||
|
* physical adapters are returned
|
|||
|
*
|
|||
|
* This function only fills in the information in the IP_ADAPTER_INFO
|
|||
|
* structure pertaining to the physical adapter (like MAC address, adapter
|
|||
|
* type, etc.) and IP address info
|
|||
|
*
|
|||
|
* ENTRY nothing
|
|||
|
*
|
|||
|
* EXIT nothing
|
|||
|
*
|
|||
|
* RETURNS Success - pointer to linked list of IP_ADAPTER_INFO structures,
|
|||
|
* 0 terminated
|
|||
|
* Failure - NULL
|
|||
|
*
|
|||
|
* ASSUMES
|
|||
|
*
|
|||
|
******************************************************************************/
|
|||
|
|
|||
|
PIP_ADAPTER_INFO GetAdapterList()
|
|||
|
{
|
|||
|
|
|||
|
TCP_REQUEST_QUERY_INFORMATION_EX req;
|
|||
|
TDIObjectID id;
|
|||
|
PIP_ADAPTER_INFO list = NULL, prev = NULL;
|
|||
|
PIP_ADAPTER_INFO this, UniList = NULL, tmp;
|
|||
|
UINT numberOfEntities;
|
|||
|
TDIEntityID* pEntity = NULL;
|
|||
|
TDIEntityID* entityList;
|
|||
|
UINT i;
|
|||
|
UINT j;
|
|||
|
DWORD status;
|
|||
|
DWORD inputLen;
|
|||
|
DWORD outputLen;
|
|||
|
PIP_ADAPTER_ORDER_MAP adapterOrderMap;
|
|||
|
PIP_UNIDIRECTIONAL_ADAPTER_ADDRESS pUniInfo=NULL;
|
|||
|
ULONG OutBufLen;
|
|||
|
|
|||
|
//
|
|||
|
// get the list of entities supported by TCP/IP then make 2 passes on the
|
|||
|
// list. Pass 1 scans for IF_ENTITY's (interface entities perhaps?) which
|
|||
|
// describe adapter instances (physical and virtual). Once we have our list
|
|||
|
// of adapters, on pass 2 we look for CL_NL_ENTITY's (connection-less
|
|||
|
// network layer entities peut-etre?) which will give us the list of IP
|
|||
|
// addresses for the adapters we found in pass 1
|
|||
|
//
|
|||
|
|
|||
|
entityList = GetEntityList(&numberOfEntities);
|
|||
|
if (!entityList) {
|
|||
|
|
|||
|
DEBUG_PRINT(("GetAdapterList: failed to get entity list\n"));
|
|||
|
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
adapterOrderMap = GetAdapterOrderMap();
|
|||
|
if (!adapterOrderMap) {
|
|||
|
DEBUG_PRINT(("GetAdapterList: failed to get adapter order map\n"));
|
|||
|
ReleaseMemory(entityList);
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
// ====================================================================
|
|||
|
// pass 1
|
|||
|
// ====================================================================
|
|||
|
|
|||
|
for (i = 0, pEntity = entityList; i < numberOfEntities; ++i, ++pEntity) {
|
|||
|
|
|||
|
DEBUG_PRINT(("Pass 1: Entity %lx [%s] Instance %ld\n",
|
|||
|
pEntity->tei_entity,
|
|||
|
entity$(pEntity->tei_entity),
|
|||
|
pEntity->tei_instance
|
|||
|
));
|
|||
|
|
|||
|
if (pEntity->tei_entity == IF_ENTITY) {
|
|||
|
|
|||
|
//
|
|||
|
// IF_ENTITY: this entity/instance describes an adapter
|
|||
|
//
|
|||
|
|
|||
|
DWORD isMib;
|
|||
|
BYTE info[sizeof(IFEntry) + MAX_ADAPTER_DESCRIPTION_LENGTH + 1];
|
|||
|
IFEntry* pIfEntry = (IFEntry*)info;
|
|||
|
int len;
|
|||
|
|
|||
|
//
|
|||
|
// find out if this entity supports MIB requests
|
|||
|
//
|
|||
|
|
|||
|
memset(&req, 0, sizeof(req));
|
|||
|
|
|||
|
id.toi_entity = *pEntity;
|
|||
|
id.toi_class = INFO_CLASS_GENERIC;
|
|||
|
id.toi_type = INFO_TYPE_PROVIDER;
|
|||
|
id.toi_id = ENTITY_TYPE_ID;
|
|||
|
|
|||
|
req.ID = id;
|
|||
|
|
|||
|
inputLen = sizeof(req);
|
|||
|
outputLen = sizeof(isMib);
|
|||
|
|
|||
|
status = WsControl(IPPROTO_TCP,
|
|||
|
WSCNTL_TCPIP_QUERY_INFO,
|
|||
|
(LPVOID)&req,
|
|||
|
&inputLen,
|
|||
|
(LPVOID)&isMib,
|
|||
|
&outputLen
|
|||
|
);
|
|||
|
|
|||
|
if (status != TDI_SUCCESS) {
|
|||
|
|
|||
|
//
|
|||
|
// unexpected results - bail out
|
|||
|
//
|
|||
|
|
|||
|
DEBUG_PRINT(("GetAdapterList: WsControl(ENTITY_TYPE_ID): status = %ld, outputLen = %ld\n",
|
|||
|
status,
|
|||
|
outputLen
|
|||
|
));
|
|||
|
|
|||
|
// goto error_exit;
|
|||
|
continue;
|
|||
|
}
|
|||
|
if (isMib != IF_MIB) {
|
|||
|
|
|||
|
//
|
|||
|
// entity doesn't support MIB requests - try another
|
|||
|
//
|
|||
|
|
|||
|
DEBUG_PRINT(("GetAdapterList: Entity %lx, Instance %ld doesn't support MIB (%lx)\n",
|
|||
|
id.toi_entity.tei_entity,
|
|||
|
id.toi_entity.tei_instance,
|
|||
|
isMib
|
|||
|
));
|
|||
|
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// MIB requests supported - query the adapter info
|
|||
|
//
|
|||
|
|
|||
|
id.toi_class = INFO_CLASS_PROTOCOL;
|
|||
|
id.toi_id = IF_MIB_STATS_ID;
|
|||
|
|
|||
|
memset(&req, 0, sizeof(req));
|
|||
|
req.ID = id;
|
|||
|
|
|||
|
inputLen = sizeof(req);
|
|||
|
outputLen = sizeof(info);
|
|||
|
|
|||
|
status = WsControl(IPPROTO_TCP,
|
|||
|
WSCNTL_TCPIP_QUERY_INFO,
|
|||
|
(LPVOID)&req,
|
|||
|
&inputLen,
|
|||
|
(LPVOID)&info,
|
|||
|
&outputLen
|
|||
|
);
|
|||
|
if (status != TDI_SUCCESS && status != ERROR_MORE_DATA) {
|
|||
|
|
|||
|
//
|
|||
|
// unexpected results - bail out
|
|||
|
//
|
|||
|
|
|||
|
DEBUG_PRINT(("GetAdapterList: WsControl(IF_MIB_STATS_ID) returns %ld\n",
|
|||
|
status
|
|||
|
));
|
|||
|
|
|||
|
// goto error_exit;
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
#ifdef DBG
|
|||
|
if( MyTrace ){
|
|||
|
print_IFEntry( "GetAdapterList", pIfEntry );
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
//
|
|||
|
// we only want physical adapters
|
|||
|
//
|
|||
|
|
|||
|
if (!IS_INTERESTING_ADAPTER(pIfEntry)) {
|
|||
|
|
|||
|
DEBUG_PRINT(("GetAdapterList: ignoring adapter #%ld [%s]\n",
|
|||
|
pIfEntry->if_index,
|
|||
|
if_type$(pIfEntry->if_type)
|
|||
|
));
|
|||
|
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// got this adapter info ok. Create a new IP_ADAPTER_INFO and
|
|||
|
// fill in what we can
|
|||
|
//
|
|||
|
|
|||
|
this = NEW(IP_ADAPTER_INFO);
|
|||
|
if (!this) {
|
|||
|
DEBUG_PRINT(("GetAdapterList: no mem for this IP_ADAPTER_INFO\n"));
|
|||
|
goto error_exit;
|
|||
|
}
|
|||
|
|
|||
|
memset( this, 0, sizeof( IP_ADAPTER_INFO ) );
|
|||
|
|
|||
|
len = (int) min(MAX_ADAPTER_DESCRIPTION_LENGTH,
|
|||
|
(size_t)pIfEntry->if_descrlen);
|
|||
|
|
|||
|
strncpy(this->Description, pIfEntry->if_descr, len);
|
|||
|
this->Description[len] = 0;
|
|||
|
|
|||
|
//
|
|||
|
// if the last word of the description is " Adapter", remove it (its
|
|||
|
// redundant) and if the description is terminated with a period,
|
|||
|
// remove that too
|
|||
|
//
|
|||
|
|
|||
|
// CleanDescription(this->Description);
|
|||
|
|
|||
|
len = (int) min(MAX_ADAPTER_ADDRESS_LENGTH,
|
|||
|
(size_t)pIfEntry->if_physaddrlen);
|
|||
|
|
|||
|
this->AddressLength = (BYTE)len;
|
|||
|
|
|||
|
memcpy(this->Address, pIfEntry->if_physaddr, len);
|
|||
|
|
|||
|
this->Index = (UINT)pIfEntry->if_index;
|
|||
|
this->Type = (UINT)pIfEntry->if_type;
|
|||
|
|
|||
|
//
|
|||
|
// add this IP_ADAPTER_INFO to our list.
|
|||
|
// We build the list sorted according to the adapter order
|
|||
|
// specified for TCP/IP under its Linkage key.
|
|||
|
// In order to put this new entry in the right place in the list,
|
|||
|
// we determine its position in the adapter-order, store that
|
|||
|
// position in the (unused) 'ComboIndex' field, and then use that
|
|||
|
// index for comparison on subsequent insertions.
|
|||
|
// If this IP_ADAPTER_INFO doesn't appear in our list at all,
|
|||
|
// we put it at the end of the current list.
|
|||
|
//
|
|||
|
|
|||
|
for (j = 0; j < adapterOrderMap->NumAdapters; j++) {
|
|||
|
if (adapterOrderMap->AdapterOrder[j] == this->Index) {
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// 'j' now contains the 'order' for the new entry.
|
|||
|
// Put the entry in the right place in the list.
|
|||
|
//
|
|||
|
|
|||
|
this->ComboIndex = j;
|
|||
|
for (prev = NULL, this->Next = list;
|
|||
|
this->Next;
|
|||
|
prev = this->Next, this->Next = this->Next->Next) {
|
|||
|
if (this->ComboIndex >= this->Next->ComboIndex) {
|
|||
|
continue;
|
|||
|
} else {
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
if (prev) { prev->Next = this; }
|
|||
|
if (list == this->Next) { list = this; }
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
OutBufLen = sizeof(IP_UNIDIRECTIONAL_ADAPTER_ADDRESS) + MAX_UNI_ADAPTERS*sizeof(IPAddr);
|
|||
|
pUniInfo = MALLOC(OutBufLen);
|
|||
|
if(!pUniInfo) {
|
|||
|
printf("GetAdapterList: IP_UNIDIRECTIONAL_ADAPTER_ADDRESS resource failure= %ld\n",status);
|
|||
|
DEBUG_PRINT(("GetAdapterList: IP_UNIDIRECTIONAL_ADAPTER_ADDRESS resource failure= %ld\n",status));
|
|||
|
goto error_exit;
|
|||
|
}
|
|||
|
pUniInfo->NumAdapters = 0;
|
|||
|
status = GetUniDirectionalAdapterInfo(pUniInfo, &OutBufLen);
|
|||
|
|
|||
|
if (status == ERROR_MORE_DATA) {
|
|||
|
OutBufLen = sizeof(IP_UNIDIRECTIONAL_ADAPTER_ADDRESS)+pUniInfo->NumAdapters*sizeof(IPAddr);
|
|||
|
pUniInfo = MALLOC(OutBufLen);
|
|||
|
if(!pUniInfo) {
|
|||
|
DEBUG_PRINT(("GetAdapterList: IP_UNIDIRECTIONAL_ADAPTER_ADDRESS resource failure= %ld\n",status));
|
|||
|
goto error_exit;
|
|||
|
}
|
|||
|
status = GetUniDirectionalAdapterInfo(pUniInfo, &OutBufLen);
|
|||
|
}
|
|||
|
if(status != NO_ERROR) {
|
|||
|
DEBUG_PRINT(("GetAdapterList: GetUniDirectionalAdapterInfo returned status= %ld\n",status));
|
|||
|
goto error_exit;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
// ====================================================================
|
|||
|
// pass 2
|
|||
|
// ====================================================================
|
|||
|
|
|||
|
for (i = 0, pEntity = entityList; i < numberOfEntities; ++i, ++pEntity) {
|
|||
|
|
|||
|
DEBUG_PRINT(("Pass 2: Entity %lx [%s] Instance %ld\n",
|
|||
|
pEntity->tei_entity,
|
|||
|
entity$(pEntity->tei_entity),
|
|||
|
pEntity->tei_instance
|
|||
|
));
|
|||
|
|
|||
|
if (pEntity->tei_entity == CL_NL_ENTITY) {
|
|||
|
|
|||
|
IPSNMPInfo info;
|
|||
|
DWORD type;
|
|||
|
|
|||
|
//
|
|||
|
// first off, see if this network layer entity supports IP
|
|||
|
//
|
|||
|
|
|||
|
memset(&req, 0, sizeof(req));
|
|||
|
|
|||
|
id.toi_entity = *pEntity;
|
|||
|
id.toi_class = INFO_CLASS_GENERIC;
|
|||
|
id.toi_type = INFO_TYPE_PROVIDER;
|
|||
|
id.toi_id = ENTITY_TYPE_ID;
|
|||
|
|
|||
|
req.ID = id;
|
|||
|
|
|||
|
inputLen = sizeof(req);
|
|||
|
outputLen = sizeof(type);
|
|||
|
|
|||
|
status = WsControl(IPPROTO_TCP,
|
|||
|
WSCNTL_TCPIP_QUERY_INFO,
|
|||
|
(LPVOID)&req,
|
|||
|
&inputLen,
|
|||
|
(LPVOID)&type,
|
|||
|
&outputLen
|
|||
|
);
|
|||
|
|
|||
|
if (status != TDI_SUCCESS) {
|
|||
|
|
|||
|
//
|
|||
|
// unexpected results - bail out
|
|||
|
//
|
|||
|
|
|||
|
DEBUG_PRINT(("GetAdapterList: WsControl(ENTITY_TYPE_ID): status = %ld, outputLen = %ld\n",
|
|||
|
status,
|
|||
|
outputLen
|
|||
|
));
|
|||
|
|
|||
|
// goto error_exit;
|
|||
|
continue;
|
|||
|
}
|
|||
|
if (type != CL_NL_IP) {
|
|||
|
|
|||
|
//
|
|||
|
// nope, not IP - try next one
|
|||
|
//
|
|||
|
|
|||
|
DEBUG_PRINT(("GetAdapterList: CL_NL_ENTITY #%ld not CL_NL_IP\n",
|
|||
|
pEntity->tei_instance
|
|||
|
));
|
|||
|
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// okay, this NL provider supports IP. Let's get them addresses:
|
|||
|
// First we find out how many by getting the SNMP stats and looking
|
|||
|
// at the number of addresses supported by this interface
|
|||
|
//
|
|||
|
|
|||
|
memset(&req, 0, sizeof(req));
|
|||
|
|
|||
|
id.toi_class = INFO_CLASS_PROTOCOL;
|
|||
|
id.toi_id = IP_MIB_STATS_ID;
|
|||
|
|
|||
|
req.ID = id;
|
|||
|
|
|||
|
inputLen = sizeof(req);
|
|||
|
outputLen = sizeof(info);
|
|||
|
|
|||
|
status = WsControl(IPPROTO_TCP,
|
|||
|
WSCNTL_TCPIP_QUERY_INFO,
|
|||
|
(LPVOID)&req,
|
|||
|
&inputLen,
|
|||
|
(LPVOID)&info,
|
|||
|
&outputLen
|
|||
|
);
|
|||
|
if ((status != TDI_SUCCESS) || (outputLen != sizeof(info))) {
|
|||
|
|
|||
|
//
|
|||
|
// unexpected results - bail out
|
|||
|
//
|
|||
|
|
|||
|
DEBUG_PRINT(("GetAdapterList: WsControl(IP_MIB_STATS_ID): status = %ld, outputLen = %ld\n",
|
|||
|
status,
|
|||
|
outputLen
|
|||
|
));
|
|||
|
|
|||
|
// goto error_exit;
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// get the IP addresses & subnet masks
|
|||
|
//
|
|||
|
|
|||
|
if (info.ipsi_numaddr) {
|
|||
|
|
|||
|
//
|
|||
|
// this interface has some addresses. What are they?
|
|||
|
//
|
|||
|
|
|||
|
LPVOID buffer;
|
|||
|
UINT numberOfAddresses;
|
|||
|
IPAddrEntry* pAddr;
|
|||
|
UINT i;
|
|||
|
|
|||
|
outputLen = (info.ipsi_numaddr + OVERFLOW_COUNT) *
|
|||
|
sizeof(IPAddrEntry);
|
|||
|
buffer = (LPVOID)NEW_MEMORY((size_t)outputLen);
|
|||
|
if (!buffer) {
|
|||
|
DEBUG_PRINT(("GetAdapterList:NEW_MEMORY failed.\n" ));
|
|||
|
goto error_exit;
|
|||
|
}
|
|||
|
|
|||
|
memset(&req, 0, sizeof(req));
|
|||
|
|
|||
|
id.toi_id = IP_MIB_ADDRTABLE_ENTRY_ID;
|
|||
|
|
|||
|
req.ID = id;
|
|||
|
|
|||
|
inputLen = sizeof(req);
|
|||
|
|
|||
|
status = WsControl(IPPROTO_TCP,
|
|||
|
WSCNTL_TCPIP_QUERY_INFO,
|
|||
|
(LPVOID)&req,
|
|||
|
&inputLen,
|
|||
|
(LPVOID)buffer,
|
|||
|
&outputLen
|
|||
|
);
|
|||
|
|
|||
|
if (status != TDI_SUCCESS) {
|
|||
|
|
|||
|
//
|
|||
|
// unexpected results - bail out
|
|||
|
//
|
|||
|
|
|||
|
DEBUG_PRINT(("GetAdapterList: WsControl(IP_MIB_ADDRTABLE_ENTRY_ID): status = %ld, outputLen = %ld\n",
|
|||
|
status,
|
|||
|
outputLen
|
|||
|
));
|
|||
|
|
|||
|
// goto error_exit;
|
|||
|
ReleaseMemory((void*)buffer);
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// now loop through this list of IP addresses, applying them
|
|||
|
// to the correct adapter
|
|||
|
//
|
|||
|
|
|||
|
numberOfAddresses = min((UINT)(outputLen / sizeof(IPAddrEntry)),
|
|||
|
(UINT)info.ipsi_numaddr
|
|||
|
);
|
|||
|
|
|||
|
DEBUG_PRINT(("GetAdapterList: %d IP addresses\n", numberOfAddresses));
|
|||
|
|
|||
|
pAddr = (IPAddrEntry*)buffer;
|
|||
|
for (i = 0; i < numberOfAddresses; ++i, ++pAddr) {
|
|||
|
|
|||
|
PIP_ADAPTER_INFO pAdapterInfo;
|
|||
|
|
|||
|
DEBUG_PRINT(("GetAdapterList: IP address %d.%d.%d.%d, index %ld, context %ld\n",
|
|||
|
((LPBYTE)&pAddr->iae_addr)[0] & 0xff,
|
|||
|
((LPBYTE)&pAddr->iae_addr)[1] & 0xff,
|
|||
|
((LPBYTE)&pAddr->iae_addr)[2] & 0xff,
|
|||
|
((LPBYTE)&pAddr->iae_addr)[3] & 0xff,
|
|||
|
pAddr->iae_index,
|
|||
|
pAddr->iae_context
|
|||
|
));
|
|||
|
|
|||
|
for (pAdapterInfo = list; pAdapterInfo; pAdapterInfo = pAdapterInfo->Next) {
|
|||
|
if (pAdapterInfo->Index == (UINT)pAddr->iae_index) {
|
|||
|
|
|||
|
DEBUG_PRINT(("GetAdapterList: adding IP address %d.%d.%d.%d, index %d, context %d\n",
|
|||
|
((LPBYTE)&pAddr->iae_addr)[0] & 0xff,
|
|||
|
((LPBYTE)&pAddr->iae_addr)[1] & 0xff,
|
|||
|
((LPBYTE)&pAddr->iae_addr)[2] & 0xff,
|
|||
|
((LPBYTE)&pAddr->iae_addr)[3] & 0xff,
|
|||
|
pAddr->iae_index,
|
|||
|
pAddr->iae_context
|
|||
|
));
|
|||
|
|
|||
|
//
|
|||
|
// Append the IP address to the list.
|
|||
|
// Note that this operation preserves the order
|
|||
|
// of the IP address list returned by TCP/IP.
|
|||
|
// This is important because that list contains
|
|||
|
// entries listed in the *reverse* of the order
|
|||
|
// specified for each adapter. A number of clients
|
|||
|
// depend upon this fact when calling this and
|
|||
|
// other API routines.
|
|||
|
//
|
|||
|
|
|||
|
if (!AddIpAddress(&pAdapterInfo->IpAddressList,
|
|||
|
pAddr->iae_addr,
|
|||
|
pAddr->iae_mask,
|
|||
|
pAddr->iae_context
|
|||
|
)) {
|
|||
|
ReleaseMemory((void*)buffer);
|
|||
|
goto error_exit;
|
|||
|
}
|
|||
|
|
|||
|
for (j = 0; j < pUniInfo->NumAdapters ; j++) {
|
|||
|
|
|||
|
if (pAddr->iae_index == pUniInfo->Address[j] ) {
|
|||
|
|
|||
|
//
|
|||
|
// Use DhcpEnabled field as a temporary
|
|||
|
// storage to remember the type
|
|||
|
//
|
|||
|
pAdapterInfo->DhcpEnabled = IF_TYPE_RECEIVE_ONLY;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
ReleaseMemory((void*)buffer);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// get the gateway server IP address(es)
|
|||
|
//
|
|||
|
|
|||
|
if (info.ipsi_numroutes) {
|
|||
|
|
|||
|
IPRouteEntry* routeTable;
|
|||
|
IPRouteEntry* pRoute;
|
|||
|
UINT numberOfRoutes;
|
|||
|
UINT i;
|
|||
|
int moreRoutes = TRUE;
|
|||
|
|
|||
|
memset(&req, 0, sizeof(req));
|
|||
|
|
|||
|
id.toi_id = IP_MIB_RTTABLE_ENTRY_ID;
|
|||
|
|
|||
|
req.ID = id;
|
|||
|
|
|||
|
inputLen = sizeof(req);
|
|||
|
outputLen = sizeof(IPRouteEntry) * info.ipsi_numroutes;
|
|||
|
routeTable = NULL;
|
|||
|
|
|||
|
//
|
|||
|
// the route table may have grown since we got the SNMP stats
|
|||
|
//
|
|||
|
|
|||
|
while (moreRoutes) {
|
|||
|
|
|||
|
DWORD previousOutputLen;
|
|||
|
|
|||
|
previousOutputLen = outputLen;
|
|||
|
if (routeTable) {
|
|||
|
ReleaseMemory((void*)routeTable);
|
|||
|
routeTable = NULL;
|
|||
|
}
|
|||
|
routeTable = (IPRouteEntry*)NEW_MEMORY((size_t)outputLen);
|
|||
|
if (!routeTable) {
|
|||
|
goto error_exit;
|
|||
|
}
|
|||
|
|
|||
|
status = WsControl(IPPROTO_TCP,
|
|||
|
WSCNTL_TCPIP_QUERY_INFO,
|
|||
|
(LPVOID)&req,
|
|||
|
&inputLen,
|
|||
|
(LPVOID)routeTable,
|
|||
|
&outputLen
|
|||
|
);
|
|||
|
if (status != TDI_SUCCESS) {
|
|||
|
|
|||
|
//
|
|||
|
// unexpected results - bail out
|
|||
|
//
|
|||
|
|
|||
|
DEBUG_PRINT(("GetAdapterList: WsControl(IP_MIB_RTTABLE_ENTRY_ID): status = %ld, outputLen = %ld\n",
|
|||
|
status,
|
|||
|
outputLen
|
|||
|
));
|
|||
|
|
|||
|
if (status == ERROR_MORE_DATA) {
|
|||
|
TCP_REQUEST_QUERY_INFORMATION_EX statsReq;
|
|||
|
IPSNMPInfo statsInfo;
|
|||
|
DWORD inLen;
|
|||
|
DWORD outLen;
|
|||
|
|
|||
|
memset(&statsReq, 0, sizeof(statsReq));
|
|||
|
|
|||
|
id.toi_id = IP_MIB_STATS_ID;
|
|||
|
|
|||
|
statsReq.ID = id;
|
|||
|
|
|||
|
inLen = sizeof(statsReq);
|
|||
|
outLen = sizeof(statsInfo);
|
|||
|
|
|||
|
status = WsControl( IPPROTO_TCP,
|
|||
|
WSCNTL_TCPIP_QUERY_INFO,
|
|||
|
(LPVOID)&statsReq,
|
|||
|
&inLen,
|
|||
|
(LPVOID)&statsInfo,
|
|||
|
&outLen);
|
|||
|
|
|||
|
if (status != TDI_SUCCESS || outLen != sizeof(statsInfo)) {
|
|||
|
ReleaseMemory((void*)routeTable);
|
|||
|
goto error_exit;
|
|||
|
} else {
|
|||
|
outputLen = sizeof(IPRouteEntry) * statsInfo.ipsi_numroutes;
|
|||
|
}
|
|||
|
} else {
|
|||
|
ReleaseMemory((void*)routeTable);
|
|||
|
goto error_exit;
|
|||
|
}
|
|||
|
}
|
|||
|
if (outputLen <= previousOutputLen) {
|
|||
|
moreRoutes = FALSE;
|
|||
|
}
|
|||
|
}
|
|||
|
numberOfRoutes = (UINT)(outputLen / sizeof(IPRouteEntry));
|
|||
|
for (i = 0, pRoute = routeTable; i < numberOfRoutes; ++i, ++pRoute)
|
|||
|
{
|
|||
|
|
|||
|
//
|
|||
|
// the gateway address has a destination of 0.0.0.0
|
|||
|
//
|
|||
|
|
|||
|
if (pRoute->ire_dest == INADDR_ANY) {
|
|||
|
|
|||
|
PIP_ADAPTER_INFO pAdapterInfo = list;
|
|||
|
|
|||
|
for (; pAdapterInfo; pAdapterInfo = pAdapterInfo->Next) {
|
|||
|
if (pAdapterInfo->Index == (UINT)pRoute->ire_index) {
|
|||
|
TRACE_PRINT(("GetAdapterList: gw=0x%08x.\n",
|
|||
|
pRoute->ire_nexthop ));
|
|||
|
if (!AddIpAddress(&pAdapterInfo->GatewayList,
|
|||
|
pRoute->ire_nexthop,
|
|||
|
|
|||
|
//
|
|||
|
// gateway IP address doesn't
|
|||
|
// have corresponding IP mask
|
|||
|
//
|
|||
|
|
|||
|
INADDR_ANY,
|
|||
|
0
|
|||
|
)) {
|
|||
|
ReleaseMemory((void*)routeTable);
|
|||
|
goto error_exit;
|
|||
|
}
|
|||
|
// MohsinA, 22-Jul-97.
|
|||
|
// break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
ReleaseMemory((void*)routeTable);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// ====================================================================
|
|||
|
|
|||
|
ReleaseMemory((void*)entityList);
|
|||
|
ReleaseMemory(adapterOrderMap);
|
|||
|
|
|||
|
//
|
|||
|
// If there are any unidirectional adapters
|
|||
|
// move them to the end of the list
|
|||
|
//
|
|||
|
|
|||
|
tmp = list;
|
|||
|
|
|||
|
if (pUniInfo->NumAdapters) {
|
|||
|
|
|||
|
this = list;
|
|||
|
prev = NULL;
|
|||
|
|
|||
|
while (this) {
|
|||
|
|
|||
|
if (this->DhcpEnabled == IF_TYPE_RECEIVE_ONLY) {
|
|||
|
|
|||
|
//
|
|||
|
// Remove "this" from the list
|
|||
|
//
|
|||
|
|
|||
|
if (prev) {
|
|||
|
prev->Next = this->Next;
|
|||
|
} else {
|
|||
|
prev = this->Next;
|
|||
|
list = this->Next;
|
|||
|
}
|
|||
|
tmp = this->Next;
|
|||
|
|
|||
|
//
|
|||
|
// Restore DhcbEnabled
|
|||
|
//
|
|||
|
|
|||
|
this->DhcpEnabled = FALSE;
|
|||
|
|
|||
|
//
|
|||
|
// Chain this to list of TV adapters
|
|||
|
//
|
|||
|
|
|||
|
this->Next = UniList;
|
|||
|
UniList = this;
|
|||
|
this = tmp;
|
|||
|
|
|||
|
} else {
|
|||
|
prev = this;
|
|||
|
this = this->Next;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Insert UniList at the end.
|
|||
|
//
|
|||
|
if (prev) {
|
|||
|
prev->Next = UniList;
|
|||
|
} else {
|
|||
|
ASSERT(list == NULL);
|
|||
|
list = UniList;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
FREE(pUniInfo);
|
|||
|
|
|||
|
return list;
|
|||
|
|
|||
|
error_exit:
|
|||
|
|
|||
|
DEBUG_PRINT(("GetAdapterList: <= failed\n"));
|
|||
|
|
|||
|
if (entityList) {
|
|||
|
ReleaseMemory((void*)entityList);
|
|||
|
}
|
|||
|
if (adapterOrderMap) {
|
|||
|
ReleaseMemory(adapterOrderMap);
|
|||
|
}
|
|||
|
if (pUniInfo) {
|
|||
|
FREE(pUniInfo);
|
|||
|
}
|
|||
|
|
|||
|
KillAdapterInfo(list);
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/*******************************************************************************
|
|||
|
*
|
|||
|
* AddIpAddress
|
|||
|
*
|
|||
|
* Adds an IP_ADDR_STRING to a list. If the input IP_ADDR_STRING is empty this
|
|||
|
* is filled in, else a new IP_ADDR_STRING is allocated and chained to the
|
|||
|
* input IP_ADDR_STRING
|
|||
|
*
|
|||
|
* ENTRY AddressList - pointer to IP_ADDR which may or may not already hold
|
|||
|
* an IP address
|
|||
|
* Address - IP address to add
|
|||
|
* Mask - corresponding IP subnet mask
|
|||
|
* Context - address context
|
|||
|
*
|
|||
|
* EXIT AddressList - updated with new info
|
|||
|
*
|
|||
|
* RETURNS Success - 1
|
|||
|
* Failure - 0
|
|||
|
*
|
|||
|
* ASSUMES 1. INADDR_ANY (ulong 0) indicates inactive IP address
|
|||
|
*
|
|||
|
******************************************************************************/
|
|||
|
|
|||
|
int AddIpAddress(PIP_ADDR_STRING AddressList, DWORD Address, DWORD Mask, DWORD Context)
|
|||
|
{
|
|||
|
|
|||
|
PIP_ADDR_STRING ipAddr;
|
|||
|
|
|||
|
if (AddressList->IpAddress.String[0]) {
|
|||
|
for (ipAddr = AddressList; ipAddr->Next; ipAddr = ipAddr->Next) {
|
|||
|
;
|
|||
|
}
|
|||
|
ipAddr->Next = NEW(IP_ADDR_STRING);
|
|||
|
if (!ipAddr->Next) {
|
|||
|
|
|||
|
DEBUG_PRINT(("AddIpAddress: failed to allocate memory for IP_ADDR_STRING\n"));
|
|||
|
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
ipAddr = ipAddr->Next;
|
|||
|
} else {
|
|||
|
ipAddr = AddressList;
|
|||
|
}
|
|||
|
ConvertIpAddressToString(Address, ipAddr->IpAddress.String);
|
|||
|
ConvertIpAddressToString(Mask, ipAddr->IpMask.String);
|
|||
|
ipAddr->Context = Context;
|
|||
|
ipAddr->Next = NULL;
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/*******************************************************************************
|
|||
|
*
|
|||
|
* AddIpAddressString
|
|||
|
*
|
|||
|
* Same as AddIpAddress, except the arguments are already converted to strings
|
|||
|
*
|
|||
|
* ENTRY AddressList - pointer to IP_ADDR which may or may not already hold
|
|||
|
* an IP address
|
|||
|
* Address - IP address to add, as a string
|
|||
|
* Mask - corresponding IP subnet mask, as a string
|
|||
|
*
|
|||
|
* EXIT AddressList - updated with new info
|
|||
|
*
|
|||
|
* RETURNS Success - 1
|
|||
|
* Failure - 0
|
|||
|
*
|
|||
|
* ASSUMES nothing
|
|||
|
*
|
|||
|
******************************************************************************/
|
|||
|
|
|||
|
int AddIpAddressString(PIP_ADDR_STRING AddressList, LPSTR Address, LPSTR Mask)
|
|||
|
{
|
|||
|
|
|||
|
PIP_ADDR_STRING ipAddr;
|
|||
|
|
|||
|
if (AddressList->IpAddress.String[0]) {
|
|||
|
for (ipAddr = AddressList; ipAddr->Next; ipAddr = ipAddr->Next) {
|
|||
|
if (!strncmp(ipAddr->IpAddress.String, Address, sizeof(ipAddr->IpAddress.String))) {
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
}
|
|||
|
if (!strncmp(ipAddr->IpAddress.String, Address, sizeof(ipAddr->IpAddress.String))) {
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
ipAddr->Next = NEW(IP_ADDR_STRING);
|
|||
|
if (!ipAddr->Next) {
|
|||
|
|
|||
|
DEBUG_PRINT(("AddIpAddressString: failed to allocate memory for IP_ADDR_STRING\n"));
|
|||
|
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
ipAddr = ipAddr->Next;
|
|||
|
} else {
|
|||
|
ipAddr = AddressList;
|
|||
|
}
|
|||
|
CopyString(ipAddr->IpAddress.String, sizeof(ipAddr->IpAddress.String), Address);
|
|||
|
CopyString(ipAddr->IpMask.String, sizeof(ipAddr->IpMask.String), Mask);
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/*******************************************************************************
|
|||
|
*
|
|||
|
* ConvertIpAddressToString
|
|||
|
*
|
|||
|
* Converts a DWORD IP address or subnet mask to dotted decimal string
|
|||
|
*
|
|||
|
* ENTRY IpAddress - IP Address to convert
|
|||
|
* String - pointer to place to store dotted decimal string
|
|||
|
*
|
|||
|
* EXIT String contains ASCII representation of IpAddress
|
|||
|
*
|
|||
|
* RETURNS nothing
|
|||
|
*
|
|||
|
* ASSUMES 1. IP address fits in a DWORD
|
|||
|
*
|
|||
|
******************************************************************************/
|
|||
|
|
|||
|
VOID ConvertIpAddressToString(DWORD IpAddress, LPSTR String)
|
|||
|
{
|
|||
|
|
|||
|
IP_ADDRESS ipAddr;
|
|||
|
|
|||
|
ipAddr.d = IpAddress;
|
|||
|
sprintf(String,
|
|||
|
"%d.%d.%d.%d",
|
|||
|
ipAddr.b[0],
|
|||
|
ipAddr.b[1],
|
|||
|
ipAddr.b[2],
|
|||
|
ipAddr.b[3]
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/*******************************************************************************
|
|||
|
*
|
|||
|
* CopyString
|
|||
|
*
|
|||
|
* Copies a string to a buffer. If the buffer would overflow, the string is
|
|||
|
* truncated
|
|||
|
*
|
|||
|
* ENTRY Destination - destination buffer to copy to
|
|||
|
* DestinationLength - size of Destination
|
|||
|
* Source - source string to copy
|
|||
|
*
|
|||
|
* EXIT Destination updated
|
|||
|
*
|
|||
|
* RETURNS nothing
|
|||
|
*
|
|||
|
* ASSUMES
|
|||
|
*
|
|||
|
******************************************************************************/
|
|||
|
|
|||
|
VOID CopyString(LPSTR Destination, DWORD DestinationLength, LPSTR Source)
|
|||
|
{
|
|||
|
|
|||
|
DWORD maximumCharacters = min(DestinationLength - 1, STRLEN(Source));
|
|||
|
|
|||
|
strncpy(Destination, Source, maximumCharacters);
|
|||
|
Destination[maximumCharacters] = '\0';
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/*******************************************************************************
|
|||
|
*
|
|||
|
* CleanDescription
|
|||
|
*
|
|||
|
* Given an adapter description string retrieved from TCP/IP, remove the
|
|||
|
* trailing substring " Adapter". If there is a trailing period, remove that
|
|||
|
* too
|
|||
|
*
|
|||
|
* ENTRY String - pointer to description string to clean up
|
|||
|
*
|
|||
|
* EXIT String - possibly bits removed
|
|||
|
*
|
|||
|
* RETURNS voidsville
|
|||
|
*
|
|||
|
* ASSUMES
|
|||
|
*
|
|||
|
******************************************************************************/
|
|||
|
|
|||
|
void CleanDescription(LPSTR String)
|
|||
|
{
|
|||
|
|
|||
|
int len = STRLEN(String);
|
|||
|
|
|||
|
if (String[len - 1] == '.') {
|
|||
|
String[--len] = 0;
|
|||
|
}
|
|||
|
if (!STRICMP(String + len - (sizeof(" Adapter") - 1), " Adapter")) {
|
|||
|
len -= sizeof(" Adapter") - 1;
|
|||
|
String[len] = 0;
|
|||
|
}
|
|||
|
}
|
|||
|
|