📄 pppoe.c
字号:
// Copy SRC MAC into the LLC
LLAGetData( ppi->hLLADirect, 6, pEth->SrcMac );
// Set Destination MAC
mmCopy( pEth->DstMac, ppi->PeerMac, 6 );
// Set ETH Header
pEth->Type = HNC16(ETHERTYPE_PPPOE_DATA);
// Set PPPOE Header
pHdr->VerType = 0x11;
pHdr->Code = 0;
pHdr->SessionId = HNC16(ppi->SessionId);
pHdr->Length = HNC16(Payload);
// Add Protocol
*(pHdr->Data) = (UINT8)(Aux/256);
*(pHdr->Data+1) = (UINT8)(Aux%256);
// Update the frag
FragSetBufParams( hFrag, ValidSize, Offset );
// Free the packet
PktSetFrag( hPkt, 0 );
PktFree( hPkt );
// Send packet
llPacketSend( IFGetIndex(ppi->hEther), pb, Offset, ValidSize, hFrag );
break;
}
}
//--------------------------------------------------------------
// pppoeInput()
//
// Generic packet Rx function for PPPOE
//--------------------------------------------------------------
void pppoeInput( HANDLE hPkt )
{
HANDLE hIF;
hIF = PktGetIFRx( hPkt );
if( pps && pps->hEther == hIF )
pppoeInputS( hPkt );
else if( ppc && ppc->ppi.hEther == hIF )
pppoeInputC( hPkt );
else
PktFree( hPkt );
}
//----------------------------------------------------------------------
//----------------------------------------------------------------------
// PPPOE CLIENT FUNCTIONS
//----------------------------------------------------------------------
//----------------------------------------------------------------------
//--------------------------------------------------------------
// pppoeTimer()
//
// Dispatches time ticks to PPP clients
//--------------------------------------------------------------
static void pppoeTimer( uint Msg )
{
(void)Msg;
if( ppc )
{
pppoeCtrlMsg( ppc, PPPOE_MSG_TIMETICK );
if( ppc->ppi.hPPP )
pppTimer( ppc->ppi.hPPP );
}
}
//--------------------------------------------------------------------
// pppoeCtrlMsg
//
// This function handles the control side of a PPPOE client.
//--------------------------------------------------------------------
static void pppoeCtrlMsg( PPPOE_CLIENT *ppc, int Msg )
{
if( !Msg || !ppc )
return;
switch( Msg )
{
case PPPOE_MSG_QUERY: // Query available services
ppc->State = PPPOE_SM_INITIATING;
ppc->ppi.Status = SI_CSTATUS_WAITING;
ppc->ppi.SessionId = 0;
ppc->Timeout = 2;
ppc->Retry = 2;
SendClientMsg( PPPOE_CODE_INITIATION, 0, MacBCast );
break;
case PPPOE_MSG_OPEN: // Open Service Session
ppc->State = PPPOE_SM_REQUESTING;
ppc->ppi.SessionId = 0;
ppc->Timeout = 2;
ppc->Retry = 2;
SendClientMsg( PPPOE_CODE_REQUEST, 0, ppc->ppi.PeerMac );
break;
case PPPOE_MSG_CLOSE: // Close Service Session
ppc->State = PPPOE_SM_IDLE;
ppc->ppi.SessionId = 0;
ppc->Timeout = 0;
break;
case PPPOE_MSG_TIMETICK: // Time Increment (about 1 sec)
// If we have nothing timing out, then exit quickly
if( !ppc->Timeout )
break;
// See if somethiong timed out this call.
if( !--ppc->Timeout )
{
//
// A timeout has occurred.
//
// See if we should retry the last operation
if( !ppc->Retry )
{
//
// Retries have expired
// Send a failure notification
//
switch( ppc->State )
{
case PPPOE_SM_INITIATING:
// Error in QUERY
pppoeSI( &(ppc->ppi),
SI_MSG_CALLSTATUS, SI_CSTATUS_DISCONNECT, 0 );
break;
case PPPOE_SM_REQUESTING:
// Error in OPEN
pppoeSI( &(ppc->ppi),
SI_MSG_CALLSTATUS, SI_CSTATUS_DISCONNECT, 0 );
break;
default:
ppc->State = PPPOE_SM_IDLE;
break;
}
}
//
// Retry the operation
//
ppc->Retry--;
switch( ppc->State )
{
case PPPOE_SM_INITIATING:
ppc->Timeout = 2;
SendClientMsg( PPPOE_CODE_INITIATION, 0, MacBCast );
break;
case PPPOE_SM_REQUESTING:
ppc->Timeout = 2;
SendClientMsg( PPPOE_CODE_REQUEST, 0, ppc->ppi.PeerMac );
break;
default:
ppc->State = PPPOE_SM_IDLE;
break;
}
}
break;
}
}
//--------------------------------------------------------------------
// SendClientMsg()
//
// Private SendClientMsg Function for State Machine
//--------------------------------------------------------------------
static void SendClientMsg( UINT8 Code, UINT16 SessionId, UINT8 *pMac )
{
ETHHDR *pEth;
PPPOEHDR *pHdr;
int TagLength,i;
UINT8 *pb,*pTagData;
HANDLE hFrag;
// Create the frag
hFrag=FragNewAlloc( FRAG_POOL_PACKET, 500, 0, 0, 0 );
if( !hFrag )
return;
// Get the pointer to the Frag buffer
pb = FragGetBufParams( hFrag, 0, 0, 0 );
pEth = (ETHHDR *)pb;
pHdr = (PPPOEHDR *)(pb + SIZE_ETHHDR);
// Set Destination MAC
mmCopy( pEth->DstMac, pMac, 6 );
// The source MAC address is always us
LLAGetData( ppc->ppi.hLLADirect, 6, pEth->SrcMac );
// The packet type is always ETHERTYPE_PPPOE_CTRL
pEth->Type = HNC16(ETHERTYPE_PPPOE_CTRL);
// Set remainder of header
pHdr->VerType = 0x11;
pHdr->Code = Code;
// The session Id is used only for PPPOE_CODE_TERMINATE and CONFIRM
if( Code == PPPOE_CODE_TERMINATE || Code == PPPOE_CODE_CONFIRM )
pHdr->SessionId = HNC16(SessionId);
else
pHdr->SessionId = 0;
//
// Add Tags
//
TagLength = 0;
pTagData = pHdr->Data;
//
// Tags are dependent on message type
//
if( Code == PPPOE_CODE_INITIATION )
{
// SNAME
*pTagData++ = PPPOE_TAG_SNAME/256;
*pTagData++ = PPPOE_TAG_SNAME&255;
*pTagData++ = 0;
*pTagData++ = 0;
TagLength += 4;
}
else if( Code == PPPOE_CODE_REQUEST )
{
// SNAME
*pTagData++ = PPPOE_TAG_SNAME/256;
*pTagData++ = PPPOE_TAG_SNAME&255;
i = strlen( ppc->ServiceName );
*pTagData++ = (UINT8)(i/256);
*pTagData++ = (UINT8)(i&255);
if( i )
memcpy( pTagData, ppc->ServiceName, i );
pTagData += i;
TagLength += 4+i;
// ACCOOKIE
if( (i = ppc->CookieSize) != 0 )
{
*pTagData++ = PPPOE_TAG_ACCOOKIE/256;
*pTagData++ = PPPOE_TAG_ACCOOKIE&255;
*pTagData++ = (UINT8)(i/256);
*pTagData++ = (UINT8)(i&255);
memcpy( pTagData, ppc->Cookie, i );
pTagData += i;
TagLength += 4+i;
}
}
// Set TagLength in packet
pHdr->Length = HNC16(TagLength);
// Send packet
llPacketSend( IFGetIndex(ppc->ppi.hEther), pb, 0,
SIZE_ETHHDR+SIZE_PPPOEHDR+TagLength, hFrag );
}
//--------------------------------------------------------------
// pppoeInputC()
//
// Packet Rx function for PPPOE Client
//--------------------------------------------------------------
static void pppoeInputC( HANDLE hPkt )
{
HANDLE hFrag;
UINT8 *pb;
uint Offset;
ETHHDR *pEth;
PPPOEHDR *pHdr;
UINT8 *pTagData;
int Tag,Len;
int TagLength;
UINT16 SessionId; // SessionId from pkt
INT8 *pServiceName; // Service string in this pkt
UINT8 *pCookie; // Cookie in this pkt
int ServiceNameSize = -1; // Length of service strings
int CookieSize = 0; // Length of cookie
UINT16 type; // Ether message type
// We require the LLC
if( !(PktGetFlags( hPkt ) & FLG_PKT_LLC_VALID) )
goto RXEXIT;
if( !(hFrag = PktGetFrag( hPkt )) )
{
DbgPrintf(DBG_ERROR,"pppoeInput: No Frag on packet!");
goto RXEXIT;
}
// Get the buffer parameters
pb = FragGetBufParams( hFrag, 0, 0, &Offset );
// Get offset to our data
pEth = (ETHHDR *)(pb + Offset);
pHdr = (PPPOEHDR *)(pb + Offset + SIZE_ETHHDR);
// Get the Ether packet type
type = HNC16(pEth->Type);
// We better double check the Ether type
if( type != ETHERTYPE_PPPOE_CTRL && type != ETHERTYPE_PPPOE_DATA )
goto RXEXIT;
// Get the session id from the packet
SessionId = HNC16(pHdr->SessionId);
// Any non-zero session must be valid
if( ppc->ppi.SessionId )
{
if( SessionId != ppc->ppi.SessionId )
goto RXEXIT;
}
// Setup to read tags
pTagData = pHdr->Data;
TagLength = HNC16(pHdr->Length);
// Make sure Tag Length is reasonable
if( TagLength > 1494 )
goto RXEXIT;
if( type == ETHERTYPE_PPPOE_DATA )
{
// Rx PPP Session Packet
if( TagLength>0 && ppc->ppi.SessionId && ppc->ppi.hPPP )
{
Offset += SIZE_ETHHDR + SIZE_PPPOEHDR;
FragSetBufParams( hFrag, TagLength, Offset );
pppInput( ppc->ppi.hPPP, hPkt );
return;
}
goto RXEXIT;
}
// Read Option tags
while( TagLength > 0 )
{
Tag = *pTagData++ * 256;
Tag += *pTagData++;
Len = *pTagData++ * 256;
Len += *pTagData++;
switch( Tag )
{
case PPPOE_TAG_EOL:
// EOL Tag
// Setup variables to fall out of "while" loop.
TagLength = 4;
Len = 0;
break;
case PPPOE_TAG_SNAME:
// Service Name Tag
// If the name isn't too long, and we have room, record the
// first service name.
if( Len<PPPOE_NAMESIZE && ServiceNameSize<0 )
{
pServiceName = (INT8 *)pTagData;
ServiceNameSize = Len;
}
break;
case PPPOE_TAG_ACCOOKIE:
// Cookie Tag
// If the cookie isn't too long, record it
if( Len && Len<PPPOE_NAMESIZE )
{
pCookie = pTagData;
CookieSize = Len;
}
break;
default:
break;
}
pTagData += Len;
TagLength -= Len + 4;
}
//
// Depending on what state we're in, we are looking for a particular
// PPPOE code.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -