www.pudn.com > IPsec_Src_Instal.rar > UtilRtns.c
#include "precomp.h"
#include "PktHdr.h"
/*
Copyright © 2003 Printing Communications Associates, Inc. (PCAUSA)
The right to use this code in your own derivative works is granted so long as
1. Your own derivative works include significant modifications of your own.
2. You retain the above copyright notices and this paragraph in its
entirety within sources derived from this code.
This product includes software developed by PCAUSA. The name of
PCAUSA may not be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE.
*/
/**************************************************************************************************/
/* */
/* Copy the payload of the specified packet into the specified buffer. */
/* */
/* Adapted from http://www.ndis.com/papers/ndispacket/readonpacket.htm, 12 May 2003. */
/* */
/**************************************************************************************************/
VOID
GetPktPayload(
PNDIS_PACKET pPacket, // Address of packet descriptor.
PUCHAR pOutBfr, // Address of output buffer, to get copied packet payload.
ULONG ulOutBfrAvail, // Size of output buffer.
PULONG pUlBytesCopied // Output variable for number of bytes copied.
)
{
PNDIS_BUFFER pNdisBfr;
ULONG ulBfrCnt,
ulTotPktLen,
ulCurrBfr,
ulAmtToMove;
PUCHAR pCurrBfr;
*pUlBytesCopied = 0; // Set 0 bytes copied.
if (0==ulOutBfrAvail) // Is output buffer 0 bytes in length?
goto Done;
NdisQueryPacket(pPacket, // Get information from packet descriptor.
NULL,
NULL,
&pNdisBfr, // Output variable for address of first buffer descriptor.
&ulTotPktLen // Output variable for number of bytes in packet payload.
);
NdisQueryBuffer(pNdisBfr, // Get information from first buffer descriptor.
&pCurrBfr, // Output variable for address of described virtual area.
&ulCurrBfr // Output variable for size of virtual area.
);
while (ulOutBfrAvail>0) // Space remaining in output buffer?
{
while (0==ulCurrBfr) // While the current buffer has zero length.
{
NdisGetNextBuffer(pNdisBfr, // Get next buffer descriptor.
&pNdisBfr
);
if (NULL==pNdisBfr) // None?
goto Done;
NdisQueryBuffer(pNdisBfr, // Get information from next buffer descriptor.
&pCurrBfr, // Output variable for address of current buffer.
&ulCurrBfr // Output variable for size of current buffer.
);
}
if (ulCurrBfr>ulOutBfrAvail) // Does current buffer's usable size exceed space remaining in output buffer?
ulAmtToMove = ulOutBfrAvail; // Use only amount remaining in output buffer.
else
ulAmtToMove = ulCurrBfr; // Use full size of current buffer.
NdisMoveMemory(pOutBfr, // Copy packet data to output buffer.
pCurrBfr,
ulAmtToMove
);
*pUlBytesCopied += ulAmtToMove; // Update output variable of bytes copied.
pOutBfr += ulAmtToMove; // Update pointer to output buffer.
ulOutBfrAvail -= ulAmtToMove; // Update number of bytes available in output buffer.
ulCurrBfr = 0; // Force search for next buffer.
} // End 'while' copy bytes to output buffer.
Done:
;
}
//****************************************************************************//
//* //
//* Copyright (C) 2003, James Antognini, antognini@mindspring.com. //
//* //
//****************************************************************************//
//****************************************************************************//
//* //
//* Derived from Ping.cpp in SDK Samples\netds\WinSock\Ping. //
//* //
//****************************************************************************//
USHORT
GetIPChecksum(PUSHORT IPH, USHORT IPHdr)
{
ULONG cksum = 0;
while (IPHdr > 1)
{
cksum += *IPH++;
IPHdr -= sizeof(USHORT);
}
cksum = (((cksum >> 16) | (cksum << 16)) + cksum) >> 16;
return (USHORT)~cksum;
}
/**************************************************************************************************/
/* */
/* Calculate TCP checksum, based on TCP datagram (TCP header + data) and pseudo-header. */
/* */
/* Derived in part from from RFC 1071, section 4.1, p 7, and in part from DDK \e100bex\offload.h. */
/* */
/* Notes: */
/* */
/* 1) This routine is written for a little-endian environment (eg, x86). It has been tested */
/* and used in WinXP user- and kernel-space environments. */
/* */
/* 2) This routine assumes the checksum field in the TCP header has been set to 0, in order */
/* to compute the checksum. */
/* */
/* 3) This routine, as is, cannot be used to check a checksum, because checking a checksum */
/* involves getting the one's complement sum over the TCP datagram, with the checksum */
/* included (see RFC 1071, p 1), but this routine does that summing and then returns the */
/* one's complement of that sum. That is, this routine will, if a checksum is correct, */
/* yield 0xffff in the folding statement below but then will return the one's complement */
/* of 0xffff, which is 0. */
/* */
/**************************************************************************************************/
/*
USHORT GetTCPChecksum(
PUSHORT TCPFd, // Pointer to TCP datagram (header + data).
PUSHORT SrcAddr, // Address of source IP address (in network format).
PUSHORT DestAddr, // Address of destination IP address (in network format).
USHORT TCPFdl // Length of TCP datagram (header + data).
)
{
#define lnPseudoHdr 12 // Size of pseudo-header.
char PseudoHdrArr[lnPseudoHdr]; // Pseudo-header.
USHORT PsHdr = lnPseudoHdr; // Length of pseudo-header.
PUSHORT PseudoHdr = (PUSHORT)PseudoHdrArr; // Pointer to pseudo-header.
ULONG sum = 0;
memcpy(PseudoHdrArr, SrcAddr, 4); // Copy source IP address.
memcpy(PseudoHdrArr+4, DestAddr, 4); // Copy destination IP address.
PseudoHdrArr[8] = 0; // Set to 0.
PseudoHdrArr[9] = IPPROTO_TCP; // Set to TCP protocol constant.
PseudoHdr[5] = (USHORT)(((TCPFdl & 0xFF00)>>8) + ((TCPFdl & 0x00FF)<<8)); // Put length of entire TCP datagram into pseudo-header.
// Do one's complement addition of pseudo-header.
while(PsHdr > 0)
{
sum += *PseudoHdr++;
PsHdr -= 2;
}
// Do one's complement addition of TCP field, except for the last byte if the field length is odd.
while(TCPFdl > 1)
{
sum += *TCPFd++;
TCPFd -= 2;
}
// Add left-over byte, if any.
if(TCPFd > 0)
sum += *(PUCHAR)TCPFd;
// Fold 32-bit sum to 16 bits
sum = (((sum >> 16) | (sum << 16)) + sum) >> 16;
// Return one's complement (in little-endian form, by the way).
return (USHORT)~sum;
}
*/
NDIS_STATUS
FilterPacket(
PADAPT pAdapt, // Address of adapter structure.
PNDIS_PACKET pPktDesc, // Address of NDIS_PACKET, if available. NULL if not.
PUCHAR pPayload, // Address of packet payload if NDIS_PACKET is NULL. Must contain at least the ethernet header and,
// if the type is IP, the IP header or, if the type is ARP or RARP, the ARP or RARP structure.
BOOLEAN bSend, // TRUE if Send, FALSE if Receive.
PBOOLEAN pBDecision // Address of boolean variable, whose value will be: TRUE => drop packet and FALSE => do not drop.
// But this is meaningful only if returned status is NDIS_STATUS_SUCCESS.
)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
#define szPayloadCopy ETH_MAX_PACKET_SIZE
UCHAR PayloadCopy[szPayloadCopy]; // Area to receive packet payload if NDIS_PACKET provided.
pEthHdr pETH;
pIPHdr pIPH;
ULONG IPAddr,ulOrigPayload;
*pBDecision = FALSE; // Default action is not to drop the packet.
do
{
if (NULL!=pPktDesc) // NDIS_PACKET provided?
{
GetPktPayload( pPktDesc, // Copy payload
PayloadCopy, // to area.
szPayloadCopy, // Amount of space in area.
&ulOrigPayload // Return number of bytes in packet.
);
}
else
{
NdisMoveMemory( PayloadCopy, // An IP packet (on ethernet) comprises the ethernet header + the IP header/body. An ARP or RARP packet
pPayload, // similarly comprises the ethernet header and the ARP or RARP body. Since the mapped IP header is 20
sizeof(EthHdr)+sizeof(IPHdr) // bytes and an ARP or RARP is 28 bytes, an amount = sizeof(EthHdr)+sizeof(IPHdr) is safely copied.
);
}
pETH = (pEthHdr)PayloadCopy; // Point to ethernet header.
if (EthHTypeIP!=RtlUshortByteSwap(pETH->Type)) // No IP header?
{
break; // Leave big 'do' group and do nothing more.
}
pIPH = (pIPHdr)(PayloadCopy + sizeof(EthHdr)); // Point to IP header in copy of payload.
if (TRUE==bSend) // Send operation?
IPAddr = pIPH->DestinationAddress; // Use destination IP address.
else
IPAddr = pIPH->SourceAddress;
if (IPAddr==RtlUlongByteSwap(0xC0A801C9)) // A hit? IP address 192.168.1.201
// Use different address for peers
{
*pBDecision = TRUE; // Indicate packet to be dropped.
break;
}
} while(0); // End big 'do' group.
return status;
}