WFP: Loopback recv-reinjection failing

I?ve implemented a network packet inspection driver using the Windows
Filtering Platform (WFP).

Within this framework, I run into a problem whenever I attempt to
receive-inject out-of-band UDP data on Win7 at the transport layer. When
the original UDP/IP packets’ source and destination are both the loopback
IP ( i.e. 127.0.0.1), I get a STATUS_DATA_NOT_ACCEPTED in my completion
routine.

If I swap out both the source and destination IPs with my (one and only)
NIC?s IP (using a call to FwpsConstructIpHeaderForTransportPacket() before
invoking FwpsInjectTransportReceiveAsync()), I find my reinjected packet at
the INBOUND_IPPACKET_DISCARD layer with reason IpDiscardNotLocallyDestined.

If I swap only the destination IP with my NIC?s IP, the
FwpsConstructIpHeaderForTransportPacket() returns
STATUS_NETWORK_UNREACHABLE.

If I swap only the source IP with my NIC?s IP, the packet arrives at the
INBOUND_IPPACKET layer and is then swallowed by the system. It does not
show up at either the INBOUND_TRANSPORT, INBOUND_IPPACKET_DISCARD or
INBOUND_TRANSPORT_DISCARD layers.

What gives? This is perplexing because this re-injection scenario and all
else works just fine if either the source or destination IP addresses are
not localhost related.
Following is my current packet packet re-injection code. What can I change
for WFP or the TCP/IP stack to accept my reinjected ‘localhost’ packets?
NTSTATUS
CloneReinjectTransportInbound(
In PendedPacket* packet
)
{
NTSTATUS status;
NET_BUFFER_LIST* clonedNetBufferList = NULL;
NET_BUFFER* netBuffer;
LONG dataOffset;
UINT32 transportHeaderSize;
NDIS_STATUS ndisStatus;

// For inbound net buffer list, we can assume it contains only one net
buffer.
netBuffer = NET_BUFFER_LIST_FIRST_NB(packet->NetBufferList);
NT_ASSERT(NULL != netBuffer);
dataOffset = NET_BUFFER_DATA_OFFSET(netBuffer);

// According to MS: The TCP/IP stack could have retreated the net
buffer list by the
// ‘transport header size’ amount; detect the condition here to avoid
retreating twice.
transportHeaderSize = packet->TransportHeaderSize;
if (dataOffset != packet->DataOffset) {
transportHeaderSize = 0;
}

// Adjust the net buffer list offset to the start of the IP header.
ndisStatus = NdisRetreatNetBufferDataStart(
netBuffer, packet->IpHeaderSize + transportHeaderSize, 0, NULL);
#if (_MSC_VER >= 1700)
Analysis_assume(ndisStatus == NDIS_STATUS_SUCCESS);
#endif

status = FwpsAllocateCloneNetBufferList(
packet->NetBufferList, NULL, NULL, 0, &clonedNetBufferList);

// Undo the adjustment on the original net buffer list.
NdisAdvanceNetBufferDataStart(
netBuffer, packet->IpHeaderSize + transportHeaderSize, FALSE, NULL);

if (!NT_SUCCESS(status)) {
goto Exit;
}

// Special handling for loopback traffic.
if (0x7F == (packet->LocalAddr & 0xFF) && (0x7f == (packet->RemoteAddr
& 0xFF))) {
// Hard coded NIC for now.
UINT32 nicIp = 0xA877A8C0; // 192.168.119.168

status = FwpsConstructIpHeaderForTransportPacket(
clonedNetBufferList,
packet->IpHeaderSize,
AF_INET,
(UINT8*)&nicIp,
(UINT8*)&nicIp,
IPPROTO_UDP,
packet->EndpointHandle,
NULL,
0,
0,
NULL,
packet->InterfaceIndex,
packet->SubInterfaceIndex);
if (!NT_SUCCESS(status)) {
goto Exit;
}

// Send-inject the cloned net buffer list.
status = FwpsInjectTransportSendAsync(
gDriver->InjectionHandle,
NULL,
packet->EndpointHandle,
0,
NULL,
AF_INET,
packet->CompartmentId,
clonedNetBufferList,
InjectTransportComplete,
packet);
if (!NT_SUCCESS(status)) {
goto Exit;
}
} else {
status = FwpsInjectTransportReceiveAsync(
gDriver->InjectionHandle,
NULL,
NULL,
0,
AF_INET,
packet->CompartmentId,
packet->InterfaceIndex,
packet->SubInterfaceIndex,
clonedNetBufferList,
InjectTransportComplete,
packet);
if (!NT_SUCCESS(status)) {
goto Exit;
}
}

// Ownership transferred to the completion function.
clonedNetBufferList = NULL;
packet = NULL;

Exit:

if (clonedNetBufferList != NULL) {
FwpsFreeCloneNetBufferList(clonedNetBufferList, 0);
}

if (packet != NULL) {
FreePendedPacket(packet);
}

return status;
}

Thanks a lot for your help and patience!

Facing similar situation, Did you get any solution for this problem ?

You think the OP is still waiting for an answer? I’m sure he’s a patient guy and all, but he posted exactly once in this forum… six years ago.

Maybe it’s just me, but I kinda doubt that he’s checking here daily to see if someone has a reply for him.

Peter

Hi

inbound redirection:

→ You recieve on physical and send to loopback in usermode.
→ kernel wfp will see it as inbound to loopback

outbound redirection:

→ You cannot redirect to loopback.You have to send it to physical.
→ physical to loopback happens in usermode