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; 
 
}