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