Modifying Incoming/Outgoing Packets using a NDIS IM Driver

Hey all,

Let me first say that I’m rather new to driver development, and most of the knowledge I have about NDIS IM driver is drawn from the PassThru and PassThruEx (part 2 specifically). So I apologize if my questions appear to be rather silly.

I’m trying to code an IM driver that will modify both incoming and outgoing packets (specifically, TCP packets; and it only modifies SOME packets). So far, by observing what’s written in PassThruEx part 2 (by Thomas), I am able to log each packet. As far as I know, from reading a few threads on this topic, that I’m not allowed to modify the content of the packet directly because I don’t have “owernship” of that packet. So a few questions I have are…

  1. Assembling a packet.
    Can I assemble a packet by copying the raw data out (as in, use NdisMoveMemory on each buffer), modify it (and update the checksum), and allocate buffers with the same sizes as the original buffers? Or does it depend on whether the packet modification changes the data? Note: the modification will NOT change the headers (other than checksum), only the data portion.

  2. ProtocolSendComplete.
    As a few mentioned on this forum/list, a modified outgoing packet should duplicate the original packet, modify it, report success on the original packet, and send the new one. Then on ProtocolSendComplete the copy packet must be freed and the original must be completed. If this is correct, how would I go about doing this? Should I use NDIS_SET_ORIGINAL_PACKET on the modified packet, so that when ProtocolSendComplete detects that the original packet is different, it would complete the original packet and free the modified packet? In other words, how would I know if a packet I get in ProtocolSendComplete is a modified packet, and how do I get a handle to the original packet to be completed?

  3. What about inbound packets?
    In the PtReceiveComplete function, individual packets are not even passed to the function. Does it mean that if I modified the packet in the same way as sending (copying, modifying, and indicating the modified packet up instead of the original one), I still have to free the modified packet and complete the original? If so, how do I get the handle to the packets?

Thanks in advance for any help!

See comments inline to your questions.

Good Luck,
-dave

David R. Cattley
Consulting Engineer
Systems Software Development

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@uab.edu
Sent: Wednesday, November 28, 2007 7:43 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] Modifying Incoming/Outgoing Packets using a NDIS IM Driver

Hey all,

Let me first say that I’m rather new to driver development, and most of the
knowledge I have about NDIS IM driver is drawn from the PassThru and
PassThruEx (part 2 specifically). So I apologize if my questions appear to
be rather silly.

I’m trying to code an IM driver that will modify both incoming and outgoing
packets (specifically, TCP packets; and it only modifies SOME packets). So
far, by observing what’s written in PassThruEx part 2 (by Thomas), I am able
to log each packet. As far as I know, from reading a few threads on this
topic, that I’m not allowed to modify the content of the packet directly
because I don’t have “owernship” of that packet. So a few questions I have
are…

  1. Assembling a packet.
    Can I assemble a packet by copying the raw data out (as in, use
    NdisMoveMemory on each buffer), modify it (and update the checksum), and
    allocate buffers with the same sizes as the original buffers? Or does it
    depend on whether the packet modification changes the data? Note: the
    modification will NOT change the headers (other than checksum), only the
    data portion.

[drc] Yes. There is not requirement that your new packet have the same
buffer sizes, etc. It is more common to allocate a single buffer of the
appropriate size and copy all of original packet data to it. The NIC does
not care if you coallesce the buffers sent by (in this case TCPIP.SYS) into
a single buffer. The only requirement is that the entire MAC header be in
the first buffer. Getting clever here is not necessary nor likely to buy
you anything other than headache.

  1. ProtocolSendComplete.
    As a few mentioned on this forum/list, a modified outgoing packet should
    duplicate the original packet, modify it, report success on the original
    packet, and send the new one. Then on ProtocolSendComplete the copy packet
    must be freed and the original must be completed. If this is correct, how
    would I go about doing this? Should I use NDIS_SET_ORIGINAL_PACKET on the
    modified packet, so that when ProtocolSendComplete detects that the original
    packet is different, it would complete the original packet and free the
    modified packet? In other words, how would I know if a packet I get in
    ProtocolSendComplete is a modified packet, and how do I get a handle to the
    original packet to be completed?

[drc] Yes, almost. Two things about what you said which I have issue with.
a) Don’t report the original packet as completed (via
NdisMSendComplete()) until the copy has completed. Your proposal above
seems to indicate you would complete the packet twice which would not be
very good. Only complete it when the copy has been completed (or canceled).
b) Don’t store the original packet in the
NDIS_SET_ORIGINAL_PACKET() structure. Instead, save it in the
ProtocolReserved area of the copy packet so that you can get it back during
ProtocolSendComplete() processing.

  1. What about inbound packets?
    In the PtReceiveComplete function, individual packets are not even passed to
    the function. Does it mean that if I modified the packet in the same way as
    sending (copying, modifying, and indicating the modified packet up instead
    of the original one), I still have to free the modified packet and complete
    the original? If so, how do I get the handle to the packets?

[drc] ProtocolReceiveComplete() is a kind of ‘status’ indication that says
that the (legacy) NIC has finished indicating packets. A protocol is
encouraged to defer processing any packets indicated by ProtocolReceive()
until a ProtocolReceiveComplete() occurs. Yes, you need to copy the
received packet into a new packet, modify the copy, and indicate the copy.
When the copy is returned, you can return the original packet - if there was
one! In the case of ProtocolRecieve() there is *not* an original packet
which is to be return via NdisReturnPackets(). Of course, you will keep
track of all of this in the MiniportReserved area of the copies for the RX
packets so again, when MiniportReturnPacket() is called, you can get the
original packet from the MiniportReserved area (if there was an original
packet, which, there might not be) and ‘return’ it with NdisReturnPackets().

Thanks in advance for any help!


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

> 1. Assembling a packet.

Can I assemble a packet by copying the raw data out (as in, use
NdisMoveMemory on each buffer), modify it (and update the checksum), and
allocate buffers with the same sizes as the original buffers?

Yes.

this? Should I use NDIS_SET_ORIGINAL_PACKET on the modified packet, so
that when ProtocolSendComplete detects that the original packet is different,

Usually ProtocolSendComplete uses the packet pool field of the packet to
distinguish between IM-allocated packet and upper-layer-allocated packet.

how would I know if a packet I get in ProtocolSendComplete is a modified
packet,

Use different packet pools.


Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com