📄 layerfsm.c
字号:
pFsm->idTxCR++;
dwResult = PppFsmActionSCR(pFsm);
if (dwResult == NO_ERROR)
newState = PFS_Request_Sent;
break;
case PFS_Closing:
newState = PFS_Stopping;
break;
}
PppFsmNewState(pFsm, newState);
return dwResult;
}
DWORD
PppFsmClose(
PPppFsm pFsm)
//
// Called to request that the finite state machine
// take steps to enter the closed state.
//
{
DWORD dwResult = NO_ERROR;
PppFsmState newState = pFsm->state;
DEBUGMSG(ZONE_TRACE, (L"PPP: PppFsmClose %hs State=%hs\n", pFsm->pDescriptor->szProtocolName, g_szStateName[pFsm->state]));
switch(pFsm->state)
{
case PFS_Initial:
break;
case PFS_Starting:
newState = PFS_Initial;
break;
case PFS_Closed:
case PFS_Closing:
break;
case PFS_Stopped:
newState = PFS_Closed;
break;
case PFS_Stopping:
newState = PFS_Closing;
break;
case PFS_Opened:
PppFsmActionTLD(pFsm);
// FALLTHROUGH
case PFS_Request_Sent:
case PFS_Ack_Received:
case PFS_Ack_Sent:
PppFsmActionIRC(pFsm, pFsm->dwMaxTerminate);
PppFsmActionSTR(pFsm);
newState = PFS_Closing;
break;
}
PppFsmNewState(pFsm, newState);
return dwResult;
}
DWORD
PppFsmRenegotiate(
PPppFsm pFsm)
//
// Called to request that the FSM renegotiate options with the peer.
// This takes the layer down if it is currently Opened, then proceeds
// through the whole negotiation process to get it back to the Opened state.
//
{
DWORD dwResult = NO_ERROR;
PppFsmState newState = pFsm->state;
DEBUGMSG(ZONE_TRACE, (L"PPP: PppFsmRenegotiate %hs State=%hs\n", pFsm->pDescriptor->szProtocolName, g_szStateName[pFsm->state]));
switch(pFsm->state)
{
case PFS_Initial:
case PFS_Closed:
case PFS_Closing:
case PFS_Starting:
break;
case PFS_Opened:
PppFsmActionTLD(pFsm);
// FALLTHROUGH
case PFS_Stopped:
case PFS_Stopping:
case PFS_Request_Sent:
case PFS_Ack_Received:
case PFS_Ack_Sent:
PppFsmActionIRC(pFsm, pFsm->dwMaxConfigure);
OptionResetNegotiation(&pFsm->optionContext);
pFsm->idTxCR++;
dwResult = PppFsmActionSCR(pFsm);
if (dwResult == NO_ERROR)
newState = PFS_Request_Sent;
break;
}
PppFsmNewState(pFsm, newState);
return dwResult;
}
DWORD
PppFsmLowerLayerUp(
PPppFsm pFsm)
//
// Called to indicate that the layer below this one has
// come up, we are able to send/receive frames.
//
{
DWORD dwResult = NO_ERROR;
PppFsmState newState = pFsm->state;
DEBUGMSG(ZONE_TRACE, (L"PPP: PppFsmLowerLayerUp %hs State=%hs\n", pFsm->pDescriptor->szProtocolName, g_szStateName[pFsm->state]));
switch(pFsm->state)
{
case PFS_Initial:
newState = PFS_Closed;
break;
case PFS_Starting:
OptionResetNegotiation(&pFsm->optionContext);
PppFsmActionIRC(pFsm, pFsm->dwMaxConfigure);
pFsm->idTxCR++;
dwResult = PppFsmActionSCR(pFsm);
if (dwResult == NO_ERROR)
newState = PFS_Request_Sent;
else
newState = PFS_Stopped;
break;
}
PppFsmNewState(pFsm, newState);
return dwResult;
}
DWORD
PppFsmLowerLayerDown(
PPppFsm pFsm)
//
// Called to indicate that the layer below this one has
// gone down, we are unable to send/receive frames any more.
//
{
DWORD dwResult = NO_ERROR;
DEBUGMSG(ZONE_TRACE, (L"PPP: PppFsmLowerLayerDown %hs State=%hs\n", pFsm->pDescriptor->szProtocolName, g_szStateName[pFsm->state]));
switch(pFsm->state)
{
case PFS_Initial:
case PFS_Starting:
break;
case PFS_Closing:
case PFS_Closed:
PppFsmNewState(pFsm, PFS_Initial);
break;
case PFS_Opened:
PppFsmActionTLD(pFsm);
// FALLTHROUGH
case PFS_Stopped:
case PFS_Stopping:
case PFS_Request_Sent:
case PFS_Ack_Received:
case PFS_Ack_Sent:
PppFsmNewState(pFsm, PFS_Starting);
break;
default:
ASSERT(FALSE);
break;
}
return dwResult;
}
DWORD
PppFsmProtocolRejected(
PPppFsm pFsm)
//
// Called to handle the rejection of our protocol
// by the peer.
//
{
DWORD dwResult = NO_ERROR;
DEBUGMSG(ZONE_TRACE, (L"PPP: PppFsmProtocolRejected %hs State=%hs\n", pFsm->pDescriptor->szProtocolName, g_szStateName[pFsm->state]));
switch(pFsm->state)
{
case PFS_Initial:
case PFS_Starting:
break;
case PFS_Closed:
case PFS_Closing:
PppFsmNewState(pFsm, PFS_Closed);
break;
case PFS_Stopped:
case PFS_Stopping:
case PFS_Request_Sent:
case PFS_Ack_Received:
case PFS_Ack_Sent:
PppFsmNewState(pFsm, PFS_Stopped);
break;
case PFS_Opened:
PppFsmActionTLD(pFsm);
PppFsmActionIRC(pFsm, pFsm->dwMaxTerminate);
PppFsmActionSTR(pFsm);
PppFsmNewState(pFsm, PFS_Stopping);
break;
}
return dwResult;
}
void
PppFsmActionSendCodeReject(
IN OUT PPppFsm pFsm,
IN PBYTE pPacket,
IN DWORD cbPacket)
//
// Send a code-reject packet containing the packet
// received from the peer with an unrecognized code.
//
{
//
// Per RFC1661 5.6
// "The Rejected-Packet MUST be truncated to comply with
// the peer's established MRU."
//
// Currently, for simplicity, assume default MRU of 1500.
//
if (cbPacket > (PPP_DEFAULT_MTU - PPP_PACKET_HEADER_SIZE))
{
// Truncate the rejected packet
cbPacket = PPP_DEFAULT_MTU - PPP_PACKET_HEADER_SIZE;
}
pFsm->cbResponsePacket = PPP_PACKET_HEADER_SIZE + cbPacket;
ASSERT(pFsm->cbResponsePacket <= PPP_DEFAULT_MTU);
PPP_SET_PACKET_HEADER(pFsm->abResponsePacket, PPP_CODE_REJECT, pFsm->idNextCodeReject, pFsm->cbResponsePacket);
pFsm->idNextCodeReject++;
memcpy(&pFsm->abResponsePacket[PPP_PACKET_HEADER_SIZE], pPacket, cbPacket);
pFsm->bmActions |= ACTION_SEND_RESPONSE;
}
#define MAX_RESPONSE_PACKET_SIZE PPP_DEFAULT_MTU
DWORD
PppFsmProcessRxConfigureRequest(
IN OUT PPppFsm pFsm,
IN PBYTE pPacket,
IN DWORD cbPacket,
OUT PBYTE pResponsePacket,
IN OUT PDWORD pcbResponsePacket)
{
DWORD dwResult;
//
// Construct a response (ACK/NAK/REJ) to the configure-request
//
dwResult = OptionProcessRxMessage(
&pFsm->optionContext,
pPacket,
cbPacket,
pResponsePacket,
pcbResponsePacket);
ASSERT ((dwResult != NO_ERROR)
|| (*pcbResponsePacket >= PPP_PACKET_HEADER_SIZE && PPP_CONFIGURE_ACK <= *pResponsePacket && *pResponsePacket <= PPP_CONFIGURE_REJ));
return dwResult;
}
DWORD
PppFsmProcessRxConfigureResponse(
IN OUT PPppFsm pFsm,
IN PBYTE pPacket,
IN DWORD cbPacket)
{
DWORD dwResult;
dwResult = OptionProcessRxMessage(
&pFsm->optionContext,
pPacket,
cbPacket,
NULL,
NULL);
return dwResult;
}
void
PppFsmProcessRxPacket(
IN OUT PPppFsm pFsm,
IN PBYTE pPacket,
IN DWORD cbPacket)
//
// Process a received packet for the protocol managed by this Fsm.
// The protocol type field must have been stripped from the packet already.
//
// For state machine table, see RFC 1661 section 4.1
//
{
PppFsmState curState,
newState;
BYTE code,
id;
DWORD dwResult;
DWORD length;
PPppFsmExtensionMessageDescriptor pMsgDescriptor;
do
{
//
// All packets have the form:
// <Code> <Id> <Length:2 octets> <Data: Length-4 octets>
//
if (cbPacket < PPP_PACKET_HEADER_SIZE)
{
DEBUGMSG(ZONE_WARN, (TEXT("PPP: WARNING RX %hs short packet, %u bytes\n"),
pFsm->pDescriptor->szProtocolName, cbPacket));
break;
}
code = pPacket[0];
id = pPacket[1];
length = (pPacket[2] << 8) | pPacket[3];
if (length < PPP_PACKET_HEADER_SIZE || cbPacket < length)
{
DEBUGMSG(ZONE_WARN, (TEXT("PPP: WARNING RX %hs length %u invalid for cbPacket %u\n"),
pFsm->pDescriptor->szProtocolName, length, cbPacket));
break;
}
curState = pFsm->state;
newState = curState;
#ifdef DEBUG
if (ZONE_TRACE)
PppFsmDebugShowPacket(pFsm, "RX", pPacket, cbPacket);
#endif
switch(code)
{
case PPP_CONFIGURE_REQUEST:
switch(curState)
{
case PFS_Closed:
PppFsmActionSTA(pFsm, id);
break;
case PFS_Stopped:
case PFS_Request_Sent:
case PFS_Ack_Sent:
case PFS_Ack_Received:
case PFS_Opened:
pFsm->cbResponsePacket = sizeof(pFsm->abResponsePacket);
dwResult = PppFsmProcessRxConfigureRequest(pFsm, pPacket, cbPacket, &pFsm->abResponsePacket[0], &pFsm->cbResponsePacket);
if (dwResult == NO_ERROR)
{
newState = pFsm->abResponsePacket[0] == PPP_CONFIGURE_ACK ? PFS_Ack_Sent : PFS_Request_Sent;
if (curState == PFS_Stopped || curState == PFS_Opened)
{
if (curState == PFS_Opened)
PppFsmActionTLD(pFsm);
OptionResetNegotiation(&pFsm->optionContext);
PppFsmActionIRC(pFsm, pFsm->dwMaxConfigure);
pFsm->idTxCR++;
if (PppFsmActionSCR(pFsm) != NO_ERROR)
newState = PFS_Stopped;
}
else if (curState == PFS_Ack_Received)
{
newState = newState == PFS_Ack_Sent ? PFS_Opened : PFS_Ack_Received;
}
//
// Note that the response must be sent AFTER the config-request sent above
// in order to prevent infinite renegotiations from occuring.
//
pFsm->bmActions |= ACTION_SEND_RESPONSE;
}
else if (dwResult == ERROR_PPP_NOT_CONVERGING)
{
// Further negotiation is probably futile, give up and shut down the link
newState = PFS_Stopped;
}
break;
}
break;
case PPP_CONFIGURE_ACK:
case PPP_CONFIGURE_NAK:
case PPP_CONFIGURE_REJ:
//
// Ignore the response if its ID does not match the most
// recent config-request we sent.
//
if (id != pFsm->idTxCR)
{
// Stale response, ignore it
DEBUGMSG(ZONE_WARN, (TEXT("PPP: WARNING - RX Stale response id=%u, expecting %u\n"), id, pFsm->idTxCR));
break;
}
switch(curState)
{
case PFS_Closed:
case PFS_Stopped:
PppFsmActionSTA(pFsm, id);
break;
case PFS_Opened:
PppFsmActionTLD(pFsm);
// FALLTHROUGH
case PFS_Ack_Received:
//
// We are in a state in which we are not expecting a response.
//
DEBUGMSG(ZONE_WARN, (TEXT("PPP: WARNING - Unexpected response received\n")));
pFsm->idTxCR++;
if (PppFsmActionSCR(pFsm) == NO_ERROR)
newState = PFS_Request_Sent;
else
{
PppFsmActionSTR(pFsm);
newState = PFS_Stopping;
}
break;
case PFS_Request_Sent:
case PFS_Ack_Sent:
//
// All improperly formed responses must be ignored, and not
// result in a state transition.
//
if (code == PPP_CONFIGURE_ACK)
{
//
// An ACK packet must be identical to the CR we issued,
// except for the 1st byte (which is ACK(2) instead of CR(1)
//
DWORD len = (pPacket[2] << 8) | pPacket[3];
if (pFsm->cbRequestBuffer != len ||
memcmp(pFsm->pRequestBuffer + 1, pPacket + 1, len - 1))
{
// Invalid ACK - ignore
DEBUGMSG(ZONE_WARN, (TEXT("PPP: WARNING - ACK received with nonmatching option list\n")));
dwResult = ERROR_INVALID_MESSAGE;
break;
}
}
dwResult = PppFsmProcessRxConfigureResponse(pFsm, pPacket, cbPacket);
if (dwResult == ERROR_UNRECOGNIZED_RESPONSE && code == PPP_CONFIGURE_ACK)
{
//
// Treat the malformed ACK packet as a NAK.
// This is specifically designed to deal with a misbehaving peer
// that sends a MPPE ACK with more than 1 encryption type enabled.
// The CCP code will adjust the next CR sent.
//
dwResult = NO_ERROR;
code = PPP_CONFIGURE_NAK;
}
if (dwResult == NO_ERROR)
{
// Valid response
PppFsmActionIRC(pFsm, pFsm->dwMaxConfigure);
if (code == PPP_CONFIGURE_ACK)
newState = curState == PFS_Request_Sent ? PFS_Ack_Received : PFS_Opened;
else
{
pFsm->idTxCR++;
if (PppFsmActionSCR(pFsm) != NO_ERROR)
newState = PFS_Stopped;
}
}
break;
}
break;
case PPP_TERMINATE_REQUEST:
switch(curState)
{
case PFS_Closed:
case PFS_Closing:
case PFS_Stopped:
case PFS_Stopping:
case PFS_Request_Sent:
PppFsmActionSTA(pFsm, id);
break;
case PFS_Ack_Received:
case PFS_Ack_Sent:
PppFsmActionSTA(pFsm, id);
newState = PFS_Request_Sent;
break;
case PFS_Opened:
PppFsmActionTLD(pFsm);
PppFsmActionZRC(pFsm);
PppFsmActionSTA(pFsm, id);
newState = PFS_Stopping;
break;
}
break;
case PPP_TERMINATE_ACK:
switch (pFsm->state)
{
case PFS_Closing:
newState = PFS_Closed;
break;
case PFS_Stopping:
newState = PFS_Stopped;
break;
case PFS_Ack_Received:
// This is per RFC1661, but seems wierd that
// we enter the Request_Sent state without
// sending a new request...
newState = PFS_Request_Sent;
break;
case PFS_Opened:
PppFsmActionTLD(pFsm);
pFsm->idTxCR++;
if (PppFsmActionSCR(pFsm) == NO_ERROR)
newState = PFS_Request_Sent;
else
newState = PFS_Stopped;
break;
}
break;
case PPP_CODE_REJECT:
//
// We must be running a newer version of the protocol,
// such that the peer does not understand the code.
//
// If the rejected code is for a required message type
// like PPP_CONFIGURE_REQUEST, this is catastrophic
// and we need to take down the link.
//
// Regardless, log the bad message the peer doesn't like,
// stop sending that message type.
//
break;
default:
//
// Search the list of protocol specific code handlers
//
pMsgDescriptor = pFsm->pDescriptor->pExtensionMessageDescriptors;
if (pMsgDescriptor)
{
while (TRUE)
{
if (pMsgDescriptor->MessageRxCb == NULL)
{
// Didn't find a matching handler
pMsgDescriptor = NULL;
break;
}
if (pMsgDescriptor->code == code)
{
break;
}
pMsgDescriptor++;
}
}
if (pMsgDescriptor)
{
//
// Invoke the extension message handler
//
pMsgDescriptor->MessageRxCb(pFsm->CbContext, code, id, pPacket + 4, length - 4);
}
else
{
//
// Unrecognized code - RUC
PppFsmActionSendCodeReject(pFsm, pPacket, cbPacket);
}
break;
}
PppFsmNewState(pFsm, newState);
} while (FALSE); // end do
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -