⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 option.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 2 页
字号:
//
// 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 + -