📄 option.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 IPCP Layer Option Processing
// Include Files
#include "windows.h"
#include "cclib.h"
#include "memory.h"
#include "cxport.h"
#include "crypt.h"
// VJ Compression Include Files
#include "ndis.h"
#include "tcpip.h"
#include "vjcomp.h"
// PPP Include Files
#include "protocol.h"
#include "ppp.h"
#include "layerfsm.h"
#include "auth.h"
#include "lcp.h"
#include "ipcp.h"
#include "mac.h"
#include "pppserver.h"
#include "ncp.h"
// DEBUG OUTPUT MACRO
#define IPADDROUT(a) (a)>>24, ((a)>>16)&0xFF, ((a)>>8)&0xFF, (a)&0xFF
#define IPADDR_TO_DWORD(dw, pB) \
(dw) = ((pB)[0] << 24) | ((pB)[1] << 16) | ((pB)[2] << 8) | ((pB)[3])
#define DWORD_TO_IPADDR(pB, dw) \
(pB)[0] = (BYTE)(dw >> 24); (pB)[1] = (BYTE)(dw >> 16); (pB)[2] = (BYTE)(dw >> 8); (pB)[3] = (BYTE)(dw)
// Van Jacobson Compressed TCP/IP Protocol Identifier
BYTE g_abVJProtocolID[2] = {0x00, 0x2D};
//
// Debug support functions to display option values as strings
//
void
ipAddressOptionToStringCb(
IN PVOID context,
IN OUT POptionInfo pInfo,
IN PBYTE pOptData,
IN DWORD cbOptData,
IN OUT PSTR *ppBuffer)
{
PSTR pBuffer = *ppBuffer;
ASSERT(cbOptData == 4);
while (TRUE)
{
pBuffer += sprintf(pBuffer, "%u", *pOptData++);
if (--cbOptData == 0)
break;
*(pBuffer++) = '.';
*pBuffer = '\0';
}
*ppBuffer = pBuffer;
}
void
ipCompressionOptionToStringCb(
IN PVOID context,
IN OUT POptionInfo pInfo,
IN PBYTE pOptData,
IN DWORD cbOptData,
IN OUT PSTR *ppBuffer)
{
PSTR pBuffer = *ppBuffer;
ASSERT(cbOptData == 4);
pBuffer += sprintf(pBuffer, "%02X%02X,MaxSlot=%u,CompSlot=%u", pOptData[0], pOptData[1], pOptData[2], pOptData[3]);
*ppBuffer = pBuffer;
}
//////////////////////////////////////////
// IPCP Option Negotation Callbacks
//////////////////////////////////////////
void
ipcpResetPeerOptionValuesCb(
IN 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.
//
{
PIPCPContext pContext = (PIPCPContext)context;
pContext->peer.VJCompressionEnabled = FALSE;
pContext->peer.ipAddress = 0;
}
void
ipcpOptionValueReset(
PIPCPContext pContext)
//
// Initialize the option states at the beginning of an
// IPCP negotiation.
//
{
pppSession_t *pSession = (pppSession_t *)(pContext->session);
RASPENTRY *pRasEntry = &pSession->rasEntry;
DEBUGMSG(ZONE_FUNCTION, (TEXT( "pppIpv6cp_OptValueInit\n" )));
//
// Disable Van Jacobsen TCP header compression until it is enabled via
// option negotiation.
//
pContext->local.VJCompressionEnabled = FALSE;
// local.MaxSlotID tells the peer what is the maximum slot number that
// we want the peer to send to us.
pContext->local.MaxSlotId = (BYTE)pContext->VJMaxSlotIdRx;
pContext->local.CompSlotId = (BYTE)pContext->VJEnableSlotIdCompressionRx;
pContext->local.ipAddress = 0;
pContext->peer.VJCompressionEnabled = FALSE;
pContext->peer.ipAddress = 0;
pContext->bNakReceived = FALSE;
if (pSession->bIsServer)
{
// Server
// Address will be retrieved when we are building the IPCP config request
}
else
{
// Client
// We'll send an IP address of 0.0.0.0 to the server unless a flag specifies
// otherwise. Sending 0.0.0.0 requests the server to NAK with an IP address
// for us to use.
//
if (pSession->dwAlwaysSuggestIpAddr || (pRasEntry->dwfOptions & RASEO_SpecificIpAddr))
{
memcpy( &pContext->local.ipAddress, &pRasEntry->ipaddr, sizeof( RASIPADDR ) );
DEBUGMSG( ZONE_NCP, (TEXT("ipcp:RasEntry IP Address: 0x%x\r\n" ), pContext->local.ipAddress ));
}
}
}
////////// IP Compression Protocol option callbacks /////////////////////
DWORD
ipcpBuildIPCompressionOptionCb(
IN PVOID context,
IN OUT POptionInfo pInfo,
OUT PBYTE pOptData,
OUT PDWORD pcbOptData)
//
// Called to fill in the data for an IP-Compression-Protocol option
// that is part of a configure-request we will send to the peer.
//
{
PIPCPContext pContext = (PIPCPContext)context;
DWORD dwResult = NO_ERROR;
//
// Make sure there is enough room to put our option data.
//
ASSERT(*pcbOptData >= 4);
memcpy(pOptData, &g_abVJProtocolID[0], sizeof(g_abVJProtocolID));
pOptData[2] = pContext->local.MaxSlotId;
pOptData[3] = pContext->local.CompSlotId;
*pcbOptData = 4;
return dwResult;
}
DWORD
ipcpAckIPCompressionOptionCb(
IN PVOID context,
IN OUT POptionInfo pInfo,
IN PBYTE pOptData,
IN DWORD cbOptData)
//
// Called when the peer ACKs the IP-Compression-Protocol option
// that we sent in a CR. Since we both now agree on the IP-Compression-Protocol,
// we can commit to using it.
//
{
PIPCPContext pContext = (PIPCPContext)context;
DWORD dwResult = NO_ERROR;
pContext->local.VJCompressionEnabled = TRUE;
return dwResult;
}
DWORD
ipcpNakIPCompressionOptionCb(
IN PVOID context,
IN OUT struct OptionInfo *pInfo,
IN PBYTE pOptData,
IN DWORD cbOptData)
//
// Called when the peer sends us a configure-nak for an IP-Compression-Protocol option
// to suggest an IP-Compression-Protocol that we should use.
//
{
PIPCPContext pContext = (PIPCPContext)context;
DWORD dwResult = NO_ERROR;
BYTE MaxSlotId,
CompSlotId;
//
// We only support Van Jacobson, so if the peer is NAKing with anything else
// we just drop the attempt to negotiate VJ
//
if ((cbOptData < 4)
|| memcmp(pOptData, &g_abVJProtocolID[0], sizeof(g_abVJProtocolID)) != 0)
{
// Peer is suggesting an unsupported compression protocol,
// treat it as a reject so we don't attempt to configure it.
pInfo->onsLocal = ONS_Rejected;
}
else
{
MaxSlotId = pOptData[2];
CompSlotId = pOptData[3];
//
// If the peer wants to use a value <= our configured max (default 15),
// then agree to use the peer's suggestion. Otherwise, ignore it.
// If we agreed to let the peer send us VJ compressed headers with
// slotIDs > the max slot ID then we wouldn't be able to decode those
// packets.
//
if (MaxSlotId <= (pContext->VJMaxSlotIdRx))
{
// Save NAK value for use in our next Config-Request
pContext->local.MaxSlotId = MaxSlotId;
}
//
// If the peer really wants to send compressed slot IDs, we'll play along
// even if we wanted it disabled.
//
DEBUGMSG(ZONE_WARN && (0 == pContext->VJEnableSlotIdCompressionRx) && CompSlotId,
(L"PPP: WARNING - Peer wants to send with VJ Slot ID Compression even though we want it disabled\n"));
pContext->local.CompSlotId = CompSlotId;
}
return dwResult;
}
DWORD
ipcpRequestIPCompressionCb(
IN OUT PVOID context,
IN OUT POptionInfo pInfo,
OUT PBYTE pCode,
IN OUT PBYTE *ppOptData,
IN OUT PDWORD pcbOptData)
//
// Called when we receive an IPCP configure request containing
// the IP-Compression-Protocol option. The peer is telling us what
// compression protocol it wants to use to send packets to us.
//
{
PIPCPContext pContext = (PIPCPContext)context;
DWORD dwResult = NO_ERROR;
PBYTE pOptData = *ppOptData;
DWORD cbOptData= *pcbOptData;
//
// We only support Van Jacobson, so if the peer is requesting anything else
// we NAK and suggest VJ.
//
if ((pOptData == NULL) // Peer did not request compression, we want to suggest it
|| (cbOptData < 4)
|| (memcmp(pOptData, &g_abVJProtocolID[0], sizeof(g_abVJProtocolID)) != 0)
|| pOptData[2] > pContext->VJMaxSlotIdTx)
{
// Peer is suggesting an unsupported compression protocol,
// or more states than we can handle for VJ compression.
// Send a NAK back with our VJ options
memcpy(&pContext->optDataVJ[0], &g_abVJProtocolID[0], sizeof(g_abVJProtocolID));
pContext->optDataVJ[2] = (BYTE)pContext->VJMaxSlotIdTx;
pContext->optDataVJ[3] = (BYTE)pContext->VJEnableSlotIdCompressionTx;
*pCode = PPP_CONFIGURE_NAK;
*ppOptData = &pContext->optDataVJ[0];
*pcbOptData = 4;
}
else // VJ requested with acceptable maxStates
{
*pCode = PPP_CONFIGURE_ACK;
// Save peer values
// Note that we won't use SlotId Compression if we have disabled it locally,
// even though we may be agreeing to it now (should always be able to send
// ok with uncompressed SlotIds).
pContext->peer.VJCompressionEnabled = TRUE;
pContext->peer.MaxSlotId = pOptData[2];
pContext->peer.CompSlotId = pOptData[3];
}
return dwResult;
}
/////////////// IP Address configuration callbacks ////////////////////////////
DWORD
ipcpBuildIPAddressOptionCb(
IN PVOID context,
IN OUT POptionInfo pInfo,
OUT PBYTE pOptData,
OUT PDWORD pcbOptData)
//
// Called to fill in the data for anIP-Address option
// that is part of a configure-request we will send to the peer.
//
{
PIPCPContext pContext = (PIPCPContext)context;
pppSession_t *pSession = pContext->session;
DWORD dwResult = NO_ERROR;
if (pSession->bIsServer)
{
//
// If we are a server then get the IP address
// (static or DHCP) allocated when the line
// was enabled.
//
pContext->local.ipAddress = PPPServerGetSessionServerIPAddress(pSession);
DEBUGMSG(ZONE_IPCP, (TEXT("PPP: Server assigning IP Address %u.%u.%u.%u to itself\n"), IPADDROUT(pContext->local.ipAddress)));
}
DWORD_TO_IPADDR(pOptData, pContext->local.ipAddress);
*pcbOptData = 4;
return dwResult;
}
DWORD
ipcpAckIPAddressOptionCb(
IN PVOID context,
IN OUT POptionInfo pInfo,
IN PBYTE pOptData,
IN DWORD cbOptData)
//
// Called when the peer ACKs the IP-Address option
// that we sent in a CR.
//
{
PIPCPContext pContext = (PIPCPContext)context;
DWORD dwResult = NO_ERROR;
RASPENTRY *pRasEntry = &pContext->session->rasEntry;
return dwResult;
}
DWORD
ipcpNakIPAddressOptionCb(
IN PVOID context,
IN OUT struct OptionInfo *pInfo,
IN PBYTE pOptData,
IN DWORD cbOptData)
//
// Called when the peer sends us a configure-nak for an IP-Address option
// to suggest an IP-Address that we should use.
//
{
PIPCPContext pContext = (PIPCPContext)context;
DWORD dwResult = NO_ERROR;
DWORD ipAddrSuggestedByPeer;
IPADDR_TO_DWORD(ipAddrSuggestedByPeer, pOptData);
pContext->bNakReceived = TRUE;
if (ipAddrSuggestedByPeer == 0 || ipAddrSuggestedByPeer == 0xFFFFFFFF)
{
//
// IP address is 0 or the broadcast address, neither of which
// is valid. We will ignore it and do no further negotiation
// of this option (treat it as if the peer had REJected it instead).
//
pInfo->onsLocal = ONS_Rejected;
DEBUGMSG(ZONE_WARN, (TEXT("PPP: WARNING - Server NAKed option %hs with Invalid IPAddr=%x\n"),
pInfo->pDescriptor->szName, ipAddrSuggestedByPeer));
}
else
{
//
// IP address seems reasonable. Save it for use in subsequent config-request
//
pContext->local.ipAddress = ipAddrSuggestedByPeer;
}
return dwResult;
}
DWORD
ipcpRejIPAddressOptionCb(
IN PVOID context,
IN OUT struct OptionInfo *pInfo,
IN PBYTE pOptData,
IN DWORD cbOptData)
//
// Called when the peer sends us a configure-rej for an IP-Address option
// to suggest an IP-Address that we should use.
//
{
PIPCPContext pContext = (PIPCPContext)context;
DWORD dwResult = NO_ERROR;
RASPENTRY *pRasEntry = &pContext->session->rasEntry;
// We really need to configure an IP address.
// The only known case where the peer will
// reject the IP address is when we are talking
// to Win95 and send it address 0.0.0.0 (really
// requesting it to configure our address). In
// that case, we fall back to using our static
// assigned address and retry that on the configure
// request.
if (0 == memcmp(&pContext->local.ipAddress, &pRasEntry->ipaddr, 4))
{
// We have no alternative static IP address to try, and the server has
// rejected the address we were trying. So, we have no way to recover from the server rejection.
//
// Set the require level to "Required", which in combination with the "Rejected"
// status will cause us to fail out when we try to build our next configure request.
//
DEBUGMSG( ZONE_NCP, (TEXT("PPP: IP Address %x REJected\n" ), pContext->local.ipAddress ));
pInfo->orlLocal = ORL_Required;
}
else
{
pInfo->onsLocal = ONS_Naked;
memcpy( &pContext->local.ipAddress, &pRasEntry->ipaddr, 4 );
DEBUGMSG( ZONE_NCP, (TEXT("PPP: IP Address REJected, using static: 0x%x\r\n" ), pContext->local.ipAddress ));
}
return dwResult;
}
DWORD
ipcpRequestIPAddressCb(
IN OUT PVOID context,
IN OUT POptionInfo pInfo,
OUT PBYTE pCode,
IN OUT PBYTE *ppOptData,
IN OUT PDWORD pcbOptData)
//
// Called when we receive an IPCP configure request containing
// the IP-Address option. The peer is telling us what
// IP address it wants to use. If the IP address is 0, then
// the peer is requesting that we NAK with an IP address for it
// to use.
//
{
PIPCPContext pContext = (PIPCPContext)context;
pppSession_t *pSession = pContext->session;
DWORD dwResult = NO_ERROR;
PBYTE pOptData = *ppOptData;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -