660 lines
14 KiB
C
660 lines
14 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1995 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
wanarp\info.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
The file contains the code that is involved with setting and
|
||
|
getting info for the adapters and interfaces
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
AmritanR
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#define __FILE_SIG__ INFO_SIG
|
||
|
|
||
|
#include "inc.h"
|
||
|
|
||
|
|
||
|
|
||
|
INT
|
||
|
WanIpSetRequest(
|
||
|
PVOID pvContext,
|
||
|
NDIS_OID Oid,
|
||
|
UINT Type
|
||
|
)
|
||
|
{
|
||
|
return NDIS_STATUS_SUCCESS;
|
||
|
}
|
||
|
|
||
|
|
||
|
UINT
|
||
|
WanIpAddAddress(
|
||
|
IN PVOID pvContext,
|
||
|
IN UINT uiType,
|
||
|
IN DWORD dwAddress,
|
||
|
IN DWORD dwMask,
|
||
|
IN PVOID pvUnused
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine is called by the upper layer to add an address as a local
|
||
|
address, or specify the broadcast address for this Interface
|
||
|
|
||
|
Locks:
|
||
|
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
|
||
|
Return Value:
|
||
|
NO_ERROR
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
TraceEnter(ADPT, "WanAddAddress");
|
||
|
|
||
|
Trace(ADPT, TRACE,
|
||
|
("AddAddress: %d.%d.%d.%d\n", PRINT_IPADDR(dwAddress)));
|
||
|
|
||
|
TraceLeave(ADPT, "WanAddAddress");
|
||
|
|
||
|
return (UINT)TRUE;
|
||
|
}
|
||
|
|
||
|
UINT
|
||
|
WanIpDeleteAddress(
|
||
|
IN PVOID pvContext,
|
||
|
IN UINT uiType,
|
||
|
IN DWORD dwAddress,
|
||
|
IN DWORD dwMask
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Called to delete a local or proxy address.
|
||
|
|
||
|
Locks:
|
||
|
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
|
||
|
Return Value:
|
||
|
NO_ERROR
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
TraceEnter(ADPT, "WanDeleteAddress");
|
||
|
|
||
|
Trace(ADPT, TRACE,
|
||
|
("DeleteAddress: %d.%d.%d.%d\n", PRINT_IPADDR(dwAddress)));
|
||
|
|
||
|
TraceLeave(ADPT, "WanDeleteAddress");
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
INT
|
||
|
WanIpQueryInfo(
|
||
|
IN PVOID pvIfContext,
|
||
|
IN TDIObjectID *pTdiObjId,
|
||
|
IN PNDIS_BUFFER pnbBuffer,
|
||
|
IN PUINT puiSize,
|
||
|
IN PVOID pvContext
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Routine is called by IP to query the MIB-II information related
|
||
|
to the UMODE_INTERFACE. IP passes us a pointer to the ADAPTER. We map
|
||
|
it to the UMODE_INTERFACE using the ADAPTER and pass back the
|
||
|
statistics related to that UMODE_INTERFACE
|
||
|
|
||
|
Locks:
|
||
|
|
||
|
We acquire the adapter lock and get a pointer to the interface from the
|
||
|
adapter. We dont lock the interface because all the info copied
|
||
|
out is changed by InterlockedXxx. Also because the adapter has a mapping
|
||
|
from to the interface, the interface can not be deleted since to
|
||
|
to bring the refcount on the interface to 0, this mapping needs to be
|
||
|
cleared from the adapter, which needs the adapter lock, which we are
|
||
|
holding
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pvIfContext The context we returned to IP, a pointer to the ADAPTER
|
||
|
pTdiObjId
|
||
|
pnbBuffer
|
||
|
puiSize
|
||
|
pvContext
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TDI_INVALID_REQUEST
|
||
|
TDI_INVALID_PARAMETER
|
||
|
TDI_BUFFER_TOO_SMALL
|
||
|
TDI_BUFFER_OVERFLOW
|
||
|
TDI_SUCCESS
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
PADAPTER pAdapter;
|
||
|
PUMODE_INTERFACE pInterface;
|
||
|
ULONG ulOffset;
|
||
|
ULONG ulBufferSize;
|
||
|
UINT BytesCopied = 0;
|
||
|
BYTE rgbyInfoBuff[sizeof(IFEntry)];
|
||
|
DWORD dwEntity;
|
||
|
DWORD dwInstance;
|
||
|
IFEntry *pIFE;
|
||
|
NTSTATUS nStatus;
|
||
|
KIRQL kiIrql;
|
||
|
|
||
|
dwEntity = pTdiObjId->toi_entity.tei_entity;
|
||
|
dwInstance = pTdiObjId->toi_entity.tei_instance;
|
||
|
pAdapter = (PADAPTER)pvIfContext;
|
||
|
|
||
|
//
|
||
|
// We support only Interface MIBs - no address xlation - pretty much like
|
||
|
// a loopback i/f (per Henry circa 1994)
|
||
|
//
|
||
|
|
||
|
if((dwEntity isnot IF_ENTITY) or
|
||
|
(dwInstance isnot pAdapter->dwIfInstance))
|
||
|
{
|
||
|
return TDI_INVALID_REQUEST;
|
||
|
}
|
||
|
|
||
|
if(pTdiObjId->toi_type isnot INFO_TYPE_PROVIDER)
|
||
|
{
|
||
|
Trace(ADPT, INFO,
|
||
|
("IpQueryInfo: toi_type is wrong 0x%x\n",
|
||
|
pTdiObjId->toi_type));
|
||
|
|
||
|
return TDI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// a safe initialization.
|
||
|
//
|
||
|
|
||
|
ulBufferSize = *puiSize;
|
||
|
*puiSize = 0;
|
||
|
ulOffset = 0;
|
||
|
|
||
|
if(pTdiObjId->toi_class is INFO_CLASS_GENERIC)
|
||
|
{
|
||
|
if(pTdiObjId->toi_id isnot ENTITY_TYPE_ID)
|
||
|
{
|
||
|
Trace(ADPT, INFO,
|
||
|
("IpQueryInfo: toi_id is wrong 0x%x\n",
|
||
|
pTdiObjId->toi_id));
|
||
|
|
||
|
return TDI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// He's trying to see what type we are.
|
||
|
//
|
||
|
|
||
|
if(ulBufferSize < sizeof(DWORD))
|
||
|
{
|
||
|
Trace(ADPT, ERROR,
|
||
|
("IpQueryInfo: Buffer size %d too small\n",
|
||
|
ulBufferSize));
|
||
|
|
||
|
return TDI_BUFFER_TOO_SMALL;
|
||
|
}
|
||
|
|
||
|
*(PDWORD)&rgbyInfoBuff[0] = (dwEntity is AT_ENTITY) ? AT_ARP : IF_MIB;
|
||
|
|
||
|
#if NDISBUFFERISMDL
|
||
|
|
||
|
nStatus = TdiCopyBufferToMdl(rgbyInfoBuff,
|
||
|
0,
|
||
|
sizeof(DWORD),
|
||
|
(PMDL)pnbBuffer,
|
||
|
0,
|
||
|
&ulOffset);
|
||
|
|
||
|
#else
|
||
|
#error "Fix this"
|
||
|
#endif
|
||
|
|
||
|
*puiSize = ulOffset;
|
||
|
|
||
|
return nStatus;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
if(pTdiObjId->toi_class isnot INFO_CLASS_PROTOCOL)
|
||
|
{
|
||
|
Trace(ADPT, INFO,
|
||
|
("IpQueryInfo: toi_class is wrong 0x%x\n",
|
||
|
pTdiObjId->toi_class));
|
||
|
|
||
|
return TDI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// The usermust be asking for Interface level information.
|
||
|
// See if we support what is being asked for
|
||
|
//
|
||
|
|
||
|
if(pTdiObjId->toi_id isnot IF_MIB_STATS_ID)
|
||
|
{
|
||
|
Trace(ADPT, INFO,
|
||
|
("IpQueryInfo: toi_id 0x%x is not MIB_STATS\n",
|
||
|
pTdiObjId->toi_id));
|
||
|
|
||
|
return TDI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// He's asking for statistics. Make sure his buffer is at least big
|
||
|
// enough to hold the fixed part.
|
||
|
//
|
||
|
|
||
|
if(ulBufferSize < IFE_FIXED_SIZE)
|
||
|
{
|
||
|
Trace(ADPT, ERROR,
|
||
|
("IpQueryInfo: Buffer size %d smaller than IFE %d\n",
|
||
|
ulBufferSize, IFE_FIXED_SIZE));
|
||
|
|
||
|
return TDI_BUFFER_TOO_SMALL;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// He's got enough to hold the fixed part. Build the IFEntry structure,
|
||
|
// and copy it to his buffer.
|
||
|
//
|
||
|
|
||
|
pAdapter = (PADAPTER)pvIfContext;
|
||
|
|
||
|
pIFE = (IFEntry *)rgbyInfoBuff;
|
||
|
|
||
|
RtlZeroMemory(pIFE,
|
||
|
sizeof(IFEntry));
|
||
|
|
||
|
RtAcquireSpinLock(&(pAdapter->rlLock),
|
||
|
&kiIrql);
|
||
|
|
||
|
//
|
||
|
// This stuff doesnt require an interface to be mapped
|
||
|
//
|
||
|
|
||
|
pIFE->if_index = pAdapter->dwAdapterIndex;
|
||
|
pIFE->if_type = IF_TYPE_PPP;
|
||
|
pIFE->if_physaddrlen = ARP_802_ADDR_LENGTH;
|
||
|
pIFE->if_outqlen = pAdapter->ulQueueLen;
|
||
|
pIFE->if_descrlen = VENDOR_DESCRIPTION_STRING_LEN;
|
||
|
|
||
|
RtlCopyMemory(pIFE->if_physaddr,
|
||
|
pAdapter->rgbyHardwareAddr,
|
||
|
ARP_802_ADDR_LENGTH);
|
||
|
|
||
|
if(pAdapter->byState isnot AS_MAPPED)
|
||
|
{
|
||
|
Trace(ADPT, INFO,
|
||
|
("IpQueryInfo: called for adapter %x that is unmapped\n",
|
||
|
pAdapter));
|
||
|
|
||
|
#if 0
|
||
|
RtReleaseSpinLock(&(pAdapter->rlLock),
|
||
|
kiIrql);
|
||
|
|
||
|
return TDI_INVALID_PARAMETER;
|
||
|
#endif
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//
|
||
|
// Get a pointer to the interface and lock the interface
|
||
|
//
|
||
|
|
||
|
pInterface = pAdapter->pInterface;
|
||
|
|
||
|
RtAssert(pInterface);
|
||
|
|
||
|
if(pAdapter->pConnEntry is NULL)
|
||
|
{
|
||
|
//
|
||
|
// If a mapped adapter doesnt have an associated connection, then
|
||
|
// it is either server adapter or router in process of connecting
|
||
|
//
|
||
|
|
||
|
RtAssert((pInterface->duUsage is DU_CALLIN) or
|
||
|
((pInterface->duUsage is DU_ROUTER) and
|
||
|
(pInterface->dwOperState is IF_OPER_STATUS_CONNECTING)));
|
||
|
|
||
|
pIFE->if_mtu = WANARP_DEFAULT_MTU;
|
||
|
pIFE->if_speed = WANARP_DEFAULT_SPEED;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pIFE->if_mtu = pAdapter->pConnEntry->ulMtu;
|
||
|
pIFE->if_speed = pAdapter->pConnEntry->ulSpeed;
|
||
|
}
|
||
|
|
||
|
pIFE->if_adminstatus = pInterface->dwAdminState;
|
||
|
pIFE->if_operstatus = pInterface->dwOperState;
|
||
|
pIFE->if_lastchange = pInterface->dwLastChange;
|
||
|
pIFE->if_inoctets = pInterface->ulInOctets;
|
||
|
pIFE->if_inucastpkts = pInterface->ulInUniPkts;
|
||
|
pIFE->if_innucastpkts = pInterface->ulInNonUniPkts;
|
||
|
pIFE->if_indiscards = pInterface->ulInDiscards;
|
||
|
pIFE->if_inerrors = pInterface->ulInErrors;
|
||
|
pIFE->if_inunknownprotos = pInterface->ulInUnknownProto;
|
||
|
pIFE->if_outoctets = pInterface->ulOutOctets;
|
||
|
pIFE->if_outucastpkts = pInterface->ulOutUniPkts;
|
||
|
pIFE->if_outnucastpkts = pInterface->ulOutNonUniPkts;
|
||
|
pIFE->if_outdiscards = pInterface->ulOutDiscards;
|
||
|
pIFE->if_outerrors = pInterface->ulOutErrors;
|
||
|
}
|
||
|
|
||
|
#if NDISBUFFERISMDL
|
||
|
|
||
|
nStatus = TdiCopyBufferToMdl(pIFE,
|
||
|
0,
|
||
|
IFE_FIXED_SIZE,
|
||
|
(PMDL)pnbBuffer,
|
||
|
0,
|
||
|
&ulOffset);
|
||
|
|
||
|
#else
|
||
|
#error "Fix this"
|
||
|
#endif
|
||
|
|
||
|
//
|
||
|
// See if he has room for the descriptor string.
|
||
|
//
|
||
|
|
||
|
if(ulBufferSize < (IFE_FIXED_SIZE + VENDOR_DESCRIPTION_STRING_LEN))
|
||
|
{
|
||
|
Trace(ADPT, INFO,
|
||
|
("IpQueryInfo: Buffer size %d too small for VENDOR string\n",
|
||
|
ulBufferSize));
|
||
|
|
||
|
//
|
||
|
// Not enough room to copy the desc. string.
|
||
|
//
|
||
|
|
||
|
*puiSize = IFE_FIXED_SIZE;
|
||
|
|
||
|
RtReleaseSpinLock(&(pAdapter->rlLock),
|
||
|
kiIrql);
|
||
|
|
||
|
return TDI_BUFFER_OVERFLOW;
|
||
|
}
|
||
|
|
||
|
#if NDISBUFFERISMDL
|
||
|
|
||
|
nStatus = TdiCopyBufferToMdl(VENDOR_DESCRIPTION_STRING,
|
||
|
0,
|
||
|
strlen(VENDOR_DESCRIPTION_STRING),
|
||
|
(PMDL)pnbBuffer,
|
||
|
ulOffset,
|
||
|
&ulOffset);
|
||
|
|
||
|
#else
|
||
|
#error "Fix this"
|
||
|
#endif
|
||
|
|
||
|
*puiSize = IFE_FIXED_SIZE + VENDOR_DESCRIPTION_STRING_LEN;
|
||
|
|
||
|
RtReleaseSpinLock(&(pAdapter->rlLock),
|
||
|
kiIrql);
|
||
|
|
||
|
return TDI_SUCCESS;
|
||
|
|
||
|
}
|
||
|
|
||
|
INT
|
||
|
WanIpSetInfo(
|
||
|
IN PVOID pvContext,
|
||
|
IN TDIObjectID *pTdiObjId,
|
||
|
IN PVOID pvBuffer,
|
||
|
IN UINT uiSize
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
The set info routine. We dont do anything here
|
||
|
|
||
|
Locks:
|
||
|
|
||
|
None because we arent changing anything
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pvContext
|
||
|
pTdiObjId
|
||
|
pvBuffer
|
||
|
uiSize
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TDI_INVALID_REQUEST
|
||
|
TDI_INVALID_PARAMETER
|
||
|
TDI_BUFFER_TOO_SMALL
|
||
|
TDI_SUCCESS
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
INT iStatus;
|
||
|
IFEntry *pIFE;
|
||
|
DWORD dwEntity;
|
||
|
DWORD dwInstance;
|
||
|
PADAPTER pAdapter;
|
||
|
|
||
|
pIFE = (IFEntry *)pvBuffer;
|
||
|
dwEntity = pTdiObjId->toi_entity.tei_entity;
|
||
|
dwInstance = pTdiObjId->toi_entity.tei_instance;
|
||
|
pAdapter = (PADAPTER)pvContext;
|
||
|
|
||
|
//
|
||
|
// Might be able to handle this.
|
||
|
//
|
||
|
|
||
|
if((dwEntity isnot IF_ENTITY) or
|
||
|
(dwInstance isnot pAdapter->dwIfInstance))
|
||
|
{
|
||
|
return TDI_INVALID_REQUEST;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// It's for the I/F level, see if it's for the statistics.
|
||
|
//
|
||
|
|
||
|
if (pTdiObjId->toi_class isnot INFO_CLASS_PROTOCOL)
|
||
|
{
|
||
|
Trace(ADPT, INFO,
|
||
|
("WanSetInfo: toi_class is wrong 0x%x\n",
|
||
|
pTdiObjId->toi_class));
|
||
|
|
||
|
return TDI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
if (pTdiObjId->toi_id isnot IF_MIB_STATS_ID)
|
||
|
{
|
||
|
Trace(ADPT, INFO,
|
||
|
("WanSetInfo: toi_id 0x%x is not MIB_STATS\n",
|
||
|
pTdiObjId->toi_id));
|
||
|
|
||
|
return TDI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// It's for the stats. Make sure it's a valid size.
|
||
|
//
|
||
|
|
||
|
if(uiSize < IFE_FIXED_SIZE)
|
||
|
{
|
||
|
Trace(ADPT, ERROR,
|
||
|
("WanSetInfo: Buffer size %d too small\n",
|
||
|
uiSize));
|
||
|
|
||
|
return TDI_BUFFER_TOO_SMALL;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// We dont allow any sets on the adapters.
|
||
|
// The only sets are via interfaces and those need to be done
|
||
|
// using the IOCTLs. We could potentially allow sets on the UMODE_INTERFACE
|
||
|
// that the adapter is mapped too, but that would be just another way
|
||
|
// of achieving what the IOCTLS do
|
||
|
//
|
||
|
|
||
|
return TDI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
INT
|
||
|
WanIpGetEntityList(
|
||
|
IN PVOID pvContext,
|
||
|
IN TDIEntityID *pTdiEntityList,
|
||
|
IN PUINT puiCount
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Called by IP to assign us a TDI entity id
|
||
|
|
||
|
Locks:
|
||
|
|
||
|
Takes the adapter lock.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pvContext,
|
||
|
pTdiEntityList,
|
||
|
puiCount
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
PADAPTER pAdapter;
|
||
|
UINT uiEntityCount;
|
||
|
UINT uiMyIFBase;
|
||
|
UINT i;
|
||
|
TDIEntityID *pTdiIFEntity;
|
||
|
KIRQL kiIrql;
|
||
|
|
||
|
|
||
|
pAdapter = (PADAPTER)pvContext;
|
||
|
|
||
|
RtAcquireSpinLock(&(pAdapter->rlLock),
|
||
|
&kiIrql);
|
||
|
|
||
|
//
|
||
|
// Walk down the list, looking for existing IF entities, and
|
||
|
// adjust our base instance accordingly.
|
||
|
//
|
||
|
|
||
|
|
||
|
uiMyIFBase = 0;
|
||
|
pTdiIFEntity = NULL;
|
||
|
|
||
|
for(i = 0;
|
||
|
i < *puiCount;
|
||
|
i++, pTdiEntityList++)
|
||
|
{
|
||
|
if(pTdiEntityList->tei_entity is IF_ENTITY)
|
||
|
{
|
||
|
//
|
||
|
// if we are already on the list remember our entity item
|
||
|
// o/w find an instance # for us.
|
||
|
//
|
||
|
|
||
|
if((pTdiEntityList->tei_instance is pAdapter->dwIfInstance) and
|
||
|
(pTdiEntityList->tei_instance isnot INVALID_ENTITY_INSTANCE))
|
||
|
{
|
||
|
//
|
||
|
// Matched our instance
|
||
|
//
|
||
|
|
||
|
pTdiIFEntity = pTdiEntityList;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//
|
||
|
// Take the max of the two
|
||
|
//
|
||
|
|
||
|
uiMyIFBase = uiMyIFBase > (pTdiEntityList->tei_instance + 1)?
|
||
|
uiMyIFBase : (pTdiEntityList->tei_instance + 1);
|
||
|
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(pTdiIFEntity is NULL )
|
||
|
{
|
||
|
//
|
||
|
// we are not on the list.
|
||
|
// make sure we have the room for it.
|
||
|
//
|
||
|
|
||
|
if (*puiCount >= MAX_TDI_ENTITIES)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
pAdapter->dwIfInstance = uiMyIFBase;
|
||
|
|
||
|
//
|
||
|
// Now fill it in.
|
||
|
//
|
||
|
|
||
|
pTdiEntityList->tei_entity = IF_ENTITY;
|
||
|
pTdiEntityList->tei_instance = uiMyIFBase;
|
||
|
|
||
|
(*puiCount)++;
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if(pAdapter->byState is AS_REMOVING)
|
||
|
{
|
||
|
//
|
||
|
// If we are going away, remove our instance
|
||
|
//
|
||
|
|
||
|
pAdapter->dwIfInstance = INVALID_ENTITY_INSTANCE;
|
||
|
pTdiEntityList->tei_instance = INVALID_ENTITY_INSTANCE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
RtReleaseSpinLock(&(pAdapter->rlLock),
|
||
|
kiIrql);
|
||
|
|
||
|
return TRUE;
|
||
|
}
|