2020-09-30 17:17:25 +02:00

290 lines
7.5 KiB
C++

/*++
Copyright (c) 2000 Microsoft Corporation
ncp.cpp
Abstract:
Network control protocol and IPCP implementation.
Revision History:
07-27-00 vadimg created
--*/
#include "precomp.h"
/***************************************************************************\
* NcpStart
*
\***************************************************************************/
BOOL NcpStart(DWORD CpIndex)
{
if (!FsmInit(CpIndex)) {
return FALSE;
}
FsmOpen(CpIndex);
FsmUp(CpIndex);
return TRUE;
}
/***************************************************************************\
* NcpReset
*
\***************************************************************************/
VOID NcpReset(VOID)
{
gIp.IpAddrRemote = 0;
gIp.IpAddrLocal = 0;
gIp.IpAddrDns = 0;
}
/***************************************************************************\
* AddIpAddressOption
*
\***************************************************************************/
VOID AddIpAddressOption(BYTE *pBuf, BYTE bOption, IPADDR ipaddr)
{
*pBuf++ = bOption;
*pBuf++ = IPADDRESSOPTIONLEN;
*((IPADDR*)pBuf) = ipaddr;
}
/***************************************************************************\
* RejectCheck
*
\***************************************************************************/
DWORD RejectCheck(PPP_CONFIG* pRecvBuf, PPP_CONFIG* pSendBuf, BOOL *pfRej)
{
PPP_OPTION *pROption = (PPP_OPTION*)pRecvBuf->Data;
PPP_OPTION *pSOption = (PPP_OPTION*)pSendBuf->Data;
WORD cbPacket = WireToHostFormat16(pRecvBuf->Length);
WORD cbLeft = cbPacket - PPP_CONFIG_HDR_LEN;
*pfRej = FALSE;
while (cbLeft > 0) {
if (cbLeft < pROption->Length) {
return ERROR_PPP_INVALID_PACKET;
}
if (pROption->Type == IPCP_IpCompression) {
*pfRej = TRUE;
CopyMemory((VOID*)pSOption, (VOID*)pROption, pROption->Length);
pSOption = (PPP_OPTION*)((BYTE*)pSOption + pROption->Length);
} else {
IPADDR ipaddr;
BOOL fBad = (pROption->Type != IPCP_IpAddress ||
pROption->Length != IPADDRESSOPTIONLEN);
if (!fBad) {
CopyMemory(&ipaddr, pROption->Data, sizeof(IPADDR));
}
if (fBad || ipaddr == 0) {
*pfRej = TRUE;
CopyMemory((VOID*)pSOption, (VOID*)pROption, pROption->Length);
pSOption = (PPP_OPTION*)((BYTE*)pSOption + pROption->Length);
} else {
gIp.IpAddrRemote = ipaddr;
}
}
if (pROption->Length && pROption->Length < cbLeft) {
cbLeft -= pROption->Length;
} else {
cbLeft = 0;
}
pROption = (PPP_OPTION*)((BYTE*)pROption + pROption->Length);
}
if (*pfRej) {
pSendBuf->Code = CONFIG_REJ;
HostToWireFormat16((WORD)((BYTE*)pSOption - (BYTE*)pSendBuf), pSendBuf->Length);
}
return NO_ERROR;
}
/***************************************************************************\
* IpcpMakeConfigRequest
*
\***************************************************************************/
DWORD IpcpMakeConfigRequest(PPP_CONFIG *pSendConfig, DWORD cbSendConfig)
{
BYTE *pb = pSendConfig->Data;
WORD cbPacket = PPP_CONFIG_HDR_LEN;
AddIpAddressOption(pb, IPCP_IpAddress, gIp.IpAddrLocal);
cbPacket += IPADDRESSOPTIONLEN;
pb += IPADDRESSOPTIONLEN;
AddIpAddressOption(pb, IPCP_DnsIpAddress, gIp.IpAddrDns);
cbPacket += IPADDRESSOPTIONLEN;
pb += IPADDRESSOPTIONLEN;
HostToWireFormat16(cbPacket, pSendConfig->Length);
return NO_ERROR;
}
/***************************************************************************\
* IpcpMakeConfigResult
*
\***************************************************************************/
DWORD IpcpMakeConfigResult(PPP_CONFIG *pRecvBuf, PPP_CONFIG *pSendBuf,
DWORD cbSendBuf, BOOL fRejectNaks)
{
DWORD dwErr;
BOOL fRej;
WORD cbPacket;
dwErr = RejectCheck(pRecvBuf, pSendBuf, &fRej);
if (dwErr != 0) {
return dwErr;
}
if (fRej) {
return NO_ERROR;
}
cbPacket = WireToHostFormat16(pRecvBuf->Length);
CopyMemory(pSendBuf, pRecvBuf, cbPacket);
pSendBuf->Code = CONFIG_ACK;
return 0;
}
/***************************************************************************\
* IpcpConfigAckReceived
*
\***************************************************************************/
DWORD IpcpConfigAckReceived(PPP_CONFIG *pRecvBuf)
{
return NO_ERROR;
}
/***************************************************************************\
* IpcpConfigRejReceived
*
\***************************************************************************/
DWORD IpcpConfigRejReceived(PPP_CONFIG *pRecvBuf)
{
return NO_ERROR;
}
/***************************************************************************\
* IpcpConfigNakReceived
*
\***************************************************************************/
DWORD IpcpConfigNakReceived(PPP_CONFIG* pRecvBuf)
{
PPP_OPTION *pROption = (PPP_OPTION*)pRecvBuf->Data;
WORD cbPacket = WireToHostFormat16(pRecvBuf->Length);
WORD cbLeft = cbPacket - PPP_CONFIG_HDR_LEN;
IPADDR ipaddr;
while (cbLeft > 0) {
if (cbLeft < pROption->Length) {
return ERROR_PPP_INVALID_PACKET;
}
switch (pROption->Type) {
case IPCP_IpAddress:
if (pROption->Length != IPADDRESSOPTIONLEN) {
return ERROR_PPP_INVALID_PACKET;
}
CopyMemory(&ipaddr, pROption->Data, sizeof(IPADDR));
if (ipaddr == 0) {
return ERROR_PPP_INVALID_PACKET;
}
gIp.IpAddrLocal = ipaddr;
break;
case IPCP_DnsIpAddress:
if (pROption->Length != IPADDRESSOPTIONLEN) {
return ERROR_PPP_INVALID_PACKET;
}
CopyMemory(&gIp.IpAddrDns, pROption->Data, sizeof(IPADDR));
break;
}
if (pROption->Length && pROption->Length < cbLeft) {
cbLeft -= pROption->Length;
} else {
cbLeft = 0;
}
pROption = (PPP_OPTION*)((BYTE*)pROption + pROption->Length);
}
return NO_ERROR;
}
/***************************************************************************\
* IpcpBegin
*
\***************************************************************************/
DWORD IpcpBegin(VOID)
{
return NO_ERROR;
}
/***************************************************************************\
* IpcpEnd
*
\***************************************************************************/
DWORD IpcpEnd(VOID)
{
return NO_ERROR;
}
/***************************************************************************\
* GetIpcpInfo
*
\***************************************************************************/
VOID GetIpcpInfo(PPP_CP_INFO *pInfo)
{
ZeroMemory(pInfo, sizeof(PPP_CP_INFO));
pInfo->Protocol = PPP_IPCP_PROTOCOL;
pInfo->Recognize = MAX_IPCP_CODE;
pInfo->CP_Begin = IpcpBegin;
pInfo->CP_End = IpcpEnd;
pInfo->CP_MakeConfigRequest = IpcpMakeConfigRequest;
pInfo->CP_MakeConfigResult = IpcpMakeConfigResult;
pInfo->CP_ConfigAckReceived = IpcpConfigAckReceived;
pInfo->CP_ConfigRejReceived = IpcpConfigRejReceived;
pInfo->CP_ConfigNakReceived = IpcpConfigNakReceived;
}