555 lines
13 KiB
C
555 lines
13 KiB
C
|
/*
|
||
|
|
||
|
Copyright (c) 1997, Microsoft Corporation, all rights reserved
|
||
|
|
||
|
Description:
|
||
|
Remote Access PPP Bandwidth Allocation Control Protocol core routines
|
||
|
|
||
|
History:
|
||
|
Mar 24, 1997: Vijay Baliga created original version.
|
||
|
|
||
|
*/
|
||
|
|
||
|
#include <nt.h> // Required by windows.h
|
||
|
#include <ntrtl.h> // Required by windows.h
|
||
|
#include <nturtl.h> // Required by windows.h
|
||
|
#include <windows.h> // Win32 base API's
|
||
|
|
||
|
#include <rasman.h> // Required by pppcp.h
|
||
|
#include <pppcp.h> // For PPP_CONFIG, PPP_BACP_PROTOCOL, etc
|
||
|
|
||
|
#define INCL_HOSTWIRE
|
||
|
#include <ppputil.h> // For HostToWireFormat16(), etc
|
||
|
|
||
|
#include <stdlib.h> // For rand(), etc
|
||
|
#include <rtutils.h> // For TraceRegister(), etc
|
||
|
#include <raserror.h> // For ERROR_PPP_INVALID_PACKET, etc
|
||
|
#include <rasbacp.h>
|
||
|
|
||
|
DWORD DwBacpTraceId;
|
||
|
|
||
|
/*
|
||
|
|
||
|
Returns:
|
||
|
VOID
|
||
|
|
||
|
Description:
|
||
|
Used for tracing.
|
||
|
|
||
|
*/
|
||
|
|
||
|
VOID
|
||
|
TraceBacp(
|
||
|
CHAR * Format,
|
||
|
...
|
||
|
)
|
||
|
{
|
||
|
va_list arglist;
|
||
|
|
||
|
va_start(arglist, Format);
|
||
|
|
||
|
TraceVprintfEx(DwBacpTraceId,
|
||
|
0x00010000 | TRACE_USE_MASK | TRACE_USE_MSEC,
|
||
|
Format,
|
||
|
arglist);
|
||
|
|
||
|
va_end(arglist);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
|
||
|
Returns:
|
||
|
A random number
|
||
|
|
||
|
Description:
|
||
|
Returns a 4 octet random number that can be used as a magic number.
|
||
|
|
||
|
*/
|
||
|
|
||
|
DWORD
|
||
|
CreateMagicNumber(
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
srand(GetCurrentTime());
|
||
|
return(rand());
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
|
||
|
Returns:
|
||
|
NO_ERROR: Success
|
||
|
non-zero error: Failure
|
||
|
|
||
|
Description:
|
||
|
Called to initialize/uninitialize this CP. In the former case, fInitialize
|
||
|
will be TRUE; in the latter case, it will be FALSE.
|
||
|
|
||
|
*/
|
||
|
|
||
|
DWORD
|
||
|
BacpInit(
|
||
|
IN BOOL fInitialize
|
||
|
)
|
||
|
{
|
||
|
static BOOL fInitialized = FALSE;
|
||
|
|
||
|
if (fInitialize && !fInitialized)
|
||
|
{
|
||
|
fInitialized = TRUE;
|
||
|
DwBacpTraceId = TraceRegister("RASBACP");
|
||
|
TraceBacp("RasBacpDllMain: DLL_PROCESS_ATTACH");
|
||
|
}
|
||
|
else if (!fInitialize && fInitialized)
|
||
|
{
|
||
|
fInitialized = FALSE;
|
||
|
TraceBacp("RasBacpDllMain: DLL_PROCESS_DETACH");
|
||
|
TraceDeregister(DwBacpTraceId);
|
||
|
}
|
||
|
|
||
|
return(NO_ERROR);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
|
||
|
Returns:
|
||
|
NO_ERROR: Success
|
||
|
non-zero error: Failure
|
||
|
|
||
|
Description:
|
||
|
This entry point is called once before any other call to BACP is made.
|
||
|
Allocate a work buffer and initialize it.
|
||
|
|
||
|
*/
|
||
|
|
||
|
DWORD
|
||
|
BacpBegin(
|
||
|
IN OUT VOID** ppWorkBuf,
|
||
|
IN VOID* pInfo
|
||
|
)
|
||
|
{
|
||
|
DWORD dwError;
|
||
|
|
||
|
TraceBacp("BacpBegin");
|
||
|
|
||
|
*ppWorkBuf = LocalAlloc(LPTR, sizeof(BACPCB));
|
||
|
|
||
|
if (*ppWorkBuf == NULL)
|
||
|
{
|
||
|
dwError = GetLastError();
|
||
|
TraceBacp("BacpBegin: ppWorkBuf is NULL. Error: %d", dwError);
|
||
|
return(dwError);
|
||
|
}
|
||
|
|
||
|
return(NO_ERROR);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
|
||
|
Returns:
|
||
|
NO_ERROR: Success
|
||
|
|
||
|
Description:
|
||
|
This entry point frees the BACP work buffer.
|
||
|
*/
|
||
|
|
||
|
DWORD
|
||
|
BacpEnd(
|
||
|
IN VOID * pWorkBuf
|
||
|
)
|
||
|
{
|
||
|
TraceBacp("BacpEnd");
|
||
|
|
||
|
if (pWorkBuf != NULL)
|
||
|
{
|
||
|
LocalFree(pWorkBuf);
|
||
|
}
|
||
|
|
||
|
return( NO_ERROR );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
|
||
|
Returns:
|
||
|
NO_ERROR: Success
|
||
|
|
||
|
Description:
|
||
|
This entry point is called to reset the state of BACP. Will re-initialize
|
||
|
the work buffer.
|
||
|
|
||
|
*/
|
||
|
|
||
|
DWORD
|
||
|
BacpReset(
|
||
|
IN VOID * pWorkBuf
|
||
|
)
|
||
|
{
|
||
|
BACPCB * pBacpCb = (BACPCB *)pWorkBuf;
|
||
|
|
||
|
TraceBacp("BacpReset");
|
||
|
|
||
|
pBacpCb->dwLocalMagicNumber = CreateMagicNumber();
|
||
|
pBacpCb->dwRemoteMagicNumber = 0;
|
||
|
|
||
|
TraceBacp("BacpReset: Local Magic-Number: %d", pBacpCb->dwLocalMagicNumber);
|
||
|
|
||
|
return(NO_ERROR);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
|
||
|
Returns:
|
||
|
NO_ERROR: Success
|
||
|
|
||
|
Description:
|
||
|
This entry point is called when BACP is entering Open state.
|
||
|
|
||
|
*/
|
||
|
|
||
|
DWORD
|
||
|
BacpThisLayerUp(
|
||
|
IN VOID* pWorkBuf
|
||
|
)
|
||
|
{
|
||
|
BACPCB * pBacpCb = (BACPCB *)pWorkBuf;
|
||
|
|
||
|
TraceBacp("BacpThisLayerUp: Local Magic-Number: %d, "
|
||
|
"Remote Magic-Number: %d",
|
||
|
pBacpCb->dwLocalMagicNumber,
|
||
|
pBacpCb->dwRemoteMagicNumber);
|
||
|
|
||
|
return(NO_ERROR);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
|
||
|
Returns:
|
||
|
NO_ERROR: Success
|
||
|
ERROR_BUFFER_TOO_SMALL: pSendConfig is too small
|
||
|
|
||
|
Description:
|
||
|
This entry point is called to make a confifure request packet.
|
||
|
|
||
|
*/
|
||
|
|
||
|
DWORD
|
||
|
BacpMakeConfigRequest(
|
||
|
IN VOID * pWorkBuffer,
|
||
|
IN PPP_CONFIG * pSendConfig,
|
||
|
IN DWORD cbSendConfig
|
||
|
)
|
||
|
{
|
||
|
BACPCB * pBacpCb = (BACPCB*)pWorkBuffer;
|
||
|
PPP_OPTION * pPppOption = (PPP_OPTION *)pSendConfig->Data;
|
||
|
|
||
|
TraceBacp("BacpMakeConfigRequest");
|
||
|
|
||
|
if (cbSendConfig < PPP_CONFIG_HDR_LEN + PPP_OPTION_HDR_LEN + 4)
|
||
|
{
|
||
|
TraceBacp("BacpMakeConfigRequest: Buffer is too small. Size: %d",
|
||
|
cbSendConfig);
|
||
|
|
||
|
return(ERROR_BUFFER_TOO_SMALL);
|
||
|
}
|
||
|
|
||
|
pSendConfig->Code = CONFIG_REQ;
|
||
|
HostToWireFormat16((WORD)(PPP_CONFIG_HDR_LEN + PPP_OPTION_HDR_LEN + 4),
|
||
|
pSendConfig->Length);
|
||
|
|
||
|
pPppOption->Type = BACP_OPTION_FAVORED_PEER;
|
||
|
pPppOption->Length = PPP_OPTION_HDR_LEN + 4;
|
||
|
HostToWireFormat32(pBacpCb->dwLocalMagicNumber, pPppOption->Data);
|
||
|
|
||
|
return(NO_ERROR);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
|
||
|
Returns:
|
||
|
NO_ERROR: Success
|
||
|
ERROR_PPP_INVALID_PACKET: Length of option is wrong
|
||
|
|
||
|
Description:
|
||
|
This entry point is called when a configure request packet is received.
|
||
|
|
||
|
*/
|
||
|
|
||
|
DWORD
|
||
|
BacpMakeConfigResult(
|
||
|
IN VOID * pWorkBuffer,
|
||
|
IN PPP_CONFIG * pRecvConfig,
|
||
|
OUT PPP_CONFIG * pSendConfig,
|
||
|
IN DWORD cbSendConfig,
|
||
|
IN BOOL fRejectNaks
|
||
|
)
|
||
|
{
|
||
|
BACPCB * pBacpCb = (BACPCB*)pWorkBuffer;
|
||
|
PPP_OPTION * pSendOption = (PPP_OPTION *)(pSendConfig->Data);
|
||
|
PPP_OPTION * pRecvOption = (PPP_OPTION *)(pRecvConfig->Data);
|
||
|
LONG lSendLength = cbSendConfig - PPP_CONFIG_HDR_LEN;
|
||
|
LONG lRecvLength = WireToHostFormat16(pRecvConfig->Length)
|
||
|
- PPP_CONFIG_HDR_LEN;
|
||
|
DWORD dwResultType = CONFIG_ACK;
|
||
|
DWORD dwResult;
|
||
|
|
||
|
TraceBacp("BacpMakeConfigResult");
|
||
|
|
||
|
while(lRecvLength > 0)
|
||
|
{
|
||
|
if (pRecvOption->Length == 0)
|
||
|
{
|
||
|
TraceBacp("BacpMakeConfigResult: Invalid option. Length is 0");
|
||
|
|
||
|
return(ERROR_PPP_INVALID_PACKET);
|
||
|
}
|
||
|
|
||
|
if ((lRecvLength -= pRecvOption->Length) < 0)
|
||
|
{
|
||
|
TraceBacp("BacpMakeConfigResult: Invalid option. Length: %d",
|
||
|
pRecvOption->Length);
|
||
|
|
||
|
return(ERROR_PPP_INVALID_PACKET);
|
||
|
}
|
||
|
|
||
|
// We only know BACP_OPTION_FAVORED_PEER
|
||
|
|
||
|
if ((pRecvOption->Length != PPP_OPTION_HDR_LEN + 4) ||
|
||
|
(pRecvOption->Type != BACP_OPTION_FAVORED_PEER))
|
||
|
{
|
||
|
TraceBacp("BacpMakeConfigResult: Unknown option. "
|
||
|
"Type: %d, Length: %d",
|
||
|
pRecvOption->Type, pRecvOption->Length);
|
||
|
|
||
|
dwResult = CONFIG_REJ;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pBacpCb->dwRemoteMagicNumber =
|
||
|
WireToHostFormat32(pRecvOption->Data);
|
||
|
|
||
|
// A Magic-Number of zero is illegal and MUST always be Nak'd.
|
||
|
|
||
|
if ((pBacpCb->dwRemoteMagicNumber == 0) ||
|
||
|
(pBacpCb->dwRemoteMagicNumber == pBacpCb->dwLocalMagicNumber))
|
||
|
{
|
||
|
TraceBacp("BacpMakeConfigResult: Unacceptable Magic-Number: %d",
|
||
|
pBacpCb->dwRemoteMagicNumber);
|
||
|
|
||
|
pBacpCb->dwRemoteMagicNumber = CreateMagicNumber();
|
||
|
|
||
|
TraceBacp("BacpMakeConfigResult: Suggesting new "
|
||
|
"Magic-Number: %d",
|
||
|
pBacpCb->dwRemoteMagicNumber);
|
||
|
|
||
|
dwResult = CONFIG_NAK;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
dwResult = CONFIG_ACK;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
|
||
|
If we were building an ACK and we got a NAK or reject OR we were
|
||
|
building a NAK and we got a reject.
|
||
|
|
||
|
*/
|
||
|
|
||
|
if ( ((dwResultType == CONFIG_ACK) && (dwResult != CONFIG_ACK)) ||
|
||
|
((dwResultType == CONFIG_NAK) && (dwResult == CONFIG_REJ)))
|
||
|
{
|
||
|
dwResultType = dwResult;
|
||
|
pSendOption = (PPP_OPTION *)(pSendConfig->Data);
|
||
|
lSendLength = cbSendConfig - PPP_CONFIG_HDR_LEN;
|
||
|
}
|
||
|
|
||
|
|
||
|
// Add the option to the list.
|
||
|
|
||
|
if (dwResult == dwResultType)
|
||
|
{
|
||
|
/*
|
||
|
|
||
|
If this option is to be rejected, simply copy the rejected option
|
||
|
to the send buffer.
|
||
|
|
||
|
*/
|
||
|
|
||
|
if ((dwResult == CONFIG_REJ) ||
|
||
|
((dwResult == CONFIG_NAK) && (fRejectNaks)))
|
||
|
{
|
||
|
CopyMemory(pSendOption, pRecvOption, pRecvOption->Length);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pSendOption->Type = BACP_OPTION_FAVORED_PEER;
|
||
|
pSendOption->Length = PPP_OPTION_HDR_LEN + 4;
|
||
|
HostToWireFormat32(pBacpCb->dwRemoteMagicNumber,
|
||
|
pSendOption->Data);
|
||
|
}
|
||
|
|
||
|
lSendLength -= pSendOption->Length;
|
||
|
|
||
|
pSendOption = (PPP_OPTION *)
|
||
|
((BYTE *)pSendOption + pSendOption->Length);
|
||
|
}
|
||
|
|
||
|
pRecvOption = (PPP_OPTION *)((BYTE*)pRecvOption + pRecvOption->Length);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
|
||
|
If this was an NAK and we have cannot send any more NAKS then we make this
|
||
|
a REJECT packet.
|
||
|
|
||
|
*/
|
||
|
|
||
|
if ((dwResultType == CONFIG_NAK) && fRejectNaks)
|
||
|
pSendConfig->Code = CONFIG_REJ;
|
||
|
else
|
||
|
pSendConfig->Code = (BYTE)dwResultType;
|
||
|
|
||
|
TraceBacp("BacpMakeConfigResult: Sending %s",
|
||
|
pSendConfig->Code == CONFIG_ACK ? "ACK" :
|
||
|
(pSendConfig->Code == CONFIG_NAK ? "NAK" : "REJ"));
|
||
|
|
||
|
HostToWireFormat16((WORD)(cbSendConfig - lSendLength), pSendConfig->Length);
|
||
|
|
||
|
return(NO_ERROR);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
|
||
|
Returns:
|
||
|
NO_ERROR: Success
|
||
|
ERROR_PPP_INVALID_PACKET: This is not the packet we sent
|
||
|
|
||
|
Description:
|
||
|
This entry point is called when a configure ack or configure rej packet is
|
||
|
received.
|
||
|
|
||
|
*/
|
||
|
|
||
|
DWORD
|
||
|
BacpConfigAckOrRejReceived(
|
||
|
IN VOID * pWorkBuffer,
|
||
|
IN PPP_CONFIG * pRecvConfig
|
||
|
)
|
||
|
{
|
||
|
BACPCB * pBacpCb = (BACPCB *)pWorkBuffer;
|
||
|
PPP_OPTION * pRecvOption = (PPP_OPTION *)(pRecvConfig->Data);
|
||
|
DWORD dwLength = WireToHostFormat16(pRecvConfig->Length);
|
||
|
DWORD dwMagicNumber = WireToHostFormat32(pRecvOption->Data);
|
||
|
|
||
|
TraceBacp("BacpConfigAckOrRejReceived");
|
||
|
|
||
|
if ((dwLength != PPP_CONFIG_HDR_LEN + PPP_OPTION_HDR_LEN + 4) ||
|
||
|
(pRecvOption->Type != BACP_OPTION_FAVORED_PEER) ||
|
||
|
(pRecvOption->Length != PPP_OPTION_HDR_LEN + 4) ||
|
||
|
(dwMagicNumber != pBacpCb->dwLocalMagicNumber))
|
||
|
{
|
||
|
TraceBacp("BacpConfigAckOrRejReceived: Invalid packet received");
|
||
|
|
||
|
return(ERROR_PPP_INVALID_PACKET);
|
||
|
}
|
||
|
else
|
||
|
return(NO_ERROR);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
|
||
|
Returns:
|
||
|
NO_ERROR: Success
|
||
|
ERROR_PPP_INVALID_PACKET: Length of option is wrong
|
||
|
|
||
|
Description:
|
||
|
This entry point is called when a configure nak packet is received.
|
||
|
|
||
|
*/
|
||
|
|
||
|
DWORD
|
||
|
BacpConfigNakReceived(
|
||
|
IN VOID * pWorkBuffer,
|
||
|
IN PPP_CONFIG * pRecvConfig
|
||
|
)
|
||
|
{
|
||
|
BACPCB * pBacpCb = (BACPCB *)pWorkBuffer;
|
||
|
PPP_OPTION * pOption = (PPP_OPTION*)(pRecvConfig->Data);
|
||
|
LONG lRecvLength = WireToHostFormat16(pRecvConfig->Length)
|
||
|
- PPP_CONFIG_HDR_LEN;
|
||
|
TraceBacp("BacpConfigNakReceived");
|
||
|
|
||
|
while (lRecvLength > 0)
|
||
|
{
|
||
|
if (pOption->Length == 0)
|
||
|
{
|
||
|
TraceBacp("BacpConfigNakReceived: Invalid option. Length is 0");
|
||
|
|
||
|
return(ERROR_PPP_INVALID_PACKET);
|
||
|
}
|
||
|
|
||
|
if ((lRecvLength -= pOption->Length) < 0)
|
||
|
{
|
||
|
TraceBacp("BacpConfigNakReceived: Invalid option. Length: %d",
|
||
|
pOption->Length);
|
||
|
|
||
|
return(ERROR_PPP_INVALID_PACKET);
|
||
|
}
|
||
|
|
||
|
if ((pOption->Type == BACP_OPTION_FAVORED_PEER) &&
|
||
|
(pOption->Length == PPP_OPTION_HDR_LEN + 4))
|
||
|
{
|
||
|
pBacpCb->dwLocalMagicNumber = WireToHostFormat32(pOption->Data);
|
||
|
|
||
|
TraceBacp("BacpConfigNakReceived: New Local Magic-Number: %d",
|
||
|
pBacpCb->dwLocalMagicNumber);
|
||
|
}
|
||
|
|
||
|
pOption = (PPP_OPTION *)((BYTE *)pOption + pOption->Length);
|
||
|
}
|
||
|
|
||
|
return(NO_ERROR);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
|
||
|
Returns:
|
||
|
NO_ERROR: Success
|
||
|
ERROR_INVALID_PARAMETER: Protocol id is unrecogized
|
||
|
|
||
|
Description:
|
||
|
This entry point is called to get all information for the control protocol
|
||
|
in this module.
|
||
|
|
||
|
*/
|
||
|
|
||
|
DWORD
|
||
|
BacpGetInfo(
|
||
|
IN DWORD dwProtocolId,
|
||
|
OUT PPPCP_INFO* pCpInfo
|
||
|
)
|
||
|
{
|
||
|
if (dwProtocolId != PPP_BACP_PROTOCOL)
|
||
|
return(ERROR_INVALID_PARAMETER);
|
||
|
|
||
|
ZeroMemory(pCpInfo, sizeof(PPPCP_INFO));
|
||
|
|
||
|
pCpInfo->Protocol = PPP_BACP_PROTOCOL;
|
||
|
lstrcpy(pCpInfo->SzProtocolName, "BACP");
|
||
|
pCpInfo->Recognize = PROT_REJ;
|
||
|
pCpInfo->RasCpInit = BacpInit;
|
||
|
pCpInfo->RasCpBegin = BacpBegin;
|
||
|
pCpInfo->RasCpEnd = BacpEnd;
|
||
|
pCpInfo->RasCpReset = BacpReset;
|
||
|
pCpInfo->RasCpThisLayerUp = BacpThisLayerUp;
|
||
|
pCpInfo->RasCpMakeConfigRequest = BacpMakeConfigRequest;
|
||
|
pCpInfo->RasCpMakeConfigResult = BacpMakeConfigResult;
|
||
|
pCpInfo->RasCpConfigAckReceived = BacpConfigAckOrRejReceived;
|
||
|
pCpInfo->RasCpConfigNakReceived = BacpConfigNakReceived;
|
||
|
pCpInfo->RasCpConfigRejReceived = BacpConfigAckOrRejReceived;
|
||
|
|
||
|
return(NO_ERROR);
|
||
|
}
|
||
|
|