Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1075 lines
27 KiB

/********************************************************************/
/** Copyright(c) 1989 Microsoft Corporation. **/
/********************************************************************/
//***
//
// Filename: rascbcp.c
//
// Description: This module contains code to implement the PPP Callback
// Control Protocol.
//
// History: April 11,1994. NarenG Created original version
//
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <ntlsa.h>
#include <ntmsv1_0.h>
#include <crypt.h>
#include <windows.h>
#include <lmcons.h>
#include <string.h>
#include <stdlib.h>
#include <rasman.h>
#include <pppcp.h>
#define INCL_PWUTIL
#define INCL_HOSTWIRE
#include <ppputil.h>
#include "rascbcp.h"
#include <raserror.h>
//**
//
// Call: CbCPGetInfo
//
// Returns: NO_ERROR
//
// Description: CbCPGetInfo entry point called by the PPP engine.
// See RasCpGetInfo interface documentation.
//
DWORD
CbCPGetInfo(
IN DWORD dwProtocolId,
OUT PPPCP_INFO* pInfo
)
{
ZeroMemory( pInfo, sizeof(PPPCP_INFO) );
pInfo->Protocol = (DWORD)PPP_CBCP_PROTOCOL;
lstrcpy(pInfo->SzProtocolName, "CBCP");
pInfo->Recognize = MAX_CBCP_CODE + 1;
pInfo->RasCpBegin = CbCPBegin;
pInfo->RasCpEnd = CbCPEnd;
pInfo->RasApMakeMessage = CbCPMakeMessage;
return( NO_ERROR );
}
//**
//
// Call: CbCPBegin
//
// Returns: NO_ERROR - success
// non-zero return code - failure
//
// Description: RasCpBegin entry point called by the PPP engine thru the
// passed address. See RasCp interface documentation. This is
// called by the PPP engine before any other calls to CbCP is
// made.
//
DWORD
CbCPBegin(
OUT VOID** ppWorkBuf,
IN VOID* pInfo
)
{
PPPCB_INPUT * pInput = (PPPCB_INPUT *)pInfo;
CBCP_WORKBUFFER * pWorkBuf;
DWORD dwRetCode;
//
// Allocate work buffer.
//
pWorkBuf = (CBCP_WORKBUFFER *)LocalAlloc(LPTR,sizeof(CBCP_WORKBUFFER));
if ( pWorkBuf == NULL )
{
return( GetLastError() );
}
pWorkBuf->State = CBCP_STATE_INITIAL;
pWorkBuf->fServer = pInput->fServer;
//
// If we are the server side then get all the callback information for
// this user
//
if ( pWorkBuf->fServer )
{
pWorkBuf->fCallbackPrivilege = pInput->bfCallbackPrivilege;
strcpy( pWorkBuf->szCallbackNumber, pInput->pszCallbackNumber );
}
else
{
pWorkBuf->CallbackDelay = pInput->CallbackDelay;
}
//
// Register work buffer with engine.
//
*ppWorkBuf = pWorkBuf;
return( NO_ERROR );
}
//**
//
// Call: CbCPEnd
//
// Returns: NO_ERROR - success
//
// Description: Called by the PPP engine to notify this Control Protocol to
// clean up.
//
DWORD
CbCPEnd(
IN VOID* pWorkBuffer
)
{
CBCP_WORKBUFFER * pWorkBuf = (CBCP_WORKBUFFER *)pWorkBuffer;
if ( pWorkBuf->pRequest != (PPP_CONFIG *)NULL )
{
LocalFree( pWorkBuf->pRequest );
}
if ( pWorkBuf->pResponse != (PPP_CONFIG *)NULL )
{
LocalFree( pWorkBuf->pResponse );
}
if ( pWorkBuf != NULL )
{
LocalFree( pWorkBuf );
}
return( NO_ERROR );
}
//**
//
// Call: CbCPMakeMessage
//
// Returns: NO_ERROR - success
// non-zero return code - failure
//
// Description: Called by the PPP engine to process a CbCP event. ie to send
// a packet, to process a received packet or to process a timeout
// event.
//
DWORD
CbCPMakeMessage(
IN VOID* pWorkBuffer,
IN PPP_CONFIG* pReceiveBuf,
OUT PPP_CONFIG* pSendBuf,
IN DWORD cbSendBuf,
OUT PPPAP_RESULT* pResult,
IN PPPAP_INPUT* pInput
)
{
CBCP_WORKBUFFER* pWorkBuf = (CBCP_WORKBUFFER *)pWorkBuffer;
return( (pWorkBuf->fServer)
? CbCPSMakeMessage( pWorkBuf,
pReceiveBuf,
pSendBuf,
cbSendBuf,
(PPPCB_RESULT *)pResult,
(PPPCB_INPUT *)pInput )
: CbCPCMakeMessage( pWorkBuf,
pReceiveBuf,
pSendBuf,
cbSendBuf,
(PPPCB_RESULT *)pResult,
(PPPCB_INPUT *)pInput ) );
}
//**
//
// Call: CbCPCMakeMessage
//
// Returns: NO_ERROR - success
// non-zero return - failure
//
// Description: Called to process the client side of Callback Control
// Protocol.
//
DWORD
CbCPCMakeMessage(
IN CBCP_WORKBUFFER * pWorkBuf,
IN PPP_CONFIG* pReceiveBuf,
OUT PPP_CONFIG* pSendBuf,
IN DWORD cbSendBuf,
OUT PPPCB_RESULT* pResult,
IN PPPCB_INPUT* pInput
)
{
DWORD dwRetCode;
DWORD dwLength;
switch( pWorkBuf->State )
{
case CBCP_STATE_INITIAL:
//
// Do nothing, wait for request
//
pWorkBuf->State = CBCP_STATE_WAIT_FOR_REQUEST;
pResult->Action = APA_NoAction;
pResult->fGetCallbackNumberFromUser = FALSE;
break;
case CBCP_STATE_WAIT_FOR_REQUEST:
//
// We have received a callback request from the server.
// Save the callback request.
//
dwLength = WireToHostFormat16( pReceiveBuf->Length );
if ( ( dwLength < PPP_CONFIG_HDR_LEN ) ||
( pReceiveBuf->Code != CBCP_CODE_Request ) )
{
return( ERROR_PPP_INVALID_PACKET );
}
pWorkBuf->pRequest = (PPP_CONFIG *)LocalAlloc( LPTR, dwLength );
if ( pWorkBuf->pRequest == (PPP_CONFIG *)NULL )
{
return( GetLastError() );
}
memcpy( pWorkBuf->pRequest, pReceiveBuf, dwLength );
//
// Find out what kind of callback privileges we have.
//
dwRetCode = GetCallbackPrivilegeFromRequest(
pWorkBuf->pRequest,
&(pWorkBuf->fCallbackPrivilege));
if ( dwRetCode != NO_ERROR )
{
return( dwRetCode );
}
//
// If we have user specifiable callback, then we need to get this
// information from the user.
//
if ( pWorkBuf->fCallbackPrivilege == RASPRIV_CallerSetCallback )
{
pResult->fGetCallbackNumberFromUser=TRUE;
pResult->Action =APA_NoAction;
pWorkBuf->State =CBCP_STATE_GET_CALLBACK_NUMBER;
break;
}
//
// Otherwise we make a reponse with preset or no callback
//
dwRetCode = MakeResponse( pWorkBuf->fCallbackPrivilege,
(LPSTR)NULL,
pWorkBuf->CallbackDelay,
pWorkBuf->pRequest,
pSendBuf,
cbSendBuf );
if ( dwRetCode != NO_ERROR )
{
return( dwRetCode );
}
//
// Save the response sent
//
dwLength = WireToHostFormat16( pSendBuf->Length );
pWorkBuf->pResponse = (PPP_CONFIG *)LocalAlloc( LPTR, dwLength );
if ( pWorkBuf->pResponse == (PPP_CONFIG *)NULL )
{
return( GetLastError() );
}
memcpy( pWorkBuf->pResponse, pSendBuf, dwLength );
pResult->Action = APA_SendWithTimeout;
pResult->bIdExpected = pReceiveBuf->Id;
pWorkBuf->State = CBCP_STATE_WAIT_FOR_ACK;
break;
case CBCP_STATE_GET_CALLBACK_NUMBER:
//
// If we have not received any packet when we are called that means
// that we have got the callback number from the user.
//
if ( pReceiveBuf == (PPP_CONFIG *)NULL )
{
//
// If no callback number was supplied then we do not want to
// do callback
//
if ( *(pInput->pszCallbackNumber) == (CHAR)NULL )
{
pWorkBuf->fCallbackPrivilege = RASPRIV_NoCallback;
}
dwRetCode = MakeResponse( pWorkBuf->fCallbackPrivilege,
pInput->pszCallbackNumber,
pWorkBuf->CallbackDelay,
pWorkBuf->pRequest,
pSendBuf,
cbSendBuf );
if ( dwRetCode != NO_ERROR )
{
return( dwRetCode );
}
//
// Save the response sent
//
dwLength = WireToHostFormat16( pSendBuf->Length );
pWorkBuf->pResponse = (PPP_CONFIG*)LocalAlloc( LPTR, dwLength );
if ( pWorkBuf->pResponse == NULL )
{
return( GetLastError() );
}
memcpy( pWorkBuf->pResponse, pSendBuf, dwLength );
pResult->Action = APA_SendWithTimeout;
pResult->bIdExpected = pWorkBuf->pResponse->Id;
pWorkBuf->State = CBCP_STATE_WAIT_FOR_ACK;
break;
}
else
{
if ( pReceiveBuf->Code == CBCP_CODE_Request )
{
//
// If we received another callback request, just save the id.
// If the current request is different than the previous one
//
dwLength = WireToHostFormat16( pWorkBuf->pRequest->Length );
if (( WireToHostFormat16( pReceiveBuf->Length ) != dwLength ) ||
( memcmp( ((PBYTE)(pWorkBuf->pRequest))+PPP_CONFIG_HDR_LEN,
((PBYTE)pReceiveBuf) + PPP_CONFIG_HDR_LEN,
dwLength - PPP_CONFIG_HDR_LEN ) ) )
{
return( ERROR_PPP_INVALID_PACKET );
}
pWorkBuf->pRequest->Id = pReceiveBuf->Id;
}
else
{
return( ERROR_PPP_INVALID_PACKET );
}
}
pResult->Action = APA_NoAction;
pResult->fGetCallbackNumberFromUser = FALSE;
break;
case CBCP_STATE_WAIT_FOR_ACK:
//
// If the receive buffer is NULL, then we have a timeout event,
// resend the response
//
if ( pReceiveBuf == (PPP_CONFIG *)NULL )
{
dwLength = WireToHostFormat16( pWorkBuf->pResponse->Length );
if ( dwLength > cbSendBuf )
{
return( ERROR_BUFFER_TOO_SMALL );
}
memcpy( pSendBuf, pWorkBuf->pResponse, dwLength );
pResult->Action = APA_SendWithTimeout;
break;
}
//
// If we received another request then simply respond with
// the same response except change the id.
//
if ( pReceiveBuf->Code == CBCP_CODE_Request )
{
//
// If the current request is different than the previous one
//
dwLength = WireToHostFormat16( pWorkBuf->pRequest->Length );
if ( ( WireToHostFormat16( pReceiveBuf->Length ) != dwLength ) ||
( memcmp( ((PBYTE)(pWorkBuf->pRequest)) + PPP_CONFIG_HDR_LEN,
((PBYTE)pReceiveBuf) + PPP_CONFIG_HDR_LEN,
dwLength - PPP_CONFIG_HDR_LEN ) ) )
{
return( ERROR_PPP_INVALID_PACKET );
}
if ( dwLength > cbSendBuf )
{
return( ERROR_BUFFER_TOO_SMALL );
}
pWorkBuf->pRequest->Id = pReceiveBuf->Id;
pWorkBuf->pResponse->Id = pReceiveBuf->Id;
pResult->bIdExpected = pReceiveBuf->Id;
pResult->Action = APA_SendWithTimeout;
memcpy( pSendBuf,
pWorkBuf->pResponse,
WireToHostFormat16( pWorkBuf->pResponse->Length ) );
break;
}
//
// If this is an ACK, then validate it and then prepare for callback
//
if ( pReceiveBuf->Code == CBCP_CODE_Ack )
{
dwLength = WireToHostFormat16( pWorkBuf->pResponse->Length );
if ( ( WireToHostFormat16( pReceiveBuf->Length ) != dwLength ) ||
( memcmp( ((PBYTE)(pWorkBuf->pResponse)) + PPP_CONFIG_HDR_LEN,
((PBYTE)pReceiveBuf) + PPP_CONFIG_HDR_LEN,
dwLength - PPP_CONFIG_HDR_LEN ) ) )
{
//
// If this Ack is invalid then we resend the response.
//
dwLength = WireToHostFormat16( pWorkBuf->pResponse->Length );
if ( dwLength > cbSendBuf )
{
return( ERROR_BUFFER_TOO_SMALL );
}
memcpy( pSendBuf, pWorkBuf->pResponse, dwLength );
pResult->Action = APA_SendWithTimeout;
break;
}
//
// We are done
//
pResult->Action = APA_Done;
pResult->bfCallbackPrivilege = (BYTE)(pWorkBuf->fCallbackPrivilege);
break;
}
else
{
return( ERROR_PPP_INVALID_PACKET );
}
//
// Fall through
//
default:
pResult->Action = APA_NoAction;
pResult->fGetCallbackNumberFromUser = FALSE;
break;
}
return( NO_ERROR );
}
//**
//
// Call: CbCPSMakeMessage
//
// Returns: NO_ERROR - success
// non-zero return - failure
//
// Description: Will be called to process and server side Callback Control
// Protocol event.
//
DWORD
CbCPSMakeMessage(
IN CBCP_WORKBUFFER * pWorkBuf,
IN PPP_CONFIG* pReceiveBuf,
OUT PPP_CONFIG* pSendBuf,
IN DWORD cbSendBuf,
OUT PPPCB_RESULT* pResult,
IN PPPCB_INPUT* pInput
)
{
DWORD dwRetCode;
DWORD dwLength;
switch( pWorkBuf->State )
{
case CBCP_STATE_INITIAL:
//
// Make the request based on the user's callback privelege
//
dwRetCode = MakeRequest( pWorkBuf->fCallbackPrivilege,
pSendBuf,
cbSendBuf );
if ( dwRetCode != NO_ERROR )
{
return( dwRetCode );
}
//
// Set the Id of the first request to 1
//
pSendBuf->Id = 1;
//
// Save the request
//
dwLength = WireToHostFormat16( pSendBuf->Length );
pWorkBuf->pRequest = (PPP_CONFIG *)LocalAlloc( LPTR, dwLength );
if ( pWorkBuf->pRequest == (PPP_CONFIG *)NULL )
{
return( GetLastError() );
}
memcpy( pWorkBuf->pRequest, pSendBuf, dwLength );
pResult->Action = APA_SendWithTimeout2;
pResult->bIdExpected = pWorkBuf->pRequest->Id;
pWorkBuf->State = CBCP_STATE_WAIT_FOR_RESPONSE;
break;
case CBCP_STATE_WAIT_FOR_RESPONSE:
//
// If the Receive buffer is NULL that means that we got a timeout.
// So resend the request.
//
if ( pReceiveBuf == (PPP_CONFIG *)NULL )
{
dwLength = WireToHostFormat16( pWorkBuf->pRequest->Length );
if ( cbSendBuf < dwLength )
{
return( ERROR_BUFFER_TOO_SMALL );
}
//
// Increment the request id
//
(pWorkBuf->pRequest->Id)++;
memcpy( pSendBuf, pWorkBuf->pRequest, dwLength );
pResult->Action = APA_SendWithTimeout2;
pResult->bIdExpected = pWorkBuf->pRequest->Id;
pWorkBuf->State = CBCP_STATE_WAIT_FOR_RESPONSE;
break;
}
//
// Fall through
//
case CBCP_STATE_DONE:
if ( pReceiveBuf == NULL )
{
//
// If we receive a timeout in the DONE state, we just ignore it.
//
pResult->Action = APA_NoAction;
break;
}
//
// If we have received a response from the client, then validate
// it and send an ACK or another request.
//
if ( pReceiveBuf->Code == CBCP_CODE_Response )
{
//
// Check the id of the response packet. If the Id is bad then
// silently discard it
//
if ( pReceiveBuf->Id != pWorkBuf->pRequest->Id )
{
return( ERROR_PPP_INVALID_PACKET );
}
dwRetCode = ValidateResponse( pReceiveBuf, pWorkBuf );
if ( dwRetCode == ERROR_PPP_INVALID_PACKET )
{
//
// If the response received was invalid, resend the request
//
dwLength = WireToHostFormat16( pWorkBuf->pRequest->Length );
if ( cbSendBuf < dwLength )
{
return( ERROR_BUFFER_TOO_SMALL );
}
//
// Increment the request id
//
(pWorkBuf->pRequest->Id)++;
memcpy( pSendBuf, pWorkBuf->pRequest, dwLength );
pResult->Action = APA_SendWithTimeout2;
pResult->bIdExpected = pWorkBuf->pRequest->Id;
pWorkBuf->State = CBCP_STATE_WAIT_FOR_RESPONSE;
break;
}
else if ( dwRetCode != NO_ERROR )
{
return( dwRetCode );
}
//
// Send the Ack
//
dwLength = WireToHostFormat16( pReceiveBuf->Length );
if ( cbSendBuf < dwLength )
{
return( ERROR_BUFFER_TOO_SMALL );
}
memcpy( pSendBuf, pReceiveBuf, dwLength );
pSendBuf->Code = CBCP_CODE_Ack;
pSendBuf->Id = pReceiveBuf->Id;
pWorkBuf->State = CBCP_STATE_DONE;
pResult->Action = APA_SendAndDone;
pResult->bfCallbackPrivilege = (BYTE)(pWorkBuf->fCallbackPrivilege);
pResult->CallbackDelay = pWorkBuf->CallbackDelay;
strcpy( pResult->szCallbackNumber, pWorkBuf->szCallbackNumber );
}
else
{
return( ERROR_PPP_INVALID_PACKET );
}
break;
default:
break;
}
return( NO_ERROR );
}
//**
//
// Call: MakeRequest
//
// Returns: NO_ERROR - success
// ERROR_BUFFER_TOO_SMALL - failure
//
// Description: Will make a callback request packet based on the user's
// callback privilege. The Id will be filled in by the caller.
//
static DWORD
MakeRequest(
IN DWORD fCallbackPrivilege,
IN OUT PPP_CONFIG * pSendBuf,
IN DWORD cbSendBuf
)
{
PPP_OPTION * pOption;
DWORD dwLength = PPP_CONFIG_HDR_LEN;
if ( cbSendBuf < PPP_CONFIG_HDR_LEN )
{
return( ERROR_BUFFER_TOO_SMALL );
}
pOption = (PPP_OPTION *)(pSendBuf->Data);
pSendBuf->Code = CBCP_CODE_Request;
if ( ( fCallbackPrivilege & RASPRIV_NoCallback ) ||
( fCallbackPrivilege & RASPRIV_CallerSetCallback ) )
{
if ( cbSendBuf < dwLength + PPP_OPTION_HDR_LEN )
{
return( ERROR_BUFFER_TOO_SMALL );
}
pOption->Type = CBCP_TYPE_NO_CALLBACK;
pOption->Length = PPP_OPTION_HDR_LEN;
dwLength += pOption->Length;
pOption = (PPP_OPTION *)(((BYTE *)pOption) + pOption->Length);
}
if ( fCallbackPrivilege & RASPRIV_CallerSetCallback )
{
if ( cbSendBuf < dwLength + PPP_OPTION_HDR_LEN + 2 )
{
return( ERROR_BUFFER_TOO_SMALL );
}
pOption->Type = CBCP_TYPE_CALLER_SET;
pOption->Length = PPP_OPTION_HDR_LEN + 3;
*(pOption->Data) = 0; // Callback Delay
*(pOption->Data+1) = CBCP_PSTN_NUMBER; // Callback Address type
*(pOption->Data+2) = 0; // Callback Address terminating NULL
dwLength += pOption->Length;
pOption = (PPP_OPTION *)(((BYTE *)pOption) + pOption->Length);
}
if ( fCallbackPrivilege & RASPRIV_AdminSetCallback )
{
if ( cbSendBuf < dwLength + PPP_OPTION_HDR_LEN + 1)
{
return( ERROR_BUFFER_TOO_SMALL );
}
pOption->Type = CBCP_TYPE_CALLEE_SET;
pOption->Length = PPP_OPTION_HDR_LEN + 1;
*(pOption->Data) = 0; // Callback Delay
dwLength += pOption->Length;
}
HostToWireFormat16( (WORD)dwLength, (PBYTE)(pSendBuf->Length) );
return( NO_ERROR );
}
//**
//
// Call: GetCallbackPrivilegeFromRequest
//
// Returns: NO_ERROR - success
//
// Description: Will parse the callback request from the server and translate
// the PPP callback privilege to what RAS understands.
//
DWORD
GetCallbackPrivilegeFromRequest(
IN PPP_CONFIG * pRequest,
IN OUT DWORD * lpdwCallbackPriv
)
{
PPP_OPTION * pOption = (PPP_OPTION *)(pRequest->Data);
DWORD dwRequestLength = WireToHostFormat16( pRequest->Length )
- PPP_CONFIG_HDR_LEN;
*lpdwCallbackPriv = 0;
//
// Walk the options
//
while( dwRequestLength > 0 )
{
if ( dwRequestLength < PPP_OPTION_HDR_LEN )
{
return( ERROR_PPP_INVALID_PACKET );
}
switch( pOption->Type )
{
case CBCP_TYPE_NO_CALLBACK:
*lpdwCallbackPriv |= RASPRIV_NoCallback;
break;
case CBCP_TYPE_CALLEE_SET:
*lpdwCallbackPriv |= RASPRIV_AdminSetCallback;
break;
case CBCP_TYPE_CALLER_SET:
*lpdwCallbackPriv |= RASPRIV_CallerSetCallback;
break;
default:
//
// Ignore anything else.
//
break;
}
dwRequestLength = dwRequestLength - pOption->Length;
pOption = (PPP_OPTION *)(((BYTE *)pOption) + pOption->Length);
}
//
// We accept Callback privleges in the following order.
// 1) Caller settable.
// 2) Admin settable
// 3) No callback
//
if ( *lpdwCallbackPriv & RASPRIV_CallerSetCallback )
{
*lpdwCallbackPriv = RASPRIV_CallerSetCallback;
}
else if ( *lpdwCallbackPriv & RASPRIV_AdminSetCallback )
{
*lpdwCallbackPriv = RASPRIV_AdminSetCallback;
}
else if ( *lpdwCallbackPriv & RASPRIV_NoCallback )
{
*lpdwCallbackPriv = RASPRIV_NoCallback;
}
else
{
//
// If we could not translate to any RAS callback privlege we simply drop
// this packet.
//
return( ERROR_PPP_INVALID_PACKET );
}
return( NO_ERROR );
}
//**
//
// Call: MakeResponse
//
// Returns: NO_ERROR - success
//
// Description:
//
DWORD
MakeResponse(
IN DWORD fCallbackPrivilege,
IN LPSTR szCallbackNumber,
IN DWORD CallbackDelay,
IN PPP_CONFIG * pRequest,
IN OUT PPP_CONFIG * pSendBuf,
IN DWORD cbSendBuf
)
{
PPP_OPTION * pOption;
DWORD dwLength;
if ( cbSendBuf < PPP_CONFIG_HDR_LEN )
{
return( ERROR_BUFFER_TOO_SMALL );
}
pOption = (PPP_OPTION *)(pSendBuf->Data);
pSendBuf->Code = CBCP_CODE_Response;
pSendBuf->Id = pRequest->Id;
if ( fCallbackPrivilege & RASPRIV_NoCallback )
{
dwLength = PPP_OPTION_HDR_LEN;
if ( cbSendBuf < dwLength )
{
return( ERROR_BUFFER_TOO_SMALL );
}
pOption->Type = CBCP_TYPE_NO_CALLBACK;
pOption->Length = (BYTE)dwLength;
}
else if ( fCallbackPrivilege & RASPRIV_CallerSetCallback )
{
dwLength = (DWORD)(PPP_OPTION_HDR_LEN + 3 + strlen( szCallbackNumber ));
if ( cbSendBuf < dwLength )
{
return( ERROR_BUFFER_TOO_SMALL );
}
pOption->Type = CBCP_TYPE_CALLER_SET;
pOption->Length = (BYTE)dwLength;
*(pOption->Data) = (BYTE)CallbackDelay; // Callback Delay
*(pOption->Data+1) = (BYTE)CBCP_PSTN_NUMBER; // Number Type
strcpy( pOption->Data+2, szCallbackNumber ); // Callback Address
}
else if ( fCallbackPrivilege & RASPRIV_AdminSetCallback )
{
dwLength = PPP_OPTION_HDR_LEN + 1;
if ( cbSendBuf < dwLength )
{
return( ERROR_BUFFER_TOO_SMALL );
}
pOption->Type = CBCP_TYPE_CALLEE_SET;
pOption->Length = (BYTE)dwLength;
*(pOption->Data)= (BYTE)CallbackDelay; // Callback Delay
}
else
{
return( ERROR_INVALID_PARAMETER );
}
dwLength += PPP_CONFIG_HDR_LEN;
HostToWireFormat16( (WORD)dwLength, (PBYTE)(pSendBuf->Length) );
return( NO_ERROR );
}
//**
//
// Call: ValidateResponse
//
// Returns: NO_ERROR - success
// ERROR_PPP_INVALID_PACKET - failure
//
// Description: Will validate the reponse from the client. If the response
// is valid, then the callback information is returned in the
// CbCPWorkBuf.
//
DWORD
ValidateResponse(
IN PPP_CONFIG * pReceiveBuf,
IN CBCP_WORKBUFFER * pWorkBuf
)
{
PPP_OPTION * pOption = (PPP_OPTION *)(pReceiveBuf->Data);
if ( WireToHostFormat16( pReceiveBuf->Length ) !=
pOption->Length + PPP_CONFIG_HDR_LEN )
{
return( ERROR_PPP_INVALID_PACKET );
}
switch( pOption->Type )
{
case CBCP_TYPE_NO_CALLBACK:
if ( !( ( pWorkBuf->fCallbackPrivilege & RASPRIV_NoCallback ) ||
( pWorkBuf->fCallbackPrivilege & RASPRIV_CallerSetCallback ) ) )
{
return( ERROR_PPP_INVALID_PACKET );
}
pWorkBuf->fCallbackPrivilege = RASPRIV_NoCallback;
break;
case CBCP_TYPE_CALLEE_SET:
if ( !(pWorkBuf->fCallbackPrivilege & RASPRIV_AdminSetCallback) )
{
return( ERROR_PPP_INVALID_PACKET );
}
pWorkBuf->fCallbackPrivilege = RASPRIV_AdminSetCallback;
pWorkBuf->CallbackDelay = *(pOption->Data);
break;
case CBCP_TYPE_CALLER_SET:
if ( !(pWorkBuf->fCallbackPrivilege & RASPRIV_CallerSetCallback) )
{
return( ERROR_PPP_INVALID_PACKET );
}
pWorkBuf->fCallbackPrivilege = RASPRIV_CallerSetCallback;
pWorkBuf->CallbackDelay = *(pOption->Data);
if ( strlen( pWorkBuf->szCallbackNumber ) <= MAX_CALLBACKNUMBER_SIZE )
{
strcpy( pWorkBuf->szCallbackNumber, pOption->Data+2 );
}
else
{
return( ERROR_PPP_INVALID_PACKET );
}
break;
default:
return( ERROR_PPP_INVALID_PACKET );
break;
}
return( NO_ERROR );
}