📄 vpnmac.c
字号:
NDIS_STATUS status;
PBINDING_CONTEXT binding;
PVPN_ADAPTER adapter;
DBG_ENTER();
binding = (PBINDING_CONTEXT) Context;
adapter = binding->adapter;
if (!adapter->open)
{
status = NDIS_STATUS_CLOSING;
DBG_LEAVE(status);
return status;
}
switch (NdisRequest->RequestType) {
case NdisRequestSetInformation:
#if DBG_MESSAGE
DBG_PRINT(("NdisRequestSetInformation: %s\n", GetOidString(NdisRequest->DATA.SET_INFORMATION.Oid)););
#endif
status = PgpMacSetInformation(
binding,
NdisRequest,
NdisRequest->DATA.SET_INFORMATION.Oid,
NdisRequest->DATA.SET_INFORMATION.InformationBuffer);
break;
case NdisRequestQueryInformation:
#if DBG_MESSAGE
DBG_PRINT(("NdisRequestQueryInformation: %s\n", GetOidString(NdisRequest->DATA.QUERY_INFORMATION.Oid)););
#endif
status = PgpMacQueryInformation(
binding,
NdisRequest,
NdisRequest->DATA.QUERY_INFORMATION.Oid,
NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer,
NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength,
&(NdisRequest->DATA.QUERY_INFORMATION.BytesWritten),
&(NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded));
break;
default:
status = NDIS_STATUS_NOT_SUPPORTED;
break;
}
DBG_LEAVE(status);
return status;
}
NDIS_STATUS MacSend(
IN NDIS_HANDLE Context,
IN PNDIS_PACKET Packet
)
{
DBG_FUNC("MacSend")
NDIS_STATUS status;
PBINDING_CONTEXT binding;
PVPN_ADAPTER adapter;
PNDIS_BUFFER src_buffer;
UINT src_len;
PNDIS_BUFFER working_buffer;
PVOID working_block;
UINT working_block_len;
PETHERNET_HEADER eth_header;
USHORT eth_protocol;
USHORT eth_header_len;
PIP_HEADER ip_header;
PUDP_HEADER udp_header = 0; /* EML 05/04/99 */
PPGPNDIS_PACKET pgpPacket;
PPGPNDIS_PACKET_HEAD packetHead;
BOOLEAN newHead = FALSE;
PGPnetPMStatus pmstatus;
BOOLEAN assembleComplete = FALSE;
DBG_ENTER();
binding = (PBINDING_CONTEXT)Context;
adapter = binding->adapter;
/*
* Check the Packet with the policy manager. Need some design work to be
* done.
*/
NdisQueryPacket(Packet, NULL, NULL, &src_buffer, &src_len);
NdisQueryBuffer(src_buffer, &working_block, &working_block_len);
/*
* An outgoing src packet would go through up to 4 stages in this stage before it is eventually
* sent out.
*/
/*
* 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 (eth_protocol != IPPROT_NET)
{
if (eth_protocol == ARPPROT_NET && adapter->media != NdisMediumWan)
{
GetIPAddressFromARP(adapter, (PVOID)((UCHAR*)eth_header + eth_header_len));
}
goto bailout;
}
if (BroadcastEthernetAddress(eth_header->eth_dstAddress))
goto bailout;
if (adapter->media != NdisMedium802_3 && adapter->media != NdisMediumWan)
{
status = NDIS_STATUS_NOT_ACCEPTED;
goto failout;
}
/*
* 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 if (working_block_len == eth_header_len)
{
NdisGetNextBuffer(src_buffer, &working_buffer);
if (working_buffer == NULL)
{
status = NDIS_STATUS_NOT_ACCEPTED;
goto failout;
}
NdisQueryBuffer(working_buffer, &working_block, &working_block_len);
ip_header = (PIP_HEADER)working_block;
}
else
{
status = NDIS_STATUS_NOT_ACCEPTED;
goto failout;
}
/*
* For Win98 WAN only
*/
#ifdef CHICAGO
if (!adapter->WanIPAddressDetected)
{
adapter->ip_address = ip_header->ip_src;
adapter->WanIPAddressDetected = TRUE;
PGPnetRASconnect(adapter, adapter->ip_address);
}
#endif
/*
* Stage 3 Policy on IGMP, ICMP to be determined.
*/
if (ip_header->ip_prot == PROTOCOL_IGMP)
goto bailout;
/*
* 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.
{
NdisGetNextBuffer(working_buffer, &working_buffer);
if (working_buffer == NULL)
{
status = NDIS_STATUS_NOT_ACCEPTED;
goto failout;
}
NdisQueryBuffer(working_buffer, &working_block, &working_block_len);
udp_header = (PUDP_HEADER)working_block;
}
else
udp_header = (PUDP_HEADER)( (UCHAR*)working_block + sizeof(IP_HEADER));
}
#if 0
if (PGPnetPMIKEPassthrough(PGPnetDriver.PolicyManagerHandle,
ip_header->ip_dest,
udp_header->dest_port))
// if (udp_header->dest_port == UDP_PORT_IKE_NET)
{
goto bailout;
}
else if (ip_header->ip_foff != 0)
{
goto bailout;
}
}
#endif
/*
* Now we have an normal ip packet, ask the policy manager for more directions.
*/
if (ip_header->ip_foff)
pmstatus = PGPnetPMNeedTransformLight(PGPnetDriver.PolicyManagerHandle,
ip_header->ip_dest,
FALSE,
adapter);
else
pmstatus = PGPnetPMNeedTransform(PGPnetDriver.PolicyManagerHandle,
ip_header->ip_dest,
(PGPUInt16)(udp_header ? udp_header->dest_port : 0), /* EML 05/04/99 */
FALSE,
0,
0,
adapter);
if ( kPGPNetPMPacketSent == pmstatus)
goto dropout;
if ( kPGPNetPMPacketWaiting == pmstatus)
goto dropout;
if ( kPGPNetPMPacketDrop == pmstatus)
goto dropout;
if ( kPGPNetPMPacketClear == pmstatus)
goto bailout;
if ( kPGPNetPMPacketEncrypt != pmstatus)
{
status = NDIS_STATUS_FAILURE;
goto failout;
}
// Now we have a packet to be secured.
// Allocate the pgpPakcet
pgpPacket = PGPNdisPacketAllocWithXformPacket(&status, adapter);
if (status != NDIS_STATUS_SUCCESS)
goto failout;
pgpPacket->Binding = binding;
pgpPacket->srcPacket = Packet;
PGPCopyPacketToBlock(pgpPacket->srcPacket, pgpPacket->srcBlock, &pgpPacket->srcBlockLen);
pgpPacket->ipAddress = ntohl(ip_header->ip_dest);
/* Start EML 05/04/99 */
pgpPacket->port = udp_header ? udp_header->dest_port : 0;
/* End ELM */
pgpPacket->offset = ntohs(ip_header->ip_foff & IP_OFFSET) << 3;
if (pgpPacket->offset == 0)
pgpPacket->firstSrcBlock = TRUE;
// Check to see if it's in the outgoing fragment list.
packetHead = PacketHeadListQuery(adapter,
&adapter->outgoing_packet_head_list,
ip_header->ip_id,
pgpPacket->ipAddress);
// If there is no outgoing fragment list. Create one.
if (packetHead == NULL)
{
packetHead = PGPNdisPacketHeadAlloc(&status, adapter);
newHead = TRUE;
}
if (status != NDIS_STATUS_SUCCESS)
goto failout;
// Add timestamp, update head information.
if (packetHead->id == 0)
{
// Initialize packetHead
packetHead->ipAddress = pgpPacket->ipAddress;
packetHead->id = ip_header->ip_id;
packetHead->timeStamp = PgpKernelGetSystemTime();
}
if (packetHead->numFragments ==0)
packetHead->accumulatedLength = htons(ip_header->ip_len);
else
packetHead->accumulatedLength += htons(ip_header->ip_len) - IP_HEADER_SIZE;
packetHead->numFragments++;
if (IP_LAST_FRAGMENT(ip_header->ip_foff))
{
ASSERT(packetHead->totalLength == 0);
pgpPacket->lastSrcBlock = TRUE;
packetHead->totalLength = htons(ip_header->ip_len) + pgpPacket->offset;
}
// Insert this pgpPacket to the packet list
InsertPGPNdisPacket(adapter, packetHead, pgpPacket);
// Check status, if finished fire up the send sequence.
if ((packetHead->totalLength) && (packetHead->totalLength == packetHead->accumulatedLength))
{
// Have them all, send them all.
PGPnetPMStatus pm_status;
PPGPNDIS_PACKET extraPacket;
// Put an extra buffer there.
extraPacket = PGPNdisPacketAllocWithXformPacket(&status, adapter);
AppendPGPNdisPacket(adapter, packetHead, extraPacket);
if ( !(packetHead->link)->lastSrcBlock )
{
// More fragment. Adjust packet length.
PIP_HEADER first_ip_hdr;
PUCHAR first_srcBlock;
first_srcBlock = (packetHead->link)->srcBlock;
first_ip_hdr = (PIP_HEADER)(first_srcBlock + ETHER_HEADER_SIZE);
first_ip_hdr->ip_len = htons(packetHead->totalLength);
}
pm_status = PGPnetPMDoTransform(PGPnetDriver.PolicyManagerHandle,
packetHead->link,
FALSE,
adapter);
if (pm_status != kPGPNetPMPacketSent)
{
DBG_PRINT(("!!!!! Yellow Alert! PGPnetPMDoTransform Error!\n"););
//PGPNdisPacketFree(adapter, pgpPacket);
PGPNdisPacketHeadFreeList(adapter, packetHead, TRUE);
PacketHeadListRemove(adapter, &adapter->outgoing_packet_head_list, packetHead);
PGPNdisPacketHeadFree(adapter, packetHead);
goto dropout;
}
status = MacSendPackets(adapter, packetHead);
assembleComplete = TRUE;
}
else
{
// Not finished, add to the outgoing list
if (newHead)
PacketHeadEnqueue(adapter, &adapter->outgoing_packet_head_list, packetHead);
}
goto dropout;
// Either way, return successful.
DBG_LEAVE(status);
return status;
bailout:
pgpPacket = PGPNdisPacketAllocWithBindingContext(&status, adapter);
if (status != NDIS_STATUS_SUCCESS)
goto failout;
pgpPacket->srcPacket = Packet;
pgpPacket->Binding = binding;
PacketEnqueue(adapter, &adapter->sent_plainpacket_list, pgpPacket);
NdisSend(&status,
adapter->NdisBindingHandleToRealMac,
Packet);
if (status != NDIS_STATUS_PENDING)
{
pgpPacket = PacketRemoveBySrcPacket(adapter, &adapter->sent_plainpacket_list, Packet);
PGPNdisPacketFreeWithBindingContext(adapter, pgpPacket);
}
adapter->SendPackets++;
failout:
DBG_LEAVE(status);
return status;
dropout:
if (assembleComplete == FALSE)
status = NDIS_STATUS_SUCCESS;
DBG_LEAVE(status);
return status;
}
NDIS_STATUS MacTransferData(
IN NDIS_HANDLE MacBindingHandle,
IN NDIS_HANDLE MacReceiveContext,
IN UINT ByteOffset,
IN UINT BytesToTransfer,
OUT PNDIS_PACKET Packet,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -