Actually, you would be writing a TDI Client - not a driver. There is
sample code in the DDK.
But what you probably want to do is write an NDIS driver - that would allow
you to listen to any network traffic to any
NIC that the NDIS driver is bound to.
Here is some code
(example only) that will allow you to get your local IP Address.
The sample code from the DDK is in DDK\SRC\FileSys\Rdr2\Supplied\RxCE.
You can also get sample TDI Client code from www.osr.com
Look in the DDK for TDI Client information.
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
NTSTATUS CDispatchTable::TdiOpenTransport( IN PWSTR pProtocol, IN USHORT
wPort)
{
CTcpAddress::IP_TRANSPORT_ADDRESS* pAddress; // transport
address
ULONG dEaLength; //
buffer size
PFILE_FULL_EA_INFORMATION pEaInfo; // pointer to
ea
NTSTATUS dStatus; // current
status
dEaLength = sizeof ( FILE_FULL_EA_INFORMATION ) + //
account for ea
sizeof ( TdiTransportAddress ) + //
account for transport
sizeof ( CTcpAddress::IP_TRANSPORT_ADDRESS ) + 1; //
account for ip address
pEaInfo = (PFILE_FULL_EA_INFORMATION)ExAllocatePool ( NonPagedPool,
dEaLength );
if ( pEaInfo ) //
validate pointer
{
RtlZeroMemory ( pEaInfo, dEaLength ); //
clear eabuffer
pEaInfo->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH; //
size
RtlCopyMemory ( pEaInfo->EaName, //
copy transport name
TdiTransportAddress,
sizeof ( TdiTransportAddress ) );
pEaInfo->EaValueLength = sizeof ( TA_IP_ADDRESS ); //
size of data
pAddress = (CTcpAddress::IP_TRANSPORT_ADDRESS*)(
pEaInfo->EaName +
sizeof (
TdiTransportAddress ));
pAddress->TAAddressCount = 1; //
number of addresses
pAddress->Address[0].AddressLength = sizeof ( TDI_ADDRESS_IP );
pAddress->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
pAddress->Address[0].ipAddr.sin_port = //
local port
W_LITTLE_TO_BIG_ENDIAN(wPort);
pAddress->Address[0].ipAddr.in_addr = 0L; //
local address
dStatus = TdiOpen (pProtocol, // tdi device
name
dEaLength, // length of
ea info
pEaInfo, //
pointer to ea info
&m_hTdiTransport, // return transport
handle
&m_pTdiTransportFileObject );// return transport
object
if ( NT_SUCCESS ( dStatus ) ) // check for valid return
{
m_LocalPort = W_LITTLE_TO_BIG_ENDIAN(wPort);
}
else
{
m_LocalPort = 0;
}
ExFreePool ( pEaInfo ); // free buffer
}
return ( dStatus );
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
NTSTATUS CDispatchTable::TdiOpen ( IN PWSTR
pProtocol,
IN ULONG
dEaLength,
IN PFILE_FULL_EA_INFORMATION
pEaInfo,
OUT PHANDLE
phHandle,
OUT PFILE_OBJECT*
ppObject )
{
UNICODE_STRING uName; // local name
OBJECT_ATTRIBUTES ObjectAttrib; // local object attribute
IO_STATUS_BLOCK IoStatusBlock; // local io status return
NTSTATUS dStatus; // current status
RtlInitUnicodeString ( &uName, pProtocol ); // get device
name
InitializeObjectAttributes( &ObjectAttrib, // return
object attribute
&uName, //
resource name
OBJ_CASE_INSENSITIVE, //
attributes
NULL, //
root directory
NULL ); //
security descriptor
dStatus = ZwCreateFile ( phHandle, //
return file handle
GENERIC_READ | GENERIC_WRITE,
// desired access
&ObjectAttrib,
// local object attribute
&IoStatusBlock,
// local io status
0L,
// initial allocation size
FILE_ATTRIBUTE_NORMAL,
// file attributes
FILE_SHARE_READ |
FILE_SHARE_WRITE, // share access
FILE_OPEN_IF,
// create disposition
0L,
// create options
pEaInfo,
// eabuffer
dEaLength );
// ealength
if ( NT_SUCCESS ( dStatus ) ) // check for valid return
{
dStatus = ObReferenceObjectByHandle ( *phHandle,
// handle to open file
FILE_ALL_ACCESS, // access mode
NULL,
// object type
KernelMode,
// access mode
(void**)ppObject, // pointer to object
NULL );
// handle information
if ( !NT_SUCCESS ( dStatus ) )
{
ZwClose ( *phHandle ); // close handle
m_hLocalIP = 0;
}
else
{
m_hLocalIP = *phHandle;
}
}
return ( dStatus );
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
NTSTATUS CDispatchTable::TdiQueryAddress( IN PFILE_OBJECT pObject,
IN PULONG pdAddress
)
{
ULONG i, j;
// local loop control
TDIEntityID* pEntityBuffer = NULL;
// buffer for ENTITY_LIST_ID
ULONG dEntityCount;
// number of entities
ULONG dEntityType;
// entity type
IPSNMPInfo SnmpInfo;
// ip information
CTcpAddress::IPAddrEntry* pIpAddress = NULL;
// ip address buffer
ULONG dBufferSize =
MAX_FAST_ENTITY_BUFFER ; // buffer length
NTSTATUS dStatus =
STATUS_INVALID_PARAMETER; // local status
*pdAddress = 0L;
for ( j = 0; j < 2; j++ )
{
pEntityBuffer = (TDIEntityID *)ExAllocatePool ( NonPagedPool,
dBufferSize );
if ( pEntityBuffer == NULL ) //
validate pointer
{
DbgPrint ( “ERROR: ExAllocatePoolWithTag\n” );
dStatus = STATUS_INSUFFICIENT_RESOURCES;
break;
}
else
{
// ********************************************
// 1-Query device for entity buffer
// ********************************************
dStatus = TdiQueryInformationExEntry ( pObject,
// control object
GENERIC_ENTITY, // entity
TL_INSTANCE, // instance
INFO_CLASS_GENERIC, // class
INFO_TYPE_PROVIDER, // type
ENTITY_LIST_ID, // id
pEntityBuffer, // output buffer
&dBufferSize ); // output buffer size
if ( dStatus == STATUS_BUFFER_TOO_SMALL ) //
check for a buffer error
{
DbgPrint ( “ERROR: Buffer too small\n”, dStatus );
ExFreePool ( pEntityBuffer );
// free buffer
pEntityBuffer = NULL;
}
else
{
if ( !NT_SUCCESS ( dStatus ) )
// check return code
DbgPrint ( “ERROR: Unable to get entity\n”,
dStatus );
break;
}
}
}
// *********************************
// Scan the entities looking for IP.
// *********************************
if ( NT_SUCCESS ( dStatus ) )
{
dEntityCount = dBufferSize / sizeof ( TDIEntityID ); //
determine number of entities
for ( i = 0; i < dEntityCount; i++ ) //
loop through all of them
{
// ********************************************
// 2-Query device for entity type
// ********************************************
if ( pEntityBuffer[i].tei_entity == CL_NL_ENTITY )
{
dBufferSize = sizeof ( dEntityType );
// store buffer size
if ( NT_SUCCESS ( dStatus ) )
// validate pointer
{
dStatus = TdiQueryInformationExEntry ( pObject,
// control object
CL_NL_ENTITY, // entity
pEntityBuffer[i].tei_instance,// instance
INFO_CLASS_GENERIC, // class
INFO_TYPE_PROVIDER, // type
ENTITY_TYPE_ID, // id
&dEntityType, // output buffer
&dBufferSize ); // output buffer size
if ( !NT_SUCCESS ( dStatus ) || ( dEntityType !=
CL_NL_IP ) ) // check for IP entity type
DbgPrint ( “ERROR: Unable to get entity
type\n”, dStatus );
}
// ***************************************
// 3-Query device for snmp info.
// We found an IP entity. Now lookup its
// addresses. Start by querying the number
// of addresses supported by this interface.
// ***************************************
if ( NT_SUCCESS ( dStatus ) )
{
dBufferSize = sizeof ( SnmpInfo ); // store
buffer size
dStatus = TdiQueryInformationExEntry ( pObject,
// control object
CL_NL_ENTITY, // entity
pEntityBuffer[i].tei_instance,// instance
INFO_CLASS_PROTOCOL, // class
INFO_TYPE_PROVIDER, // type
IP_MIB_STATS_ID, // id
&SnmpInfo, // output buffer
&dBufferSize ); // output buffer size
if ( !NT_SUCCESS ( dStatus ) || (
SnmpInfo.ipsi_numaddr == 0 ) )
DbgPrint ( “ERROR: Unable to get snmp\n”,
dStatus );
}
// ***************************************
// 4-Query device for all ip addresses
// ***************************************
if ( NT_SUCCESS ( dStatus ) )
{
dBufferSize = SnmpInfo.ipsi_numaddr * sizeof (
CTcpAddress::IPAddrEntry );
for ( j = 0; j < 2; j++ )
{
pIpAddress = (CTcpAddress::IPAddrEntry
*)ExAllocatePool ( NonPagedPool,
dBufferSize );
if ( pIpAddress == NULL )
{
DbgPrint ( “ERROR:
ExAllocatePoolWithTag\n” );
dStatus = STATUS_INSUFFICIENT_RESOURCES;
break;
}
else
{
dStatus = TdiQueryInformationExEntry (
pObject, // control object
CL_NL_ENTITY, // entity
pEntityBuffer[i].tei_instance, // instance
INFO_CLASS_PROTOCOL, // class
INFO_TYPE_PROVIDER, // type
IP_MIB_ADDRTABLE_ENTRY_ID, // id
pIpAddress, // output buffer
&dBufferSize ); // output buffer size
if ( dStatus == STATUS_BUFFER_TOO_SMALL
) // check for a buffer error
{
DbgPrint ( “ERROR: Buffer too
small\n”, dStatus );
ExFreePool ( pIpAddress );
// free buffer
pIpAddress = NULL;
// reset pointer
}
else
{
if ( !NT_SUCCESS ( dStatus ) )//
check return code
{
DbgPrint ( “ERROR: Unable to
get address\n”, dStatus );
}
else
{
if ( pdAddress )
{
// store real ip address
*pdAddress =
pIpAddress->iae_addr;
}
}
break; // break for loop
}
}
}
}
}
}
}
if ( pEntityBuffer ) // validate
pointer
ExFreePool ( pEntityBuffer ); // free buffer
if ( pIpAddress ) // validate
buffer
ExFreePool ( pIpAddress ); // free buffer
if ( NT_SUCCESS ( dStatus ) && ( *pdAddress == 0L ) )
dStatus = STATUS_INVALID_PARAMETER;
return ( dStatus ); // return with status
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
NTSTATUS CDispatchTable::TdiQueryDeviceControl ( IN PFILE_OBJECT
pObject,
IN
ULONG dIoControlCode,
IN
PVOID InputBuffer,
IN
ULONG InputBufferSize,
IN OUT
PVOID OutputBuffer,
IN
ULONG OutputBufferSize,
OUT
PULONG pdReturn )
{
PIRP pIrp; //
local i/o request
PIO_STACK_LOCATION pIoStack; // I/O
Stack Location
PDEVICE_OBJECT pDeviceObject; //
local device object
IO_STATUS_BLOCK IoStatusBlock;
// return status
NTSTATUS dStatus = STATUS_INVALID_PARAMETER;
// default return status
if ( pObject )
{
pDeviceObject = IoGetRelatedDeviceObject ( pObject ); //
get device object
KEVENT kEvent; //
signaling event
KeInitializeEvent ( &kEvent, NotificationEvent, FALSE ); //
reset notification event
pIrp = IoBuildDeviceIoControlRequest ( dIoControlCode,
pDeviceObject,
InputBuffer,
InputBufferSize,
OutputBuffer,
OutputBufferSize,
FALSE,
&kEvent,
// pointer to event
&IoStatusBlock
); // pointer to return buffer
if ( pIrp == NULL )
{
DbgPrint ( “ERROR: IoBuildDeviceIoControlRequest\n” );
dStatus = STATUS_INSUFFICIENT_RESOURCES;
}
else
{
pIoStack = IoGetNextIrpStackLocation ( pIrp );
// get the iostack
pIoStack->DeviceObject = pDeviceObject;
// store current device object
pIoStack->FileObject = pObject;
// store file object in the stack
dStatus = IoCallDriver ( pDeviceObject, pIrp );
// call next driver
if ( dStatus == STATUS_PENDING )
// make all request synchronous
{
(void)KeWaitForSingleObject ( (PVOID)&kEvent,
// signaling object
Executive,
// wait reason
KernelMode,
// wait mode
TRUE,
// alertable
NULL );
// timeout
}
if ( pdReturn )
// requested by user?
*pdReturn = IoStatusBlock.Information;
// return information size
}
}
return ( dStatus ); //
return with status
}
xxxxx@lists.osr.com on 08/07/2000 05:25:07 AM
Please respond to “NT Developers Interest List”
To: “NT Developers Interest List”
cc:
Subject: [ntdev] TDI drivers question
Hello everybody!
I have a problem, and I hope someone might be able to help…
I need a driver that “listens” to the network.
Well, it’s NOT a snoop or something like this - I want it
to listen ONLY to IP packets that are designated for the
machine.
In addition, I need it to be able to work on any layer below 3
(i.e.: it should work with modem, ISDN, Ethernet, token ring etc.)
For this reason, I thought to “bind” my driver on top of the TCP/IP stack,
as a TDI driver. I thought that doing so will make me talk to the TCP/IP
stack
only, using the common API, and I won’t need to bother about low-level
protocols.
My questions:
1. Is it possible?
2. Will I see all the IP frames aimed to me? (Note: I want these packets
to arrive BOTH to my TDI driver AND to the application they were
designated to
3. If it’s impossible - what’s the best way to do so?
4. Does anybody have a sample code?
thanks in advance,
- Barak Mandelovich
------------------------------------------------------------------------
Barak Mandelovich xxxxx@mercury.co.il
Mercury Interactive ltd.
------------------------------------------------------------------------
—
You are currently subscribed to ntdev as: xxxxx@miramarsys.com
To unsubscribe send a blank email to $subst(‘Email.Unsub’)