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