📄 ipv6cp.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.
//
/*****************************************************************************
*
*
* @doc
* @module ipv6cp.c | PPP Internet Protocol Version 6 Control Protocol (IPV6CP)
*
*/
// Include Files
#include "windows.h"
#include "cclib.h"
#include "memory.h"
#include "cxport.h"
#include "ndis.h"
#include "ndiswan.h"
#include "tcpip.h"
#include "vjcomp.h"
// PPP Include Files
#include "protocol.h"
#include "ppp.h"
#include "lcp.h"
#include "auth.h"
#include "ipcp.h"
#include "ncp.h"
#include "ccp.h"
#include "mac.h"
#include "ip_intf.h"
#include "ras.h"
#include "util.h"
#include "layerfsm.h"
#include "ipv6cp.h"
#include "ipv6intf.h"
extern BOOL DumpIPv6 (BOOL Direction, PBYTE Buffer, DWORD Len);
static DWORD
ipv6cpUp(
PVOID context)
//
// This is called when the FSM enters the Opened state
//
{
PIPV6Context pContext = (PIPV6Context)context;
pppSession_t *pSession = (pppSession_t *)(pContext->pSession);
BOOL bResult;
DEBUGMSG( ZONE_IPV6CP, ( TEXT( "PPP: IPV6CP UP\n" )));
bResult = PPPAddIPV6Interface(pSession->context);
if (bResult == TRUE)
{
// Indicate connected to RAS (unless still waiting on encryption)
pppNcp_IndicateConnected(pSession->ncpCntxt);
}
return NO_ERROR;
}
static DWORD
ipv6cpDown(
PVOID context)
//
// This is called when the FSM leaves the Opened state
//
{
PIPV6Context pContext = (PIPV6Context)context;
pppSession_t *pSession = (pppSession_t *)(pContext->pSession);
DEBUGMSG( ZONE_IPV6CP, ( TEXT( "PPP: IPV6CP DOWN\n" )));
PPPDeleteIPV6Interface(pSession->context);
pContext->NextIFIDMethod = 0;
return NO_ERROR;
}
static DWORD
ipv6cpStarted(
PVOID context)
//
// This is called when the FSM enters the Opened state
//
{
PIPV6Context pContext = (PIPV6Context)context;
pppSession_t *pSession = (pppSession_t *)(pContext->pSession);
DEBUGMSG( ZONE_IPV6CP, ( TEXT( "PPP: IPV6CP STARTED\n" )));
ipv6cpOptionValueReset(pContext);
return NO_ERROR;
}
static DWORD
ipv6cpFinished(
PVOID context)
{
PIPV6Context pContext = (PIPV6Context)context;
// Indicate to NCP layer the IPCP Protocol is Down
// TODO - NCP should only go down if both IPCP and IPV6CP are down
return NO_ERROR;
}
static DWORD
ipv6cpSendPacket(
PVOID context,
USHORT ProtocolWord,
PBYTE pData,
DWORD cbData)
{
PIPV6Context pContext = (PIPV6Context)context;
pppSession_t *pSession = (pppSession_t *)(pContext->pSession);
DWORD dwResult;
dwResult = pppSendData(pSession, ProtocolWord, pData, cbData);
return dwResult;
}
void
ipv6cpResetPeerOptionsToDefaultSettings(
PVOID context)
//
// This function is called whenever a new configure-request is
// received from the peer prior to processing the options therein
// contained. This function must reset all options to their default
// values, such that any not explicity contained within the configure
// request will use the default setting.
//
{
PIPV6Context pContext = (PIPV6Context)context;
// Set Peer IFID to 0 prior to the peer assigning it a value.
memset(pContext->PeerInterfaceIdentifier, 0, 8);
}
DWORD
ipv6cpSessionLock(
PVOID context)
//
// This is called by the FSM when it needs to lock the session
// because a timer has expired.
//
{
PIPV6Context pContext = (PIPV6Context)context;
pppLock(pContext->pSession);
return NO_ERROR;
}
DWORD
ipv6cpSessionUnlock(
PVOID context)
//
// This is called by the FSM when it needs to unlock the session
// after a prior call to lock it due to timer expiry.
//
{
PIPV6Context pContext = (PIPV6Context)context;
pppUnLock(pContext->pSession);
return NO_ERROR;
}
static PppFsmDescriptor ipv6cpFsmData =
{
"IPV6CP", // szProtocolName
PPP_PROTOCOL_IPV6CP, // ProtocolWord
32, // cbMaxTxPacket
ipv6cpUp,
ipv6cpDown,
ipv6cpStarted,
ipv6cpFinished,
ipv6cpSendPacket,
ipv6cpSessionLock,
ipv6cpSessionUnlock,
NULL // No extension message types for IPCP
};
PROTOCOL_DESCRIPTOR pppIpv6cpProtocolDescriptor =
{
pppIpv6cpRcvData,
pppIpv6cp_Rejected,
Ipv6cpOpen,
Ipv6cpClose,
Ipv6cpRenegotiate
};
PROTOCOL_DESCRIPTOR pppIPV6ProtocolDescriptor =
{
pppIpv6ReceiveIPV6,
NULL
};
/*****************************************************************************
*
* @func DWORD | pppIpv6cp_InstanceCreate | Creates IPV6CP instance.
*
* @parm void * | SessionContext | Session context pointer.
* @parm void ** | ReturnedContext | Returned context pointer.
*
* @rdesc Returns error code, return of 0 indicates success.
*
* @comm This function creates an instance of the IPV6CP layer and returns
* a pointer to it. This pointer is used for all subsequent calls
* to this context.
*/
DWORD
pppIpv6cp_InstanceCreate(
IN PVOID session,
OUT PVOID *ReturnedContext)
{
pppSession_t *pSession = (pppSession_t *)session;
PIPV6Context pContext;
DWORD dwResult = NO_ERROR;
DWORD nRead;
DWORD cbRegistryIFID;
DEBUGMSG(ZONE_FUNCTION, (TEXT( "pppIpv6cp_InstanceCreate\r\n" )));
do
{
pContext = (PIPV6Context)pppAlloc(pSession, sizeof(*pContext), TEXT( "IPV6CP CONTEXT" ) );
if (pContext == NULL)
{
dwResult = ERROR_NOT_ENOUGH_MEMORY;
break;
}
// Register IPV6CP context and protocol decriptor with session
dwResult = PPPSessionRegisterProtocol(pSession, PPP_PROTOCOL_IPV6CP, &pppIpv6cpProtocolDescriptor, pContext);
if (dwResult != NO_ERROR)
break;
dwResult = PPPSessionRegisterProtocol(pSession, PPP_PROTOCOL_IPV6, &pppIPV6ProtocolDescriptor, pContext);
if (dwResult != NO_ERROR)
break;
// Initialize context
pContext->pSession = session;
// Create Fsm
pContext->pFsm = PppFsmNew(&ipv6cpFsmData, ipv6cpResetPeerOptionsToDefaultSettings, pContext);
if (pContext->pFsm == NULL)
{
dwResult = ERROR_NOT_ENOUGH_MEMORY;
break;
}
nRead = ReadRegistryValues(HKEY_LOCAL_MACHINE, TEXT("Comm\\ppp\\Parms"),
RAS_VALUENAME_IPV6_FLAGS, REG_DWORD, 0, &pContext->dwOptionFlags, sizeof(DWORD),
NULL);
//
// Read in registry IFID if present
//
cbRegistryIFID = IPV6_IFID_LENGTH;
nRead = ReadRegistryValues(HKEY_LOCAL_MACHINE, TEXT("Comm\\ppp\\Parms"),
RAS_VALUENAME_IPV6_IFID, REG_BINARY, 0, &pContext->RegistryIFID[0], &cbRegistryIFID,
NULL);
pContext->bRegistryIFIDPresent = nRead == 1 && cbRegistryIFID == IPV6_IFID_LENGTH;
cbRegistryIFID = IPV6_IFID_LENGTH;
nRead = ReadRegistryValues(HKEY_LOCAL_MACHINE, TEXT("Comm\\ppp\\Parms"),
RAS_VALUENAME_IPV6_RANDOM_IFID, REG_BINARY, 0, &pContext->RegistryRandomIFID[0], &cbRegistryIFID,
NULL);
pContext->bRegistryRandomIFIDPresent = nRead == 1 && cbRegistryIFID == IPV6_IFID_LENGTH;
// Get the EUI of an adapter during initialization, rather than during
// option negotiation, to avoid problems with deadlock due to calls to
// the IP Helpers calling back into NDIS miniports.
if (utilGetEUI(0, &pContext->EUI[0], &pContext->cbEUI) == FALSE)
pContext->cbEUI = 0;
// Get the machine unique ID if available
pContext->cbDeviceID = sizeof(pContext->DeviceID);
utilGetDeviceIDHash(&pContext->DeviceID[0], &pContext->cbDeviceID);
// Configure option values
ipv6cpOptionInit(pContext);
// Put the FSM into the opened state, ready to go when the lower layer comes up
PppFsmOpen(pContext->pFsm);
} while (FALSE);
if (dwResult != NO_ERROR)
{
pppFree(pSession, pContext, TEXT( "IPV6CP CONTEXT" ));
pContext = NULL;
}
*ReturnedContext = pContext;
return dwResult;
}
DWORD
Ipv6cpOpen(
IN PVOID context )
//
// Called to open the IPV6CP layer.
//
{
PIPV6Context pContext = (PIPV6Context)context;
return PppFsmOpen(pContext->pFsm);
}
DWORD
Ipv6cpClose(
IN PVOID context )
//
// Called to initiate the closure of the IPV6CP layer.
//
{
PIPV6Context pContext = (PIPV6Context)context;
return PppFsmClose(pContext->pFsm);
}
DWORD
Ipv6cpRenegotiate(
IN PVOID context )
//
// Called to renegotiate IPV6CP layer parameters with the peer.
//
{
PIPV6Context pContext = (PIPV6Context)context;
return PppFsmRenegotiate(pContext->pFsm);
}
void
pppIpv6cp_Rejected(
IN PVOID context )
//
// Called when the peer rejects the IPV6CP protocol
//
{
PIPV6Context pContext = (PIPV6Context)context;
PppFsmProtocolRejected(pContext->pFsm);
}
/*****************************************************************************
*
* @func void | pppIpv6cp_InstanceDelete | Deletes ipv6cp instance.
*
* @parm void * | context | Instance context pointer.
*
* @comm This function deletes the passed in context.
*/
void
pppIpv6cp_InstanceDelete(
IN PVOID context )
{
PIPV6Context pContext = (PIPV6Context)context;
DEBUGMSG( ZONE_IPV6CP | ZONE_FUNCTION, (TEXT("pppIpv6cp_InstanceDelete\r\n" )));
if (context)
{
PppFsmClose(pContext->pFsm);
PppFsmDelete(pContext->pFsm);
pppFree( pContext->pSession, pContext, TEXT( "IPV6CP CONTEXT" ) );
}
}
void
pppIpv6cp_LowerLayerUp(
IN PVOID context)
//
// This function will be called when the auth layer is up
//
{
PIPV6Context pContext = (PIPV6Context)context;
PppFsmLowerLayerUp(pContext->pFsm);
}
void
pppIpv6cp_LowerLayerDown(
IN PVOID context)
//
// This function will be called when the auth layer is down
//
{
PIPV6Context pContext = (PIPV6Context)context;
PppFsmLowerLayerDown(pContext->pFsm);
}
void
pppIpv6cpRcvData(
PVOID context,
pppMsg_t *pMsg )
//
// Process received IPV6CP Control Messages
//
{
PIPV6Context pContext = (PIPV6Context)context;
ASSERT(PPP_PROTOCOL_IPV6CP == pMsg->ProtocolType);
// If the layer below IPV6CP (usually auth) has not indicated that it is up yet,
// then receiving a IPV6CP packet means that we probably lost an
// authentication success packet from the peer. So, for some
// authentication protocols the reception of a network layer
// packet (e.g. CCP, IPV6CP) is implicit authentication success.
//
if (pContext->pFsm->state <= PFS_Starting)
{
AuthRxImpliedSuccessPacket(pContext->pSession->authCntxt);
}
PppFsmProcessRxPacket(pContext->pFsm, pMsg->data, pMsg->len);
}
void
pppIpv6ReceiveIPV6(
IN PIPV6Context pContext,
IN pppMsg_t *pMsg )
//
// Process a received IPv6 packet
//
{
pppSession_t *pSession = pContext->pSession;
if (pContext->pFsm->state == PFS_Opened)
{
PPPSessionUpdateRxPacketStats(pSession, pMsg);
PppIPV6Receive( pContext->pSession->context, pMsg);
}
}
void
pppIpv6cpSendData(
IN PVOID context,
IN PNDIS_PACKET pNdisPacket)
//
// This function is called to send an IPv6 packet.
//
{
PIPV6Context pContext = (PIPV6Context)context;
pppSession_t *pSession = pContext->pSession;
ncpCntxt_t *ncp_p = (ncpCntxt_t *)pSession->ncpCntxt;
PNDIS_WAN_PACKET pWanPacket;
USHORT wProtocol;
void *pMac = pSession->macCntxt;
NDIS_STATUS Status;
DWORD dwFlatLen;
DEBUGMSG( ZONE_IPCP | ZONE_FUNCTION, (TEXT( "pppIpcpSndData( %08x, %08x, %08x )\r\n" ), context, pNdisPacket ));
ASSERT( pNdisPacket );
do
{
// Protocol State MUST be OPEN to accept messages
if (pContext->pFsm->state != PFS_Opened)
{
DEBUGMSG(ZONE_IPV6CP, (TEXT("PPP: IPv6 unable to send packet in state %u\n"), pContext->pFsm->state));
break;
}
// It's just easier to make a linear buffer now rather than later. Let's
// get one and copy the NDIS buffer's to it.
// Get a WAN packet.
pWanPacket = pppMac_GetPacket (pMac);
if (!pWanPacket)
{
DEBUGMSG(ZONE_IPV6CP, (TEXT("PPP: No Tx buffers\n")));
break;
}
// Reserve space for the possible PPP header
pWanPacket->CurrentBuffer += 4;
pWanPacket->CurrentLength -= 4;
if( ncp_p->protocol[NCP_CCP].enabled )
{
// Allow 2 header bytes for the coherency
// header and 2 bytes for the encapsulated protocol.
pWanPacket->CurrentBuffer += 4;
pWanPacket->CurrentLength -= 4;
}
if (!CopyNdisPacketToWanPacket(pNdisPacket, pWanPacket))
{
NdisWanFreePacket (pMac, pWanPacket);
break;
}
dwFlatLen = pWanPacket->CurrentLength; // Save for later
pSession->Stats.BytesSent += pWanPacket->CurrentLength;
pSession->Stats.FramesSent++;
wProtocol = PPP_PROTOCOL_IPV6;
#ifdef DEBUG
if (dpCurSettings.ulZoneMask & 0x80000000)
DumpIPv6(TRUE, pWanPacket->CurrentBuffer, pWanPacket->CurrentLength);
#endif
// CCP Datagram Compression
//
// If CCP is enabled pass the packet to the CCP protocol for compression.
// If this option has been negotiated the pppData structure will be
// suitably modified to pass to PPP for transmission.
if( ncp_p->protocol[NCP_CCP].enabled )
{
// Pass in a pointer to the current Wan Packet.
// The compression code might replace our packet if it can compress
// the data
if (!pppCcp_Compress( pSession, &pWanPacket, &wProtocol))
{
// Encryption is required and CCP is not open, discard packet
NdisWanFreePacket (pMac, pWanPacket);
break;
}
}
// If either compression enabled then keep track of compression stats.
pSession->Stats.BytesTransmittedUncompressed += dwFlatLen;
pSession->Stats.BytesTransmittedCompressed += pWanPacket->CurrentLength;
// Send down to the miniport.
Status = pppMacSndData (pMac, wProtocol, pWanPacket);
} while (FALSE);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -