mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-08-31 12:23:31 +00:00
ARP query support.
Thanks to WaxDragon for encouragement and debugging. svn path=/branches/ros-branch-0_3_1/; revision=24226
This commit is contained in:
@@ -40,7 +40,7 @@
|
||||
#include "ifenum.h"
|
||||
#include <assert.h>
|
||||
|
||||
#define NDEBUG
|
||||
//#define NDEBUG
|
||||
#include "debug.h"
|
||||
|
||||
/* Globals */
|
||||
@@ -124,6 +124,7 @@ NTSTATUS tdiGetSetOfThings( HANDLE tcpFile,
|
||||
DWORD toiType,
|
||||
DWORD toiId,
|
||||
DWORD teiEntity,
|
||||
DWORD teiInstance,
|
||||
DWORD fixedPart,
|
||||
DWORD entrySize,
|
||||
PVOID *tdiEntitySet,
|
||||
@@ -148,6 +149,7 @@ NTSTATUS tdiGetSetOfThings( HANDLE tcpFile,
|
||||
req.ID.toi_type = toiType;
|
||||
req.ID.toi_id = toiId;
|
||||
req.ID.toi_entity.tei_entity = teiEntity;
|
||||
req.ID.toi_entity.tei_instance = teiInstance;
|
||||
|
||||
/* There's a subtle problem here...
|
||||
* If an interface is added at this exact instant, (as if by a PCMCIA
|
||||
@@ -168,7 +170,7 @@ NTSTATUS tdiGetSetOfThings( HANDLE tcpFile,
|
||||
&allocationSizeForEntityArray,
|
||||
NULL );
|
||||
|
||||
if(!status)
|
||||
if(!NT_SUCCESS(status))
|
||||
{
|
||||
DPRINT("IOCTL Failed\n");
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
@@ -285,6 +287,7 @@ NTSTATUS tdiGetEntityIDSet( HANDLE tcpFile,
|
||||
INFO_TYPE_PROVIDER,
|
||||
ENTITY_LIST_ID,
|
||||
GENERIC_ENTITY,
|
||||
0,
|
||||
0,
|
||||
sizeof(TDIEntityID),
|
||||
(PVOID *)entitySet,
|
||||
@@ -303,7 +306,7 @@ NTSTATUS tdiGetEntityIDSet( HANDLE tcpFile,
|
||||
return status;
|
||||
}
|
||||
|
||||
static BOOL isInterface( TDIEntityID *if_maybe ) {
|
||||
BOOL isInterface( TDIEntityID *if_maybe ) {
|
||||
return
|
||||
if_maybe->tei_entity == IF_ENTITY;
|
||||
}
|
||||
@@ -348,6 +351,30 @@ NTSTATUS tdiGetEntityType( HANDLE tcpFile, TDIEntityID *ent, PULONG type ) {
|
||||
return (status ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
|
||||
BOOL hasArp( HANDLE tcpFile, TDIEntityID *arp_maybe ) {
|
||||
TCP_REQUEST_QUERY_INFORMATION_EX req = TCP_REQUEST_QUERY_INFORMATION_INIT;
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
DWORD returnSize, type;
|
||||
|
||||
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 = AT_ENTITY;
|
||||
req.ID.toi_entity.tei_instance = arp_maybe->tei_instance;
|
||||
|
||||
status = DeviceIoControl( tcpFile,
|
||||
IOCTL_TCP_QUERY_INFORMATION_EX,
|
||||
&req,
|
||||
sizeof(req),
|
||||
&type,
|
||||
sizeof(type),
|
||||
&returnSize,
|
||||
NULL );
|
||||
|
||||
if( !NT_SUCCESS(status) ) return FALSE;
|
||||
return type == AT_ENTITY;
|
||||
}
|
||||
|
||||
static NTSTATUS getInterfaceInfoSet( HANDLE tcpFile,
|
||||
IFInfo **infoSet,
|
||||
PDWORD numInterfaces ) {
|
||||
|
||||
@@ -118,7 +118,8 @@ VOID closeTcpFile(HANDLE tcpFile);
|
||||
NTSTATUS tdiGetEntityIDSet( HANDLE tcpFile, TDIEntityID **entitySet,
|
||||
PDWORD numEntities );
|
||||
NTSTATUS tdiGetSetOfThings( HANDLE tcpFile, DWORD toiClass, DWORD toiType,
|
||||
DWORD toiId, DWORD teiEntity, DWORD fixedPart,
|
||||
DWORD toiId, DWORD teiEntity, DWORD teiInstance,
|
||||
DWORD fixedPart,
|
||||
DWORD entrySize, PVOID *tdiEntitySet,
|
||||
PDWORD numEntries );
|
||||
VOID tdiFreeThingSet( PVOID things );
|
||||
@@ -134,6 +135,8 @@ PWCHAR GetNthChildKeyName( HANDLE RegHandle, DWORD n );
|
||||
void ConsumeChildKeyName( PWCHAR Name );
|
||||
PWCHAR QueryRegistryValueString( HANDLE RegHandle, PWCHAR ValueName );
|
||||
void ConsumeRegValueString( PWCHAR NameServer );
|
||||
BOOL isInterface( TDIEntityID *if_maybe );
|
||||
BOOL hasArp( HANDLE tcpFile, TDIEntityID *arp_maybe );
|
||||
|
||||
#include <w32api.h>
|
||||
/* This is here until we switch to version 2.5 of the mingw headers */
|
||||
|
||||
@@ -183,6 +183,7 @@ NTSTATUS tdiGetRoutesForIpEntity
|
||||
INFO_TYPE_PROVIDER,
|
||||
IP_MIB_ROUTETABLE_ENTRY_ID,
|
||||
ent->tei_entity,
|
||||
0,
|
||||
0,
|
||||
sizeof(IPRouteEntry),
|
||||
(PVOID *)routes,
|
||||
@@ -203,6 +204,7 @@ NTSTATUS tdiGetIpAddrsForIpEntity
|
||||
INFO_TYPE_PROVIDER,
|
||||
IP_MIB_ADDRTABLE_ENTRY_ID,
|
||||
ent->tei_entity,
|
||||
0,
|
||||
0,
|
||||
sizeof(IPAddrEntry),
|
||||
(PVOID *)addrs,
|
||||
@@ -507,12 +509,106 @@ RouteTable *getRouteTable(void)
|
||||
|
||||
DWORD getNumArpEntries(void)
|
||||
{
|
||||
return getNumWithOneHeader("/proc/net/arp");
|
||||
DWORD numEntities;
|
||||
TDIEntityID *entitySet = NULL;
|
||||
HANDLE tcpFile;
|
||||
int i, totalNumber = 0;
|
||||
NTSTATUS status;
|
||||
PMIB_IPNETROW IpArpTable = NULL;
|
||||
DWORD returnSize;
|
||||
|
||||
TRACE("called.\n");
|
||||
|
||||
status = openTcpFile( &tcpFile );
|
||||
|
||||
if( !NT_SUCCESS(status) ) {
|
||||
TRACE("failure: %08x\n", (int)status );
|
||||
return 0;
|
||||
}
|
||||
|
||||
status = tdiGetEntityIDSet( tcpFile, &entitySet, &numEntities );
|
||||
|
||||
for( i = 0; i < numEntities; i++ ) {
|
||||
if( isInterface( &entitySet[i] ) &&
|
||||
hasArp( tcpFile, &entitySet[i] ) ) {
|
||||
|
||||
status = tdiGetSetOfThings( tcpFile,
|
||||
INFO_CLASS_PROTOCOL,
|
||||
INFO_TYPE_PROVIDER,
|
||||
IP_MIB_ARPTABLE_ENTRY_ID,
|
||||
AT_ENTITY,
|
||||
entitySet[i].tei_instance,
|
||||
0,
|
||||
sizeof(MIB_IPNETROW),
|
||||
(PVOID *)&IpArpTable,
|
||||
&returnSize );
|
||||
|
||||
if( status == STATUS_SUCCESS ) totalNumber += returnSize;
|
||||
if( IpArpTable ) tdiFreeThingSet( IpArpTable );
|
||||
}
|
||||
}
|
||||
|
||||
closeTcpFile( tcpFile );
|
||||
if( IpArpTable ) tdiFreeThingSet( IpArpTable );
|
||||
if( entitySet ) tdiFreeThingSet( entitySet );
|
||||
return totalNumber;
|
||||
}
|
||||
|
||||
PMIB_IPNETTABLE getArpTable(void)
|
||||
{
|
||||
return 0;
|
||||
DWORD numEntities, returnSize;
|
||||
TDIEntityID *entitySet;
|
||||
HANDLE tcpFile;
|
||||
int i, row = 0, totalNumber;
|
||||
NTSTATUS status;
|
||||
PMIB_IPNETTABLE IpArpTable = NULL;
|
||||
PMIB_IPNETROW AdapterArpTable = NULL;
|
||||
|
||||
TRACE("called.\n");
|
||||
|
||||
totalNumber = getNumArpEntries();
|
||||
|
||||
status = openTcpFile( &tcpFile );
|
||||
|
||||
if( !NT_SUCCESS(status) ) {
|
||||
TRACE("failure: %08x\n", (int)status );
|
||||
return 0;
|
||||
}
|
||||
|
||||
IpArpTable = HeapAlloc
|
||||
( GetProcessHeap(), 0,
|
||||
sizeof(DWORD) + (sizeof(MIB_IPNETROW) * totalNumber) );
|
||||
|
||||
status = tdiGetEntityIDSet( tcpFile, &entitySet, &numEntities );
|
||||
|
||||
for( i = 0; i < numEntities; i++ ) {
|
||||
if( isIpEntity( tcpFile, &entitySet[i] ) &&
|
||||
hasArp( tcpFile, &entitySet[i] ) ) {
|
||||
|
||||
status = tdiGetSetOfThings( tcpFile,
|
||||
INFO_CLASS_PROTOCOL,
|
||||
INFO_TYPE_PROVIDER,
|
||||
IP_MIB_ARPTABLE_ENTRY_ID,
|
||||
AT_ENTITY,
|
||||
entitySet[i].tei_instance,
|
||||
0,
|
||||
sizeof(MIB_IPNETROW),
|
||||
(PVOID *)&AdapterArpTable,
|
||||
&returnSize );
|
||||
|
||||
if( status == STATUS_SUCCESS ) {
|
||||
for( row = 0; row < returnSize; row++ )
|
||||
IpArpTable->table[row] = AdapterArpTable[row];
|
||||
}
|
||||
|
||||
if( AdapterArpTable ) tdiFreeThingSet( AdapterArpTable );
|
||||
}
|
||||
}
|
||||
|
||||
tdiFreeThingSet( entitySet );
|
||||
IpArpTable->dwNumEntries = row;
|
||||
|
||||
return IpArpTable;
|
||||
}
|
||||
|
||||
DWORD getNumUdpEntries(void)
|
||||
|
||||
@@ -46,6 +46,19 @@ typedef struct IPADDR_ENTRY {
|
||||
USHORT Pad;
|
||||
} IPADDR_ENTRY, *PIPADDR_ENTRY;
|
||||
|
||||
#define ARP_ENTRY_STATIC 4
|
||||
#define ARP_ENTRY_DYNAMIC 3
|
||||
#define ARP_ENTRY_INVALID 2
|
||||
#define ARP_ENTRY_OTHER 1
|
||||
|
||||
typedef struct IPARP_ENTRY {
|
||||
ULONG Index;
|
||||
ULONG AddrSize;
|
||||
UCHAR PhysAddr[8];
|
||||
ULONG LogAddr;
|
||||
ULONG Type;
|
||||
} IPARP_ENTRY, *PIPARP_ENTRY;
|
||||
|
||||
typedef struct IPROUTE_ENTRY {
|
||||
ULONG Dest;
|
||||
ULONG Index; //matches if_index in IFEntry and iae_index in IPAddrEntry
|
||||
@@ -96,6 +109,9 @@ typedef struct IFENTRY {
|
||||
#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
|
||||
|
||||
@@ -107,6 +107,10 @@ BOOLEAN NBQueuePacket(
|
||||
VOID NBRemoveNeighbor(
|
||||
PNEIGHBOR_CACHE_ENTRY NCE);
|
||||
|
||||
DWORD NBCopyNeighbors(
|
||||
PIP_INTERFACE Interface,
|
||||
PIPARP_ENTRY ArpTable);
|
||||
|
||||
#endif /* __NEIGHBOR_H */
|
||||
|
||||
/* EOF */
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <checksum.h>
|
||||
#include <address.h>
|
||||
#include <routines.h>
|
||||
#include <info.h>
|
||||
#include <neighbor.h>
|
||||
#include <route.h>
|
||||
#include <receive.h>
|
||||
@@ -29,7 +30,6 @@
|
||||
#include <tilists.h>
|
||||
#include <dispatch.h>
|
||||
#include <fileobjs.h>
|
||||
#include <info.h>
|
||||
#include <lock.h>
|
||||
#include <wait.h>
|
||||
#include <bug.h>
|
||||
|
||||
@@ -78,6 +78,42 @@ TDI_STATUS InfoTdiQueryGetInterfaceMIB(TDIEntityID *ID,
|
||||
return Status;
|
||||
}
|
||||
|
||||
TDI_STATUS InfoTdiQueryGetArptableMIB(TDIEntityID *ID,
|
||||
PIP_INTERFACE Interface,
|
||||
PNDIS_BUFFER Buffer,
|
||||
PUINT BufferSize) {
|
||||
NTSTATUS Status;
|
||||
DWORD NumNeighbors = NBCopyNeighbors( Interface, NULL );
|
||||
DWORD MemSize = NumNeighbors * sizeof(IPARP_ENTRY);
|
||||
PIPARP_ENTRY ArpEntries =
|
||||
ExAllocatePoolWithTag
|
||||
( NonPagedPool, MemSize, FOURCC('A','R','P','t') );
|
||||
|
||||
if( !ArpEntries ) return STATUS_NO_MEMORY;
|
||||
NBCopyNeighbors( Interface, ArpEntries );
|
||||
|
||||
Status = InfoCopyOut( (PVOID)ArpEntries, MemSize, Buffer, BufferSize );
|
||||
|
||||
ExFreePool( ArpEntries );
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
TDI_STATUS InfoTdiQueryGetArpCapability(TDIEntityID *ID,
|
||||
PIP_INTERFACE Interface,
|
||||
PNDIS_BUFFER Buffer,
|
||||
PUINT BufferSize) {
|
||||
NTSTATUS Status;
|
||||
DWORD Capability = 0x280;
|
||||
|
||||
TI_DbgPrint(MID_TRACE,("Copying out %d bytes (AT_ENTITY capability)\n",
|
||||
sizeof(Capability)));
|
||||
Status = InfoCopyOut
|
||||
( (PVOID)&Capability, sizeof(Capability), Buffer, BufferSize );
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
TDI_STATUS InfoInterfaceTdiQueryEx( UINT InfoClass,
|
||||
UINT InfoType,
|
||||
UINT InfoId,
|
||||
@@ -87,13 +123,22 @@ TDI_STATUS InfoInterfaceTdiQueryEx( UINT InfoClass,
|
||||
PUINT BufferSize ) {
|
||||
if( InfoClass == INFO_CLASS_GENERIC &&
|
||||
InfoType == INFO_TYPE_PROVIDER &&
|
||||
InfoId == ENTITY_TYPE_ID ) {
|
||||
ULONG Temp = IF_MIB;
|
||||
return InfoCopyOut( (PCHAR)&Temp, sizeof(Temp), Buffer, BufferSize );
|
||||
InfoId == ENTITY_TYPE_ID &&
|
||||
id->tei_entity == AT_ENTITY ) {
|
||||
return InfoTdiQueryGetArpCapability( id, Context, Buffer, BufferSize );
|
||||
} else if( InfoClass == INFO_CLASS_PROTOCOL &&
|
||||
InfoType == INFO_TYPE_PROVIDER &&
|
||||
InfoId == IF_MIB_STATS_ID ) {
|
||||
return InfoTdiQueryGetInterfaceMIB( id, Context, Buffer, BufferSize );
|
||||
} else if( InfoClass == INFO_CLASS_GENERIC &&
|
||||
InfoType == INFO_TYPE_PROVIDER &&
|
||||
InfoId == ENTITY_TYPE_ID ) {
|
||||
ULONG Temp = IF_MIB;
|
||||
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 );
|
||||
} else
|
||||
return TDI_INVALID_REQUEST;
|
||||
}
|
||||
|
||||
@@ -164,6 +164,35 @@ TDI_STATUS InfoTdiQueryInformationEx(
|
||||
Status = TDI_INVALID_PARAMETER;
|
||||
} else
|
||||
Status = InfoTdiQueryListEntities(Buffer, BufferSize);
|
||||
} else if (ID->toi_entity.tei_entity == AT_ENTITY) {
|
||||
TcpipAcquireSpinLock( &EntityListLock, &OldIrql );
|
||||
|
||||
for( i = 0; i < EntityCount; i++ ) {
|
||||
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 );
|
||||
|
||||
if( FoundEntity ) {
|
||||
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 );
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
|
||||
#define IF_MIB_STATS_ID 1
|
||||
#define IP_MIB_STATS_ID 1
|
||||
#define IP_MIB_ARPTABLE_ENTRY_ID 0x101
|
||||
#define IP_MIB_ADDRTABLE_ENTRY_ID 0x102
|
||||
#define IP_INTFC_INFO_ID 0x103
|
||||
#define MAX_PHYSADDR_SIZE 8
|
||||
|
||||
@@ -514,3 +514,43 @@ VOID NBRemoveNeighbor(
|
||||
|
||||
TcpipReleaseSpinLock(&NeighborCache[HashValue].Lock, OldIrql);
|
||||
}
|
||||
|
||||
ULONG NBCopyNeighbors
|
||||
(PIP_INTERFACE Interface,
|
||||
PIPARP_ENTRY ArpTable)
|
||||
{
|
||||
PNEIGHBOR_CACHE_ENTRY CurNCE;
|
||||
KIRQL OldIrql;
|
||||
UINT Size = 0, i;
|
||||
|
||||
for (i = 0; i <= NB_HASHMASK; i++) {
|
||||
TcpipAcquireSpinLock(&NeighborCache[i].Lock, &OldIrql);
|
||||
for( CurNCE = NeighborCache[i].Cache;
|
||||
CurNCE;
|
||||
CurNCE = CurNCE->Next ) {
|
||||
if( CurNCE->Interface == Interface ) {
|
||||
if( ArpTable ) {
|
||||
ArpTable[Size].Index = Interface->Index;
|
||||
ArpTable[Size].AddrSize = CurNCE->LinkAddressLength;
|
||||
RtlCopyMemory
|
||||
(ArpTable[Size].PhysAddr,
|
||||
CurNCE->LinkAddress,
|
||||
CurNCE->LinkAddressLength);
|
||||
ArpTable[Size].LogAddr = CurNCE->Address.Address.IPv4Address;
|
||||
if( CurNCE->State & NUD_PERMANENT )
|
||||
ArpTable[Size].Type = ARP_ENTRY_STATIC;
|
||||
else if( CurNCE->State & NUD_CONNECTED )
|
||||
ArpTable[Size].Type = ARP_ENTRY_DYNAMIC;
|
||||
else if( !(CurNCE->State & NUD_VALID) )
|
||||
ArpTable[Size].Type = ARP_ENTRY_INVALID;
|
||||
else
|
||||
ArpTable[Size].Type = ARP_ENTRY_OTHER;
|
||||
}
|
||||
Size++;
|
||||
}
|
||||
}
|
||||
TcpipReleaseSpinLock(&NeighborCache[i].Lock, OldIrql);
|
||||
}
|
||||
|
||||
return Size;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user