SAMV71 Xplained Ultra Software Package 1.3

lcp.c

00001 /*****************************************************************************
00002 * lcp.c - Network Link Control Protocol program file.
00003 *
00004 * Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
00005 * portions Copyright (c) 1997 by Global Election Systems Inc.
00006 *
00007 * The authors hereby grant permission to use, copy, modify, distribute,
00008 * and license this software and its documentation for any purpose, provided
00009 * that existing copyright notices are retained in all copies and that this
00010 * notice and the following disclaimer are included verbatim in any 
00011 * distributions. No written agreement, license, or royalty fee is required
00012 * for any of the authorized uses.
00013 *
00014 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
00015 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00016 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
00017 * IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00018 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00019 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00020 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00021 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00022 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00023 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00024 *
00025 ******************************************************************************
00026 * REVISION HISTORY
00027 *
00028 * 03-01-01 Marc Boucher <marc@mbsi.ca>
00029 *   Ported to lwIP.
00030 * 97-12-01 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
00031 *   Original.
00032 *****************************************************************************/
00033 
00034 /*
00035  * lcp.c - PPP Link Control Protocol.
00036  *
00037  * Copyright (c) 1989 Carnegie Mellon University.
00038  * All rights reserved.
00039  *
00040  * Redistribution and use in source and binary forms are permitted
00041  * provided that the above copyright notice and this paragraph are
00042  * duplicated in all such forms and that any documentation,
00043  * advertising materials, and other materials related to such
00044  * distribution and use acknowledge that the software was developed
00045  * by Carnegie Mellon University.  The name of the
00046  * University may not be used to endorse or promote products derived
00047  * from this software without specific prior written permission.
00048  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
00049  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
00050  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00051  */
00052  
00053 
00054 #include "lwip/opt.h"
00055 
00056 #if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */
00057 
00058 #include "ppp.h"
00059 #include "pppdebug.h"
00060 
00061 #include "fsm.h"
00062 #include "chap.h"
00063 #include "magic.h"
00064 #include "auth.h"
00065 #include "lcp.h"
00066 
00067 #include <string.h>
00068 
00069 #if PPPOE_SUPPORT
00070 #include "netif/ppp_oe.h"
00071 #else
00072 #define PPPOE_MAXMTU PPP_MAXMRU
00073 #endif
00074 
00075 
00076 /*************************/
00077 /*** LOCAL DEFINITIONS ***/
00078 /*************************/
00079 /*
00080  * Length of each type of configuration option (in octets)
00081  */
00082 #define CILEN_VOID  2
00083 #define CILEN_CHAR  3
00084 #define CILEN_SHORT 4 /* CILEN_VOID + sizeof(short) */
00085 #define CILEN_CHAP  5 /* CILEN_VOID + sizeof(short) + 1 */
00086 #define CILEN_LONG  6 /* CILEN_VOID + sizeof(long) */
00087 #define CILEN_LQR   8 /* CILEN_VOID + sizeof(short) + sizeof(long) */
00088 #define CILEN_CBCP  3
00089 
00090 
00091 /***********************************/
00092 /*** LOCAL FUNCTION DECLARATIONS ***/
00093 /***********************************/
00094 /*
00095  * Callbacks for fsm code.  (CI = Configuration Information)
00096  */
00097 static void lcp_resetci (fsm*);                   /* Reset our CI */
00098 static int  lcp_cilen (fsm*);                     /* Return length of our CI */
00099 static void lcp_addci (fsm*, u_char*, int*);      /* Add our CI to pkt */
00100 static int  lcp_ackci (fsm*, u_char*, int);       /* Peer ack'd our CI */
00101 static int  lcp_nakci (fsm*, u_char*, int);       /* Peer nak'd our CI */
00102 static int  lcp_rejci (fsm*, u_char*, int);       /* Peer rej'd our CI */
00103 static int  lcp_reqci (fsm*, u_char*, int*, int); /* Rcv peer CI */
00104 static void lcp_up (fsm*);                        /* We're UP */
00105 static void lcp_down (fsm*);                      /* We're DOWN */
00106 static void lcp_starting (fsm*);                  /* We need lower layer up */
00107 static void lcp_finished (fsm*);                  /* We need lower layer down */
00108 static int  lcp_extcode (fsm*, int, u_char, u_char*, int);
00109 
00110 static void lcp_rprotrej (fsm*, u_char*, int);
00111 
00112 /*
00113  * routines to send LCP echos to peer
00114  */
00115 static void lcp_echo_lowerup (int);
00116 static void lcp_echo_lowerdown (int);
00117 static void LcpEchoTimeout (void*);
00118 static void lcp_received_echo_reply (fsm*, int, u_char*, int);
00119 static void LcpSendEchoRequest (fsm*);
00120 static void LcpLinkFailure (fsm*);
00121 static void LcpEchoCheck (fsm*);
00122 
00123 /*
00124  * Protocol entry points.
00125  * Some of these are called directly.
00126  */
00127 static void lcp_input (int, u_char *, int);
00128 static void lcp_protrej (int);
00129 
00130 #define CODENAME(x) ((x) == CONFACK ? "ACK" : (x) == CONFNAK ? "NAK" : "REJ")
00131 
00132 
00133 /******************************/
00134 /*** PUBLIC DATA STRUCTURES ***/
00135 /******************************/
00136 /* global vars */
00137 LinkPhase lcp_phase[NUM_PPP];          /* Phase of link session (RFC 1661) */
00138 lcp_options lcp_wantoptions[NUM_PPP];  /* Options that we want to request */
00139 lcp_options lcp_gotoptions[NUM_PPP];   /* Options that peer ack'd */
00140 lcp_options lcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */
00141 lcp_options lcp_hisoptions[NUM_PPP];   /* Options that we ack'd */
00142 ext_accm xmit_accm[NUM_PPP];           /* extended transmit ACCM */
00143 
00144 
00145 
00146 /*****************************/
00147 /*** LOCAL DATA STRUCTURES ***/
00148 /*****************************/
00149 static fsm lcp_fsm[NUM_PPP];                            /* LCP fsm structure (global)*/
00150 static u_int lcp_echo_interval      = LCP_ECHOINTERVAL; /* Interval between LCP echo-requests */
00151 static u_int lcp_echo_fails         = LCP_MAXECHOFAILS; /* Tolerance to unanswered echo-requests */
00152 static u32_t lcp_echos_pending      = 0;                /* Number of outstanding echo msgs */
00153 static u32_t lcp_echo_number        = 0;                /* ID number of next echo frame */
00154 static u32_t lcp_echo_timer_running = 0;                /* TRUE if a timer is running */
00155 
00156 static u_char nak_buffer[PPP_MRU]; /* where we construct a nak packet */
00157 
00158 static fsm_callbacks lcp_callbacks = { /* LCP callback routines */
00159   lcp_resetci,  /* Reset our Configuration Information */
00160   lcp_cilen,    /* Length of our Configuration Information */
00161   lcp_addci,    /* Add our Configuration Information */
00162   lcp_ackci,    /* ACK our Configuration Information */
00163   lcp_nakci,    /* NAK our Configuration Information */
00164   lcp_rejci,    /* Reject our Configuration Information */
00165   lcp_reqci,    /* Request peer's Configuration Information */
00166   lcp_up,       /* Called when fsm reaches LS_OPENED state */
00167   lcp_down,     /* Called when fsm leaves LS_OPENED state */
00168   lcp_starting, /* Called when we want the lower layer up */
00169   lcp_finished, /* Called when we want the lower layer down */
00170   NULL,         /* Called when Protocol-Reject received */
00171   NULL,         /* Retransmission is necessary */
00172   lcp_extcode,  /* Called to handle LCP-specific codes */
00173   "LCP"         /* String name of protocol */
00174 };
00175 
00176 struct protent lcp_protent = {
00177     PPP_LCP,
00178     lcp_init,
00179     lcp_input,
00180     lcp_protrej,
00181     lcp_lowerup,
00182     lcp_lowerdown,
00183     lcp_open,
00184     lcp_close,
00185 #if 0
00186     lcp_printpkt,
00187     NULL,
00188 #endif
00189     1,
00190     "LCP",
00191 #if 0
00192     NULL,
00193     NULL,
00194     NULL
00195 #endif
00196 };
00197 
00198 int lcp_loopbackfail = DEFLOOPBACKFAIL;
00199 
00200 
00201 
00202 /***********************************/
00203 /*** PUBLIC FUNCTION DEFINITIONS ***/
00204 /***********************************/
00205 /*
00206  * lcp_init - Initialize LCP.
00207  */
00208 void
00209 lcp_init(int unit)
00210 {
00211   fsm         *f  = &lcp_fsm[unit];
00212   lcp_options *wo = &lcp_wantoptions[unit];
00213   lcp_options *ao = &lcp_allowoptions[unit];
00214   
00215   f->unit      = unit;
00216   f->protocol  = PPP_LCP;
00217   f->callbacks = &lcp_callbacks;
00218   
00219   fsm_init(f);
00220   
00221   wo->passive           = 0;
00222   wo->silent            = 0;
00223   wo->restart           = 0;               /* Set to 1 in kernels or multi-line implementations */
00224   wo->neg_mru           = 1;
00225   wo->mru               = PPP_DEFMRU;
00226   wo->neg_asyncmap      = 1;
00227   wo->asyncmap          = 0x00000000l;     /* Assume don't need to escape any ctl chars. */
00228   wo->neg_chap          = 0;               /* Set to 1 on server */
00229   wo->neg_upap          = 0;               /* Set to 1 on server */
00230   wo->chap_mdtype       = CHAP_DIGEST_MD5;
00231   wo->neg_magicnumber   = 1;
00232   wo->neg_pcompression  = 1;
00233   wo->neg_accompression = 1;
00234   wo->neg_lqr           = 0;               /* no LQR implementation yet */
00235   wo->neg_cbcp          = 0;
00236   
00237   ao->neg_mru           = 1;
00238   ao->mru               = PPP_MAXMRU;
00239   ao->neg_asyncmap      = 1;
00240   ao->asyncmap          = 0x00000000l;     /* Assume don't need to escape any ctl chars. */
00241   ao->neg_chap          = (CHAP_SUPPORT != 0);
00242   ao->chap_mdtype       = CHAP_DIGEST_MD5;
00243   ao->neg_upap          = (PAP_SUPPORT != 0);
00244   ao->neg_magicnumber   = 1;
00245   ao->neg_pcompression  = 1;
00246   ao->neg_accompression = 1;
00247   ao->neg_lqr           = 0;               /* no LQR implementation yet */
00248   ao->neg_cbcp          = (CBCP_SUPPORT != 0);
00249 
00250   /* 
00251    * Set transmit escape for the flag and escape characters plus anything
00252    * set for the allowable options.
00253    */
00254   memset(xmit_accm[unit], 0, sizeof(xmit_accm[0]));
00255   xmit_accm[unit][15] = 0x60;
00256   xmit_accm[unit][0]  = (u_char)((ao->asyncmap        & 0xFF));
00257   xmit_accm[unit][1]  = (u_char)((ao->asyncmap >> 8)  & 0xFF);
00258   xmit_accm[unit][2]  = (u_char)((ao->asyncmap >> 16) & 0xFF);
00259   xmit_accm[unit][3]  = (u_char)((ao->asyncmap >> 24) & 0xFF);
00260   LCPDEBUG((LOG_INFO, "lcp_init: xmit_accm=%X %X %X %X\n",
00261         xmit_accm[unit][0],
00262         xmit_accm[unit][1],
00263         xmit_accm[unit][2],
00264         xmit_accm[unit][3]));
00265   
00266   lcp_phase[unit] = PHASE_INITIALIZE;
00267 }
00268 
00269 
00270 /*
00271  * lcp_open - LCP is allowed to come up.
00272  */
00273 void
00274 lcp_open(int unit)
00275 {
00276   fsm         *f  = &lcp_fsm[unit];
00277   lcp_options *wo = &lcp_wantoptions[unit];
00278 
00279   f->flags = 0;
00280   if (wo->passive) {
00281     f->flags |= OPT_PASSIVE;
00282   }
00283   if (wo->silent) {
00284     f->flags |= OPT_SILENT;
00285   }
00286   fsm_open(f);
00287 
00288   lcp_phase[unit] = PHASE_ESTABLISH;
00289 }
00290 
00291 
00292 /*
00293  * lcp_close - Take LCP down.
00294  */
00295 void
00296 lcp_close(int unit, char *reason)
00297 {
00298   fsm *f = &lcp_fsm[unit];
00299 
00300   if (lcp_phase[unit] != PHASE_DEAD) {
00301     lcp_phase[unit] = PHASE_TERMINATE;
00302   }
00303   if (f->state == LS_STOPPED && f->flags & (OPT_PASSIVE|OPT_SILENT)) {
00304     /*
00305      * This action is not strictly according to the FSM in RFC1548,
00306      * but it does mean that the program terminates if you do an
00307      * lcp_close() in passive/silent mode when a connection hasn't
00308      * been established.
00309      */
00310     f->state = LS_CLOSED;
00311     lcp_finished(f);
00312   } else {
00313     fsm_close(&lcp_fsm[unit], reason);
00314   }
00315 }
00316 
00317 
00318 /*
00319  * lcp_lowerup - The lower layer is up.
00320  */
00321 void
00322 lcp_lowerup(int unit)
00323 {
00324   lcp_options *wo = &lcp_wantoptions[unit];
00325 
00326   /*
00327    * Don't use A/C or protocol compression on transmission,
00328    * but accept A/C and protocol compressed packets
00329    * if we are going to ask for A/C and protocol compression.
00330    */
00331   ppp_set_xaccm(unit, &xmit_accm[unit]);
00332   ppp_send_config(unit, PPP_MRU, 0xffffffffl, 0, 0);
00333   ppp_recv_config(unit, PPP_MRU, 0x00000000l,
00334   wo->neg_pcompression, wo->neg_accompression);
00335   peer_mru[unit] = PPP_MRU;
00336   lcp_allowoptions[unit].asyncmap = (u_long)xmit_accm[unit][0]
00337                                  | ((u_long)xmit_accm[unit][1] << 8)
00338                                  | ((u_long)xmit_accm[unit][2] << 16)
00339                                  | ((u_long)xmit_accm[unit][3] << 24);
00340   LCPDEBUG((LOG_INFO, "lcp_lowerup: asyncmap=%X %X %X %X\n",
00341             xmit_accm[unit][3],
00342             xmit_accm[unit][2],
00343             xmit_accm[unit][1],
00344             xmit_accm[unit][0]));
00345 
00346   fsm_lowerup(&lcp_fsm[unit]);
00347 }
00348 
00349 
00350 /*
00351  * lcp_lowerdown - The lower layer is down.
00352  */
00353 void
00354 lcp_lowerdown(int unit)
00355 {
00356   fsm_lowerdown(&lcp_fsm[unit]);
00357 }
00358 
00359 /*
00360  * lcp_sprotrej - Send a Protocol-Reject for some protocol.
00361  */
00362 void
00363 lcp_sprotrej(int unit, u_char *p, int len)
00364 {
00365   /*
00366    * Send back the protocol and the information field of the
00367    * rejected packet.  We only get here if LCP is in the LS_OPENED state.
00368    */
00369 
00370   fsm_sdata(&lcp_fsm[unit], PROTREJ, ++lcp_fsm[unit].id, p, len);
00371 }
00372 
00373 
00374 
00375 /**********************************/
00376 /*** LOCAL FUNCTION DEFINITIONS ***/
00377 /**********************************/
00378 /*
00379  * lcp_input - Input LCP packet.
00380  */
00381 static void
00382 lcp_input(int unit, u_char *p, int len)
00383 {
00384   fsm *f = &lcp_fsm[unit];
00385 
00386   fsm_input(f, p, len);
00387 }
00388 
00389 
00390 /*
00391  * lcp_extcode - Handle a LCP-specific code.
00392  */
00393 static int
00394 lcp_extcode(fsm *f, int code, u_char id, u_char *inp, int len)
00395 {
00396   u_char *magp;
00397 
00398   switch( code ){
00399     case PROTREJ:
00400       lcp_rprotrej(f, inp, len);
00401       break;
00402   
00403     case ECHOREQ:
00404       if (f->state != LS_OPENED) {
00405         break;
00406       }
00407       LCPDEBUG((LOG_INFO, "lcp: Echo-Request, Rcvd id %d\n", id));
00408       magp = inp;
00409       PUTLONG(lcp_gotoptions[f->unit].magicnumber, magp);
00410       fsm_sdata(f, ECHOREP, id, inp, len);
00411       break;
00412 
00413     case ECHOREP:
00414       lcp_received_echo_reply(f, id, inp, len);
00415       break;
00416     
00417     case DISCREQ:
00418       break;
00419     
00420     default:
00421       return 0;
00422   }
00423   return 1;
00424 }
00425 
00426 
00427 /*
00428  * lcp_rprotrej - Receive an Protocol-Reject.
00429  *
00430  * Figure out which protocol is rejected and inform it.
00431  */
00432 static void
00433 lcp_rprotrej(fsm *f, u_char *inp, int len)
00434 {
00435   int i;
00436   struct protent *protp;
00437   u_short prot;
00438 
00439   if (len < sizeof (u_short)) {
00440     LCPDEBUG((LOG_INFO, "lcp_rprotrej: Rcvd short Protocol-Reject packet!\n"));
00441     return;
00442   }
00443 
00444   GETSHORT(prot, inp);
00445 
00446   LCPDEBUG((LOG_INFO, "lcp_rprotrej: Rcvd Protocol-Reject packet for %x!\n", prot));
00447 
00448   /*
00449    * Protocol-Reject packets received in any state other than the LCP
00450    * LS_OPENED state SHOULD be silently discarded.
00451    */
00452   if( f->state != LS_OPENED ) {
00453     LCPDEBUG((LOG_INFO, "Protocol-Reject discarded: LCP in state %d\n", f->state));
00454     return;
00455   }
00456 
00457   /*
00458    * Upcall the proper Protocol-Reject routine.
00459    */
00460   for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) {
00461     if (protp->protocol == prot && protp->enabled_flag) {
00462       (*protp->protrej)(f->unit);
00463       return;
00464     }
00465   }
00466 
00467   LCPDEBUG((LOG_WARNING, "Protocol-Reject for unsupported protocol 0x%x\n", prot));
00468 }
00469 
00470 
00471 /*
00472  * lcp_protrej - A Protocol-Reject was received.
00473  */
00474 static void
00475 lcp_protrej(int unit)
00476 {
00477   LWIP_UNUSED_ARG(unit);
00478   /*
00479    * Can't reject LCP!
00480    */
00481   LCPDEBUG((LOG_WARNING, "lcp_protrej: Received Protocol-Reject for LCP!\n"));
00482   fsm_protreject(&lcp_fsm[unit]);
00483 }
00484 
00485 
00486 /*
00487  * lcp_resetci - Reset our CI.
00488  */
00489 static void
00490 lcp_resetci(fsm *f)
00491 {
00492   lcp_wantoptions[f->unit].magicnumber = magic();
00493   lcp_wantoptions[f->unit].numloops = 0;
00494   lcp_gotoptions[f->unit] = lcp_wantoptions[f->unit];
00495   peer_mru[f->unit] = PPP_MRU;
00496   auth_reset(f->unit);
00497 }
00498 
00499 
00500 /*
00501  * lcp_cilen - Return length of our CI.
00502  */
00503 static int lcp_cilen(fsm *f)
00504 {
00505   lcp_options *go = &lcp_gotoptions[f->unit];
00506 
00507 #define LENCIVOID(neg)  ((neg) ? CILEN_VOID : 0)
00508 #define LENCICHAP(neg)  ((neg) ? CILEN_CHAP : 0)
00509 #define LENCISHORT(neg) ((neg) ? CILEN_SHORT : 0)
00510 #define LENCILONG(neg)  ((neg) ? CILEN_LONG : 0)
00511 #define LENCILQR(neg)   ((neg) ? CILEN_LQR: 0)
00512 #define LENCICBCP(neg)  ((neg) ? CILEN_CBCP: 0)
00513   /*
00514    * NB: we only ask for one of CHAP and UPAP, even if we will
00515    * accept either.
00516    */
00517   return (LENCISHORT(go->neg_mru && go->mru != PPP_DEFMRU) +
00518           LENCILONG(go->neg_asyncmap && go->asyncmap != 0xFFFFFFFFl) +
00519           LENCICHAP(go->neg_chap) +
00520           LENCISHORT(!go->neg_chap && go->neg_upap) +
00521           LENCILQR(go->neg_lqr) +
00522           LENCICBCP(go->neg_cbcp) +
00523           LENCILONG(go->neg_magicnumber) +
00524           LENCIVOID(go->neg_pcompression) +
00525           LENCIVOID(go->neg_accompression));
00526 }
00527 
00528 
00529 /*
00530  * lcp_addci - Add our desired CIs to a packet.
00531  */
00532 static void
00533 lcp_addci(fsm *f, u_char *ucp, int *lenp)
00534 {
00535   lcp_options *go = &lcp_gotoptions[f->unit];
00536   u_char *start_ucp = ucp;
00537 
00538 #define ADDCIVOID(opt, neg) \
00539   if (neg) { \
00540     LCPDEBUG((LOG_INFO, "lcp_addci: opt=%d\n", opt)); \
00541     PUTCHAR(opt, ucp); \
00542     PUTCHAR(CILEN_VOID, ucp); \
00543   }
00544 #define ADDCISHORT(opt, neg, val) \
00545   if (neg) { \
00546     LCPDEBUG((LOG_INFO, "lcp_addci: INT opt=%d %X\n", opt, val)); \
00547     PUTCHAR(opt, ucp); \
00548     PUTCHAR(CILEN_SHORT, ucp); \
00549     PUTSHORT(val, ucp); \
00550   }
00551 #define ADDCICHAP(opt, neg, val, digest) \
00552   if (neg) { \
00553     LCPDEBUG((LOG_INFO, "lcp_addci: CHAP opt=%d %X\n", opt, val)); \
00554     PUTCHAR(opt, ucp); \
00555     PUTCHAR(CILEN_CHAP, ucp); \
00556     PUTSHORT(val, ucp); \
00557     PUTCHAR(digest, ucp); \
00558   }
00559 #define ADDCILONG(opt, neg, val) \
00560   if (neg) { \
00561     LCPDEBUG((LOG_INFO, "lcp_addci: L opt=%d %lX\n", opt, val)); \
00562     PUTCHAR(opt, ucp); \
00563     PUTCHAR(CILEN_LONG, ucp); \
00564     PUTLONG(val, ucp); \
00565   }
00566 #define ADDCILQR(opt, neg, val) \
00567   if (neg) { \
00568     LCPDEBUG((LOG_INFO, "lcp_addci: LQR opt=%d %lX\n", opt, val)); \
00569     PUTCHAR(opt, ucp); \
00570     PUTCHAR(CILEN_LQR, ucp); \
00571     PUTSHORT(PPP_LQR, ucp); \
00572     PUTLONG(val, ucp); \
00573   }
00574 #define ADDCICHAR(opt, neg, val) \
00575   if (neg) { \
00576     LCPDEBUG((LOG_INFO, "lcp_addci: CHAR opt=%d %X '%z'\n", opt, val, val)); \
00577     PUTCHAR(opt, ucp); \
00578     PUTCHAR(CILEN_CHAR, ucp); \
00579     PUTCHAR(val, ucp); \
00580   }
00581 
00582   ADDCISHORT(CI_MRU, go->neg_mru && go->mru != PPP_DEFMRU, go->mru);
00583   ADDCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFFl, go->asyncmap);
00584   ADDCICHAP(CI_AUTHTYPE, go->neg_chap, PPP_CHAP, go->chap_mdtype);
00585   ADDCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP);
00586   ADDCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period);
00587   ADDCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT);
00588   ADDCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber);
00589   ADDCIVOID(CI_PCOMPRESSION, go->neg_pcompression);
00590   ADDCIVOID(CI_ACCOMPRESSION, go->neg_accompression);
00591 
00592   if (ucp - start_ucp != *lenp) {
00593     /* this should never happen, because peer_mtu should be 1500 */
00594     LCPDEBUG((LOG_ERR, "Bug in lcp_addci: wrong length\n"));
00595   }
00596 }
00597 
00598 
00599 /*
00600  * lcp_ackci - Ack our CIs.
00601  * This should not modify any state if the Ack is bad.
00602  *
00603  * Returns:
00604  *  0 - Ack was bad.
00605  *  1 - Ack was good.
00606  */
00607 static int
00608 lcp_ackci(fsm *f, u_char *p, int len)
00609 {
00610   lcp_options *go = &lcp_gotoptions[f->unit];
00611   u_char cilen, citype, cichar;
00612   u_short cishort;
00613   u32_t cilong;
00614 
00615   /*
00616    * CIs must be in exactly the same order that we sent.
00617    * Check packet length and CI length at each step.
00618    * If we find any deviations, then this packet is bad.
00619    */
00620 #define ACKCIVOID(opt, neg) \
00621   if (neg) { \
00622     if ((len -= CILEN_VOID) < 0) \
00623       goto bad; \
00624     GETCHAR(citype, p); \
00625     GETCHAR(cilen, p); \
00626     if (cilen != CILEN_VOID || citype != opt) \
00627       goto bad; \
00628   }
00629 #define ACKCISHORT(opt, neg, val) \
00630   if (neg) { \
00631     if ((len -= CILEN_SHORT) < 0) \
00632       goto bad; \
00633     GETCHAR(citype, p); \
00634     GETCHAR(cilen, p); \
00635     if (cilen != CILEN_SHORT || citype != opt) \
00636       goto bad; \
00637     GETSHORT(cishort, p); \
00638     if (cishort != val) \
00639       goto bad; \
00640   }
00641 #define ACKCICHAR(opt, neg, val) \
00642   if (neg) { \
00643     if ((len -= CILEN_CHAR) < 0) \
00644       goto bad; \
00645     GETCHAR(citype, p); \
00646     GETCHAR(cilen, p); \
00647     if (cilen != CILEN_CHAR || citype != opt) \
00648       goto bad; \
00649     GETCHAR(cichar, p); \
00650     if (cichar != val) \
00651       goto bad; \
00652   }
00653 #define ACKCICHAP(opt, neg, val, digest) \
00654   if (neg) { \
00655     if ((len -= CILEN_CHAP) < 0) \
00656       goto bad; \
00657     GETCHAR(citype, p); \
00658     GETCHAR(cilen, p); \
00659     if (cilen != CILEN_CHAP || citype != opt) \
00660       goto bad; \
00661     GETSHORT(cishort, p); \
00662     if (cishort != val) \
00663       goto bad; \
00664     GETCHAR(cichar, p); \
00665     if (cichar != digest) \
00666       goto bad; \
00667   }
00668 #define ACKCILONG(opt, neg, val) \
00669   if (neg) { \
00670     if ((len -= CILEN_LONG) < 0) \
00671       goto bad; \
00672     GETCHAR(citype, p); \
00673     GETCHAR(cilen, p); \
00674     if (cilen != CILEN_LONG ||  citype != opt) \
00675       goto bad; \
00676     GETLONG(cilong, p); \
00677     if (cilong != val) \
00678       goto bad; \
00679   }
00680 #define ACKCILQR(opt, neg, val) \
00681   if (neg) { \
00682     if ((len -= CILEN_LQR) < 0) \
00683       goto bad; \
00684     GETCHAR(citype, p); \
00685     GETCHAR(cilen, p); \
00686     if (cilen != CILEN_LQR || citype != opt) \
00687       goto bad; \
00688     GETSHORT(cishort, p); \
00689     if (cishort != PPP_LQR) \
00690       goto bad; \
00691     GETLONG(cilong, p); \
00692     if (cilong != val) \
00693       goto bad; \
00694   }
00695 
00696   ACKCISHORT(CI_MRU, go->neg_mru && go->mru != PPP_DEFMRU, go->mru);
00697   ACKCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFFl, go->asyncmap);
00698   ACKCICHAP(CI_AUTHTYPE, go->neg_chap, PPP_CHAP, go->chap_mdtype);
00699   ACKCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP);
00700   ACKCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period);
00701   ACKCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT);
00702   ACKCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber);
00703   ACKCIVOID(CI_PCOMPRESSION, go->neg_pcompression);
00704   ACKCIVOID(CI_ACCOMPRESSION, go->neg_accompression);
00705 
00706   /*
00707    * If there are any remaining CIs, then this packet is bad.
00708    */
00709   if (len != 0) {
00710     goto bad;
00711   }
00712   LCPDEBUG((LOG_INFO, "lcp_acki: Ack\n"));
00713   return (1);
00714 bad:
00715   LCPDEBUG((LOG_WARNING, "lcp_acki: received bad Ack!\n"));
00716   return (0);
00717 }
00718 
00719 
00720 /*
00721  * lcp_nakci - Peer has sent a NAK for some of our CIs.
00722  * This should not modify any state if the Nak is bad
00723  * or if LCP is in the LS_OPENED state.
00724  *
00725  * Returns:
00726  *  0 - Nak was bad.
00727  *  1 - Nak was good.
00728  */
00729 static int
00730 lcp_nakci(fsm *f, u_char *p, int len)
00731 {
00732   lcp_options *go = &lcp_gotoptions[f->unit];
00733   lcp_options *wo = &lcp_wantoptions[f->unit];
00734   u_char citype, cichar, *next;
00735   u_short cishort;
00736   u32_t cilong;
00737   lcp_options no;     /* options we've seen Naks for */
00738   lcp_options try;    /* options to request next time */
00739   int looped_back = 0;
00740   int cilen;
00741 
00742   BZERO(&no, sizeof(no));
00743   try = *go;
00744 
00745   /*
00746    * Any Nak'd CIs must be in exactly the same order that we sent.
00747    * Check packet length and CI length at each step.
00748    * If we find any deviations, then this packet is bad.
00749    */
00750 #define NAKCIVOID(opt, neg, code) \
00751   if (go->neg && \
00752       len >= CILEN_VOID && \
00753       p[1] == CILEN_VOID && \
00754       p[0] == opt) { \
00755     len -= CILEN_VOID; \
00756     INCPTR(CILEN_VOID, p); \
00757     no.neg = 1; \
00758     code \
00759   }
00760 #define NAKCICHAP(opt, neg, code) \
00761   if (go->neg && \
00762       len >= CILEN_CHAP && \
00763       p[1] == CILEN_CHAP && \
00764       p[0] == opt) { \
00765     len -= CILEN_CHAP; \
00766     INCPTR(2, p); \
00767     GETSHORT(cishort, p); \
00768     GETCHAR(cichar, p); \
00769     no.neg = 1; \
00770     code \
00771   }
00772 #define NAKCICHAR(opt, neg, code) \
00773   if (go->neg && \
00774       len >= CILEN_CHAR && \
00775       p[1] == CILEN_CHAR && \
00776       p[0] == opt) { \
00777     len -= CILEN_CHAR; \
00778     INCPTR(2, p); \
00779     GETCHAR(cichar, p); \
00780     no.neg = 1; \
00781     code \
00782   }
00783 #define NAKCISHORT(opt, neg, code) \
00784   if (go->neg && \
00785       len >= CILEN_SHORT && \
00786       p[1] == CILEN_SHORT && \
00787       p[0] == opt) { \
00788     len -= CILEN_SHORT; \
00789     INCPTR(2, p); \
00790     GETSHORT(cishort, p); \
00791     no.neg = 1; \
00792     code \
00793   }
00794 #define NAKCILONG(opt, neg, code) \
00795   if (go->neg && \
00796       len >= CILEN_LONG && \
00797       p[1] == CILEN_LONG && \
00798       p[0] == opt) { \
00799     len -= CILEN_LONG; \
00800     INCPTR(2, p); \
00801     GETLONG(cilong, p); \
00802     no.neg = 1; \
00803     code \
00804   }
00805 #define NAKCILQR(opt, neg, code) \
00806   if (go->neg && \
00807       len >= CILEN_LQR && \
00808       p[1] == CILEN_LQR && \
00809       p[0] == opt) { \
00810     len -= CILEN_LQR; \
00811     INCPTR(2, p); \
00812     GETSHORT(cishort, p); \
00813     GETLONG(cilong, p); \
00814     no.neg = 1; \
00815     code \
00816   }
00817 
00818   /*
00819    * We don't care if they want to send us smaller packets than
00820    * we want.  Therefore, accept any MRU less than what we asked for,
00821    * but then ignore the new value when setting the MRU in the kernel.
00822    * If they send us a bigger MRU than what we asked, accept it, up to
00823    * the limit of the default MRU we'd get if we didn't negotiate.
00824    */
00825   if (go->neg_mru && go->mru != PPP_DEFMRU) {
00826     NAKCISHORT(CI_MRU, neg_mru,
00827       if (cishort <= wo->mru || cishort < PPP_DEFMRU) {
00828         try.mru = cishort;
00829       }
00830     );
00831   }
00832 
00833   /*
00834    * Add any characters they want to our (receive-side) asyncmap.
00835    */
00836   if (go->neg_asyncmap && go->asyncmap != 0xFFFFFFFFl) {
00837     NAKCILONG(CI_ASYNCMAP, neg_asyncmap,
00838       try.asyncmap = go->asyncmap | cilong;
00839     );
00840   }
00841 
00842   /*
00843    * If they've nak'd our authentication-protocol, check whether
00844    * they are proposing a different protocol, or a different
00845    * hash algorithm for CHAP.
00846    */
00847   if ((go->neg_chap || go->neg_upap)
00848       && len >= CILEN_SHORT
00849       && p[0] == CI_AUTHTYPE && p[1] >= CILEN_SHORT && p[1] <= len) {
00850     cilen = p[1];
00851     len -= cilen;
00852     no.neg_chap = go->neg_chap;
00853     no.neg_upap = go->neg_upap;
00854     INCPTR(2, p);
00855     GETSHORT(cishort, p);
00856     if (cishort == PPP_PAP && cilen == CILEN_SHORT) {
00857       /*
00858        * If we were asking for CHAP, they obviously don't want to do it.
00859        * If we weren't asking for CHAP, then we were asking for PAP,
00860        * in which case this Nak is bad.
00861        */
00862       if (!go->neg_chap) {
00863         goto bad;
00864       }
00865       try.neg_chap = 0;
00866     
00867     } else if (cishort == PPP_CHAP && cilen == CILEN_CHAP) {
00868       GETCHAR(cichar, p);
00869       if (go->neg_chap) {
00870         /*
00871          * We were asking for CHAP/MD5; they must want a different
00872          * algorithm.  If they can't do MD5, we'll have to stop
00873          * asking for CHAP.
00874          */
00875         if (cichar != go->chap_mdtype) {
00876           try.neg_chap = 0;
00877         }
00878       } else {
00879         /*
00880          * Stop asking for PAP if we were asking for it.
00881          */
00882         try.neg_upap = 0;
00883       }
00884     
00885     } else {
00886       /*
00887        * We don't recognize what they're suggesting.
00888        * Stop asking for what we were asking for.
00889        */
00890       if (go->neg_chap) {
00891         try.neg_chap = 0;
00892       } else {
00893         try.neg_upap = 0;
00894       }
00895       p += cilen - CILEN_SHORT;
00896     }
00897   }
00898 
00899   /*
00900    * If they can't cope with our link quality protocol, we'll have
00901    * to stop asking for LQR.  We haven't got any other protocol.
00902    * If they Nak the reporting period, take their value XXX ?
00903    */
00904   NAKCILQR(CI_QUALITY, neg_lqr,
00905     if (cishort != PPP_LQR) {
00906       try.neg_lqr = 0;
00907     } else {
00908       try.lqr_period = cilong;
00909     }
00910   );
00911 
00912   /*
00913    * Only implementing CBCP...not the rest of the callback options
00914    */
00915   NAKCICHAR(CI_CALLBACK, neg_cbcp,
00916     try.neg_cbcp = 0;
00917   );
00918 
00919   /*
00920    * Check for a looped-back line.
00921    */
00922   NAKCILONG(CI_MAGICNUMBER, neg_magicnumber,
00923     try.magicnumber = magic();
00924     looped_back = 1;
00925   );
00926 
00927   /*
00928    * Peer shouldn't send Nak for protocol compression or
00929    * address/control compression requests; they should send
00930    * a Reject instead.  If they send a Nak, treat it as a Reject.
00931    */
00932   NAKCIVOID(CI_PCOMPRESSION, neg_pcompression,
00933     try.neg_pcompression = 0;
00934   );
00935   NAKCIVOID(CI_ACCOMPRESSION, neg_accompression,
00936     try.neg_accompression = 0;
00937   );
00938 
00939   /*
00940    * There may be remaining CIs, if the peer is requesting negotiation
00941    * on an option that we didn't include in our request packet.
00942    * If we see an option that we requested, or one we've already seen
00943    * in this packet, then this packet is bad.
00944    * If we wanted to respond by starting to negotiate on the requested
00945    * option(s), we could, but we don't, because except for the
00946    * authentication type and quality protocol, if we are not negotiating
00947    * an option, it is because we were told not to.
00948    * For the authentication type, the Nak from the peer means
00949    * `let me authenticate myself with you' which is a bit pointless.
00950    * For the quality protocol, the Nak means `ask me to send you quality
00951    * reports', but if we didn't ask for them, we don't want them.
00952    * An option we don't recognize represents the peer asking to
00953    * negotiate some option we don't support, so ignore it.
00954    */
00955   while (len > CILEN_VOID) {
00956     GETCHAR(citype, p);
00957     GETCHAR(cilen, p);
00958     if (cilen < CILEN_VOID || (len -= cilen) < 0) {
00959       goto bad;
00960     }
00961     next = p + cilen - 2;
00962 
00963     switch (citype) {
00964       case CI_MRU:
00965         if ((go->neg_mru && go->mru != PPP_DEFMRU)
00966             || no.neg_mru || cilen != CILEN_SHORT) {
00967           goto bad;
00968         }
00969         GETSHORT(cishort, p);
00970         if (cishort < PPP_DEFMRU) {
00971           try.mru = cishort;
00972         }
00973         break;
00974       case CI_ASYNCMAP:
00975         if ((go->neg_asyncmap && go->asyncmap != 0xFFFFFFFFl)
00976             || no.neg_asyncmap || cilen != CILEN_LONG) {
00977           goto bad;
00978         }
00979         break;
00980       case CI_AUTHTYPE:
00981         if (go->neg_chap || no.neg_chap || go->neg_upap || no.neg_upap) {
00982           goto bad;
00983         }
00984         break;
00985       case CI_MAGICNUMBER:
00986         if (go->neg_magicnumber || no.neg_magicnumber ||
00987             cilen != CILEN_LONG) {
00988           goto bad;
00989         }
00990         break;
00991       case CI_PCOMPRESSION:
00992         if (go->neg_pcompression || no.neg_pcompression
00993             || cilen != CILEN_VOID) {
00994           goto bad;
00995         }
00996         break;
00997       case CI_ACCOMPRESSION:
00998         if (go->neg_accompression || no.neg_accompression
00999             || cilen != CILEN_VOID) {
01000           goto bad;
01001         }
01002         break;
01003       case CI_QUALITY:
01004         if (go->neg_lqr || no.neg_lqr || cilen != CILEN_LQR) {
01005           goto bad;
01006         }
01007         break;
01008     }
01009     p = next;
01010   }
01011 
01012   /* If there is still anything left, this packet is bad. */
01013   if (len != 0) {
01014     goto bad;
01015   }
01016 
01017   /*
01018   * OK, the Nak is good.  Now we can update state.
01019   */
01020   if (f->state != LS_OPENED) {
01021     if (looped_back) {
01022       if (++try.numloops >= lcp_loopbackfail) {
01023         LCPDEBUG((LOG_NOTICE, "Serial line is looped back.\n"));
01024         lcp_close(f->unit, "Loopback detected");
01025       }
01026     } else {
01027       try.numloops = 0;
01028     }
01029     *go = try;
01030   }
01031 
01032   return 1;
01033 
01034 bad:
01035   LCPDEBUG((LOG_WARNING, "lcp_nakci: received bad Nak!\n"));
01036   return 0;
01037 }
01038 
01039 
01040 /*
01041  * lcp_rejci - Peer has Rejected some of our CIs.
01042  * This should not modify any state if the Reject is bad
01043  * or if LCP is in the LS_OPENED state.
01044  *
01045  * Returns:
01046  *  0 - Reject was bad.
01047  *  1 - Reject was good.
01048  */
01049 static int
01050 lcp_rejci(fsm *f, u_char *p, int len)
01051 {
01052   lcp_options *go = &lcp_gotoptions[f->unit];
01053   u_char cichar;
01054   u_short cishort;
01055   u32_t cilong;
01056   lcp_options try; /* options to request next time */
01057 
01058   try = *go;
01059 
01060   /*
01061    * Any Rejected CIs must be in exactly the same order that we sent.
01062    * Check packet length and CI length at each step.
01063    * If we find any deviations, then this packet is bad.
01064    */
01065 #define REJCIVOID(opt, neg) \
01066   if (go->neg && \
01067       len >= CILEN_VOID && \
01068       p[1] == CILEN_VOID && \
01069       p[0] == opt) { \
01070     len -= CILEN_VOID; \
01071     INCPTR(CILEN_VOID, p); \
01072     try.neg = 0; \
01073     LCPDEBUG((LOG_INFO, "lcp_rejci: void opt %d rejected\n", opt)); \
01074   }
01075 #define REJCISHORT(opt, neg, val) \
01076   if (go->neg && \
01077       len >= CILEN_SHORT && \
01078       p[1] == CILEN_SHORT && \
01079       p[0] == opt) { \
01080     len -= CILEN_SHORT; \
01081     INCPTR(2, p); \
01082     GETSHORT(cishort, p); \
01083     /* Check rejected value. */ \
01084     if (cishort != val) { \
01085       goto bad; \
01086     } \
01087     try.neg = 0; \
01088     LCPDEBUG((LOG_INFO,"lcp_rejci: short opt %d rejected\n", opt)); \
01089   }
01090 #define REJCICHAP(opt, neg, val, digest) \
01091   if (go->neg && \
01092       len >= CILEN_CHAP && \
01093       p[1] == CILEN_CHAP && \
01094       p[0] == opt) { \
01095     len -= CILEN_CHAP; \
01096     INCPTR(2, p); \
01097     GETSHORT(cishort, p); \
01098     GETCHAR(cichar, p); \
01099     /* Check rejected value. */ \
01100     if (cishort != val || cichar != digest) { \
01101       goto bad; \
01102     } \
01103     try.neg = 0; \
01104     try.neg_upap = 0; \
01105     LCPDEBUG((LOG_INFO,"lcp_rejci: chap opt %d rejected\n", opt)); \
01106   }
01107 #define REJCILONG(opt, neg, val) \
01108   if (go->neg && \
01109       len >= CILEN_LONG && \
01110       p[1] == CILEN_LONG && \
01111       p[0] == opt) { \
01112     len -= CILEN_LONG; \
01113     INCPTR(2, p); \
01114     GETLONG(cilong, p); \
01115     /* Check rejected value. */ \
01116     if (cilong != val) { \
01117       goto bad; \
01118     } \
01119     try.neg = 0; \
01120     LCPDEBUG((LOG_INFO,"lcp_rejci: long opt %d rejected\n", opt)); \
01121   }
01122 #define REJCILQR(opt, neg, val) \
01123   if (go->neg && \
01124       len >= CILEN_LQR && \
01125       p[1] == CILEN_LQR && \
01126       p[0] == opt) { \
01127     len -= CILEN_LQR; \
01128     INCPTR(2, p); \
01129     GETSHORT(cishort, p); \
01130     GETLONG(cilong, p); \
01131     /* Check rejected value. */ \
01132     if (cishort != PPP_LQR || cilong != val) { \
01133       goto bad; \
01134     } \
01135     try.neg = 0; \
01136     LCPDEBUG((LOG_INFO,"lcp_rejci: LQR opt %d rejected\n", opt)); \
01137   }
01138 #define REJCICBCP(opt, neg, val) \
01139   if (go->neg && \
01140       len >= CILEN_CBCP && \
01141       p[1] == CILEN_CBCP && \
01142       p[0] == opt) { \
01143     len -= CILEN_CBCP; \
01144     INCPTR(2, p); \
01145     GETCHAR(cichar, p); \
01146     /* Check rejected value. */ \
01147     if (cichar != val) { \
01148       goto bad; \
01149     } \
01150     try.neg = 0; \
01151     LCPDEBUG((LOG_INFO,"lcp_rejci: Callback opt %d rejected\n", opt)); \
01152   }
01153   
01154   REJCISHORT(CI_MRU, neg_mru, go->mru);
01155   REJCILONG(CI_ASYNCMAP, neg_asyncmap, go->asyncmap);
01156   REJCICHAP(CI_AUTHTYPE, neg_chap, PPP_CHAP, go->chap_mdtype);
01157   if (!go->neg_chap) {
01158     REJCISHORT(CI_AUTHTYPE, neg_upap, PPP_PAP);
01159   }
01160   REJCILQR(CI_QUALITY, neg_lqr, go->lqr_period);
01161   REJCICBCP(CI_CALLBACK, neg_cbcp, CBCP_OPT);
01162   REJCILONG(CI_MAGICNUMBER, neg_magicnumber, go->magicnumber);
01163   REJCIVOID(CI_PCOMPRESSION, neg_pcompression);
01164   REJCIVOID(CI_ACCOMPRESSION, neg_accompression);
01165   
01166   /*
01167    * If there are any remaining CIs, then this packet is bad.
01168    */
01169   if (len != 0) {
01170     goto bad;
01171   }
01172   /*
01173    * Now we can update state.
01174    */
01175   if (f->state != LS_OPENED) {
01176     *go = try;
01177   }
01178   return 1;
01179   
01180 bad:
01181   LCPDEBUG((LOG_WARNING, "lcp_rejci: received bad Reject!\n"));
01182   return 0;
01183 }
01184 
01185 
01186 /*
01187  * lcp_reqci - Check the peer's requested CIs and send appropriate response.
01188  *
01189  * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified
01190  * appropriately.  If reject_if_disagree is non-zero, doesn't return
01191  * CONFNAK; returns CONFREJ if it can't return CONFACK.
01192  */
01193 static int
01194 lcp_reqci(fsm *f, 
01195           u_char *inp,    /* Requested CIs */
01196           int *lenp,      /* Length of requested CIs */
01197           int reject_if_disagree)
01198 {
01199   lcp_options *go = &lcp_gotoptions[f->unit];
01200   lcp_options *ho = &lcp_hisoptions[f->unit];
01201   lcp_options *ao = &lcp_allowoptions[f->unit];
01202   u_char *cip, *next;         /* Pointer to current and next CIs */
01203   int cilen, citype, cichar;  /* Parsed len, type, char value */
01204   u_short cishort;            /* Parsed short value */
01205   u32_t cilong;               /* Parse long value */
01206   int rc = CONFACK;           /* Final packet return code */
01207   int orc;                    /* Individual option return code */
01208   u_char *p;                  /* Pointer to next char to parse */
01209   u_char *rejp;               /* Pointer to next char in reject frame */
01210   u_char *nakp;               /* Pointer to next char in Nak frame */
01211   int l = *lenp;              /* Length left */
01212 #if TRACELCP > 0
01213   char traceBuf[80];
01214   int traceNdx = 0;
01215 #endif
01216 
01217   /*
01218    * Reset all his options.
01219    */
01220   BZERO(ho, sizeof(*ho));
01221 
01222   /*
01223    * Process all his options.
01224    */
01225   next = inp;
01226   nakp = nak_buffer;
01227   rejp = inp;
01228   while (l) {
01229     orc = CONFACK;      /* Assume success */
01230     cip = p = next;     /* Remember begining of CI */
01231     if (l < 2 ||        /* Not enough data for CI header or */
01232         p[1] < 2 ||     /*  CI length too small or */
01233         p[1] > l) {     /*  CI length too big? */
01234       LCPDEBUG((LOG_WARNING, "lcp_reqci: bad CI length!\n"));
01235       orc = CONFREJ;    /* Reject bad CI */
01236       cilen = l;        /* Reject till end of packet */
01237       l = 0;            /* Don't loop again */
01238       citype = 0;
01239       goto endswitch;
01240     }
01241     GETCHAR(citype, p); /* Parse CI type */
01242     GETCHAR(cilen, p);  /* Parse CI length */
01243     l -= cilen;         /* Adjust remaining length */
01244     next += cilen;      /* Step to next CI */
01245 
01246     switch (citype) {   /* Check CI type */
01247       case CI_MRU:
01248         if (!ao->neg_mru) {    /* Allow option? */
01249           LCPDEBUG((LOG_INFO, "lcp_reqci: Reject MRU - not allowed\n"));
01250           orc = CONFREJ;    /* Reject CI */
01251           break;
01252         } else if (cilen != CILEN_SHORT) {  /* Check CI length */
01253           LCPDEBUG((LOG_INFO, "lcp_reqci: Reject MRU - bad length\n"));
01254           orc = CONFREJ;    /* Reject CI */
01255           break;
01256         }
01257         GETSHORT(cishort, p);  /* Parse MRU */
01258 
01259         /*
01260          * He must be able to receive at least our minimum.
01261          * No need to check a maximum.  If he sends a large number,
01262          * we'll just ignore it.
01263          */
01264         if (cishort < PPP_MINMRU) {
01265           LCPDEBUG((LOG_INFO, "lcp_reqci: Nak - MRU too small\n"));
01266           orc = CONFNAK;    /* Nak CI */
01267           PUTCHAR(CI_MRU, nakp);
01268           PUTCHAR(CILEN_SHORT, nakp);
01269           PUTSHORT(PPP_MINMRU, nakp);  /* Give him a hint */
01270           break;
01271         }
01272         ho->neg_mru = 1;    /* Remember he sent MRU */
01273         ho->mru = cishort;    /* And remember value */
01274 #if TRACELCP > 0
01275         snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " MRU %d", cishort);
01276         traceNdx = strlen(traceBuf);
01277 #endif
01278         break;
01279 
01280       case CI_ASYNCMAP:
01281         if (!ao->neg_asyncmap) {
01282           LCPDEBUG((LOG_INFO, "lcp_reqci: Reject ASYNCMAP not allowed\n"));
01283           orc = CONFREJ;
01284           break;
01285         } else if (cilen != CILEN_LONG) {
01286           LCPDEBUG((LOG_INFO, "lcp_reqci: Reject ASYNCMAP bad length\n"));
01287           orc = CONFREJ;
01288           break;
01289         }
01290         GETLONG(cilong, p);
01291         
01292         /*
01293          * Asyncmap must have set at least the bits
01294          * which are set in lcp_allowoptions[unit].asyncmap.
01295          */
01296         if ((ao->asyncmap & ~cilong) != 0) {
01297           LCPDEBUG((LOG_INFO, "lcp_reqci: Nak ASYNCMAP %lX missing %lX\n", 
01298                     cilong, ao->asyncmap));
01299           orc = CONFNAK;
01300           PUTCHAR(CI_ASYNCMAP, nakp);
01301           PUTCHAR(CILEN_LONG, nakp);
01302           PUTLONG(ao->asyncmap | cilong, nakp);
01303           break;
01304         }
01305         ho->neg_asyncmap = 1;
01306         ho->asyncmap = cilong;
01307 #if TRACELCP > 0
01308         snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " ASYNCMAP=%lX", cilong);
01309         traceNdx = strlen(traceBuf);
01310 #endif
01311         break;
01312 
01313       case CI_AUTHTYPE:
01314         if (cilen < CILEN_SHORT) {
01315           LCPDEBUG((LOG_INFO, "lcp_reqci: Reject AUTHTYPE missing arg\n"));
01316           orc = CONFREJ;
01317           break;
01318         } else if (!(ao->neg_upap || ao->neg_chap)) {
01319           /*
01320            * Reject the option if we're not willing to authenticate.
01321            */
01322           LCPDEBUG((LOG_INFO, "lcp_reqci: Reject AUTHTYPE not allowed\n"));
01323           orc = CONFREJ;
01324           break;
01325         }
01326         GETSHORT(cishort, p);
01327         
01328         /*
01329          * Authtype must be UPAP or CHAP.
01330          *
01331          * Note: if both ao->neg_upap and ao->neg_chap are set,
01332          * and the peer sends a Configure-Request with two
01333          * authenticate-protocol requests, one for CHAP and one
01334          * for UPAP, then we will reject the second request.
01335          * Whether we end up doing CHAP or UPAP depends then on
01336          * the ordering of the CIs in the peer's Configure-Request.
01337          */
01338         
01339         if (cishort == PPP_PAP) {
01340           if (ho->neg_chap) {  /* we've already accepted CHAP */
01341             LCPDEBUG((LOG_WARNING, "lcp_reqci: Reject AUTHTYPE PAP already accepted\n"));
01342             orc = CONFREJ;
01343             break;
01344           } else if (cilen != CILEN_SHORT) {
01345             LCPDEBUG((LOG_WARNING, "lcp_reqci: Reject AUTHTYPE PAP bad len\n"));
01346             orc = CONFREJ;
01347             break;
01348           }
01349           if (!ao->neg_upap) {  /* we don't want to do PAP */
01350             LCPDEBUG((LOG_WARNING, "lcp_reqci: Nak AUTHTYPE PAP not allowed\n"));
01351             orc = CONFNAK;  /* NAK it and suggest CHAP */
01352             PUTCHAR(CI_AUTHTYPE, nakp);
01353             PUTCHAR(CILEN_CHAP, nakp);
01354             PUTSHORT(PPP_CHAP, nakp);
01355             PUTCHAR(ao->chap_mdtype, nakp);
01356             break;
01357           }
01358           ho->neg_upap = 1;
01359 #if TRACELCP > 0
01360           snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " PAP (%X)", cishort);
01361           traceNdx = strlen(traceBuf);
01362 #endif
01363           break;
01364         }
01365         if (cishort == PPP_CHAP) {
01366           if (ho->neg_upap) {  /* we've already accepted PAP */
01367             LCPDEBUG((LOG_WARNING, "lcp_reqci: Reject AUTHTYPE CHAP accepted PAP\n"));
01368             orc = CONFREJ;
01369             break;
01370           } else if (cilen != CILEN_CHAP) {
01371             LCPDEBUG((LOG_WARNING, "lcp_reqci: Reject AUTHTYPE CHAP bad len\n"));
01372             orc = CONFREJ;
01373             break;
01374           }
01375           if (!ao->neg_chap) {  /* we don't want to do CHAP */
01376             LCPDEBUG((LOG_WARNING, "lcp_reqci: Nak AUTHTYPE CHAP not allowed\n"));
01377             orc = CONFNAK;  /* NAK it and suggest PAP */
01378             PUTCHAR(CI_AUTHTYPE, nakp);
01379             PUTCHAR(CILEN_SHORT, nakp);
01380             PUTSHORT(PPP_PAP, nakp);
01381             break;
01382           }
01383           GETCHAR(cichar, p);  /* get digest type*/
01384           if (cichar != CHAP_DIGEST_MD5
01385 #ifdef CHAPMS
01386               && cichar != CHAP_MICROSOFT
01387 #endif
01388           ) {
01389             LCPDEBUG((LOG_WARNING, "lcp_reqci: Nak AUTHTYPE CHAP digest=%d\n", cichar));
01390             orc = CONFNAK;
01391             PUTCHAR(CI_AUTHTYPE, nakp);
01392             PUTCHAR(CILEN_CHAP, nakp);
01393             PUTSHORT(PPP_CHAP, nakp);
01394             PUTCHAR(ao->chap_mdtype, nakp);
01395             break;
01396           }
01397 #if TRACELCP > 0
01398           snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CHAP %X,%d", cishort, cichar);
01399           traceNdx = strlen(traceBuf);
01400 #endif
01401           ho->chap_mdtype = cichar; /* save md type */
01402           ho->neg_chap = 1;
01403           break;
01404         }
01405         
01406         /*
01407          * We don't recognize the protocol they're asking for.
01408          * Nak it with something we're willing to do.
01409          * (At this point we know ao->neg_upap || ao->neg_chap.)
01410          */
01411         orc = CONFNAK;
01412         PUTCHAR(CI_AUTHTYPE, nakp);
01413         if (ao->neg_chap) {
01414           LCPDEBUG((LOG_WARNING, "lcp_reqci: Nak AUTHTYPE %d req CHAP\n", cishort));
01415           PUTCHAR(CILEN_CHAP, nakp);
01416           PUTSHORT(PPP_CHAP, nakp);
01417           PUTCHAR(ao->chap_mdtype, nakp);
01418         } else {
01419           LCPDEBUG((LOG_WARNING, "lcp_reqci: Nak AUTHTYPE %d req PAP\n", cishort));
01420           PUTCHAR(CILEN_SHORT, nakp);
01421           PUTSHORT(PPP_PAP, nakp);
01422         }
01423         break;
01424       
01425       case CI_QUALITY:
01426         GETSHORT(cishort, p);
01427         GETLONG(cilong, p);
01428 #if TRACELCP > 0
01429         snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " QUALITY (%x %x)", cishort, (unsigned int) cilong);
01430         traceNdx = strlen(traceBuf);
01431 #endif
01432 
01433         if (!ao->neg_lqr ||
01434             cilen != CILEN_LQR) {
01435           orc = CONFREJ;
01436           break;
01437         }
01438         
01439         /*
01440          * Check the protocol and the reporting period.
01441          * XXX When should we Nak this, and what with?
01442          */
01443         if (cishort != PPP_LQR) {
01444           orc = CONFNAK;
01445           PUTCHAR(CI_QUALITY, nakp);
01446           PUTCHAR(CILEN_LQR, nakp);
01447           PUTSHORT(PPP_LQR, nakp);
01448           PUTLONG(ao->lqr_period, nakp);
01449           break;
01450         }
01451         break;
01452       
01453       case CI_MAGICNUMBER:
01454         if (!(ao->neg_magicnumber || go->neg_magicnumber) ||
01455             cilen != CILEN_LONG) {
01456           orc = CONFREJ;
01457           break;
01458         }
01459         GETLONG(cilong, p);
01460 #if TRACELCP > 0
01461         snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " MAGICNUMBER (%lX)", cilong);
01462         traceNdx = strlen(traceBuf);
01463 #endif
01464 
01465         /*
01466          * He must have a different magic number.
01467          */
01468         if (go->neg_magicnumber &&
01469             cilong == go->magicnumber) {
01470           cilong = magic();  /* Don't put magic() inside macro! */
01471           orc = CONFNAK;
01472           PUTCHAR(CI_MAGICNUMBER, nakp);
01473           PUTCHAR(CILEN_LONG, nakp);
01474           PUTLONG(cilong, nakp);
01475           break;
01476         }
01477         ho->neg_magicnumber = 1;
01478         ho->magicnumber = cilong;
01479         break;
01480       
01481       
01482       case CI_PCOMPRESSION:
01483 #if TRACELCP > 0
01484         snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " PCOMPRESSION");
01485         traceNdx = strlen(traceBuf);
01486 #endif
01487         if (!ao->neg_pcompression ||
01488             cilen != CILEN_VOID) {
01489           orc = CONFREJ;
01490           break;
01491         }
01492         ho->neg_pcompression = 1;
01493         break;
01494       
01495       case CI_ACCOMPRESSION:
01496 #if TRACELCP > 0
01497         snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " ACCOMPRESSION");
01498         traceNdx = strlen(traceBuf);
01499 #endif
01500         if (!ao->neg_accompression ||
01501             cilen != CILEN_VOID) {
01502           orc = CONFREJ;
01503           break;
01504         }
01505         ho->neg_accompression = 1;
01506         break;
01507       
01508       case CI_MRRU:
01509 #if TRACELCP > 0
01510         snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CI_MRRU");
01511         traceNdx = strlen(traceBuf);
01512 #endif
01513         orc = CONFREJ;
01514         break;
01515       
01516       case CI_SSNHF:
01517 #if TRACELCP > 0
01518         snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CI_SSNHF");
01519         traceNdx = strlen(traceBuf);
01520 #endif
01521         orc = CONFREJ;
01522         break;
01523       
01524       case CI_EPDISC:
01525 #if TRACELCP > 0
01526         snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CI_EPDISC");
01527         traceNdx = strlen(traceBuf);
01528 #endif
01529         orc = CONFREJ;
01530         break;
01531       
01532       default:
01533 #if TRACELCP
01534         snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " unknown %d", citype);
01535         traceNdx = strlen(traceBuf);
01536 #endif
01537         orc = CONFREJ;
01538         break;
01539     }
01540 
01541   endswitch:
01542 #if TRACELCP
01543     if (traceNdx >= 80 - 32) {
01544       LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd%s\n", traceBuf));
01545       traceNdx = 0;
01546     }
01547 #endif
01548     if (orc == CONFACK && /* Good CI */
01549         rc != CONFACK) {  /*  but prior CI wasnt? */
01550       continue;           /* Don't send this one */
01551     }
01552 
01553     if (orc == CONFNAK) {     /* Nak this CI? */
01554       if (reject_if_disagree  /* Getting fed up with sending NAKs? */
01555           && citype != CI_MAGICNUMBER) {
01556         orc = CONFREJ;        /* Get tough if so */
01557       } else {
01558         if (rc == CONFREJ) {  /* Rejecting prior CI? */
01559           continue;           /* Don't send this one */
01560         }
01561         rc = CONFNAK;
01562       }
01563     }
01564     if (orc == CONFREJ) {        /* Reject this CI */
01565       rc = CONFREJ;
01566       if (cip != rejp) {         /* Need to move rejected CI? */
01567         BCOPY(cip, rejp, cilen); /* Move it */
01568       }
01569       INCPTR(cilen, rejp);       /* Update output pointer */
01570     }
01571   }
01572 
01573   /*
01574    * If we wanted to send additional NAKs (for unsent CIs), the
01575    * code would go here.  The extra NAKs would go at *nakp.
01576    * At present there are no cases where we want to ask the
01577    * peer to negotiate an option.
01578    */
01579 
01580   switch (rc) {
01581     case CONFACK:
01582       *lenp = (int)(next - inp);
01583       break;
01584     case CONFNAK:
01585       /*
01586        * Copy the Nak'd options from the nak_buffer to the caller's buffer.
01587        */
01588       *lenp = (int)(nakp - nak_buffer);
01589       BCOPY(nak_buffer, inp, *lenp);
01590       break;
01591     case CONFREJ:
01592       *lenp = (int)(rejp - inp);
01593       break;
01594   }
01595 
01596 #if TRACELCP > 0
01597   if (traceNdx > 0) {
01598     LCPDEBUG((LOG_INFO, "lcp_reqci: %s\n", traceBuf));
01599   }
01600 #endif
01601   LCPDEBUG((LOG_INFO, "lcp_reqci: returning CONF%s.\n", CODENAME(rc)));
01602   return (rc);      /* Return final code */
01603 }
01604 
01605 
01606 /*
01607  * lcp_up - LCP has come UP.
01608  */
01609 static void
01610 lcp_up(fsm *f)
01611 {
01612   lcp_options *wo = &lcp_wantoptions[f->unit];
01613   lcp_options *ho = &lcp_hisoptions[f->unit];
01614   lcp_options *go = &lcp_gotoptions[f->unit];
01615   lcp_options *ao = &lcp_allowoptions[f->unit];
01616 
01617   if (!go->neg_magicnumber) {
01618     go->magicnumber = 0;
01619   }
01620   if (!ho->neg_magicnumber) {
01621     ho->magicnumber = 0;
01622   }
01623 
01624   /*
01625    * Set our MTU to the smaller of the MTU we wanted and
01626    * the MRU our peer wanted.  If we negotiated an MRU,
01627    * set our MRU to the larger of value we wanted and
01628    * the value we got in the negotiation.
01629    */
01630   ppp_send_config(f->unit, LWIP_MIN(ao->mru, (ho->neg_mru? ho->mru: PPP_MRU)),
01631                  (ho->neg_asyncmap? ho->asyncmap: 0xffffffffl),
01632                   ho->neg_pcompression, ho->neg_accompression);
01633   /*
01634    * If the asyncmap hasn't been negotiated, we really should
01635    * set the receive asyncmap to ffffffff, but we set it to 0
01636    * for backwards contemptibility.
01637    */
01638   ppp_recv_config(f->unit, (go->neg_mru? LWIP_MAX(wo->mru, go->mru): PPP_MRU),
01639                  (go->neg_asyncmap? go->asyncmap: 0x00000000),
01640                   go->neg_pcompression, go->neg_accompression);
01641 
01642   if (ho->neg_mru) {
01643     peer_mru[f->unit] = ho->mru;
01644   }
01645 
01646   lcp_echo_lowerup(f->unit); /* Enable echo messages */
01647 
01648   link_established(f->unit);
01649 }
01650 
01651 
01652 /*
01653  * lcp_down - LCP has gone DOWN.
01654  *
01655  * Alert other protocols.
01656  */
01657 static void
01658 lcp_down(fsm *f)
01659 {
01660   lcp_options *go = &lcp_gotoptions[f->unit];
01661 
01662   lcp_echo_lowerdown(f->unit);
01663 
01664   link_down(f->unit);
01665 
01666   ppp_send_config(f->unit, PPP_MRU, 0xffffffffl, 0, 0);
01667   ppp_recv_config(f->unit, PPP_MRU,
01668                   (go->neg_asyncmap? go->asyncmap: 0x00000000),
01669                    go->neg_pcompression, go->neg_accompression);
01670   peer_mru[f->unit] = PPP_MRU;
01671 }
01672 
01673 
01674 /*
01675  * lcp_starting - LCP needs the lower layer up.
01676  */
01677 static void
01678 lcp_starting(fsm *f)
01679 {
01680   link_required(f->unit);
01681 }
01682 
01683 
01684 /*
01685  * lcp_finished - LCP has finished with the lower layer.
01686  */
01687 static void
01688 lcp_finished(fsm *f)
01689 {
01690   link_terminated(f->unit);
01691 }
01692 
01693 
01694 #if 0
01695 /*
01696  * print_string - print a readable representation of a string using
01697  * printer.
01698  */
01699 static void
01700 print_string( char *p, int len, void (*printer) (void *, char *, ...), void *arg)
01701 {
01702   int c;
01703   
01704   printer(arg, "\"");
01705   for (; len > 0; --len) {
01706     c = *p++;
01707     if (' ' <= c && c <= '~') {
01708         if (c == '\\' || c == '"') {
01709           printer(arg, "\\");
01710         }
01711         printer(arg, "%c", c);
01712     } else {
01713       switch (c) {
01714         case '\n':
01715           printer(arg, "\\n");
01716           break;
01717         case '\r':
01718           printer(arg, "\\r");
01719           break;
01720         case '\t':
01721           printer(arg, "\\t");
01722           break;
01723         default:
01724           printer(arg, "\\%.3o", c);
01725         }
01726     }
01727   }
01728   printer(arg, "\"");
01729 }
01730 
01731 
01732 /*
01733  * lcp_printpkt - print the contents of an LCP packet.
01734  */
01735 static char *lcp_codenames[] = {
01736   "ConfReq", "ConfAck", "ConfNak", "ConfRej",
01737   "TermReq", "TermAck", "CodeRej", "ProtRej",
01738   "EchoReq", "EchoRep", "DiscReq"
01739 };
01740 
01741 static int
01742 lcp_printpkt( u_char *p, int plen, void (*printer) (void *, char *, ...), void *arg)
01743 {
01744   int code, id, len, olen;
01745   u_char *pstart, *optend;
01746   u_short cishort;
01747   u32_t cilong;
01748 
01749   if (plen < HEADERLEN) {
01750     return 0;
01751   }
01752   pstart = p;
01753   GETCHAR(code, p);
01754   GETCHAR(id, p);
01755   GETSHORT(len, p);
01756   if (len < HEADERLEN || len > plen) {
01757     return 0;
01758   }
01759 
01760   if (code >= 1 && code <= sizeof(lcp_codenames) / sizeof(char *)) {
01761     printer(arg, " %s", lcp_codenames[code-1]);
01762   } else {
01763     printer(arg, " code=0x%x", code);
01764   }
01765   printer(arg, " id=0x%x", id);
01766   len -= HEADERLEN;
01767   switch (code) {
01768     case CONFREQ:
01769     case CONFACK:
01770     case CONFNAK:
01771     case CONFREJ:
01772       /* print option list */
01773       while (len >= 2) {
01774         GETCHAR(code, p);
01775         GETCHAR(olen, p);
01776         p -= 2;
01777         if (olen < 2 || olen > len) {
01778           break;
01779         }
01780         printer(arg, " <");
01781         len -= olen;
01782         optend = p + olen;
01783         switch (code) {
01784           case CI_MRU:
01785             if (olen == CILEN_SHORT) {
01786               p += 2;
01787               GETSHORT(cishort, p);
01788               printer(arg, "mru %d", cishort);
01789             }
01790             break;
01791           case CI_ASYNCMAP:
01792             if (olen == CILEN_LONG) {
01793               p += 2;
01794               GETLONG(cilong, p);
01795               printer(arg, "asyncmap 0x%lx", cilong);
01796             }
01797             break;
01798           case CI_AUTHTYPE:
01799             if (olen >= CILEN_SHORT) {
01800               p += 2;
01801               printer(arg, "auth ");
01802               GETSHORT(cishort, p);
01803               switch (cishort) {
01804                 case PPP_PAP:
01805                   printer(arg, "pap");
01806                   break;
01807                 case PPP_CHAP:
01808                   printer(arg, "chap");
01809                   break;
01810                 default:
01811                   printer(arg, "0x%x", cishort);
01812               }
01813             }
01814             break;
01815           case CI_QUALITY:
01816             if (olen >= CILEN_SHORT) {
01817               p += 2;
01818               printer(arg, "quality ");
01819               GETSHORT(cishort, p);
01820               switch (cishort) {
01821                 case PPP_LQR:
01822                   printer(arg, "lqr");
01823                   break;
01824                 default:
01825                   printer(arg, "0x%x", cishort);
01826               }
01827             }
01828             break;
01829           case CI_CALLBACK:
01830             if (olen >= CILEN_CHAR) {
01831               p += 2;
01832               printer(arg, "callback ");
01833               GETSHORT(cishort, p);
01834               switch (cishort) {
01835                 case CBCP_OPT:
01836                   printer(arg, "CBCP");
01837                   break;
01838                 default:
01839                   printer(arg, "0x%x", cishort);
01840               }
01841             }
01842             break;
01843           case CI_MAGICNUMBER:
01844             if (olen == CILEN_LONG) {
01845               p += 2;
01846               GETLONG(cilong, p);
01847               printer(arg, "magic 0x%x", cilong);
01848             }
01849             break;
01850           case CI_PCOMPRESSION:
01851             if (olen == CILEN_VOID) {
01852               p += 2;
01853               printer(arg, "pcomp");
01854             }
01855             break;
01856           case CI_ACCOMPRESSION:
01857             if (olen == CILEN_VOID) {
01858               p += 2;
01859               printer(arg, "accomp");
01860             }
01861             break;
01862         }
01863         while (p < optend) {
01864           GETCHAR(code, p);
01865           printer(arg, " %.2x", code);
01866         }
01867         printer(arg, ">");
01868       }
01869       break;
01870     
01871     case TERMACK:
01872     case TERMREQ:
01873       if (len > 0 && *p >= ' ' && *p < 0x7f) {
01874         printer(arg, " ");
01875         print_string((char*)p, len, printer, arg);
01876         p += len;
01877         len = 0;
01878       }
01879       break;
01880     
01881     case ECHOREQ:
01882     case ECHOREP:
01883     case DISCREQ:
01884       if (len >= 4) {
01885         GETLONG(cilong, p);
01886         printer(arg, " magic=0x%x", cilong);
01887         p += 4;
01888         len -= 4;
01889       }
01890       break;
01891   }
01892 
01893   /* print the rest of the bytes in the packet */
01894   for (; len > 0; --len) {
01895     GETCHAR(code, p);
01896     printer(arg, " %.2x", code);
01897   }
01898 
01899   return (int)(p - pstart);
01900 }
01901 #endif
01902 
01903 /*
01904  * Time to shut down the link because there is nothing out there.
01905  */
01906 static void
01907 LcpLinkFailure (fsm *f)
01908 {
01909   if (f->state == LS_OPENED) {
01910     LCPDEBUG((LOG_INFO, "No response to %d echo-requests\n", lcp_echos_pending));
01911     LCPDEBUG((LOG_NOTICE, "Serial link appears to be disconnected.\n"));
01912     lcp_close(f->unit, "Peer not responding");
01913   }
01914 }
01915 
01916 /*
01917  * Timer expired for the LCP echo requests from this process.
01918  */
01919 static void
01920 LcpEchoCheck (fsm *f)
01921 {
01922   LcpSendEchoRequest (f);
01923 
01924   /*
01925    * Start the timer for the next interval.
01926    */
01927   LWIP_ASSERT("lcp_echo_timer_running == 0", lcp_echo_timer_running == 0);
01928 
01929   TIMEOUT (LcpEchoTimeout, f, lcp_echo_interval);
01930   lcp_echo_timer_running = 1;
01931 }
01932 
01933 /*
01934  * LcpEchoTimeout - Timer expired on the LCP echo
01935  */
01936 static void
01937 LcpEchoTimeout (void *arg)
01938 {
01939   if (lcp_echo_timer_running != 0) {
01940     lcp_echo_timer_running = 0;
01941     LcpEchoCheck ((fsm *) arg);
01942   }
01943 }
01944 
01945 /*
01946  * LcpEchoReply - LCP has received a reply to the echo
01947  */
01948 static void
01949 lcp_received_echo_reply (fsm *f, int id, u_char *inp, int len)
01950 {
01951   u32_t magic;
01952 
01953   LWIP_UNUSED_ARG(id);
01954 
01955   /* Check the magic number - don't count replies from ourselves. */
01956   if (len < 4) {
01957     LCPDEBUG((LOG_WARNING, "lcp: received short Echo-Reply, length %d\n", len));
01958     return;
01959   }
01960   GETLONG(magic, inp);
01961   if (lcp_gotoptions[f->unit].neg_magicnumber && magic == lcp_gotoptions[f->unit].magicnumber) {
01962     LCPDEBUG((LOG_WARNING, "appear to have received our own echo-reply!\n"));
01963     return;
01964   }
01965   
01966   /* Reset the number of outstanding echo frames */
01967   lcp_echos_pending = 0;
01968 }
01969 
01970 /*
01971  * LcpSendEchoRequest - Send an echo request frame to the peer
01972  */
01973 static void
01974 LcpSendEchoRequest (fsm *f)
01975 {
01976   u32_t lcp_magic;
01977   u_char pkt[4], *pktp;
01978 
01979   /*
01980    * Detect the failure of the peer at this point.
01981    */
01982   if (lcp_echo_fails != 0) {
01983     if (lcp_echos_pending++ >= lcp_echo_fails) {
01984       LcpLinkFailure(f);
01985       lcp_echos_pending = 0;
01986     }
01987   }
01988 
01989   /*
01990    * Make and send the echo request frame.
01991    */
01992   if (f->state == LS_OPENED) {
01993     lcp_magic = lcp_gotoptions[f->unit].magicnumber;
01994     pktp = pkt;
01995     PUTLONG(lcp_magic, pktp);
01996     fsm_sdata(f, ECHOREQ, (u_char)(lcp_echo_number++ & 0xFF), pkt, (int)(pktp - pkt));
01997   }
01998 }
01999 
02000 /*
02001  * lcp_echo_lowerup - Start the timer for the LCP frame
02002  */
02003 
02004 static void
02005 lcp_echo_lowerup (int unit)
02006 {
02007   fsm *f = &lcp_fsm[unit];
02008 
02009   /* Clear the parameters for generating echo frames */
02010   lcp_echos_pending      = 0;
02011   lcp_echo_number        = 0;
02012   lcp_echo_timer_running = 0;
02013 
02014   /* If a timeout interval is specified then start the timer */
02015   if (lcp_echo_interval != 0) {
02016     LcpEchoCheck (f);
02017   }
02018 }
02019 
02020 /*
02021  * lcp_echo_lowerdown - Stop the timer for the LCP frame
02022  */
02023 
02024 static void
02025 lcp_echo_lowerdown (int unit)
02026 {
02027   fsm *f = &lcp_fsm[unit];
02028 
02029   if (lcp_echo_timer_running != 0) {
02030     UNTIMEOUT (LcpEchoTimeout, f);
02031     lcp_echo_timer_running = 0;
02032   }
02033 }
02034 
02035 #endif /* PPP_SUPPORT */
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines