Answered by:
NDIS loopback data not captured by application

Question
-
Hello there,
I am trying to get my NDIS concept clear by extending the example mux driver (NDIS) in WDDK.
I have created two miniport instance and given them two different IP address (A and C). My application sends data using A interface to a destination B reachable from that interface. I captured that packet & manipulate it to set the destination IP to another interface C. There is a server running at C interface. I have traced the packet and it shows that it is sending from A -> C interface.
Now the problem is that, the application cannot recognize that packet.
I am using an UDP server client application.
I have also updated the IP header checksum and UDP checksum so that the tcp/ip stack validates the packet. But for reason it is not reaching to my server application. Can anyone suggest me what can be wrong?
Thanks in advance & sorry for my English.
fadedreamzThursday, March 31, 2011 7:59 PM
Answers
-
You probably need to change the MAC address as well! We had code in an NDIS IM driver that would redirect outbound packets to a localhost application, in the ip header we swapped the source and dest addresses (so it looked like the packet was inbound) and then we called the ndis function to indicate the packet back up the stack. The packet never got to the user mode app ... it showed up in the packet capture ok but it was being dropped by ip (I think we saw this by running netstat -s). We then swapped the mac addresses in the ethernet header and then it worked.
I suggest ...
run netstat -s to see if there are any UDP drops
set the destination MAC address to the MAC address of your C interface ... I think this will fix it ... at the ndis miniport level there is no mac address resolution ... your packet must have the correct destination ip address AND destination MAC address to reach its destination.
- Proposed as answer by Mirage2k2 Friday, April 1, 2011 3:28 AM
- Marked as answer by fadedreamz Wednesday, September 28, 2011 7:06 AM
Friday, April 1, 2011 3:27 AM
All replies
-
You probably need to change the MAC address as well! We had code in an NDIS IM driver that would redirect outbound packets to a localhost application, in the ip header we swapped the source and dest addresses (so it looked like the packet was inbound) and then we called the ndis function to indicate the packet back up the stack. The packet never got to the user mode app ... it showed up in the packet capture ok but it was being dropped by ip (I think we saw this by running netstat -s). We then swapped the mac addresses in the ethernet header and then it worked.
I suggest ...
run netstat -s to see if there are any UDP drops
set the destination MAC address to the MAC address of your C interface ... I think this will fix it ... at the ndis miniport level there is no mac address resolution ... your packet must have the correct destination ip address AND destination MAC address to reach its destination.
- Proposed as answer by Mirage2k2 Friday, April 1, 2011 3:28 AM
- Marked as answer by fadedreamz Wednesday, September 28, 2011 7:06 AM
Friday, April 1, 2011 3:27 AM -
You probably need to change the MAC address as well! We had code in an NDIS IM driver that would redirect outbound packets to a localhost application, in the ip header we swapped the source and dest addresses (so it looked like the packet was inbound) and then we called the ndis function to indicate the packet back up the stack. The packet never got to the user mode app ... it showed up in the packet capture ok but it was being dropped by ip (I think we saw this by running netstat -s). We then swapped the mac addresses in the ethernet header and then it worked.
I suggest ...
run netstat -s to see if there are any UDP drops
set the destination MAC address to the MAC address of your C interface ... I think this will fix it ... at the ndis miniport level there is no mac address resolution ... your packet must have the correct destination ip address AND destination MAC address to reach its destination.
fadedreamzFriday, April 1, 2011 5:09 AM -
So the checksum calculation is wrong?
-- pa
fadedreamzFriday, April 1, 2011 5:37 AM -
I need more information ...
Are there 2 physical interfaces (1 for A and 1 for C) on the same machine? If there is then I'm not sure what happens when you send a packet from C to A at this level in the stack ... I guess the packet would leave your machine on interface A and then go to your switch (which would lookup the port for interface C) and then it would send the packet back to your machine and it would be received on interface C. I would imagine that if this is what happens (I'm not sure) then you would be able to do a packet capture on interface C and see the packet as an inbound packet. If you can then wireshark might tell you what is wrong with it.
Anyway, since you are using a MUX driver, I'm sure that there is some way that you can take the outgoing packet on interface A binding and route it (using internal bindings) to interface C binding ... I have never done this but this is what MUX drivers are for. I think it is simple (I may be wrong) ... when you have changed the addresses in your outbound packet and recalculated the checksums, do not send the packet using NdisSend(), but instead indicate the packet up the stack using NdisMIndicateReceivePacket() but use the interface C binding as the binding parameter in the function call, this will fool ndis into thinking that the packet arrived on interface C. Let me know how this goes.
Friday, April 1, 2011 5:50 AM -
I need more information ...
Are there 2 physical interfaces (1 for A and 1 for C) on the same machine? If there is then I'm not sure what happens when you send a packet from C to A at this level in the stack ... I guess the packet would leave your machine on interface A and then go to your switch (which would lookup the port for interface C) and then it would send the packet back to your machine and it would be received on interface C. I would imagine that if this is what happens (I'm not sure) then you would be able to do a packet capture on interface C and see the packet as an inbound packet. If you can then wireshark might tell you what is wrong with it.
Anyway, since you are using a MUX driver, I'm sure that there is some way that you can take the outgoing packet on interface A binding and route it (using internal bindings) to interface C binding ... I have never done this but this is what MUX drivers are for. I think it is simple (I may be wrong) ... when you have changed the addresses in your outbou nd packet and recalculated the checksums, do not send the packet using NdisSend(), but instead indicate the packet up the stack using NdisMIndicateReceivePacket() but use the interface C binding as the binding parameter in the function call, this will fool ndis into thinking that the packet arrived on interface C. Let me know how this goes.
fadedreamzFriday, April 1, 2011 6:08 AM -
So my educated guess was pretty good ... you are already doing what I suggested. If you are trying convince ndis that this packet has been recieved on interface C then you must call NdisMIndicateReceivePacket() with the binding context for interface C. You must also make the packet headers look right, so I guess your destination MAC address must be set to interface C MAC address ... but what about the source address? I guess this should be set to interface A MAC address, or perhaps you could set it to broadcast address ffff...
I dont know exactly what your problem is but I do know that this packet must 100% look like a genuine received network packet (all the addresses MAC,IP and UDP must be correct), and all the parameters in the call to NdisMIndicateReceivePacket() must be correct. I would try the broadcast address as the source MAC address.
You must also be careful about completion and freeing the packet etc. Are you still calling NdisMSendComplete()? You must do this to complete the sending of the original packet on interface A ... but if you do this at the wrong time then ndis may free the packet while you are still busy indicating it up on interface C (it might free up the chained buffers!). You should indicate the packet up with status == RESOURCES and then call NdisMSendComplete().
I recall that we had a bug with this type of thing and it turned out that modifying the send packet was not good enough because there was lots of "outbound" type data in the NDIS_PACKET structure. In the end we created a new (clean) NDIS_PACKET structure and chained the buffers from the send packet into this one. Afterwards we indicated up the new packet and this worked. This is worth a try!
My suspician is that you are doing most of it right but perhaps your packet is being overwritten because it got freed!
Finally, run your driver with driver verifier ... this way if you are doing something funny you may get a BSOD and then you can get to the bottom of the problem!
Good luck!
Friday, April 1, 2011 7:32 AM -
So my educated guess was pretty good ... you are already doing what I suggested. If you are trying convince ndis that this packet has been recieved on interface C then you must call NdisMIndicateReceivePacket() with the binding context for interface C. You must also make the packet headers look right, so I guess your destination MAC address must be set to interface C MAC address ... but what about the source address? I guess this should be set to interface A MAC address, or perhaps you could set it to broadcast address ffff...
I dont know exactly what your problem is but I do know that this packet must 100% look like a genuine received network packet (all the addresses MAC,IP and UDP must be correct), and all the parameters in the call to NdisMIndicateReceivePacket() must be correct. I would try the broadcast address as the source MAC address.
You must also be careful about completion and freeing the packet etc. Are you still calling NdisMSendComplete()? You must do this to complete the sending of the original packet on interface A ... but if you do this at the wrong time then ndis may free the packet while you are still busy indicating it up on interface C (it might free up the chained buffers!). You should indicate the packet up with status == RESOURCES and then call NdisMSendComplete().
I recall that we had a bug with this type of thing and it turned out that modifying the send packet was not good enough because there was lots of "outbound" type data in the NDIS_PACKET structure. In the end we created a new (clean) NDIS_PACKET structure and chained the buffers from the send packet into this one. Afterwards we indicated up the new packet and this worked. This is worth a try!
My suspician is that you are doing most of it right but perhaps your packet is being overwritten because it got freed!
Finally, run your driver with driver verifier ... this way if you are doing something funny you may get a BSOD and then you can get to the bottom of the problem!
Good luck!
fadedreamzFriday, April 1, 2011 10:00 AM -
I would create a new NDIS_PACKET, chain in the buffers from the send packet, indicate the new packet up the stack with the packet status == NDIS_STATUS_RESOURCES and with the MiniportAdapterHandle == interface C's handle, then complete the send on the send packet. The protocol will not free the buffers in the send packet until you have completed the send (NdisMSendComplete)Monday, April 4, 2011 6:23 AM
-
I would create a new NDIS_PACKET, chain in the buffers from the send packet, indicate the new packet up the stack with the packet status == NDIS_STATUS_RESOURCES and with the MiniportAdapterHandle == interface C's handle, then complete the send on the send packet. The protocol will not free the buffers in the send packet until you have completed the send (NdisMSendComplete)
Thank you Mirage2k2 for your reply. I tried your solution but still no luck. In MPSendPackets - Allocated new NDIS_PACKET, then NdisChainBufferAtFront & Back with that packet. Lastly set the status of the packet to NDIS_STATUS_RESOURCES. Then modified the buffer to manipulate the packet. And then send the packet using NdisSend. Now the problem is the packet is not received at the other interface (checked with omnipeek). will NDIS perform automatic loopback while sending the packet? I also set the NDIS_PACKET_LOOPBACK in the packet flag. What should I do send a packet to the PtReceive (i,e fake the NDIS that a packet has been received) from the MPSendPackets (from the function where actual packet sending occurs)? Thanks again & regards,
fadedreamzMonday, April 4, 2011 11:45 AM -
Dont send it with NdisSend(), indicate it up with NdisMIndicateReceivePacket() ... with MiniportAdapterHandle paramter == interface C'sTuesday, April 5, 2011 1:35 AM
-
Dont send it with NdisSend(), indicate it up with NdisMIndicateReceivePacket() ... with MiniportAdapterHandle paramter == interface C's miniport handle (check the ddk help on NdisMIndicateReceivePacket())Tuesday, April 5, 2011 1:35 AM
-
Thank you for your reply. Still the problem consists. I can see the packets been received to other interface via omnipeek. But the received packet does not reach the application layer. After some tries, I think I will take a step back and try to repeat the process again. I will update the post asap. Thank you all for your reply again. regards,
fadedreamzWednesday, April 6, 2011 9:52 AM