📄 lcp.c
字号:
// Adjust our options according to Nak or Rej
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_MRU:
if( pHdr->Code == LCPCODE_CFGNAK )
{
// Read the size desired by peer
wTmp = RdNet16s( pTagData );
p->MTU_Rx = wTmp;
}
break;
case LCPOPT_MAGIC:
if( pHdr->Code == LCPCODE_CFGNAK )
p->lcp.OurMagic = RdNet32( pTagData );
else
p->lcp.OurMagic = 0;
break;
case LCPOPT_CMAP:
// When CMAP is specified, it is required
goto StopConnect;
case LCPOPT_AUTH:
// Can't negotiate authentication in server mode
if( p->Flags & PPPFLG_SERVER )
goto StopConnect;
// Fallthrough...
default:
goto ZapOption;
}
// If Reject, kill this option
if( pHdr->Code == LCPCODE_CFGREJ )
{
ZapOption:
p->lcp.UseMask &= ~(1l<<Tag);
}
// Goto next tag
TagLen -= (int)TagSize;
pTagData += TagSize - 2;
}
// Send a new CFG
p->lcp.StateCFG = PROT_CFG_PENDING;
p->lcp.Count = 5;
lcpSendCfg( p );
break;
case LCPCODE_TERMREQ:
//---------------------
// Term Request
//---------------------
// ACK the request
// Change the code to Ack
pHdr->Code = LCPCODE_TERMACK;
// Send Packet
FragSetBufParams( hFrag, Len, Offset );
p->SICtrl(p->hSI, SI_MSG_SENDPACKET, PPPPROT_LCP, hPkt );
hPkt = 0;
StopConnect:
p->lcp.State = PROT_STATE_STOPPED;
// Notify PPP
pppEvent( (HANDLE)p, PPP_EVENT_LCP_STOPPED );
break;
case LCPCODE_ECHOREQ:
//---------------------
// Echo Request
//---------------------
// Discard request if not connected
if( p->lcp.State != PROT_STATE_CONNECTED )
break;
// Change the code to Ack
pHdr->Code = LCPCODE_ECHOREPLY;
WrNet32( pHdr->TagData, p->lcp.OurMagic );
// Send Packet
FragSetBufParams( hFrag, Len, Offset );
p->SICtrl(p->hSI, SI_MSG_SENDPACKET, PPPPROT_LCP, hPkt );
hPkt = 0;
break;
case LCPCODE_ECHOREPLY:
//---------------------
// Echo Reply
//---------------------
// Keep track that we got the echo reply
if( p->lcp.State == PROT_STATE_CONNECTED )
p->lcp.Count = 0;
break;
default:
break;
}
goto LCPExit;
LCPStateChange:
if( p->lcp.State == PROT_STATE_OPEN )
{
// Check to see if we should start up a configuration request
if( p->lcp.StateCFG == PROT_CFG_IDLE &&
p->lcp.StateACK != PROT_CFG_IDLE )
lcpOpen( p, 1 );
// Check to see if we're connected
if( p->lcp.StateCFG == PROT_CFG_OK && p->lcp.StateACK == PROT_CFG_OK )
{
p->lcp.State = PROT_STATE_CONNECTED;
p->lcp.Timer = LCP_TIMER_ECHOREQUEST;
p->lcp.Count = 0;
pppEvent( (HANDLE)p, PPP_EVENT_LCP_CONNECT );
}
}
LCPExit:
if( hPkt )
PktFree( hPkt );
}
//--------------------------------------------------------------------
// lcpTimer()
//
// Called every second for LCP timeout
//--------------------------------------------------------------------
void lcpTimer( PPP_SESSION *p )
{
// What we do depends on our state
if( p->lcp.Timer && !--p->lcp.Timer )
switch( p->lcp.State )
{
case PROT_STATE_OPEN:
// See if we need a CFG message retry
if( p->lcp.Count )
{
p->lcp.Count--;
lcpSendCfg( p );
}
else
{
AbortConnect:
lcpSendTerm( p );
p->lcp.State = PROT_STATE_STOPPED;
pppEvent( (HANDLE)p, PPP_EVENT_LCP_STOPPED );
}
break;
case PROT_STATE_CONNECTED:
// We use count to track events without pings
p->lcp.Count++;
if( p->lcp.Count > LCP_TIMER_ECHORETRY )
goto AbortConnect;
// Now send a ping ourselves
lcpSendEcho( p );
// Reset the timer
p->lcp.Timer = LCP_TIMER_ECHOREQUEST;
break;
}
}
//--------------------------------------------------------------------
// lcpSendCfg()
//
// Send a LCP Configuration Request
//--------------------------------------------------------------------
static void lcpSendCfg( PPP_SESSION *p )
{
HANDLE hPkt,hFrag;
uint Offset;
UINT8 *pb;
LCPHDR *pHdr;
UINT16 Len,wTmp;
UINT8 *pTagData;
// Create the packet (use size of 100 for now)
if( !(hPkt = IFCreatePacket( 100, 0, 0 )) )
return;
// Get the frag
hFrag = PktGetFrag( hPkt );
// Get a pointer to the new header
pb = FragGetBufParams( hFrag, 0, 0, 0 );
Offset = PktGetSizeLLC( hPkt );
pHdr = (LCPHDR *)(pb + Offset);
// Reset the timeout
p->lcp.Timer = LCP_TIMER_CFGRETRY;
// Bump the Id
p->lcp.LastId++;
// Build the CFG packet
pHdr->Code = LCPCODE_CFGREQ;
pHdr->Id = p->lcp.LastId;
// Add options
pTagData = pHdr->TagData;
Len = SIZE_LCPHDR;
for( wTmp=1; wTmp<32; wTmp++ )
{
if( p->lcp.UseMask & (1l<<wTmp) )
switch( wTmp )
{
case LCPOPT_MRU:
*pTagData++ = LCPOPT_MRU;
*pTagData++ = 4;
*pTagData++ = (UINT8)(p->MTU_Rx/256);
*pTagData++ = (UINT8)(p->MTU_Rx&255);
Len += 4;
break;
case LCPOPT_CMAP:
*pTagData++ = LCPOPT_CMAP;
*pTagData++ = 6;
*pTagData++ = (UINT8)((p->CMap>>24)&255);
*pTagData++ = (UINT8)((p->CMap>>16)&255);
*pTagData++ = (UINT8)((p->CMap>>8)&255);
*pTagData++ = (UINT8)((p->CMap)&255);
Len += 6;
break;
case LCPOPT_AUTH:
switch( p->auth.Protocol )
{
case PPPPROT_PAP:
*pTagData++ = LCPOPT_AUTH;
*pTagData++ = 4;
*pTagData++ = (UINT8)(PPPPROT_PAP/256);
*pTagData++ = (UINT8)(PPPPROT_PAP&255);
Len += 4;
break;
case PPPPROT_CHAP:
*pTagData++ = LCPOPT_AUTH;
*pTagData++ = 5;
*pTagData++ = (UINT8)(PPPPROT_CHAP/256);
*pTagData++ = (UINT8)(PPPPROT_CHAP&255);
*pTagData++ = 5; // MD5
Len += 5;
}
break;
case LCPOPT_MAGIC:
*pTagData++ = LCPOPT_MAGIC;
*pTagData++ = 6;
WrNet32( pTagData, p->lcp.OurMagic );
pTagData += 4;
Len += 6;
break;
default:
break;
}
}
pHdr->Length = HNC16(Len);
// Send the packet
FragSetBufParams( hFrag, Len, Offset );
p->SICtrl(p->hSI, SI_MSG_SENDPACKET, PPPPROT_LCP, hPkt );
}
//--------------------------------------------------------------------
// lcpSendTerm()
//
// Send a LCP Termination Request
//--------------------------------------------------------------------
static void lcpSendTerm( PPP_SESSION *p )
{
HANDLE hPkt,hFrag;
uint Offset;
UINT8 *pb;
LCPHDR *pHdr;
// Create the packet (use size of 100 for now)
if( !(hPkt = IFCreatePacket( 100, 0, 0 )) )
return;
// Get the frag
hFrag = PktGetFrag( hPkt );
// Get a pointer to the new header
pb = FragGetBufParams( hFrag, 0, 0, 0 );
Offset = PktGetSizeLLC( hPkt );
pHdr = (LCPHDR *)(pb + Offset);
// Bump the Id
p->lcp.LastId++;
// Build the CFG packet
pHdr->Code = LCPCODE_TERMREQ;
pHdr->Id = p->lcp.LastId;
pHdr->Length = HNC16(SIZE_LCPHDR);
// Send the packet
FragSetBufParams( hFrag, SIZE_LCPHDR, Offset );
p->SICtrl(p->hSI, SI_MSG_SENDPACKET, PPPPROT_LCP, hPkt );
}
//--------------------------------------------------------------------
// lcpSendEcho()
//
// Send a LCP Echo Request
//--------------------------------------------------------------------
static void lcpSendEcho( PPP_SESSION *p )
{
HANDLE hPkt,hFrag;
uint Offset;
UINT8 *pb;
LCPHDR *pHdr;
// Create the packet (use size of 100 for now)
if( !(hPkt = IFCreatePacket( 100, 0, 0 )) )
return;
// Get the frag
hFrag = PktGetFrag( hPkt );
// Get a pointer to the new header
pb = FragGetBufParams( hFrag, 0, 0, 0 );
Offset = PktGetSizeLLC( hPkt );
pHdr = (LCPHDR *)(pb + Offset);
// Bump the Id
p->lcp.LastId++;
// Build the CFG packet
pHdr->Code = LCPCODE_ECHOREQ;
pHdr->Id = p->lcp.LastId;
pHdr->Length = HNC16((SIZE_LCPHDR+4));
WrNet32( pHdr->TagData, p->lcp.OurMagic );
// Send the packet
FragSetBufParams( hFrag, SIZE_LCPHDR+4, Offset );
p->SICtrl(p->hSI, SI_MSG_SENDPACKET, PPPPROT_LCP, hPkt );
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -