📄 msg.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
// PPP CCP Layer Message Processing
#include "windows.h"
#include "cclib.h"
#include "memory.h"
#include "cxport.h"
// PPP Include Files
#include "protocol.h"
#include "ppp.h"
#include "lcp.h"
#include "auth.h"
#include "ccp.h"
#include "ncp.h"
#include "mac.h"
#include "ip_intf.h"
void
ccpRxResetRequest(
IN PVOID context,
IN BYTE code,
IN BYTE id,
IN PBYTE pData,
IN DWORD cbData)
//
// Called when we receive a CCP Reset-Request packet
//
{
PCCPContext pContext = (PCCPContext)context;
DEBUGMSG( ZONE_NCP | ZONE_FUNCTION, (TEXT( "PPP: ccpRxResetRequest\n" )));
// A compression reset forces a TX flush sequence. We set the flush
// flag to force the next tx packet to be uncompressed and re-initialize
// the send context.
// Flush next tx packet
pContext->txFlush = TRUE;
initsendcontext( &pContext->mppcSndCntxt );
// NOTE:
// The Microsoft implementation does not send an ACK
// but rather sets the PACKET_FLUSH bit on the next outgoing packet
// to signal a reset.
}
void
ccpRxResetAck(
IN PVOID context,
IN BYTE code,
IN BYTE id,
IN PBYTE pData,
IN DWORD cbData)
//
// Called when we receive a CCP Reset-Ack packet
//
{
PCCPContext pContext = (PCCPContext)context;
DEBUGMSG( ZONE_NCP | ZONE_FUNCTION, (TEXT( "PPP: ccpRxResetAck\n" )));
// MS CCP does not use the ACK mechanism.
}
void
ccpTxResetRequest(
IN PCCPContext pContext)
//
// Send Reset Request Packet
//
{
BYTE resetRequestPacket[PPP_PACKET_HEADER_SIZE];
pContext->idResetRequest++;
PPP_INIT_PACKET( &resetRequestPacket[0], CCP_RESET_REQ, pContext->idResetRequest);
pppSendData(pContext->session, PPP_PROTOCOL_CCP, resetRequestPacket, PPP_PACKET_HEADER_SIZE);
}
void
CpktProcessRxPacket(
IN OUT PVOID context,
IN OUT pppMsg_t *pMsg)
//
// Process a compressed/encrypted data packet received
// from the peer.
//
{ PCCPContext pContext = (PCCPContext)context;
PBYTE pDecompressed;
DWORD cbDecompressed;
USHORT coherencyHdr;
DEBUGMSG( ZONE_NCP | ZONE_FUNCTION, (TEXT("PPP: RX CCP Data Message\n")));
if (pContext->pFsm->state != PFS_Opened)
{
DEBUGMSG(ZONE_WARN, (TEXT("PPP: WARNING - Ignoring CCP data packet, CCP not opened\n")));
return;
}
#ifdef DEBUG
if (ZONE_TRACE)
{
DEBUGMSG (1, (TEXT("PPP: CCP: RX Packet (%d):\n"), pMsg->len));
DumpMem (pMsg->data, pMsg->len);
}
#endif // DEBUG
// Access the Coherency Header and adjust msg
if (pMsg->len < 2)
{
DEBUGMSG(ZONE_WARN, (TEXT("PPP: WARNING - CCP compressed packet has no coherency header\n")));
return;
}
coherencyHdr = (pMsg->data[0] << 8) + pMsg->data[1];
pMsg->data += 2;
pMsg->len -= 2;
DEBUGMSG( ZONE_NCP, (TEXT( "PPP: CCP: RX: coherency hdr= 0x%x\n" ), coherencyHdr ));
// Force a resync for a FLUSHED packet
if( coherencyHdr & (PACKET_FLUSHED << 8) )
{
DEBUGMSG (ZONE_CCP || ZONE_TRACE, (TEXT( "PPP: CCP RX FLUSH LastGood=0x%x New=0x%x.\n"), pContext->rxCoherency, coherencyHdr));
//
// If the peer acked our config-request for encryption, then
// the peer will be sending encrypted packets to us so we need
// to reset the receive encrypt context.
//
if (pContext->local.SupportedBits & (MSTYPE_ENCRYPTION_40F | MSTYPE_ENCRYPTION_128))
{
//
// If it appears that this FLUSHED packet is stale, that is, we have
// already changed our session key to the next one because we passed
// a flag packet, then ignore it.
//
// That is, if we receive packets out of order due to some strangeness
// at the MAC layer like this:
//
// RX CC = 0FE
// RX CC = 0FF (Session Key changed)
// RX CC = 100
// RX CC = 0FC FLUSHED
//
// Then the CC=0FC packet is probably being received out of order. If we
// accepted it as valid and in order then that would mean that we missed
// the almost 4000 packets from 101 to 0FB, and thus would need to change
// our session key 15 times to account for the intervening missed flag
// packets. More likely, however, is that the 0FC packet is old and delivered
// out of order for some reason. If we change our session key 15 times then
// we will permanently lose sync with the transmitter's encryption key.
//
// So, rather than changing the encryption key 15 times we ignore the packet.
// As a simplification, we ignore any FLUSHED packet with a CC that is in the
// range of the 256 most recent CC's we received.
//
if ((((coherencyHdr & 0x0fff) - pContext->rxCoherency) & 0x0fff) >= 0x0f00)
{
DEBUGMSG(ZONE_WARN, (L"PPP: CCP RX Ignore FLUSHED Out-of-order - rx=%04x exp=%04x\n", coherencyHdr, pContext->rxCoherency));
return;
}
//
// Each packet that gets encrypted modifies the current encryption key state. As a result, if a packet
// is lost the receiver will not be able to decode subsequent packets because its decryption key will
// not be in sync with the encryption key. To solve this issue, the MPPE protocol specifies that when
// a CCP packet is sent with the PACKET_FLUSHED bit set, the encryption key is reset to discard all
// prior packet data that has modified its state.
//
// That is, suppose the receiver processes packets with CC=0 through CC=2A. The encryption key for both
// sender and receiver has been modified by all the data in these packets. But then CC=2B is dropped.
// The sender's encryption key has been modified by the data of packet 2B, but the receiver's has not,
// so the receiver cannot decrypt any more packets in this stream. So, the receiver sends a CCP Reset
// request to the sender. This causes the sender to reset its encryption key, discarding all the packet
// data history from CC=0 to CC=2B prior to encrypting its next packet, which it sends with FLUSHED=1.
// The receiver, when it sees the FLUSHED bit, then resets its decryption key discarding all prior
// packet data and thus is able to once again decrypt packets in the stream.
//
EncryptionInfoReinitializeKey(pContext->prxEncryptionInfo);
}
//
// If the peer acked our config-request for MCCP_COMPRESSION, then
// the peer will be sending compressed packets to us so we need
// to reset the receive compress context.
//
if (pContext->local.SupportedBits & MCCP_COMPRESSION)
{
initrecvcontext( &pContext->mppcRcvCntxt ); // reset rcv context
}
//
// This is now our new coherency count.
//
pContext->rxCoherency = coherencyHdr & 0x0fff;
//
// We are back in sync...
//
pContext->bRxOutOfSync = FALSE;
}
// If the received coherency counters agree then we are in sync.
// Note: if the packet was a flush packet then the above logic
// forces the coherency counters to agree and resets the context
// so we are in sync here, albeit, without any history.
if ((pContext->bRxOutOfSync)
|| ((coherencyHdr & 0x0fff) != pContext->rxCoherency))
{
DEBUGMSG( ZONE_ERROR | ZONE_NCP, (TEXT( "PPP: CCP:rx:TOSS PKT - BAD COHERENCY (got %x expected %x\n"),
coherencyHdr, pContext->rxCoherency));
// Changes for coherency fix
// this indicates a lost packet, try re-syncing our
// coherency counter, reseting the context, and the
// sending a reset request packet
pContext->bRxOutOfSync = TRUE;
ccpTxResetRequest(pContext);
return;
}
//
// This is the next good coherency number we expect.
//
pContext->rxCoherency = (pContext->rxCoherency + 1) & 0x0FFF;
// If packet is encrypted then attempt to decrypt
if( coherencyHdr & (PACKET_ENCRYPTED << 8) )
{
DEBUGMSG( ZONE_CCP, (TEXT( "PPP: CCP - Decrypting packet\n" )));
DecryptRxData(pContext, pMsg->data, pMsg->len);
#ifdef DEBUG
if (ZONE_TRACE)
{
DEBUGMSG (1, (TEXT("PPP: CCP: RX Decrypted packet (%d):\n"), pMsg->len));
DumpMem (pMsg->data, pMsg->len);
}
#endif
}
// If packet is compressed attempt to decompress
if( coherencyHdr & (PACKET_COMPRESSED << 8) )
{
if (!(pContext->local.SupportedBits & MCCP_COMPRESSION))
{
DEBUGMSG(ZONE_ERROR, (TEXT("PPP: CCP-ERROR Rx compressed packet with compression disabled\n")));
return;
}
if( decompress( pMsg->data,
pMsg->len,
((coherencyHdr & (PACKET_AT_FRONT << 8)) >> 8),
&pDecompressed,
&cbDecompressed,
&pContext->mppcRcvCntxt ) == FALSE )
{
// Coherency is lost - Request a reset from Peer
DEBUGMSG( ZONE_CCP | ZONE_ERROR, (TEXT( "CCP:RX:PKT DECOMPRESS FAILED - REQUEST RESET\r\n" )));
//
// Should not reduce the pContext->rxCoherency here because we have already
// done the DecryptRxData().
//
ccpTxResetRequest(pContext);
//
// We are in out of sync state. Only flush packet can get us back...
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -