📄 pppoe.c
字号:
//--------------------------------------------------------------------------
// Ip Stack
//--------------------------------------------------------------------------
// PPPOE.C
//
// Member functions for the PPPOE CLIENT and SERVER
//
// Author: Michael A. Denio
// Copyright 2000 by Texas Instruments Inc.
//-------------------------------------------------------------------------
#include <stkmain.h>
#include "pppoe.h"
#ifdef _INCLUDE_PPPOE_CODE
static UINT8 MacBCast[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
// Serial Interface Control Function
#define FULLHEADER (SIZE_ETHHDR+SIZE_PPPOEHDR+2)
// CLIENT
static void pppoeTimer( uint Msg );
static void SendClientMsg( UINT8 Code, UINT16 SessionId, UINT8 *pMac );
static void pppoeInputC( HANDLE hPkt );
static PPPOE_CLIENT *ppc = 0;
// SERVER
static void pppoesTimer( uint Msg );
static void SendSeverMsg( UINT8 Code, UINT16 SessionId, UINT8 *pMac );
static void pppoeInputS( HANDLE hPkt );
static PPPOE_SERVER *pps = 0;
//-----------------------------------------------
// PPPOE Client State Machine States
#define PPPOE_SM_IDLE 0
#define PPPOE_SM_INITIATING 1
#define PPPOE_SM_REQUESTING 2
#define PPPOE_SM_CONFIRMED 3
//-----------------------------------------------
// PPPOE State Machine Control Function
static void pppoeCtrlMsg( PPPOE_CLIENT *ppc, int Msg );
//-----------------------------------------------
// Messages for the Control function
#define PPPOE_MSG_QUERY 1 // Query available services
#define PPPOE_MSG_OPEN 2 // Open Service Session
#define PPPOE_MSG_CLOSE 3 // Close Service Session
#define PPPOE_MSG_TIMETICK 4 // Time Tick (about 1 sec) (ctrl function only)
//----------------------------------------------------------------------
// USER FUNCTIONS
//
// The following functions must be callable from outside the kernel.
// They use llEnter()/llExit().
//----------------------------------------------------------------------
//--------------------------------------------------------------
// pppoeNew() USER FUNCTION
//
// Open PPPOE Client
//--------------------------------------------------------------
HANDLE pppoeNew( HANDLE hEth, uint pppFlags,
INT8 *Username, INT8 *Password )
{
// Only one instance allowed
if( ppc != 0 )
return(0);
// Enter kernel mode
llEnter();
// Validate arguments
if( !hEth || !Username || !Password )
goto ExitNew;
// If size of ServerName or ServiceName > PPPOE_NAMESIZE,
// then abort
if( strlen(Username) >= PPPOE_NAMESIZE
|| strlen(Password) >= PPPOE_NAMESIZE )
goto ExitNew;
// Allocate space for instance
if( !(ppc = mmAlloc(sizeof(PPPOE_CLIENT))) )
{
DbgPrintf(DBG_WARN,"pppoeNew: OOM");
ExecLowResource();
goto ExitNew;
}
// Initialize type
ppc->Type = HTYPE_PPPOE_CLIENT;
// Save master settings
ppc->hTimer = TimerNew( &pppoeTimer, 2, 0 );
ppc->pppFlags = pppFlags;
strcpy( ppc->Username, Username );
strcpy( ppc->Password, Password );
ppc->ppi.hParent = (HANDLE)ppc;
ppc->ppi.iType = PPPOE_INST_CLIENT;
ppc->ppi.hEther = hEth;
ppc->ppi.hLLADirect = EtherGetLLADirect( hEth );
ppc->ppi.SessionId = 0;
ppc->ppi.hPPP = 0;
// Record our padding requirements
IFSetPad( FULLHEADER, 0 );
// Send a PPPOE QUERY to see if there are any services
pppoeCtrlMsg( ppc, PPPOE_MSG_QUERY );
ExitNew:
// Exit kernel mode
llExit();
return( (HANDLE)ppc );
}
//--------------------------------------------------------------
// pppoeFree() USER FUNCTIION
//
// Close PPPOE Client
//--------------------------------------------------------------
void pppoeFree( HANDLE hPPPOE )
{
// Enter kernel mode
llEnter();
if( ppc && ppc == hPPPOE )
{
pppoeSI( &(ppc->ppi), SI_MSG_CALLSTATUS, SI_CSTATUS_DISCONNECT, 0 );
if( ppc->hTimer )
TimerFree( ppc->hTimer );
mmFree( ppc );
ppc = 0;
}
// Exit kernel mode
llExit();
}
//--------------------------------------------------------------
// pppoeGetStatus() USER FUNCTION
//
// Get the status of the PPPOE Client
//--------------------------------------------------------------
uint pppoeGetStatus( HANDLE hPPPOE )
{
uint Status = 0;
// Enter kernel mode
llEnter();
if( ppc && ppc == hPPPOE )
Status = ppc->ppi.Status;
// Exit kernel mode
llExit();
return( Status );
}
//--------------------------------------------------------------
// pppoesNew() USER FUNCTION
//
// Open PPPOE Server
//--------------------------------------------------------------
HANDLE pppoesNew( HANDLE hEth, uint pppFlags, uint SessionMax,
IPN IPServer, IPN IPMask, IPN IPClientBase,
INT8 *ServerName, INT8 *ServiceName )
{
uint i;
// Only one server instance allowed
if( pps != 0 )
return(0);
// Enter kernel mode
llEnter();
// Validate arguments
if( !hEth || !SessionMax || !IPClientBase || !ServerName || !ServiceName )
goto ExitSNew;
// If size of ServerName or ServiceName > PPPOE_NAMESIZE,
// then abort
if( strlen(ServerName) >= PPPOE_NAMESIZE
|| strlen(ServiceName) >= PPPOE_NAMESIZE )
goto ExitSNew;
// Allocate space for server
i = sizeof(PPPOE_SERVER);
if( SessionMax > 1 )
i += sizeof(PPPOE_INST)*(SessionMax-1);
if( !(pps = mmAlloc( i )) )
{
DbgPrintf(DBG_WARN,"pppoesNew: OOM");
ExecLowResource();
goto ExitSNew;
}
// Initialize type
pps->Type = HTYPE_PPPOE_SERVER;
// Save master settings
pps->hEther = hEth;
pps->hTimer = TimerNew( &pppoesTimer, 2, 0 );
pps->hLLADirect = EtherGetLLADirect( hEth );
pps->pppFlags = pppFlags;
pps->SessionMax = SessionMax;
pps->IPClientBase = IPClientBase;
pps->IPServer = IPServer;
pps->IPMask = IPMask;
strcpy( pps->ServerName, ServerName );
strcpy( pps->ServiceName, ServiceName );
// Init sessions
for( i=0; i<SessionMax; i++ )
{
mmZeroInit( &(pps->ppi[i]), sizeof(PPPOE_INST) );
pps->ppi[i].hParent = (HANDLE)pps;
pps->ppi[i].iType = PPPOE_INST_SERVER;
pps->ppi[i].hEther = pps->hEther;
pps->ppi[i].hLLADirect = pps->hLLADirect;
pps->ppi[i].SessionId = i+1;
}
// Record our padding requirements
IFSetPad( FULLHEADER, 0 );
ExitSNew:
// Exit kernel mode
llExit();
return( (HANDLE)pps );
}
//--------------------------------------------------------------
// pppoesFree()
//
// Close PPPOE Server
//--------------------------------------------------------------
void pppoesFree( HANDLE hPPPOES )
{
uint i;
// Enter kernel mode
llEnter();
if( pps && pps == hPPPOES )
{
for( i=0; i<pps->SessionMax; i++ )
if( pps->ppi[i].hPPP )
pppoeSI( &(pps->ppi[i]), SI_MSG_CALLSTATUS,
SI_CSTATUS_DISCONNECT, 0 );
if( pps->hTimer )
TimerFree( pps->hTimer );
mmFree( pps );
pps = 0;
}
// Exit kernel mode
llExit();
}
//----------------------------------------------------------------------
// STACK FUNCTIONS
//
// The following functions are normal stack functions.
//----------------------------------------------------------------------
//----------------------------------------------------------------------
// The following is the standard serial interface (SI) control function
//
//--------------------------------------------------------------------
// SI Control Function
//--------------------------------------------------------------------
void pppoeSI( HANDLE hSI, uint Msg, UINT32 Aux, HANDLE hPkt )
{
PPPOE_INST *ppi = (PPPOE_INST *)hSI;
HANDLE hFrag;
uint Offset,ValidSize,Payload;
UINT8 *pb;
ETHHDR *pEth;
PPPOEHDR *pHdr;
HANDLE hTmp;
UINT8 *pbCopy;
switch( Msg )
{
case SI_MSG_CALLSTATUS:
ppi->Status = (uint)Aux;
if( Aux >= SI_CSTATUS_DISCONNECT )
{
// Close PPP
if( ppi->hPPP )
{
hTmp = ppi->hPPP;
ppi->hPPP = 0;
pppFree( hTmp );
}
// Terminate the PPPOE session
if( ppi->iType == PPPOE_INST_SERVER )
{
// Server Shutdown
SendSeverMsg( PPPOE_CODE_TERMINATE,
ppi->SessionId, ppi->PeerMac );
}
else
{
// Client Shutdown
if( ppi->SessionId )
SendClientMsg( PPPOE_CODE_TERMINATE,
ppi->SessionId, ppi->PeerMac );
pppoeCtrlMsg( (PPPOE_CLIENT *)ppi->hParent, PPPOE_MSG_CLOSE );
}
}
break;
case SI_MSG_PEERCMAP:
DbgPrintf( DBG_WARN, "PPPOE: Unexpected Peer CMAP %08lx",Aux );
break;
case SI_MSG_SENDPACKET:
// Make sure packet is valid
if( !hPkt || !(hFrag = PktGetFrag( hPkt )) )
{
DbgPrintf(DBG_ERROR,"pppoeSI: Bad packet");
PktFree( hPkt );
return;
}
// Silently discard if we're not connected
if( !ppi->SessionId )
{
PktFree( hPkt );
return;
}
// Get the buffer parameters
pb = FragGetBufParams( hFrag, 0, &ValidSize, &Offset );
// We can't have an LLC since SI framing is undefined
if( PktGetFlags( hPkt ) & FLG_PKT_LLC_VALID )
{
DbgPrintf(DBG_ERROR,"pppoeSI: LLC on PPP");
PktFree( hPkt );
return;
}
// We need room to add the LLC
// If we don't have it, we'll have to shuffle some data
if( Offset < FULLHEADER )
{
// Allocate a new frag
hTmp = FragNewAlloc( FRAG_POOL_PACKET,
ValidSize+FULLHEADER, 4, 0, 0 );
if( !hTmp )
{
PktFree( hPkt );
return;
}
// Copy payload data
pbCopy = FragGetBufParams( hTmp, 0, 0, 0 );
mmCopy( pbCopy+FULLHEADER, pb+Offset, ValidSize );
// Attach the frag to the packet and free old frag
PktSetFrag( hPkt, hTmp );
FragFree( hFrag );
// Asssume new identity
hFrag = hTmp;
Offset = FULLHEADER;
pb = pbCopy;
}
// Add the LLC
// The end of the header should be flush against the
// start of the current offset.
Payload = ValidSize+2;
Offset -= FULLHEADER;
ValidSize += FULLHEADER;
pEth = (ETHHDR *)(pb + Offset);
pHdr = (PPPOEHDR *)(pb + Offset + SIZE_ETHHDR);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -