Home | History | Annotate | Line # | Download | only in pppd
      1 /*	$NetBSD: lcp.c,v 1.6 2025/01/08 19:59:39 christos Exp $	*/
      2 
      3 /*
      4  * lcp.c - PPP Link Control Protocol.
      5  *
      6  * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  *
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  *
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in
     17  *    the documentation and/or other materials provided with the
     18  *    distribution.
     19  *
     20  * 3. The name "Carnegie Mellon University" must not be used to
     21  *    endorse or promote products derived from this software without
     22  *    prior written permission. For permission or any legal
     23  *    details, please contact
     24  *      Office of Technology Transfer
     25  *      Carnegie Mellon University
     26  *      5000 Forbes Avenue
     27  *      Pittsburgh, PA  15213-3890
     28  *      (412) 268-4387, fax: (412) 268-7395
     29  *      tech-transfer (at) andrew.cmu.edu
     30  *
     31  * 4. Redistributions of any form whatsoever must retain the following
     32  *    acknowledgment:
     33  *    "This product includes software developed by Computing Services
     34  *     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
     35  *
     36  * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
     37  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
     38  * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
     39  * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     40  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
     41  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
     42  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     43  */
     44 
     45 #include <sys/cdefs.h>
     46 __RCSID("$NetBSD: lcp.c,v 1.6 2025/01/08 19:59:39 christos Exp $");
     47 
     48 #ifdef HAVE_CONFIG_H
     49 #include "config.h"
     50 #endif
     51 
     52 #include <stdio.h>
     53 #include <string.h>
     54 #include <stdlib.h>
     55 #include <fcntl.h>
     56 #include <string.h>
     57 #include <time.h>
     58 #include <arpa/inet.h>
     59 #include <sys/mman.h>
     60 
     61 #include "pppd-private.h"
     62 #include "options.h"
     63 #include "fsm.h"
     64 #include "lcp.h"
     65 #include "eap.h"
     66 #include "chap.h"
     67 #include "magic.h"
     68 #include "multilink.h"
     69 
     70 /*
     71  * When the link comes up we want to be able to wait for a short while,
     72  * or until seeing some input from the peer, before starting to send
     73  * configure-requests.  We do this by delaying the fsm_lowerup call.
     74  */
     75 /* steal a bit in fsm flags word */
     76 #define DELAYED_UP	0x100
     77 
     78 static void lcp_delayed_up(void *);
     79 
     80 /*
     81  * These definitions relate to the measurement and logging of round-trip
     82  * time (RTT) of LCP echo-requests implemented in lcp_rtt_update_buffer().
     83  */
     84 #define LCP_RTT_MAGIC 0x19450425
     85 #define LCP_RTT_HEADER_LENGTH 4
     86 #define LCP_RTT_FILE_SIZE 8192
     87 #define LCP_RTT_ELEMENTS (LCP_RTT_FILE_SIZE / sizeof(u_int32_t) - LCP_RTT_HEADER_LENGTH) / 2
     88 
     89 /*
     90  * LCP-related command-line options.
     91  */
     92 int	lcp_echo_interval = 0; 	/* Interval between LCP echo-requests */
     93 int	lcp_echo_fails = 0;	/* Tolerance to unanswered echo-requests */
     94 bool	lcp_echo_adaptive = 0;	/* request echo only if the link was idle */
     95 char	*lcp_rtt_file = NULL;	/* measure the RTT of LCP echo-requests */
     96 bool	lax_recv = 0;		/* accept control chars in asyncmap */
     97 bool	noendpoint = 0;		/* don't send/accept endpoint discriminator */
     98 
     99 static int noopt(char **);
    100 
    101 #ifdef PPP_WITH_MULTILINK
    102 static int setendpoint(char **);
    103 static void printendpoint(option_t *, void (*)(void *, char *, ...), void *);
    104 #endif /* PPP_WITH_MULTILINK */
    105 
    106 static struct option lcp_option_list[] = {
    107     /* LCP options */
    108     { "-all", o_special_noarg, (void *)noopt,
    109       "Don't request/allow any LCP options" },
    110 
    111     { "noaccomp", o_bool, &lcp_wantoptions[0].neg_accompression,
    112       "Disable address/control compression",
    113       OPT_A2CLR, &lcp_allowoptions[0].neg_accompression },
    114     { "-ac", o_bool, &lcp_wantoptions[0].neg_accompression,
    115       "Disable address/control compression",
    116       OPT_ALIAS | OPT_A2CLR, &lcp_allowoptions[0].neg_accompression },
    117 
    118     { "asyncmap", o_uint32, &lcp_wantoptions[0].asyncmap,
    119       "Set asyncmap (for received packets)",
    120       OPT_OR, &lcp_wantoptions[0].neg_asyncmap },
    121     { "-as", o_uint32, &lcp_wantoptions[0].asyncmap,
    122       "Set asyncmap (for received packets)",
    123       OPT_ALIAS | OPT_OR, &lcp_wantoptions[0].neg_asyncmap },
    124     { "default-asyncmap", o_uint32, &lcp_wantoptions[0].asyncmap,
    125       "Disable asyncmap negotiation",
    126       OPT_OR | OPT_NOARG | OPT_VAL(~0U) | OPT_A2CLR,
    127       &lcp_allowoptions[0].neg_asyncmap },
    128     { "-am", o_uint32, &lcp_wantoptions[0].asyncmap,
    129       "Disable asyncmap negotiation",
    130       OPT_ALIAS | OPT_OR | OPT_NOARG | OPT_VAL(~0U) | OPT_A2CLR,
    131       &lcp_allowoptions[0].neg_asyncmap },
    132 
    133     { "nomagic", o_bool, &lcp_wantoptions[0].neg_magicnumber,
    134       "Disable magic number negotiation (looped-back line detection)",
    135       OPT_A2CLR, &lcp_allowoptions[0].neg_magicnumber },
    136     { "-mn", o_bool, &lcp_wantoptions[0].neg_magicnumber,
    137       "Disable magic number negotiation (looped-back line detection)",
    138       OPT_ALIAS | OPT_A2CLR, &lcp_allowoptions[0].neg_magicnumber },
    139 
    140     { "mru", o_int, &lcp_wantoptions[0].mru,
    141       "Set MRU (maximum received packet size) for negotiation",
    142       OPT_PRIO, &lcp_wantoptions[0].neg_mru },
    143     { "default-mru", o_bool, &lcp_wantoptions[0].neg_mru,
    144       "Disable MRU negotiation (use default 1500)",
    145       OPT_PRIOSUB | OPT_A2CLR, &lcp_allowoptions[0].neg_mru },
    146     { "-mru", o_bool, &lcp_wantoptions[0].neg_mru,
    147       "Disable MRU negotiation (use default 1500)",
    148       OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR, &lcp_allowoptions[0].neg_mru },
    149 
    150     { "mtu", o_int, &lcp_allowoptions[0].mru,
    151       "Set our MTU", OPT_LIMITS, NULL, MAXMRU, MINMRU },
    152 
    153     { "nopcomp", o_bool, &lcp_wantoptions[0].neg_pcompression,
    154       "Disable protocol field compression",
    155       OPT_A2CLR, &lcp_allowoptions[0].neg_pcompression },
    156     { "-pc", o_bool, &lcp_wantoptions[0].neg_pcompression,
    157       "Disable protocol field compression",
    158       OPT_ALIAS | OPT_A2CLR, &lcp_allowoptions[0].neg_pcompression },
    159 
    160     { "passive", o_bool, &lcp_wantoptions[0].passive,
    161       "Set passive mode", 1 },
    162     { "-p", o_bool, &lcp_wantoptions[0].passive,
    163       "Set passive mode", OPT_ALIAS | 1 },
    164 
    165     { "silent", o_bool, &lcp_wantoptions[0].silent,
    166       "Set silent mode", 1 },
    167 
    168     { "lcp-echo-failure", o_int, &lcp_echo_fails,
    169       "Set number of consecutive echo failures to indicate link failure",
    170       OPT_PRIO },
    171     { "lcp-echo-interval", o_int, &lcp_echo_interval,
    172       "Set time in seconds between LCP echo requests", OPT_PRIO },
    173     { "lcp-echo-adaptive", o_bool, &lcp_echo_adaptive,
    174       "Suppress LCP echo requests if traffic was received", 1 },
    175     { "lcp-rtt-file", o_string, &lcp_rtt_file,
    176       "Filename for logging the round-trip time of LCP echo requests",
    177       OPT_PRIO | OPT_PRIV },
    178     { "lcp-restart", o_int, &lcp_fsm[0].timeouttime,
    179       "Set time in seconds between LCP retransmissions", OPT_PRIO },
    180     { "lcp-max-terminate", o_int, &lcp_fsm[0].maxtermtransmits,
    181       "Set maximum number of LCP terminate-request transmissions", OPT_PRIO },
    182     { "lcp-max-configure", o_int, &lcp_fsm[0].maxconfreqtransmits,
    183       "Set maximum number of LCP configure-request transmissions", OPT_PRIO },
    184     { "lcp-max-failure", o_int, &lcp_fsm[0].maxnakloops,
    185       "Set limit on number of LCP configure-naks", OPT_PRIO },
    186 
    187     { "receive-all", o_bool, &lax_recv,
    188       "Accept all received control characters", 1 },
    189 
    190 #ifdef PPP_WITH_MULTILINK
    191     { "mrru", o_int, &lcp_wantoptions[0].mrru,
    192       "Maximum received packet size for multilink bundle",
    193       OPT_PRIO, &lcp_wantoptions[0].neg_mrru },
    194 
    195     { "mpshortseq", o_bool, &lcp_wantoptions[0].neg_ssnhf,
    196       "Use short sequence numbers in multilink headers",
    197       OPT_PRIO | 1, &lcp_allowoptions[0].neg_ssnhf },
    198     { "nompshortseq", o_bool, &lcp_wantoptions[0].neg_ssnhf,
    199       "Don't use short sequence numbers in multilink headers",
    200       OPT_PRIOSUB | OPT_A2CLR, &lcp_allowoptions[0].neg_ssnhf },
    201 
    202     { "endpoint", o_special, (void *) setendpoint,
    203       "Endpoint discriminator for multilink",
    204       OPT_PRIO | OPT_A2PRINTER, (void *) printendpoint },
    205 #endif /* PPP_WITH_MULTILINK */
    206 
    207     { "noendpoint", o_bool, &noendpoint,
    208       "Don't send or accept multilink endpoint discriminator", 1 },
    209 
    210     {NULL}
    211 };
    212 
    213 /* global vars */
    214 fsm lcp_fsm[NUM_PPP];			/* LCP fsm structure (global)*/
    215 lcp_options lcp_wantoptions[NUM_PPP];	/* Options that we want to request */
    216 lcp_options lcp_gotoptions[NUM_PPP];	/* Options that peer ack'd */
    217 lcp_options lcp_allowoptions[NUM_PPP];	/* Options we allow peer to request */
    218 lcp_options lcp_hisoptions[NUM_PPP];	/* Options that we ack'd */
    219 
    220 static int lcp_echos_pending = 0;	/* Number of outstanding echo msgs */
    221 static int lcp_echo_number   = 0;	/* ID number of next echo frame */
    222 static int lcp_echo_timer_running = 0;  /* set if a timer is running */
    223 static int lcp_rtt_file_fd = 0;		/* fd for the opened LCP RTT file */
    224 static u_int32_t *lcp_rtt_buffer = NULL; /* the mmap'ed LCP RTT file */
    225 
    226 static u_char nak_buffer[PPP_MRU];	/* where we construct a nak packet */
    227 
    228 /*
    229  * Callbacks for fsm code.  (CI = Configuration Information)
    230  */
    231 static void lcp_resetci(fsm *);	/* Reset our CI */
    232 static int  lcp_cilen(fsm *);		/* Return length of our CI */
    233 static void lcp_addci(fsm *, u_char *, int *); /* Add our CI to pkt */
    234 static int  lcp_ackci(fsm *, u_char *, int); /* Peer ack'd our CI */
    235 static int  lcp_nakci(fsm *, u_char *, int, int); /* Peer nak'd our CI */
    236 static int  lcp_rejci(fsm *, u_char *, int); /* Peer rej'd our CI */
    237 static int  lcp_reqci(fsm *, u_char *, int *, int); /* Rcv peer CI */
    238 static void lcp_up(fsm *);		/* We're UP */
    239 static void lcp_down(fsm *);		/* We're DOWN */
    240 static void lcp_starting(fsm *);	/* We need lower layer up */
    241 static void lcp_finished(fsm *);	/* We need lower layer down */
    242 static int  lcp_extcode(fsm *, int, int, u_char *, int);
    243 static void lcp_rprotrej(fsm *, u_char *, int);
    244 
    245 /*
    246  * routines to send LCP echos to peer
    247  */
    248 
    249 static void lcp_echo_lowerup(int);
    250 static void lcp_echo_lowerdown(int);
    251 static void LcpEchoTimeout(void *);
    252 static void lcp_received_echo_reply(fsm *, int, u_char *, int);
    253 static void LcpSendEchoRequest(fsm *);
    254 static void LcpLinkFailure(fsm *);
    255 static void LcpEchoCheck(fsm *);
    256 
    257 static fsm_callbacks lcp_callbacks = {	/* LCP callback routines */
    258     lcp_resetci,		/* Reset our Configuration Information */
    259     lcp_cilen,			/* Length of our Configuration Information */
    260     lcp_addci,			/* Add our Configuration Information */
    261     lcp_ackci,			/* ACK our Configuration Information */
    262     lcp_nakci,			/* NAK our Configuration Information */
    263     lcp_rejci,			/* Reject our Configuration Information */
    264     lcp_reqci,			/* Request peer's Configuration Information */
    265     lcp_up,			/* Called when fsm reaches OPENED state */
    266     lcp_down,			/* Called when fsm leaves OPENED state */
    267     lcp_starting,		/* Called when we want the lower layer up */
    268     lcp_finished,		/* Called when we want the lower layer down */
    269     NULL,			/* Called when Protocol-Reject received */
    270     NULL,			/* Retransmission is necessary */
    271     lcp_extcode,		/* Called to handle LCP-specific codes */
    272     "LCP"			/* String name of protocol */
    273 };
    274 
    275 /*
    276  * Protocol entry points.
    277  * Some of these are called directly.
    278  */
    279 
    280 static void lcp_init(int);
    281 static void lcp_input(int, u_char *, int);
    282 static void lcp_protrej(int);
    283 static int  lcp_printpkt(u_char *, int, void (*)(void *, char *, ...), void *);
    284 
    285 struct protent lcp_protent = {
    286     PPP_LCP,
    287     lcp_init,
    288     lcp_input,
    289     lcp_protrej,
    290     lcp_lowerup,
    291     lcp_lowerdown,
    292     lcp_open,
    293     lcp_close,
    294     lcp_printpkt,
    295     NULL,
    296     1,
    297     "LCP",
    298     NULL,
    299     lcp_option_list,
    300     NULL,
    301     NULL,
    302     NULL
    303 };
    304 
    305 int lcp_loopbackfail = DEFLOOPBACKFAIL;
    306 
    307 /*
    308  * Length of each type of configuration option (in octets)
    309  */
    310 #define CILEN_VOID	2
    311 #define CILEN_CHAR	3
    312 #define CILEN_SHORT	4	/* CILEN_VOID + 2 */
    313 #define CILEN_CHAP	5	/* CILEN_VOID + 2 + 1 */
    314 #define CILEN_LONG	6	/* CILEN_VOID + 4 */
    315 #define CILEN_LQR	8	/* CILEN_VOID + 2 + 4 */
    316 #define CILEN_CBCP	3
    317 
    318 #define CODENAME(x)	((x) == CONFACK ? "ACK" : \
    319 			 (x) == CONFNAK ? "NAK" : "REJ")
    320 
    321 /*
    322  * noopt - Disable all options (why?).
    323  */
    324 static int
    325 noopt(char **argv)
    326 {
    327     BZERO((char *) &lcp_wantoptions[0], sizeof (struct lcp_options));
    328     BZERO((char *) &lcp_allowoptions[0], sizeof (struct lcp_options));
    329 
    330     return (1);
    331 }
    332 
    333 #ifdef PPP_WITH_MULTILINK
    334 static int
    335 setendpoint(char **argv)
    336 {
    337     if (str_to_epdisc(&lcp_wantoptions[0].endpoint, *argv)) {
    338 	lcp_wantoptions[0].neg_endpoint = 1;
    339 	return 1;
    340     }
    341     ppp_option_error("Can't parse '%s' as an endpoint discriminator", *argv);
    342     return 0;
    343 }
    344 
    345 static void
    346 printendpoint(option_t *opt, void (*printer)(void *, char *, ...), void *arg)
    347 {
    348 	printer(arg, "%s", epdisc_to_str(&lcp_wantoptions[0].endpoint));
    349 }
    350 #endif /* PPP_WITH_MULTILINK */
    351 
    352 /*
    353  * lcp_init - Initialize LCP.
    354  */
    355 static void
    356 lcp_init(int unit)
    357 {
    358     fsm *f = &lcp_fsm[unit];
    359     lcp_options *wo = &lcp_wantoptions[unit];
    360     lcp_options *ao = &lcp_allowoptions[unit];
    361 
    362     f->unit = unit;
    363     f->protocol = PPP_LCP;
    364     f->callbacks = &lcp_callbacks;
    365 
    366     fsm_init(f);
    367 
    368     BZERO(wo, sizeof(*wo));
    369     wo->neg_mru = 1;
    370     wo->mru = DEFMRU;
    371     wo->neg_asyncmap = 1;
    372     wo->neg_magicnumber = 1;
    373     wo->neg_pcompression = 1;
    374     wo->neg_accompression = 1;
    375 
    376     BZERO(ao, sizeof(*ao));
    377     ao->neg_mru = 1;
    378     ao->mru = MAXMRU;
    379     ao->neg_asyncmap = 1;
    380     ao->neg_chap = 1;
    381     ao->chap_mdtype = chap_mdtype_all;
    382     ao->neg_upap = 1;
    383     ao->neg_eap = 1;
    384     ao->neg_magicnumber = 1;
    385     ao->neg_pcompression = 1;
    386     ao->neg_accompression = 1;
    387     ao->neg_endpoint = 1;
    388 }
    389 
    390 
    391 /*
    392  * lcp_open - LCP is allowed to come up.
    393  */
    394 void
    395 lcp_open(int unit)
    396 {
    397     fsm *f = &lcp_fsm[unit];
    398     lcp_options *wo = &lcp_wantoptions[unit];
    399 
    400     f->flags &= ~(OPT_PASSIVE | OPT_SILENT);
    401     if (wo->passive)
    402 	f->flags |= OPT_PASSIVE;
    403     if (wo->silent)
    404 	f->flags |= OPT_SILENT;
    405     fsm_open(f);
    406 }
    407 
    408 
    409 /*
    410  * lcp_close - Take LCP down.
    411  */
    412 void
    413 lcp_close(int unit, char *reason)
    414 {
    415     fsm *f = &lcp_fsm[unit];
    416     int oldstate;
    417 
    418     if (!in_phase(PHASE_DEAD) && !in_phase(PHASE_MASTER))
    419 	new_phase(PHASE_TERMINATE);
    420 
    421     if (f->flags & DELAYED_UP) {
    422 	UNTIMEOUT(lcp_delayed_up, f);
    423 	f->state = STOPPED;
    424     }
    425     oldstate = f->state;
    426 
    427     fsm_close(f, reason);
    428     if (oldstate == STOPPED && f->flags & (OPT_PASSIVE|OPT_SILENT|DELAYED_UP)) {
    429 	/*
    430 	 * This action is not strictly according to the FSM in RFC1548,
    431 	 * but it does mean that the program terminates if you do a
    432 	 * lcp_close() when a connection hasn't been established
    433 	 * because we are in passive/silent mode or because we have
    434 	 * delayed the fsm_lowerup() call and it hasn't happened yet.
    435 	 */
    436 	f->flags &= ~DELAYED_UP;
    437 	lcp_finished(f);
    438     }
    439 }
    440 
    441 
    442 /*
    443  * lcp_lowerup - The lower layer is up.
    444  */
    445 void
    446 lcp_lowerup(int unit)
    447 {
    448     lcp_options *wo = &lcp_wantoptions[unit];
    449     fsm *f = &lcp_fsm[unit];
    450 
    451     /*
    452      * Don't use A/C or protocol compression on transmission,
    453      * but accept A/C and protocol compressed packets
    454      * if we are going to ask for A/C and protocol compression.
    455      */
    456     if (ppp_send_config(unit, PPP_MRU, 0xffffffff, 0, 0) < 0
    457 	|| ppp_recv_config(unit, PPP_MRU, (lax_recv? 0: 0xffffffff),
    458 			   wo->neg_pcompression, wo->neg_accompression) < 0)
    459 	    return;
    460     peer_mru[unit] = PPP_MRU;
    461 
    462     if (listen_time != 0) {
    463 	f->flags |= DELAYED_UP;
    464 	ppp_timeout(lcp_delayed_up, f, 0, listen_time * 1000);
    465     } else
    466 	fsm_lowerup(f);
    467 }
    468 
    469 
    470 /*
    471  * lcp_lowerdown - The lower layer is down.
    472  */
    473 void
    474 lcp_lowerdown(int unit)
    475 {
    476     fsm *f = &lcp_fsm[unit];
    477 
    478     if (f->flags & DELAYED_UP) {
    479 	f->flags &= ~DELAYED_UP;
    480 	UNTIMEOUT(lcp_delayed_up, f);
    481     } else
    482 	fsm_lowerdown(&lcp_fsm[unit]);
    483 }
    484 
    485 
    486 /*
    487  * lcp_delayed_up - Bring the lower layer up now.
    488  */
    489 static void
    490 lcp_delayed_up(void *arg)
    491 {
    492     fsm *f = arg;
    493 
    494     if (f->flags & DELAYED_UP) {
    495 	f->flags &= ~DELAYED_UP;
    496 	fsm_lowerup(f);
    497     }
    498 }
    499 
    500 
    501 /*
    502  * lcp_input - Input LCP packet.
    503  */
    504 static void
    505 lcp_input(int unit, u_char *p, int len)
    506 {
    507     fsm *f = &lcp_fsm[unit];
    508 
    509     if (f->flags & DELAYED_UP) {
    510 	f->flags &= ~DELAYED_UP;
    511 	UNTIMEOUT(lcp_delayed_up, f);
    512 	fsm_lowerup(f);
    513     }
    514     fsm_input(f, p, len);
    515 }
    516 
    517 /*
    518  * lcp_extcode - Handle a LCP-specific code.
    519  */
    520 static int
    521 lcp_extcode(fsm *f, int code, int id, u_char *inp, int len)
    522 {
    523     u_char *magp;
    524 
    525     switch( code ){
    526     case PROTREJ:
    527 	lcp_rprotrej(f, inp, len);
    528 	break;
    529 
    530     case ECHOREQ:
    531 	if (f->state != OPENED)
    532 	    break;
    533 	magp = inp;
    534 	PUTLONG(lcp_gotoptions[f->unit].magicnumber, magp);
    535 	fsm_sdata(f, ECHOREP, id, inp, len);
    536 	break;
    537 
    538     case ECHOREP:
    539 	lcp_received_echo_reply(f, id, inp, len);
    540 	break;
    541 
    542     case DISCREQ:
    543     case IDENTIF:
    544     case TIMEREM:
    545 	break;
    546 
    547     default:
    548 	return 0;
    549     }
    550     return 1;
    551 }
    552 
    553 
    554 /*
    555  * lcp_rprotrej - Receive an Protocol-Reject.
    556  *
    557  * Figure out which protocol is rejected and inform it.
    558  */
    559 static void
    560 lcp_rprotrej(fsm *f, u_char *inp, int len)
    561 {
    562     int i;
    563     struct protent *protp;
    564     u_short prot;
    565     const char *pname;
    566 
    567     if (len < 2) {
    568 	LCPDEBUG(("lcp_rprotrej: Rcvd short Protocol-Reject packet!"));
    569 	return;
    570     }
    571 
    572     GETSHORT(prot, inp);
    573 
    574     /*
    575      * Protocol-Reject packets received in any state other than the LCP
    576      * OPENED state SHOULD be silently discarded.
    577      */
    578     if( f->state != OPENED ){
    579 	LCPDEBUG(("Protocol-Reject discarded: LCP in state %d", f->state));
    580 	return;
    581     }
    582 
    583     pname = protocol_name(prot);
    584 
    585     /*
    586      * Upcall the proper Protocol-Reject routine.
    587      */
    588     for (i = 0; (protp = protocols[i]) != NULL; ++i)
    589 	if (protp->protocol == prot && protp->enabled_flag) {
    590 	    if (pname == NULL)
    591 		dbglog("Protocol-Reject for 0x%x received", prot);
    592 	    else
    593 		dbglog("Protocol-Reject for '%s' (0x%x) received", pname,
    594 		       prot);
    595 	    (*protp->protrej)(f->unit);
    596 	    return;
    597 	}
    598 
    599     if (pname == NULL)
    600 	warn("Protocol-Reject for unsupported protocol 0x%x", prot);
    601     else
    602 	warn("Protocol-Reject for unsupported protocol '%s' (0x%x)", pname,
    603 	     prot);
    604 }
    605 
    606 
    607 /*
    608  * lcp_protrej - A Protocol-Reject was received.
    609  */
    610 /*ARGSUSED*/
    611 static void
    612 lcp_protrej(int unit)
    613 {
    614     /*
    615      * Can't reject LCP!
    616      */
    617     error("Received Protocol-Reject for LCP!");
    618     fsm_protreject(&lcp_fsm[unit]);
    619 }
    620 
    621 
    622 /*
    623  * lcp_sprotrej - Send a Protocol-Reject for some protocol.
    624  */
    625 void
    626 lcp_sprotrej(int unit, u_char *p, int len)
    627 {
    628     /*
    629      * Send back the protocol and the information field of the
    630      * rejected packet.  We only get here if LCP is in the OPENED state.
    631      */
    632     p += 2;
    633     len -= 2;
    634 
    635     fsm_sdata(&lcp_fsm[unit], PROTREJ, ++lcp_fsm[unit].id,
    636 	      p, len);
    637 }
    638 
    639 
    640 /*
    641  * lcp_resetci - Reset our CI.
    642  */
    643 static void
    644 lcp_resetci(fsm *f)
    645 {
    646     lcp_options *wo = &lcp_wantoptions[f->unit];
    647     lcp_options *go = &lcp_gotoptions[f->unit];
    648     lcp_options *ao = &lcp_allowoptions[f->unit];
    649 
    650     wo->magicnumber = magic();
    651     wo->numloops = 0;
    652     *go = *wo;
    653     if (!multilink) {
    654 	go->neg_mrru = 0;
    655 	go->neg_ssnhf = 0;
    656 	go->neg_endpoint = 0;
    657     }
    658     if (noendpoint)
    659 	ao->neg_endpoint = 0;
    660     peer_mru[f->unit] = PPP_MRU;
    661     auth_reset(f->unit);
    662 }
    663 
    664 
    665 /*
    666  * lcp_cilen - Return length of our CI.
    667  */
    668 static int
    669 lcp_cilen(fsm *f)
    670 {
    671     lcp_options *go = &lcp_gotoptions[f->unit];
    672 
    673 #define LENCIVOID(neg)	((neg) ? CILEN_VOID : 0)
    674 #define LENCICHAP(neg)	((neg) ? CILEN_CHAP : 0)
    675 #define LENCISHORT(neg)	((neg) ? CILEN_SHORT : 0)
    676 #define LENCILONG(neg)	((neg) ? CILEN_LONG : 0)
    677 #define LENCILQR(neg)	((neg) ? CILEN_LQR: 0)
    678 #define LENCICBCP(neg)	((neg) ? CILEN_CBCP: 0)
    679     /*
    680      * NB: we only ask for one of CHAP, UPAP, or EAP, even if we will
    681      * accept more than one.  We prefer EAP first, then CHAP, then
    682      * PAP.
    683      */
    684     return (LENCISHORT(go->neg_mru && go->mru != DEFMRU) +
    685 	    LENCILONG(go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) +
    686 	    LENCISHORT(go->neg_eap) +
    687 	    LENCICHAP(!go->neg_eap && go->neg_chap) +
    688 	    LENCISHORT(!go->neg_eap && !go->neg_chap && go->neg_upap) +
    689 	    LENCILQR(go->neg_lqr) +
    690 	    LENCICBCP(go->neg_cbcp) +
    691 	    LENCILONG(go->neg_magicnumber) +
    692 	    LENCIVOID(go->neg_pcompression) +
    693 	    LENCIVOID(go->neg_accompression) +
    694 	    LENCISHORT(go->neg_mrru) +
    695 	    LENCIVOID(go->neg_ssnhf) +
    696 	    (go->neg_endpoint? CILEN_CHAR + go->endpoint.length: 0));
    697 }
    698 
    699 
    700 /*
    701  * lcp_addci - Add our desired CIs to a packet.
    702  */
    703 static void
    704 lcp_addci(fsm *f, u_char *ucp, int *lenp)
    705 {
    706     lcp_options *go = &lcp_gotoptions[f->unit];
    707     u_char *start_ucp = ucp;
    708 
    709 #define ADDCIVOID(opt, neg) \
    710     if (neg) { \
    711 	PUTCHAR(opt, ucp); \
    712 	PUTCHAR(CILEN_VOID, ucp); \
    713     }
    714 #define ADDCISHORT(opt, neg, val) \
    715     if (neg) { \
    716 	PUTCHAR(opt, ucp); \
    717 	PUTCHAR(CILEN_SHORT, ucp); \
    718 	PUTSHORT(val, ucp); \
    719     }
    720 #define ADDCICHAP(opt, neg, val) \
    721     if (neg) { \
    722 	PUTCHAR((opt), ucp); \
    723 	PUTCHAR(CILEN_CHAP, ucp); \
    724 	PUTSHORT(PPP_CHAP, ucp); \
    725 	PUTCHAR((CHAP_DIGEST(val)), ucp); \
    726     }
    727 #define ADDCILONG(opt, neg, val) \
    728     if (neg) { \
    729 	PUTCHAR(opt, ucp); \
    730 	PUTCHAR(CILEN_LONG, ucp); \
    731 	PUTLONG(val, ucp); \
    732     }
    733 #define ADDCILQR(opt, neg, val) \
    734     if (neg) { \
    735 	PUTCHAR(opt, ucp); \
    736 	PUTCHAR(CILEN_LQR, ucp); \
    737 	PUTSHORT(PPP_LQR, ucp); \
    738 	PUTLONG(val, ucp); \
    739     }
    740 #define ADDCICHAR(opt, neg, val) \
    741     if (neg) { \
    742 	PUTCHAR(opt, ucp); \
    743 	PUTCHAR(CILEN_CHAR, ucp); \
    744 	PUTCHAR(val, ucp); \
    745     }
    746 #define ADDCIENDP(opt, neg, class, val, len) \
    747     if (neg) { \
    748 	int i; \
    749 	PUTCHAR(opt, ucp); \
    750 	PUTCHAR(CILEN_CHAR + len, ucp); \
    751 	PUTCHAR(class, ucp); \
    752 	for (i = 0; i < len; ++i) \
    753 	    PUTCHAR(val[i], ucp); \
    754     }
    755 
    756     ADDCISHORT(CI_MRU, go->neg_mru && go->mru != DEFMRU, go->mru);
    757     ADDCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF,
    758 	      go->asyncmap);
    759     ADDCISHORT(CI_AUTHTYPE, go->neg_eap, PPP_EAP);
    760     ADDCICHAP(CI_AUTHTYPE, !go->neg_eap && go->neg_chap, go->chap_mdtype);
    761     ADDCISHORT(CI_AUTHTYPE, !go->neg_eap && !go->neg_chap && go->neg_upap,
    762 	       PPP_PAP);
    763     ADDCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period);
    764     ADDCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT);
    765     ADDCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber);
    766     ADDCIVOID(CI_PCOMPRESSION, go->neg_pcompression);
    767     ADDCIVOID(CI_ACCOMPRESSION, go->neg_accompression);
    768     ADDCISHORT(CI_MRRU, go->neg_mrru, go->mrru);
    769     ADDCIVOID(CI_SSNHF, go->neg_ssnhf);
    770     ADDCIENDP(CI_EPDISC, go->neg_endpoint, go->endpoint.class,
    771 	      go->endpoint.value, go->endpoint.length);
    772 
    773     if (ucp - start_ucp != *lenp) {
    774 	/* this should never happen, because peer_mtu should be 1500 */
    775 	error("Bug in lcp_addci: wrong length");
    776     }
    777 }
    778 
    779 
    780 /*
    781  * lcp_ackci - Ack our CIs.
    782  * This should not modify any state if the Ack is bad.
    783  *
    784  * Returns:
    785  *	0 - Ack was bad.
    786  *	1 - Ack was good.
    787  */
    788 static int
    789 lcp_ackci(fsm *f, u_char *p, int len)
    790 {
    791     lcp_options *go = &lcp_gotoptions[f->unit];
    792     u_char cilen, citype, cichar;
    793     u_short cishort;
    794     u_int32_t cilong;
    795 
    796     /*
    797      * CIs must be in exactly the same order that we sent.
    798      * Check packet length and CI length at each step.
    799      * If we find any deviations, then this packet is bad.
    800      */
    801 #define ACKCIVOID(opt, neg) \
    802     if (neg) { \
    803 	if ((len -= CILEN_VOID) < 0) \
    804 	    goto bad; \
    805 	GETCHAR(citype, p); \
    806 	GETCHAR(cilen, p); \
    807 	if (cilen != CILEN_VOID || \
    808 	    citype != opt) \
    809 	    goto bad; \
    810     }
    811 #define ACKCISHORT(opt, neg, val) \
    812     if (neg) { \
    813 	if ((len -= CILEN_SHORT) < 0) \
    814 	    goto bad; \
    815 	GETCHAR(citype, p); \
    816 	GETCHAR(cilen, p); \
    817 	if (cilen != CILEN_SHORT || \
    818 	    citype != opt) \
    819 	    goto bad; \
    820 	GETSHORT(cishort, p); \
    821 	if (cishort != val) \
    822 	    goto bad; \
    823     }
    824 #define ACKCICHAR(opt, neg, val) \
    825     if (neg) { \
    826 	if ((len -= CILEN_CHAR) < 0) \
    827 	    goto bad; \
    828 	GETCHAR(citype, p); \
    829 	GETCHAR(cilen, p); \
    830 	if (cilen != CILEN_CHAR || \
    831 	    citype != opt) \
    832 	    goto bad; \
    833 	GETCHAR(cichar, p); \
    834 	if (cichar != val) \
    835 	    goto bad; \
    836     }
    837 #define ACKCICHAP(opt, neg, val) \
    838     if (neg) { \
    839 	if ((len -= CILEN_CHAP) < 0) \
    840 	    goto bad; \
    841 	GETCHAR(citype, p); \
    842 	GETCHAR(cilen, p); \
    843 	if (cilen != CILEN_CHAP || \
    844 	    citype != (opt)) \
    845 	    goto bad; \
    846 	GETSHORT(cishort, p); \
    847 	if (cishort != PPP_CHAP) \
    848 	    goto bad; \
    849 	GETCHAR(cichar, p); \
    850 	if (cichar != (CHAP_DIGEST(val))) \
    851 	  goto bad; \
    852     }
    853 #define ACKCILONG(opt, neg, val) \
    854     if (neg) { \
    855 	if ((len -= CILEN_LONG) < 0) \
    856 	    goto bad; \
    857 	GETCHAR(citype, p); \
    858 	GETCHAR(cilen, p); \
    859 	if (cilen != CILEN_LONG || \
    860 	    citype != opt) \
    861 	    goto bad; \
    862 	GETLONG(cilong, p); \
    863 	if (cilong != val) \
    864 	    goto bad; \
    865     }
    866 #define ACKCILQR(opt, neg, val) \
    867     if (neg) { \
    868 	if ((len -= CILEN_LQR) < 0) \
    869 	    goto bad; \
    870 	GETCHAR(citype, p); \
    871 	GETCHAR(cilen, p); \
    872 	if (cilen != CILEN_LQR || \
    873 	    citype != opt) \
    874 	    goto bad; \
    875 	GETSHORT(cishort, p); \
    876 	if (cishort != PPP_LQR) \
    877 	    goto bad; \
    878 	GETLONG(cilong, p); \
    879 	if (cilong != val) \
    880 	  goto bad; \
    881     }
    882 #define ACKCIENDP(opt, neg, class, val, vlen) \
    883     if (neg) { \
    884 	int i; \
    885 	if ((len -= CILEN_CHAR + vlen) < 0) \
    886 	    goto bad; \
    887 	GETCHAR(citype, p); \
    888 	GETCHAR(cilen, p); \
    889 	if (cilen != CILEN_CHAR + vlen || \
    890 	    citype != opt) \
    891 	    goto bad; \
    892 	GETCHAR(cichar, p); \
    893 	if (cichar != class) \
    894 	    goto bad; \
    895 	for (i = 0; i < vlen; ++i) { \
    896 	    GETCHAR(cichar, p); \
    897 	    if (cichar != val[i]) \
    898 		goto bad; \
    899 	} \
    900     }
    901 
    902     ACKCISHORT(CI_MRU, go->neg_mru && go->mru != DEFMRU, go->mru);
    903     ACKCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF,
    904 	      go->asyncmap);
    905     ACKCISHORT(CI_AUTHTYPE, go->neg_eap, PPP_EAP);
    906     ACKCICHAP(CI_AUTHTYPE, !go->neg_eap && go->neg_chap, go->chap_mdtype);
    907     ACKCISHORT(CI_AUTHTYPE, !go->neg_eap && !go->neg_chap && go->neg_upap,
    908 	       PPP_PAP);
    909     ACKCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period);
    910     ACKCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT);
    911     ACKCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber);
    912     ACKCIVOID(CI_PCOMPRESSION, go->neg_pcompression);
    913     ACKCIVOID(CI_ACCOMPRESSION, go->neg_accompression);
    914     ACKCISHORT(CI_MRRU, go->neg_mrru, go->mrru);
    915     ACKCIVOID(CI_SSNHF, go->neg_ssnhf);
    916     ACKCIENDP(CI_EPDISC, go->neg_endpoint, go->endpoint.class,
    917 	      go->endpoint.value, go->endpoint.length);
    918 
    919     /*
    920      * If there are any remaining CIs, then this packet is bad.
    921      */
    922     if (len != 0)
    923 	goto bad;
    924     return (1);
    925 bad:
    926     LCPDEBUG(("lcp_acki: received bad Ack!"));
    927     return (0);
    928 }
    929 
    930 
    931 /*
    932  * lcp_nakci - Peer has sent a NAK for some of our CIs.
    933  * This should not modify any state if the Nak is bad
    934  * or if LCP is in the OPENED state.
    935  *
    936  * Returns:
    937  *	0 - Nak was bad.
    938  *	1 - Nak was good.
    939  */
    940 static int
    941 lcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject)
    942 {
    943     lcp_options *go = &lcp_gotoptions[f->unit];
    944     lcp_options *wo = &lcp_wantoptions[f->unit];
    945     u_char citype, cichar, *next;
    946     u_short cishort;
    947     u_int32_t cilong;
    948     lcp_options no;		/* options we've seen Naks for */
    949     lcp_options try;		/* options to request next time */
    950     int looped_back = 0;
    951     int cilen;
    952 
    953     BZERO(&no, sizeof(no));
    954     try = *go;
    955 
    956     /*
    957      * Any Nak'd CIs must be in exactly the same order that we sent.
    958      * Check packet length and CI length at each step.
    959      * If we find any deviations, then this packet is bad.
    960      */
    961 #define NAKCIVOID(opt, neg) \
    962     if (go->neg && \
    963 	len >= CILEN_VOID && \
    964 	p[1] == CILEN_VOID && \
    965 	p[0] == opt) { \
    966 	len -= CILEN_VOID; \
    967 	INCPTR(CILEN_VOID, p); \
    968 	no.neg = 1; \
    969 	try.neg = 0; \
    970     }
    971 #define NAKCICHAP(opt, neg, code) \
    972     if (go->neg && \
    973 	len >= CILEN_CHAP && \
    974 	p[1] == CILEN_CHAP && \
    975 	p[0] == opt) { \
    976 	len -= CILEN_CHAP; \
    977 	INCPTR(2, p); \
    978 	GETSHORT(cishort, p); \
    979 	GETCHAR(cichar, p); \
    980 	no.neg = 1; \
    981 	code \
    982     }
    983 #define NAKCICHAR(opt, neg, code) \
    984     if (go->neg && \
    985 	len >= CILEN_CHAR && \
    986 	p[1] == CILEN_CHAR && \
    987 	p[0] == opt) { \
    988 	len -= CILEN_CHAR; \
    989 	INCPTR(2, p); \
    990 	GETCHAR(cichar, p); \
    991 	no.neg = 1; \
    992 	code \
    993     }
    994 #define NAKCISHORT(opt, neg, code) \
    995     if (go->neg && \
    996 	len >= CILEN_SHORT && \
    997 	p[1] == CILEN_SHORT && \
    998 	p[0] == opt) { \
    999 	len -= CILEN_SHORT; \
   1000 	INCPTR(2, p); \
   1001 	GETSHORT(cishort, p); \
   1002 	no.neg = 1; \
   1003 	code \
   1004     }
   1005 #define NAKCILONG(opt, neg, code) \
   1006     if (go->neg && \
   1007 	len >= CILEN_LONG && \
   1008 	p[1] == CILEN_LONG && \
   1009 	p[0] == opt) { \
   1010 	len -= CILEN_LONG; \
   1011 	INCPTR(2, p); \
   1012 	GETLONG(cilong, p); \
   1013 	no.neg = 1; \
   1014 	code \
   1015     }
   1016 #define NAKCILQR(opt, neg, code) \
   1017     if (go->neg && \
   1018 	len >= CILEN_LQR && \
   1019 	p[1] == CILEN_LQR && \
   1020 	p[0] == opt) { \
   1021 	len -= CILEN_LQR; \
   1022 	INCPTR(2, p); \
   1023 	GETSHORT(cishort, p); \
   1024 	GETLONG(cilong, p); \
   1025 	no.neg = 1; \
   1026 	code \
   1027     }
   1028 #define NAKCIENDP(opt, neg) \
   1029     if (go->neg && \
   1030 	len >= CILEN_CHAR && \
   1031 	p[0] == opt && \
   1032 	p[1] >= CILEN_CHAR && \
   1033 	p[1] <= len) { \
   1034 	len -= p[1]; \
   1035 	INCPTR(p[1], p); \
   1036 	no.neg = 1; \
   1037 	try.neg = 0; \
   1038     }
   1039 
   1040     /*
   1041      * NOTE!  There must be no assignments to individual fields of *go in
   1042      * the code below.  Any such assignment is a BUG!
   1043      */
   1044     /*
   1045      * We don't care if they want to send us smaller packets than
   1046      * we want.  Therefore, accept any MRU less than what we asked for,
   1047      * but then ignore the new value when setting the MRU in the kernel.
   1048      * If they send us a bigger MRU than what we asked, accept it, up to
   1049      * the limit of the default MRU we'd get if we didn't negotiate.
   1050      */
   1051     if (go->neg_mru && go->mru != DEFMRU) {
   1052 	NAKCISHORT(CI_MRU, neg_mru,
   1053 		   if (cishort <= wo->mru || cishort <= DEFMRU)
   1054 		       try.mru = cishort;
   1055 		   );
   1056     }
   1057 
   1058     /*
   1059      * Add any characters they want to our (receive-side) asyncmap.
   1060      */
   1061     if (go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) {
   1062 	NAKCILONG(CI_ASYNCMAP, neg_asyncmap,
   1063 		  try.asyncmap = go->asyncmap | cilong;
   1064 		  );
   1065     }
   1066 
   1067     /*
   1068      * If they've nak'd our authentication-protocol, check whether
   1069      * they are proposing a different protocol, or a different
   1070      * hash algorithm for CHAP.
   1071      */
   1072     if ((go->neg_chap || go->neg_upap || go->neg_eap)
   1073 	&& len >= CILEN_SHORT
   1074 	&& p[0] == CI_AUTHTYPE && p[1] >= CILEN_SHORT && p[1] <= len) {
   1075 	cilen = p[1];
   1076 	len -= cilen;
   1077 	no.neg_chap = go->neg_chap;
   1078 	no.neg_upap = go->neg_upap;
   1079 	no.neg_eap = go->neg_eap;
   1080 	INCPTR(2, p);
   1081 	GETSHORT(cishort, p);
   1082 	if (cishort == PPP_PAP && cilen == CILEN_SHORT) {
   1083 	    /* If we were asking for EAP, then we need to stop that. */
   1084 	    if (go->neg_eap)
   1085 		try.neg_eap = 0;
   1086 
   1087 	    /* If we were asking for CHAP, then we need to stop that. */
   1088 	    else if (go->neg_chap)
   1089 		try.neg_chap = 0;
   1090 	    /*
   1091 	     * If we weren't asking for CHAP or EAP, then we were asking for
   1092 	     * PAP, in which case this Nak is bad.
   1093 	     */
   1094 	    else
   1095 		goto bad;
   1096 
   1097 	} else if (cishort == PPP_CHAP && cilen == CILEN_CHAP) {
   1098 	    GETCHAR(cichar, p);
   1099 	    /* Stop asking for EAP, if we were. */
   1100 	    if (go->neg_eap) {
   1101 		try.neg_eap = 0;
   1102 		/* Try to set up to use their suggestion, if possible */
   1103 		if (CHAP_CANDIGEST(go->chap_mdtype, cichar))
   1104 		    try.chap_mdtype = CHAP_MDTYPE_D(cichar);
   1105 	    } else if (go->neg_chap) {
   1106 		/*
   1107 		 * We were asking for our preferred algorithm, they must
   1108 		 * want something different.
   1109 		 */
   1110 		if (cichar != CHAP_DIGEST(go->chap_mdtype)) {
   1111 		    if (CHAP_CANDIGEST(go->chap_mdtype, cichar)) {
   1112 			/* Use their suggestion if we support it ... */
   1113 			try.chap_mdtype = CHAP_MDTYPE_D(cichar);
   1114 		    } else {
   1115 			/* ... otherwise, try our next-preferred algorithm. */
   1116 			try.chap_mdtype &= ~(CHAP_MDTYPE(try.chap_mdtype));
   1117 			if (try.chap_mdtype == MDTYPE_NONE) /* out of algos */
   1118 			    try.neg_chap = 0;
   1119 		    }
   1120 		} else {
   1121 		    /*
   1122 		     * Whoops, they Nak'd our algorithm of choice
   1123 		     * but then suggested it back to us.
   1124 		     */
   1125 		    goto bad;
   1126 		}
   1127 	    } else {
   1128 		/*
   1129 		 * Stop asking for PAP if we were asking for it.
   1130 		 */
   1131 		try.neg_upap = 0;
   1132 	    }
   1133 
   1134 	} else {
   1135 
   1136 	    /*
   1137 	     * If we were asking for EAP, and they're Conf-Naking EAP,
   1138 	     * well, that's just strange.  Nobody should do that.
   1139 	     */
   1140 	    if (cishort == PPP_EAP && cilen == CILEN_SHORT && go->neg_eap)
   1141 		dbglog("Unexpected Conf-Nak for EAP");
   1142 
   1143 	    /*
   1144 	     * We don't recognize what they're suggesting.
   1145 	     * Stop asking for what we were asking for.
   1146 	     */
   1147 	    if (go->neg_eap)
   1148 		try.neg_eap = 0;
   1149 	    else if (go->neg_chap)
   1150 		try.neg_chap = 0;
   1151 	    else
   1152 		try.neg_upap = 0;
   1153 	    p += cilen - CILEN_SHORT;
   1154 	}
   1155     }
   1156 
   1157     /*
   1158      * If they can't cope with our link quality protocol, we'll have
   1159      * to stop asking for LQR.  We haven't got any other protocol.
   1160      * If they Nak the reporting period, take their value XXX ?
   1161      */
   1162     NAKCILQR(CI_QUALITY, neg_lqr,
   1163 	     if (cishort != PPP_LQR)
   1164 		 try.neg_lqr = 0;
   1165 	     else
   1166 		 try.lqr_period = cilong;
   1167 	     );
   1168 
   1169     /*
   1170      * Only implementing CBCP...not the rest of the callback options
   1171      */
   1172     NAKCICHAR(CI_CALLBACK, neg_cbcp,
   1173               try.neg_cbcp = 0;
   1174               );
   1175 
   1176     /*
   1177      * Check for a looped-back line.
   1178      */
   1179     NAKCILONG(CI_MAGICNUMBER, neg_magicnumber,
   1180 	      try.magicnumber = magic();
   1181 	      looped_back = 1;
   1182 	      );
   1183 
   1184     /*
   1185      * Peer shouldn't send Nak for protocol compression or
   1186      * address/control compression requests; they should send
   1187      * a Reject instead.  If they send a Nak, treat it as a Reject.
   1188      */
   1189     NAKCIVOID(CI_PCOMPRESSION, neg_pcompression);
   1190     NAKCIVOID(CI_ACCOMPRESSION, neg_accompression);
   1191 
   1192     /*
   1193      * Nak for MRRU option - accept their value if it is smaller
   1194      * than the one we want.
   1195      */
   1196     if (go->neg_mrru) {
   1197 	NAKCISHORT(CI_MRRU, neg_mrru,
   1198 		   if (treat_as_reject)
   1199 		       try.neg_mrru = 0;
   1200 		   else if (cishort <= wo->mrru)
   1201 		       try.mrru = cishort;
   1202 		   );
   1203     }
   1204 
   1205     /*
   1206      * Nak for short sequence numbers shouldn't be sent, treat it
   1207      * like a reject.
   1208      */
   1209     NAKCIVOID(CI_SSNHF, neg_ssnhf);
   1210 
   1211     /*
   1212      * Nak of the endpoint discriminator option is not permitted,
   1213      * treat it like a reject.
   1214      */
   1215     NAKCIENDP(CI_EPDISC, neg_endpoint);
   1216 
   1217     /*
   1218      * There may be remaining CIs, if the peer is requesting negotiation
   1219      * on an option that we didn't include in our request packet.
   1220      * If we see an option that we requested, or one we've already seen
   1221      * in this packet, then this packet is bad.
   1222      * If we wanted to respond by starting to negotiate on the requested
   1223      * option(s), we could, but we don't, because except for the
   1224      * authentication type and quality protocol, if we are not negotiating
   1225      * an option, it is because we were told not to.
   1226      * For the authentication type, the Nak from the peer means
   1227      * `let me authenticate myself with you' which is a bit pointless.
   1228      * For the quality protocol, the Nak means `ask me to send you quality
   1229      * reports', but if we didn't ask for them, we don't want them.
   1230      * An option we don't recognize represents the peer asking to
   1231      * negotiate some option we don't support, so ignore it.
   1232      */
   1233     while (len >= CILEN_VOID) {
   1234 	GETCHAR(citype, p);
   1235 	GETCHAR(cilen, p);
   1236 	if (cilen < CILEN_VOID || (len -= cilen) < 0)
   1237 	    goto bad;
   1238 	next = p + cilen - 2;
   1239 
   1240 	switch (citype) {
   1241 	case CI_MRU:
   1242 	    if ((go->neg_mru && go->mru != DEFMRU)
   1243 		|| no.neg_mru || cilen != CILEN_SHORT)
   1244 		goto bad;
   1245 	    GETSHORT(cishort, p);
   1246 	    if (cishort < DEFMRU) {
   1247 		try.neg_mru = 1;
   1248 		try.mru = cishort;
   1249 	    }
   1250 	    break;
   1251 	case CI_ASYNCMAP:
   1252 	    if ((go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF)
   1253 		|| no.neg_asyncmap || cilen != CILEN_LONG)
   1254 		goto bad;
   1255 	    break;
   1256 	case CI_AUTHTYPE:
   1257 	    if (go->neg_chap || no.neg_chap || go->neg_upap || no.neg_upap ||
   1258 		go->neg_eap || no.neg_eap)
   1259 		goto bad;
   1260 	    break;
   1261 	case CI_MAGICNUMBER:
   1262 	    if (go->neg_magicnumber || no.neg_magicnumber ||
   1263 		cilen != CILEN_LONG)
   1264 		goto bad;
   1265 	    break;
   1266 	case CI_PCOMPRESSION:
   1267 	    if (go->neg_pcompression || no.neg_pcompression
   1268 		|| cilen != CILEN_VOID)
   1269 		goto bad;
   1270 	    break;
   1271 	case CI_ACCOMPRESSION:
   1272 	    if (go->neg_accompression || no.neg_accompression
   1273 		|| cilen != CILEN_VOID)
   1274 		goto bad;
   1275 	    break;
   1276 	case CI_QUALITY:
   1277 	    if (go->neg_lqr || no.neg_lqr || cilen != CILEN_LQR)
   1278 		goto bad;
   1279 	    break;
   1280 	case CI_MRRU:
   1281 	    if (go->neg_mrru || no.neg_mrru || cilen != CILEN_SHORT)
   1282 		goto bad;
   1283 	    break;
   1284 	case CI_SSNHF:
   1285 	    if (go->neg_ssnhf || no.neg_ssnhf || cilen != CILEN_VOID)
   1286 		goto bad;
   1287 	    try.neg_ssnhf = 1;
   1288 	    break;
   1289 	case CI_EPDISC:
   1290 	    if (go->neg_endpoint || no.neg_endpoint || cilen < CILEN_CHAR)
   1291 		goto bad;
   1292 	    break;
   1293 	}
   1294 	p = next;
   1295     }
   1296 
   1297     /*
   1298      * OK, the Nak is good.  Now we can update state.
   1299      * If there are any options left we ignore them.
   1300      */
   1301     if (f->state != OPENED) {
   1302 	if (looped_back) {
   1303 	    if (++try.numloops >= lcp_loopbackfail) {
   1304 		notice("Serial line is looped back.");
   1305 		ppp_set_status(EXIT_LOOPBACK);
   1306 		lcp_close(f->unit, "Loopback detected");
   1307 	    }
   1308 	} else
   1309 	    try.numloops = 0;
   1310 	*go = try;
   1311     }
   1312 
   1313     return 1;
   1314 
   1315 bad:
   1316     LCPDEBUG(("lcp_nakci: received bad Nak!"));
   1317     return 0;
   1318 }
   1319 
   1320 
   1321 /*
   1322  * lcp_rejci - Peer has Rejected some of our CIs.
   1323  * This should not modify any state if the Reject is bad
   1324  * or if LCP is in the OPENED state.
   1325  *
   1326  * Returns:
   1327  *	0 - Reject was bad.
   1328  *	1 - Reject was good.
   1329  */
   1330 static int
   1331 lcp_rejci(fsm *f, u_char *p, int len)
   1332 {
   1333     lcp_options *go = &lcp_gotoptions[f->unit];
   1334     u_char cichar;
   1335     u_short cishort;
   1336     u_int32_t cilong;
   1337     lcp_options try;		/* options to request next time */
   1338 
   1339     try = *go;
   1340 
   1341     /*
   1342      * Any Rejected CIs must be in exactly the same order that we sent.
   1343      * Check packet length and CI length at each step.
   1344      * If we find any deviations, then this packet is bad.
   1345      */
   1346 #define REJCIVOID(opt, neg) \
   1347     if (go->neg && \
   1348 	len >= CILEN_VOID && \
   1349 	p[1] == CILEN_VOID && \
   1350 	p[0] == opt) { \
   1351 	len -= CILEN_VOID; \
   1352 	INCPTR(CILEN_VOID, p); \
   1353 	try.neg = 0; \
   1354     }
   1355 #define REJCISHORT(opt, neg, val) \
   1356     if (go->neg && \
   1357 	len >= CILEN_SHORT && \
   1358 	p[1] == CILEN_SHORT && \
   1359 	p[0] == opt) { \
   1360 	len -= CILEN_SHORT; \
   1361 	INCPTR(2, p); \
   1362 	GETSHORT(cishort, p); \
   1363 	/* Check rejected value. */ \
   1364 	if (cishort != val) \
   1365 	    goto bad; \
   1366 	try.neg = 0; \
   1367     }
   1368 #define REJCICHAP(opt, neg, val) \
   1369     if (go->neg && \
   1370 	len >= CILEN_CHAP && \
   1371 	p[1] == CILEN_CHAP && \
   1372 	p[0] == opt) { \
   1373 	len -= CILEN_CHAP; \
   1374 	INCPTR(2, p); \
   1375 	GETSHORT(cishort, p); \
   1376 	GETCHAR(cichar, p); \
   1377 	/* Check rejected value. */ \
   1378 	if ((cishort != PPP_CHAP) || (cichar != (CHAP_DIGEST(val)))) \
   1379 	    goto bad; \
   1380 	try.neg = 0; \
   1381 	try.neg_eap = try.neg_upap = 0; \
   1382     }
   1383 #define REJCILONG(opt, neg, val) \
   1384     if (go->neg && \
   1385 	len >= CILEN_LONG && \
   1386 	p[1] == CILEN_LONG && \
   1387 	p[0] == opt) { \
   1388 	len -= CILEN_LONG; \
   1389 	INCPTR(2, p); \
   1390 	GETLONG(cilong, p); \
   1391 	/* Check rejected value. */ \
   1392 	if (cilong != val) \
   1393 	    goto bad; \
   1394 	try.neg = 0; \
   1395     }
   1396 #define REJCILQR(opt, neg, val) \
   1397     if (go->neg && \
   1398 	len >= CILEN_LQR && \
   1399 	p[1] == CILEN_LQR && \
   1400 	p[0] == opt) { \
   1401 	len -= CILEN_LQR; \
   1402 	INCPTR(2, p); \
   1403 	GETSHORT(cishort, p); \
   1404 	GETLONG(cilong, p); \
   1405 	/* Check rejected value. */ \
   1406 	if (cishort != PPP_LQR || cilong != val) \
   1407 	    goto bad; \
   1408 	try.neg = 0; \
   1409     }
   1410 #define REJCICBCP(opt, neg, val) \
   1411     if (go->neg && \
   1412 	len >= CILEN_CBCP && \
   1413 	p[1] == CILEN_CBCP && \
   1414 	p[0] == opt) { \
   1415 	len -= CILEN_CBCP; \
   1416 	INCPTR(2, p); \
   1417 	GETCHAR(cichar, p); \
   1418 	/* Check rejected value. */ \
   1419 	if (cichar != val) \
   1420 	    goto bad; \
   1421 	try.neg = 0; \
   1422     }
   1423 #define REJCIENDP(opt, neg, class, val, vlen) \
   1424     if (go->neg && \
   1425 	len >= CILEN_CHAR + vlen && \
   1426 	p[0] == opt && \
   1427 	p[1] == CILEN_CHAR + vlen) { \
   1428 	int i; \
   1429 	len -= CILEN_CHAR + vlen; \
   1430 	INCPTR(2, p); \
   1431 	GETCHAR(cichar, p); \
   1432 	if (cichar != class) \
   1433 	    goto bad; \
   1434 	for (i = 0; i < vlen; ++i) { \
   1435 	    GETCHAR(cichar, p); \
   1436 	    if (cichar != val[i]) \
   1437 		goto bad; \
   1438 	} \
   1439 	try.neg = 0; \
   1440     }
   1441 
   1442     REJCISHORT(CI_MRU, neg_mru, go->mru);
   1443     REJCILONG(CI_ASYNCMAP, neg_asyncmap, go->asyncmap);
   1444     REJCISHORT(CI_AUTHTYPE, neg_eap, PPP_EAP);
   1445     if (!go->neg_eap) {
   1446 	REJCICHAP(CI_AUTHTYPE, neg_chap, go->chap_mdtype);
   1447 	if (!go->neg_chap) {
   1448 	    REJCISHORT(CI_AUTHTYPE, neg_upap, PPP_PAP);
   1449 	}
   1450     }
   1451     REJCILQR(CI_QUALITY, neg_lqr, go->lqr_period);
   1452     REJCICBCP(CI_CALLBACK, neg_cbcp, CBCP_OPT);
   1453     REJCILONG(CI_MAGICNUMBER, neg_magicnumber, go->magicnumber);
   1454     REJCIVOID(CI_PCOMPRESSION, neg_pcompression);
   1455     REJCIVOID(CI_ACCOMPRESSION, neg_accompression);
   1456     REJCISHORT(CI_MRRU, neg_mrru, go->mrru);
   1457     REJCIVOID(CI_SSNHF, neg_ssnhf);
   1458     REJCIENDP(CI_EPDISC, neg_endpoint, go->endpoint.class,
   1459 	      go->endpoint.value, go->endpoint.length);
   1460 
   1461     /*
   1462      * If there are any remaining CIs, then this packet is bad.
   1463      */
   1464     if (len != 0)
   1465 	goto bad;
   1466     /*
   1467      * Now we can update state.
   1468      */
   1469     if (f->state != OPENED)
   1470 	*go = try;
   1471     return 1;
   1472 
   1473 bad:
   1474     LCPDEBUG(("lcp_rejci: received bad Reject!"));
   1475     return 0;
   1476 }
   1477 
   1478 
   1479 /*
   1480  * lcp_reqci - Check the peer's requested CIs and send appropriate response.
   1481  *
   1482  * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified
   1483  * appropriately.  If reject_if_disagree is non-zero, doesn't return
   1484  * CONFNAK; returns CONFREJ if it can't return CONFACK.
   1485  */
   1486 static int
   1487 lcp_reqci(fsm *f, u_char *inp, int *lenp, int reject_if_disagree)
   1488 {
   1489     lcp_options *go = &lcp_gotoptions[f->unit];
   1490     lcp_options *ho = &lcp_hisoptions[f->unit];
   1491     lcp_options *ao = &lcp_allowoptions[f->unit];
   1492     u_char *cip, *next;		/* Pointer to current and next CIs */
   1493     int cilen, citype, cichar;	/* Parsed len, type, char value */
   1494     u_short cishort;		/* Parsed short value */
   1495     u_int32_t cilong;		/* Parse long value */
   1496     int rc = CONFACK;		/* Final packet return code */
   1497     int orc;			/* Individual option return code */
   1498     u_char *p;			/* Pointer to next char to parse */
   1499     u_char *rejp;		/* Pointer to next char in reject frame */
   1500     u_char *nakp;		/* Pointer to next char in Nak frame */
   1501     int l = *lenp;		/* Length left */
   1502 
   1503     /*
   1504      * Reset all his options.
   1505      */
   1506     BZERO(ho, sizeof(*ho));
   1507 
   1508     /*
   1509      * Process all his options.
   1510      */
   1511     next = inp;
   1512     nakp = nak_buffer;
   1513     rejp = inp;
   1514     while (l) {
   1515 	orc = CONFACK;			/* Assume success */
   1516 	cip = p = next;			/* Remember begining of CI */
   1517 	if (l < 2 ||			/* Not enough data for CI header or */
   1518 	    p[1] < 2 ||			/*  CI length too small or */
   1519 	    p[1] > l) {			/*  CI length too big? */
   1520 	    LCPDEBUG(("lcp_reqci: bad CI length!"));
   1521 	    orc = CONFREJ;		/* Reject bad CI */
   1522 	    cilen = l;			/* Reject till end of packet */
   1523 	    l = 0;			/* Don't loop again */
   1524 	    citype = 0;
   1525 	    goto endswitch;
   1526 	}
   1527 	GETCHAR(citype, p);		/* Parse CI type */
   1528 	GETCHAR(cilen, p);		/* Parse CI length */
   1529 	l -= cilen;			/* Adjust remaining length */
   1530 	next += cilen;			/* Step to next CI */
   1531 
   1532 	switch (citype) {		/* Check CI type */
   1533 	case CI_MRU:
   1534 	    if (!ao->neg_mru ||		/* Allow option? */
   1535 		cilen != CILEN_SHORT) {	/* Check CI length */
   1536 		orc = CONFREJ;		/* Reject CI */
   1537 		break;
   1538 	    }
   1539 	    GETSHORT(cishort, p);	/* Parse MRU */
   1540 
   1541 	    /*
   1542 	     * He must be able to receive at least our minimum.
   1543 	     * No need to check a maximum.  If he sends a large number,
   1544 	     * we'll just ignore it.
   1545 	     */
   1546 	    if (cishort < MINMRU) {
   1547 		orc = CONFNAK;		/* Nak CI */
   1548 		PUTCHAR(CI_MRU, nakp);
   1549 		PUTCHAR(CILEN_SHORT, nakp);
   1550 		PUTSHORT(MINMRU, nakp);	/* Give him a hint */
   1551 		break;
   1552 	    }
   1553 	    ho->neg_mru = 1;		/* Remember he sent MRU */
   1554 	    ho->mru = cishort;		/* And remember value */
   1555 	    break;
   1556 
   1557 	case CI_ASYNCMAP:
   1558 	    if (!ao->neg_asyncmap ||
   1559 		cilen != CILEN_LONG) {
   1560 		orc = CONFREJ;
   1561 		break;
   1562 	    }
   1563 	    GETLONG(cilong, p);
   1564 
   1565 	    /*
   1566 	     * Asyncmap must have set at least the bits
   1567 	     * which are set in lcp_allowoptions[unit].asyncmap.
   1568 	     */
   1569 	    if ((ao->asyncmap & ~cilong) != 0) {
   1570 		orc = CONFNAK;
   1571 		PUTCHAR(CI_ASYNCMAP, nakp);
   1572 		PUTCHAR(CILEN_LONG, nakp);
   1573 		PUTLONG(ao->asyncmap | cilong, nakp);
   1574 		break;
   1575 	    }
   1576 	    ho->neg_asyncmap = 1;
   1577 	    ho->asyncmap = cilong;
   1578 	    break;
   1579 
   1580 	case CI_AUTHTYPE:
   1581 	    if (cilen < CILEN_SHORT ||
   1582 		!(ao->neg_upap || ao->neg_chap || ao->neg_eap)) {
   1583 		/*
   1584 		 * Reject the option if we're not willing to authenticate.
   1585 		 */
   1586 		dbglog("No auth is possible");
   1587 		orc = CONFREJ;
   1588 		break;
   1589 	    }
   1590 	    GETSHORT(cishort, p);
   1591 
   1592 	    /*
   1593 	     * Authtype must be PAP, CHAP, or EAP.
   1594 	     *
   1595 	     * Note: if more than one of ao->neg_upap, ao->neg_chap, and
   1596 	     * ao->neg_eap are set, and the peer sends a Configure-Request
   1597 	     * with two or more authenticate-protocol requests, then we will
   1598 	     * reject the second request.
   1599 	     * Whether we end up doing CHAP, UPAP, or EAP depends then on
   1600 	     * the ordering of the CIs in the peer's Configure-Request.
   1601              */
   1602 
   1603 	    if (cishort == PPP_PAP) {
   1604 		/* we've already accepted CHAP or EAP */
   1605 		if (ho->neg_chap || ho->neg_eap ||
   1606 		    cilen != CILEN_SHORT) {
   1607 		    LCPDEBUG(("lcp_reqci: rcvd AUTHTYPE PAP, rejecting..."));
   1608 		    orc = CONFREJ;
   1609 		    break;
   1610 		}
   1611 		if (!ao->neg_upap) {	/* we don't want to do PAP */
   1612 		    orc = CONFNAK;	/* NAK it and suggest CHAP or EAP */
   1613 		    PUTCHAR(CI_AUTHTYPE, nakp);
   1614 		    if (ao->neg_eap) {
   1615 			PUTCHAR(CILEN_SHORT, nakp);
   1616 			PUTSHORT(PPP_EAP, nakp);
   1617 		    } else {
   1618 			PUTCHAR(CILEN_CHAP, nakp);
   1619 			PUTSHORT(PPP_CHAP, nakp);
   1620 			PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakp);
   1621 		    }
   1622 		    break;
   1623 		}
   1624 		ho->neg_upap = 1;
   1625 		break;
   1626 	    }
   1627 	    if (cishort == PPP_CHAP) {
   1628 		/* we've already accepted PAP or EAP */
   1629 		if (ho->neg_upap || ho->neg_eap ||
   1630 		    cilen != CILEN_CHAP) {
   1631 		    LCPDEBUG(("lcp_reqci: rcvd AUTHTYPE CHAP, rejecting..."));
   1632 		    orc = CONFREJ;
   1633 		    break;
   1634 		}
   1635 		if (!ao->neg_chap) {	/* we don't want to do CHAP */
   1636 		    orc = CONFNAK;	/* NAK it and suggest EAP or PAP */
   1637 		    PUTCHAR(CI_AUTHTYPE, nakp);
   1638 		    PUTCHAR(CILEN_SHORT, nakp);
   1639 		    if (ao->neg_eap) {
   1640 			PUTSHORT(PPP_EAP, nakp);
   1641 		    } else {
   1642 			PUTSHORT(PPP_PAP, nakp);
   1643 		    }
   1644 		    break;
   1645 		}
   1646 		GETCHAR(cichar, p);	/* get digest type */
   1647 		if (!(CHAP_CANDIGEST(ao->chap_mdtype, cichar))) {
   1648 		    /*
   1649 		     * We can't/won't do the requested type,
   1650 		     * suggest something else.
   1651 		     */
   1652 		    orc = CONFNAK;
   1653 		    PUTCHAR(CI_AUTHTYPE, nakp);
   1654 		    PUTCHAR(CILEN_CHAP, nakp);
   1655 		    PUTSHORT(PPP_CHAP, nakp);
   1656 		    PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakp);
   1657 		    break;
   1658 		}
   1659 		ho->chap_mdtype = CHAP_MDTYPE_D(cichar); /* save md type */
   1660 		ho->neg_chap = 1;
   1661 		break;
   1662 	    }
   1663 	    if (cishort == PPP_EAP) {
   1664 		/* we've already accepted CHAP or PAP */
   1665 		if (ho->neg_chap || ho->neg_upap || cilen != CILEN_SHORT) {
   1666 		    LCPDEBUG(("lcp_reqci: rcvd AUTHTYPE EAP, rejecting..."));
   1667 		    orc = CONFREJ;
   1668 		    break;
   1669 		}
   1670 		if (!ao->neg_eap) {	/* we don't want to do EAP */
   1671 		    orc = CONFNAK;	/* NAK it and suggest CHAP or PAP */
   1672 		    PUTCHAR(CI_AUTHTYPE, nakp);
   1673 		    if (ao->neg_chap) {
   1674 			PUTCHAR(CILEN_CHAP, nakp);
   1675 			PUTSHORT(PPP_CHAP, nakp);
   1676 			PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakp);
   1677 		    } else {
   1678 			PUTCHAR(CILEN_SHORT, nakp);
   1679 			PUTSHORT(PPP_PAP, nakp);
   1680 		    }
   1681 		    break;
   1682 		}
   1683 		ho->neg_eap = 1;
   1684 		break;
   1685 	    }
   1686 
   1687 	    /*
   1688 	     * We don't recognize the protocol they're asking for.
   1689 	     * Nak it with something we're willing to do.
   1690 	     * (At this point we know ao->neg_upap || ao->neg_chap ||
   1691 	     * ao->neg_eap.)
   1692 	     */
   1693 	    orc = CONFNAK;
   1694 	    PUTCHAR(CI_AUTHTYPE, nakp);
   1695 	    if (ao->neg_eap) {
   1696 		PUTCHAR(CILEN_SHORT, nakp);
   1697 		PUTSHORT(PPP_EAP, nakp);
   1698 	    } else if (ao->neg_chap) {
   1699 		PUTCHAR(CILEN_CHAP, nakp);
   1700 		PUTSHORT(PPP_CHAP, nakp);
   1701 		PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakp);
   1702 	    } else {
   1703 		PUTCHAR(CILEN_SHORT, nakp);
   1704 		PUTSHORT(PPP_PAP, nakp);
   1705 	    }
   1706 	    break;
   1707 
   1708 	case CI_QUALITY:
   1709 	    if (!ao->neg_lqr ||
   1710 		cilen != CILEN_LQR) {
   1711 		orc = CONFREJ;
   1712 		break;
   1713 	    }
   1714 
   1715 	    GETSHORT(cishort, p);
   1716 	    GETLONG(cilong, p);
   1717 
   1718 	    /*
   1719 	     * Check the protocol and the reporting period.
   1720 	     * XXX When should we Nak this, and what with?
   1721 	     */
   1722 	    if (cishort != PPP_LQR) {
   1723 		orc = CONFNAK;
   1724 		PUTCHAR(CI_QUALITY, nakp);
   1725 		PUTCHAR(CILEN_LQR, nakp);
   1726 		PUTSHORT(PPP_LQR, nakp);
   1727 		PUTLONG(ao->lqr_period, nakp);
   1728 		break;
   1729 	    }
   1730 	    break;
   1731 
   1732 	case CI_MAGICNUMBER:
   1733 	    if (!(ao->neg_magicnumber || go->neg_magicnumber) ||
   1734 		cilen != CILEN_LONG) {
   1735 		orc = CONFREJ;
   1736 		break;
   1737 	    }
   1738 	    GETLONG(cilong, p);
   1739 
   1740 	    /*
   1741 	     * He must have a different magic number.
   1742 	     */
   1743 	    if (go->neg_magicnumber &&
   1744 		cilong == go->magicnumber) {
   1745 		cilong = magic();	/* Don't put magic() inside macro! */
   1746 		orc = CONFNAK;
   1747 		PUTCHAR(CI_MAGICNUMBER, nakp);
   1748 		PUTCHAR(CILEN_LONG, nakp);
   1749 		PUTLONG(cilong, nakp);
   1750 		break;
   1751 	    }
   1752 	    ho->neg_magicnumber = 1;
   1753 	    ho->magicnumber = cilong;
   1754 	    break;
   1755 
   1756 
   1757 	case CI_PCOMPRESSION:
   1758 	    if (!ao->neg_pcompression ||
   1759 		cilen != CILEN_VOID) {
   1760 		orc = CONFREJ;
   1761 		break;
   1762 	    }
   1763 	    ho->neg_pcompression = 1;
   1764 	    break;
   1765 
   1766 	case CI_ACCOMPRESSION:
   1767 	    if (!ao->neg_accompression ||
   1768 		cilen != CILEN_VOID) {
   1769 		orc = CONFREJ;
   1770 		break;
   1771 	    }
   1772 	    ho->neg_accompression = 1;
   1773 	    break;
   1774 
   1775 	case CI_MRRU:
   1776 	    if (!ao->neg_mrru || !multilink ||
   1777 		cilen != CILEN_SHORT) {
   1778 		orc = CONFREJ;
   1779 		break;
   1780 	    }
   1781 
   1782 	    GETSHORT(cishort, p);
   1783 	    /* possibly should insist on a minimum/maximum MRRU here */
   1784 	    ho->neg_mrru = 1;
   1785 	    ho->mrru = cishort;
   1786 	    break;
   1787 
   1788 	case CI_SSNHF:
   1789 	    if (!ao->neg_ssnhf || !multilink ||
   1790 		cilen != CILEN_VOID) {
   1791 		orc = CONFREJ;
   1792 		break;
   1793 	    }
   1794 	    ho->neg_ssnhf = 1;
   1795 	    break;
   1796 
   1797 	case CI_EPDISC:
   1798 	    if (!ao->neg_endpoint ||
   1799 		cilen < CILEN_CHAR ||
   1800 		cilen > CILEN_CHAR + MAX_ENDP_LEN) {
   1801 		orc = CONFREJ;
   1802 		break;
   1803 	    }
   1804 	    GETCHAR(cichar, p);
   1805 	    cilen -= CILEN_CHAR;
   1806 	    ho->neg_endpoint = 1;
   1807 	    ho->endpoint.class = cichar;
   1808 	    ho->endpoint.length = cilen;
   1809 	    BCOPY(p, ho->endpoint.value, cilen);
   1810 	    INCPTR(cilen, p);
   1811 	    break;
   1812 
   1813 	default:
   1814 	    LCPDEBUG(("lcp_reqci: rcvd unknown option %d", citype));
   1815 	    orc = CONFREJ;
   1816 	    break;
   1817 	}
   1818 
   1819 endswitch:
   1820 	if (orc == CONFACK &&		/* Good CI */
   1821 	    rc != CONFACK)		/*  but prior CI wasnt? */
   1822 	    continue;			/* Don't send this one */
   1823 
   1824 	if (orc == CONFNAK) {		/* Nak this CI? */
   1825 	    if (reject_if_disagree	/* Getting fed up with sending NAKs? */
   1826 		&& citype != CI_MAGICNUMBER) {
   1827 		orc = CONFREJ;		/* Get tough if so */
   1828 	    } else {
   1829 		if (rc == CONFREJ)	/* Rejecting prior CI? */
   1830 		    continue;		/* Don't send this one */
   1831 		rc = CONFNAK;
   1832 	    }
   1833 	}
   1834 	if (orc == CONFREJ) {		/* Reject this CI */
   1835 	    rc = CONFREJ;
   1836 	    if (cip != rejp)		/* Need to move rejected CI? */
   1837 		BCOPY(cip, rejp, cilen); /* Move it */
   1838 	    INCPTR(cilen, rejp);	/* Update output pointer */
   1839 	}
   1840     }
   1841 
   1842     /*
   1843      * If we wanted to send additional NAKs (for unsent CIs), the
   1844      * code would go here.  The extra NAKs would go at *nakp.
   1845      * At present there are no cases where we want to ask the
   1846      * peer to negotiate an option.
   1847      */
   1848 
   1849     switch (rc) {
   1850     case CONFACK:
   1851 	*lenp = next - inp;
   1852 	break;
   1853     case CONFNAK:
   1854 	/*
   1855 	 * Copy the Nak'd options from the nak_buffer to the caller's buffer.
   1856 	 */
   1857 	*lenp = nakp - nak_buffer;
   1858 	BCOPY(nak_buffer, inp, *lenp);
   1859 	break;
   1860     case CONFREJ:
   1861 	*lenp = rejp - inp;
   1862 	break;
   1863     }
   1864 
   1865     LCPDEBUG(("lcp_reqci: returning CONF%s.", CODENAME(rc)));
   1866     return (rc);			/* Return final code */
   1867 }
   1868 
   1869 
   1870 /*
   1871  * lcp_up - LCP has come UP.
   1872  */
   1873 static void
   1874 lcp_up(fsm *f)
   1875 {
   1876     lcp_options *wo = &lcp_wantoptions[f->unit];
   1877     lcp_options *ho = &lcp_hisoptions[f->unit];
   1878     lcp_options *go = &lcp_gotoptions[f->unit];
   1879     lcp_options *ao = &lcp_allowoptions[f->unit];
   1880     int mtu, mru;
   1881 
   1882     if (!go->neg_magicnumber)
   1883 	go->magicnumber = 0;
   1884     if (!ho->neg_magicnumber)
   1885 	ho->magicnumber = 0;
   1886 
   1887     /*
   1888      * Set our MTU to the smaller of the MTU we wanted and
   1889      * the MRU our peer wanted.  If we negotiated an MRU,
   1890      * set our MRU to the larger of value we wanted and
   1891      * the value we got in the negotiation.
   1892      * Note on the MTU: the link MTU can be the MRU the peer wanted,
   1893      * the interface MTU is set to the lowest of that, the
   1894      * MTU we want to use, and our link MRU.
   1895      */
   1896     mtu = ho->neg_mru? ho->mru: PPP_MRU;
   1897     mru = go->neg_mru? MAX(wo->mru, go->mru): PPP_MRU;
   1898 #ifdef PPP_WITH_MULTILINK
   1899     if (!(multilink && go->neg_mrru && ho->neg_mrru))
   1900 #endif /* PPP_WITH_MULTILINK */
   1901 	ppp_set_mtu(f->unit, MIN(MIN(mtu, mru), ao->mru));
   1902     ppp_send_config(f->unit, mtu,
   1903 		    (ho->neg_asyncmap? ho->asyncmap: 0xffffffff),
   1904 		    ho->neg_pcompression, ho->neg_accompression);
   1905     ppp_recv_config(f->unit, mru,
   1906 		    (lax_recv? 0: go->neg_asyncmap? go->asyncmap: 0xffffffff),
   1907 		    go->neg_pcompression, go->neg_accompression);
   1908 
   1909     if (ho->neg_mru)
   1910 	peer_mru[f->unit] = ho->mru;
   1911 
   1912     lcp_echo_lowerup(f->unit);  /* Enable echo messages */
   1913 
   1914     link_established(f->unit);
   1915 }
   1916 
   1917 
   1918 /*
   1919  * lcp_down - LCP has gone DOWN.
   1920  *
   1921  * Alert other protocols.
   1922  */
   1923 static void
   1924 lcp_down(fsm *f)
   1925 {
   1926     lcp_options *go = &lcp_gotoptions[f->unit];
   1927 
   1928     lcp_echo_lowerdown(f->unit);
   1929 
   1930     link_down(f->unit);
   1931 
   1932     ppp_send_config(f->unit, PPP_MRU, 0xffffffff, 0, 0);
   1933     ppp_recv_config(f->unit, PPP_MRU,
   1934 		    (go->neg_asyncmap? go->asyncmap: 0xffffffff),
   1935 		    go->neg_pcompression, go->neg_accompression);
   1936     peer_mru[f->unit] = PPP_MRU;
   1937 }
   1938 
   1939 
   1940 /*
   1941  * lcp_starting - LCP needs the lower layer up.
   1942  */
   1943 static void
   1944 lcp_starting(fsm *f)
   1945 {
   1946     link_required(f->unit);
   1947 }
   1948 
   1949 
   1950 /*
   1951  * lcp_finished - LCP has finished with the lower layer.
   1952  */
   1953 static void
   1954 lcp_finished(fsm *f)
   1955 {
   1956     link_terminated(f->unit);
   1957 }
   1958 
   1959 
   1960 /*
   1961  * lcp_printpkt - print the contents of an LCP packet.
   1962  */
   1963 static char *lcp_codenames[] = {
   1964     "ConfReq", "ConfAck", "ConfNak", "ConfRej",
   1965     "TermReq", "TermAck", "CodeRej", "ProtRej",
   1966     "EchoReq", "EchoRep", "DiscReq", "Ident",
   1967     "TimeRem"
   1968 };
   1969 
   1970 static int
   1971 lcp_printpkt(u_char *p, int plen, void (*printer)(void *, char *, ...), void *arg)
   1972 {
   1973     int code, id, len, olen, i;
   1974     u_char *pstart, *optend;
   1975     u_short cishort;
   1976     u_int32_t cilong;
   1977 
   1978     if (plen < HEADERLEN)
   1979 	return 0;
   1980     pstart = p;
   1981     GETCHAR(code, p);
   1982     GETCHAR(id, p);
   1983     GETSHORT(len, p);
   1984     if (len < HEADERLEN || len > plen)
   1985 	return 0;
   1986 
   1987     if (code >= 1 && code <= sizeof(lcp_codenames) / sizeof(char *))
   1988 	printer(arg, " %s", lcp_codenames[code-1]);
   1989     else
   1990 	printer(arg, " code=0x%x", code);
   1991     printer(arg, " id=0x%x", id);
   1992     len -= HEADERLEN;
   1993     switch (code) {
   1994     case CONFREQ:
   1995     case CONFACK:
   1996     case CONFNAK:
   1997     case CONFREJ:
   1998 	/* print option list */
   1999 	while (len >= 2) {
   2000 	    GETCHAR(code, p);
   2001 	    GETCHAR(olen, p);
   2002 	    p -= 2;
   2003 	    if (olen < 2 || olen > len) {
   2004 		break;
   2005 	    }
   2006 	    printer(arg, " <");
   2007 	    len -= olen;
   2008 	    optend = p + olen;
   2009 	    switch (code) {
   2010 	    case CI_MRU:
   2011 		if (olen == CILEN_SHORT) {
   2012 		    p += 2;
   2013 		    GETSHORT(cishort, p);
   2014 		    printer(arg, "mru %d", cishort);
   2015 		}
   2016 		break;
   2017 	    case CI_ASYNCMAP:
   2018 		if (olen == CILEN_LONG) {
   2019 		    p += 2;
   2020 		    GETLONG(cilong, p);
   2021 		    printer(arg, "asyncmap 0x%x", cilong);
   2022 		}
   2023 		break;
   2024 	    case CI_AUTHTYPE:
   2025 		if (olen >= CILEN_SHORT) {
   2026 		    p += 2;
   2027 		    printer(arg, "auth ");
   2028 		    GETSHORT(cishort, p);
   2029 		    switch (cishort) {
   2030 		    case PPP_PAP:
   2031 			printer(arg, "pap");
   2032 			break;
   2033 		    case PPP_CHAP:
   2034 			printer(arg, "chap");
   2035 			if (p < optend) {
   2036 			    switch (*p) {
   2037 			    case CHAP_MD5:
   2038 				printer(arg, " MD5");
   2039 				++p;
   2040 				break;
   2041 			    case CHAP_MICROSOFT:
   2042 				printer(arg, " MS");
   2043 				++p;
   2044 				break;
   2045 
   2046 			    case CHAP_MICROSOFT_V2:
   2047 				printer(arg, " MS-v2");
   2048 				++p;
   2049 				break;
   2050 			    }
   2051 			}
   2052 			break;
   2053 		    case PPP_EAP:
   2054 			printer(arg, "eap");
   2055 			break;
   2056 		    default:
   2057 			printer(arg, "0x%x", cishort);
   2058 		    }
   2059 		}
   2060 		break;
   2061 	    case CI_QUALITY:
   2062 		if (olen >= CILEN_SHORT) {
   2063 		    p += 2;
   2064 		    printer(arg, "quality ");
   2065 		    GETSHORT(cishort, p);
   2066 		    switch (cishort) {
   2067 		    case PPP_LQR:
   2068 			printer(arg, "lqr");
   2069 			break;
   2070 		    default:
   2071 			printer(arg, "0x%x", cishort);
   2072 		    }
   2073 		}
   2074 		break;
   2075 	    case CI_CALLBACK:
   2076 		if (olen >= CILEN_CHAR) {
   2077 		    p += 2;
   2078 		    printer(arg, "callback ");
   2079 		    GETCHAR(cishort, p);
   2080 		    switch (cishort) {
   2081 		    case CBCP_OPT:
   2082 			printer(arg, "CBCP");
   2083 			break;
   2084 		    default:
   2085 			printer(arg, "0x%x", cishort);
   2086 		    }
   2087 		}
   2088 		break;
   2089 	    case CI_MAGICNUMBER:
   2090 		if (olen == CILEN_LONG) {
   2091 		    p += 2;
   2092 		    GETLONG(cilong, p);
   2093 		    printer(arg, "magic 0x%x", cilong);
   2094 		}
   2095 		break;
   2096 	    case CI_PCOMPRESSION:
   2097 		if (olen == CILEN_VOID) {
   2098 		    p += 2;
   2099 		    printer(arg, "pcomp");
   2100 		}
   2101 		break;
   2102 	    case CI_ACCOMPRESSION:
   2103 		if (olen == CILEN_VOID) {
   2104 		    p += 2;
   2105 		    printer(arg, "accomp");
   2106 		}
   2107 		break;
   2108 	    case CI_MRRU:
   2109 		if (olen == CILEN_SHORT) {
   2110 		    p += 2;
   2111 		    GETSHORT(cishort, p);
   2112 		    printer(arg, "mrru %d", cishort);
   2113 		}
   2114 		break;
   2115 	    case CI_SSNHF:
   2116 		if (olen == CILEN_VOID) {
   2117 		    p += 2;
   2118 		    printer(arg, "ssnhf");
   2119 		}
   2120 		break;
   2121 	    case CI_EPDISC:
   2122 #ifdef PPP_WITH_MULTILINK
   2123 		if (olen >= CILEN_CHAR) {
   2124 		    struct epdisc epd;
   2125 		    p += 2;
   2126 		    GETCHAR(epd.class, p);
   2127 		    epd.length = olen - CILEN_CHAR;
   2128 		    if (epd.length > MAX_ENDP_LEN)
   2129 			epd.length = MAX_ENDP_LEN;
   2130 		    if (epd.length > 0) {
   2131 			BCOPY(p, epd.value, epd.length);
   2132 			p += epd.length;
   2133 		    }
   2134 		    printer(arg, "endpoint [%s]", epdisc_to_str(&epd));
   2135 		}
   2136 #else
   2137 		printer(arg, "endpoint");
   2138 #endif
   2139 		break;
   2140 	    }
   2141 	    while (p < optend) {
   2142 		GETCHAR(code, p);
   2143 		printer(arg, " %.2x", code);
   2144 	    }
   2145 	    printer(arg, ">");
   2146 	}
   2147 	break;
   2148 
   2149     case TERMACK:
   2150     case TERMREQ:
   2151 	if (len > 0 && *p >= ' ' && *p < 0x7f) {
   2152 	    printer(arg, " ");
   2153 	    print_string((char *)p, len, printer, arg);
   2154 	    p += len;
   2155 	    len = 0;
   2156 	}
   2157 	break;
   2158 
   2159     case ECHOREQ:
   2160     case ECHOREP:
   2161     case DISCREQ:
   2162 	if (len >= 4) {
   2163 	    GETLONG(cilong, p);
   2164 	    printer(arg, " magic=0x%x", cilong);
   2165 	    len -= 4;
   2166 	}
   2167 	break;
   2168 
   2169     case IDENTIF:
   2170     case TIMEREM:
   2171 	if (len >= 4) {
   2172 	    GETLONG(cilong, p);
   2173 	    printer(arg, " magic=0x%x", cilong);
   2174 	    len -= 4;
   2175 	}
   2176 	if (code == TIMEREM) {
   2177 	    if (len < 4)
   2178 		break;
   2179 	    GETLONG(cilong, p);
   2180 	    printer(arg, " seconds=%u", cilong);
   2181 	    len -= 4;
   2182 	}
   2183 	if (len > 0) {
   2184 	    printer(arg, " ");
   2185 	    print_string((char *)p, len, printer, arg);
   2186 	    p += len;
   2187 	    len = 0;
   2188 	}
   2189 	break;
   2190     }
   2191 
   2192     /* print the rest of the bytes in the packet */
   2193     for (i = 0; i < len && i < 32; ++i) {
   2194 	GETCHAR(code, p);
   2195 	printer(arg, " %.2x", code);
   2196     }
   2197     if (i < len) {
   2198 	printer(arg, " ...");
   2199 	p += len - i;
   2200     }
   2201 
   2202     return p - pstart;
   2203 }
   2204 
   2205 /*
   2206  * Time to shut down the link because there is nothing out there.
   2207  */
   2208 
   2209 static
   2210 void LcpLinkFailure (fsm *f)
   2211 {
   2212     if (f->state == OPENED) {
   2213 	info("No response to %d echo-requests", lcp_echos_pending);
   2214         notice("Serial link appears to be disconnected.");
   2215 	ppp_set_status(EXIT_PEER_DEAD);
   2216 	lcp_close(f->unit, "Peer not responding");
   2217     }
   2218 }
   2219 
   2220 /*
   2221  * Timer expired for the LCP echo requests from this process.
   2222  */
   2223 
   2224 static void
   2225 LcpEchoCheck (fsm *f)
   2226 {
   2227     LcpSendEchoRequest (f);
   2228     if (f->state != OPENED)
   2229 	return;
   2230 
   2231     /*
   2232      * Start the timer for the next interval.
   2233      */
   2234     if (lcp_echo_timer_running)
   2235 	warn("assertion lcp_echo_timer_running==0 failed");
   2236     TIMEOUT (LcpEchoTimeout, f, lcp_echo_interval);
   2237     lcp_echo_timer_running = 1;
   2238 }
   2239 
   2240 /*
   2241  * LcpEchoTimeout - Timer expired on the LCP echo
   2242  */
   2243 
   2244 static void
   2245 LcpEchoTimeout (void *arg)
   2246 {
   2247     if (lcp_echo_timer_running != 0) {
   2248         lcp_echo_timer_running = 0;
   2249         LcpEchoCheck ((fsm *) arg);
   2250     }
   2251 }
   2252 
   2253 /*
   2254  * Log the round-trip time (RTT) of the received LCP echo-request.
   2255  *
   2256  * The header section at the beginning of lcp_rtt_file contains
   2257  * LCP_RTT_HEADER_LENGTH fields, each a u_int32_t in network byte order:
   2258  * [0] LCP_RTT_MAGIC
   2259  * [1] status (1: the file is open and is being written)
   2260  * [2] index of the most recently updated element
   2261  * [3] the value of the lcp-echo-interval parameter
   2262  *
   2263  * The header is followed by a ring buffer of LCP_RTT_ELEMENTS elements, each
   2264  * containing a pair of u_int32_t in network byte order with this content:
   2265  * [0] UNIX timestamp
   2266  * [1] bits 24-31: the number of lost LCP echo replies
   2267  *     bits 0-23:  the measured RTT in microseconds
   2268  *
   2269  * The timestamp is unsigned to support storing dates beyond 2038.
   2270  *
   2271  * Consumers of lcp_rtt_file are expected to:
   2272  * - read the complete file of arbitrary length
   2273  * - check the magic number
   2274  * - process the data elements starting at the index
   2275  * - ignore any elements with a timestamp of 0
   2276  */
   2277 static void
   2278 lcp_rtt_update_buffer (unsigned long rtt)
   2279 {
   2280     volatile u_int32_t *const ring_header = lcp_rtt_buffer;
   2281     volatile u_int32_t *const ring_buffer = lcp_rtt_buffer
   2282 	+ LCP_RTT_HEADER_LENGTH;
   2283     unsigned int next_entry, lost;
   2284 
   2285     /* choose the next entry where the data will be stored */
   2286     if (ntohl(ring_header[2]) >= (LCP_RTT_ELEMENTS - 1) * 2)
   2287 	next_entry = 0;				/* go back to the beginning */
   2288     else
   2289 	next_entry = ntohl(ring_header[2]) + 2;	/* use the next one */
   2290 
   2291     /* update the data element */
   2292     /* storing the timestamp in an *unsigned* long allows dates up to 2106 */
   2293     ring_buffer[next_entry] = htonl((u_int32_t) time(NULL));
   2294     lost = lcp_echos_pending - 1;
   2295     if (lost > 0xFF)
   2296 	lost = 0xFF;		/* truncate the lost packets count to 256 */
   2297     if (rtt > 0xFFFFFF)
   2298 	rtt = 0xFFFFFF;		/* truncate the RTT to 16777216 */
   2299     /* use bits 24-31 for the lost packets count and bits 0-23 for the RTT */
   2300     ring_buffer[next_entry + 1] = htonl((u_int32_t) ((lost << 24) + rtt));
   2301 
   2302     /* update the pointer to the (just updated) most current data element */
   2303     ring_header[2] = htonl(next_entry);
   2304 
   2305     /* In theory, CPUs implementing a weakly-consistent memory model do not
   2306      * guarantee that these three memory store operations to the buffer will
   2307      * be seen in the same order by the reader process.
   2308      * This means that a process reading the file could see the index
   2309      * having been updated before the element that the index points to had
   2310      * been written.
   2311      * But in practice we expect that the read(2) system call used by
   2312      * consumers processes is atomic with respect to the following msync(2)
   2313      * call, so we ignore the issue.
   2314      */
   2315 
   2316     if (msync(lcp_rtt_buffer, LCP_RTT_FILE_SIZE, MS_ASYNC) < 0)
   2317 	error("msync() for %s failed: %m", lcp_rtt_file);
   2318 }
   2319 
   2320 /*
   2321  * LcpEchoReply - LCP has received a reply to the echo
   2322  */
   2323 
   2324 static void
   2325 lcp_received_echo_reply (fsm *f, int id, u_char *inp, int len)
   2326 {
   2327     u_int32_t magic;
   2328 
   2329     /* Check the magic number - don't count replies from ourselves. */
   2330     if (len < 4) {
   2331 	dbglog("lcp: received short Echo-Reply, length %d", len);
   2332 	return;
   2333     }
   2334     GETLONG(magic, inp);
   2335     if (lcp_gotoptions[f->unit].neg_magicnumber
   2336 	&& magic == lcp_gotoptions[f->unit].magicnumber) {
   2337 	warn("appear to have received our own echo-reply!");
   2338 	return;
   2339     }
   2340 
   2341     if (lcp_rtt_file_fd && len >= 16) {
   2342 	long lcp_rtt_magic;
   2343 
   2344 	/*
   2345 	 * If the magic word is found at the beginning of the data section
   2346 	 * of the frame then read the timestamp which follows and subtract
   2347 	 * it from the current time to compute the round trip time.
   2348 	 */
   2349 	GETLONG(lcp_rtt_magic, inp);
   2350 	if (lcp_rtt_magic == LCP_RTT_MAGIC) {
   2351 	    struct timespec ts;
   2352 	    unsigned long req_sec, req_nsec, rtt;
   2353 
   2354 	    clock_gettime(CLOCK_MONOTONIC, &ts);
   2355 	    GETLONG(req_sec, inp);
   2356 	    GETLONG(req_nsec, inp);
   2357 	    /* compute the RTT in microseconds */
   2358 	    rtt = (ts.tv_sec - req_sec) * 1000000
   2359 		+ (ts.tv_nsec / 1000 - req_nsec / 1000);
   2360 	    /* log the RTT */
   2361 	    lcp_rtt_update_buffer(rtt);
   2362 	}
   2363     }
   2364 
   2365     /* Reset the number of outstanding echo frames */
   2366     lcp_echos_pending = 0;
   2367 }
   2368 
   2369 /*
   2370  * LcpSendEchoRequest - Send an echo request frame to the peer
   2371  */
   2372 
   2373 static void
   2374 LcpSendEchoRequest (fsm *f)
   2375 {
   2376     u_int32_t lcp_magic;
   2377     u_char pkt[16], *pktp;
   2378 
   2379     /*
   2380      * Detect the failure of the peer at this point.
   2381      */
   2382     if (lcp_echo_fails != 0) {
   2383         if (lcp_echos_pending >= lcp_echo_fails) {
   2384             LcpLinkFailure(f);
   2385 	    lcp_echos_pending = 0;
   2386 	}
   2387     }
   2388 
   2389     /*
   2390      * If adaptive echos have been enabled, only send the echo request if
   2391      * no traffic was received since the last one.
   2392      */
   2393     if (lcp_echo_adaptive) {
   2394 	static unsigned int last_pkts_in = 0;
   2395 	struct pppd_stats cur_stats;
   2396 
   2397 	if (get_ppp_stats(f->unit, &cur_stats) && cur_stats.pkts_in != last_pkts_in) {
   2398 	    last_pkts_in = cur_stats.pkts_in;
   2399 	    /* receipt of traffic indicates the link is working... */
   2400 	    lcp_echos_pending = 0;
   2401 	    return;
   2402 	}
   2403     }
   2404 
   2405     /*
   2406      * Make and send the echo request frame.
   2407      */
   2408     if (f->state == OPENED) {
   2409         lcp_magic = lcp_gotoptions[f->unit].magicnumber;
   2410 	pktp = pkt;
   2411 	PUTLONG(lcp_magic, pktp);
   2412 
   2413 	/* Put a timestamp in the data section of the frame */
   2414 	if (lcp_rtt_file_fd) {
   2415 	    struct timespec ts;
   2416 
   2417 	    PUTLONG(LCP_RTT_MAGIC, pktp);
   2418 	    clock_gettime(CLOCK_MONOTONIC, &ts);
   2419 	    PUTLONG((u_int32_t)ts.tv_sec, pktp);
   2420 	    PUTLONG((u_int32_t)ts.tv_nsec, pktp);
   2421 	}
   2422 
   2423         fsm_sdata(f, ECHOREQ, lcp_echo_number++ & 0xFF, pkt, pktp - pkt);
   2424 	++lcp_echos_pending;
   2425     }
   2426 }
   2427 
   2428 static void
   2429 lcp_rtt_open_file (void)
   2430 {
   2431     volatile u_int32_t *ring_header;
   2432 
   2433     if (!lcp_rtt_file)
   2434 	return;
   2435 
   2436     lcp_rtt_file_fd = open(lcp_rtt_file, O_RDWR | O_CREAT, 0644);
   2437     if (lcp_rtt_file_fd < 0) {
   2438 	error("Can't open the RTT log file %s: %m", lcp_rtt_file);
   2439 	lcp_rtt_file_fd = 0;
   2440 	return;
   2441     }
   2442 
   2443     if (ftruncate(lcp_rtt_file_fd, LCP_RTT_FILE_SIZE) < 0)
   2444 	fatal("ftruncate() of %s failed: %m", lcp_rtt_file);
   2445     lcp_rtt_buffer = mmap(0, LCP_RTT_FILE_SIZE, PROT_READ | PROT_WRITE,
   2446 	    MAP_SHARED, lcp_rtt_file_fd, 0);
   2447     if (lcp_rtt_buffer == MAP_FAILED)
   2448 	fatal("mmap() of %s failed: %m", lcp_rtt_file);
   2449     ring_header = lcp_rtt_buffer;
   2450 
   2451     /* initialize the ring buffer */
   2452     if (ring_header[0] != htonl(LCP_RTT_MAGIC)) {
   2453 	memset(lcp_rtt_buffer, 0, LCP_RTT_FILE_SIZE);
   2454 	ring_header[0] = htonl(LCP_RTT_MAGIC);
   2455     }
   2456 
   2457     ring_header[3] = htonl(lcp_echo_interval);
   2458     ring_header[1] = htonl(1); /* status: LCP up, file opened */
   2459 }
   2460 
   2461 static void
   2462 lcp_rtt_close_file (void)
   2463 {
   2464     volatile u_int32_t *const ring_header = lcp_rtt_buffer;
   2465 
   2466     if (!lcp_rtt_file_fd)
   2467 	return;
   2468 
   2469     ring_header[1] = htonl(0); /* status: LCP down, file closed */
   2470 
   2471     if (munmap(lcp_rtt_buffer, LCP_RTT_FILE_SIZE) < 0)
   2472 	error("munmap() of %s failed: %m", lcp_rtt_file);
   2473     if (close(lcp_rtt_file_fd) < 0)
   2474 	error("close() of %s failed: %m", lcp_rtt_file);
   2475     lcp_rtt_buffer = NULL;
   2476     lcp_rtt_file_fd = 0;
   2477 }
   2478 
   2479 /*
   2480  * lcp_echo_lowerup - Start the timer for the LCP frame
   2481  */
   2482 
   2483 static void
   2484 lcp_echo_lowerup (int unit)
   2485 {
   2486     fsm *f = &lcp_fsm[unit];
   2487 
   2488     /* Clear the parameters for generating echo frames */
   2489     lcp_echos_pending      = 0;
   2490     lcp_echo_number        = 0;
   2491     lcp_echo_timer_running = 0;
   2492 
   2493     /* Open the file where the LCP RTT data will be logged */
   2494     lcp_rtt_open_file();
   2495 
   2496     /* If a timeout interval is specified then start the timer */
   2497     if (lcp_echo_interval != 0)
   2498         LcpEchoCheck (f);
   2499 }
   2500 
   2501 /*
   2502  * lcp_echo_lowerdown - Stop the timer for the LCP frame
   2503  */
   2504 
   2505 static void
   2506 lcp_echo_lowerdown (int unit)
   2507 {
   2508     fsm *f = &lcp_fsm[unit];
   2509 
   2510     if (lcp_echo_timer_running != 0) {
   2511         UNTIMEOUT (LcpEchoTimeout, f);
   2512         lcp_echo_timer_running = 0;
   2513     }
   2514 
   2515     /* Close the file containing the LCP RTT data */
   2516     lcp_rtt_close_file();
   2517 }
   2518