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

📄 lcp.c

📁 代码在ti的c67系列单片机上实现了完整的TCPIP协议栈
💻 C
📖 第 1 页 / 共 2 页
字号:
//--------------------------------------------------------------------------
// Ip Stack
//--------------------------------------------------------------------------
// LCP.C
//
// Member functions for PPP/LCP
//
// Author: Michael A. Denio
// Copyright 2000 by Texas Instruments Inc.
//-------------------------------------------------------------------------
#include <stkmain.h>
#include "ppp.h"

#ifdef _INCLUDE_PPP_CODE

// Timer Equates
#define LCP_TIMER_CFGIDLE       5
#define LCP_TIMER_CFGRETRY      3
#define LCP_TIMER_ECHOREQUEST   15
#define LCP_TIMER_ECHORETRY     8

// LCP Codes
#define LCPCODE_CFGREQ          1
#define LCPCODE_CFGACK          2
#define LCPCODE_CFGNAK          3
#define LCPCODE_CFGREJ          4
#define LCPCODE_TERMREQ         5
#define LCPCODE_TERMACK         6
#define LCPCODE_CODEREJ         7
#define LCPCODE_PROTREJ         8
#define LCPCODE_ECHOREQ         9
#define LCPCODE_ECHOREPLY       10
#define LCPCODE_DISCREQ         11

// LCP Configuration Options
#define LCPOPT_MRU              1
#define LCPOPT_CMAP             2
#define LCPOPT_AUTH             3
#define LCPOPT_MAGIC            5

static void lcpSendCfg( PPP_SESSION *p );
static void lcpSendTerm( PPP_SESSION *p );
static void lcpSendEcho( PPP_SESSION *p );

//--------------------------------------------------------------------
// lcpInit()
//
// Initialize LCP and set it to CLOSED state
//--------------------------------------------------------------------
void lcpInit( PPP_SESSION *p )
{
    p->lcp.State     = PROT_STATE_CLOSED;
    p->lcp.StateCFG  = PROT_CFG_IDLE;
    p->lcp.StateACK  = PROT_CFG_IDLE;
    p->lcp.PeerMagic = 0;
    llTimerGetTime(&p->lcp.OurMagic);
    p->lcp.OurMagic = (p->lcp.OurMagic << 4) + llTimerGetTime(0);

    // The following can be used prior to our startup

    // Set the options we allow
    p->lcp.OptMask  = (1l<<LCPOPT_MRU) | (1l<<LCPOPT_MAGIC);

    // On client, we allow authentication
    if( p->Flags & PPPFLG_CLIENT )
        p->lcp.OptMask |= (1l<<LCPOPT_AUTH);

    // If requested, we allow CMAP
    if( p->Flags & PPPFLG_SIOPT_RECVCMAP )
        p->lcp.OptMask |= (1l<<LCPOPT_CMAP);
}

//--------------------------------------------------------------------
// lcpOpen()
//
// Open LCP and set passive or active
//--------------------------------------------------------------------
void lcpOpen( PPP_SESSION *p, uint fStart )
{
    // Set our new state
    if(p->lcp.State == PROT_STATE_CLOSED || p->lcp.State == PROT_STATE_STOPPED)
        p->lcp.State = PROT_STATE_OPEN;

    // Start our negotiation if desired
    if( fStart && p->lcp.StateCFG == PROT_CFG_IDLE )
    {
        p->lcp.StateCFG = PROT_CFG_PENDING;
        p->lcp.Count    = 5;               // Retry Count

        // Set some defaults
        p->lcp.LastId   = 0;               // Default Id
        p->MTU_Rx       = p->MTU_Phys;     // Our MTU (MRU)

        // Desired Options
        p->lcp.UseMask  = (1l<<LCPOPT_MRU) | (1l<<LCPOPT_MAGIC);
        if( p->auth.Protocol )
            p->lcp.UseMask |= (1l<<LCPOPT_AUTH);

        // If requested, we send CMAP
        if( p->Flags & PPPFLG_SIOPT_SENDCMAP )
            p->lcp.UseMask |= (1l<<LCPOPT_CMAP);

        lcpSendCfg( p );

        p->SICtrl( p->hSI, SI_MSG_CALLSTATUS, SI_CSTATUS_NEGOTIATE, 0);
    }
    else
    {
        // Regardless of state, we set a timeout. If this timeout
        // fires while StateACK is idle, we close
        p->lcp.Timer = LCP_TIMER_CFGIDLE;
        p->lcp.Count = 0;
    }
}

//--------------------------------------------------------------------
// lcpClose()
//
// Close the LCP and reset
//--------------------------------------------------------------------
void lcpClose( PPP_SESSION *p )
{
    // Send Termination if we are connected
    if( p->lcp.State == PROT_STATE_CONNECTED )
    {
        lcpSendTerm( p );
        p->lcp.State = PROT_STATE_STOPPED;
    }
}

//--------------------------------------------------------------------
// lcpInput()
//
// Receive an LCP packet
//--------------------------------------------------------------------
void lcpInput( PPP_SESSION *p, HANDLE hPkt )
{
    LCPHDR      *pHdr;
    HANDLE      hFrag;
    UINT8       *pb;
    uint        Size,Offset;
    UINT32      cmap;
    int         TagLen;
    UINT16      Len,wTmp;
    UINT8       Tag,TagSize,*pTagData;
    int         RetCode;
    int         BadTagLen;
    UINT8       *pBadTagData;

    // If we're closed, return now
    if( p->lcp.State == PROT_STATE_CLOSED )
        goto LCPExit;

    // We know we have a Frag...
    hFrag = PktGetFrag( hPkt );

    // Get the buffer parameters
    pb = FragGetBufParams( hFrag, 0, &Size, &Offset );
    pb += Offset;

    // Get the LCPHDR
    pHdr = (LCPHDR *)pb;

    // Get packet length
    Len  = HNC16( pHdr->Length );

    // Verify that we have the entire packet
    if( Len > (UINT16)Size )
        goto LCPExit;

    switch( pHdr->Code )
    {
    case LCPCODE_CFGREQ:
        //---------------------
        // Configure-Request
        //---------------------

        // Set default MRU
        p->MTU_Tx = p->MTU_Phys;

        // Scan the options
        pTagData    = pHdr->TagData;
        TagLen      = (int)(Len - SIZE_LCPHDR);
        RetCode     = LCPCODE_CFGACK;

        // Setup these pointers for use by NAK
        BadTagLen   = 0;
        pBadTagData = pHdr->TagData;

        while( TagLen > 0 )
        {
            Tag     = *pTagData++;
            TagSize = *pTagData++;

            // Check for malformed packet
            if( !TagSize )
                goto LCPExit;

            // First try reject
            if( Tag > 31 || !(p->lcp.OptMask & (1l<<Tag)) )
            {
                // Reject this option
                if( RetCode != LCPCODE_CFGREJ )
                {
                    // We now use the pointer for REJ, so reset them
                    RetCode     = LCPCODE_CFGREJ;
                    BadTagLen   = 0;
                    pBadTagData = pHdr->TagData;
                }

                *pBadTagData++ = Tag;
                *pBadTagData++ = TagSize;
                if( TagSize > 2 )
                    mmCopy( pBadTagData, pTagData, TagSize );
                BadTagLen   += TagSize;
                pBadTagData += TagSize - 2;
            }

            // If not in reject state, process option
            if( RetCode != LCPCODE_CFGREJ )
            {
                // Process
                switch( Tag )
                {
                case LCPOPT_MAGIC:
                    // If the magic number is ours, discard the request
                    if( p->lcp.OurMagic &&
                            p->lcp.OurMagic == RdNet32( pTagData ) )
                        goto LCPExit;
                    break;

                case LCPOPT_MRU:
                    wTmp = RdNet16s( pTagData );
                    if( wTmp > (UINT16)p->MTU_Tx )
                    {
                        // We must NAK this value
                        RetCode = LCPCODE_CFGNAK;

                        *pBadTagData++ = Tag;
                        *pBadTagData++ = 4;
                        *pBadTagData++ = (UINT8)(p->MTU_Tx/256);
                        *pBadTagData++ = (UINT8)(p->MTU_Tx&255);
                        BadTagLen += 4;
                    }
                    else
                        p->MTU_Tx = wTmp;
                    break;

                case LCPOPT_AUTH:
                    // If we are a client, we try and accept what the peer
                    // is giving us. If we don't handle it, we ask for PAP.
                    if( p->Flags & PPPFLG_CLIENT )
                    {
                        wTmp = RdNet16s( pTagData );

                        if( ( wTmp == PPPPROT_CHAP &&
                                   (TagSize!=5 || *(pTagData+2)!=5) ) ||
                            ( wTmp != PPPPROT_CHAP && wTmp != PPPPROT_PAP ) )
                        {
                            // We don't support the requested authorization
                            // Ask for PAP, just in case they'll take it
                            RetCode = LCPCODE_CFGNAK;

                            *pBadTagData++ = Tag;
                            *pBadTagData++ = 4;
                            *pBadTagData++ = (UINT8)(PPPPROT_PAP/256);
                            *pBadTagData++ = (UINT8)(PPPPROT_PAP&255);
                            BadTagLen += 4;
                        }
                        else
                            p->auth.Protocol = wTmp;
                    }
                    break;

                case LCPOPT_CMAP:
                    if( TagSize == 6 )
                    {
                        wTmp = RdNet16s( pTagData );
                        cmap = ((UINT32)wTmp)<<16;
                        wTmp = RdNet16s( (pTagData+2) );
                        cmap |= (UINT32)wTmp;
                        p->SICtrl( p->hSI, SI_MSG_PEERCMAP, cmap, 0 );
                    }
                    break;
                }
            }

            // Goto next tag
            TagLen -= (int)TagSize;
            pTagData += TagSize - 2;
        }

        // Reply to this request
        pHdr->Code = RetCode;
        if( RetCode == LCPCODE_CFGACK )
        {
            FragSetBufParams( hFrag, Len, Offset );
            // Set new state
            p->lcp.StateACK = PROT_CFG_OK;
        }
        else
        {
            // Change length to reflect bad options
            BadTagLen += SIZE_LCPHDR;
            pHdr->Length = HNC16(BadTagLen);
            FragSetBufParams( hFrag, BadTagLen, Offset );
            // Set new state
            p->lcp.StateACK = PROT_CFG_PENDING;
        }

        // Send Packet
        p->SICtrl(p->hSI, SI_MSG_SENDPACKET, PPPPROT_LCP, hPkt );
        hPkt = 0;
        goto LCPStateChange;

    case LCPCODE_CFGACK:
        //---------------------
        // Configure-Ack
        //---------------------
        // If this ID does not match ours, ignore it
        if( p->lcp.LastId != pHdr->Id )
            goto LCPExit;

        // Scan options
        pTagData = pHdr->TagData;
        TagLen   = (int)(Len - SIZE_LCPHDR);

        while( TagLen > 0 )
        {
            Tag     = *pTagData++;
            TagSize = *pTagData++;

            // Check for malformed packet
            if( !TagSize )
                goto LCPExit;

            switch( Tag )
            {
            case LCPOPT_MAGIC:
                // Magic number must be ours
                if( p->lcp.OurMagic &&
                        p->lcp.OurMagic != RdNet32( pTagData ) )
                    goto LCPExit;
                break;
            }

            // Goto next tag
            TagLen -= (int)TagSize;
            pTagData += TagSize - 2;
        }

        // CFG half is connected
        p->lcp.StateCFG = PROT_CFG_OK;
        goto LCPStateChange;

    case LCPCODE_CFGNAK:
    case LCPCODE_CFGREJ:
        //---------------------
        // Configure-Nak
        // Configure-Reject
        //---------------------
        // If this ID does not match ours, ignore it
        if( p->lcp.LastId != pHdr->Id )
            goto LCPExit;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -