📄 cpgpnetfilteradapter.cpp
字号:
/*____________________________________________________________________________
Copyright (C) 2002 PGP Corporation
All rights reserved.
$Id: CPGPnetFilterAdapter.cpp,v 1.5 2002/08/06 20:10:26 dallen Exp $
____________________________________________________________________________*/
#include "pgpnetBase.h"
#include "pgpnetGlobal.h"
#include "pgpnetPacket.h"
#include "pgpnetPacketHelper.h"
#include "CPGPnetAdapter.h"
#include "CPGPnetFilterAdapter.h"
#include "pgpNetComm.h"
#include "pgpNetIPdef.h"
#include "pgpnetIpHelper.h"
#include "pgpKernelTiming.h"
/* PM includes */
#include "pgpNetPM.h"
#include "pgpNetWin32.h"
#include "CPGPnetDriver.h"
#include "CPGPnetFilterDriver.h"
#include "CPGPnetIPPacket.h"
#include "pgpnetDebug.h"
static PGPnetLastFragmentList*
LastFragmentListQuery(PGPnetLastFragmentList *list,
PGPUInt32 ipAddress,
USHORT ipId);
static PGPnetLastFragmentList*
LastFragmentListAdd(PGPnetLastFragmentList **list,
PGPUInt32 ipAddress,
USHORT ipId);
static VOID
LastFragmentListFree(PGPnetLastFragmentList **list,
PGPUInt32 ipAddress,
USHORT ipId);
static VOID
LastFragmentListFreeAll(PGPnetLastFragmentList *list);
VOID CPGPnetFilterAdapter::DoCfgEthernetTransform(PGPnetPacket *inPacket)
{
PGPnetPacket* packet = inPacket;
DBG_FUNC("DoCfgEthernetTransform");
while (packet != NULL) {
NdisMoveMemory((PCHAR)packet->xformBlock + 6, mHardwareAddress, 6);
packet = packet->link;
}
}
VOID CPGPnetFilterAdapter::DoMTUTransform(PGPnetPacket* packet)
{
PETHERNET_HEADER src_eth_header;
PIP_HEADER src_ip_header;
PETHERNET_HEADER xform_eth_header;
USHORT xform_eth_protocol;
PIP_HEADER xform_ip_header;
PICMP_HEADER icmp_header;
PTYPE3_ICMP_HEADER type3_icmp_header;
UCHAR hardwareAddress[6];
USHORT mtu;
src_eth_header = (PETHERNET_HEADER)packet->srcBlock;
src_ip_header = (PIP_HEADER)(packet->srcBlock + ETHER_HEADER_SIZE);
xform_eth_header = (PETHERNET_HEADER)packet->xformBlock;
xform_eth_protocol = *((PUSHORT)(&xform_eth_header->eth_protocolType[0]));
xform_ip_header = (PIP_HEADER)(packet->xformBlock + ETHER_HEADER_SIZE);
icmp_header = (PICMP_HEADER)((UCHAR*)xform_ip_header + IP_HEADER_SIZE);
type3_icmp_header = (PTYPE3_ICMP_HEADER)icmp_header;
// switch hardware address
NdisMoveMemory(hardwareAddress, xform_eth_header->eth_srcAddress, 6);
NdisMoveMemory(xform_eth_header->eth_srcAddress, xform_eth_header->eth_dstAddress, 6);
NdisMoveMemory(xform_eth_header->eth_dstAddress, hardwareAddress, 6);
// change ethernet protocol
// Still IP packet
// change misc ip fields
// change ip address
xform_ip_header->ip_dest = xform_ip_header->ip_src;
// change ip protocol
xform_ip_header->ip_prot = PROTOCOL_ICMP;
xform_ip_header->ip_chksum = 0;
// construct icmp header
icmp_header->icmp_type = ICMP_TYPE_UNREACHABLE;
icmp_header->icmp_code = ICMP_UNREACHABLE_CODE_FRAGMENT;
icmp_header->icmp_checksum = 0;
// copy icmp data
if (htons(xform_ip_header->ip_len) > htons(src_ip_header->ip_len))
mtu = htons(xform_ip_header->ip_len) - htons(src_ip_header->ip_len);
else
mtu = 0;
type3_icmp_header->u.icmp_unused = 0;
type3_icmp_header->u.icmp_code5.code5_mtu = mtu;
type3_icmp_header->u.icmp_code5.code5_unused = 0;
NdisMoveMemory(&type3_icmp_header->icmp_ip_header, src_ip_header, IP_HEADER_SIZE);
NdisMoveMemory(&type3_icmp_header->icmp_ip_data, src_ip_header + IP_HEADER_SIZE, 8);
// adjust ip len
xform_ip_header->ip_len = htons(IP_HEADER_SIZE + sizeof(TYPE3_ICMP_HEADER));
// calculate ip checksum
xform_ip_header->ip_chksum = HeaderChecksum((USHORT*)xform_ip_header, TYPE_IP);
// caculate icmp checksum
icmp_header->icmp_checksum = HeaderChecksum((USHORT*)icmp_header, TYPE_ICMP);
// adjust transform buffer length
packet->xformBlockLen = ETHER_HEADER_SIZE + htons(xform_ip_header->ip_len);
// set last fragment
packet->lastXformBlock = TRUE;
}
VOID CPGPnetFilterAdapter::DoCopyTransforms(PGPnetPacket *pgpnetPacket)
{
DBG_FUNC("CPGPnetFilterAdapter::DoCopyTransform")
PGPnetPacket* packet = pgpnetPacket;
PGPnetPacket* next;
DBG_ENTER();
while (packet != NULL)
{
DoCopyTransform(packet);
if (packet->lastSrcBlock)
next = NULL;
else
next = packet->link;
packet = next;
}
DBG_LEAVE(0);
}
VOID CPGPnetFilterAdapter::DoCopyTransform(PGPnetPacket* pgpnetPacket)
{
DBG_FUNC("CPGPnetFilterAdapter::DoCopyTransform")
DBG_ENTER();
CopySrcBlockToXformBlock(pgpnetPacket);
if (pgpnetPacket->firstSrcBlock)
pgpnetPacket->firstXformBlock = TRUE;
if (pgpnetPacket->lastSrcBlock)
pgpnetPacket->lastXformBlock = TRUE;
PGPnetAdjustXformPacket(pgpnetPacket);
DBG_LEAVE(0);
}
CPGPnetFilterAdapter::CPGPnetFilterAdapter()
{
HardwareAddressDetected = FALSE;
RealAdapterMedia = (NDIS_MEDIUM) (PGPUInt32) -1;
MaximumFrameSize = MAX_ETHER_FRAME_SIZE - ETHER_HEADER_SIZE;
}
CPGPnetFilterAdapter::~CPGPnetFilterAdapter()
{
}
PGPBoolean CPGPnetFilterAdapter::SetRealAdapterName(PNDIS_STRING String)
{
DBG_FUNC("CPGPnetFitlerAdapter::SetRealAdapterName")
NDIS_STATUS status;
DBG_ENTER();
/*
status = NdisAllocateMemory((VOID**)&RealAdapterName.Buffer, String->Length, 0, HighestAcceptableAddress);
if (status != NDIS_STATUS_SUCCESS)
{
DBG_PRINT(("!!!!! NdisAllocateMemory failed status=%Xh\n", status););
DBG_LEAVE(0);
return (FALSE);
}
NdisMoveMemory(RealAdapterName.Buffer, String->Buffer, String->Length);
RealAdapterName.MaximumLength = String->Length;
RealAdapterName.Length = String->Length;
*/
RtlInitUnicodeString(
&RealAdapterName,
String->Buffer
);
DBG_LEAVE(0);
return TRUE;
}
VOID CPGPnetFilterAdapter::AllocatePacketPool()
{
sent_plainpacket_list = (PGPnetPacket*)NULL;
incoming_plaintransferComplete_wait_list = (PGPnetPacket*)NULL;
incoming_ipsectransferComplete_wait_list = (PGPnetPacket*)NULL;
incoming_indicateComplete_wait_list = (PGPnetPacket*)NULL;
incoming_fragment_indicateComplete_wait_list = (PGPnetPacket*)NULL;
incoming_mac_transferdata_wait_list = (PGPnetPacket*)NULL;
outgoing_multiple_ipsecpacket_list = (PGPnetPacket*)NULL;
outgoing_multiple_cfgpacket_list = (PGPnetPacket*)NULL;
outgoing_local_packet_head_list = (PPGPnetPacketHead)NULL;
outgoing_cfg_packet_head_list = (PPGPnetPacketHead)NULL;
incoming_packet_head_list = (PPGPnetPacketHead)NULL;
sent_packet_head_list = (PPGPnetPacketHead)NULL;
last_fragment_list = (PGPnetLastFragmentList*)NULL;
}
VOID CPGPnetFilterAdapter::FreePacketPool()
{
PPGPnetPacketHead head;
while ((head = PacketHeadDequeue(&outgoing_local_packet_head_list)) != NULL)
{
PGPNdisPacketHeadFreeList(head);
PGPNdisPacketHeadFree(head);
}
while ((head = PacketHeadDequeue(&outgoing_cfg_packet_head_list)) != NULL)
{
PGPNdisPacketHeadFreeList(head);
PGPNdisPacketHeadFree(head);
}
while ((head = PacketHeadDequeue(&incoming_packet_head_list)) != NULL)
{
PGPNdisPacketHeadFreeList(head);
PGPNdisPacketHeadFree(head);
}
LastFragmentListFreeAll(last_fragment_list);
sent_plainpacket_list = (PGPnetPacket*)NULL;
incoming_plaintransferComplete_wait_list = (PGPnetPacket*)NULL;
incoming_ipsectransferComplete_wait_list = (PGPnetPacket*)NULL;
incoming_indicateComplete_wait_list = (PGPnetPacket*)NULL;
incoming_fragment_indicateComplete_wait_list = (PGPnetPacket*)NULL;
outgoing_multiple_ipsecpacket_list = (PGPnetPacket*)NULL;
outgoing_multiple_cfgpacket_list = (PGPnetPacket*)NULL;
outgoing_local_packet_head_list = (PPGPnetPacketHead)NULL;
outgoing_cfg_packet_head_list = (PPGPnetPacketHead)NULL;
incoming_packet_head_list = (PPGPnetPacketHead)NULL;
sent_packet_head_list = (PPGPnetPacketHead)NULL;
last_fragment_list = (PGPnetLastFragmentList*)NULL;
}
PGPnetPacketStatus
CPGPnetFilterAdapter::PGPnetFilterPacketCheck(PGPnetPacket *pgpnetPacket, PGPBoolean incoming)
{
PGPnetPacketStatus packetStatus = PacketFurtherCheck;
PVOID working_block;
UINT working_block_len;
PETHERNET_HEADER eth_header;
USHORT eth_protocol;
USHORT eth_header_len;
PIP_HEADER ip_header;
PGPUInt16 port = 0;
#if !defined(CHICAGO) && !defined(NDIS40)
PGPBoolean Broadcast = FALSE;
#endif
DBG_FUNC("PGPnetFilterPacketCheck");
working_block = pgpnetPacket->srcBlock;
working_block_len = pgpnetPacket->srcBlockLen;
do
{
if (Media != NdisMedium802_3 && Media != NdisMediumWan)
{
packetStatus = PacketDrop;
break;
}
/*
* Stage 1. Get the ethernet header. Determines if this is an ip packet. If not bail out early,
* otherwise go to stage 2.
*/
eth_header = (PETHERNET_HEADER) working_block;
eth_protocol = *((PUSHORT)(ð_header->eth_protocolType[0]));
eth_header_len = sizeof(ETHERNET_HEADER);
if ( RealAdapterMedia == NdisMediumWan &&
(eth_protocol == PPPOE_DISCOVERY_PORT_NET || eth_protocol == PPPOE_SESSION_PORT_NET))
{
packetStatus = PacketDrop;
break;
}
if (eth_protocol != IPPROT_NET)
{
if (eth_protocol == ARPPROT_NET && Media != NdisMediumWan && !incoming)
{
PGPUInt32 IpAddress;
IpAddress = GetIPAddressFromARP((PVOID)((UCHAR*)eth_header + eth_header_len));
if (IpAddress)
mIpAddress = IpAddress;
}
packetStatus = PacketPassthrough;
break;
}
if (BroadcastEthernetAddress(eth_header->eth_dstAddress) && !incoming)
{
#if !defined(CHICAGO) && !defined(NDIS40)
Broadcast = TRUE;
#else
packetStatus = PacketPassthrough;
break;
#endif
}
if (incoming)
NdisMoveMemory(pgpnetPacket->xformBlock, pgpnetPacket->srcBlock, ETHER_HEADER_SIZE);
else if (!HardwareAddressDetected &&
(eth_header->eth_srcAddress[0] != 0xFF ||
eth_header->eth_srcAddress[1] != 0xFF ||
eth_header->eth_srcAddress[2] != 0xFF ||
eth_header->eth_srcAddress[3] != 0 ||
eth_header->eth_srcAddress[4] != 0 ||
eth_header->eth_srcAddress[5] != 0))
{
HardwareAddressDetected = TRUE;
NdisMoveMemory(mHardwareAddress, eth_header->eth_srcAddress, 6);
#if defined(NDIS40)
if (RealAdapterMedia == NdisMediumWan)
PGPnetRASconnect();
#endif
}
/*
* Stage 2 Get the ip header.
*/
if (working_block_len >= eth_header_len + sizeof(IP_HEADER))
{
ip_header = (PIP_HEADER) ( (PCHAR)working_block + eth_header_len);
working_block = (PCHAR)working_block + eth_header_len;
working_block_len -= eth_header_len;
}
else
{
packetStatus = PacketDrop;
break;
}
if (!mWanIPAddressDetected && !incoming)
{
mIpAddress = ip_header->ip_src;
mWanIPAddressDetected = TRUE;
}
/*
* Stage 4. If it's UDP, Get the UDP header.
* Determine if this is a UDP 500 packet. If it is, bail out.
*/
if (ip_header->ip_prot == PROTOCOL_UDP)
{
if( working_block_len <= sizeof(struct tag_IP_HEADER) ) // FIX!!! ONLY work for ordinary ipv4 header.
{
packetStatus = PacketDrop;
break;
}
else
{
port = ((PUDP_HEADER)( (UCHAR*)working_block + sizeof(IP_HEADER)))->dest_port;
#if !defined(CHICAGO) && !defined(NDIS40)
if (port == UDP_PORT_BOOTPS_NET || port == UDP_PORT_BOOTPC_NET)
{
PUDP_HEADER udp_header;
PDHCP_HEADER dhcp_header;
CPGPnetDHCPPacket *dhcpPacket;
udp_header = (PUDP_HEADER) ( (PCHAR)working_block + sizeof(IP_HEADER));
working_block = (PCHAR)working_block + sizeof(IP_HEADER);
working_block_len -= sizeof(IP_HEADER);
dhcp_header = (PDHCP_HEADER) ( (PCHAR)working_block + sizeof(UDP_HEADER));
working_block = (PCHAR)working_block + sizeof(UDP_HEADER);
working_block_len -= sizeof(UDP_HEADER);
if (working_block_len <= sizeof(DHCP_HEADER))
break;
// now we have the DHCP Packet
dhcpPacket = new CPGPnetDHCPPacket(working_block, working_block_len);
switch (dhcpPacket->GetDHCPType())
{
case TYPE_DISCOVER:
break;
case TYPE_OFFER:
break;
case TYPE_REQUEST:
break;
case TYPE_DECLINE:
break;
case TYPE_ACK:
{
PGPUInt32 dns1;
PGPUInt32 dns2;
dhcpPacket->GetDHCPDNSServer(&dns1, &dns2);
PGPnetFilterDriver->dns1 = dns1;
PGPnetFilterDriver->dns2 = dns2;
}
break;
case TYPE_NAK:
break;
case TYPE_RELEASE:
break;
case TYPE_INFORM:
break;
case TYPE_INVALID:
break;
default:
ASSERT(0);
break;
}
delete dhcpPacket;
}
#endif
}
} else if (ip_header->ip_prot == PROTOCOL_TCP) {
if( working_block_len <= sizeof(struct tag_IP_HEADER) ) // FIX!!! ONLY work for ordinary ipv4 header.
{
packetStatus = PacketDrop;
break;
}
else
NdisMoveMemory(&(port), (UCHAR*)working_block + sizeof(IP_HEADER) + 2, 2);
}
} while (0);
#if !defined(CHICAGO) && !defined(NDIS40)
if(Broadcast && !incoming)
packetStatus = PacketPassthrough;
#endif
return packetStatus;
}
NDIS_STATUS CPGPnetFilterAdapter::SendPacket(PGPnetPacket *pgpnetPacket)
{
DBG_FUNC("CPGPnetFilterAdapter::SendPacket")
NDIS_STATUS status;
DBG_ENTER();
PacketEnqueue(&sent_plainpacket_list, pgpnetPacket);
#ifdef NDIS_MINIPORT_DRIVER
NdisSetPacketFlags(pgpnetPacket->xformPacket, pgpnetPacket->SendFlag);
#endif
ProtocolSendRequest(&status,
NdisBindingHandleToRealAdapter,
pgpnetPacket->xformPacket);
if (status != NDIS_STATUS_PENDING)
{
pgpnetPacket = PacketRemoveByXformPacket(&sent_plainpacket_list, pgpnetPacket->xformPacket);
FreePGPnetPacket(pgpnetPacket);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -