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;
|
||
}
|
||
}
|
||
|