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

📄 lcp.c

📁 基于STM32F107的UDP服务器程序
💻 C
📖 第 1 页 / 共 4 页
字号:
/*****************************************************************************
* lcp.c - Network Link Control Protocol program file.
*
* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
* portions Copyright (c) 1997 by Global Election Systems Inc.
*
* The authors hereby grant permission to use, copy, modify, distribute,
* and license this software and its documentation for any purpose, provided
* that existing copyright notices are retained in all copies and that this
* notice and the following disclaimer are included verbatim in any 
* distributions. No written agreement, license, or royalty fee is required
* for any of the authorized uses.
*
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
* REVISION HISTORY
*
* 03-01-01 Marc Boucher <marc@mbsi.ca>
*   Ported to lwIP.
* 97-12-01 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
*   Original.
*****************************************************************************/

/*
 * lcp.c - PPP Link Control Protocol.
 *
 * Copyright (c) 1989 Carnegie Mellon University.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by Carnegie Mellon University.  The name of the
 * University may not be used to endorse or promote products derived
 * from this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */
 

#include "lwip/opt.h"

#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */

#include "ppp.h"
#include "pppdebug.h"

#include "fsm.h"
#include "chap.h"
#include "magic.h"
#include "auth.h"
#include "lcp.h"

#include <string.h>

#if PPPOE_SUPPORT
#include "netif/ppp_oe.h"
#else
#define PPPOE_MAXMTU PPP_MAXMRU
#endif


/*************************/
/*** LOCAL DEFINITIONS ***/
/*************************/
/*
 * Length of each type of configuration option (in octets)
 */
#define CILEN_VOID  2
#define CILEN_CHAR  3
#define CILEN_SHORT 4 /* CILEN_VOID + sizeof(short) */
#define CILEN_CHAP  5 /* CILEN_VOID + sizeof(short) + 1 */
#define CILEN_LONG  6 /* CILEN_VOID + sizeof(long) */
#define CILEN_LQR   8 /* CILEN_VOID + sizeof(short) + sizeof(long) */
#define CILEN_CBCP  3


/***********************************/
/*** LOCAL FUNCTION DECLARATIONS ***/
/***********************************/
/*
 * Callbacks for fsm code.  (CI = Configuration Information)
 */
static void lcp_resetci (fsm*);                   /* Reset our CI */
static int  lcp_cilen (fsm*);                     /* Return length of our CI */
static void lcp_addci (fsm*, u_char*, int*);      /* Add our CI to pkt */
static int  lcp_ackci (fsm*, u_char*, int);       /* Peer ack'd our CI */
static int  lcp_nakci (fsm*, u_char*, int);       /* Peer nak'd our CI */
static int  lcp_rejci (fsm*, u_char*, int);       /* Peer rej'd our CI */
static int  lcp_reqci (fsm*, u_char*, int*, int); /* Rcv peer CI */
static void lcp_up (fsm*);                        /* We're UP */
static void lcp_down (fsm*);                      /* We're DOWN */
static void lcp_starting (fsm*);                  /* We need lower layer up */
static void lcp_finished (fsm*);                  /* We need lower layer down */
static int  lcp_extcode (fsm*, int, u_char, u_char*, int);

static void lcp_rprotrej (fsm*, u_char*, int);

/*
 * routines to send LCP echos to peer
 */
static void lcp_echo_lowerup (int);
static void lcp_echo_lowerdown (int);
static void LcpEchoTimeout (void*);
static void lcp_received_echo_reply (fsm*, int, u_char*, int);
static void LcpSendEchoRequest (fsm*);
static void LcpLinkFailure (fsm*);
static void LcpEchoCheck (fsm*);

/*
 * Protocol entry points.
 * Some of these are called directly.
 */
static void lcp_input (int, u_char *, int);
static void lcp_protrej (int);

#define CODENAME(x) ((x) == CONFACK ? "ACK" : (x) == CONFNAK ? "NAK" : "REJ")


/******************************/
/*** PUBLIC DATA STRUCTURES ***/
/******************************/
/* global vars */
LinkPhase lcp_phase[NUM_PPP];          /* Phase of link session (RFC 1661) */
lcp_options lcp_wantoptions[NUM_PPP];  /* Options that we want to request */
lcp_options lcp_gotoptions[NUM_PPP];   /* Options that peer ack'd */
lcp_options lcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */
lcp_options lcp_hisoptions[NUM_PPP];   /* Options that we ack'd */
ext_accm xmit_accm[NUM_PPP];           /* extended transmit ACCM */



/*****************************/
/*** LOCAL DATA STRUCTURES ***/
/*****************************/
static fsm lcp_fsm[NUM_PPP];                            /* LCP fsm structure (global)*/
static u_int lcp_echo_interval      = LCP_ECHOINTERVAL; /* Interval between LCP echo-requests */
static u_int lcp_echo_fails         = LCP_MAXECHOFAILS; /* Tolerance to unanswered echo-requests */
static u32_t lcp_echos_pending      = 0;                /* Number of outstanding echo msgs */
static u32_t lcp_echo_number        = 0;                /* ID number of next echo frame */
static u32_t lcp_echo_timer_running = 0;                /* TRUE if a timer is running */

static u_char nak_buffer[PPP_MRU]; /* where we construct a nak packet */

static fsm_callbacks lcp_callbacks = { /* LCP callback routines */
  lcp_resetci,  /* Reset our Configuration Information */
  lcp_cilen,    /* Length of our Configuration Information */
  lcp_addci,    /* Add our Configuration Information */
  lcp_ackci,    /* ACK our Configuration Information */
  lcp_nakci,    /* NAK our Configuration Information */
  lcp_rejci,    /* Reject our Configuration Information */
  lcp_reqci,    /* Request peer's Configuration Information */
  lcp_up,       /* Called when fsm reaches LS_OPENED state */
  lcp_down,     /* Called when fsm leaves LS_OPENED state */
  lcp_starting, /* Called when we want the lower layer up */
  lcp_finished, /* Called when we want the lower layer down */
  NULL,         /* Called when Protocol-Reject received */
  NULL,         /* Retransmission is necessary */
  lcp_extcode,  /* Called to handle LCP-specific codes */
  "LCP"         /* String name of protocol */
};

struct protent lcp_protent = {
    PPP_LCP,
    lcp_init,
    lcp_input,
    lcp_protrej,
    lcp_lowerup,
    lcp_lowerdown,
    lcp_open,
    lcp_close,
#if 0
    lcp_printpkt,
    NULL,
#endif
    1,
    "LCP",
#if 0
    NULL,
    NULL,
    NULL
#endif
};

int lcp_loopbackfail = DEFLOOPBACKFAIL;



/***********************************/
/*** PUBLIC FUNCTION DEFINITIONS ***/
/***********************************/
/*
 * lcp_init - Initialize LCP.
 */
void
lcp_init(int unit)
{
  fsm         *f  = &lcp_fsm[unit];
  lcp_options *wo = &lcp_wantoptions[unit];
  lcp_options *ao = &lcp_allowoptions[unit];
  
  f->unit      = unit;
  f->protocol  = PPP_LCP;
  f->callbacks = &lcp_callbacks;
  
  fsm_init(f);
  
  wo->passive           = 0;
  wo->silent            = 0;
  wo->restart           = 0;               /* Set to 1 in kernels or multi-line implementations */
  wo->neg_mru           = 1;
  wo->mru               = PPP_DEFMRU;
  wo->neg_asyncmap      = 1;
  wo->asyncmap          = 0x00000000l;     /* Assume don't need to escape any ctl chars. */
  wo->neg_chap          = 0;               /* Set to 1 on server */
  wo->neg_upap          = 0;               /* Set to 1 on server */
  wo->chap_mdtype       = CHAP_DIGEST_MD5;
  wo->neg_magicnumber   = 1;
  wo->neg_pcompression  = 1;
  wo->neg_accompression = 1;
  wo->neg_lqr           = 0;               /* no LQR implementation yet */
  wo->neg_cbcp          = 0;
  
  ao->neg_mru           = 1;
  ao->mru               = PPP_MAXMRU;
  ao->neg_asyncmap      = 1;
  ao->asyncmap          = 0x00000000l;     /* Assume don't need to escape any ctl chars. */
  ao->neg_chap          = (CHAP_SUPPORT != 0);
  ao->chap_mdtype       = CHAP_DIGEST_MD5;
  ao->neg_upap          = (PAP_SUPPORT != 0);
  ao->neg_magicnumber   = 1;
  ao->neg_pcompression  = 1;
  ao->neg_accompression = 1;
  ao->neg_lqr           = 0;               /* no LQR implementation yet */
  ao->neg_cbcp          = (CBCP_SUPPORT != 0);

  /* 
   * Set transmit escape for the flag and escape characters plus anything
   * set for the allowable options.
   */
  memset(xmit_accm[unit], 0, sizeof(xmit_accm[0]));
  xmit_accm[unit][15] = 0x60;
  xmit_accm[unit][0]  = (u_char)((ao->asyncmap        & 0xFF));
  xmit_accm[unit][1]  = (u_char)((ao->asyncmap >> 8)  & 0xFF);
  xmit_accm[unit][2]  = (u_char)((ao->asyncmap >> 16) & 0xFF);
  xmit_accm[unit][3]  = (u_char)((ao->asyncmap >> 24) & 0xFF);
  LCPDEBUG((LOG_INFO, "lcp_init: xmit_accm=%X %X %X %X\n",
        xmit_accm[unit][0],
        xmit_accm[unit][1],
        xmit_accm[unit][2],
        xmit_accm[unit][3]));
  
  lcp_phase[unit] = PHASE_INITIALIZE;
}


/*
 * lcp_open - LCP is allowed to come up.
 */
void
lcp_open(int unit)
{
  fsm         *f  = &lcp_fsm[unit];
  lcp_options *wo = &lcp_wantoptions[unit];

  f->flags = 0;
  if (wo->passive) {
    f->flags |= OPT_PASSIVE;
  }
  if (wo->silent) {
    f->flags |= OPT_SILENT;
  }
  fsm_open(f);

  lcp_phase[unit] = PHASE_ESTABLISH;
}


/*
 * lcp_close - Take LCP down.
 */
void
lcp_close(int unit, char *reason)
{
  fsm *f = &lcp_fsm[unit];

  if (lcp_phase[unit] != PHASE_DEAD) {
    lcp_phase[unit] = PHASE_TERMINATE;
  }
  if (f->state == LS_STOPPED && f->flags & (OPT_PASSIVE|OPT_SILENT)) {
    /*
     * This action is not strictly according to the FSM in RFC1548,
     * but it does mean that the program terminates if you do an
     * lcp_close() in passive/silent mode when a connection hasn't
     * been established.
     */
    f->state = LS_CLOSED;
    lcp_finished(f);
  } else {
    fsm_close(&lcp_fsm[unit], reason);
  }
}


/*
 * lcp_lowerup - The lower layer is up.
 */
void
lcp_lowerup(int unit)
{
  lcp_options *wo = &lcp_wantoptions[unit];

  /*
   * Don't use A/C or protocol compression on transmission,
   * but accept A/C and protocol compressed packets
   * if we are going to ask for A/C and protocol compression.
   */
  ppp_set_xaccm(unit, &xmit_accm[unit]);
  ppp_send_config(unit, PPP_MRU, 0xffffffffl, 0, 0);
  ppp_recv_config(unit, PPP_MRU, 0x00000000l,
  wo->neg_pcompression, wo->neg_accompression);
  peer_mru[unit] = PPP_MRU;
  lcp_allowoptions[unit].asyncmap = (u_long)xmit_accm[unit][0]
                                 | ((u_long)xmit_accm[unit][1] << 8)
                                 | ((u_long)xmit_accm[unit][2] << 16)
                                 | ((u_long)xmit_accm[unit][3] << 24);
  LCPDEBUG((LOG_INFO, "lcp_lowerup: asyncmap=%X %X %X %X\n",
            xmit_accm[unit][3],
            xmit_accm[unit][2],
            xmit_accm[unit][1],
            xmit_accm[unit][0]));

  fsm_lowerup(&lcp_fsm[unit]);
}


/*
 * lcp_lowerdown - The lower layer is down.
 */
void
lcp_lowerdown(int unit)
{
  fsm_lowerdown(&lcp_fsm[unit]);
}

/*
 * lcp_sprotrej - Send a Protocol-Reject for some protocol.
 */
void
lcp_sprotrej(int unit, u_char *p, int len)
{
  /*
   * Send back the protocol and the information field of the
   * rejected packet.  We only get here if LCP is in the LS_OPENED state.
   */

  fsm_sdata(&lcp_fsm[unit], PROTREJ, ++lcp_fsm[unit].id, p, len);
}



/**********************************/
/*** LOCAL FUNCTION DEFINITIONS ***/
/**********************************/
/*
 * lcp_input - Input LCP packet.
 */
static void
lcp_input(int unit, u_char *p, int len)
{
  fsm *f = &lcp_fsm[unit];

  fsm_input(f, p, len);
}


/*
 * lcp_extcode - Handle a LCP-specific code.
 */
static int
lcp_extcode(fsm *f, int code, u_char id, u_char *inp, int len)
{
  u_char *magp;

  switch( code ){
    case PROTREJ:
      lcp_rprotrej(f, inp, len);
      break;
  
    case ECHOREQ:
      if (f->state != LS_OPENED) {
        break;
      }
      LCPDEBUG((LOG_INFO, "lcp: Echo-Request, Rcvd id %d\n", id));
      magp = inp;
      PUTLONG(lcp_gotoptions[f->unit].magicnumber, magp);
      fsm_sdata(f, ECHOREP, id, inp, len);
      break;

    case ECHOREP:
      lcp_received_echo_reply(f, id, inp, len);
      break;
    
    case DISCREQ:
      break;
    
    default:
      return 0;
  }
  return 1;
}


/*
 * lcp_rprotrej - Receive an Protocol-Reject.
 *
 * Figure out which protocol is rejected and inform it.
 */
static void
lcp_rprotrej(fsm *f, u_char *inp, int len)
{
  int i;
  struct protent *protp;
  u_short prot;

  if (len < sizeof (u_short)) {
    LCPDEBUG((LOG_INFO, "lcp_rprotrej: Rcvd short Protocol-Reject packet!\n"));
    return;
  }

  GETSHORT(prot, inp);

  LCPDEBUG((LOG_INFO, "lcp_rprotrej: Rcvd Protocol-Reject packet for %x!\n", prot));

  /*
   * Protocol-Reject packets received in any state other than the LCP
   * LS_OPENED state SHOULD be silently discarded.
   */
  if( f->state != LS_OPENED ) {
    LCPDEBUG((LOG_INFO, "Protocol-Reject discarded: LCP in state %d\n", f->state));
    return;
  }

  /*
   * Upcall the proper Protocol-Reject routine.
   */
  for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) {
    if (protp->protocol == prot && protp->enabled_flag) {
      (*protp->protrej)(f->unit);
      return;
    }
  }

  LCPDEBUG((LOG_WARNING, "Protocol-Reject for unsupported protocol 0x%x\n", prot));
}


/*
 * lcp_protrej - A Protocol-Reject was received.
 */
static void
lcp_protrej(int unit)
{
  LWIP_UNUSED_ARG(unit);
  /*
   * Can't reject LCP!
   */
  LCPDEBUG((LOG_WARNING, "lcp_protrej: Received Protocol-Reject for LCP!\n"));
  fsm_protreject(&lcp_fsm[unit]);
}


/*
 * lcp_resetci - Reset our CI.
 */
static void
lcp_resetci(fsm *f)
{
  lcp_wantoptions[f->unit].magicnumber = magic();
  lcp_wantoptions[f->unit].numloops = 0;
  lcp_gotoptions[f->unit] = lcp_wantoptions[f->unit];
  peer_mru[f->unit] = PPP_MRU;
  auth_reset(f->unit);
}


/*
 * lcp_cilen - Return length of our CI.
 */
static int lcp_cilen(fsm *f)
{
  lcp_options *go = &lcp_gotoptions[f->unit];

#define LENCIVOID(neg)  ((neg) ? CILEN_VOID : 0)
#define LENCICHAP(neg)  ((neg) ? CILEN_CHAP : 0)
#define LENCISHORT(neg) ((neg) ? CILEN_SHORT : 0)

⌨️ 快捷键说明

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