📄 lcp.c
字号:
/* * 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. */#define RCSID "$Id: lcp.c,v 1.57 2001/03/08 05:11:14 paulus Exp $"/* * TODO: */#include <stdio.h>#include <string.h>#include <stdlib.h>#include "pppd.h"#include "fsm.h"#include "lcp.h"#include "chap.h"#include "magic.h"static const char rcsid[] = RCSID;/* * When the link comes up we want to be able to wait for a short while, * or until seeing some input from the peer, before starting to send * configure-requests. We do this by delaying the fsm_lowerup call. *//* steal a bit in fsm flags word */#define DELAYED_UP 0x100static void lcp_delayed_up __P((void *));/* * LCP-related command-line options. */int lcp_echo_interval = 0; /* Interval between LCP echo-requests */int lcp_echo_fails = 0; /* Tolerance to unanswered echo-requests */bool lax_recv = 0; /* accept control chars in asyncmap */bool noendpoint = 0; /* don't send/accept endpoint discriminator */static int noopt __P((char **));#ifdef HAVE_MULTILINKstatic int setendpoint __P((char **));static void printendpoint __P((option_t *, void (*)(void *, char *, ...), void *));#endif /* HAVE_MULTILINK */static option_t lcp_option_list[] = { /* LCP options */ { "-all", o_special_noarg, (void *)noopt, "Don't request/allow any LCP options" }, { "noaccomp", o_bool, &lcp_wantoptions[0].neg_accompression, "Disable address/control compression", OPT_A2CLR, &lcp_allowoptions[0].neg_accompression }, { "-ac", o_bool, &lcp_wantoptions[0].neg_accompression, "Disable address/control compression", OPT_ALIAS | OPT_A2CLR, &lcp_allowoptions[0].neg_accompression }, { "asyncmap", o_uint32, &lcp_wantoptions[0].asyncmap, "Set asyncmap (for received packets)", OPT_OR, &lcp_wantoptions[0].neg_asyncmap }, { "-as", o_uint32, &lcp_wantoptions[0].asyncmap, "Set asyncmap (for received packets)", OPT_ALIAS | OPT_OR, &lcp_wantoptions[0].neg_asyncmap }, { "default-asyncmap", o_uint32, &lcp_wantoptions[0].asyncmap, "Disable asyncmap negotiation", OPT_OR | OPT_NOARG | OPT_VAL(~0U) | OPT_A2CLR, &lcp_allowoptions[0].neg_asyncmap }, { "-am", o_uint32, &lcp_wantoptions[0].asyncmap, "Disable asyncmap negotiation", OPT_ALIAS | OPT_OR | OPT_NOARG | OPT_VAL(~0U) | OPT_A2CLR, &lcp_allowoptions[0].neg_asyncmap }, { "nomagic", o_bool, &lcp_wantoptions[0].neg_magicnumber, "Disable magic number negotiation (looped-back line detection)", OPT_A2CLR, &lcp_allowoptions[0].neg_magicnumber }, { "-mn", o_bool, &lcp_wantoptions[0].neg_magicnumber, "Disable magic number negotiation (looped-back line detection)", OPT_ALIAS | OPT_A2CLR, &lcp_allowoptions[0].neg_magicnumber }, { "mru", o_int, &lcp_wantoptions[0].mru, "Set MRU (maximum received packet size) for negotiation", OPT_PRIO, &lcp_wantoptions[0].neg_mru }, { "default-mru", o_bool, &lcp_wantoptions[0].neg_mru, "Disable MRU negotiation (use default 1500)", OPT_PRIOSUB | OPT_A2CLR, &lcp_allowoptions[0].neg_mru }, { "-mru", o_bool, &lcp_wantoptions[0].neg_mru, "Disable MRU negotiation (use default 1500)", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR, &lcp_allowoptions[0].neg_mru }, { "mtu", o_int, &lcp_allowoptions[0].mru, "Set our MTU", OPT_LIMITS, NULL, MAXMRU, MINMRU }, { "nopcomp", o_bool, &lcp_wantoptions[0].neg_pcompression, "Disable protocol field compression", OPT_A2CLR, &lcp_allowoptions[0].neg_pcompression }, { "-pc", o_bool, &lcp_wantoptions[0].neg_pcompression, "Disable protocol field compression", OPT_ALIAS | OPT_A2CLR, &lcp_allowoptions[0].neg_pcompression }, { "passive", o_bool, &lcp_wantoptions[0].passive, "Set passive mode", 1 }, { "-p", o_bool, &lcp_wantoptions[0].passive, "Set passive mode", OPT_ALIAS | 1 }, { "silent", o_bool, &lcp_wantoptions[0].silent, "Set silent mode", 1 }, { "lcp-echo-failure", o_int, &lcp_echo_fails, "Set number of consecutive echo failures to indicate link failure", OPT_PRIO }, { "lcp-echo-interval", o_int, &lcp_echo_interval, "Set time in seconds between LCP echo requests", OPT_PRIO }, { "lcp-restart", o_int, &lcp_fsm[0].timeouttime, "Set time in seconds between LCP retransmissions", OPT_PRIO }, { "lcp-max-terminate", o_int, &lcp_fsm[0].maxtermtransmits, "Set maximum number of LCP terminate-request transmissions", OPT_PRIO }, { "lcp-max-configure", o_int, &lcp_fsm[0].maxconfreqtransmits, "Set maximum number of LCP configure-request transmissions", OPT_PRIO }, { "lcp-max-failure", o_int, &lcp_fsm[0].maxnakloops, "Set limit on number of LCP configure-naks", OPT_PRIO }, { "receive-all", o_bool, &lax_recv, "Accept all received control characters", 1 },#ifdef HAVE_MULTILINK { "mrru", o_int, &lcp_wantoptions[0].mrru, "Maximum received packet size for multilink bundle", OPT_PRIO, &lcp_wantoptions[0].neg_mrru }, { "mpshortseq", o_bool, &lcp_wantoptions[0].neg_ssnhf, "Use short sequence numbers in multilink headers", OPT_PRIO | 1, &lcp_allowoptions[0].neg_ssnhf }, { "nompshortseq", o_bool, &lcp_wantoptions[0].neg_ssnhf, "Don't use short sequence numbers in multilink headers", OPT_PRIOSUB | OPT_A2CLR, &lcp_allowoptions[0].neg_ssnhf }, { "endpoint", o_special, (void *) setendpoint, "Endpoint discriminator for multilink", OPT_PRIO | OPT_A2PRINTER, (void *) printendpoint },#endif /* HAVE_MULTILINK */ { "noendpoint", o_bool, &noendpoint, "Don't send or accept multilink endpoint discriminator", 1 }, {NULL}};/* global vars */fsm lcp_fsm[NUM_PPP]; /* LCP fsm structure (global)*/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 */static int lcp_echos_pending = 0; /* Number of outstanding echo msgs */static int lcp_echo_number = 0; /* ID number of next echo frame */static int lcp_echo_timer_running = 0; /* set if a timer is running */static u_char nak_buffer[PPP_MRU]; /* where we construct a nak packet *//* * Callbacks for fsm code. (CI = Configuration Information) */static void lcp_resetci __P((fsm *)); /* Reset our CI */static int lcp_cilen __P((fsm *)); /* Return length of our CI */static void lcp_addci __P((fsm *, u_char *, int *)); /* Add our CI to pkt */static int lcp_ackci __P((fsm *, u_char *, int)); /* Peer ack'd our CI */static int lcp_nakci __P((fsm *, u_char *, int)); /* Peer nak'd our CI */static int lcp_rejci __P((fsm *, u_char *, int)); /* Peer rej'd our CI */static int lcp_reqci __P((fsm *, u_char *, int *, int)); /* Rcv peer CI */static void lcp_up __P((fsm *)); /* We're UP */static void lcp_down __P((fsm *)); /* We're DOWN */static void lcp_starting __P((fsm *)); /* We need lower layer up */static void lcp_finished __P((fsm *)); /* We need lower layer down */static int lcp_extcode __P((fsm *, int, int, u_char *, int));static void lcp_rprotrej __P((fsm *, u_char *, int));/* * routines to send LCP echos to peer */static void lcp_echo_lowerup __P((int));static void lcp_echo_lowerdown __P((int));static void LcpEchoTimeout __P((void *));static void lcp_received_echo_reply __P((fsm *, int, u_char *, int));static void LcpSendEchoRequest __P((fsm *));static void LcpLinkFailure __P((fsm *));static void LcpEchoCheck __P((fsm *));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 */};/* * Protocol entry points. * Some of these are called directly. */static void lcp_init __P((int));static void lcp_input __P((int, u_char *, int));static void lcp_protrej __P((int));static int lcp_printpkt __P((u_char *, int, void (*) __P((void *, char *, ...)), void *));struct protent lcp_protent = { PPP_LCP, lcp_init, lcp_input, lcp_protrej, lcp_lowerup, lcp_lowerdown, lcp_open, lcp_close, lcp_printpkt, NULL, 1, "LCP", NULL, lcp_option_list, NULL, NULL, NULL};int lcp_loopbackfail = DEFLOOPBACKFAIL;/* * Length of each type of configuration option (in octets) */#define CILEN_VOID 2#define CILEN_CHAR 3#define CILEN_SHORT 4 /* CILEN_VOID + 2 */#define CILEN_CHAP 5 /* CILEN_VOID + 2 + 1 */#define CILEN_LONG 6 /* CILEN_VOID + 4 */#define CILEN_LQR 8 /* CILEN_VOID + 2 + 4 */#define CILEN_CBCP 3#define CODENAME(x) ((x) == CONFACK ? "ACK" : \ (x) == CONFNAK ? "NAK" : "REJ")/* * noopt - Disable all options (why?). */static intnoopt(argv) char **argv;{ BZERO((char *) &lcp_wantoptions[0], sizeof (struct lcp_options)); BZERO((char *) &lcp_allowoptions[0], sizeof (struct lcp_options)); return (1);}#ifdef HAVE_MULTILINKstatic intsetendpoint(argv) char **argv;{ if (str_to_epdisc(&lcp_wantoptions[0].endpoint, *argv)) { lcp_wantoptions[0].neg_endpoint = 1; return 1; } option_error("Can't parse '%s' as an endpoint discriminator", *argv); return 0;}static voidprintendpoint(opt, printer, arg) option_t *opt; void (*printer) __P((void *, char *, ...)); void *arg;{ printer(arg, "%s", epdisc_to_str(&lcp_wantoptions[0].endpoint));}#endif /* HAVE_MULTILINK *//* * lcp_init - Initialize LCP. */static voidlcp_init(unit) 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); BZERO(wo, sizeof(*wo)); wo->neg_mru = 1; wo->mru = DEFMRU; wo->neg_asyncmap = 1; wo->chap_mdtype = CHAP_DIGEST_MD5; wo->neg_magicnumber = 1; wo->neg_pcompression = 1; wo->neg_accompression = 1; BZERO(ao, sizeof(*ao)); ao->neg_mru = 1; ao->mru = MAXMRU; ao->neg_asyncmap = 1; ao->neg_chap = 1; ao->chap_mdtype = CHAP_DIGEST_MD5; ao->neg_upap = 1; ao->neg_magicnumber = 1; ao->neg_pcompression = 1; ao->neg_accompression = 1;#ifdef CBCP_SUPPORT ao->neg_cbcp = 1;#endif ao->neg_endpoint = 1;}/* * lcp_open - LCP is allowed to come up. */voidlcp_open(unit) int unit;{ fsm *f = &lcp_fsm[unit]; lcp_options *wo = &lcp_wantoptions[unit]; f->flags &= ~(OPT_PASSIVE | OPT_SILENT); if (wo->passive) f->flags |= OPT_PASSIVE; if (wo->silent) f->flags |= OPT_SILENT; fsm_open(f);}/* * lcp_close - Take LCP down. */voidlcp_close(unit, reason) int unit; char *reason;{ fsm *f = &lcp_fsm[unit]; if (phase != PHASE_DEAD) new_phase(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 a * 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. */voidlcp_lowerup(unit) int unit;{ lcp_options *wo = &lcp_wantoptions[unit]; fsm *f = &lcp_fsm[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_send_config(unit, PPP_MRU, 0xffffffff, 0, 0); ppp_recv_config(unit, PPP_MRU, (lax_recv? 0: 0xffffffff), wo->neg_pcompression, wo->neg_accompression); peer_mru[unit] = PPP_MRU; if (listen_time != 0) { f->flags |= DELAYED_UP; timeout(lcp_delayed_up, f, 0, listen_time * 1000); } else fsm_lowerup(f);}/* * lcp_lowerdown - The lower layer is down. */voidlcp_lowerdown(unit) int unit;{ fsm *f = &lcp_fsm[unit]; if (f->flags & DELAYED_UP) f->flags &= ~DELAYED_UP; else fsm_lowerdown(&lcp_fsm[unit]);}/* * lcp_delayed_up - Bring the lower layer up now. */static voidlcp_delayed_up(arg) void *arg;{ fsm *f = arg; if (f->flags & DELAYED_UP) { f->flags &= ~DELAYED_UP; fsm_lowerup(f); }}/* * lcp_input - Input LCP packet. */static voidlcp_input(unit, p, len) int unit; u_char *p; int len;{ fsm *f = &lcp_fsm[unit]; if (f->flags & DELAYED_UP) { f->flags &= ~DELAYED_UP; fsm_lowerup(f); } fsm_input(f, p, len);}/* * lcp_extcode - Handle a LCP-specific code. */static intlcp_extcode(f, code, id, inp, len) fsm *f; int code, 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; 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 voidlcp_rprotrej(f, inp, len) fsm *f; u_char *inp; int len;{ int i; struct protent *protp; u_short prot; if (len < 2) { LCPDEBUG(("lcp_rprotrej: Rcvd short Protocol-Reject packet!")); return; } GETSHORT(prot, inp); /* * Protocol-Reject packets received in any state other than the LCP * OPENED state SHOULD be silently discarded. */ if( f->state != OPENED ){ LCPDEBUG(("Protocol-Reject discarded: LCP in state %d", f->state)); return; } /* * Upcall the proper Protocol-Reject routine. */ for (i = 0; (protp = protocols[i]) != NULL; ++i) if (protp->protocol == prot && protp->enabled_flag) { (*protp->protrej)(f->unit); return; } warn("Protocol-Reject for unsupported protocol 0x%x", prot);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -