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

📄 pppoe.c

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