1 /*
2 * lcp.c - PPP Link Control Protocol.
3 *
4 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
5 * Use is subject to license terms.
6 *
7 * Copyright (c) 1989 Carnegie Mellon University.
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms are permitted
11 * provided that the above copyright notice and this paragraph are
12 * duplicated in all such forms and that any documentation,
13 * advertising materials, and other materials related to such
14 * distribution and use acknowledge that the software was developed
15 * by Carnegie Mellon University. The name of the
16 * University may not be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
20 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21 */
22
23 #define RCSID "$Id: lcp.c,v 1.54 2000/04/27 03:51:18 masputra Exp $"
24
25 /*
26 * TODO:
27 */
28
29 #include <stdio.h>
30 #include <string.h>
31 #include <stdlib.h>
32 #include <ctype.h>
33 #if defined(CHAPMS) || defined(CHAPMSV2)
34 #ifdef HAVE_CRYPT_H
35 #include <crypt.h>
36 #endif
37 #ifndef USE_CRYPT
38 #include <des.h>
39 #endif
40 #ifdef SOL2
41 #include <errno.h>
42 #endif
43 #endif
44
45 #include "pppd.h"
46 #include "fsm.h"
47 #include "lcp.h"
48 #include "chap.h"
49 #include "magic.h"
50 #include "patchlevel.h"
51
52 #if !defined(lint) && !defined(_lint)
53 static const char rcsid[] = RCSID;
54 #endif
55
56 /*
57 * Special failure codes for logging link failure reasons.
58 */
59 bool peer_nak_auth; /* Peer sent nak for our auth request */
60 u_short nak_auth_orig; /* Auth proto peer naked */
61 u_short nak_auth_proto; /* Auth proto peer suggested instead */
62 bool unsolicited_nak_auth; /* Peer asked us to authenticate */
63 u_short unsolicit_auth_proto; /* Auth proto peer wants */
64 bool peer_reject_auth; /* Peer sent reject for auth */
65 u_short reject_auth_proto; /* Protocol that peer rejected */
66 bool rejected_peers_auth; /* We sent a reject to the peer */
67 u_short rejected_auth_proto; /* Protocol that peer wanted to use */
68 bool naked_peers_auth; /* We sent a nak to the peer */
69 u_short naked_auth_orig; /* Protocol that we wanted to use */
70 u_short naked_auth_proto; /* Protocol that peer wants us to use */
71
72 /*
73 * LCP-related command-line options.
74 */
75 int lcp_echo_interval = 0; /* Interval between LCP echo-requests */
76 int lcp_echo_fails = 0; /* Tolerance to unanswered echo-requests */
77 bool lax_recv = 0; /* accept control chars in asyncmap */
78 static int use_accm_test = 2; /* use big echo-requests to check ACCM */
79 #define ACCM_TEST_FAILS 5
80
81 #define _tostr2(x) #x
82 #define _tostr(x) _tostr2(x)
83 static char identstr[256] = /* Identification string */
84 "ppp-" VERSION "." _tostr(PATCHLEVEL) IMPLEMENTATION;
85 static int noident = 0; /* 1 to disable; 2 to reject */
86 static int sentident = 0; /* counts the # of ident codes sent */
87
88 /* set if we're allowed to send an unsolicited Configure-Nak for MRU. */
89 static bool unsolicit_mru;
90
91 static int setescape __P((char **, option_t *));
92
93 static bool do_msft_workaround = 1;
94 static int setasyncmap __P((char **, option_t *));
95
96 bool noendpoint = 0; /* don't send/accept endpoint discriminator */
97 static int setendpoint __P((char **, option_t *));
98
99 static char *callback_strings[] = {
100 "auth", "dialstring", "location", "E.164", "X.500", "", "CBCP", NULL
101 };
102
103 /* This is used in packet printing even if NEGOTIATE_FCS isn't enabled */
104 static char *fcsalt_strings[] = {
105 "null", "crc16", "crc32", NULL
106 };
107
108 #ifdef NEGOTIATE_FCS
109 static int setfcsallow __P((char **, option_t *));
110 static int setfcswant __P((char **, option_t *));
111 #endif
112
113 /* Backward compatibility for Linux */
114 #ifndef PPP_MAXMRU
115 #define PPP_MTU 1500 /* Default MTU (size of Info field) */
116 #define PPP_MAXMTU 65535 - (PPP_HDRLEN + PPP_FCSLEN)
117 #define PPP_MINMTU 64
118 #define PPP_MAXMRU 65000 /* Largest MRU we allow */
119 #define PPP_MINMRU 128
120 #endif
121
122 static option_t lcp_option_list[] = {
123 /* LCP options */
124 { "noaccomp", o_bool, &lcp_wantoptions[0].neg_accompression,
125 "Disable address/control compression",
126 OPT_A2COPY, &lcp_allowoptions[0].neg_accompression },
127 { "-ac", o_bool, &lcp_wantoptions[0].neg_accompression,
128 "Disable address/control compression",
129 OPT_A2COPY, &lcp_allowoptions[0].neg_accompression },
130 { "default-asyncmap", o_bool, &lcp_wantoptions[0].neg_asyncmap,
131 "Disable asyncmap negotiation",
132 OPT_A2COPY, &lcp_allowoptions[0].neg_asyncmap },
133 { "-am", o_bool, &lcp_wantoptions[0].neg_asyncmap,
134 "Disable asyncmap negotiation",
135 OPT_A2COPY, &lcp_allowoptions[0].neg_asyncmap },
136 { "asyncmap", o_special, (void *)setasyncmap,
137 "Set asyncmap (for received packets)" },
138 { "-as", o_special, (void *)setasyncmap,
139 "Set asyncmap (for received packets)" },
140 { "nomagic", o_bool, &lcp_wantoptions[0].neg_magicnumber,
141 "Disable magic number option (looped-back line detect)",
142 OPT_A2COPY, &lcp_allowoptions[0].neg_magicnumber },
143 { "-mn", o_bool, &lcp_wantoptions[0].neg_magicnumber,
144 "Disable magic number option (looped-back line detect)",
145 OPT_A2COPY, &lcp_allowoptions[0].neg_magicnumber },
146 { "default-mru", o_bool, &lcp_wantoptions[0].neg_mru,
147 "Disable MRU negotiation (use default 1500)",
148 OPT_A2COPY, &lcp_allowoptions[0].neg_mru },
149 { "-mru", o_bool, &lcp_wantoptions[0].neg_mru,
150 "Disable MRU negotiation (use default 1500)",
151 OPT_A2COPY, &lcp_allowoptions[0].neg_mru },
152 { "mru", o_int, &lcp_wantoptions[0].mru,
153 "Set MRU (maximum received packet size) for negotiation",
154 OPT_LIMITS, &lcp_wantoptions[0].neg_mru, PPP_MAXMRU, PPP_MINMRU },
155 { "mtu", o_int, &lcp_allowoptions[0].mru,
156 "Set our MTU", OPT_LIMITS|OPT_A2COPY, &lcp_allowoptions[0].mrru,
157 PPP_MAXMTU, PPP_MINMTU },
158 { "nopcomp", o_bool, &lcp_wantoptions[0].neg_pcompression,
159 "Disable protocol field compression",
160 OPT_A2COPY, &lcp_allowoptions[0].neg_pcompression },
161 { "-pc", o_bool, &lcp_wantoptions[0].neg_pcompression,
162 "Disable protocol field compression",
163 OPT_A2COPY, &lcp_allowoptions[0].neg_pcompression },
164 { "-p", o_bool, &lcp_wantoptions[0].passive,
165 "Set passive mode", 1 },
166 { "passive", o_bool, &lcp_wantoptions[0].passive,
167 "Set passive mode", 1 },
168 { "silent", o_bool, &lcp_wantoptions[0].silent,
169 "Set silent mode", 1 },
170 { "escape", o_special, (void *)setescape,
171 "List of character codes to escape on transmission" },
172 { "lcp-echo-failure", o_int, &lcp_echo_fails,
173 "Number of consecutive echo failures for link failure" },
174 { "lcp-echo-interval", o_int, &lcp_echo_interval,
175 "Set time in seconds between LCP echo requests" },
176 { "no-accm-test", o_int, &use_accm_test,
177 "Disable use of LCP Echo-Request asyncmap checking",
178 OPT_NOARG|OPT_VAL(0) },
179 { "small-accm-test", o_int, &use_accm_test,
180 "Use only small Echo-Requests for asyncmap checking",
181 OPT_NOARG|OPT_VAL(1) },
182 { "lcp-restart", o_int, &lcp_fsm[0].timeouttime,
183 "Set time in seconds between LCP retransmissions" },
184 { "lcp-max-terminate", o_int, &lcp_fsm[0].maxtermtransmits,
185 "Maximum number of LCP terminate-request transmissions" },
186 { "lcp-max-configure", o_int, &lcp_fsm[0].maxconfreqtransmits,
187 "Maximum number of LCP configure-request transmissions" },
188 { "lcp-max-failure", o_int, &lcp_fsm[0].maxnakloops,
189 "Set limit on number of LCP configure-naks" },
190 { "receive-all", o_bool, &lax_recv,
191 "Accept all received control characters", 1 },
192 #ifdef HAVE_MULTILINK
193 { "mrru", o_int, &lcp_wantoptions[0].mrru,
194 "Maximum received packet size for multilink bundle",
195 OPT_LIMITS, &lcp_wantoptions[0].neg_mrru, PPP_MAXMRU, PPP_MINMRU },
196 { "mpshortseq", o_bool, &lcp_wantoptions[0].neg_ssnhf,
197 "Use short sequence numbers in multilink headers",
198 OPT_A2COPY | 1, &lcp_allowoptions[0].neg_ssnhf },
199 { "nompshortseq", o_bool, &lcp_wantoptions[0].neg_ssnhf,
200 "Don't use short sequence numbers in multilink headers",
201 OPT_A2COPY, &lcp_allowoptions[0].neg_ssnhf },
202 #endif /* HAVE_MULTILINK */
203 { "endpoint", o_special, (void *)setendpoint,
204 "Endpoint discriminator for multilink", },
205 { "noendpoint", o_bool, &noendpoint,
206 "Don't send or accept multilink endpoint discriminator", 1 },
207 { "ident", o_string, identstr,
208 "LCP Identification string", OPT_STATIC, NULL, sizeof(identstr) },
209 { "noident", o_int, &noident,
210 "Disable use of LCP Identification", OPT_INC|OPT_NOARG|1 },
211 #ifdef NEGOTIATE_FCS
212 { "default-fcs", o_bool, &lcp_wantoptions[0].neg_fcs,
213 "Disable FCS Alternatives option (use default CRC-16)",
214 OPT_A2COPY, &lcp_allowoptions[0].neg_fcs },
215 { "allow-fcs", o_special, (void *)setfcsallow,
216 "Set allowable FCS types; crc16, crc32, null, or number" },
217 { "fcs", o_special, (void *)setfcswant,
218 "Set FCS type(s) desired; crc16, crc32, null, or number" },
219 #endif
220 #ifdef MUX_FRAME
221 /*
222 * if pppmux option is turned on, then the parameter to this
223 * is time value in microseconds
224 */
225 { "pppmux", o_int, &lcp_wantoptions[0].pppmux,
226 "Set PPP Multiplexing option timer", OPT_LLIMIT | OPT_A2COPY,
227 &lcp_allowoptions[0].pppmux, 0, 0 },
228 #endif
229 {NULL}
230 };
231
232 /* global vars */
233 fsm lcp_fsm[NUM_PPP]; /* LCP fsm structure (global)*/
234 lcp_options lcp_wantoptions[NUM_PPP]; /* Options that we want to request */
235 lcp_options lcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */
236 lcp_options lcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */
237 lcp_options lcp_hisoptions[NUM_PPP]; /* Options that we ack'd */
238 u_int32_t xmit_accm[NUM_PPP][8]; /* extended transmit ACCM */
239
240 /*
241 * These variables allow a plugin to assert limits on the maximum
242 * MRU/MTU values that can be negotiated.
243 */
244 int absmax_mru = PPP_MAXMRU;
245 int absmax_mtu = PPP_MAXMTU;
246
247 static int lcp_echos_pending = 0; /* Number of outstanding echo msgs */
248 static int lcp_echo_number = 0; /* ID number of next echo frame */
249 static int lcp_echo_timer_running = 0; /* set if a timer is running */
250 static bool lcp_echo_accm_test = 0; /* flag if still testing ACCM */
251 static int lcp_echo_badreplies = 0; /* number of bad replies from peer */
252 /*
253 * The maximum number of bad replies we tolerate before bringing the
254 * link down.
255 */
256 #define LCP_ECHO_MAX_BADREPLIES 10
257
258 /*
259 * Callbacks for fsm code. (CI = Configuration Information)
260 */
261 static void lcp_resetci __P((fsm *)); /* Reset our CI */
262 static int lcp_cilen __P((fsm *)); /* Return length of our CI */
263 static void lcp_addci __P((fsm *, u_char *, int *)); /* Add our CI to pkt */
264 static int lcp_ackci __P((fsm *, u_char *, int)); /* Peer ack'd our CI */
265 static int lcp_nakci __P((fsm *, u_char *, int)); /* Peer nak'd our CI */
266 static int lcp_rejci __P((fsm *, u_char *, int)); /* Peer rej'd our CI */
267 static int lcp_reqci __P((fsm *, u_char *, int *, int)); /* Rcv peer CI */
268 static void lcp_up __P((fsm *)); /* We're UP */
269 static void lcp_down __P((fsm *)); /* We're DOWN */
270 static void lcp_starting __P((fsm *)); /* We need lower layer up */
271 static void lcp_finished __P((fsm *)); /* We need lower layer down */
272 static int lcp_extcode __P((fsm *, int, int, u_char *, int));
273 static void lcp_rprotrej __P((fsm *, u_char *, int));
274 static int lcp_coderej __P((fsm *f, int code, int id, u_char *inp, int len));
275
276 /*
277 * routines to send LCP echos to peer
278 */
279
280 static void lcp_echo_lowerup __P((int));
281 static void lcp_echo_lowerdown __P((int));
282 static void LcpEchoTimeout __P((void *));
283 static int lcp_received_echo_reply __P((fsm *, int, u_char *, int));
284 static void LcpSendEchoRequest __P((fsm *));
285 static void LcpLinkFailure __P((fsm *));
286 static void LcpEchoCheck __P((fsm *));
287
288 /*
289 * routines to send and receive additional LCP packets described in
290 * section 1 of rfc1570.
291 */
292 static void LcpSendIdentification __P((fsm *));
293 static void lcp_received_identification __P((fsm *, int, u_char *, int));
294 static void LcpSendTimeRemaining __P((fsm *, u_int32_t));
295 static void lcp_timeremaining __P((void *));
296 static void lcp_received_timeremain __P((fsm *, int, u_char *, int));
297
298
299 static fsm_callbacks lcp_callbacks = { /* LCP callback routines */
300 lcp_resetci, /* Reset our Configuration Information */
301 lcp_cilen, /* Length of our Configuration Information */
302 lcp_addci, /* Add our Configuration Information */
303 lcp_ackci, /* ACK our Configuration Information */
304 lcp_nakci, /* NAK our Configuration Information */
305 lcp_rejci, /* Reject our Configuration Information */
306 lcp_reqci, /* Request peer's Configuration Information */
307 lcp_up, /* Called when fsm reaches OPENED state */
308 lcp_down, /* Called when fsm leaves OPENED state */
309 lcp_starting, /* Called when we want the lower layer up */
310 lcp_finished, /* Called when we want the lower layer down */
311 NULL, /* Retransmission is necessary */
312 lcp_extcode, /* Called to handle LCP-specific codes */
313 "LCP", /* String name of protocol */
314 lcp_coderej, /* Peer rejected a code number */
315 };
316
317 /*
318 * Protocol entry points.
319 * Some of these are called directly.
320 */
321
322 static void lcp_init __P((int));
323 static void lcp_input __P((int, u_char *, int));
324 static void lcp_protrej __P((int));
325 static int lcp_printpkt __P((u_char *, int,
326 void (*) __P((void *, const char *, ...)), void *));
327
328
329 struct protent lcp_protent = {
330 PPP_LCP, /* Protocol Number for LCP */
331 lcp_init, /* Initializes LCP */
332 lcp_input, /* Processes a received LCP packet */
333 lcp_protrej, /* Process a received Protocol-reject */
334 lcp_lowerup, /* Called after the serial device has been set up */
335 lcp_lowerdown, /* Called when the link is brought down */
336 lcp_open, /* Called after lcp_lowerup when bringing up the link */
337 lcp_close, /* Called when the link goes down */
338 lcp_printpkt, /* Print a packet in human readable form */
339 NULL, /* Process a received data packet */
340 1, /* LCP is enabled by default */
341 "LCP", /* Name of the protocol */
342 NULL, /* Name of the corresponding data protocol */
343 lcp_option_list, /* List of LCP command-line options */
344 NULL, /* Assigns default values for options */
345 NULL, /* Configures demand-dial */
346 NULL /* Bring up the link for this packet? */
347 };
348
349 int lcp_loopbackfail = DEFLOOPBACKFAIL;
350
351 /*
352 * Length of each type of configuration option (in octets)
353 */
354 #define CILEN_VOID 2
355 #define CILEN_CHAR 3
356 #define CILEN_SHORT 4 /* CILEN_VOID + 2 */
357 #define CILEN_CHAP 5 /* CILEN_VOID + 2 + 1 */
358 #define CILEN_LONG 6 /* CILEN_VOID + 4 */
359 #define CILEN_LQR 8 /* CILEN_VOID + 2 + 4 */
360 #define CILEN_CBCP 3
361
362
363 /*
364 * setescape - add chars to the set we escape on transmission.
365 */
366 /*ARGSUSED*/
367 static int
setescape(argv,opt)368 setescape(argv, opt)
369 char **argv;
370 option_t *opt;
371 {
372 int n, ret;
373 char *p, *endp;
374
375 p = *argv;
376 ret = 1;
377 while (*p != '\0') {
378 n = strtol(p, &endp, 16);
379 if (p == endp) {
380 option_error("escape parameter contains invalid hex number '%s'",
381 p);
382 return 0;
383 }
384 p = endp;
385 if (n < 0 || n == 0x5E || n > 0xFF) {
386 option_error("can't escape character 0x%x", n);
387 ret = 0;
388 } else
389 xmit_accm[0][n >> 5] |= 1 << (n & 0x1F);
390 while (*p == ',' || *p == ' ')
391 ++p;
392 }
393 return ret;
394 }
395
396 /*
397 * setasyncmap - set async map negotiated
398 */
399 /*ARGSUSED*/
400 static int
setasyncmap(argv,opt)401 setasyncmap(argv, opt)
402 char **argv;
403 option_t *opt;
404 {
405 u_int32_t val;
406 char *endp;
407
408 val = strtoul(*argv, &endp, 16);
409 if (*argv == endp) {
410 option_error("invalid numeric parameter '%s' for 'asyncmap' option",
411 *argv);
412 return 0;
413 }
414 lcp_wantoptions[0].asyncmap |= val;
415 lcp_wantoptions[0].neg_asyncmap = (~lcp_wantoptions[0].asyncmap != 0);
416 do_msft_workaround = 0;
417 return 1;
418 }
419
420 /*ARGSUSED*/
421 static int
setendpoint(argv,opt)422 setendpoint(argv, opt)
423 char **argv;
424 option_t *opt;
425 {
426 if (str_to_epdisc(&lcp_wantoptions[0].endpoint, *argv)) {
427 lcp_wantoptions[0].neg_endpoint = 1;
428 return 1;
429 }
430 option_error("Can't parse '%s' as an endpoint discriminator", *argv);
431 return 0;
432 }
433
434 #ifdef NEGOTIATE_FCS
435 static int
str_to_fcstype(opt,arg)436 str_to_fcstype(opt,arg)
437 lcp_options *opt;
438 char *arg;
439 {
440 char **cpp, *cp;
441 int val, len;
442
443 if (*arg != '\0') {
444 val = 0;
445 while (*arg != '\0') {
446 len = 0;
447 if (isdigit(*arg)) {
448 len = strtol(arg, &cp, 0);
449 if (len < 0 || len > 255 || arg == cp ||
450 (*cp != '\0' && *cp != ','))
451 break;
452 val |= len;
453 len = cp - arg;
454 } else {
455 for (cpp = fcsalt_strings; *cpp != NULL; cpp++) {
456 len = strlen(*cpp);
457 if (strncasecmp(arg, *cpp, len) == 0 &&
458 (arg[len] == '\0' || arg[len] == ','))
459 break;
460 }
461 if (*cpp == NULL)
462 break;
463 val |= 1<<(cpp-fcsalt_strings);
464 }
465 if (arg[len] == '\0') {
466 opt->neg_fcs = 1;
467 opt->fcs_type = val;
468 return (1);
469 }
470 arg += len+1;
471 }
472 }
473 option_error("Can't parse '%s' as an FCS type", arg);
474 return (0);
475 }
476
477 /*ARGSUSED*/
478 static int
setfcsallow(argv,opt)479 setfcsallow(argv, opt)
480 char **argv;
481 option_t *opt;
482 {
483 return str_to_fcstype(&lcp_allowoptions[0], *argv);
484 }
485
486 /*ARGSUSED*/
487 static int
setfcswant(argv,opt)488 setfcswant(argv, opt)
489 char **argv;
490 option_t *opt;
491 {
492 return str_to_fcstype(&lcp_wantoptions[0], *argv);
493 }
494 #endif
495
496 /*
497 * lcp_init - Initialize LCP.
498 */
499 static void
lcp_init(unit)500 lcp_init(unit)
501 int unit;
502 {
503 fsm *f = &lcp_fsm[unit];
504 lcp_options *wo = &lcp_wantoptions[unit];
505 lcp_options *ao = &lcp_allowoptions[unit];
506
507 f->unit = unit;
508 f->protocol = PPP_LCP;
509 f->callbacks = &lcp_callbacks;
510
511 fsm_init(f);
512
513 BZERO(wo, sizeof(*wo));
514 wo->neg_mru = 1;
515 wo->mru = PPP_MRU;
516 wo->neg_asyncmap = 1;
517 wo->chap_mdtype = CHAP_DIGEST_MD5;
518 wo->neg_magicnumber = 1;
519 wo->neg_pcompression = 1;
520 wo->neg_accompression = 1;
521
522 /*
523 * Leave allowed MRU (MTU) at zero; configuration option sets it
524 * non-zero if we should nak for something else.
525 */
526 BZERO(ao, sizeof(*ao));
527 ao->neg_mru = 1;
528 ao->neg_asyncmap = 1;
529 ao->neg_chap = 1;
530 #if defined(CHAPMS) || defined(CHAPMSV2)
531 #ifdef SOL2
532 /* Check if DES wasn't exported */
533 errno = 0;
534 setkey("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
535 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
536 if (errno == 0)
537 #endif
538 {
539 #ifdef CHAPMS
540 ao->neg_mschap = 1;
541 #endif
542 #ifdef CHAPMSV2
543 ao->neg_mschapv2 = 1;
544 #endif
545 }
546 #endif
547 ao->chap_mdtype = CHAP_DIGEST_MD5;
548 ao->neg_upap = 1;
549 ao->neg_magicnumber = 1;
550 ao->neg_pcompression = 1;
551 ao->neg_accompression = 1;
552 #ifdef CBCP_SUPPORT
553 ao->neg_cbcp = 1;
554 #endif
555 ao->neg_endpoint = 1;
556 #ifdef NEGOTIATE_FCS
557 ao->neg_fcs = 1;
558 ao->fcs_type = FCSALT_NULL|FCSALT_16|FCSALT_32;
559 #endif
560
561 BZERO(xmit_accm[unit], sizeof(xmit_accm[0]));
562 xmit_accm[unit][3] = 0x60000000;
563 }
564
565
566 /*
567 * lcp_open - LCP is allowed to come up.
568 */
569 void
lcp_open(unit)570 lcp_open(unit)
571 int unit;
572 {
573 fsm *f = &lcp_fsm[unit];
574 lcp_options *wo = &lcp_wantoptions[unit];
575
576 f->flags = 0;
577 if (wo->passive)
578 f->flags |= OPT_PASSIVE;
579 if (wo->silent)
580 f->flags |= OPT_SILENT;
581 fsm_open(f);
582 }
583
584
585 /*
586 * lcp_close - Take LCP down.
587 */
588 void
lcp_close(unit,reason)589 lcp_close(unit, reason)
590 int unit;
591 char *reason;
592 {
593 fsm *f = &lcp_fsm[unit];
594
595 if (phase != PHASE_DEAD)
596 new_phase(PHASE_TERMINATE);
597 if (f->state == STOPPED && (f->flags & (OPT_PASSIVE|OPT_SILENT))) {
598 /*
599 * This action is not strictly according to the FSM in RFC1548,
600 * but it does mean that the program terminates if you do a
601 * lcp_close() in passive/silent mode when a connection hasn't
602 * been established.
603 */
604 f->state = CLOSED;
605 lcp_finished(f);
606
607 } else
608 fsm_close(&lcp_fsm[unit], reason);
609 }
610
611
612 /*
613 * lcp_lowerup - The lower layer is up.
614 */
615 void
lcp_lowerup(unit)616 lcp_lowerup(unit)
617 int unit;
618 {
619 lcp_options *wo = &lcp_wantoptions[unit];
620 int mru, mtu;
621
622 mru = PPP_MRU > absmax_mru ? absmax_mru : PPP_MRU;
623 mtu = PPP_MTU > absmax_mtu ? absmax_mtu : PPP_MTU;
624
625 /*
626 * Don't use A/C or protocol compression on transmission,
627 * but accept A/C and protocol compressed packets
628 * if we are going to ask for A/C and protocol compression.
629 */
630 ppp_set_xaccm(unit, xmit_accm[unit]);
631 ppp_send_config(unit, mtu, 0xffffffff, 0, 0);
632 ppp_recv_config(unit, mru, (lax_recv? 0: 0xffffffff),
633 wo->neg_pcompression, wo->neg_accompression);
634 #ifdef NEGOTIATE_FCS
635 ppp_send_fcs(unit, FCSALT_16);
636 ppp_recv_fcs(unit, FCSALT_16);
637 #endif
638
639 fsm_setpeermru(unit, mtu);
640 lcp_allowoptions[unit].asyncmap = xmit_accm[unit][0];
641
642 fsm_lowerup(&lcp_fsm[unit]);
643 }
644
645
646 /*
647 * lcp_lowerdown - The lower layer is down.
648 */
649 void
lcp_lowerdown(unit)650 lcp_lowerdown(unit)
651 int unit;
652 {
653 fsm_lowerdown(&lcp_fsm[unit]);
654 }
655
656
657 /*
658 * lcp_input - Input LCP packet.
659 */
660 static void
lcp_input(unit,p,len)661 lcp_input(unit, p, len)
662 int unit;
663 u_char *p;
664 int len;
665 {
666 fsm *f = &lcp_fsm[unit];
667
668 fsm_input(f, p, len);
669 }
670
671
672 /*
673 * lcp_extcode - Handle a LCP-specific code.
674 */
675 static int
lcp_extcode(f,code,id,inp,len)676 lcp_extcode(f, code, id, inp, len)
677 fsm *f;
678 int code, id;
679 u_char *inp;
680 int len;
681 {
682 u_char *magp;
683
684 switch( code ){
685 case CODE_PROTREJ:
686 lcp_rprotrej(f, inp, len);
687 break;
688
689 case CODE_ECHOREQ:
690 if (f->state != OPENED)
691 break;
692 magp = inp;
693 PUTLONG(lcp_gotoptions[f->unit].magicnumber, magp);
694 fsm_sdata(f, CODE_ECHOREP, id, inp, len);
695 break;
696
697 case CODE_ECHOREP:
698 if (!lcp_received_echo_reply(f, id, inp, len)) {
699 lcp_echo_badreplies++;
700 if (lcp_echo_badreplies > LCP_ECHO_MAX_BADREPLIES) {
701 LcpLinkFailure(f);
702 lcp_echos_pending = 0;
703 lcp_echo_badreplies = 0;
704 }
705 }
706 break;
707
708 case CODE_DISCREQ:
709 break;
710
711 case CODE_IDENT:
712 /* More than one 'noident' tells us to reject the code number. */
713 if (noident > 1)
714 return 0;
715 lcp_received_identification(f, id, inp, len);
716 break;
717
718 case CODE_TIMEREMAIN:
719 lcp_received_timeremain(f, id, inp, len);
720 break;
721
722 default:
723 return 0;
724 }
725 return 1;
726 }
727
728 /*
729 * lcp_rprotrej - Receive an Protocol-Reject.
730 *
731 * Figure out which protocol is rejected and inform it.
732 */
733 static void
lcp_rprotrej(f,inp,len)734 lcp_rprotrej(f, inp, len)
735 fsm *f;
736 u_char *inp;
737 int len;
738 {
739 int i;
740 struct protent *protp;
741 u_short prot;
742
743 if (len < 2) {
744 dbglog("lcp_rprotrej: Rcvd short Protocol-Reject packet!");
745 return;
746 }
747
748 GETSHORT(prot, inp);
749
750 /*
751 * Protocol-Reject packets received in any state other than the LCP
752 * OPENED state SHOULD be silently discarded.
753 */
754 if( f->state != OPENED ){
755 dbglog("Protocol-Reject discarded: LCP in state %s",
756 fsm_state(f->state));
757 return;
758 }
759
760 /*
761 * Upcall the proper Protocol-Reject routine.
762 */
763 for (i = 0; (protp = protocols[i]) != NULL; ++i)
764 if (protp->protocol == prot && protp->enabled_flag) {
765 (*protp->protrej)(f->unit);
766 return;
767 }
768
769 warn("Protocol-Reject for unsupported protocol 0x%x", prot);
770 }
771
772
773 /*
774 * lcp_protrej - A Protocol-Reject was received.
775 */
776 /*ARGSUSED*/
777 static void
lcp_protrej(unit)778 lcp_protrej(unit)
779 int unit;
780 {
781 /*
782 * Can't reject LCP!
783 */
784 error("Received Protocol-Reject for LCP!");
785 }
786
787 /*
788 * lcp_coderej - A Code-Reject was received.
789 */
790 /*ARGSUSED*/
791 static int
lcp_coderej(f,code,id,inp,len)792 lcp_coderej(f, code, id, inp, len)
793 fsm *f;
794 int code;
795 int id;
796 u_char *inp;
797 int len;
798 {
799 /* The peer cannot reject these code numbers. */
800 if (code >= CODE_CONFREQ && code <= CODE_PROTREJ)
801 return 1;
802 switch (code) {
803 case CODE_ECHOREQ:
804 /*
805 * If the peer rejects an Echo-Request, then stop doing that.
806 */
807 if (lcp_echo_timer_running != 0) {
808 UNTIMEOUT (LcpEchoTimeout, f);
809 lcp_echo_timer_running = 0;
810 lcp_echo_interval = 0;
811 }
812 break;
813 }
814 return 0;
815 }
816
817 /*
818 * lcp_sprotrej - Send a Protocol-Reject for some protocol.
819 */
820 void
lcp_sprotrej(unit,p,len)821 lcp_sprotrej(unit, p, len)
822 int unit;
823 u_char *p;
824 int len;
825 {
826 /*
827 * Send back the protocol and the information field of the
828 * rejected packet. We only get here if LCP is in the OPENED state.
829 */
830 p += 2;
831 len -= 2;
832
833 fsm_sdata(&lcp_fsm[unit], CODE_PROTREJ, ++lcp_fsm[unit].id,
834 p, len);
835 }
836
837
838 /*
839 * lcp_resetci - Reset our CI.
840 */
841 static void
lcp_resetci(f)842 lcp_resetci(f)
843 fsm *f;
844 {
845 lcp_options *wo = &lcp_wantoptions[f->unit];
846 lcp_options *go = &lcp_gotoptions[f->unit];
847 lcp_options *ao = &lcp_allowoptions[f->unit];
848
849 wo->magicnumber = magic();
850 wo->numloops = 0;
851 sentident = 0;
852 *go = *wo;
853 if (!multilink) {
854 go->neg_mrru = 0;
855 go->neg_ssnhf = 0;
856 }
857 if (noendpoint)
858 ao->neg_endpoint = 0;
859 if (go->mru > absmax_mru)
860 go->mru = absmax_mru;
861 if (ao->mru > absmax_mtu)
862 ao->mru = absmax_mtu;
863 unsolicit_mru = 1;
864 fsm_setpeermru(f->unit, PPP_MTU > absmax_mtu ? absmax_mtu : PPP_MTU);
865 auth_reset(f->unit);
866 }
867
868
869 /*
870 * lcp_cilen - Return length of our CI.
871 */
872 static int
lcp_cilen(f)873 lcp_cilen(f)
874 fsm *f;
875 {
876 lcp_options *go = &lcp_gotoptions[f->unit];
877
878 #define LENCIVOID(neg) ((neg) ? CILEN_VOID : 0)
879 #define LENCICHAP(neg) ((neg) ? CILEN_CHAP : 0)
880 #define LENCICHAR(neg) ((neg) ? CILEN_CHAR : 0)
881 #define LENCISHORT(neg) ((neg) ? CILEN_SHORT : 0)
882 #define LENCILONG(neg) ((neg) ? CILEN_LONG : 0)
883 #define LENCILQR(neg) ((neg) ? CILEN_LQR: 0)
884 #define LENCICBCP(neg) ((neg) ? CILEN_CBCP: 0)
885 /*
886 * NB: we only ask for one of CHAP and UPAP, even if we will
887 * accept either.
888 */
889 return (LENCISHORT(go->neg_mru && go->mru != PPP_MRU) +
890 LENCILONG(go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) +
891 LENCICHAP(go->neg_chap || go->neg_mschap || go->neg_mschapv2) +
892 LENCISHORT(!go->neg_chap && go->neg_upap && !go->neg_mschap &&
893 !go->neg_mschapv2) +
894 LENCILQR(go->neg_lqr) +
895 LENCICBCP(go->neg_cbcp) +
896 LENCILONG(go->neg_magicnumber) +
897 LENCIVOID(go->neg_pcompression) +
898 LENCIVOID(go->neg_accompression) +
899 LENCICHAR(go->neg_fcs) +
900 LENCISHORT(go->neg_mrru) +
901 LENCIVOID(go->neg_ssnhf) +
902 #ifdef MUX_FRAME
903 LENCIVOID(go->pppmux) +
904 #endif
905 (go->neg_endpoint? CILEN_CHAR + go->endpoint.length: 0));
906 }
907
908
909 /*
910 * lcp_addci - Add our desired CIs to a packet.
911 */
912 static void
lcp_addci(f,ucp,lenp)913 lcp_addci(f, ucp, lenp)
914 fsm *f;
915 u_char *ucp;
916 int *lenp;
917 {
918 lcp_options *go = &lcp_gotoptions[f->unit];
919 lcp_options *ho = &lcp_hisoptions[f->unit];
920 u_char *start_ucp = ucp;
921
922 #define ADDCIVOID(opt, neg) \
923 if (neg) { \
924 PUTCHAR(opt, ucp); \
925 PUTCHAR(CILEN_VOID, ucp); \
926 }
927 #define ADDCISHORT(opt, neg, val) \
928 if (neg) { \
929 PUTCHAR(opt, ucp); \
930 PUTCHAR(CILEN_SHORT, ucp); \
931 PUTSHORT(val, ucp); \
932 }
933 #define ADDCICHAP(opt, neg, val, digest) \
934 if (neg) { \
935 PUTCHAR(opt, ucp); \
936 PUTCHAR(CILEN_CHAP, ucp); \
937 PUTSHORT(val, ucp); \
938 PUTCHAR(digest, ucp); \
939 }
940 #define ADDCILONG(opt, neg, val) \
941 if (neg) { \
942 PUTCHAR(opt, ucp); \
943 PUTCHAR(CILEN_LONG, ucp); \
944 PUTLONG(val, ucp); \
945 }
946 #define ADDCILQR(opt, neg, val) \
947 if (neg) { \
948 PUTCHAR(opt, ucp); \
949 PUTCHAR(CILEN_LQR, ucp); \
950 PUTSHORT(PPP_LQR, ucp); \
951 PUTLONG(val, ucp); \
952 }
953 #define ADDCICHAR(opt, neg, val) \
954 if (neg) { \
955 PUTCHAR(opt, ucp); \
956 PUTCHAR(CILEN_CHAR, ucp); \
957 PUTCHAR(val, ucp); \
958 }
959 #define ADDCIENDP(opt, neg, class, val, len) \
960 if (neg) { \
961 int i; \
962 PUTCHAR(opt, ucp); \
963 PUTCHAR(CILEN_CHAR + len, ucp); \
964 PUTCHAR(class, ucp); \
965 for (i = 0; i < len; ++i) \
966 PUTCHAR(val[i], ucp); \
967 }
968
969 ADDCISHORT(CI_MRU, go->neg_mru && go->mru != PPP_MRU, go->mru);
970 ADDCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF,
971 go->asyncmap);
972 /* go->chap_mdtype always points to a useful value */
973 ADDCICHAP(CI_AUTHTYPE, go->neg_chap || go->neg_mschap || go->neg_mschapv2,
974 PPP_CHAP, go->chap_mdtype);
975 ADDCISHORT(CI_AUTHTYPE, !(go->neg_chap || go->neg_mschap ||
976 go->neg_mschapv2) && go->neg_upap, PPP_PAP);
977 /* We can't both say zero for LQR period. */
978 if (f->state == ACKSENT && go->neg_lqr && go->lqr_period == 0 &&
979 ho->neg_lqr && ho->lqr_period == 0)
980 go->lqr_period = 500;
981 ADDCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period);
982 ADDCICHAR(CI_CALLBACK, go->neg_cbcp, CBOP_CBCP);
983 ADDCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber);
984 ADDCIVOID(CI_PCOMPRESSION, go->neg_pcompression);
985 ADDCIVOID(CI_ACCOMPRESSION, go->neg_accompression);
986 ADDCICHAR(CI_FCSALTERN, (go->neg_fcs && go->fcs_type != 0), go->fcs_type);
987 ADDCIENDP(CI_EPDISC, go->neg_endpoint, go->endpoint.class,
988 go->endpoint.value, go->endpoint.length);
989 #ifdef MUX_FRAME
990 ADDCIVOID(CI_MUXING, go->pppmux);
991 #endif
992 ADDCISHORT(CI_MRRU, go->neg_mrru, go->mrru);
993 ADDCIVOID(CI_SSNHF, go->neg_ssnhf);
994
995 if (ucp - start_ucp != *lenp) {
996 /* this should never happen, because peer_mtu should be 1500 */
997 error("Bug in lcp_addci: wrong length");
998 }
999 }
1000
1001
1002 /*
1003 * lcp_ackci - Ack our CIs.
1004 * This should not modify any state if the Ack is bad.
1005 *
1006 * Returns:
1007 * 0 - Ack was bad.
1008 * 1 - Ack was good.
1009 */
1010 static int
lcp_ackci(f,p,len)1011 lcp_ackci(f, p, len)
1012 fsm *f;
1013 u_char *p;
1014 int len;
1015 {
1016 lcp_options *go = &lcp_gotoptions[f->unit];
1017 #ifdef MUX_FRAME
1018 lcp_options *ao = &lcp_allowoptions[f->unit];
1019 #endif
1020 u_char cilen, citype, cichar;
1021 u_short cishort;
1022 u_int32_t cilong;
1023
1024 /*
1025 * CIs must be in exactly the same order that we sent.
1026 * Check packet length and CI length at each step.
1027 * If we find any deviations, then this packet is bad.
1028 */
1029 #define ACKCIVOID(opt, neg) \
1030 if (neg) { \
1031 if ((len -= CILEN_VOID) < 0) \
1032 goto bad; \
1033 GETCHAR(citype, p); \
1034 GETCHAR(cilen, p); \
1035 if (cilen != CILEN_VOID || \
1036 citype != opt) \
1037 goto bad; \
1038 }
1039 #define ACKCISHORT(opt, neg, val) \
1040 if (neg) { \
1041 if ((len -= CILEN_SHORT) < 0) \
1042 goto bad; \
1043 GETCHAR(citype, p); \
1044 GETCHAR(cilen, p); \
1045 if (cilen != CILEN_SHORT || \
1046 citype != opt) \
1047 goto bad; \
1048 GETSHORT(cishort, p); \
1049 if (cishort != val) \
1050 goto bad; \
1051 }
1052 #define ACKCIAUTH(opt, neg, val) \
1053 if (neg) { \
1054 if ((len -= CILEN_SHORT) < 0) \
1055 goto bad; \
1056 GETCHAR(citype, p); \
1057 GETCHAR(cilen, p); \
1058 if (cilen != CILEN_SHORT || \
1059 citype != opt) \
1060 goto bad; \
1061 GETSHORT(cishort, p); \
1062 if (cishort != val) \
1063 goto bad; \
1064 peer_nak_auth = 0; \
1065 peer_reject_auth = 0; \
1066 }
1067 #define ACKCICHAR(opt, neg, val) \
1068 if (neg) { \
1069 if ((len -= CILEN_CHAR) < 0) \
1070 goto bad; \
1071 GETCHAR(citype, p); \
1072 GETCHAR(cilen, p); \
1073 if (cilen != CILEN_CHAR || \
1074 citype != opt) \
1075 goto bad; \
1076 GETCHAR(cichar, p); \
1077 if (cichar != val) \
1078 goto bad; \
1079 }
1080 #define ACKCICHAP(opt, neg, val, digest) \
1081 if (neg) { \
1082 if ((len -= CILEN_CHAP) < 0) \
1083 goto bad; \
1084 GETCHAR(citype, p); \
1085 GETCHAR(cilen, p); \
1086 if (cilen != CILEN_CHAP || \
1087 citype != opt) \
1088 goto bad; \
1089 GETSHORT(cishort, p); \
1090 if (cishort != val) \
1091 goto bad; \
1092 GETCHAR(cichar, p); \
1093 if (cichar != digest) \
1094 goto bad; \
1095 peer_nak_auth = 0; \
1096 peer_reject_auth = 0; \
1097 }
1098 #define ACKCILONG(opt, neg, val) \
1099 if (neg) { \
1100 if ((len -= CILEN_LONG) < 0) \
1101 goto bad; \
1102 GETCHAR(citype, p); \
1103 GETCHAR(cilen, p); \
1104 if (cilen != CILEN_LONG || \
1105 citype != opt) \
1106 goto bad; \
1107 GETLONG(cilong, p); \
1108 if (cilong != val) \
1109 goto bad; \
1110 }
1111 #define ACKCILQR(opt, neg, val) \
1112 if (neg) { \
1113 if ((len -= CILEN_LQR) < 0) \
1114 goto bad; \
1115 GETCHAR(citype, p); \
1116 GETCHAR(cilen, p); \
1117 if (cilen != CILEN_LQR || \
1118 citype != opt) \
1119 goto bad; \
1120 GETSHORT(cishort, p); \
1121 if (cishort != PPP_LQR) \
1122 goto bad; \
1123 GETLONG(cilong, p); \
1124 if (cilong != val) \
1125 goto bad; \
1126 }
1127 #define ACKCIENDP(opt, neg, class, val, vlen) \
1128 if (neg) { \
1129 int i; \
1130 if ((len -= CILEN_CHAR + vlen) < 0) \
1131 goto bad; \
1132 GETCHAR(citype, p); \
1133 GETCHAR(cilen, p); \
1134 if (cilen != CILEN_CHAR + vlen || \
1135 citype != opt) \
1136 goto bad; \
1137 GETCHAR(cichar, p); \
1138 if (cichar != class) \
1139 goto bad; \
1140 for (i = 0; i < vlen; ++i) { \
1141 GETCHAR(cichar, p); \
1142 if (cichar != val[i]) \
1143 goto bad; \
1144 } \
1145 }
1146
1147 ACKCISHORT(CI_MRU, go->neg_mru && go->mru != PPP_MRU, go->mru);
1148 ACKCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF,
1149 go->asyncmap);
1150 /* go->chap_mdtype always points to a useful value */
1151 ACKCICHAP(CI_AUTHTYPE, go->neg_chap || go->neg_mschap || go->neg_mschapv2,
1152 PPP_CHAP, go->chap_mdtype);
1153 ACKCIAUTH(CI_AUTHTYPE, !(go->neg_chap || go->neg_mschap ||
1154 go->neg_mschapv2) && go->neg_upap, PPP_PAP);
1155 ACKCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period);
1156 ACKCICHAR(CI_CALLBACK, go->neg_cbcp, CBOP_CBCP);
1157 ACKCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber);
1158 ACKCIVOID(CI_PCOMPRESSION, go->neg_pcompression);
1159 ACKCIVOID(CI_ACCOMPRESSION, go->neg_accompression);
1160 ACKCICHAR(CI_FCSALTERN, go->neg_fcs, go->fcs_type);
1161 ACKCIENDP(CI_EPDISC, go->neg_endpoint, go->endpoint.class,
1162 go->endpoint.value, go->endpoint.length);
1163 #ifdef MUX_FRAME
1164 ACKCIVOID(CI_MUXING, go->pppmux);
1165 if (go->pppmux)
1166 go->pppmux = ao->pppmux;
1167 #endif
1168 ACKCISHORT(CI_MRRU, go->neg_mrru, go->mrru);
1169 ACKCIVOID(CI_SSNHF, go->neg_ssnhf);
1170
1171 /*
1172 * If there are any remaining CIs, then this packet is bad.
1173 */
1174 if (len != 0)
1175 goto bad;
1176 return (1);
1177 bad:
1178 dbglog("lcp_acki: received bad Ack!");
1179 return (0);
1180 }
1181
1182
1183 /*
1184 * lcp_nakci - Peer has sent a NAK for some of our CIs.
1185 * This should not modify any state if the Nak is bad
1186 * or if LCP is in the OPENED state.
1187 *
1188 * Returns:
1189 * 0 - Nak was bad.
1190 * 1 - Nak was good.
1191 */
1192 static int
lcp_nakci(f,p,len)1193 lcp_nakci(f, p, len)
1194 fsm *f;
1195 u_char *p;
1196 int len;
1197 {
1198 lcp_options *go = &lcp_gotoptions[f->unit];
1199 lcp_options *wo = &lcp_wantoptions[f->unit];
1200 u_char citype, cichar, *next;
1201 u_short cishort;
1202 u_int32_t cilong;
1203 lcp_options no; /* options we've seen Naks for */
1204 lcp_options try; /* options to request next time */
1205 int looped_back = 0;
1206 int cilen;
1207
1208 BZERO(&no, sizeof(no));
1209 try = *go;
1210
1211 /*
1212 * Any Nak'd CIs must be in exactly the same order that we sent.
1213 * Check packet length and CI length at each step.
1214 * If we find any deviations, then this packet is bad.
1215 */
1216 #define NAKCIVOID(opt, neg) \
1217 if (go->neg && \
1218 len >= CILEN_VOID && \
1219 p[1] == CILEN_VOID && \
1220 p[0] == opt) { \
1221 len -= CILEN_VOID; \
1222 INCPTR(CILEN_VOID, p); \
1223 no.neg = 1; \
1224 try.neg = 0; \
1225 }
1226 #define NAKCICHAR(opt, neg, code) \
1227 if (go->neg && \
1228 len >= CILEN_CHAR && \
1229 p[1] == CILEN_CHAR && \
1230 p[0] == opt) { \
1231 len -= CILEN_CHAR; \
1232 INCPTR(2, p); \
1233 GETCHAR(cichar, p); \
1234 no.neg = 1; \
1235 code \
1236 }
1237 #define NAKCISHORT(opt, neg, code) \
1238 if (go->neg && \
1239 len >= CILEN_SHORT && \
1240 p[1] == CILEN_SHORT && \
1241 p[0] == opt) { \
1242 len -= CILEN_SHORT; \
1243 INCPTR(2, p); \
1244 GETSHORT(cishort, p); \
1245 no.neg = 1; \
1246 code \
1247 }
1248 #define NAKCILONG(opt, neg, code) \
1249 if (go->neg && \
1250 len >= CILEN_LONG && \
1251 p[1] == CILEN_LONG && \
1252 p[0] == opt) { \
1253 len -= CILEN_LONG; \
1254 INCPTR(2, p); \
1255 GETLONG(cilong, p); \
1256 no.neg = 1; \
1257 code \
1258 }
1259 #define NAKCILQR(opt, neg, code) \
1260 if (go->neg && \
1261 len >= CILEN_LQR && \
1262 p[1] == CILEN_LQR && \
1263 p[0] == opt) { \
1264 len -= CILEN_LQR; \
1265 INCPTR(2, p); \
1266 GETSHORT(cishort, p); \
1267 GETLONG(cilong, p); \
1268 no.neg = 1; \
1269 code \
1270 }
1271 #define NAKCIENDP(opt, neg) \
1272 if (go->neg && \
1273 len >= CILEN_CHAR && \
1274 p[0] == opt && \
1275 p[1] >= CILEN_CHAR && \
1276 p[1] <= len) { \
1277 len -= p[1]; \
1278 INCPTR(p[1], p); \
1279 no.neg = 1; \
1280 try.neg = 0; \
1281 }
1282
1283 /*
1284 * We don't care if they want to send us smaller packets than
1285 * we want. Therefore, accept any MRU less than what we asked for,
1286 * but then ignore the new value when setting the MRU in the kernel.
1287 * If they send us a bigger MRU than what we asked, accept it, up to
1288 * the limit of the default MRU we'd get if we didn't negotiate.
1289 */
1290 if (go->neg_mru && go->mru != PPP_MRU) {
1291 NAKCISHORT(CI_MRU, neg_mru,
1292 if (cishort <= wo->mru ||
1293 (cishort <= PPP_MRU && cishort <= absmax_mru))
1294 try.mru = cishort;
1295 );
1296 }
1297
1298 /*
1299 * Add any characters they want to our (receive-side) asyncmap.
1300 */
1301 if (go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) {
1302 NAKCILONG(CI_ASYNCMAP, neg_asyncmap,
1303 try.asyncmap = go->asyncmap | cilong;
1304 );
1305 }
1306
1307 /*
1308 * If they've nak'd our authentication-protocol, check whether
1309 * they are proposing a different protocol, or a different
1310 * hash algorithm for CHAP.
1311 */
1312 if ((go->neg_chap || go->neg_mschap || go->neg_mschapv2 || go->neg_upap) &&
1313 len >= CILEN_SHORT && p[0] == CI_AUTHTYPE && p[1] >= CILEN_SHORT &&
1314 p[1] <= len) {
1315 cilen = p[1];
1316 len -= cilen;
1317 INCPTR(2, p);
1318 GETSHORT(cishort, p);
1319 peer_nak_auth = 1;
1320 nak_auth_orig = (go->neg_chap || go->neg_mschap || go->neg_mschapv2) ?
1321 PPP_CHAP : PPP_PAP;
1322 nak_auth_proto = cishort;
1323 if (cishort == PPP_PAP && cilen == CILEN_SHORT) {
1324 no.neg_upap = go->neg_upap;
1325 /*
1326 * If we were asking for CHAP, they obviously don't want to do it.
1327 * If we weren't asking for CHAP, then we were asking for PAP,
1328 * in which case this Nak is bad.
1329 */
1330 if (!go->neg_chap && !go->neg_mschap && !go->neg_mschapv2)
1331 goto bad;
1332 try.neg_chap = 0;
1333 try.neg_mschap = 0;
1334 try.neg_mschapv2 = 0;
1335
1336 } else if (cishort == PPP_CHAP && cilen >= CILEN_CHAP) {
1337 /* stop asking for that type */
1338 switch (go->chap_mdtype) {
1339 case CHAP_DIGEST_MD5:
1340 no.neg_chap = go->neg_chap;
1341 try.neg_chap = 0;
1342 break;
1343 case CHAP_MICROSOFT:
1344 no.neg_mschap = go->neg_mschap;
1345 try.neg_mschap = 0;
1346 break;
1347 case CHAP_MICROSOFT_V2:
1348 no.neg_mschapv2 = go->neg_mschapv2;
1349 try.neg_mschapv2 = 0;
1350 break;
1351 }
1352 GETCHAR(cichar, p);
1353 /* Allow >= on length here for broken and silly peers. */
1354 p += cilen - CILEN_CHAP;
1355 try.neg_upap = 0;
1356 if ((cichar == CHAP_DIGEST_MD5 && wo->neg_chap) ||
1357 (cichar == CHAP_MICROSOFT && wo->neg_mschap) ||
1358 (cichar == CHAP_MICROSOFT_V2 && wo->neg_mschapv2)) {
1359 /* Try his requested algorithm. */
1360 try.chap_mdtype = cichar;
1361 } else {
1362 goto try_another;
1363 }
1364
1365 } else {
1366 /*
1367 * We don't recognize what they're suggesting.
1368 * Stop asking for what we were asking for.
1369 */
1370 try_another:
1371 if (go->neg_chap || go->neg_mschap || go->neg_mschapv2) {
1372 switch (go->chap_mdtype) {
1373 case CHAP_DIGEST_MD5:
1374 try.neg_chap = 0;
1375 if (wo->neg_mschap) {
1376 try.chap_mdtype = CHAP_MICROSOFT;
1377 break;
1378 }
1379 /*FALLTHROUGH*/
1380 case CHAP_MICROSOFT:
1381 try.neg_mschap = 0;
1382 if (wo->neg_mschapv2) {
1383 try.chap_mdtype = CHAP_MICROSOFT_V2;
1384 break;
1385 }
1386 /*FALLTHROUGH*/
1387 case CHAP_MICROSOFT_V2:
1388 try.neg_mschapv2 = 0;
1389 break;
1390 }
1391 } else
1392 try.neg_upap = 0;
1393 p += cilen - CILEN_SHORT;
1394 }
1395 }
1396
1397 /*
1398 * If they can't cope with our link quality protocol, we'll have
1399 * to stop asking for LQR. We haven't got any other protocol. If
1400 * they Nak the reporting period, then the following logic
1401 * applies:
1402 * If he suggests zero and go->neg_fcs is true and
1403 * ao->lqr_period isn't zero, then take his suggestion. If he
1404 * suggests zero otherwise, ignore it. If he suggests a nonzero
1405 * value and wo->lqr_period is zero, then take his suggestion. If
1406 * he suggests a nonzero value otherwise that's less than
1407 * wo->lqr_period, then ignore it.
1408 */
1409 NAKCILQR(CI_QUALITY, neg_lqr,
1410 if (cishort != PPP_LQR)
1411 try.neg_lqr = 0;
1412 else if (cilong == 0 && go->neg_fcs && wo->lqr_period != 0)
1413 try.lqr_period = cilong;
1414 else if (cilong != 0 &&
1415 (wo->lqr_period == 0 || cilong > wo->lqr_period))
1416 try.lqr_period = cilong;
1417 );
1418
1419 /*
1420 * Only implementing CBCP...not the rest of the callback options
1421 */
1422 NAKCICHAR(CI_CALLBACK, neg_cbcp,
1423 try.neg_cbcp = 0;
1424 );
1425
1426 /*
1427 * Check for a looped-back line.
1428 */
1429 NAKCILONG(CI_MAGICNUMBER, neg_magicnumber,
1430 try.magicnumber = magic();
1431 looped_back = 1;
1432 );
1433
1434 /*
1435 * Peer shouldn't send Nak for protocol compression or
1436 * address/control compression requests; they should send
1437 * a Reject instead. If they send a Nak, treat it as a Reject.
1438 */
1439 NAKCIVOID(CI_PCOMPRESSION, neg_pcompression);
1440 NAKCIVOID(CI_ACCOMPRESSION, neg_accompression);
1441
1442 /*
1443 * Remove any FCS types he doesn't like from our (receive-side)
1444 * FCS list.
1445 */
1446 NAKCICHAR(CI_FCSALTERN, neg_fcs, try.fcs_type = go->fcs_type & cichar;);
1447
1448 #ifdef MUX_FRAME
1449 /* Nacked MUX option */
1450 NAKCIVOID(CI_MUXING, pppmux);
1451 #endif
1452
1453 /*
1454 * Nak of the endpoint discriminator option is not permitted,
1455 * treat it like a reject.
1456 */
1457 NAKCIENDP(CI_EPDISC, neg_endpoint);
1458
1459 /*
1460 * Nak for MRRU option - accept their value if it is smaller
1461 * than the one we want.
1462 */
1463 if (go->neg_mrru) {
1464 NAKCISHORT(CI_MRRU, neg_mrru,
1465 if (cishort <= wo->mrru)
1466 try.mrru = cishort;
1467 );
1468 }
1469
1470 /*
1471 * Nak for short sequence numbers shouldn't be sent, treat it
1472 * like a reject.
1473 */
1474 NAKCIVOID(CI_SSNHF, neg_ssnhf);
1475
1476 /*
1477 * There may be remaining CIs, if the peer is requesting negotiation
1478 * on an option that we didn't include in our request packet.
1479 * If we see an option that we requested, or one we've already seen
1480 * in this packet, then this packet is bad.
1481 * If we wanted to respond by starting to negotiate on the requested
1482 * option(s), we could, but we don't, because except for the
1483 * authentication type and quality protocol, if we are not negotiating
1484 * an option, it is because we were told not to.
1485 * For the authentication type, the Nak from the peer means
1486 * `let me authenticate myself with you' which is a bit pointless.
1487 * For the quality protocol, the Nak means `ask me to send you quality
1488 * reports', but if we didn't ask for them, we don't want them.
1489 * An option we don't recognize represents the peer asking to
1490 * negotiate some option we don't support, so ignore it.
1491 */
1492 while (len > CILEN_VOID) {
1493 GETCHAR(citype, p);
1494 GETCHAR(cilen, p);
1495 if (cilen < CILEN_VOID || (len -= cilen) < 0)
1496 goto bad;
1497 next = p + cilen - 2;
1498
1499 switch (citype) {
1500 case CI_MRU:
1501 if ((go->neg_mru && go->mru != PPP_MRU)
1502 || no.neg_mru || cilen != CILEN_SHORT)
1503 goto bad;
1504 GETSHORT(cishort, p);
1505 if (cishort < PPP_MRU && cishort < absmax_mru) {
1506 try.neg_mru = 1;
1507 try.mru = cishort;
1508 notice("Peer sent unsolicited Nak for MRU less than default.");
1509 }
1510 break;
1511 case CI_ASYNCMAP:
1512 if ((go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF)
1513 || no.neg_asyncmap || cilen != CILEN_LONG)
1514 goto bad;
1515 break;
1516 case CI_AUTHTYPE:
1517 unsolicited_nak_auth = 1;
1518 if (cilen >= CILEN_SHORT) {
1519 GETSHORT(unsolicit_auth_proto, p);
1520 } else {
1521 unsolicit_auth_proto = 0;
1522 }
1523 if (go->neg_chap || no.neg_chap ||
1524 go->neg_mschap || no.neg_mschap ||
1525 go->neg_mschapv2 || no.neg_mschapv2 ||
1526 go->neg_upap || no.neg_upap)
1527 goto bad;
1528 break;
1529 case CI_MAGICNUMBER:
1530 if (go->neg_magicnumber || no.neg_magicnumber ||
1531 cilen != CILEN_LONG)
1532 goto bad;
1533 break;
1534 case CI_PCOMPRESSION:
1535 if (go->neg_pcompression || no.neg_pcompression
1536 || cilen != CILEN_VOID)
1537 goto bad;
1538 break;
1539 case CI_ACCOMPRESSION:
1540 if (go->neg_accompression || no.neg_accompression
1541 || cilen != CILEN_VOID)
1542 goto bad;
1543 break;
1544 case CI_QUALITY:
1545 if (go->neg_lqr || no.neg_lqr || cilen != CILEN_LQR)
1546 goto bad;
1547 break;
1548 case CI_MRRU:
1549 if (go->neg_mrru || no.neg_mrru || cilen != CILEN_SHORT)
1550 goto bad;
1551 break;
1552 case CI_SSNHF:
1553 if (go->neg_ssnhf || no.neg_ssnhf || cilen != CILEN_VOID)
1554 goto bad;
1555 try.neg_ssnhf = 1;
1556 break;
1557 case CI_EPDISC:
1558 if (go->neg_endpoint || no.neg_endpoint || cilen < CILEN_CHAR)
1559 goto bad;
1560 break;
1561 case CI_FCSALTERN:
1562 if (go->neg_fcs || no.neg_fcs || cilen < CILEN_CHAR)
1563 goto bad;
1564 break;
1565 #ifdef MUX_FRAME
1566 case CI_MUXING:
1567 if (go->pppmux || no.pppmux || cilen < CILEN_VOID)
1568 goto bad;
1569 break;
1570 #endif
1571 }
1572 p = next;
1573 }
1574
1575 /*
1576 * OK, the Nak is good. Now we can update state.
1577 * If there are any options left we ignore them.
1578 */
1579 if (f->state != OPENED) {
1580 /*
1581 * Note: the code once reset try.numloops to zero here if
1582 * looped_back wasn't set. This is wrong because a mixture of
1583 * looped-back and peer data (possible if half-duplex is used)
1584 * will allow the link to come up, and it shouldn't.
1585 */
1586 if (looped_back) {
1587 if (++try.numloops >= lcp_loopbackfail) {
1588 notice("Serial line is looped back.");
1589 lcp_close(f->unit, "Loopback detected");
1590 status = EXIT_LOOPBACK;
1591 }
1592 }
1593 *go = try;
1594 }
1595
1596 return 1;
1597
1598 bad:
1599 dbglog("lcp_nakci: received bad Nak!");
1600 return 0;
1601 }
1602
1603
1604 /*
1605 * lcp_rejci - Peer has Rejected some of our CIs.
1606 * This should not modify any state if the Reject is bad
1607 * or if LCP is in the OPENED state.
1608 *
1609 * Returns:
1610 * 0 - Reject was bad.
1611 * 1 - Reject was good.
1612 */
1613 static int
lcp_rejci(f,p,len)1614 lcp_rejci(f, p, len)
1615 fsm *f;
1616 u_char *p;
1617 int len;
1618 {
1619 lcp_options *go = &lcp_gotoptions[f->unit];
1620 u_char cichar;
1621 u_short cishort;
1622 u_int32_t cilong;
1623 lcp_options try; /* options to request next time */
1624
1625 try = *go;
1626
1627 /*
1628 * Any Rejected CIs must be in exactly the same order that we sent.
1629 * Check packet length and CI length at each step.
1630 * If we find any deviations, then this packet is bad.
1631 */
1632 #define REJCIVOID(opt, neg) \
1633 if (go->neg && \
1634 len >= CILEN_VOID && \
1635 p[1] == CILEN_VOID && \
1636 p[0] == opt) { \
1637 len -= CILEN_VOID; \
1638 INCPTR(CILEN_VOID, p); \
1639 try.neg = 0; \
1640 }
1641 #define REJCICHAR(opt, neg, val) \
1642 if (go->neg && \
1643 len >= CILEN_CHAR && \
1644 p[1] == CILEN_CHAR && \
1645 p[0] == opt) { \
1646 len -= CILEN_CHAR; \
1647 INCPTR(2, p); \
1648 GETCHAR(cichar, p); \
1649 /* Check rejected value. */ \
1650 if (cichar != val) \
1651 goto bad; \
1652 try.neg = 0; \
1653 }
1654 #define REJCISHORT(opt, neg, val) \
1655 if (go->neg && \
1656 len >= CILEN_SHORT && \
1657 p[1] == CILEN_SHORT && \
1658 p[0] == opt) { \
1659 len -= CILEN_SHORT; \
1660 INCPTR(2, p); \
1661 GETSHORT(cishort, p); \
1662 /* Check rejected value. */ \
1663 if (cishort != val) \
1664 goto bad; \
1665 try.neg = 0; \
1666 }
1667 #define REJCIAUTH(opt, neg, val) \
1668 if (go->neg && \
1669 len >= CILEN_SHORT && \
1670 p[1] == CILEN_SHORT && \
1671 p[0] == opt) { \
1672 len -= CILEN_SHORT; \
1673 INCPTR(2, p); \
1674 GETSHORT(cishort, p); \
1675 /* Check rejected value. */ \
1676 peer_reject_auth = 1; \
1677 reject_auth_proto = cishort; \
1678 if (cishort != val) \
1679 goto bad; \
1680 try.neg = 0; \
1681 }
1682 #define REJCILONG(opt, neg, val) \
1683 if (go->neg && \
1684 len >= CILEN_LONG && \
1685 p[1] == CILEN_LONG && \
1686 p[0] == opt) { \
1687 len -= CILEN_LONG; \
1688 INCPTR(2, p); \
1689 GETLONG(cilong, p); \
1690 /* Check rejected value. */ \
1691 if (cilong != val) \
1692 goto bad; \
1693 try.neg = 0; \
1694 }
1695 #define REJCILQR(opt, neg, val) \
1696 if (go->neg && \
1697 len >= CILEN_LQR && \
1698 p[1] == CILEN_LQR && \
1699 p[0] == opt) { \
1700 len -= CILEN_LQR; \
1701 INCPTR(2, p); \
1702 GETSHORT(cishort, p); \
1703 GETLONG(cilong, p); \
1704 /* Check rejected value. */ \
1705 if (cishort != PPP_LQR || cilong != val) \
1706 goto bad; \
1707 try.neg = 0; \
1708 }
1709 #define REJCICBCP(opt, neg, val) \
1710 if (go->neg && \
1711 len >= CILEN_CBCP && \
1712 p[1] == CILEN_CBCP && \
1713 p[0] == opt) { \
1714 len -= CILEN_CBCP; \
1715 INCPTR(2, p); \
1716 GETCHAR(cichar, p); \
1717 /* Check rejected value. */ \
1718 if (cichar != val) \
1719 goto bad; \
1720 try.neg = 0; \
1721 }
1722 #define REJCIENDP(opt, neg, class, val, vlen) \
1723 if (go->neg && \
1724 len >= CILEN_CHAR + vlen && \
1725 p[0] == opt && \
1726 p[1] == CILEN_CHAR + vlen) { \
1727 int i; \
1728 len -= CILEN_CHAR + vlen; \
1729 INCPTR(2, p); \
1730 GETCHAR(cichar, p); \
1731 if (cichar != class) \
1732 goto bad; \
1733 for (i = 0; i < vlen; ++i) { \
1734 GETCHAR(cichar, p); \
1735 if (cichar != val[i]) \
1736 goto bad; \
1737 } \
1738 try.neg = 0; \
1739 }
1740
1741 /* Received a Configure-Reject, try to send Identification now. */
1742 if (!noident && sentident < 3) {
1743 LcpSendIdentification(f);
1744 sentident++;
1745 }
1746
1747 REJCISHORT(CI_MRU, neg_mru, go->mru);
1748 REJCILONG(CI_ASYNCMAP, neg_asyncmap, go->asyncmap);
1749
1750 /*
1751 * There are broken peers (such as unbundled Solaris PPP) that
1752 * send Configure-Reject for authentication when they really
1753 * intend Configure-Nak. This code works around this problem.
1754 */
1755 if ((go->neg_chap || go->neg_mschap || go->neg_mschapv2) &&
1756 len >= CILEN_CHAP && p[1] == CILEN_CHAP && p[0] == CI_AUTHTYPE) {
1757 len -= CILEN_CHAP;
1758 INCPTR(2, p);
1759 GETSHORT(cishort, p);
1760 GETCHAR(cichar, p);
1761 peer_reject_auth = 1;
1762 reject_auth_proto = cishort;
1763 /* Check rejected value. */
1764 if (cishort != PPP_CHAP || cichar != go->chap_mdtype)
1765 goto bad;
1766 /* Disable the one that he rejected */
1767 switch (cichar) {
1768 case CHAP_DIGEST_MD5:
1769 try.neg_chap = 0;
1770 break;
1771 case CHAP_MICROSOFT:
1772 try.neg_mschap = 0;
1773 break;
1774 case CHAP_MICROSOFT_V2:
1775 try.neg_mschapv2 = 0;
1776 break;
1777 }
1778 /* Try another, if we can. */
1779 if (try.neg_chap)
1780 try.chap_mdtype = CHAP_DIGEST_MD5;
1781 else if (try.neg_mschap)
1782 try.chap_mdtype = CHAP_MICROSOFT;
1783 else
1784 try.chap_mdtype = CHAP_MICROSOFT_V2;
1785 }
1786
1787 if (!go->neg_chap && !go->neg_mschap && !go->neg_mschapv2) {
1788 REJCIAUTH(CI_AUTHTYPE, neg_upap, PPP_PAP);
1789 }
1790 REJCILQR(CI_QUALITY, neg_lqr, go->lqr_period);
1791 REJCICBCP(CI_CALLBACK, neg_cbcp, CBOP_CBCP);
1792 REJCILONG(CI_MAGICNUMBER, neg_magicnumber, go->magicnumber);
1793 REJCIVOID(CI_PCOMPRESSION, neg_pcompression);
1794 REJCIVOID(CI_ACCOMPRESSION, neg_accompression);
1795 REJCICHAR(CI_FCSALTERN, neg_fcs, go->fcs_type);
1796 #ifdef MUX_FRAME
1797 REJCIVOID(CI_MUXING,pppmux);
1798 #endif
1799 REJCIENDP(CI_EPDISC, neg_endpoint, go->endpoint.class,
1800 go->endpoint.value, go->endpoint.length);
1801 REJCISHORT(CI_MRRU, neg_mrru, go->mrru);
1802 REJCIVOID(CI_SSNHF, neg_ssnhf);
1803
1804 /*
1805 * If there are any remaining CIs, then this packet is bad.
1806 */
1807 if (len != 0)
1808 goto bad;
1809 /*
1810 * Now we can update state.
1811 */
1812 if (f->state != OPENED)
1813 *go = try;
1814 return 1;
1815
1816 bad:
1817 dbglog("lcp_rejci: received bad Reject!");
1818 return 0;
1819 }
1820
1821
1822 /*
1823 * lcp_reqci - Check the peer's requested CIs and send appropriate response.
1824 *
1825 * Returns: CODE_CONFACK, CODE_CONFNAK or CODE_CONFREJ and input
1826 * packet modified appropriately. If reject_if_disagree is non-zero,
1827 * doesn't return CODE_CONFNAK; returns CODE_CONFREJ if it can't
1828 * return CODE_CONFACK.
1829 */
1830 static int
lcp_reqci(f,p,lenp,dont_nak)1831 lcp_reqci(f, p, lenp, dont_nak)
1832 fsm *f;
1833 u_char *p; /* Requested CIs */
1834 int *lenp; /* Length of requested CIs */
1835 int dont_nak;
1836 {
1837 lcp_options *wo = &lcp_wantoptions[f->unit];
1838 lcp_options *go = &lcp_gotoptions[f->unit];
1839 lcp_options *ho = &lcp_hisoptions[f->unit];
1840 lcp_options *ao = &lcp_allowoptions[f->unit];
1841 int cilen, citype, cichar; /* Parsed len, type, char value */
1842 u_short cishort; /* Parsed short value */
1843 u_int32_t cilong; /* Parse long value */
1844 int ret, newret;
1845 u_char *p0, *nakp, *rejp, *prev;
1846 int len;
1847
1848 /*
1849 * Loop through options once to find out if peer is offering
1850 * Multilink, and repair values as needed.
1851 */
1852 ao->mru = ao->mrru;
1853 p0 = p;
1854 for (len = *lenp; len > 0; len -= cilen, p = prev + cilen) {
1855 if (len < 2 || p[1] > len) {
1856 /*
1857 * RFC 1661 page 40 -- if the option extends beyond the
1858 * packet, then discard the entire packet.
1859 */
1860 dbglog("discarding LCP Configure-Request due to truncated option");
1861 return (0);
1862 }
1863 prev = p;
1864 GETCHAR(citype, p);
1865 GETCHAR(cilen, p);
1866 if (citype == CI_MRRU) {
1867 if (ao->mrru != 0) {
1868 if (ao->mrru+6 > PPP_MTU)
1869 ao->mru = PPP_MTU;
1870 else
1871 ao->mru = ao->mrru + 6;
1872 }
1873 }
1874 if (cilen < 2)
1875 cilen = 2;
1876 }
1877 if (ao->mru > absmax_mtu)
1878 ao->mru = absmax_mtu;
1879
1880 ret = CODE_CONFACK;
1881 rejp = p = p0;
1882 nakp = nak_buffer;
1883
1884 /*
1885 * Reset all his options.
1886 */
1887 BZERO(ho, sizeof(*ho));
1888
1889 /*
1890 * Process all his options.
1891 */
1892 for (len = *lenp; len > 0; len -= cilen, p = prev + cilen) {
1893 newret = CODE_CONFACK; /* Assume success */
1894
1895 prev = p;
1896 GETCHAR(citype, p);
1897 GETCHAR(cilen, p);
1898
1899 switch (citype) { /* Check CI type */
1900 case CI_MRU:
1901 if (!ao->neg_mru) {
1902 newret = CODE_CONFREJ;
1903 break;
1904 }
1905
1906 if (cilen != CILEN_SHORT) { /* Check CI length */
1907 newret = CODE_CONFNAK;
1908 cishort = ao->mru;
1909 } else {
1910 /* extract the MRU from the option */
1911 GETSHORT(cishort, p);
1912
1913 /*
1914 * If the offered MRU is less than our desired MTU, we
1915 * should nak. This is especially helpful if we're
1916 * doing demand-dial, since those queued up packets
1917 * might be discarded otherwise.
1918 */
1919 if (cishort < ao->mru) {
1920 newret = CODE_CONFNAK;
1921 cishort = ao->mru;
1922 }
1923 }
1924
1925 /*
1926 * If we're going to send a nak with something less than
1927 * or equal to the default PPP MTU, then just reject instead.
1928 */
1929 if (newret == CODE_CONFNAK && cishort <= PPP_MTU)
1930 newret = CODE_CONFREJ;
1931
1932 if (newret == CODE_CONFNAK) {
1933 PUTCHAR(CI_MRU, nakp);
1934 PUTCHAR(CILEN_SHORT, nakp);
1935 PUTSHORT(cishort, nakp); /* Give him a hint */
1936 }
1937
1938 ho->neg_mru = 1; /* Remember he sent MRU */
1939 ho->mru = cishort; /* And remember value */
1940 break;
1941
1942 case CI_ASYNCMAP:
1943 if (!ao->neg_asyncmap) {
1944 newret = CODE_CONFREJ;
1945 break;
1946 }
1947
1948 if (cilen != CILEN_LONG) {
1949 newret = CODE_CONFNAK;
1950 cilong = 0;
1951 } else {
1952 GETLONG(cilong, p);
1953
1954 /*
1955 * Asyncmap must have set at least the bits
1956 * which are set in lcp_allowoptions[unit].asyncmap.
1957 */
1958 if ((ao->asyncmap & ~cilong) != 0)
1959 newret = CODE_CONFNAK;
1960 }
1961
1962 /*
1963 * Workaround for common broken Microsoft software -- if
1964 * the peer is sending us a nonzero ACCM, then he *needs*
1965 * us to send the same to him. Adjust our Configure-
1966 * Request message and restart LCP.
1967 */
1968 if (do_msft_workaround && (cilong & ~wo->asyncmap)) {
1969 dbglog("adjusted requested asyncmap from %X to %X",
1970 wo->asyncmap, wo->asyncmap | cilong);
1971 do_msft_workaround = 0;
1972 wo->neg_asyncmap = 1;
1973 wo->asyncmap |= cilong;
1974 f->flags &= ~OPT_SILENT;
1975 info("possibly broken peer detected; restarting LCP");
1976 fsm_lowerdown(f);
1977 fsm_lowerup(f);
1978 return (0);
1979 }
1980
1981 if (newret == CODE_CONFNAK) {
1982 PUTCHAR(CI_ASYNCMAP, nakp);
1983 PUTCHAR(CILEN_LONG, nakp);
1984 PUTLONG(ao->asyncmap | cilong, nakp);
1985 }
1986 ho->neg_asyncmap = 1;
1987 ho->asyncmap = cilong;
1988 break;
1989
1990 case CI_AUTHTYPE:
1991 if (!(ao->neg_upap || ao->neg_chap || ao->neg_mschap ||
1992 ao->neg_mschapv2)) {
1993 rejected_peers_auth = 1;
1994 if (cilen >= CILEN_SHORT) {
1995 GETSHORT(rejected_auth_proto, p);
1996 } else {
1997 rejected_auth_proto = 0;
1998 }
1999 /*
2000 * Reject the option if we're not willing to authenticate.
2001 */
2002 newret = CODE_CONFREJ;
2003 break;
2004 }
2005 rejected_peers_auth = 0;
2006 naked_peers_auth = 0;
2007
2008 if (cilen >= CILEN_SHORT) {
2009 /* Extract the authentication protocol from the option */
2010 GETSHORT(cishort, p);
2011
2012 if (ho->neg_upap || ho->neg_chap || ho->neg_mschap ||
2013 ho->neg_mschapv2) {
2014 dbglog("Rejecting extra authentication protocol option");
2015 newret = CODE_CONFREJ;
2016 break;
2017 }
2018
2019 /*
2020 * Authtype must be PAP or CHAP.
2021 *
2022 * Note: if both ao->neg_upap and ao->neg_*chap* are
2023 * set, and the peer sends a Configure-Request with
2024 * two authenticate-protocol requests, one for CHAP
2025 * and one for UPAP, then we will reject the second
2026 * request. Whether we end up doing CHAP or UPAP
2027 * depends then on the ordering of the CIs in the
2028 * peer's Configure-Request.
2029 *
2030 * We're supposed to list all of the protocols we can
2031 * possibly use in the returned Configure-Nak. This
2032 * part of RFC 1661 (section 5.3) is in conflict with
2033 * the section that says the options shouldn't be
2034 * reordered, so it's often ignored.
2035 */
2036
2037 if (cishort == PPP_PAP) {
2038 if (ao->neg_upap) {
2039 if (cilen != CILEN_SHORT)
2040 goto try_pap_anyway;
2041 ho->neg_upap = 1;
2042 break;
2043 }
2044 } else if (cishort == PPP_CHAP) {
2045 /* Test >= here to allow for broken peers. */
2046 if (cilen >= CILEN_CHAP &&
2047 (ao->neg_chap || ao->neg_mschap || ao->neg_mschapv2)) {
2048 GETCHAR(cichar, p);
2049 if (cichar == CHAP_DIGEST_MD5 && ao->neg_chap)
2050 ho->neg_chap = 1;
2051 else if (cichar == CHAP_MICROSOFT && ao->neg_mschap)
2052 ho->neg_mschap = 1;
2053 else if (cichar == CHAP_MICROSOFT_V2 &&
2054 ao->neg_mschapv2)
2055 ho->neg_mschap = 1;
2056 if (ho->neg_chap || ho->neg_mschap ||
2057 ho->neg_mschapv2) {
2058 ho->chap_mdtype = cichar; /* save md type */
2059 break;
2060 }
2061 }
2062 }
2063 }
2064
2065 /*
2066 * We don't recognize the protocol they're asking for.
2067 * Nak it with something we're willing to do.
2068 * (At this point we know ao->neg_upap || ao->neg_chap.)
2069 */
2070 PUTCHAR(CI_AUTHTYPE, nakp);
2071 if (ao->neg_chap || ao->neg_mschap || ao->neg_mschapv2) {
2072 PUTCHAR(CILEN_CHAP, nakp);
2073 PUTSHORT(PPP_CHAP, nakp);
2074 PUTCHAR(ao->chap_mdtype, nakp);
2075 naked_auth_proto = PPP_CHAP;
2076 } else {
2077 try_pap_anyway:
2078 PUTCHAR(CILEN_SHORT, nakp);
2079 PUTSHORT(PPP_PAP, nakp);
2080 naked_auth_proto = PPP_PAP;
2081 }
2082 naked_peers_auth = 1;
2083 naked_auth_orig = cishort;
2084 newret = CODE_CONFNAK;
2085 break;
2086
2087 case CI_QUALITY:
2088 if (!ao->neg_lqr) {
2089 newret = CODE_CONFREJ;
2090 break;
2091 }
2092
2093 if (cilen != CILEN_LQR) {
2094 newret = CODE_CONFNAK;
2095 cilong = ao->lqr_period;
2096 } else {
2097
2098 GETSHORT(cishort, p);
2099 GETLONG(cilong, p);
2100
2101 /* Check the LQM protocol */
2102 if (cishort != PPP_LQR) {
2103 newret = CODE_CONFNAK;
2104 }
2105
2106 /* Check the reporting period; we can't both send zero */
2107 if ((cilong == 0 && go->lqr_period == 0) ||
2108 cilong < ao->lqr_period) {
2109 newret = CODE_CONFNAK;
2110 if ((cilong = ao->lqr_period) == 0)
2111 cilong = 500;
2112 }
2113 }
2114
2115 if (newret == CODE_CONFNAK) {
2116 PUTCHAR(CI_QUALITY, nakp);
2117 PUTCHAR(CILEN_LQR, nakp);
2118 PUTSHORT(PPP_LQR, nakp);
2119 PUTLONG(cilong, nakp);
2120 }
2121
2122 ho->neg_lqr = 1;
2123 ho->lqr_period = cilong;
2124 break;
2125
2126 case CI_MAGICNUMBER:
2127 if (!(ao->neg_magicnumber || go->neg_magicnumber)) {
2128 newret = CODE_CONFREJ;
2129 break;
2130 }
2131
2132 ho->neg_magicnumber = 1;
2133 if (cilen < CILEN_LONG) {
2134 /*
2135 * If we send Magic-Number, then we must not reject it
2136 * when the peer sends it to us, even if his version
2137 * looks odd to us. Ack if the cilen is wrong in this
2138 * case. If we're not sending Magic-Number, then we don't
2139 * much care what his value is anyway.
2140 */
2141 break;
2142 }
2143
2144 GETLONG(cilong, p);
2145 ho->magicnumber = cilong;
2146 if (cilen > CILEN_LONG)
2147 break;
2148
2149 /*
2150 * He must have a different magic number. Make sure we
2151 * give him a good one to use.
2152 */
2153 while (go->neg_magicnumber && cilong == go->magicnumber) {
2154 newret = CODE_CONFNAK;
2155 cilong = magic();
2156 }
2157
2158 if (newret == CODE_CONFNAK) {
2159 PUTCHAR(CI_MAGICNUMBER, nakp);
2160 PUTCHAR(CILEN_LONG, nakp);
2161 PUTLONG(cilong, nakp);
2162 /*
2163 * We don't need to bump the numloops counter here
2164 * since it's already done upon reception of a nak.
2165 */
2166 }
2167 break;
2168
2169 case CI_PCOMPRESSION:
2170 if (!ao->neg_pcompression) {
2171 newret = CODE_CONFREJ;
2172 break;
2173 }
2174 if (cilen != CILEN_VOID) {
2175 newret = CODE_CONFNAK;
2176 PUTCHAR(CI_PCOMPRESSION, nakp);
2177 PUTCHAR(CILEN_VOID, nakp);
2178 }
2179 ho->neg_pcompression = 1;
2180 break;
2181
2182 case CI_ACCOMPRESSION:
2183 if (!ao->neg_accompression) {
2184 newret = CODE_CONFREJ;
2185 break;
2186 }
2187 if (cilen != CILEN_VOID) {
2188 newret = CODE_CONFNAK;
2189 PUTCHAR(CI_ACCOMPRESSION, nakp);
2190 PUTCHAR(CILEN_VOID, nakp);
2191 }
2192 ho->neg_accompression = 1;
2193 break;
2194
2195 case CI_FCSALTERN:
2196 if (!ao->neg_fcs) {
2197 newret = CODE_CONFREJ;
2198 break;
2199 }
2200
2201 if (cilen != CILEN_CHAR) {
2202 newret = CODE_CONFNAK;
2203 cichar = ao->fcs_type;
2204 } else {
2205
2206 GETCHAR(cichar, p);
2207 /* If he has bits we don't like, tell him to stop. */
2208 if (cichar & ~ao->fcs_type) {
2209 if ((cichar &= ao->fcs_type) == 0) {
2210 newret = CODE_CONFREJ;
2211 break;
2212 }
2213 newret = CODE_CONFNAK;
2214 }
2215 }
2216 if (newret == CODE_CONFNAK) {
2217 PUTCHAR(CI_FCSALTERN, nakp);
2218 PUTCHAR(CILEN_CHAR, nakp);
2219 PUTCHAR(cichar, nakp);
2220 }
2221 ho->neg_fcs = 1;
2222 ho->fcs_type = cichar;
2223 break;
2224
2225 case CI_MRRU:
2226 if (!ao->neg_mrru || !multilink) {
2227 newret = CODE_CONFREJ;
2228 break;
2229 }
2230 if (cilen != CILEN_SHORT) {
2231 newret = CODE_CONFNAK;
2232 cishort = ao->mrru;
2233 } else {
2234 GETSHORT(cishort, p);
2235 if (cishort < ao->mrru) {
2236 newret = CODE_CONFNAK;
2237 cishort = ao->mrru;
2238 }
2239 }
2240
2241 if (cishort < PPP_MINMTU) {
2242 newret = CODE_CONFNAK;
2243 cishort = PPP_MINMTU;
2244 }
2245
2246 if (newret == CODE_CONFNAK) {
2247 PUTCHAR(CI_MRRU, nakp);
2248 PUTCHAR(CILEN_SHORT, nakp);
2249 PUTSHORT(cishort, nakp);
2250 }
2251
2252 ho->neg_mrru = 1;
2253 ho->mrru = cishort;
2254 break;
2255
2256 case CI_SSNHF:
2257 if (!ao->neg_ssnhf || !multilink) {
2258 newret = CODE_CONFREJ;
2259 break;
2260 }
2261 if (cilen != CILEN_VOID) {
2262 newret = CODE_CONFNAK;
2263 PUTCHAR(CI_SSNHF, nakp);
2264 PUTCHAR(CILEN_VOID, nakp);
2265 }
2266 ho->neg_ssnhf = 1;
2267 break;
2268
2269 case CI_EPDISC:
2270 if (!ao->neg_endpoint) {
2271 newret = CODE_CONFREJ;
2272 break;
2273 }
2274 if (cilen < CILEN_CHAR || cilen > CILEN_CHAR + MAX_ENDP_LEN) {
2275 int i;
2276
2277 newret = CODE_CONFNAK;
2278 PUTCHAR(CI_EPDISC, nakp);
2279 PUTCHAR(CILEN_CHAR + ao->endpoint.length, nakp);
2280 PUTCHAR(ao->endpoint.class, nakp);
2281 for (i = 0; i < ao->endpoint.length; i++)
2282 PUTCHAR(ao->endpoint.value[i], nakp);
2283 break;
2284 }
2285 GETCHAR(cichar, p);
2286 ho->neg_endpoint = 1;
2287 ho->endpoint.class = cichar;
2288 ho->endpoint.length = cilen - 3;
2289 BCOPY(p, ho->endpoint.value, cilen - 3);
2290 break;
2291
2292 #ifdef MUX_FRAME
2293 case CI_MUXING:
2294 if (ao->pppmux == 0 || cilen != CILEN_VOID) {
2295 newret = CODE_CONFREJ;
2296 break;
2297 }
2298 /* remember his option */
2299 ho->pppmux = ao->pppmux;
2300 break;
2301 #endif
2302
2303 default:
2304 dbglog("LCP: rejecting unknown option %d", citype);
2305 newret = CODE_CONFREJ;
2306 break;
2307 }
2308
2309 /* Cope with confused peers. */
2310 if (cilen < 2)
2311 cilen = 2;
2312
2313 /*
2314 * If this is an Ack'able CI, but we're sending back a Nak,
2315 * don't include this CI.
2316 */
2317 if (newret == CODE_CONFACK && ret != CODE_CONFACK)
2318 continue;
2319
2320 if (newret == CODE_CONFNAK) {
2321 /*
2322 * Continue naking the Magic Number option until the cows come
2323 * home -- rejecting it is wrong.
2324 */
2325 if (dont_nak && citype != CI_MAGICNUMBER) {
2326 newret = CODE_CONFREJ;
2327 } else {
2328 /* Ignore subsequent Nak'able things if rejecting. */
2329 if (ret == CODE_CONFREJ)
2330 continue;
2331 ret = CODE_CONFNAK;
2332 }
2333 }
2334
2335 if (newret == CODE_CONFREJ) {
2336 ret = CODE_CONFREJ;
2337 if (prev != rejp)
2338 BCOPY(prev, rejp, cilen);
2339 rejp += cilen;
2340 }
2341 }
2342
2343 /*
2344 * If the peer hasn't negotiated his MRU, and we'd like an MTU
2345 * that's larger than the default, try sending an unsolicited
2346 * Nak for what we want.
2347 */
2348 if (ret != CODE_CONFREJ && !ho->neg_mru && ao->mru > PPP_MTU &&
2349 !dont_nak && unsolicit_mru) {
2350 unsolicit_mru = 0; /* don't ask again */
2351 ret = CODE_CONFNAK;
2352 PUTCHAR(CI_MRU, nakp);
2353 PUTCHAR(CILEN_SHORT, nakp);
2354 PUTSHORT(ao->mru, nakp);
2355 }
2356
2357 switch (ret) {
2358 case CODE_CONFACK:
2359 *lenp = p - p0;
2360 break;
2361 case CODE_CONFNAK:
2362 /*
2363 * Copy the Nak'd options from the nak_buffer to the caller's buffer.
2364 */
2365 *lenp = nakp - nak_buffer;
2366 BCOPY(nak_buffer, p0, *lenp);
2367 break;
2368 case CODE_CONFREJ:
2369 *lenp = rejp - p0;
2370
2371 /* We're about to send Configure-Reject; send Identification */
2372 if (!noident && sentident < 3) {
2373 LcpSendIdentification(f);
2374 sentident++;
2375 }
2376 break;
2377 }
2378
2379 LCPDEBUG(("lcp_reqci: returning %s.", code_name(ret, 1)));
2380 return (ret); /* Return final code */
2381 }
2382
2383
2384 /*
2385 * lcp_up - LCP has come UP.
2386 */
2387 static void
lcp_up(f)2388 lcp_up(f)
2389 fsm *f;
2390 {
2391 lcp_options *wo = &lcp_wantoptions[f->unit];
2392 lcp_options *ho = &lcp_hisoptions[f->unit];
2393 lcp_options *go = &lcp_gotoptions[f->unit];
2394 lcp_options *ao = &lcp_allowoptions[f->unit];
2395 int mru, mtu;
2396
2397 if (!go->neg_magicnumber)
2398 go->magicnumber = 0;
2399 if (!ho->neg_magicnumber)
2400 ho->magicnumber = 0;
2401
2402 /*
2403 * Set our MTU to the smaller of the MTU we wanted and
2404 * the MRU our peer wanted. If we negotiated an MRU,
2405 * set our MRU to the larger of value we wanted and
2406 * the value we got in the negotiation.
2407 */
2408 if (ao->mru != 0 && ho->mru > ao->mru)
2409 ho->mru = ao->mru;
2410 mtu = (ho->neg_mru ? ho->mru: PPP_MRU);
2411 if (mtu > absmax_mtu)
2412 mtu = absmax_mtu;
2413 ppp_send_config(f->unit, mtu,
2414 (ho->neg_asyncmap? ho->asyncmap: 0xffffffff),
2415 ho->neg_pcompression, ho->neg_accompression);
2416 fsm_setpeermru(f->unit, mtu);
2417 mru = (go->neg_mru? MAX(wo->mru, go->mru): PPP_MRU);
2418 if (mru > absmax_mru)
2419 mru = absmax_mru;
2420 ppp_recv_config(f->unit, mru,
2421 (lax_recv? 0: go->neg_asyncmap? go->asyncmap: 0xffffffff),
2422 go->neg_pcompression, go->neg_accompression);
2423 #ifdef NEGOTIATE_FCS
2424 ppp_send_fcs(f->unit, ho->neg_fcs ? ho->fcs_type : FCSALT_16);
2425 ppp_recv_fcs(f->unit, go->neg_fcs ? go->fcs_type : FCSALT_16);
2426 #endif
2427 #ifdef MUX_FRAME
2428 ppp_send_muxoption(f->unit, ho->pppmux);
2429 ppp_recv_muxoption(f->unit, go->pppmux);
2430 #endif
2431
2432 lcp_echo_lowerup(f->unit); /* Enable echo messages */
2433
2434 /* LCP is Up; send Identification */
2435 if (!noident) {
2436 LcpSendIdentification(f);
2437 sentident++;
2438 }
2439
2440 link_established(f->unit);
2441 }
2442
2443
2444 /*
2445 * lcp_down - LCP has gone DOWN.
2446 *
2447 * Alert other protocols.
2448 */
2449 static void
lcp_down(f)2450 lcp_down(f)
2451 fsm *f;
2452 {
2453 int mtu;
2454 lcp_options *go = &lcp_gotoptions[f->unit];
2455
2456 lcp_echo_lowerdown(f->unit);
2457
2458 link_down(f->unit);
2459
2460 mtu = PPP_MTU > absmax_mtu ? absmax_mtu : PPP_MTU;
2461 ppp_send_config(f->unit, mtu, 0xffffffff, 0, 0);
2462 ppp_recv_config(f->unit, (PPP_MRU > absmax_mru ? absmax_mru : PPP_MRU),
2463 (go->neg_asyncmap? go->asyncmap: 0xffffffff),
2464 go->neg_pcompression, go->neg_accompression);
2465 #ifdef NEGOTIATE_FCS
2466 ppp_send_fcs(f->unit, FCSALT_16);
2467 ppp_recv_fcs(f->unit, FCSALT_16);
2468 #endif
2469 fsm_setpeermru(f->unit, mtu);
2470 }
2471
2472
2473 /*
2474 * lcp_starting - LCP needs the lower layer up.
2475 */
2476 static void
lcp_starting(f)2477 lcp_starting(f)
2478 fsm *f;
2479 {
2480 link_required(f->unit);
2481 }
2482
2483
2484 /*
2485 * lcp_finished - LCP has finished with the lower layer.
2486 */
2487 static void
lcp_finished(f)2488 lcp_finished(f)
2489 fsm *f;
2490 {
2491 link_terminated(f->unit);
2492 }
2493
2494
2495 /*
2496 * lcp_printpkt - print the contents of an LCP packet.
2497 */
2498
2499 static int
lcp_printpkt(p,plen,printer,arg)2500 lcp_printpkt(p, plen, printer, arg)
2501 u_char *p;
2502 int plen;
2503 void (*printer) __P((void *, const char *, ...));
2504 void *arg;
2505 {
2506 int code, id, len, olen, i;
2507 u_char *pstart, *optend, cichar;
2508 u_short cishort;
2509 u_int32_t cilong;
2510
2511 if (plen < HEADERLEN)
2512 return 0;
2513 pstart = p;
2514 GETCHAR(code, p);
2515 GETCHAR(id, p);
2516 GETSHORT(len, p);
2517 if (len < HEADERLEN || len > plen)
2518 return 0;
2519
2520 printer(arg, " %s id=0x%x", code_name(code,1), id);
2521 len -= HEADERLEN;
2522 switch (code) {
2523 case CODE_CONFREQ:
2524 case CODE_CONFACK:
2525 case CODE_CONFNAK:
2526 case CODE_CONFREJ:
2527 /* print option list */
2528 while (len >= 2) {
2529 GETCHAR(code, p);
2530 GETCHAR(olen, p);
2531 p -= 2;
2532 if (olen < 2 || olen > len) {
2533 break;
2534 }
2535 printer(arg, " <");
2536 len -= olen;
2537 optend = p + olen;
2538 switch (code) {
2539 case CI_MRU:
2540 if (olen >= CILEN_SHORT) {
2541 p += 2;
2542 GETSHORT(cishort, p);
2543 printer(arg, "mru %d", cishort);
2544 }
2545 break;
2546 case CI_ASYNCMAP:
2547 if (olen >= CILEN_LONG) {
2548 p += 2;
2549 GETLONG(cilong, p);
2550 printer(arg, "asyncmap 0x%x", cilong);
2551 }
2552 break;
2553 case CI_AUTHTYPE:
2554 if (olen >= CILEN_SHORT) {
2555 p += 2;
2556 printer(arg, "auth ");
2557 GETSHORT(cishort, p);
2558 switch (cishort) {
2559 case PPP_PAP:
2560 printer(arg, "pap");
2561 break;
2562 case PPP_CHAP:
2563 printer(arg, "chap");
2564 if (p < optend) {
2565 switch (*p) {
2566 case CHAP_DIGEST_MD5:
2567 printer(arg, " MD5");
2568 ++p;
2569 break;
2570 case CHAP_MICROSOFT:
2571 printer(arg, " m$oft");
2572 ++p;
2573 break;
2574 case CHAP_MICROSOFT_V2:
2575 printer(arg, " m$oft-v2");
2576 ++p;
2577 break;
2578 }
2579 }
2580 break;
2581 #ifdef PPP_EAP
2582 case PPP_EAP:
2583 printer(arg, "eap");
2584 break;
2585 #endif
2586 case 0xC027:
2587 printer(arg, "spap");
2588 break;
2589 case 0xC123:
2590 printer(arg, "old-spap");
2591 break;
2592 default:
2593 printer(arg, "0x%x", cishort);
2594 }
2595 }
2596 break;
2597 case CI_QUALITY:
2598 if (olen >= CILEN_SHORT) {
2599 p += 2;
2600 printer(arg, "quality ");
2601 GETSHORT(cishort, p);
2602 switch (cishort) {
2603 case PPP_LQR:
2604 printer(arg, "lqr");
2605 break;
2606 default:
2607 printer(arg, "0x%x", cishort);
2608 }
2609 }
2610 break;
2611 case CI_CALLBACK:
2612 if (olen >= CILEN_CHAR) {
2613 p += 2;
2614 printer(arg, "callback ");
2615 GETCHAR(cichar, p);
2616 if (cichar <= 6 &&
2617 *callback_strings[(int)cichar] != '\0') {
2618 printer(arg, "%s", callback_strings[(int)cichar]);
2619 } else {
2620 printer(arg, "0x%x", cichar);
2621 }
2622 }
2623 break;
2624 case CI_MAGICNUMBER:
2625 if (olen >= CILEN_LONG) {
2626 p += 2;
2627 GETLONG(cilong, p);
2628 printer(arg, "magic 0x%x", cilong);
2629 }
2630 break;
2631 case CI_PCOMPRESSION:
2632 if (olen >= CILEN_VOID) {
2633 p += 2;
2634 printer(arg, "pcomp");
2635 }
2636 break;
2637 case CI_ACCOMPRESSION:
2638 if (olen >= CILEN_VOID) {
2639 p += 2;
2640 printer(arg, "accomp");
2641 }
2642 break;
2643 case CI_FCSALTERN:
2644 if (olen >= CILEN_CHAR) {
2645 char **cpp;
2646 int needcomma = 0;
2647
2648 p += 2;
2649 GETCHAR(cichar, p);
2650 for (cpp = fcsalt_strings; *cpp != NULL; cpp++)
2651 if (cichar & 1<<(cpp-fcsalt_strings)) {
2652 cichar &= ~(1<<(cpp-fcsalt_strings));
2653 printer(arg, (needcomma ? ",%s" : "fcs %s"), *cpp);
2654 needcomma = 1;
2655 }
2656 if (cichar != 0 || !needcomma)
2657 printer(arg, (needcomma ? ",0x%x" : "fcs 0x%x"),
2658 cichar);
2659 }
2660 break;
2661 case CI_NUMBERED:
2662 if (olen >= CILEN_SHORT) {
2663 p += 2;
2664 GETCHAR(cichar, p);
2665 printer(arg, "numb win %d", cichar);
2666 GETCHAR(cichar, p);
2667 printer(arg, " addr %d", cichar);
2668 }
2669 break;
2670 case CI_MRRU:
2671 if (olen >= CILEN_SHORT) {
2672 p += 2;
2673 GETSHORT(cishort, p);
2674 printer(arg, "mrru %d", cishort);
2675 }
2676 break;
2677 case CI_SSNHF:
2678 if (olen >= CILEN_VOID) {
2679 p += 2;
2680 printer(arg, "ssnhf");
2681 }
2682 break;
2683 case CI_EPDISC:
2684 if (olen >= CILEN_CHAR) {
2685 struct epdisc epd;
2686 p += 2;
2687 GETCHAR(epd.class, p);
2688 epd.length = olen - CILEN_CHAR;
2689 if (epd.length > MAX_ENDP_LEN)
2690 epd.length = MAX_ENDP_LEN;
2691 if (epd.length > 0) {
2692 BCOPY(p, epd.value, epd.length);
2693 p += epd.length;
2694 }
2695 printer(arg, "endpoint [%s]", epdisc_to_str(&epd));
2696 }
2697 break;
2698 case CI_LINKDISC:
2699 if (olen >= CILEN_SHORT) {
2700 p += 2;
2701 GETSHORT(cishort, p);
2702 printer(arg, "linkdisc %d", cishort);
2703 }
2704 break;
2705 case CI_COBS:
2706 if (olen >= CILEN_CHAR) {
2707 p += 2;
2708 GETCHAR(cichar, p);
2709 printer(arg, "cobs 0x%x", cichar);
2710 }
2711 break;
2712 case CI_PFXELISION:
2713 if (olen >= CILEN_CHAR) {
2714 p += 2;
2715 printer(arg, "pfx");
2716 }
2717 break;
2718 case CI_MPHDRFMT:
2719 if (olen >= CILEN_SHORT) {
2720 p += 2;
2721 printer(arg, "mphdr ");
2722 GETCHAR(cichar, p);
2723 switch (cichar) {
2724 case 2:
2725 printer(arg, "long");
2726 break;
2727 case 6:
2728 printer(arg, "short");
2729 break;
2730 default:
2731 printer(arg, "0x%x", cichar);
2732 break;
2733 }
2734 GETCHAR(cichar, p);
2735 printer(arg, " #cl %d", cichar);
2736 }
2737 break;
2738 case CI_I18N:
2739 if (olen >= CILEN_LONG) {
2740 p += 2;
2741 GETLONG(cilong, p);
2742 printer(arg, "i18n charset 0x%x", cilong);
2743 if (olen > CILEN_LONG) {
2744 printer(arg, " lang ");
2745 print_string((char *)p, olen-CILEN_LONG, printer, arg);
2746 p = optend;
2747 }
2748 }
2749 break;
2750 case CI_SDL:
2751 if (olen >= CILEN_VOID) {
2752 p += 2;
2753 printer(arg, "sdl");
2754 }
2755 break;
2756 case CI_MUXING:
2757 if (olen >= CILEN_VOID) {
2758 p += 2;
2759 printer(arg, "mux");
2760 }
2761 break;
2762 }
2763 while (p < optend) {
2764 GETCHAR(code, p);
2765 printer(arg, " %.2x", code);
2766 }
2767 printer(arg, ">");
2768 }
2769 break;
2770
2771 case CODE_TERMACK:
2772 case CODE_TERMREQ:
2773 if (len > 0 && *p >= ' ' && *p < 0x7f) {
2774 printer(arg, " ");
2775 print_string((char *)p, len, printer, arg);
2776 p += len;
2777 len = 0;
2778 }
2779 break;
2780
2781 case CODE_ECHOREQ:
2782 case CODE_ECHOREP:
2783 case CODE_DISCREQ:
2784 if (len >= 4) {
2785 GETLONG(cilong, p);
2786 printer(arg, " magic=0x%x", cilong);
2787 len -= 4;
2788 }
2789 break;
2790
2791 case CODE_IDENT:
2792 if (len >= 4) {
2793 GETLONG(cilong, p);
2794 printer(arg, " magic=0x%x", cilong);
2795 len -= 4;
2796 } else
2797 break;
2798 if (len > 0 && (len > 1 || *p != '\0')) {
2799 printer(arg, " ");
2800 print_string((char *)p, len, printer, arg);
2801 p += len;
2802 len = 0;
2803 }
2804 break;
2805
2806 case CODE_TIMEREMAIN:
2807 if (len >= 4) {
2808 GETLONG(cilong, p);
2809 printer(arg, " magic=0x%x", cilong);
2810 len -= 4;
2811 } else
2812 break;
2813 if (len >= 4) {
2814 GETLONG(cilong, p);
2815 printer(arg, " seconds=%d", cilong);
2816 len -= 4;
2817 } else
2818 break;
2819 if (len > 0 && (len > 1 || *p != '\0')) {
2820 printer(arg, " ");
2821 print_string((char *)p, len, printer, arg);
2822 p += len;
2823 len = 0;
2824 }
2825 break;
2826 }
2827
2828 /* print the rest of the bytes in the packet */
2829 for (i = 0; i < len && i < 32; ++i) {
2830 GETCHAR(code, p);
2831 printer(arg, " %.2x", code);
2832 }
2833 if (i < len) {
2834 printer(arg, " ...");
2835 p += len - i;
2836 }
2837
2838 return p - pstart;
2839 }
2840
2841 /*
2842 * Time to shut down the link because there is nothing out there.
2843 */
2844
2845 static void
LcpLinkFailure(f)2846 LcpLinkFailure (f)
2847 fsm *f;
2848 {
2849 char *close_message;
2850
2851 if (f->state == OPENED) {
2852 if (lcp_echo_badreplies > LCP_ECHO_MAX_BADREPLIES) {
2853 info("Received %d bad echo-replies", lcp_echo_badreplies);
2854 close_message = "Receiving malformed Echo-Replies";
2855 } else if (lcp_echo_accm_test) {
2856 /*
2857 * If this is an asynchronous line and we've missed all of
2858 * the initial echo requests, then this is probably due to
2859 * a bad ACCM.
2860 */
2861 notice("Peer not responding to initial Echo-Requests.");
2862 notice("Negotiated asyncmap may be incorrect for this link.");
2863 close_message = "Peer not responding; perhaps bad asyncmap";
2864 } else {
2865 info("No response to %d echo-requests", lcp_echos_pending);
2866 notice("Serial link appears to be disconnected.");
2867 close_message = "Peer not responding";
2868 }
2869
2870 lcp_close(f->unit, close_message);
2871 status = EXIT_PEER_DEAD;
2872 }
2873 }
2874
2875 /*
2876 * Timer expired for the LCP echo requests from this process.
2877 */
2878
2879 static void
LcpEchoCheck(f)2880 LcpEchoCheck (f)
2881 fsm *f;
2882 {
2883 if (f->state != OPENED || lcp_echo_interval == 0)
2884 return;
2885
2886 LcpSendEchoRequest (f);
2887
2888 /*
2889 * Start the timer for the next interval.
2890 */
2891 if (lcp_echo_timer_running)
2892 warn("assertion lcp_echo_timer_running==0 failed");
2893 TIMEOUT (LcpEchoTimeout, f, lcp_echo_interval);
2894 lcp_echo_timer_running = 1;
2895 }
2896
2897 /*
2898 * LcpEchoTimeout - Timer expired on the LCP echo
2899 */
2900
2901 static void
LcpEchoTimeout(arg)2902 LcpEchoTimeout (arg)
2903 void *arg;
2904 {
2905 if (lcp_echo_timer_running != 0) {
2906 lcp_echo_timer_running = 0;
2907 LcpEchoCheck ((fsm *) arg);
2908 }
2909 }
2910
2911 /*
2912 * LcpEchoReply - LCP has received a reply to the echo
2913 */
2914 /*ARGSUSED*/
2915 static int
lcp_received_echo_reply(f,id,inp,len)2916 lcp_received_echo_reply (f, id, inp, len)
2917 fsm *f;
2918 int id;
2919 u_char *inp;
2920 int len;
2921 {
2922 u_int32_t magic;
2923
2924 /* Check the magic number - don't count replies from ourselves. */
2925 if (len < 4) {
2926 dbglog("lcp: received short Echo-Reply, length %d", len);
2927 return (0);
2928 }
2929 GETLONG(magic, inp);
2930 if (lcp_gotoptions[f->unit].neg_magicnumber &&
2931 magic == lcp_gotoptions[f->unit].magicnumber) {
2932 warn("appear to have received our own echo-reply!");
2933 return (0);
2934 }
2935
2936 /* Reset the number of outstanding echo frames */
2937 lcp_echos_pending = 0;
2938
2939 if (lcp_echo_accm_test) {
2940 dbglog("lcp: validated asyncmap setting");
2941 lcp_echo_accm_test = 0;
2942 if (lcp_echo_fails == 0)
2943 lcp_echo_interval = 0;
2944 }
2945 return (1);
2946 }
2947
2948 /*
2949 * LcpSendEchoRequest - Send an echo request frame to the peer
2950 */
2951
2952 static void
LcpSendEchoRequest(f)2953 LcpSendEchoRequest (f)
2954 fsm *f;
2955 {
2956 u_int32_t lcp_magic;
2957 u_char pkt[4+256], *pktp;
2958 int i;
2959
2960 /*
2961 * Detect the failure of the peer at this point. If we're not currently
2962 * performing the ACCM test, then we just check for the user's echo-failure
2963 * point. If we are performing the ACCM test, then use ACCM_TEST_FAILS if
2964 * the user hasn't specified a different failure point.
2965 */
2966 i = lcp_echo_fails;
2967 if (i == 0)
2968 i = ACCM_TEST_FAILS;
2969 if ((!lcp_echo_accm_test && lcp_echo_fails != 0 &&
2970 lcp_echos_pending >= lcp_echo_fails) ||
2971 (lcp_echo_accm_test && lcp_echos_pending >= i)) {
2972 LcpLinkFailure(f);
2973 lcp_echos_pending = 0;
2974 lcp_echo_badreplies = 0;
2975 }
2976
2977 /*
2978 * Make and send the echo request frame.
2979 */
2980 if (f->state == OPENED) {
2981 lcp_magic = lcp_gotoptions[f->unit].magicnumber;
2982 pktp = pkt;
2983 PUTLONG(lcp_magic, pktp);
2984 /* Send some test packets so we can fail the link early. */
2985 if (lcp_echo_accm_test) {
2986 switch (use_accm_test) {
2987 case 1:
2988 /* Only the characters covered by negotiated ACCM */
2989 for (i = 0; i < 32; i++)
2990 *pktp++ = i;
2991 break;
2992 case 2:
2993 /* All characters */
2994 for (i = 0; i < 256; i++)
2995 *pktp++ = i;
2996 break;
2997 }
2998 }
2999 fsm_sdata(f, CODE_ECHOREQ, lcp_echo_number++ & 0xFF, pkt, pktp - pkt);
3000 ++lcp_echos_pending;
3001 }
3002 }
3003
3004 /*
3005 * lcp_echo_lowerup - Start the timer for the LCP frame
3006 */
3007
3008 static void
lcp_echo_lowerup(unit)3009 lcp_echo_lowerup (unit)
3010 int unit;
3011 {
3012 fsm *f = &lcp_fsm[unit];
3013
3014 /* Clear the parameters for generating echo frames */
3015 lcp_echos_pending = 0;
3016 lcp_echo_number = 0;
3017 lcp_echo_timer_running = 0;
3018 lcp_echo_accm_test = !sync_serial && use_accm_test;
3019
3020 /* If a timeout interval is specified then start the timer */
3021 LcpEchoCheck(f);
3022 }
3023
3024 /*
3025 * lcp_echo_lowerdown - Stop the timer for the LCP frame
3026 */
3027
3028 static void
lcp_echo_lowerdown(unit)3029 lcp_echo_lowerdown (unit)
3030 int unit;
3031 {
3032 fsm *f = &lcp_fsm[unit];
3033
3034 if (lcp_echo_timer_running != 0) {
3035 UNTIMEOUT (LcpEchoTimeout, f);
3036 lcp_echo_timer_running = 0;
3037 }
3038 }
3039
3040 /*
3041 * LcpSendIdentification - Send LCP Identification string to peer.
3042 */
3043
3044 static void
LcpSendIdentification(f)3045 LcpSendIdentification (f)
3046 fsm *f;
3047 {
3048 u_int32_t lcp_magic;
3049 u_char pkt[4 + sizeof(identstr)], *pktp;
3050 int idlen;
3051
3052 /*
3053 * Make and send the Identification frame.
3054 */
3055 if (f->state == OPENED)
3056 lcp_magic = lcp_gotoptions[f->unit].magicnumber;
3057 else
3058 lcp_magic = 0;
3059
3060 pktp = pkt;
3061 PUTLONG(lcp_magic, pktp);
3062 idlen = strlen(identstr);
3063 BCOPY(identstr, pktp, idlen);
3064 INCPTR(idlen, pktp);
3065 fsm_sdata(f, CODE_IDENT, ++f->id, pkt, pktp - pkt);
3066 }
3067
3068 /*ARGSUSED*/
3069 static void
lcp_received_identification(f,id,inp,len)3070 lcp_received_identification (f, id, inp, len)
3071 fsm *f;
3072 int id;
3073 u_char *inp;
3074 int len;
3075 {
3076 u_int32_t magic;
3077
3078 /* Check the magic number - don't count replies from ourselves. */
3079 if (len < 4) {
3080 dbglog("%s: received short Identification; %d < 4", len);
3081 return;
3082 }
3083 GETLONG(magic, inp);
3084 len -= 4;
3085 if (lcp_gotoptions[f->unit].neg_magicnumber && f->state == OPENED &&
3086 magic == lcp_gotoptions[f->unit].magicnumber) {
3087 warn("appear to have received our own Identification!");
3088 return;
3089 }
3090 if (len > 0 && (len > 1 || *inp != '\0'))
3091 notice("Peer Identification: %0.*v", len, inp);
3092 }
3093
3094 /*
3095 * Send a Time-Remaining LCP packet. We don't include a message.
3096 */
3097 static void
LcpSendTimeRemaining(f,time_remaining)3098 LcpSendTimeRemaining(f, time_remaining)
3099 fsm *f;
3100 u_int32_t time_remaining;
3101 {
3102 u_int32_t lcp_magic;
3103 u_char pkt[8];
3104 u_char *pktp;
3105
3106 if (f->state != OPENED)
3107 return;
3108
3109 lcp_magic = lcp_gotoptions[f->unit].magicnumber;
3110 pktp = pkt;
3111 PUTLONG(lcp_magic, pktp);
3112 PUTLONG(time_remaining, pktp);
3113 fsm_sdata(f, CODE_TIMEREMAIN, ++f->id, pkt, pktp - pkt);
3114 }
3115
3116 /*ARGSUSED*/
3117 static void
lcp_received_timeremain(f,id,inp,len)3118 lcp_received_timeremain(f, id, inp, len)
3119 fsm *f;
3120 int id;
3121 u_char *inp;
3122 int len;
3123 {
3124 u_int32_t magic;
3125 u_int32_t time_remaining;
3126
3127 /* Check the magic number - don't count replies from ourselves. */
3128 if (len < 8) {
3129 dbglog("%s: received short Time-Remain; %d < 8", len);
3130 return;
3131 }
3132 GETLONG(magic, inp);
3133 if (lcp_gotoptions[f->unit].neg_magicnumber && f->state == OPENED &&
3134 magic == lcp_gotoptions[f->unit].magicnumber) {
3135 warn("appear to have received our own Time-Remain!");
3136 return;
3137 }
3138 GETLONG(time_remaining, inp);
3139 if (len > 8) {
3140 notice("%d seconds remain: \"%.*s\"", time_remaining,
3141 len-8, inp);
3142 } else {
3143 notice("Time Remaining: %d seconds", time_remaining);
3144 }
3145 }
3146
3147 /*
3148 * lcp_timeremaining - timeout handler which sends LCP Time-Remaining
3149 * packet.
3150 */
3151 static void
lcp_timeremaining(arg)3152 lcp_timeremaining(arg)
3153 void *arg;
3154 {
3155 struct lcp_timer *lt = (struct lcp_timer *)arg;
3156 u_int32_t time_remaining;
3157 int unit;
3158
3159 unit = lt->unit;
3160 time_remaining = lt->tr;
3161 LcpSendTimeRemaining(&lcp_fsm[unit], time_remaining);
3162 free(lt);
3163 }
3164
3165 /*
3166 * lcp_settimeremaining - set a timeout to send an LCP Time-Remaining
3167 * packet. The first argument, connecttime, is the time remaining
3168 * at the time this function is called. The second argument is the
3169 * desired time remaining when the packet should be sent out.
3170 */
3171 void
lcp_settimeremaining(unit,connecttime,time_remaining)3172 lcp_settimeremaining(unit, connecttime, time_remaining)
3173 int unit;
3174 u_int32_t connecttime;
3175 u_int32_t time_remaining;
3176 {
3177 struct lcp_timer *lt;
3178
3179 if (connecttime == time_remaining) {
3180 LcpSendTimeRemaining(&lcp_fsm[unit], time_remaining);
3181 } else {
3182 lt = (struct lcp_timer *)malloc(sizeof (struct lcp_timer));
3183 lt->unit = unit;
3184 lt->tr = time_remaining;
3185 TIMEOUT(lcp_timeremaining, (void *)lt, connecttime - time_remaining);
3186 }
3187 }
3188