Re: TDI driver event queueing

Tech-Archive recommends: Fix windows errors by optimizing your registry

From: serge (pserge77_at_ukr.net)
Date: 02/10/05


Date: Thu, 10 Feb 2005 17:58:29 +0200

Hello, Steve!

S> Have you considered using an NDIS IM
S> driver and queueing packets instead?

This is already done :)
Probably you rememer my NDIS IM related questions here some weeks ago.

I want to allow/deny incoming and outgoing connections on user level.
I can do so on NDIS IM level, but there is one problem:

Process name is unknown when SYN packet arrives. I can not provide user with
application name that attempts to connect to remote host, or accepts
incoming connection.

I can see two solutions:
(1) wait until system replies with SYN+ACK. This will be done in process
context, so we can get it's name.
(2) filter connections on TDI level.

As for (1) - I am not sure about security. Probably it's not not safe to
allow application to receive stand-alone SYN packet. Also, it's not clear
how to drop connection in this case (application sent SYN+ACK will be
waiting for ACK packet(s) from remote host....)

Also, I feel that TDI queueing is not very simple task, and it even may not
work on all Windows builds...

Best regards,
Serge.

You wrote on Wed, 9 Feb 2005 17:49:32 -0800:

 S> Firstly, your event is called by tcpip (when the event
 S> occurrs) not by the kernel-mode client. You call the
 S> kernel-mode client when you call the original handler
 S> (which is the clients handler).

 S> As for the BytesTaken and IoRequestPacket I am not sure
 S> how you can deal with them. They are pointers to
 S> variables that belong to tcpip. The client in its event
 S> handler would read the data received and inform tcpip how
 S> much it read in BytesTaken. Also, the client might
 S> allocate an irp for IoRequestPacket, this irp would be
 S> set up to receive any more available data. What you are
 S> attempting to do is very difficult. If your filter does
 S> nothing with BytesTaken and IoRequestPacket tcpip will
 S> assume that the client is not interested in the received
 S> data! You will have to process this event as if you were
 S> the client, i.e. read all data and set BytesTaken, and
 S> create irp for IoRequestPacket. This gets even trickier
 S> because then you will be responsible for this irp - you
 S> will need to register a completion routine for it, etc.

 S> When you dequeue and call the original client handler you
 S> will have to look and behave like tcpip, i.e. process any
 S> irp the client gives you in IoRequestPacket (i.e. copy
 S> data from the irp your filter created).

 S> Filtering in the tdi is very complicated, as you are
 S> finding. You are the middle man, to the client you must
 S> look and act like tcpip, to tcpip you must look and act
 S> like the client. Have you considered using an NDIS IM
 S> driver and queueing packets instead?

 S> Steve.

>> -----Original Message-----
>> Hello, Steve!
>>
>> I already created transparent TDI driver that filters
 S> all the events and
>> requests, so now I am moving towards queueing. Yes, I
 S> have seen tdi_fw
>> sources, thay are great as a start point.
>>
>> I can not understand one thing:
>> When kernel-mode client sends event to my TDI driver,
 S> does it want to get
>> reply immediately?
>> I can save input variables, and then call original event
 S> handler in my
>> worker thread, but what about output variables?
>>
>> In our example parameters BytesTaken and IoRequestPacket
 S> are output one.
>> Can I save these pointers and use them in my thread
 S> later?
>> Are these variables located in static memory?
>> I afraid I will receive BSOD when I try to write there
 S> something there from
>> my thread...
>>
>> Best regards,
>> Serge.
>>
>> You wrote on Wed, 9 Feb 2005 16:27:47 -0800:
>>
 S>>> TdiEventContext is the context that you supplied in
 S> the
 S>>> filter function for TDI_SET_EVENT_HANDLER. If you
 S> look at
 S>>> the example I gave you TdiEventContext is ...
 S>>> EventContext *filteredCtx;
>>
 S>>> You use this value to get back the original context
 S> and
 S>>> handler. If you call the original handler within
 S> your
 S>>> filtered handler your code will look something like
 S>>> this ...
>>
 S>>> EventContext *ctx = (EventContext*)TdiEventContext;
>>
 S>>> // call old handler with old context
 S>>> //
 S>>> return ((PTDI_IND_RECEIVE_DATAGRAM)(ctx-
>> oldEventHandler))
 S>>> (ctx->oldEventContext,
 S>>> SourceAddressLength,
 S>>> SourceAddress,
 S>>> OptionsLength,
 S>>> Options,
 S>>> ReceiveDatagramFlags,
 S>>> BytesIndicated,
 S>>> BytesAvailable,
 S>>> BytesTaken,
 S>>> Tsdu,
 S>>> IoRequestPacket);
>>
 S>>> I recommend that you firstly get the code working
 S> without
 S>>> queueing (i.e. call the original handler immediately
 S> in
 S>>> your filtered handler) ... this way you can ensure
 S> your
 S>>> filters are working correctly. Move on to queueing
 S>>> after ... this is something I have not tried so you
 S> will
 S>>> have to work that out. The help on
 S>>> ClientEventReceiveDatagram should answer most of your
 S>>> other questions.
>>
 S>>> There is a great example tdi firewall called tdi_fw
 S> that
 S>>> you should try to download
 S>>> http://sourceforge.net/projects/tdifw.
>>
 S>>> ps. you might have noticed there is a small bug in
 S> the
 S>>> example ...
 S>>> filteredCtx = ExAllocatePool(NonPagedPool, sizeof
 S>>> (TDI_EVENT_CONTEXT));
>>
 S>>> This should be ...
 S>>> filteredCtx = ExAllocatePool(NonPagedPool, sizeof
 S>>> (EventContext));
>>
 S>>> Steve
>>
>>>> -----Original Message-----
>>>> Hello, Steve!
>>>>
>>>> Thanks for the reply.
>>>> There are several moments that are not crear for me.
>>>> Almost all event callback functions have pointers as
 S>>> input parameters.
>>>> Do they point to static memory? Can I simply store
 S>>> pointers, or I must
>>>> allocate memory and copy original one?
>>>>
>>>> Can you clarify the following:
>>>>
>>>> //
>>>> // the callback function set via
 S> TDI_SET_EVENT_HANDLER
>>>> //
>>>> NTSTATUS tdi_event_receive_datagram(
>>>> //
>>>> // ** I do not know memory size pointed by
 S>>> TdiEventContext
>>>> IN PVOID TdiEventContext,
>>>> IN LONG SourceAddressLength,
>>>> IN PVOID SourceAddress,
>>>> IN LONG OptionsLength,
>>>> IN PVOID Options,
>>>> IN ULONG ReceiveDatagramFlags,
>>>> IN ULONG BytesIndicated,
>>>> IN ULONG BytesAvailable,
>>>> //
>>>> // ** does it point to static variable?
>>>> OUT ULONG *BytesTaken,
>>>> //
>>>> // ** memory size pointed by Tsdu is unknown?
>>>> IN PVOID Tsdu,
>>>> //
>>>> // ** do I need to store the pointer or the value?
>>>> OUT PIRP *IoRequestPacket)
>>>> {
>>>>
>>>> // adding to queue all the input parameters;
>>>>
>>>> //
>>>> // what value should I return exactly?
>>>> //
>>>> return STATUS_PENDING;
>>>> }
>>>>
>>>> void MyThread()
>>>> {
>>>> // here I will call old original event handler
>>>> // with parameters previously stored in queue.
>>>> // and then release allocated memory.
>>>> }
>>>>
>>>> Best regards,
>>>> Serge.
>>>>
>>>> You wrote on Tue, 8 Feb 2005 18:25:23 -0800:
>>>>
 S>>>>> Firstly, you will need to filter the events. With
 S>>>>> filtering in place, when an event is triggered on
 S> an
 S>>>>> address object your event filter function will get
 S>>>>> called, and then you can call the original event
 S>>>>> function, either immediately, or later if you are
 S>>>>> queueing.
>>>>
 S>>>>> To setup filtering events you must first filter the
 S>>>>> handler for TDI_SET_EVENT_HANDLER (as you filter
 S> any
 S>>>>> other IRP). A client that wants to register an
 S> event
 S>>>>> will send a TDI_SET_EVENT_HANDLER irp for a
 S>>> particular
 S>>>>> address object. This irp will contain an event
 S> type,
 S>>>>> handler and context. Here you patch in your
 S> handler
 S>>> (and
 S>>>>> context) and store away the original handler and
 S>>>>> context. You will need the original values so that
 S>>> when
 S>>>>> your event handler is called, you can then call the
 S>>>>> original handler. A typical way to store the
 S>>>>> originalvalues is to store them in your own event
 S>>> context.
>>>>
 S>>>>> Here is an example handler for
 S>>> TDI_SET_EVENT_HANDLER ...
>>>>
 S>>>>> typedef struct
 S>>>>> {
 S>>>>> PFILE_OBJECT fileobj; // address object
 S>>>>> PVOID oldEventHandler;
 S>>>>> PVOID oldEventContext;
>>>>
 S>>>>> } EventContext;
>>>>
 S>>>>> // -----------------------------------------------
 S> --
 S>>> -----
 S>>>>> ----------------------
 S>>>>> void SetEventHandler(PIRP irp, PIO_STACK_LOCATION
 S>>> irps)
 S>>>>> {
 S>>>>> PTDI_REQUEST_KERNEL_SET_EVENT event =
 S>>>>> (PTDI_REQUEST_KERNEL_SET_EVENT)&irps->Parameters;
 S>>>>> EventContext *filteredCtx;
>>>>
 S>>>>> filteredCtx = ExAllocatePool(NonPagedPool, sizeof
 S>>>>> (TDI_EVENT_CONTEXT));
>>>>
 S>>>>> // store original (client supplied) data
 S>>>>> //
 S>>>>> filteredCtx->fileobj = irps->FileObject; //
 S>>> address
 S>>>>> object
 S>>>>> filteredCtx->oldEventHandler = event-
>> EventHandler;
 S>>>>> filteredCtx->oldEventContext = event-
>> EventContext;
>>>>
 S>>>>> // patch in our data
 S>>>>> //
 S>>>>> event->EventHandler = filteredEventHandler; //
 S>>> this
 S>>>>> must point to a function
 S>>>>> //
 S>>> that
 S>>>>> has the same definition
 S>>>>> //
 S> as
 S>>> the
 S>>>>> event function you are
 S>>>>> //
 S>>>>> filtering
 S>>>>> event->EventContext = filteredCtx;
>>>>
 S>>>>> // now send IRP on down to lower driver ...
 S>>>>> }
>>>>
 S>>>>> If you need more help email me.
 S>>>>> Steve.
>>>>
>>>>>> -----Original Message-----
>>>>>> Hello,
>>>>>>
>>>>>> I can save IRP requests, and complete/cancel them
 S>>> later
 S>>>>> successfully.
>>>>>> But I want to queue events, set by
 S>>> TDI_SET_EVENT_HANDLER
 S>>>>> as well.
>>>>>>
>>>>>> Could anybody clarify how this can be done?
>>>>>>
>>>>>> Thanks!
>>>>>>
>>>>>> Best regards,
>>>>>> Serge.



Relevant Pages

  • Re: Please help with a serious issue
    ... does a filter statement on an adotable happen on the client machine or the ... >>User 1 selects customer 1. ... >>server db for all the clients. ...
    (borland.public.delphi.database.ado)
  • Re: Still Need desperate help to start with ASP NET - simplified problems - HELP!!
    ... You could do it as a web service. ... The handler can draw on the webservice for information and db lookup. ... IE posts data AJAX to handler on web server ... featured application (say thick client) which does a lot of complicate ...
    (microsoft.public.dotnet.framework.aspnet)
  • Re: 2 plans - 1 a sub set of another
    ... Dave Eade wrote: ... Putiing all client ... What I was hoping was that I could have a plan 'linked' to the main plan ... I don't just want to 'filter' one plan and show the Client, ...
    (microsoft.public.project)
  • Re: 2 plans - 1 a sub set of another
    ... Dave Eade wrote: ... paste into a new msp which is then passed onto the client. ... What I was hoping was that I could have a plan 'linked' to the main plan ... I don't just want to 'filter' one plan and show the Client, ...
    (microsoft.public.project)
  • [RFC 5/5] [TALPA] Userspace vetting of open and close access.
    ... Userspace vetting is an evaluation filter which passes vetting request ... Example vetting client which allows access to everything except one very ...
    (Linux-Kernel)