Packet Injection Functions
A callout driver can call the following WFP functions to inject pended or modified packet data into the TCP/IP stack. The applicable layers from which data can be injected, together with possible destinations, are listed in the following table.
Injection function | Applicable layer | Destination |
---|---|---|
network layer |
the forwarding data path |
|
network layer |
the receive data path |
|
network layer |
the send data path |
|
packet data from the transport, datagram data, ICMP error, or ALE layers |
the receive data path |
|
packet data from the transport, datagram data, ICMP error, or ALE layers |
the send data path |
|
TCP data segments |
a data stream |
In addition, the FwpsQueryPacketInjectionState0 function is used to inspect the injection history of packet data.
Cross-layer injection is enabled if the callout can supply all needed information that is required by the injection function, and the net buffer list has the format expected by the injection function. For example, a callout can capture a packet at the forward path, modify its destination address to that of the local computer, and call FwpsInjectTransportReceiveAsync0 to redirect the packet into the local computer's TCP/IP stack.
Except for the stream (TCP data) injection, injected incoming packets reenter from the "bottom" of the stack and WFP layers, while injected outgoing packets reenter from the "top" of the stack and WFP layers. For example, a UDP packet injected from the incoming datagram data layer will reenter the stack and traverse the network layer, the transport layer, the ALE receive or accept layer (optional), and back into the datagram data layer. Another UDP packet injected from the outgoing network layer will reenter the stack and traverse the ALE (optional), datagram data, and transport layers, and back to the network layer.
FwpsInjectTransportReceiveAsync0 automatically bypasses IPsec processing for the reinjected packet because it had previously gone through IPsec verification.
A packet injected by a WFP callout driver will be re-indicated to the callout except in the cases in which modification to the packet causes it to miss the original filter conditions. WFP provides the FwpsQueryPacketInjectionState0 function for callouts to query whether the packet was injected (or injected earlier) by the callout. To prevent infinite looping, callouts should permit self-injected packets.
Callouts must adjust the IP or transport layer checksum, or both, after they modify an IP packet. A callout can set the checksum to 0 for UDP over IPv4 packets. To be compatible with transport layer checksum offload, and to adjust the full checksum versus pseudo checksum calculations accordingly, a callout can use the following logic:
NDIS_TCP_IP_CHECKSUM_PACKET_INFO ChecksumInfo;
ChecksumInfo.Value =
(ULONG) (ULONG_PTR)NET_BUFFER_LIST_INFO(
NetBufferList,TcpIpChecksumNetBufferListInfo);
If ChecksumInfo.Transmit.NdisPacketTcpChecksum is TRUE, the TCP send operation will be offloaded. If ChecksumInfo.Transmit.NdisPacketUdpChecksum is TRUE, the UDP send operation will be offloaded.
In Windows Vista with Service Pack 1 (SP1) and Windows Server 2008, if inMetaValues->headerIncludeHeaderLength is greater than 0, the outgoing packet is a RAW send reinjection that includes an IP header. To perform RAW send reinjections that include an IP header for Windows Vista with SP1 and Windows Server 2008, you must retreat the cloned packet by the amount in inMetaValues->headerIncludeHeaderLength and copy the inMetaValues->headerIncludeHeader over the newly extended space. Then, use FwpsInjectTransportSendAsync0 with the net buffer list for the packet and leave the FWPS_TRANSPORT_SEND_PARAMS0 parameter set to NULL. For more information about retreat operations for net buffer lists, see Retreat and Advance Operations.
Note For raw send operations, the net buffer list must contain only a single net buffer. If your net buffer list contains more than one net buffer, you have to convert your net buffer list to a series of net buffer lists, and each in the series must contain a single net buffer. For more information about net buffer list management, see NET_BUFFER Architecture.