More support for IOCTL_TCP_QUERY/SET_INFORMATION_EX

Connected ControlChannel handle type.
Allowed empty EaInfo in create -> ControlChannel.
Added TDI entity for interfaces.
Fixed IPSnmpInfo interface number report.
Fixed returned buffer size report in DispTdiQueryInformationExComplete
Added IPROUTE_ENTRY struct.

What works:
tcpquery lists three entities, two builtin and one IF_ENTITY
tcpquery -i reports 1 interface and 1 address for me (addr=127.0.0.1)

TODO:
Type information for each entity (only two builtin entities are supported now)
Interface info out (IFEntry)
Route info in/out (IPRouteEntry)

svn path=/trunk/; revision=8588
This commit is contained in:
Art Yerkes 2004-03-08 10:20:18 +00:00
parent 9183e287b1
commit 0c76856d9c
9 changed files with 193 additions and 22 deletions

View file

@ -44,10 +44,29 @@ typedef struct IPADDR_ENTRY {
USHORT Pad; USHORT Pad;
} IPADDR_ENTRY, *PIPADDR_ENTRY; } IPADDR_ENTRY, *PIPADDR_ENTRY;
typedef struct IPROUTE_ENTRY {
ULONG Dest;
ULONG Index; //matches if_index in IFEntry and iae_index in IPAddrEntry
ULONG Metric1;
ULONG Metric2;
ULONG Metric3;
ULONG Metric4;
ULONG Gw;
ULONG Type;
ULONG Proto;
ULONG Age;
ULONG Mask;
ULONG Metric5;
ULONG Info;
} IPROUTE_ENTRY, *PIPROUTE_ENTRY;
#define IP_MIB_STATS_ID 1 #define IP_MIB_STATS_ID 1
#ifndef IP_MIB_ADDRTABLE_ENTRY_ID #ifndef IP_MIB_ADDRTABLE_ENTRY_ID
#define IP_MIB_ADDRTABLE_ENTRY_ID 0x102 #define IP_MIB_ADDRTABLE_ENTRY_ID 0x102
#endif #endif
#ifndef IP_MIB_ROUTETABLE_ENTRY_ID
#define IP_MIB_ROUTETABLE_ENTRY_ID 0x103
#endif
#ifndef MAX_PHYSADDR_SIZE #ifndef MAX_PHYSADDR_SIZE
#define MAX_PHYSADDR_SIZE 8 #define MAX_PHYSADDR_SIZE 8

View file

@ -11,9 +11,9 @@
#include <address.h> #include <address.h>
#include <router.h> #include <router.h>
#include <pool.h> #include <pool.h>
#include <info.h>
#include <arp.h> #include <arp.h>
/* Route Cache Node structure. /* Route Cache Node structure.
* The primary purpose of the RCN is to cache selected source and * The primary purpose of the RCN is to cache selected source and
* next-hop addresses. The routing cache is implemented as a binary * next-hop addresses. The routing cache is implemented as a binary

View file

@ -122,6 +122,7 @@ extern LIST_ENTRY AddressFileListHead;
extern KSPIN_LOCK AddressFileListLock; extern KSPIN_LOCK AddressFileListLock;
extern NDIS_HANDLE GlobalPacketPool; extern NDIS_HANDLE GlobalPacketPool;
extern NDIS_HANDLE GlobalBufferPool; extern NDIS_HANDLE GlobalBufferPool;
extern KSPIN_LOCK EntityListLock;
extern TDIEntityID *EntityList; extern TDIEntityID *EntityList;
extern ULONG EntityCount; extern ULONG EntityCount;
extern UDP_STATISTICS UDPStats; extern UDP_STATISTICS UDPStats;

View file

@ -699,4 +699,21 @@ VOID RouteInvalidateNCE(
KeReleaseSpinLock(&RouteCacheLock, OldIrql); KeReleaseSpinLock(&RouteCacheLock, OldIrql);
} }
NTSTATUS
RouteFriendlyAddRoute( PIPROUTE_ENTRY ire ) {
PNET_TABLE_ENTRY Nte;
PNEIGHBOR_CACHE_ENTRY Nce;
PIP_INTERFACE If;
IP_ADDRESS Dest;
KIRQL OldIrql;
/* Find IF */
KeAcquireSpinLock(&InterfaceListLock, &OldIrql);
//RouteAddRouteToDestination(&Dest,Nte,If,Nce);
KeReleaseSpinLock(&InterfaceListLock, OldIrql);
return STATUS_SUCCESS;
}
/* EOF */ /* EOF */

View file

@ -1022,7 +1022,7 @@ VOID DispTdiQueryInformationExComplete(
MmUnlockPages(QueryContext->OutputMdl); MmUnlockPages(QueryContext->OutputMdl);
IoFreeMdl(QueryContext->OutputMdl); IoFreeMdl(QueryContext->OutputMdl);
QueryContext->Irp->IoStatus.Information = Count; QueryContext->Irp->IoStatus.Information = ByteCount;
QueryContext->Irp->IoStatus.Status = Status; QueryContext->Irp->IoStatus.Status = Status;
ExFreePool(QueryContext); ExFreePool(QueryContext);

View file

@ -38,6 +38,18 @@ VOID AddrFileFree(
} }
VOID ControlChannelFree(
PVOID Object)
/*
* FUNCTION: Frees an address file object
* ARGUMENTS:
* Object = Pointer to address file object to free
*/
{
ExFreePool(Object);
}
VOID DeleteAddress( VOID DeleteAddress(
PADDRESS_FILE AddrFile) PADDRESS_FILE AddrFile)
/* /*
@ -538,7 +550,37 @@ NTSTATUS FileCloseConnection(
NTSTATUS FileOpenControlChannel( NTSTATUS FileOpenControlChannel(
PTDI_REQUEST Request) PTDI_REQUEST Request)
{ {
return STATUS_NOT_IMPLEMENTED; PCONTROL_CHANNEL ControlChannel;
TI_DbgPrint(MID_TRACE, ("Called.\n"));
ControlChannel = ExAllocatePool(NonPagedPool, sizeof(*ControlChannel));
if (!ControlChannel) {
TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory(ControlChannel, sizeof(CONTROL_CHANNEL));
/* Make sure address is a local unicast address or 0 */
/* Locate address entry. If specified address is 0, a random address is chosen */
/* Initialize receive and transmit queues */
InitializeListHead(&ControlChannel->ListEntry);
/* Initialize spin lock that protects the address file object */
KeInitializeSpinLock(&ControlChannel->Lock);
/* Reference the object */
ControlChannel->RefCount = 1;
/* Return address file object */
Request->Handle.ControlChannel = ControlChannel;
TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
return STATUS_SUCCESS;
} }
@ -552,7 +594,14 @@ NTSTATUS FileOpenControlChannel(
NTSTATUS FileCloseControlChannel( NTSTATUS FileCloseControlChannel(
PTDI_REQUEST Request) PTDI_REQUEST Request)
{ {
return STATUS_NOT_IMPLEMENTED; PCONTROL_CHANNEL ControlChannel = Request->Handle.ControlChannel;
KIRQL OldIrql;
NTSTATUS Status = STATUS_SUCCESS;
ExFreePool(ControlChannel);
Request->Handle.ControlChannel = NULL;
return Status;
} }
/* EOF */ /* EOF */

View file

@ -158,6 +158,21 @@ TDI_STATUS IPTdiQueryInformationEx(
RtlZeroMemory(&SnmpInfo, sizeof(IPSNMP_INFO)); RtlZeroMemory(&SnmpInfo, sizeof(IPSNMP_INFO));
/* Count number of interfaces */
Count = 0;
KeAcquireSpinLock(&InterfaceListLock, &OldIrql);
CurrentIFEntry = InterfaceListHead.Flink;
while (CurrentIFEntry != &InterfaceListHead)
{
Count++;
CurrentIFEntry = CurrentIFEntry->Flink;
}
KeReleaseSpinLock(&InterfaceListLock, OldIrql);
SnmpInfo.NumIf = Count;
/* Count number of addresses */ /* Count number of addresses */
Count = 0; Count = 0;
KeAcquireSpinLock(&InterfaceListLock, &OldIrql); KeAcquireSpinLock(&InterfaceListLock, &OldIrql);
@ -205,8 +220,12 @@ TDI_STATUS InfoTdiQueryInformationEx(
* Status of operation * Status of operation
*/ */
{ {
PLIST_ENTRY CurrentIFEntry;
PLIST_ENTRY CurrentADEEntry;
PLIST_ENTRY CurrentADFEntry; PLIST_ENTRY CurrentADFEntry;
PADDRESS_FILE CurrentADF; PADDRESS_FILE CurrentADF;
PADDRESS_ENTRY CurrentADE;
PIP_INTERFACE CurrentIF;
ADDRESS_INFO Info; ADDRESS_INFO Info;
KIRQL OldIrql; KIRQL OldIrql;
UINT BufSize; UINT BufSize;
@ -215,6 +234,7 @@ TDI_STATUS InfoTdiQueryInformationEx(
ULONG Temp; ULONG Temp;
UINT Count; UINT Count;
UINT Size; UINT Size;
TDIEntityID EntityId;
Offset = 0; Offset = 0;
BufSize = *BufferSize; BufSize = *BufferSize;
@ -230,18 +250,44 @@ TDI_STATUS InfoTdiQueryInformationEx(
return TDI_INVALID_PARAMETER; return TDI_INVALID_PARAMETER;
} }
*BufferSize = 0; /* Count Adapters */
KeAcquireSpinLock(&InterfaceListLock, &OldIrql);
CurrentIFEntry = InterfaceListHead.Flink;
Count = EntityCount;
while( CurrentIFEntry != &InterfaceListHead ) {
Count++;
CurrentIFEntry = CurrentIFEntry->Flink;
}
KeReleaseSpinLock(&InterfaceListLock, OldIrql);
Size = Count * sizeof(TDIEntityID);
*BufferSize = Size;
Size = EntityCount * sizeof(TDIEntityID);
if (BufSize < Size) if (BufSize < Size)
{ {
/* The buffer is too small to contain requested data */ /* The buffer is too small to contain requested data */
return TDI_BUFFER_TOO_SMALL; return TDI_BUFFER_TOO_SMALL;
} }
DbgPrint("About to copy %d TDIEntityIDs (%d bytes) to user\n",
Count, Size);
KeAcquireSpinLock(&EntityListLock, &OldIrql);
/* Update entity list */
for( Temp = EntityCount; Temp < Count; Temp++ ) {
EntityList[Temp].tei_entity = IF_ENTITY;
EntityList[Temp].tei_instance = Temp - EntityCount;
}
/* Return entity list */ /* Return entity list */
Count = CopyBufferToBufferChain(Buffer, 0, (PUCHAR)EntityList, Size); Count = CopyBufferToBufferChain(Buffer, 0, (PUCHAR)EntityList, Size);
KeReleaseSpinLock(&EntityListLock, OldIrql);
*BufferSize = Size; *BufferSize = Size;
return TDI_SUCCESS; return TDI_SUCCESS;
@ -378,7 +424,30 @@ TDI_STATUS InfoTdiSetInformationEx(
* Status of operation * Status of operation
*/ */
{ {
/* FIXME: Set extended information */ switch( ID->toi_class ) {
case INFO_CLASS_PROTOCOL:
switch( ID->toi_type ) {
case INFO_TYPE_PROVIDER:
switch( ID->toi_id ) {
case IP_MIB_ROUTETABLE_ENTRY_ID:
if( ID->toi_entity.tei_entity == CL_NL_ENTITY &&
ID->toi_entity.tei_instance == TL_INSTANCE &&
BufferSize >= sizeof(IPROUTE_ENTRY) ) {
/* Add route -- buffer is an IPRouteEntry */
PIPROUTE_ENTRY ire = (PIPROUTE_ENTRY)Buffer;
RouteFriendlyAddRoute( ire );
} else {
return TDI_INVALID_PARAMETER;
/* In my experience, we are being over
protective compared to windows */
}
break;
}
break;
}
break;
}
return TDI_INVALID_REQUEST; return TDI_INVALID_PARAMETER;
} }

View file

@ -19,7 +19,7 @@
#include <rosrtl/string.h> #include <rosrtl/string.h>
#ifdef DBG #ifdef DBG
DWORD DebugTraceLevel = MIN_TRACE; DWORD DebugTraceLevel = 0x7fffffff;
#endif /* DBG */ #endif /* DBG */
PDEVICE_OBJECT TCPDeviceObject = NULL; PDEVICE_OBJECT TCPDeviceObject = NULL;
@ -28,8 +28,10 @@ PDEVICE_OBJECT IPDeviceObject = NULL;
PDEVICE_OBJECT RawIPDeviceObject = NULL; PDEVICE_OBJECT RawIPDeviceObject = NULL;
NDIS_HANDLE GlobalPacketPool = NULL; NDIS_HANDLE GlobalPacketPool = NULL;
NDIS_HANDLE GlobalBufferPool = NULL; NDIS_HANDLE GlobalBufferPool = NULL;
KSPIN_LOCK EntityListLock;
TDIEntityID *EntityList = NULL; TDIEntityID *EntityList = NULL;
ULONG EntityCount = 0; ULONG EntityCount = 0;
ULONG EntityMax = 0;
UDP_STATISTICS UDPStats; UDP_STATISTICS UDPStats;
@ -165,10 +167,14 @@ NTSTATUS TiCreateFileObject(
EaInfo = Irp->AssociatedIrp.SystemBuffer; EaInfo = Irp->AssociatedIrp.SystemBuffer;
CP CP
/* Parameter check */ /* Parameter check */
/* No EA information means that we're opening for SET/QUERY_INFORMATION
* style calls. */
#if 0
if (!EaInfo) { if (!EaInfo) {
TI_DbgPrint(MIN_TRACE, ("No EA information in IRP.\n")); TI_DbgPrint(MIN_TRACE, ("No EA information in IRP.\n"));
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
} }
#endif
CP CP
/* Allocate resources here. We release them again if something failed */ /* Allocate resources here. We release them again if something failed */
Context = ExAllocatePool(NonPagedPool, sizeof(TRANSPORT_CONTEXT)); Context = ExAllocatePool(NonPagedPool, sizeof(TRANSPORT_CONTEXT));
@ -186,8 +192,10 @@ CP
Request.RequestContext = Irp; Request.RequestContext = Irp;
CP CP
/* Branch to the right handler */ /* Branch to the right handler */
if ((EaInfo->EaNameLength == TDI_TRANSPORT_ADDRESS_LENGTH) && if (EaInfo &&
(RtlCompareMemory(&EaInfo->EaName, TdiTransportAddress, (EaInfo->EaNameLength == TDI_TRANSPORT_ADDRESS_LENGTH) &&
(RtlCompareMemory
(&EaInfo->EaName, TdiTransportAddress,
TDI_TRANSPORT_ADDRESS_LENGTH) == TDI_TRANSPORT_ADDRESS_LENGTH)) { TDI_TRANSPORT_ADDRESS_LENGTH) == TDI_TRANSPORT_ADDRESS_LENGTH)) {
/* This is a request to open an address */ /* This is a request to open an address */
CP CP
@ -232,9 +240,12 @@ CP
Context->Handle.AddressHandle = Request.Handle.AddressHandle; Context->Handle.AddressHandle = Request.Handle.AddressHandle;
} }
CP CP
} else if ((EaInfo->EaNameLength == TDI_CONNECTION_CONTEXT_LENGTH) && } else if (EaInfo &&
(RtlCompareMemory(&EaInfo->EaName, TdiConnectionContext, (EaInfo->EaNameLength == TDI_CONNECTION_CONTEXT_LENGTH) &&
TDI_CONNECTION_CONTEXT_LENGTH) == TDI_CONNECTION_CONTEXT_LENGTH)) { (RtlCompareMemory
(&EaInfo->EaName, TdiConnectionContext,
TDI_CONNECTION_CONTEXT_LENGTH) ==
TDI_CONNECTION_CONTEXT_LENGTH)) {
/* This is a request to open a connection endpoint */ /* This is a request to open a connection endpoint */
CP CP
/* Parameter checks */ /* Parameter checks */
@ -264,10 +275,11 @@ CP
} }
} else { } else {
/* This is a request to open a control connection */ /* This is a request to open a control connection */
Status = FileOpenControlChannel(&Request);
TI_DbgPrint(MIN_TRACE, ("Control connections are not implemented yet\n")); if (NT_SUCCESS(Status)) {
IrpSp->FileObject->FsContext2 = (PVOID)TDI_CONTROL_CHANNEL_FILE;
Status = STATUS_NOT_IMPLEMENTED; Context->Handle.ControlChannel = Request.Handle.ControlChannel;
}
} }
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
@ -594,10 +606,12 @@ TiDispatch(
/* See if this request is TCP/IP specific */ /* See if this request is TCP/IP specific */
switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) { switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {
case IOCTL_TCP_QUERY_INFORMATION_EX: case IOCTL_TCP_QUERY_INFORMATION_EX:
TI_DbgPrint(MIN_TRACE, ("TCP_QUERY_INFORMATION_EX\n"));
Status = DispTdiQueryInformationEx(Irp, IrpSp); Status = DispTdiQueryInformationEx(Irp, IrpSp);
break; break;
case IOCTL_TCP_SET_INFORMATION_EX: case IOCTL_TCP_SET_INFORMATION_EX:
TI_DbgPrint(MIN_TRACE, ("TCP_SET_INFORMATION_EX\n"));
Status = DispTdiSetInformationEx(Irp, IrpSp); Status = DispTdiSetInformationEx(Irp, IrpSp);
break; break;
@ -813,7 +827,8 @@ DriverEntry(
} }
/* Setup network layer and transport layer entities */ /* Setup network layer and transport layer entities */
EntityList = ExAllocatePool(NonPagedPool, sizeof(TDIEntityID) * 2); KeInitializeSpinLock(&EntityListLock);
EntityList = ExAllocatePool(NonPagedPool, sizeof(TDIEntityID) * MAX_TDI_ENTITIES );
if (!NT_SUCCESS(Status)) { if (!NT_SUCCESS(Status)) {
TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
TiUnload(DriverObject); TiUnload(DriverObject);
@ -825,6 +840,7 @@ DriverEntry(
EntityList[1].tei_entity = CL_TL_ENTITY; EntityList[1].tei_entity = CL_TL_ENTITY;
EntityList[1].tei_instance = 0; EntityList[1].tei_instance = 0;
EntityCount = 2; EntityCount = 2;
EntityMax = MAX_TDI_ENTITIES;
/* Use direct I/O */ /* Use direct I/O */
IPDeviceObject->Flags |= DO_DIRECT_IO; IPDeviceObject->Flags |= DO_DIRECT_IO;