- Rewrite IOCTL_TCP_QUERY_INFORMATION_EX/IOCTL_TCP_SET_INFORMATION_EX handling

- Remove duplicate defines for the same IOCTL
 - Remove unneeded code
 - Fix a completely wrong implementation of ENTITY_TYPE_ID
 - Perform parameter checking
 - Remove several hacks in iphlpapi that worked around bugs in the previous implementation
 - We now support retrieving interface-specific routing tables and ARP tables

svn path=/trunk/; revision=43338
This commit is contained in:
Cameron Gutman 2009-10-09 02:40:38 +00:00
parent 8a1b2b51be
commit a3ab545150
10 changed files with 380 additions and 491 deletions

View file

@ -323,36 +323,8 @@ BOOL isLoopback( HANDLE tcpFile, TDIEntityID *loop_maybe ) {
loop_maybe, loop_maybe,
&entryInfo ); &entryInfo );
return NT_SUCCESS(status) && (!entryInfo.ent.if_type || return NT_SUCCESS(status) &&
entryInfo.ent.if_type == IFENT_SOFTWARE_LOOPBACK); (entryInfo.ent.if_type == IFENT_SOFTWARE_LOOPBACK);
}
NTSTATUS tdiGetEntityType( HANDLE tcpFile, TDIEntityID *ent, PULONG type ) {
TCP_REQUEST_QUERY_INFORMATION_EX req = TCP_REQUEST_QUERY_INFORMATION_INIT;
NTSTATUS status = STATUS_SUCCESS;
DWORD returnSize;
TRACE("TdiGetEntityType(tcpFile %x,entityId %x)\n",
(DWORD)tcpFile, ent->tei_instance);
req.ID.toi_class = INFO_CLASS_GENERIC;
req.ID.toi_type = INFO_TYPE_PROVIDER;
req.ID.toi_id = ENTITY_TYPE_ID;
req.ID.toi_entity.tei_entity = ent->tei_entity;
req.ID.toi_entity.tei_instance = ent->tei_instance;
status = DeviceIoControl( tcpFile,
IOCTL_TCP_QUERY_INFORMATION_EX,
&req,
sizeof(req),
type,
sizeof(*type),
&returnSize,
NULL );
TRACE("TdiGetEntityType() => %08x %08x\n", *type, status);
return (status ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
} }
BOOL hasArp( HANDLE tcpFile, TDIEntityID *arp_maybe ) { BOOL hasArp( HANDLE tcpFile, TDIEntityID *arp_maybe ) {
@ -374,9 +346,9 @@ BOOL hasArp( HANDLE tcpFile, TDIEntityID *arp_maybe ) {
sizeof(type), sizeof(type),
&returnSize, &returnSize,
NULL ); NULL );
if( !NT_SUCCESS(status) ) return FALSE; if( !NT_SUCCESS(status) ) return FALSE;
return type == AT_ENTITY;
return (type & AT_ARP);
} }
static NTSTATUS getInterfaceInfoSet( HANDLE tcpFile, static NTSTATUS getInterfaceInfoSet( HANDLE tcpFile,
@ -386,7 +358,6 @@ static NTSTATUS getInterfaceInfoSet( HANDLE tcpFile,
TDIEntityID *entIDSet = 0; TDIEntityID *entIDSet = 0;
NTSTATUS status = tdiGetEntityIDSet( tcpFile, &entIDSet, &numEntities ); NTSTATUS status = tdiGetEntityIDSet( tcpFile, &entIDSet, &numEntities );
IFInfo *infoSetInt = 0; IFInfo *infoSetInt = 0;
BOOL interfaceInfoComplete;
int curInterf = 0, i; int curInterf = 0, i;
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
@ -412,8 +383,7 @@ static NTSTATUS getInterfaceInfoSet( HANDLE tcpFile,
TDIEntityID ip_ent; TDIEntityID ip_ent;
int j; int j;
interfaceInfoComplete = FALSE; status = getNthIpEntity( tcpFile, curInterf, &ip_ent );
status = getNthIpEntity( tcpFile, 0, &ip_ent );
if( NT_SUCCESS(status) ) if( NT_SUCCESS(status) )
status = tdiGetIpAddrsForIpEntity status = tdiGetIpAddrsForIpEntity
( tcpFile, &ip_ent, &addrs, &numAddrs ); ( tcpFile, &ip_ent, &addrs, &numAddrs );

View file

@ -60,8 +60,6 @@
#define TCP_REQUEST_QUERY_INFORMATION_INIT { { { 0 } } } #define TCP_REQUEST_QUERY_INFORMATION_INIT { { { 0 } } }
#define TCP_REQUEST_SET_INFORMATION_INIT { { 0 } } #define TCP_REQUEST_SET_INFORMATION_INIT { { 0 } }
#define IP_MIB_ROUTETABLE_ENTRY_ID 0x101
// As in the mib from RFC 1213 // As in the mib from RFC 1213
typedef struct _IPRouteEntry { typedef struct _IPRouteEntry {

View file

@ -62,30 +62,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(iphlpapi);
#endif #endif
BOOL isIpEntity( HANDLE tcpFile, TDIEntityID *ent ) { BOOL isIpEntity( HANDLE tcpFile, TDIEntityID *ent ) {
DWORD entityType, returnedLen; return (ent->tei_entity == CL_NL_ENTITY ||
NTSTATUS status; ent->tei_entity == CO_NL_ENTITY);
TCP_REQUEST_QUERY_INFORMATION_EX req;
req.ID.toi_class = INFO_CLASS_GENERIC;
req.ID.toi_type = INFO_TYPE_PROVIDER;
req.ID.toi_id = ENTITY_TYPE_ID;
req.ID.toi_entity = *ent;
status =
DeviceIoControl
( tcpFile,
IOCTL_TCP_QUERY_INFORMATION_EX,
&req,
sizeof(req),
&entityType,
sizeof(entityType),
&returnedLen,
NULL );
TRACE("Ent: %04x:d -> %04x\n",
ent->tei_entity, ent->tei_instance, entityType );
return NT_SUCCESS(status) && entityType == CL_NL_IP;
} }
NTSTATUS getNthIpEntity( HANDLE tcpFile, DWORD index, TDIEntityID *ent ) { NTSTATUS getNthIpEntity( HANDLE tcpFile, DWORD index, TDIEntityID *ent ) {
@ -182,9 +160,9 @@ NTSTATUS tdiGetRoutesForIpEntity
status = tdiGetSetOfThings( tcpFile, status = tdiGetSetOfThings( tcpFile,
INFO_CLASS_PROTOCOL, INFO_CLASS_PROTOCOL,
INFO_TYPE_PROVIDER, INFO_TYPE_PROVIDER,
IP_MIB_ROUTETABLE_ENTRY_ID, IP_MIB_ARPTABLE_ENTRY_ID,
ent->tei_entity, CL_NL_ENTITY,
0, ent->tei_instance,
0, 0,
sizeof(IPRouteEntry), sizeof(IPRouteEntry),
(PVOID *)routes, (PVOID *)routes,
@ -204,8 +182,8 @@ NTSTATUS tdiGetIpAddrsForIpEntity
INFO_CLASS_PROTOCOL, INFO_CLASS_PROTOCOL,
INFO_TYPE_PROVIDER, INFO_TYPE_PROVIDER,
IP_MIB_ADDRTABLE_ENTRY_ID, IP_MIB_ADDRTABLE_ENTRY_ID,
ent->tei_entity, CL_NL_ENTITY,
0, ent->tei_instance,
0, 0,
sizeof(IPAddrEntry), sizeof(IPAddrEntry),
(PVOID *)addrs, (PVOID *)addrs,

View file

@ -69,8 +69,9 @@ DWORD createIpForwardEntry( PMIB_IPFORWARDROW pRoute ) {
if( NT_SUCCESS(status) ) { if( NT_SUCCESS(status) ) {
req.Req.ID.toi_class = INFO_CLASS_PROTOCOL; req.Req.ID.toi_class = INFO_CLASS_PROTOCOL;
req.Req.ID.toi_type = INFO_TYPE_PROVIDER; req.Req.ID.toi_type = INFO_TYPE_PROVIDER;
req.Req.ID.toi_id = IP_MIB_ROUTETABLE_ENTRY_ID; req.Req.ID.toi_id = IP_MIB_ARPTABLE_ENTRY_ID;
req.Req.ID.toi_entity = id; req.Req.ID.toi_entity.tei_instance = id.tei_instance;
req.Req.ID.toi_entity.tei_instance = CL_NL_ENTITY;
req.Req.BufferSize = sizeof(*rte); req.Req.BufferSize = sizeof(*rte);
rte = rte =
(IPRouteEntry *)&req.Req.Buffer[0]; (IPRouteEntry *)&req.Req.Buffer[0];
@ -133,8 +134,9 @@ DWORD deleteIpForwardEntry( PMIB_IPFORWARDROW pRoute ) {
if( NT_SUCCESS(status) ) { if( NT_SUCCESS(status) ) {
req.Req.ID.toi_class = INFO_CLASS_PROTOCOL; req.Req.ID.toi_class = INFO_CLASS_PROTOCOL;
req.Req.ID.toi_type = INFO_TYPE_PROVIDER; req.Req.ID.toi_type = INFO_TYPE_PROVIDER;
req.Req.ID.toi_id = IP_MIB_ROUTETABLE_ENTRY_ID; req.Req.ID.toi_id = IP_MIB_ARPTABLE_ENTRY_ID;
req.Req.ID.toi_entity = id; req.Req.ID.toi_entity.tei_instance = id.tei_instance;
req.Req.ID.toi_entity.tei_entity = CL_NL_ENTITY;
req.Req.BufferSize = sizeof(*rte); req.Req.BufferSize = sizeof(*rte);
rte = rte =
(IPRouteEntry *)&req.Req.Buffer[0]; (IPRouteEntry *)&req.Req.Buffer[0];

View file

@ -7,6 +7,8 @@
#ifndef __INFO_H #ifndef __INFO_H
#define __INFO_H #define __INFO_H
#include <tcpioctl.h>
#define MAX_PHYSADDR_LEN 8 #define MAX_PHYSADDR_LEN 8
#define MAX_IFDESCR_LEN 256 #define MAX_IFDESCR_LEN 256
@ -100,23 +102,6 @@ typedef struct IFENTRY {
ULONG DescrLen; ULONG DescrLen;
} IFENTRY, *PIFENTRY; } IFENTRY, *PIFENTRY;
#define IP_MIB_STATS_ID 1
#define IF_MIB_STATS_ID 1
#ifndef IP_MIB_ROUTETABLE_ENTRY_ID
#define IP_MIB_ROUTETABLE_ENTRY_ID 0x101
#endif
#ifndef IP_MIB_ADDRTABLE_ENTRY_ID
#define IP_MIB_ADDRTABLE_ENTRY_ID 0x102
#endif
#ifndef IP_MIB_ARPTABLE_ENTRY_ID
#define IP_MIB_ARPTABLE_ENTRY_ID 0x101
#endif
#ifndef MAX_PHYSADDR_SIZE
#define MAX_PHYSADDR_SIZE 8
#endif
/* Only UDP is supported */ /* Only UDP is supported */
#define TDI_SERVICE_FLAGS (TDI_SERVICE_CONNECTIONLESS_MODE | \ #define TDI_SERVICE_FLAGS (TDI_SERVICE_CONNECTIONLESS_MODE | \
TDI_SERVICE_BROADCAST_SUPPORTED) TDI_SERVICE_BROADCAST_SUPPORTED)
@ -157,54 +142,28 @@ TDI_STATUS InfoTdiSetInformationEx(
PVOID Buffer, PVOID Buffer,
UINT BufferSize); UINT BufferSize);
/* Network layer info functions */ TDI_STATUS InfoTdiQueryGetAddrTable(TDIEntityID ID,
TDI_STATUS InfoNetworkLayerTdiQueryEx( UINT InfoClass,
UINT InfoType,
UINT InfoId,
PVOID Context,
TDIEntityID *id,
PNDIS_BUFFER Buffer,
PUINT BufferSize );
TDI_STATUS InfoNetworkLayerTdiSetEx( UINT InfoClass,
UINT InfoType,
UINT InfoId,
PVOID Context,
TDIEntityID *id,
PCHAR Buffer,
UINT BufferSize );
TDI_STATUS InfoTransportLayerTdiQueryEx( UINT InfoClass,
UINT InfoType,
UINT InfoId,
PVOID Context,
TDIEntityID *id,
PNDIS_BUFFER Buffer,
PUINT BufferSize );
TDI_STATUS InfoTransportLayerTdiSetEx( UINT InfoClass,
UINT InfoType,
UINT InfoId,
PVOID Context,
TDIEntityID *id,
PCHAR Buffer,
UINT BufferSize );
TDI_STATUS InfoInterfaceTdiQueryEx( UINT InfoClass,
UINT InfoType,
UINT InfoId,
PVOID Context,
TDIEntityID *id,
PNDIS_BUFFER Buffer, PNDIS_BUFFER Buffer,
PUINT BufferSize ); PUINT BufferSize);
TDI_STATUS InfoInterfaceTdiSetEx( UINT InfoClass, TDI_STATUS InfoTdiQueryGetInterfaceMIB(TDIEntityID ID,
UINT InfoType, PIP_INTERFACE Interface,
UINT InfoId, PNDIS_BUFFER Buffer,
PVOID Context, PUINT BufferSize);
TDIEntityID *id,
PCHAR Buffer, TDI_STATUS InfoTdiQueryGetIPSnmpInfo( TDIEntityID ID,
UINT BufferSize ); PNDIS_BUFFER Buffer,
PUINT BufferSize );
TDI_STATUS InfoTdiQueryGetRouteTable( PNDIS_BUFFER Buffer,
PUINT BufferSize );
TDI_STATUS InfoTdiSetRoute(PIPROUTE_ENTRY Route);
TDI_STATUS InfoTdiQueryGetArptableMIB(TDIEntityID ID,
PIP_INTERFACE Interface,
PNDIS_BUFFER Buffer,
PUINT BufferSize);
/* Insert and remove interface entities */ /* Insert and remove interface entities */
VOID InsertTDIInterfaceEntity( PIP_INTERFACE Interface ); VOID InsertTDIInterfaceEntity( PIP_INTERFACE Interface );

View file

@ -149,29 +149,12 @@ struct sockaddr
char sa_data[14]; char sa_data[14];
}; };
typedef TDI_STATUS (*InfoRequest_f)( UINT InfoClass,
UINT InfoType,
UINT InfoId,
PVOID Context,
TDIEntityID *id,
PNDIS_BUFFER Buffer,
PUINT BufferSize );
typedef TDI_STATUS (*InfoSet_f)( UINT InfoClass,
UINT InfoType,
UINT InfoId,
PVOID Context,
TDIEntityID *id,
PCHAR Buffer,
UINT BufferSize );
/* Sufficient information to manage the entity list */ /* Sufficient information to manage the entity list */
typedef struct { typedef struct {
UINT tei_entity; UINT tei_entity;
UINT tei_instance; UINT tei_instance;
PVOID context; PVOID context;
InfoRequest_f info_req; UINT flags;
InfoSet_f info_set;
} TDIEntityInfo; } TDIEntityInfo;
#ifndef htons #ifndef htons

View file

@ -10,21 +10,26 @@
#include "precomp.h" #include "precomp.h"
TDI_STATUS InfoTdiQueryGetInterfaceMIB(TDIEntityID *ID, TDI_STATUS InfoTdiQueryGetInterfaceMIB(TDIEntityID ID,
PIP_INTERFACE Interface, PIP_INTERFACE Interface,
PNDIS_BUFFER Buffer, PNDIS_BUFFER Buffer,
PUINT BufferSize) { PUINT BufferSize) {
TDI_STATUS Status = TDI_INVALID_REQUEST; TDI_STATUS Status = TDI_INVALID_REQUEST;
PIFENTRY OutData; PIFENTRY OutData;
PLAN_ADAPTER IF = (PLAN_ADAPTER)Interface->Context; PLAN_ADAPTER IF;
PCHAR IFDescr; PCHAR IFDescr;
ULONG Size; ULONG Size;
UINT DescrLenMax = MAX_IFDESCR_LEN - 1; UINT DescrLenMax = MAX_IFDESCR_LEN - 1;
NDIS_STATUS NdisStatus; NDIS_STATUS NdisStatus;
if (!Interface)
return TDI_INVALID_PARAMETER;
IF = (PLAN_ADAPTER)Interface->Context;
TI_DbgPrint(DEBUG_INFO, TI_DbgPrint(DEBUG_INFO,
("Getting IFEntry MIB (IF %08x LA %08x) (%04x:%d)\n", ("Getting IFEntry MIB (IF %08x LA %08x) (%04x:%d)\n",
Interface, IF, ID->tei_entity, ID->tei_instance)); Interface, IF, ID.tei_entity, ID.tei_instance));
OutData = OutData =
(PIFENTRY)exAllocatePool( NonPagedPool, (PIFENTRY)exAllocatePool( NonPagedPool,
@ -91,7 +96,7 @@ TDI_STATUS InfoTdiQueryGetInterfaceMIB(TDIEntityID *ID,
Size = IFDescr - (PCHAR)OutData + 1; Size = IFDescr - (PCHAR)OutData + 1;
TI_DbgPrint(DEBUG_INFO, ("Finished IFEntry MIB (%04x:%d) size %d\n", TI_DbgPrint(DEBUG_INFO, ("Finished IFEntry MIB (%04x:%d) size %d\n",
ID->tei_entity, ID->tei_instance, Size)); ID.tei_entity, ID.tei_instance, Size));
Status = InfoCopyOut( (PCHAR)OutData, Size, Buffer, BufferSize ); Status = InfoCopyOut( (PCHAR)OutData, Size, Buffer, BufferSize );
exFreePool( OutData ); exFreePool( OutData );
@ -101,7 +106,7 @@ TDI_STATUS InfoTdiQueryGetInterfaceMIB(TDIEntityID *ID,
return Status; return Status;
} }
TDI_STATUS InfoTdiQueryGetArptableMIB(TDIEntityID *ID, TDI_STATUS InfoTdiQueryGetArptableMIB(TDIEntityID ID,
PIP_INTERFACE Interface, PIP_INTERFACE Interface,
PNDIS_BUFFER Buffer, PNDIS_BUFFER Buffer,
PUINT BufferSize) { PUINT BufferSize) {
@ -122,58 +127,106 @@ TDI_STATUS InfoTdiQueryGetArptableMIB(TDIEntityID *ID,
return Status; return Status;
} }
TDI_STATUS InfoTdiQueryGetArpCapability(TDIEntityID *ID, VOID InsertTDIInterfaceEntity( PIP_INTERFACE Interface ) {
PIP_INTERFACE Interface, KIRQL OldIrql;
PNDIS_BUFFER Buffer, UINT IFCount = 0, CLNLCount = 0, CLTLCount = 0, COTLCount = 0, ATCount = 0, ERCount = 0, i;
PUINT BufferSize) {
NTSTATUS Status;
ULONG Capability = 0x280;
TI_DbgPrint(MID_TRACE,("Copying out %d bytes (AT_ENTITY capability)\n", TI_DbgPrint(DEBUG_INFO,
sizeof(Capability))); ("Inserting interface %08x (%d entities already)\n",
Status = InfoCopyOut Interface, EntityCount));
( (PVOID)&Capability, sizeof(Capability), Buffer, BufferSize );
return Status; TcpipAcquireSpinLock( &EntityListLock, &OldIrql );
/* Count IP Entities */
for( i = 0; i < EntityCount; i++ )
switch( EntityList[i].tei_entity )
{
case IF_ENTITY:
IFCount++;
break;
case CL_NL_ENTITY:
CLNLCount++;
break;
case CL_TL_ENTITY:
CLTLCount++;
break;
case CO_TL_ENTITY:
COTLCount++;
break;
case AT_ENTITY:
ATCount++;
break;
case ER_ENTITY:
ERCount++;
break;
default:
break;
}
EntityList[EntityCount].tei_entity = IF_ENTITY;
EntityList[EntityCount].tei_instance = IFCount;
EntityList[EntityCount].context = Interface;
EntityList[EntityCount].flags = IF_MIB;
EntityCount++;
EntityList[EntityCount].tei_entity = CL_NL_ENTITY;
EntityList[EntityCount].tei_instance = CLNLCount;
EntityList[EntityCount].context = Interface;
EntityList[EntityCount].flags = CL_NL_IP;
EntityCount++;
EntityList[EntityCount].tei_entity = CL_TL_ENTITY;
EntityList[EntityCount].tei_instance = CLTLCount;
EntityList[EntityCount].context = Interface;
EntityList[EntityCount].flags = CL_TL_UDP;
EntityCount++;
EntityList[EntityCount].tei_entity = CO_TL_ENTITY;
EntityList[EntityCount].tei_instance = COTLCount;
EntityList[EntityCount].context = Interface;
EntityList[EntityCount].flags = CO_TL_TCP;
EntityCount++;
EntityList[EntityCount].tei_entity = ER_ENTITY;
EntityList[EntityCount].tei_instance = ERCount;
EntityList[EntityCount].context = Interface;
EntityList[EntityCount].flags = ER_ICMP;
EntityCount++;
EntityList[EntityCount].tei_entity = AT_ENTITY;
EntityList[EntityCount].tei_instance = ATCount;
EntityList[EntityCount].context = Interface;
EntityList[EntityCount].flags = AT_ARP;
EntityCount++;
TcpipReleaseSpinLock( &EntityListLock, OldIrql );
} }
TDI_STATUS InfoInterfaceTdiQueryEx( UINT InfoClass, VOID RemoveTDIInterfaceEntity( PIP_INTERFACE Interface ) {
UINT InfoType, KIRQL OldIrql;
UINT InfoId, UINT i;
PVOID Context,
TDIEntityID *id, TI_DbgPrint(DEBUG_INFO,("Removing TDI entry 0x%x\n", Interface));
PNDIS_BUFFER Buffer,
PUINT BufferSize ) { TcpipAcquireSpinLock( &EntityListLock, &OldIrql );
if( InfoClass == INFO_CLASS_GENERIC &&
InfoType == INFO_TYPE_PROVIDER && /* Remove entities that have this interface as context
InfoId == ENTITY_TYPE_ID && * In the future, this might include AT_ENTITY types, too
id->tei_entity == AT_ENTITY ) { */
return InfoTdiQueryGetArpCapability( id, Context, Buffer, BufferSize ); for( i = 0; i < EntityCount; i++ ) {
} else if( InfoClass == INFO_CLASS_PROTOCOL && TI_DbgPrint(DEBUG_INFO,("--> examining TDI entry 0x%x\n", EntityList[i].context));
InfoType == INFO_TYPE_PROVIDER && if( EntityList[i].context == Interface ) {
InfoId == IF_MIB_STATS_ID ) { if( i != EntityCount-1 ) {
return InfoTdiQueryGetInterfaceMIB( id, Context, Buffer, BufferSize ); memcpy( &EntityList[i],
} else if( InfoClass == INFO_CLASS_GENERIC && &EntityList[--EntityCount],
InfoType == INFO_TYPE_PROVIDER && sizeof(EntityList[i]) );
InfoId == ENTITY_TYPE_ID ) { } else {
ULONG Temp = IF_MIB; EntityCount--;
return InfoCopyOut( (PCHAR)&Temp, sizeof(Temp), Buffer, BufferSize ); }
} else if( InfoClass == INFO_CLASS_PROTOCOL && }
InfoType == INFO_TYPE_PROVIDER && }
InfoId == IP_MIB_ARPTABLE_ENTRY_ID ) {
return InfoTdiQueryGetArptableMIB( id, Context, Buffer, BufferSize ); TcpipReleaseSpinLock( &EntityListLock, OldIrql );
} else
return TDI_INVALID_REQUEST;
} }
TDI_STATUS InfoInterfaceTdiSetEx( UINT InfoClass,
UINT InfoType,
UINT InfoId,
PVOID Context,
TDIEntityID *id,
PCHAR Buffer,
UINT BufferSize ) {
TI_DbgPrint(DEBUG_INFO, ("Got Request: Class %x Type %x Id %x, EntityID %x:%x\n",
InfoClass, InfoId, id->tei_entity, id->tei_instance));
return TDI_INVALID_REQUEST;
}

View file

@ -12,6 +12,35 @@
#include <debug.h> #include <debug.h>
#include <route.h> #include <route.h>
PVOID GetContext(TDIEntityID ID)
{
UINT i;
KIRQL OldIrql;
PVOID Context;
TcpipAcquireSpinLock(&EntityListLock, &OldIrql);
for (i = 0; i < EntityCount; i++)
{
if (EntityList[i].tei_entity == ID.tei_entity &&
EntityList[i].tei_instance == ID.tei_instance)
break;
}
if (i == EntityCount)
{
TcpipReleaseSpinLock(&EntityListLock, OldIrql);
DbgPrint("WARNING: Unable to get context for %d %d\n", ID.tei_entity, ID.tei_instance);
return NULL;
}
Context = EntityList[i].context;
TcpipReleaseSpinLock(&EntityListLock, OldIrql);
return Context;
}
TDI_STATUS InfoCopyOut( PCHAR DataOut, UINT SizeOut, TDI_STATUS InfoCopyOut( PCHAR DataOut, UINT SizeOut,
PNDIS_BUFFER ClientBuf, PUINT ClientBufSize ) { PNDIS_BUFFER ClientBuf, PUINT ClientBufSize ) {
UINT RememberedCBSize = *ClientBufSize; UINT RememberedCBSize = *ClientBufSize;
@ -27,60 +56,38 @@ TDI_STATUS InfoCopyOut( PCHAR DataOut, UINT SizeOut,
} }
} }
VOID InsertTDIInterfaceEntity( PIP_INTERFACE Interface ) { TDI_STATUS InfoTdiQueryEntityType(TDIEntityID ID,
PNDIS_BUFFER Buffer,
PUINT BufferSize)
{
KIRQL OldIrql; KIRQL OldIrql;
UINT Count = 0, i; UINT i, Flags = 0;
TI_DbgPrint(DEBUG_INFO, TcpipAcquireSpinLock(&EntityListLock, &OldIrql);
("Inserting interface %08x (%d entities already)\n",
Interface, EntityCount));
TcpipAcquireSpinLock( &EntityListLock, &OldIrql ); for (i = 0; i < EntityCount; i++)
{
/* Count IP Entities */ if (EntityList[i].tei_entity == ID.tei_entity &&
for( i = 0; i < EntityCount; i++ ) EntityList[i].tei_instance == ID.tei_instance)
if( EntityList[i].tei_entity == IF_ENTITY ) { break;
Count++;
TI_DbgPrint(DEBUG_INFO, ("Entity %d is an IF. Found %d\n",
i, Count));
}
EntityList[EntityCount].tei_entity = IF_ENTITY;
EntityList[EntityCount].tei_instance = Count;
EntityList[EntityCount].context = Interface;
EntityList[EntityCount].info_req = InfoInterfaceTdiQueryEx;
EntityList[EntityCount].info_set = InfoInterfaceTdiSetEx;
EntityCount++;
TcpipReleaseSpinLock( &EntityListLock, OldIrql );
}
VOID RemoveTDIInterfaceEntity( PIP_INTERFACE Interface ) {
KIRQL OldIrql;
UINT i;
TI_DbgPrint(DEBUG_INFO,("Removing TDI entry 0x%x\n", Interface));
TcpipAcquireSpinLock( &EntityListLock, &OldIrql );
/* Remove entities that have this interface as context
* In the future, this might include AT_ENTITY types, too
*/
for( i = 0; i < EntityCount; i++ ) {
TI_DbgPrint(DEBUG_INFO,("--> examining TDI entry 0x%x\n", EntityList[i].context));
if( EntityList[i].context == Interface ) {
if( i != EntityCount-1 ) {
memcpy( &EntityList[i],
&EntityList[--EntityCount],
sizeof(EntityList[i]) );
} else {
EntityCount--;
}
}
} }
TcpipReleaseSpinLock( &EntityListLock, OldIrql ); if (i == EntityCount)
{
TcpipReleaseSpinLock(&EntityListLock, OldIrql);
return TDI_INVALID_PARAMETER;
}
Flags = EntityList[i].flags;
InfoCopyOut((PCHAR)&Flags,
sizeof(ULONG),
Buffer,
BufferSize);
TcpipReleaseSpinLock(&EntityListLock, OldIrql);
return TDI_SUCCESS;
} }
TDI_STATUS InfoTdiQueryListEntities(PNDIS_BUFFER Buffer, TDI_STATUS InfoTdiQueryListEntities(PNDIS_BUFFER Buffer,
@ -139,12 +146,7 @@ TDI_STATUS InfoTdiQueryInformationEx(
* Status of operation * Status of operation
*/ */
{ {
KIRQL OldIrql; PVOID EntityListContext;
UINT i;
PVOID context = NULL;
NTSTATUS Status = TDI_INVALID_PARAMETER;
BOOLEAN FoundEntity = FALSE;
InfoRequest_f InfoRequest = NULL;
TI_DbgPrint(DEBUG_INFO, TI_DbgPrint(DEBUG_INFO,
("InfoEx Req: %x %x %x!%04x:%d\n", ("InfoEx Req: %x %x %x!%04x:%d\n",
@ -154,79 +156,83 @@ TDI_STATUS InfoTdiQueryInformationEx(
ID->toi_entity.tei_entity, ID->toi_entity.tei_entity,
ID->toi_entity.tei_instance)); ID->toi_entity.tei_instance));
/* Check wether it is a query for a list of entities */ switch (ID->toi_class)
if (ID->toi_entity.tei_entity == GENERIC_ENTITY)
{ {
if ((ID->toi_class != INFO_CLASS_GENERIC) || case INFO_CLASS_GENERIC:
(ID->toi_type != INFO_TYPE_PROVIDER) || switch (ID->toi_id)
(ID->toi_id != ENTITY_LIST_ID)) { {
TI_DbgPrint(DEBUG_INFO,("Invalid parameter\n")); case ENTITY_LIST_ID:
Status = TDI_INVALID_PARAMETER; if (ID->toi_type != INFO_TYPE_PROVIDER)
} else return TDI_INVALID_PARAMETER;
Status = InfoTdiQueryListEntities(Buffer, BufferSize);
} else if (ID->toi_entity.tei_entity == AT_ENTITY) {
TcpipAcquireSpinLock( &EntityListLock, &OldIrql );
for( i = 0; i < EntityCount; i++ ) { return InfoTdiQueryListEntities(Buffer, BufferSize);
if( EntityList[i].tei_entity == IF_ENTITY &&
EntityList[i].tei_instance == ID->toi_entity.tei_instance ) {
InfoRequest = EntityList[i].info_req;
context = EntityList[i].context;
FoundEntity = TRUE;
break;
}
}
TcpipReleaseSpinLock( &EntityListLock, OldIrql ); case ENTITY_TYPE_ID:
if (ID->toi_type != INFO_TYPE_PROVIDER)
return TDI_INVALID_PARAMETER;
if( FoundEntity ) { return InfoTdiQueryEntityType(ID->toi_entity, Buffer, BufferSize);
TI_DbgPrint(DEBUG_INFO,
("Calling AT Entity %d (%04x:%d) InfoEx (%x,%x,%x)\n",
i, ID->toi_entity.tei_entity,
ID->toi_entity.tei_instance,
ID->toi_class, ID->toi_type, ID->toi_id));
Status = InfoRequest( ID->toi_class,
ID->toi_type,
ID->toi_id,
context,
&ID->toi_entity,
Buffer,
BufferSize );
}
} else {
TcpipAcquireSpinLock( &EntityListLock, &OldIrql );
for( i = 0; i < EntityCount; i++ ) { default:
if( EntityList[i].tei_entity == ID->toi_entity.tei_entity && return TDI_INVALID_REQUEST;
EntityList[i].tei_instance == ID->toi_entity.tei_instance ) { }
InfoRequest = EntityList[i].info_req;
context = EntityList[i].context;
FoundEntity = TRUE;
break;
}
}
TcpipReleaseSpinLock( &EntityListLock, OldIrql ); case INFO_CLASS_PROTOCOL:
switch (ID->toi_id)
{
case IF_MIB_STATS_ID:
if (ID->toi_entity.tei_entity == IF_ENTITY)
if ((EntityListContext = GetContext(ID->toi_entity)))
return InfoTdiQueryGetInterfaceMIB(ID->toi_entity, EntityListContext, Buffer, BufferSize);
else
return TDI_INVALID_PARAMETER;
else if (ID->toi_entity.tei_entity == CL_NL_ENTITY ||
ID->toi_entity.tei_entity == CO_NL_ENTITY)
return InfoTdiQueryGetIPSnmpInfo(ID->toi_entity, Buffer, BufferSize);
else
return TDI_INVALID_PARAMETER;
if( FoundEntity ) { case IP_MIB_ADDRTABLE_ENTRY_ID:
TI_DbgPrint(DEBUG_INFO, if (ID->toi_entity.tei_entity != CL_NL_ENTITY &&
("Calling Entity %d (%04x:%d) InfoEx (%x,%x,%x)\n", ID->toi_entity.tei_entity != CO_NL_ENTITY)
i, ID->toi_entity.tei_entity, return TDI_INVALID_PARAMETER;
ID->toi_entity.tei_instance,
ID->toi_class, ID->toi_type, ID->toi_id)); if (ID->toi_type != INFO_TYPE_PROVIDER)
Status = InfoRequest( ID->toi_class, return TDI_INVALID_PARAMETER;
ID->toi_type,
ID->toi_id, return InfoTdiQueryGetAddrTable(ID->toi_entity, Buffer, BufferSize);
context,
&ID->toi_entity, case IP_MIB_ARPTABLE_ENTRY_ID:
Buffer, if (ID->toi_type != INFO_TYPE_PROVIDER)
BufferSize ); return TDI_INVALID_PARAMETER;
}
if (ID->toi_entity.tei_entity == AT_ENTITY)
if ((EntityListContext = GetContext(ID->toi_entity)))
return InfoTdiQueryGetArptableMIB(ID->toi_entity, EntityListContext,
Buffer, BufferSize);
else
return TDI_INVALID_PARAMETER;
else if (ID->toi_entity.tei_entity == CO_NL_ENTITY ||
ID->toi_entity.tei_entity == CL_NL_ENTITY)
return InfoTdiQueryGetRouteTable(Buffer, BufferSize);
else
return TDI_INVALID_PARAMETER;
#if 0
case IP_INTFC_INFO_ID:
if (ID->toi_type != INFO_TYPE_PROVIDER)
return TDI_INVALID_PARAMETER;
return InfoTdiQueryGetIFInfo(Context, Buffer, BufferSize);
#endif
default:
return TDI_INVALID_REQUEST;
}
default:
return TDI_INVALID_REQUEST;
} }
TI_DbgPrint(DEBUG_INFO,("Status: %08x\n", Status));
return Status;
} }
TDI_STATUS InfoTdiSetInformationEx TDI_STATUS InfoTdiSetInformationEx
@ -245,24 +251,26 @@ TDI_STATUS InfoTdiSetInformationEx
* Status of operation * Status of operation
*/ */
{ {
switch( ID->toi_class ) { switch (ID->toi_class)
case INFO_CLASS_PROTOCOL: {
switch( ID->toi_type ) { case INFO_CLASS_PROTOCOL:
case INFO_TYPE_PROVIDER: switch (ID->toi_id)
switch( ID->toi_id ) { {
case IP_MIB_ROUTETABLE_ENTRY_ID: case IP_MIB_ARPTABLE_ENTRY_ID:
return InfoNetworkLayerTdiSetEx if (ID->toi_id != INFO_TYPE_PROVIDER)
( ID->toi_class, return TDI_INVALID_PARAMETER;
ID->toi_type,
ID->toi_id,
NULL,
&ID->toi_entity,
Buffer,
BufferSize );
}
}
break;
}
return TDI_INVALID_PARAMETER; if (ID->toi_entity.tei_entity != CL_NL_ENTITY &&
ID->toi_entity.tei_entity != CO_NL_ENTITY)
return TDI_INVALID_PARAMETER;
return InfoTdiSetRoute((PIPROUTE_ENTRY)Buffer);
default:
return TDI_INVALID_REQUEST;
}
default:
return TDI_INVALID_REQUEST;
}
} }

View file

@ -699,17 +699,7 @@ DriverEntry(
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
} }
EntityList[0].tei_entity = CL_NL_ENTITY; EntityCount = 0;
EntityList[0].tei_instance = 0;
EntityList[0].context = 0;
EntityList[0].info_req = InfoNetworkLayerTdiQueryEx;
EntityList[0].info_set = InfoNetworkLayerTdiSetEx;
EntityList[1].tei_entity = CL_TL_ENTITY;
EntityList[1].tei_instance = 0;
EntityList[1].context = 0;
EntityList[1].info_req = InfoTransportLayerTdiQueryEx;
EntityList[1].info_set = InfoTransportLayerTdiSetEx;
EntityCount = 2;
EntityMax = MAX_TDI_ENTITIES; EntityMax = MAX_TDI_ENTITIES;
/* Allocate NDIS packet descriptors */ /* Allocate NDIS packet descriptors */

View file

@ -13,57 +13,7 @@
#define IP_ROUTE_TYPE_ADD 3 #define IP_ROUTE_TYPE_ADD 3
#define IP_ROUTE_TYPE_DEL 2 #define IP_ROUTE_TYPE_DEL 2
TDI_STATUS InfoTdiQueryGetAddrTable( PNDIS_BUFFER Buffer,
PUINT BufferSize ) {
TDI_STATUS Status = TDI_INVALID_REQUEST;
KIRQL OldIrql;
UINT Count = 0;
UINT IfCount = CountInterfaces();
PIPADDR_ENTRY IpAddress =
exAllocatePool( NonPagedPool, sizeof( IPADDR_ENTRY ) * IfCount );
PIPADDR_ENTRY IpCurrent = IpAddress;
IF_LIST_ITER(CurrentIF);
TI_DbgPrint(DEBUG_INFO, ("Called.\n"));
if (!IpAddress)
return TDI_NO_RESOURCES;
TcpipAcquireSpinLock(&InterfaceListLock, &OldIrql);
ForEachInterface(CurrentIF) {
IpCurrent->Index = CurrentIF->Index;
IpCurrent->Addr = 0;
IpCurrent->BcastAddr = 0;
IpCurrent->Mask = 0;
/* Locate the diffrent addresses and put them the right place */
GetInterfaceIPv4Address( CurrentIF,
ADE_UNICAST,
&IpCurrent->Addr );
GetInterfaceIPv4Address( CurrentIF,
ADE_BROADCAST,
&IpCurrent->BcastAddr );
GetInterfaceIPv4Address( CurrentIF,
ADE_ADDRMASK,
&IpCurrent->Mask );
IpCurrent++;
Count++;
} EndFor(CurrentIF);
ASSERT( Count == IfCount );
TcpipReleaseSpinLock(&InterfaceListLock, OldIrql);
Status = InfoCopyOut( (PCHAR)IpAddress, sizeof(*IpAddress) * IfCount,
Buffer, BufferSize );
exFreePool( IpAddress );
TI_DbgPrint(DEBUG_INFO, ("Returning %08x\n", Status));
return Status;
}
/* Get IPRouteEntry s for each of the routes in the system */ /* Get IPRouteEntry s for each of the routes in the system */
TDI_STATUS InfoTdiQueryGetRouteTable( PNDIS_BUFFER Buffer, PUINT BufferSize ) { TDI_STATUS InfoTdiQueryGetRouteTable( PNDIS_BUFFER Buffer, PUINT BufferSize ) {
@ -138,7 +88,65 @@ TDI_STATUS InfoTdiQueryGetRouteTable( PNDIS_BUFFER Buffer, PUINT BufferSize ) {
return Status; return Status;
} }
TDI_STATUS InfoTdiQueryGetIPSnmpInfo( PNDIS_BUFFER Buffer, TDI_STATUS InfoTdiQueryGetAddrTable(TDIEntityID ID,
PNDIS_BUFFER Buffer,
PUINT BufferSize)
{
KIRQL OldIrql;
PIPADDR_ENTRY IPEntry;
PIP_INTERFACE CurrentIF;
UINT i;
TI_DbgPrint(DEBUG_INFO, ("Called.\n"));
TcpipAcquireSpinLock(&EntityListLock, &OldIrql);
for (i = 0; i < EntityCount; i++)
{
if (EntityList[i].tei_entity == ID.tei_entity &&
EntityList[i].tei_instance == ID.tei_instance)
break;
}
if (i == EntityCount)
{
TcpipReleaseSpinLock(&EntityListLock, OldIrql);
return TDI_INVALID_PARAMETER;
}
IPEntry = exAllocatePool(NonPagedPool, sizeof(IPADDR_ENTRY));
if (!IPEntry)
{
TcpipReleaseSpinLock(&EntityListLock, OldIrql);
return TDI_NO_RESOURCES;
}
CurrentIF = EntityList[i].context;
IPEntry->Index = CurrentIF->Index;
GetInterfaceIPv4Address(CurrentIF,
ADE_UNICAST,
&IPEntry->Addr);
GetInterfaceIPv4Address(CurrentIF,
ADE_ADDRMASK,
&IPEntry->Mask);
GetInterfaceIPv4Address(CurrentIF,
ADE_BROADCAST,
&IPEntry->BcastAddr);
TcpipReleaseSpinLock(&EntityListLock, OldIrql);
InfoCopyOut((PCHAR)IPEntry, sizeof(IPADDR_ENTRY),
Buffer, BufferSize);
exFreePool(IPEntry);
return TDI_SUCCESS;
}
TDI_STATUS InfoTdiQueryGetIPSnmpInfo( TDIEntityID ID,
PNDIS_BUFFER Buffer,
PUINT BufferSize ) { PUINT BufferSize ) {
IPSNMP_INFO SnmpInfo; IPSNMP_INFO SnmpInfo;
UINT IfCount = CountInterfaces(); UINT IfCount = CountInterfaces();
@ -161,95 +169,35 @@ TDI_STATUS InfoTdiQueryGetIPSnmpInfo( PNDIS_BUFFER Buffer,
return Status; return Status;
} }
TDI_STATUS InfoNetworkLayerTdiQueryEx( UINT InfoClass, TDI_STATUS InfoTdiSetRoute(PIPROUTE_ENTRY Route)
UINT InfoType, {
UINT InfoId, IP_ADDRESS Address, Netmask, Router;
PVOID Context,
TDIEntityID *id,
PNDIS_BUFFER Buffer,
PUINT BufferSize ) {
TDI_STATUS Status = TDI_INVALID_REQUEST;
TI_DbgPrint(DEBUG_INFO, ("Called.\n"));
switch( InfoClass ) {
case INFO_CLASS_GENERIC:
if( InfoType == INFO_TYPE_PROVIDER && InfoId == ENTITY_TYPE_ID ) {
ULONG Return = CL_NL_IP;
Status = InfoCopyOut( (PCHAR)&Return, sizeof(Return),
Buffer, BufferSize );
}
break;
case INFO_CLASS_PROTOCOL:
switch( InfoType ) {
case INFO_TYPE_PROVIDER:
switch( InfoId ) {
case IP_MIB_ADDRTABLE_ENTRY_ID:
Status = InfoTdiQueryGetAddrTable( Buffer, BufferSize );
break;
case IP_MIB_ROUTETABLE_ENTRY_ID:
Status = InfoTdiQueryGetRouteTable( Buffer, BufferSize );
break;
case IP_MIB_STATS_ID:
Status = InfoTdiQueryGetIPSnmpInfo( Buffer, BufferSize );
break;
}
break;
}
}
TI_DbgPrint(DEBUG_INFO, ("Returning %08x\n", Status));
return Status;
}
TDI_STATUS InfoNetworkLayerTdiSetEx( UINT InfoClass,
UINT InfoType,
UINT InfoId,
PVOID Context,
TDIEntityID *id,
PCHAR Buffer,
UINT BufferSize ) {
NTSTATUS Status = TDI_INVALID_REQUEST;
IP_ADDRESS Address;
IP_ADDRESS Netmask;
IP_ADDRESS Router;
PNEIGHBOR_CACHE_ENTRY NCE; PNEIGHBOR_CACHE_ENTRY NCE;
TI_DbgPrint(DEBUG_INFO,("Called\n")); AddrInitIPv4( &Address, Route->Dest );
AddrInitIPv4( &Netmask, Route->Mask );
AddrInitIPv4( &Router, Route->Gw );
//OskitDumpBuffer( (OSK_PCHAR)Buffer, BufferSize ); if( Route->Type == IP_ROUTE_TYPE_ADD ) { /* Add the route */
TI_DbgPrint(DEBUG_INFO,("Adding route (%s)\n", A2S(&Address)));
/* Find the existing route this belongs to */
NCE = RouterGetRoute( &Router );
if (!NCE) return TDI_INVALID_PARAMETER;
if( InfoClass == INFO_CLASS_PROTOCOL && /* Really add the route */
InfoType == INFO_TYPE_PROVIDER && if (!RouterCreateRoute( &Address, &Netmask, &Router,
InfoId == IP_MIB_ROUTETABLE_ENTRY_ID && NCE->Interface, Route->Metric1))
id->tei_entity == CL_NL_ENTITY ) { /* Add or delete a route */ return TDI_NO_RESOURCES;
PIPROUTE_ENTRY Route = (PIPROUTE_ENTRY)Buffer;
AddrInitIPv4( &Address, Route->Dest );
AddrInitIPv4( &Netmask, Route->Mask );
AddrInitIPv4( &Router, Route->Gw );
if( Route->Type == IP_ROUTE_TYPE_ADD ) { /* Add the route */ return TDI_SUCCESS;
TI_DbgPrint(DEBUG_INFO,("Adding route (%s)\n", A2S(&Address))); } else if( Route->Type == IP_ROUTE_TYPE_DEL ) {
/* Find the existing route this belongs to */ TI_DbgPrint(DEBUG_INFO,("Removing route (%s)\n", A2S(&Address)));
NCE = RouterGetRoute( &Router ); if (NT_SUCCESS(RouterRemoveRoute( &Address, &Router )))
/* Really add the route */ return TDI_SUCCESS;
if( NCE && else
RouterCreateRoute( &Address, &Netmask, &Router, return TDI_INVALID_PARAMETER;
NCE->Interface, Route->Metric1 ) ) }
Status = STATUS_SUCCESS;
else
Status = STATUS_UNSUCCESSFUL;
} else if( Route->Type == IP_ROUTE_TYPE_DEL ) {
TI_DbgPrint(DEBUG_INFO,("Removing route (%s)\n", A2S(&Address)));
Status = RouterRemoveRoute( &Address, &Router );
} else Status = TDI_INVALID_REQUEST;
}
TI_DbgPrint(DEBUG_INFO,("Returning %x\n", Status)); return TDI_INVALID_REQUEST;
return Status;
} }