I’m writing an NDIS intermediate driver. It’s job is to intercept IPSec packets (outbound),
wrap them in a new ip/udp header and direct them back up the stack to a listening port
on the local machine.
The filtering is based on the Mr. Divines packet blocking sample.
Presently, I examine the ip src/dest for all outbound ipsec packets, and if a match exists,
the function returns a divert signal.
I then allocate a new packet, and ndisallocatememwithtag for the packetsize + sizeof( ip_header)
- sizeof( udp_header).
Once memory is allocated, I call ndisallocatebuffer on a private buffer pool I instantiate when the
driver is initialized.
I’m using ndiscopyfrompackettopacket to transfer the eth header to the beginning of the packet,
and using cast pointers to IP_HEADER and UDP_HEADER onto the area just after the eth header,
I fill in the info for the headers.
I then use ndiscopyfrompackettopacket to transfer the payload data into the remaining buffer.
After all that is done, I use ndismindicaterecievepacket to indicate the packet up.
However I’m not seeing the packet arrival using a UDP port listener? And I get erratic system
behavior after uninstalling the driver.
Here are the relevant sections of code, please help as this is my first attempt at writing a driver,
and unfortunately, I’m NOT very proficient with C, which is compounding my frustration. If anyone
can direct me to samples on originating packets from within an IM driver, that would be of great
help.
This code resides in the MPSEND function. I have noticed that the driver registers MPSENDPACKETS
rather than MPSend, so right off the bat I’m guessing I’ll have to copy the code into MPSENDPACKETS.
But before I do I need to know if I’m doing everything properly to craft a packet in the driver and have it
flow up to the application layer properly.
typedef struct mypacket
{
ETH_HEADER ethHdr;
IP_HEADER ipHdr;
UDP_HEADER udpHdr;
char data[0];
} MY_PACKET, *PMY_PACKET, **HMY_PACKET;
if( SndDivertAction == SND_FLT_DIVERT_PACKET )
{
FltReadOnPacket(
Packet,
&oldethHdr,
sizeof( ETH_HEADER ),
0,
&NumberOfBytesRead
);
if( NumberOfBytesRead != sizeof( UDP_HEADER ) )
{
return NDIS_STATUS_RESOURCES;
}
FltReadOnPacket(
Packet,
&oldipHdr,
sizeof( IP_HEADER ),
sizeof( ETHER_HDR_LEN ),
&NumberOfBytesRead
);
if( NumberOfBytesRead != sizeof( IP_HEADER ) )
{
return NDIS_STATUS_RESOURCES;
}
//
// Aloocate a new packet from the received pool
//
NdisDprAllocatePacket(&Status,
&DivertPacket,
pAdapt->RecvPacketPoolHandle);
if(Status == NDIS_STATUS_SUCCESS)
{
PSEND_RSVD DivertRsvd;
DivertRsvd = (PSEND_RSVD)(DivertPacket->MiniportReserved);
DivertRsvd->OriginalPkt = Packet;
pFilterContext = (PADAPT_FILTER_RSVD )&pAdapt->FilterReserved;
//
// Allocate a memory pool and copy the packet buffer data
//
NdisQueryPacket(Packet, &oldPhysicalBufferCount, &oldBufferCount, &poldFirstBuffer, &oldPacketLength);
DivertPacketLength = oldPacketLength + sizeof( IP_HEADER ) + sizeof( UDP_HEADER );
NdisAllocateMemoryWithTag(&pDivertVa, DivertPacketLength, TAG );
NdisAllocateBuffer(&Status,
&pDivertBuffer,
DivertBufferPool,
pDivertVa,
DivertPacketLength
);
if (Status == NDIS_STATUS_SUCCESS)
{
//
//New packet allocation is success
//Begin transferring data to new packet
//
// Copy Ether Header
//
#ifdef NDIS51
NdisCopyFromPacketToPacketSafe(DivertPacket,
0,
sizeof( ETH_HEADER ),
Packet,
0,
&BytesCopied,
NormalPagePriority
);
#else
NdisCopyFromPacketToPacket(DivertPacket,
0,
sizeof( ETH_HEADER ),
Packet,
0,
&BytesCopied
);
#endif
if(BytesCopied == sizeof( ETH_HEADER ))
{
//
// Prepare the new ip header
//
ipHdr = &pDivertVa->ipHdr;
ipHdr->ip_v = 4;
ipHdr->ip_hl = 0x05;
ipHdr->ip_tos = 0;
ipHdr->ip_p = 17;
ipHdr->ip_ttl = 0;
ipHdr->ip_id = pAdapt->PacketID;
ipHdr->ip_id++;
ipHdr->ip_off = 0;
ipHdr->ip_dst.S_un.S_addr = oldipHdr.ip_src.S_un.S_addr;
ipHdr->ip_src.S_un.S_addr = oldipHdr.ip_dst.S_un.S_addr;
ipHdr->ip_len = oldipHdr.ip_len + sizeof( IP_HEADER ) + sizeof( UDP_HEADER );
ipHdr->ip_sum = 0;
//
// Prepare the new udp header
//
udpHdr = &pDivertVa->udpHdr;
udpHdr->uh_sport = pFilterContext->DivertPort;
udpHdr->uh_dport = pFilterContext->DivertPort;
udpHdr->uh_ulen = oldipHdr.ip_len + sizeof( UDP_HEADER ) ;
udpHdr->uh_sum = 0;
//
// Move remaining packet data
//
#ifdef NDIS51
NdisCopyFromPacketToPacketSafe(DivertPacket,
sizeof( MY_PACKET ),
oldPacketLength - sizeof( ETH_HEADER ),
Packet,
sizeof( ETH_HEADER ),
&BytesCopied,
NormalPagePriority
);
#else
NdisCopyFromPacketToPacket(DivertPacket,
sizeof( MY_PACKET ),
oldPacketLength - sizeof( ETH_HEADER ),
Packet,
sizeof( ETH_HEADER ),
&BytesCopied
);
#endif
if (BytesCopied == oldPacketLength - sizeof( ETH_HEADER ) )
{
NdisChainBufferAtFront(DivertPacket, pDivertBuffer);
//
// Set Packet Flags
//
NdisGetPacketFlags(DivertPacket) = NdisGetPacketFlags(Packet);
Status = NDIS_GET_PACKET_STATUS(Packet);
NDIS_SET_PACKET_HEADER_SIZE(DivertPacket, NDIS_GET_PACKET_HEADER_SIZE(Packet));
pChecksumFlags->Receive.NdisPacketIpChecksumFailed = 0;
pChecksumFlags->Receive.NdisPacketIpChecksumSucceeded = 1;
pChecksumFlags->Receive.NdisPacketTcpChecksumFailed = 0;
pChecksumFlags->Receive.NdisPacketTcpChecksumSucceeded = 0;
pChecksumFlags->Receive.NdisPacketUdpChecksumFailed = 0;
pChecksumFlags->Receive.NdisPacketUdpChecksumSucceeded = 1;
NDIS_PER_PACKET_INFO_FROM_PACKET(DivertPacket, TcpIpChecksumPacketInfo) = pChecksumFlags;
//
// Force protocols above to make a copy if they want to hang
// on to data in this packet. This is because we are in our
// Receive handler (not ReceivePacket) and we can’t return a
// ref count from here.
//
NDIS_SET_PACKET_STATUS(DivertPacket, NDIS_STATUS_RESOURCES);
//
// By setting NDIS_STATUS_RESOURCES, we also know that we can reclaim
// this packet as soon as the call to NdisMIndicateReceivePacket
// returns.
//
NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &DivertPacket, 1);
NdisFreeBuffer(pDivertBuffer);
NdisFreeMemory(pDivertVa, DivertPacketLength, 0);
NdisDprFreePacket(DivertPacket);
return NDIS_STATUS_SUCCESS;
}
else
{
return NDIS_STATUS_RESOURCES;
}
}
else
{
return NDIS_STATUS_RESOURCES;
}
}
}
else
{
//
// We are out of packets. Silently drop it.
//
return NDIS_STATUS_RESOURCES;
}
}