📄 lcp.c
字号:
//--------------------------------------------------------------------------
// Ip Stack
//--------------------------------------------------------------------------
// LCP.C
//
// Member functions for PPP/LCP
//
// Author: Michael A. Denio
// Copyright 2000 by Texas Instruments Inc.
//-------------------------------------------------------------------------
#include <stkmain.h>
#include "ppp.h"
#ifdef _INCLUDE_PPP_CODE
// Timer Equates
#define LCP_TIMER_CFGIDLE 5
#define LCP_TIMER_CFGRETRY 3
#define LCP_TIMER_ECHOREQUEST 15
#define LCP_TIMER_ECHORETRY 8
// LCP Codes
#define LCPCODE_CFGREQ 1
#define LCPCODE_CFGACK 2
#define LCPCODE_CFGNAK 3
#define LCPCODE_CFGREJ 4
#define LCPCODE_TERMREQ 5
#define LCPCODE_TERMACK 6
#define LCPCODE_CODEREJ 7
#define LCPCODE_PROTREJ 8
#define LCPCODE_ECHOREQ 9
#define LCPCODE_ECHOREPLY 10
#define LCPCODE_DISCREQ 11
// LCP Configuration Options
#define LCPOPT_MRU 1
#define LCPOPT_CMAP 2
#define LCPOPT_AUTH 3
#define LCPOPT_MAGIC 5
static void lcpSendCfg( PPP_SESSION *p );
static void lcpSendTerm( PPP_SESSION *p );
static void lcpSendEcho( PPP_SESSION *p );
//--------------------------------------------------------------------
// lcpInit()
//
// Initialize LCP and set it to CLOSED state
//--------------------------------------------------------------------
void lcpInit( PPP_SESSION *p )
{
p->lcp.State = PROT_STATE_CLOSED;
p->lcp.StateCFG = PROT_CFG_IDLE;
p->lcp.StateACK = PROT_CFG_IDLE;
p->lcp.PeerMagic = 0;
llTimerGetTime(&p->lcp.OurMagic);
p->lcp.OurMagic = (p->lcp.OurMagic << 4) + llTimerGetTime(0);
// The following can be used prior to our startup
// Set the options we allow
p->lcp.OptMask = (1l<<LCPOPT_MRU) | (1l<<LCPOPT_MAGIC);
// On client, we allow authentication
if( p->Flags & PPPFLG_CLIENT )
p->lcp.OptMask |= (1l<<LCPOPT_AUTH);
// If requested, we allow CMAP
if( p->Flags & PPPFLG_SIOPT_RECVCMAP )
p->lcp.OptMask |= (1l<<LCPOPT_CMAP);
}
//--------------------------------------------------------------------
// lcpOpen()
//
// Open LCP and set passive or active
//--------------------------------------------------------------------
void lcpOpen( PPP_SESSION *p, uint fStart )
{
// Set our new state
if(p->lcp.State == PROT_STATE_CLOSED || p->lcp.State == PROT_STATE_STOPPED)
p->lcp.State = PROT_STATE_OPEN;
// Start our negotiation if desired
if( fStart && p->lcp.StateCFG == PROT_CFG_IDLE )
{
p->lcp.StateCFG = PROT_CFG_PENDING;
p->lcp.Count = 5; // Retry Count
// Set some defaults
p->lcp.LastId = 0; // Default Id
p->MTU_Rx = p->MTU_Phys; // Our MTU (MRU)
// Desired Options
p->lcp.UseMask = (1l<<LCPOPT_MRU) | (1l<<LCPOPT_MAGIC);
if( p->auth.Protocol )
p->lcp.UseMask |= (1l<<LCPOPT_AUTH);
// If requested, we send CMAP
if( p->Flags & PPPFLG_SIOPT_SENDCMAP )
p->lcp.UseMask |= (1l<<LCPOPT_CMAP);
lcpSendCfg( p );
p->SICtrl( p->hSI, SI_MSG_CALLSTATUS, SI_CSTATUS_NEGOTIATE, 0);
}
else
{
// Regardless of state, we set a timeout. If this timeout
// fires while StateACK is idle, we close
p->lcp.Timer = LCP_TIMER_CFGIDLE;
p->lcp.Count = 0;
}
}
//--------------------------------------------------------------------
// lcpClose()
//
// Close the LCP and reset
//--------------------------------------------------------------------
void lcpClose( PPP_SESSION *p )
{
// Send Termination if we are connected
if( p->lcp.State == PROT_STATE_CONNECTED )
{
lcpSendTerm( p );
p->lcp.State = PROT_STATE_STOPPED;
}
}
//--------------------------------------------------------------------
// lcpInput()
//
// Receive an LCP packet
//--------------------------------------------------------------------
void lcpInput( PPP_SESSION *p, HANDLE hPkt )
{
LCPHDR *pHdr;
HANDLE hFrag;
UINT8 *pb;
uint Size,Offset;
UINT32 cmap;
int TagLen;
UINT16 Len,wTmp;
UINT8 Tag,TagSize,*pTagData;
int RetCode;
int BadTagLen;
UINT8 *pBadTagData;
// If we're closed, return now
if( p->lcp.State == PROT_STATE_CLOSED )
goto LCPExit;
// We know we have a Frag...
hFrag = PktGetFrag( hPkt );
// Get the buffer parameters
pb = FragGetBufParams( hFrag, 0, &Size, &Offset );
pb += Offset;
// Get the LCPHDR
pHdr = (LCPHDR *)pb;
// Get packet length
Len = HNC16( pHdr->Length );
// Verify that we have the entire packet
if( Len > (UINT16)Size )
goto LCPExit;
switch( pHdr->Code )
{
case LCPCODE_CFGREQ:
//---------------------
// Configure-Request
//---------------------
// Set default MRU
p->MTU_Tx = p->MTU_Phys;
// Scan the options
pTagData = pHdr->TagData;
TagLen = (int)(Len - SIZE_LCPHDR);
RetCode = LCPCODE_CFGACK;
// Setup these pointers for use by NAK
BadTagLen = 0;
pBadTagData = pHdr->TagData;
while( TagLen > 0 )
{
Tag = *pTagData++;
TagSize = *pTagData++;
// Check for malformed packet
if( !TagSize )
goto LCPExit;
// First try reject
if( Tag > 31 || !(p->lcp.OptMask & (1l<<Tag)) )
{
// Reject this option
if( RetCode != LCPCODE_CFGREJ )
{
// We now use the pointer for REJ, so reset them
RetCode = LCPCODE_CFGREJ;
BadTagLen = 0;
pBadTagData = pHdr->TagData;
}
*pBadTagData++ = Tag;
*pBadTagData++ = TagSize;
if( TagSize > 2 )
mmCopy( pBadTagData, pTagData, TagSize );
BadTagLen += TagSize;
pBadTagData += TagSize - 2;
}
// If not in reject state, process option
if( RetCode != LCPCODE_CFGREJ )
{
// Process
switch( Tag )
{
case LCPOPT_MAGIC:
// If the magic number is ours, discard the request
if( p->lcp.OurMagic &&
p->lcp.OurMagic == RdNet32( pTagData ) )
goto LCPExit;
break;
case LCPOPT_MRU:
wTmp = RdNet16s( pTagData );
if( wTmp > (UINT16)p->MTU_Tx )
{
// We must NAK this value
RetCode = LCPCODE_CFGNAK;
*pBadTagData++ = Tag;
*pBadTagData++ = 4;
*pBadTagData++ = (UINT8)(p->MTU_Tx/256);
*pBadTagData++ = (UINT8)(p->MTU_Tx&255);
BadTagLen += 4;
}
else
p->MTU_Tx = wTmp;
break;
case LCPOPT_AUTH:
// If we are a client, we try and accept what the peer
// is giving us. If we don't handle it, we ask for PAP.
if( p->Flags & PPPFLG_CLIENT )
{
wTmp = RdNet16s( pTagData );
if( ( wTmp == PPPPROT_CHAP &&
(TagSize!=5 || *(pTagData+2)!=5) ) ||
( wTmp != PPPPROT_CHAP && wTmp != PPPPROT_PAP ) )
{
// We don't support the requested authorization
// Ask for PAP, just in case they'll take it
RetCode = LCPCODE_CFGNAK;
*pBadTagData++ = Tag;
*pBadTagData++ = 4;
*pBadTagData++ = (UINT8)(PPPPROT_PAP/256);
*pBadTagData++ = (UINT8)(PPPPROT_PAP&255);
BadTagLen += 4;
}
else
p->auth.Protocol = wTmp;
}
break;
case LCPOPT_CMAP:
if( TagSize == 6 )
{
wTmp = RdNet16s( pTagData );
cmap = ((UINT32)wTmp)<<16;
wTmp = RdNet16s( (pTagData+2) );
cmap |= (UINT32)wTmp;
p->SICtrl( p->hSI, SI_MSG_PEERCMAP, cmap, 0 );
}
break;
}
}
// Goto next tag
TagLen -= (int)TagSize;
pTagData += TagSize - 2;
}
// Reply to this request
pHdr->Code = RetCode;
if( RetCode == LCPCODE_CFGACK )
{
FragSetBufParams( hFrag, Len, Offset );
// Set new state
p->lcp.StateACK = PROT_CFG_OK;
}
else
{
// Change length to reflect bad options
BadTagLen += SIZE_LCPHDR;
pHdr->Length = HNC16(BadTagLen);
FragSetBufParams( hFrag, BadTagLen, Offset );
// Set new state
p->lcp.StateACK = PROT_CFG_PENDING;
}
// Send Packet
p->SICtrl(p->hSI, SI_MSG_SENDPACKET, PPPPROT_LCP, hPkt );
hPkt = 0;
goto LCPStateChange;
case LCPCODE_CFGACK:
//---------------------
// Configure-Ack
//---------------------
// If this ID does not match ours, ignore it
if( p->lcp.LastId != pHdr->Id )
goto LCPExit;
// Scan options
pTagData = pHdr->TagData;
TagLen = (int)(Len - SIZE_LCPHDR);
while( TagLen > 0 )
{
Tag = *pTagData++;
TagSize = *pTagData++;
// Check for malformed packet
if( !TagSize )
goto LCPExit;
switch( Tag )
{
case LCPOPT_MAGIC:
// Magic number must be ours
if( p->lcp.OurMagic &&
p->lcp.OurMagic != RdNet32( pTagData ) )
goto LCPExit;
break;
}
// Goto next tag
TagLen -= (int)TagSize;
pTagData += TagSize - 2;
}
// CFG half is connected
p->lcp.StateCFG = PROT_CFG_OK;
goto LCPStateChange;
case LCPCODE_CFGNAK:
case LCPCODE_CFGREJ:
//---------------------
// Configure-Nak
// Configure-Reject
//---------------------
// If this ID does not match ours, ignore it
if( p->lcp.LastId != pHdr->Id )
goto LCPExit;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -