📄 pppoe.c
字号:
//
switch( ppc->State )
{
case PPPOE_SM_IDLE:
break;
// During a service query...
case PPPOE_SM_INITIATING:
// Look for an OFFER
if( pHdr->Code != PPPOE_CODE_OFFER )
break;
// Check for service
if( ServiceNameSize >= 0 )
{
// Copy Service Name
if( ServiceNameSize > 0 )
mmCopy( ppc->ServiceName, pServiceName, ServiceNameSize );
ppc->ServiceName[ServiceNameSize] = 0;
// Copy cookie
if( CookieSize )
memcpy( ppc->Cookie, pCookie, CookieSize );
ppc->CookieSize = CookieSize;
// Copy server MAC
mmCopy( ppc->ppi.PeerMac, pEth->SrcMac, 6 );
}
// Open the service
pppoeCtrlMsg( ppc, PPPOE_MSG_OPEN );
break;
// Opening a session...
case PPPOE_SM_REQUESTING:
// Look for a CONFIRM
if( pHdr->Code != PPPOE_CODE_CONFIRM )
break;
// If the SessionId is NULL, we have an error
if( !SessionId )
break;
// Save our session Id
ppc->ppi.SessionId = SessionId;
// Open the PPP device
ppc->ppi.hPPP = pppNew( &(ppc->ppi), ppc->pppFlags, 1492, 0, 0, 0,
ppc->Username, ppc->Password, 0, &pppoeSI );
if( !ppc->ppi.hPPP )
break;
// Notify the status function
ppc->State = PPPOE_SM_CONFIRMED;
break;
// During an established session...
case PPPOE_SM_CONFIRMED:
// Look for a TERMINATE
if( pHdr->Code != PPPOE_CODE_TERMINATE )
break;
// The session ID must be ours
if( SessionId != ppc->ppi.SessionId )
break;
// Close the session
pppoeSI( &(ppc->ppi), SI_MSG_CALLSTATUS, SI_CSTATUS_DISCONNECT, 0 );
break;
}
RXEXIT:
// hPkt Must be Free'd
if( hPkt )
PktFree( hPkt );
}
//----------------------------------------------------------------------
//----------------------------------------------------------------------
// PPPOE SERVER
//----------------------------------------------------------------------
//----------------------------------------------------------------------
//--------------------------------------------------------------
// pppoesTimer()
//
// Dispatches time ticks to PPP clients
//--------------------------------------------------------------
static void pppoesTimer( uint Msg )
{
uint i;
(void)Msg;
// Indicate timer tick to all open sessions
if( pps )
for( i=0; i<pps->SessionMax; i++ )
if( pps->ppi[i].hPPP )
pppTimer( pps->ppi[i].hPPP );
}
//--------------------------------------------------------------------
// SendSeverMsg()
//
// Private SendSeverMsg Function for State Machine
//--------------------------------------------------------------------
static void SendSeverMsg( 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( pps->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_OFFER || Code == PPPOE_CODE_CONFIRM )
{
// SNAME
*pTagData++ = PPPOE_TAG_SNAME/256;
*pTagData++ = PPPOE_TAG_SNAME&255;
i = strlen( pps->ServiceName );
*pTagData++ = (UINT8)(i/256);
*pTagData++ = (UINT8)(i&255);
if( i )
mmCopy( pTagData, pps->ServiceName, i );
pTagData += i;
TagLength += 4+i;
}
if( Code == PPPOE_CODE_OFFER )
{
// ACNAME
*pTagData++ = PPPOE_TAG_ACNAME/256;
*pTagData++ = PPPOE_TAG_ACNAME&255;
i = strlen( pps->ServerName );
*pTagData++ = (UINT8)(i/256);
*pTagData++ = (UINT8)(i&255);
if( i )
mmCopy( pTagData, pps->ServerName, i );
pTagData += i;
TagLength += 4+i;
}
// Set TagLength in packet
pHdr->Length = HNC16(TagLength);
// Send packet
llPacketSend( IFGetIndex(pps->hEther), pb, 0,
SIZE_ETHHDR+SIZE_PPPOEHDR+TagLength, hFrag );
}
//--------------------------------------------------------------
// pppoeInputS()
//
// Packet Rx function for PPPOE Server
//--------------------------------------------------------------
static void pppoeInputS( HANDLE hPkt )
{
PPPOE_INST *ppi = 0;
HANDLE hFrag;
UINT8 *pb;
uint Offset,i;
ETHHDR *pEth;
PPPOEHDR *pHdr;
UINT8 *pTagData;
int Tag,Len;
int TagLength;
UINT16 SessionId; // SessionId from pkt
INT8 *pServiceName; // Service string in this pkt
int ServiceNameSize = -1; // Length of service strings
UINT16 type; // Ether message type
IPN IPClient; // Client IP address
// Discard packet if not open or not on out ETHER device
if( !pps || pps->hEther != PktGetIFRx( hPkt ) )
goto RXEXIT;
// We require the LLC
if( !(PktGetFlags( hPkt ) & FLG_PKT_LLC_VALID) )
goto RXEXIT;
if( !(hFrag = PktGetFrag( hPkt )) )
{
DbgPrintf(DBG_ERROR,"pppoesInput: 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);
// Get a pointer to the server session if SessionId != 0
// Any non-zero session must be valid
if( SessionId )
{
if( SessionId > pps->SessionMax )
goto RXEXIT;
ppi = &(pps->ppi[SessionId-1]);
if( !ppi->hPPP )
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 && ppi->hPPP )
{
Offset += SIZE_ETHHDR + SIZE_PPPOEHDR;
FragSetBufParams( hFrag, TagLength, Offset );
pppInput( 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 this
// service name.
if( Len<PPPOE_NAMESIZE && ServiceNameSize<0 )
{
pServiceName = (INT8 *)pTagData;
ServiceNameSize = Len;
}
break;
default:
break;
}
pTagData += Len;
TagLength -= Len + 4;
}
//
// Depending on what state we're in, we are looking for a particular
// PPPOE code.
//
switch( pHdr->Code )
{
case PPPOE_CODE_INITIATION:
// Sender is asking for an offer
// Send the offer
SendSeverMsg( PPPOE_CODE_OFFER, 0, pEth->SrcMac );
break;
case PPPOE_CODE_OFFER:
break;
case PPPOE_CODE_REQUEST:
// Sender is asking for a session
// Verify the sender is requesting our serivce
if( ServiceNameSize > 0 )
{
if( (int)strlen( pps->ServiceName ) != ServiceNameSize )
break;
if( strncmp( pps->ServiceName, pServiceName, ServiceNameSize ) )
break;
}
// Open a new session
for( i=0; i<pps->SessionMax; i++ )
{
ppi = &(pps->ppi[i]);
if( !ppi->hPPP )
break;
}
// If no sessions available, ignore request
if( i == pps->SessionMax )
break;
// Get the client IP address
IPClient = HNC32(pps->IPClientBase) + i;
IPClient = HNC32(IPClient);
// Record the Mac address of our client
mmCopy( ppi->PeerMac, pEth->SrcMac, 6 );
// Open PPP
ppi->hPPP = pppNew( ppi, pps->pppFlags, 1492,
pps->IPServer, pps->IPMask, IPClient,
0, 0, 0, &pppoeSI );
if( !ppi->hPPP )
break;
// Send the confirmation
SendSeverMsg( PPPOE_CODE_CONFIRM, ppi->SessionId, ppi->PeerMac );
break;
case PPPOE_CODE_CONFIRM:
break;
case PPPOE_CODE_TERMINATE:
// Send the confirmation
if( ppi )
pppoeSI( ppi, SI_MSG_CALLSTATUS, SI_CSTATUS_DISCONNECT, 0 );
break;
}
RXEXIT:
// hPkt Must be Free'd
if( hPkt )
PktFree( hPkt );
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -