⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pppoe.c

📁 代码在ti的c67系列单片机上实现了完整的TCPIP协议栈
💻 C
📖 第 1 页 / 共 3 页
字号:
//--------------------------------------------------------------------------
// 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 + -