?? lcp.c
字號(hào):
/*****************************************************************************
* 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 "pppconf.h"
#if PPP_SUPPORT > 0
#include "ppp.h"
#include "fsm.h"
#include "chap.h"
#include "magic.h"
#include "auth.h"
#include "lcp.h"
#include "pppdebug.h"
/*************************/
/*** 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, int, u_char*, int);
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 OPENED state */
lcp_down, /* Called when fsm leaves 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 == 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 = 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 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, int id, u_char *inp, int len)
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 != 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
* OPENED state SHOULD be silently discarded.
*/
if( f->state != 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)
{
(void)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)
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -