mirror of
https://github.com/reactos/reactos.git
synced 2025-04-21 12:40:33 +00:00
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:
parent
9183e287b1
commit
0c76856d9c
9 changed files with 193 additions and 22 deletions
|
@ -593,7 +593,7 @@ VOID LANTransmit(
|
|||
|
||||
VOID BindAdapter(
|
||||
PLAN_ADAPTER Adapter,
|
||||
PNDIS_STRING RegistryPath)
|
||||
PNDIS_STRING RegistryPath)
|
||||
/*
|
||||
* FUNCTION: Binds a LAN adapter to IP layer
|
||||
* ARGUMENTS:
|
||||
|
|
|
@ -44,10 +44,29 @@ typedef struct IPADDR_ENTRY {
|
|||
USHORT Pad;
|
||||
} 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
|
||||
#ifndef IP_MIB_ADDRTABLE_ENTRY_ID
|
||||
#define IP_MIB_ADDRTABLE_ENTRY_ID 0x102
|
||||
#endif
|
||||
#ifndef IP_MIB_ROUTETABLE_ENTRY_ID
|
||||
#define IP_MIB_ROUTETABLE_ENTRY_ID 0x103
|
||||
#endif
|
||||
|
||||
#ifndef MAX_PHYSADDR_SIZE
|
||||
#define MAX_PHYSADDR_SIZE 8
|
||||
|
|
|
@ -11,9 +11,9 @@
|
|||
#include <address.h>
|
||||
#include <router.h>
|
||||
#include <pool.h>
|
||||
#include <info.h>
|
||||
#include <arp.h>
|
||||
|
||||
|
||||
/* Route Cache Node structure.
|
||||
* The primary purpose of the RCN is to cache selected source and
|
||||
* next-hop addresses. The routing cache is implemented as a binary
|
||||
|
|
|
@ -122,6 +122,7 @@ extern LIST_ENTRY AddressFileListHead;
|
|||
extern KSPIN_LOCK AddressFileListLock;
|
||||
extern NDIS_HANDLE GlobalPacketPool;
|
||||
extern NDIS_HANDLE GlobalBufferPool;
|
||||
extern KSPIN_LOCK EntityListLock;
|
||||
extern TDIEntityID *EntityList;
|
||||
extern ULONG EntityCount;
|
||||
extern UDP_STATISTICS UDPStats;
|
||||
|
|
|
@ -699,4 +699,21 @@ VOID RouteInvalidateNCE(
|
|||
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 */
|
||||
|
|
|
@ -1022,7 +1022,7 @@ VOID DispTdiQueryInformationExComplete(
|
|||
MmUnlockPages(QueryContext->OutputMdl);
|
||||
IoFreeMdl(QueryContext->OutputMdl);
|
||||
|
||||
QueryContext->Irp->IoStatus.Information = Count;
|
||||
QueryContext->Irp->IoStatus.Information = ByteCount;
|
||||
QueryContext->Irp->IoStatus.Status = Status;
|
||||
|
||||
ExFreePool(QueryContext);
|
||||
|
|
|
@ -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(
|
||||
PADDRESS_FILE AddrFile)
|
||||
/*
|
||||
|
@ -536,9 +548,39 @@ NTSTATUS FileCloseConnection(
|
|||
* Status of operation
|
||||
*/
|
||||
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(
|
||||
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 */
|
||||
|
|
|
@ -158,6 +158,21 @@ TDI_STATUS IPTdiQueryInformationEx(
|
|||
|
||||
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 = 0;
|
||||
KeAcquireSpinLock(&InterfaceListLock, &OldIrql);
|
||||
|
@ -205,8 +220,12 @@ TDI_STATUS InfoTdiQueryInformationEx(
|
|||
* Status of operation
|
||||
*/
|
||||
{
|
||||
PLIST_ENTRY CurrentIFEntry;
|
||||
PLIST_ENTRY CurrentADEEntry;
|
||||
PLIST_ENTRY CurrentADFEntry;
|
||||
PADDRESS_FILE CurrentADF;
|
||||
PADDRESS_ENTRY CurrentADE;
|
||||
PIP_INTERFACE CurrentIF;
|
||||
ADDRESS_INFO Info;
|
||||
KIRQL OldIrql;
|
||||
UINT BufSize;
|
||||
|
@ -215,6 +234,7 @@ TDI_STATUS InfoTdiQueryInformationEx(
|
|||
ULONG Temp;
|
||||
UINT Count;
|
||||
UINT Size;
|
||||
TDIEntityID EntityId;
|
||||
|
||||
Offset = 0;
|
||||
BufSize = *BufferSize;
|
||||
|
@ -230,18 +250,44 @@ TDI_STATUS InfoTdiQueryInformationEx(
|
|||
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)
|
||||
{
|
||||
/* The buffer is too small to contain requested data */
|
||||
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 */
|
||||
Count = CopyBufferToBufferChain(Buffer, 0, (PUCHAR)EntityList, Size);
|
||||
|
||||
KeReleaseSpinLock(&EntityListLock, OldIrql);
|
||||
|
||||
*BufferSize = Size;
|
||||
|
||||
return TDI_SUCCESS;
|
||||
|
@ -378,7 +424,30 @@ TDI_STATUS InfoTdiSetInformationEx(
|
|||
* 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#include <rosrtl/string.h>
|
||||
|
||||
#ifdef DBG
|
||||
DWORD DebugTraceLevel = MIN_TRACE;
|
||||
DWORD DebugTraceLevel = 0x7fffffff;
|
||||
#endif /* DBG */
|
||||
|
||||
PDEVICE_OBJECT TCPDeviceObject = NULL;
|
||||
|
@ -28,8 +28,10 @@ PDEVICE_OBJECT IPDeviceObject = NULL;
|
|||
PDEVICE_OBJECT RawIPDeviceObject = NULL;
|
||||
NDIS_HANDLE GlobalPacketPool = NULL;
|
||||
NDIS_HANDLE GlobalBufferPool = NULL;
|
||||
KSPIN_LOCK EntityListLock;
|
||||
TDIEntityID *EntityList = NULL;
|
||||
ULONG EntityCount = 0;
|
||||
ULONG EntityMax = 0;
|
||||
UDP_STATISTICS UDPStats;
|
||||
|
||||
|
||||
|
@ -165,10 +167,14 @@ NTSTATUS TiCreateFileObject(
|
|||
EaInfo = Irp->AssociatedIrp.SystemBuffer;
|
||||
CP
|
||||
/* Parameter check */
|
||||
/* No EA information means that we're opening for SET/QUERY_INFORMATION
|
||||
* style calls. */
|
||||
#if 0
|
||||
if (!EaInfo) {
|
||||
TI_DbgPrint(MIN_TRACE, ("No EA information in IRP.\n"));
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
#endif
|
||||
CP
|
||||
/* Allocate resources here. We release them again if something failed */
|
||||
Context = ExAllocatePool(NonPagedPool, sizeof(TRANSPORT_CONTEXT));
|
||||
|
@ -186,9 +192,11 @@ CP
|
|||
Request.RequestContext = Irp;
|
||||
CP
|
||||
/* Branch to the right handler */
|
||||
if ((EaInfo->EaNameLength == TDI_TRANSPORT_ADDRESS_LENGTH) &&
|
||||
(RtlCompareMemory(&EaInfo->EaName, TdiTransportAddress,
|
||||
TDI_TRANSPORT_ADDRESS_LENGTH) == TDI_TRANSPORT_ADDRESS_LENGTH)) {
|
||||
if (EaInfo &&
|
||||
(EaInfo->EaNameLength == TDI_TRANSPORT_ADDRESS_LENGTH) &&
|
||||
(RtlCompareMemory
|
||||
(&EaInfo->EaName, TdiTransportAddress,
|
||||
TDI_TRANSPORT_ADDRESS_LENGTH) == TDI_TRANSPORT_ADDRESS_LENGTH)) {
|
||||
/* This is a request to open an address */
|
||||
CP
|
||||
|
||||
|
@ -232,9 +240,12 @@ CP
|
|||
Context->Handle.AddressHandle = Request.Handle.AddressHandle;
|
||||
}
|
||||
CP
|
||||
} else if ((EaInfo->EaNameLength == TDI_CONNECTION_CONTEXT_LENGTH) &&
|
||||
(RtlCompareMemory(&EaInfo->EaName, TdiConnectionContext,
|
||||
TDI_CONNECTION_CONTEXT_LENGTH) == TDI_CONNECTION_CONTEXT_LENGTH)) {
|
||||
} else if (EaInfo &&
|
||||
(EaInfo->EaNameLength == 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 */
|
||||
CP
|
||||
/* Parameter checks */
|
||||
|
@ -264,10 +275,11 @@ CP
|
|||
}
|
||||
} else {
|
||||
/* This is a request to open a control connection */
|
||||
|
||||
TI_DbgPrint(MIN_TRACE, ("Control connections are not implemented yet\n"));
|
||||
|
||||
Status = STATUS_NOT_IMPLEMENTED;
|
||||
Status = FileOpenControlChannel(&Request);
|
||||
if (NT_SUCCESS(Status)) {
|
||||
IrpSp->FileObject->FsContext2 = (PVOID)TDI_CONTROL_CHANNEL_FILE;
|
||||
Context->Handle.ControlChannel = Request.Handle.ControlChannel;
|
||||
}
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
|
@ -594,10 +606,12 @@ TiDispatch(
|
|||
/* See if this request is TCP/IP specific */
|
||||
switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {
|
||||
case IOCTL_TCP_QUERY_INFORMATION_EX:
|
||||
TI_DbgPrint(MIN_TRACE, ("TCP_QUERY_INFORMATION_EX\n"));
|
||||
Status = DispTdiQueryInformationEx(Irp, IrpSp);
|
||||
break;
|
||||
|
||||
case IOCTL_TCP_SET_INFORMATION_EX:
|
||||
TI_DbgPrint(MIN_TRACE, ("TCP_SET_INFORMATION_EX\n"));
|
||||
Status = DispTdiSetInformationEx(Irp, IrpSp);
|
||||
break;
|
||||
|
||||
|
@ -813,7 +827,8 @@ DriverEntry(
|
|||
}
|
||||
|
||||
/* 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)) {
|
||||
TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
|
||||
TiUnload(DriverObject);
|
||||
|
@ -825,6 +840,7 @@ DriverEntry(
|
|||
EntityList[1].tei_entity = CL_TL_ENTITY;
|
||||
EntityList[1].tei_instance = 0;
|
||||
EntityCount = 2;
|
||||
EntityMax = MAX_TDI_ENTITIES;
|
||||
|
||||
/* Use direct I/O */
|
||||
IPDeviceObject->Flags |= DO_DIRECT_IO;
|
||||
|
|
Loading…
Reference in a new issue