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

📄 pppoe.c

📁 代码在ti的c67系列单片机上实现了完整的TCPIP协议栈
💻 C
📖 第 1 页 / 共 3 页
字号:

        // 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 + -