source: azure_iot_hub_f767zi/trunk/asp_baseplatform/lwip/lwip-2.1.2/src/netif/ppp/ccp.c@ 457

Last change on this file since 457 was 457, checked in by coas-nagasima, 4 years ago

ファイルを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 47.0 KB
Line 
1/*
2 * ccp.c - PPP Compression Control Protocol.
3 *
4 * Copyright (c) 1994-2002 Paul Mackerras. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * 2. The name(s) of the authors of this software must not be used to
14 * endorse or promote products derived from this software without
15 * prior written permission.
16 *
17 * 3. Redistributions of any form whatsoever must retain the following
18 * acknowledgment:
19 * "This product includes software developed by Paul Mackerras
20 * <paulus@samba.org>".
21 *
22 * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
23 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
24 * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
25 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
26 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
27 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
28 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
29 */
30
31#include "netif/ppp/ppp_opts.h"
32#if PPP_SUPPORT && CCP_SUPPORT /* don't build if not configured for use in lwipopts.h */
33
34#include <stdlib.h>
35#include <string.h>
36
37#include "netif/ppp/ppp_impl.h"
38
39#include "netif/ppp/fsm.h"
40#include "netif/ppp/ccp.h"
41
42#if MPPE_SUPPORT
43#include "netif/ppp/lcp.h" /* lcp_close(), lcp_fsm */
44#include "netif/ppp/mppe.h" /* mppe_init() */
45#endif /* MPPE_SUPPORT */
46
47/*
48 * Unfortunately there is a bug in zlib which means that using a
49 * size of 8 (window size = 256) for Deflate compression will cause
50 * buffer overruns and kernel crashes in the deflate module.
51 * Until this is fixed we only accept sizes in the range 9 .. 15.
52 * Thanks to James Carlson for pointing this out.
53 */
54#define DEFLATE_MIN_WORKS 9
55
56/*
57 * Command-line options.
58 */
59#if PPP_OPTIONS
60static int setbsdcomp (char **);
61static int setdeflate (char **);
62static char bsd_value[8];
63static char deflate_value[8];
64
65/*
66 * Option variables.
67 */
68#if MPPE_SUPPORT
69bool refuse_mppe_stateful = 1; /* Allow stateful mode? */
70#endif /* MPPE_SUPPORT */
71
72static option_t ccp_option_list[] = {
73 { "noccp", o_bool, &ccp_protent.enabled_flag,
74 "Disable CCP negotiation" },
75 { "-ccp", o_bool, &ccp_protent.enabled_flag,
76 "Disable CCP negotiation", OPT_ALIAS },
77
78 { "bsdcomp", o_special, (void *)setbsdcomp,
79 "Request BSD-Compress packet compression",
80 OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, bsd_value },
81 { "nobsdcomp", o_bool, &ccp_wantoptions[0].bsd_compress,
82 "don't allow BSD-Compress", OPT_PRIOSUB | OPT_A2CLR,
83 &ccp_allowoptions[0].bsd_compress },
84 { "-bsdcomp", o_bool, &ccp_wantoptions[0].bsd_compress,
85 "don't allow BSD-Compress", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR,
86 &ccp_allowoptions[0].bsd_compress },
87
88 { "deflate", o_special, (void *)setdeflate,
89 "request Deflate compression",
90 OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, deflate_value },
91 { "nodeflate", o_bool, &ccp_wantoptions[0].deflate,
92 "don't allow Deflate compression", OPT_PRIOSUB | OPT_A2CLR,
93 &ccp_allowoptions[0].deflate },
94 { "-deflate", o_bool, &ccp_wantoptions[0].deflate,
95 "don't allow Deflate compression", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR,
96 &ccp_allowoptions[0].deflate },
97
98 { "nodeflatedraft", o_bool, &ccp_wantoptions[0].deflate_draft,
99 "don't use draft deflate #", OPT_A2COPY,
100 &ccp_allowoptions[0].deflate_draft },
101
102 { "predictor1", o_bool, &ccp_wantoptions[0].predictor_1,
103 "request Predictor-1", OPT_PRIO | 1 },
104 { "nopredictor1", o_bool, &ccp_wantoptions[0].predictor_1,
105 "don't allow Predictor-1", OPT_PRIOSUB | OPT_A2CLR,
106 &ccp_allowoptions[0].predictor_1 },
107 { "-predictor1", o_bool, &ccp_wantoptions[0].predictor_1,
108 "don't allow Predictor-1", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR,
109 &ccp_allowoptions[0].predictor_1 },
110
111#if MPPE_SUPPORT
112 /* MPPE options are symmetrical ... we only set wantoptions here */
113 { "require-mppe", o_bool, &ccp_wantoptions[0].mppe,
114 "require MPPE encryption",
115 OPT_PRIO | MPPE_OPT_40 | MPPE_OPT_128 },
116 { "+mppe", o_bool, &ccp_wantoptions[0].mppe,
117 "require MPPE encryption",
118 OPT_ALIAS | OPT_PRIO | MPPE_OPT_40 | MPPE_OPT_128 },
119 { "nomppe", o_bool, &ccp_wantoptions[0].mppe,
120 "don't allow MPPE encryption", OPT_PRIO },
121 { "-mppe", o_bool, &ccp_wantoptions[0].mppe,
122 "don't allow MPPE encryption", OPT_ALIAS | OPT_PRIO },
123
124 /* We use ccp_allowoptions[0].mppe as a junk var ... it is reset later */
125 { "require-mppe-40", o_bool, &ccp_allowoptions[0].mppe,
126 "require MPPE 40-bit encryption", OPT_PRIO | OPT_A2OR | MPPE_OPT_40,
127 &ccp_wantoptions[0].mppe },
128 { "+mppe-40", o_bool, &ccp_allowoptions[0].mppe,
129 "require MPPE 40-bit encryption", OPT_PRIO | OPT_A2OR | MPPE_OPT_40,
130 &ccp_wantoptions[0].mppe },
131 { "nomppe-40", o_bool, &ccp_allowoptions[0].mppe,
132 "don't allow MPPE 40-bit encryption",
133 OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_40, &ccp_wantoptions[0].mppe },
134 { "-mppe-40", o_bool, &ccp_allowoptions[0].mppe,
135 "don't allow MPPE 40-bit encryption",
136 OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_40,
137 &ccp_wantoptions[0].mppe },
138
139 { "require-mppe-128", o_bool, &ccp_allowoptions[0].mppe,
140 "require MPPE 128-bit encryption", OPT_PRIO | OPT_A2OR | MPPE_OPT_128,
141 &ccp_wantoptions[0].mppe },
142 { "+mppe-128", o_bool, &ccp_allowoptions[0].mppe,
143 "require MPPE 128-bit encryption",
144 OPT_ALIAS | OPT_PRIO | OPT_A2OR | MPPE_OPT_128,
145 &ccp_wantoptions[0].mppe },
146 { "nomppe-128", o_bool, &ccp_allowoptions[0].mppe,
147 "don't allow MPPE 128-bit encryption",
148 OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_128, &ccp_wantoptions[0].mppe },
149 { "-mppe-128", o_bool, &ccp_allowoptions[0].mppe,
150 "don't allow MPPE 128-bit encryption",
151 OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_128,
152 &ccp_wantoptions[0].mppe },
153
154 /* strange one; we always request stateless, but will we allow stateful? */
155 { "mppe-stateful", o_bool, &refuse_mppe_stateful,
156 "allow MPPE stateful mode", OPT_PRIO },
157 { "nomppe-stateful", o_bool, &refuse_mppe_stateful,
158 "disallow MPPE stateful mode", OPT_PRIO | 1 },
159#endif /* MPPE_SUPPORT */
160
161 { NULL }
162};
163#endif /* PPP_OPTIONS */
164
165/*
166 * Protocol entry points from main code.
167 */
168static void ccp_init(ppp_pcb *pcb);
169static void ccp_open(ppp_pcb *pcb);
170static void ccp_close(ppp_pcb *pcb, const char *reason);
171static void ccp_lowerup(ppp_pcb *pcb);
172static void ccp_lowerdown(ppp_pcb *pcb);
173static void ccp_input(ppp_pcb *pcb, u_char *pkt, int len);
174static void ccp_protrej(ppp_pcb *pcb);
175#if PRINTPKT_SUPPORT
176static int ccp_printpkt(const u_char *p, int plen, void (*printer) (void *, const char *, ...), void *arg);
177#endif /* PRINTPKT_SUPPORT */
178#if PPP_DATAINPUT
179static void ccp_datainput(ppp_pcb *pcb, u_char *pkt, int len);
180#endif /* PPP_DATAINPUT */
181
182const struct protent ccp_protent = {
183 PPP_CCP,
184 ccp_init,
185 ccp_input,
186 ccp_protrej,
187 ccp_lowerup,
188 ccp_lowerdown,
189 ccp_open,
190 ccp_close,
191#if PRINTPKT_SUPPORT
192 ccp_printpkt,
193#endif /* PRINTPKT_SUPPORT */
194#if PPP_DATAINPUT
195 ccp_datainput,
196#endif /* PPP_DATAINPUT */
197#if PRINTPKT_SUPPORT
198 "CCP",
199 "Compressed",
200#endif /* PRINTPKT_SUPPORT */
201#if PPP_OPTIONS
202 ccp_option_list,
203 NULL,
204#endif /* PPP_OPTIONS */
205#if DEMAND_SUPPORT
206 NULL,
207 NULL
208#endif /* DEMAND_SUPPORT */
209};
210
211/*
212 * Callbacks for fsm code.
213 */
214static void ccp_resetci (fsm *);
215static int ccp_cilen (fsm *);
216static void ccp_addci (fsm *, u_char *, int *);
217static int ccp_ackci (fsm *, u_char *, int);
218static int ccp_nakci (fsm *, u_char *, int, int);
219static int ccp_rejci (fsm *, u_char *, int);
220static int ccp_reqci (fsm *, u_char *, int *, int);
221static void ccp_up (fsm *);
222static void ccp_down (fsm *);
223static int ccp_extcode (fsm *, int, int, u_char *, int);
224static void ccp_rack_timeout (void *);
225static const char *method_name (ccp_options *, ccp_options *);
226
227static const fsm_callbacks ccp_callbacks = {
228 ccp_resetci,
229 ccp_cilen,
230 ccp_addci,
231 ccp_ackci,
232 ccp_nakci,
233 ccp_rejci,
234 ccp_reqci,
235 ccp_up,
236 ccp_down,
237 NULL,
238 NULL,
239 NULL,
240 NULL,
241 ccp_extcode,
242 "CCP"
243};
244
245/*
246 * Do we want / did we get any compression?
247 */
248static int ccp_anycompress(ccp_options *opt) {
249 return (0
250#if DEFLATE_SUPPORT
251 || (opt)->deflate
252#endif /* DEFLATE_SUPPORT */
253#if BSDCOMPRESS_SUPPORT
254 || (opt)->bsd_compress
255#endif /* BSDCOMPRESS_SUPPORT */
256#if PREDICTOR_SUPPORT
257 || (opt)->predictor_1 || (opt)->predictor_2
258#endif /* PREDICTOR_SUPPORT */
259#if MPPE_SUPPORT
260 || (opt)->mppe
261#endif /* MPPE_SUPPORT */
262 );
263}
264
265/*
266 * Local state (mainly for handling reset-reqs and reset-acks).
267 */
268#define RACK_PENDING 1 /* waiting for reset-ack */
269#define RREQ_REPEAT 2 /* send another reset-req if no reset-ack */
270
271#define RACKTIMEOUT 1 /* second */
272
273#if PPP_OPTIONS
274/*
275 * Option parsing
276 */
277static int
278setbsdcomp(argv)
279 char **argv;
280{
281 int rbits, abits;
282 char *str, *endp;
283
284 str = *argv;
285 abits = rbits = strtol(str, &endp, 0);
286 if (endp != str && *endp == ',') {
287 str = endp + 1;
288 abits = strtol(str, &endp, 0);
289 }
290 if (*endp != 0 || endp == str) {
291 option_error("invalid parameter '%s' for bsdcomp option", *argv);
292 return 0;
293 }
294 if ((rbits != 0 && (rbits < BSD_MIN_BITS || rbits > BSD_MAX_BITS))
295 || (abits != 0 && (abits < BSD_MIN_BITS || abits > BSD_MAX_BITS))) {
296 option_error("bsdcomp option values must be 0 or %d .. %d",
297 BSD_MIN_BITS, BSD_MAX_BITS);
298 return 0;
299 }
300 if (rbits > 0) {
301 ccp_wantoptions[0].bsd_compress = 1;
302 ccp_wantoptions[0].bsd_bits = rbits;
303 } else
304 ccp_wantoptions[0].bsd_compress = 0;
305 if (abits > 0) {
306 ccp_allowoptions[0].bsd_compress = 1;
307 ccp_allowoptions[0].bsd_bits = abits;
308 } else
309 ccp_allowoptions[0].bsd_compress = 0;
310 ppp_slprintf(bsd_value, sizeof(bsd_value),
311 rbits == abits? "%d": "%d,%d", rbits, abits);
312
313 return 1;
314}
315
316static int
317setdeflate(argv)
318 char **argv;
319{
320 int rbits, abits;
321 char *str, *endp;
322
323 str = *argv;
324 abits = rbits = strtol(str, &endp, 0);
325 if (endp != str && *endp == ',') {
326 str = endp + 1;
327 abits = strtol(str, &endp, 0);
328 }
329 if (*endp != 0 || endp == str) {
330 option_error("invalid parameter '%s' for deflate option", *argv);
331 return 0;
332 }
333 if ((rbits != 0 && (rbits < DEFLATE_MIN_SIZE || rbits > DEFLATE_MAX_SIZE))
334 || (abits != 0 && (abits < DEFLATE_MIN_SIZE
335 || abits > DEFLATE_MAX_SIZE))) {
336 option_error("deflate option values must be 0 or %d .. %d",
337 DEFLATE_MIN_SIZE, DEFLATE_MAX_SIZE);
338 return 0;
339 }
340 if (rbits == DEFLATE_MIN_SIZE || abits == DEFLATE_MIN_SIZE) {
341 if (rbits == DEFLATE_MIN_SIZE)
342 rbits = DEFLATE_MIN_WORKS;
343 if (abits == DEFLATE_MIN_SIZE)
344 abits = DEFLATE_MIN_WORKS;
345 warn("deflate option value of %d changed to %d to avoid zlib bug",
346 DEFLATE_MIN_SIZE, DEFLATE_MIN_WORKS);
347 }
348 if (rbits > 0) {
349 ccp_wantoptions[0].deflate = 1;
350 ccp_wantoptions[0].deflate_size = rbits;
351 } else
352 ccp_wantoptions[0].deflate = 0;
353 if (abits > 0) {
354 ccp_allowoptions[0].deflate = 1;
355 ccp_allowoptions[0].deflate_size = abits;
356 } else
357 ccp_allowoptions[0].deflate = 0;
358 ppp_slprintf(deflate_value, sizeof(deflate_value),
359 rbits == abits? "%d": "%d,%d", rbits, abits);
360
361 return 1;
362}
363#endif /* PPP_OPTIONS */
364
365/*
366 * ccp_init - initialize CCP.
367 */
368static void ccp_init(ppp_pcb *pcb) {
369 fsm *f = &pcb->ccp_fsm;
370
371 f->pcb = pcb;
372 f->protocol = PPP_CCP;
373 f->callbacks = &ccp_callbacks;
374 fsm_init(f);
375
376#if 0 /* Not necessary, everything is cleared in ppp_new() */
377 memset(wo, 0, sizeof(*wo));
378 memset(go, 0, sizeof(*go));
379 memset(ao, 0, sizeof(*ao));
380 memset(ho, 0, sizeof(*ho));
381#endif /* 0 */
382
383#if DEFLATE_SUPPORT
384 wo->deflate = 1;
385 wo->deflate_size = DEFLATE_MAX_SIZE;
386 wo->deflate_correct = 1;
387 wo->deflate_draft = 1;
388 ao->deflate = 1;
389 ao->deflate_size = DEFLATE_MAX_SIZE;
390 ao->deflate_correct = 1;
391 ao->deflate_draft = 1;
392#endif /* DEFLATE_SUPPORT */
393
394#if BSDCOMPRESS_SUPPORT
395 wo->bsd_compress = 1;
396 wo->bsd_bits = BSD_MAX_BITS;
397 ao->bsd_compress = 1;
398 ao->bsd_bits = BSD_MAX_BITS;
399#endif /* BSDCOMPRESS_SUPPORT */
400
401#if PREDICTOR_SUPPORT
402 ao->predictor_1 = 1;
403#endif /* PREDICTOR_SUPPORT */
404}
405
406/*
407 * ccp_open - CCP is allowed to come up.
408 */
409static void ccp_open(ppp_pcb *pcb) {
410 fsm *f = &pcb->ccp_fsm;
411 ccp_options *go = &pcb->ccp_gotoptions;
412
413 if (f->state != PPP_FSM_OPENED)
414 ccp_set(pcb, 1, 0, 0, 0);
415
416 /*
417 * Find out which compressors the kernel supports before
418 * deciding whether to open in silent mode.
419 */
420 ccp_resetci(f);
421 if (!ccp_anycompress(go))
422 f->flags |= OPT_SILENT;
423
424 fsm_open(f);
425}
426
427/*
428 * ccp_close - Terminate CCP.
429 */
430static void ccp_close(ppp_pcb *pcb, const char *reason) {
431 fsm *f = &pcb->ccp_fsm;
432 ccp_set(pcb, 0, 0, 0, 0);
433 fsm_close(f, reason);
434}
435
436/*
437 * ccp_lowerup - we may now transmit CCP packets.
438 */
439static void ccp_lowerup(ppp_pcb *pcb) {
440 fsm *f = &pcb->ccp_fsm;
441 fsm_lowerup(f);
442}
443
444/*
445 * ccp_lowerdown - we may not transmit CCP packets.
446 */
447static void ccp_lowerdown(ppp_pcb *pcb) {
448 fsm *f = &pcb->ccp_fsm;
449 fsm_lowerdown(f);
450}
451
452/*
453 * ccp_input - process a received CCP packet.
454 */
455static void ccp_input(ppp_pcb *pcb, u_char *p, int len) {
456 fsm *f = &pcb->ccp_fsm;
457 ccp_options *go = &pcb->ccp_gotoptions;
458 int oldstate;
459
460 /*
461 * Check for a terminate-request so we can print a message.
462 */
463 oldstate = f->state;
464 fsm_input(f, p, len);
465 if (oldstate == PPP_FSM_OPENED && p[0] == TERMREQ && f->state != PPP_FSM_OPENED) {
466 ppp_notice("Compression disabled by peer.");
467#if MPPE_SUPPORT
468 if (go->mppe) {
469 ppp_error("MPPE disabled, closing LCP");
470 lcp_close(pcb, "MPPE disabled by peer");
471 }
472#endif /* MPPE_SUPPORT */
473 }
474
475 /*
476 * If we get a terminate-ack and we're not asking for compression,
477 * close CCP.
478 */
479 if (oldstate == PPP_FSM_REQSENT && p[0] == TERMACK
480 && !ccp_anycompress(go))
481 ccp_close(pcb, "No compression negotiated");
482}
483
484/*
485 * Handle a CCP-specific code.
486 */
487static int ccp_extcode(fsm *f, int code, int id, u_char *p, int len) {
488 ppp_pcb *pcb = f->pcb;
489 LWIP_UNUSED_ARG(p);
490 LWIP_UNUSED_ARG(len);
491
492 switch (code) {
493 case CCP_RESETREQ:
494 if (f->state != PPP_FSM_OPENED)
495 break;
496 ccp_reset_comp(pcb);
497 /* send a reset-ack, which the transmitter will see and
498 reset its compression state. */
499 fsm_sdata(f, CCP_RESETACK, id, NULL, 0);
500 break;
501
502 case CCP_RESETACK:
503 if ((pcb->ccp_localstate & RACK_PENDING) && id == f->reqid) {
504 pcb->ccp_localstate &= ~(RACK_PENDING | RREQ_REPEAT);
505 UNTIMEOUT(ccp_rack_timeout, f);
506 ccp_reset_decomp(pcb);
507 }
508 break;
509
510 default:
511 return 0;
512 }
513
514 return 1;
515}
516
517/*
518 * ccp_protrej - peer doesn't talk CCP.
519 */
520static void ccp_protrej(ppp_pcb *pcb) {
521 fsm *f = &pcb->ccp_fsm;
522#if MPPE_SUPPORT
523 ccp_options *go = &pcb->ccp_gotoptions;
524#endif /* MPPE_SUPPORT */
525
526 ccp_set(pcb, 0, 0, 0, 0);
527 fsm_lowerdown(f);
528
529#if MPPE_SUPPORT
530 if (go->mppe) {
531 ppp_error("MPPE required but peer negotiation failed");
532 lcp_close(pcb, "MPPE required but peer negotiation failed");
533 }
534#endif /* MPPE_SUPPORT */
535
536}
537
538/*
539 * ccp_resetci - initialize at start of negotiation.
540 */
541static void ccp_resetci(fsm *f) {
542 ppp_pcb *pcb = f->pcb;
543 ccp_options *go = &pcb->ccp_gotoptions;
544 ccp_options *wo = &pcb->ccp_wantoptions;
545#if MPPE_SUPPORT
546 ccp_options *ao = &pcb->ccp_allowoptions;
547#endif /* MPPE_SUPPORT */
548#if DEFLATE_SUPPORT || BSDCOMPRESS_SUPPORT || PREDICTOR_SUPPORT
549 u_char opt_buf[CCP_MAX_OPTION_LENGTH];
550#endif /* DEFLATE_SUPPORT || BSDCOMPRESS_SUPPORT || PREDICTOR_SUPPORT */
551#if DEFLATE_SUPPORT || BSDCOMPRESS_SUPPORT
552 int res;
553#endif /* DEFLATE_SUPPORT || BSDCOMPRESS_SUPPORT */
554
555#if MPPE_SUPPORT
556 if (pcb->settings.require_mppe) {
557 wo->mppe = ao->mppe =
558 (pcb->settings.refuse_mppe_40 ? 0 : MPPE_OPT_40)
559 | (pcb->settings.refuse_mppe_128 ? 0 : MPPE_OPT_128);
560 }
561#endif /* MPPE_SUPPORT */
562
563 *go = *wo;
564 pcb->ccp_all_rejected = 0;
565
566#if MPPE_SUPPORT
567 if (go->mppe) {
568 int auth_mschap_bits = pcb->auth_done;
569 int numbits;
570
571 /*
572 * Start with a basic sanity check: mschap[v2] auth must be in
573 * exactly one direction. RFC 3079 says that the keys are
574 * 'derived from the credentials of the peer that initiated the call',
575 * however the PPP protocol doesn't have such a concept, and pppd
576 * cannot get this info externally. Instead we do the best we can.
577 * NB: If MPPE is required, all other compression opts are invalid.
578 * So, we return right away if we can't do it.
579 */
580
581 /* Leave only the mschap auth bits set */
582 auth_mschap_bits &= (CHAP_MS_WITHPEER | CHAP_MS_PEER |
583 CHAP_MS2_WITHPEER | CHAP_MS2_PEER);
584 /* Count the mschap auths */
585 auth_mschap_bits >>= CHAP_MS_SHIFT;
586 numbits = 0;
587 do {
588 numbits += auth_mschap_bits & 1;
589 auth_mschap_bits >>= 1;
590 } while (auth_mschap_bits);
591 if (numbits > 1) {
592 ppp_error("MPPE required, but auth done in both directions.");
593 lcp_close(pcb, "MPPE required but not available");
594 return;
595 }
596 if (!numbits) {
597 ppp_error("MPPE required, but MS-CHAP[v2] auth not performed.");
598 lcp_close(pcb, "MPPE required but not available");
599 return;
600 }
601
602 /* A plugin (eg radius) may not have obtained key material. */
603 if (!pcb->mppe_keys_set) {
604 ppp_error("MPPE required, but keys are not available. "
605 "Possible plugin problem?");
606 lcp_close(pcb, "MPPE required but not available");
607 return;
608 }
609
610 /* LM auth not supported for MPPE */
611 if (pcb->auth_done & (CHAP_MS_WITHPEER | CHAP_MS_PEER)) {
612 /* This might be noise */
613 if (go->mppe & MPPE_OPT_40) {
614 ppp_notice("Disabling 40-bit MPPE; MS-CHAP LM not supported");
615 go->mppe &= ~MPPE_OPT_40;
616 wo->mppe &= ~MPPE_OPT_40;
617 }
618 }
619
620 /* Last check: can we actually negotiate something? */
621 if (!(go->mppe & (MPPE_OPT_40 | MPPE_OPT_128))) {
622 /* Could be misconfig, could be 40-bit disabled above. */
623 ppp_error("MPPE required, but both 40-bit and 128-bit disabled.");
624 lcp_close(pcb, "MPPE required but not available");
625 return;
626 }
627
628 /* sync options */
629 ao->mppe = go->mppe;
630 /* MPPE is not compatible with other compression types */
631#if BSDCOMPRESS_SUPPORT
632 ao->bsd_compress = go->bsd_compress = 0;
633#endif /* BSDCOMPRESS_SUPPORT */
634#if PREDICTOR_SUPPORT
635 ao->predictor_1 = go->predictor_1 = 0;
636 ao->predictor_2 = go->predictor_2 = 0;
637#endif /* PREDICTOR_SUPPORT */
638#if DEFLATE_SUPPORT
639 ao->deflate = go->deflate = 0;
640#endif /* DEFLATE_SUPPORT */
641 }
642#endif /* MPPE_SUPPORT */
643
644 /*
645 * Check whether the kernel knows about the various
646 * compression methods we might request.
647 */
648#if BSDCOMPRESS_SUPPORT
649 /* FIXME: we don't need to test if BSD compress is available
650 * if BSDCOMPRESS_SUPPORT is set, it is.
651 */
652 if (go->bsd_compress) {
653 opt_buf[0] = CI_BSD_COMPRESS;
654 opt_buf[1] = CILEN_BSD_COMPRESS;
655 for (;;) {
656 if (go->bsd_bits < BSD_MIN_BITS) {
657 go->bsd_compress = 0;
658 break;
659 }
660 opt_buf[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits);
661 res = ccp_test(pcb, opt_buf, CILEN_BSD_COMPRESS, 0);
662 if (res > 0) {
663 break;
664 } else if (res < 0) {
665 go->bsd_compress = 0;
666 break;
667 }
668 go->bsd_bits--;
669 }
670 }
671#endif /* BSDCOMPRESS_SUPPORT */
672#if DEFLATE_SUPPORT
673 /* FIXME: we don't need to test if deflate is available
674 * if DEFLATE_SUPPORT is set, it is.
675 */
676 if (go->deflate) {
677 if (go->deflate_correct) {
678 opt_buf[0] = CI_DEFLATE;
679 opt_buf[1] = CILEN_DEFLATE;
680 opt_buf[3] = DEFLATE_CHK_SEQUENCE;
681 for (;;) {
682 if (go->deflate_size < DEFLATE_MIN_WORKS) {
683 go->deflate_correct = 0;
684 break;
685 }
686 opt_buf[2] = DEFLATE_MAKE_OPT(go->deflate_size);
687 res = ccp_test(pcb, opt_buf, CILEN_DEFLATE, 0);
688 if (res > 0) {
689 break;
690 } else if (res < 0) {
691 go->deflate_correct = 0;
692 break;
693 }
694 go->deflate_size--;
695 }
696 }
697 if (go->deflate_draft) {
698 opt_buf[0] = CI_DEFLATE_DRAFT;
699 opt_buf[1] = CILEN_DEFLATE;
700 opt_buf[3] = DEFLATE_CHK_SEQUENCE;
701 for (;;) {
702 if (go->deflate_size < DEFLATE_MIN_WORKS) {
703 go->deflate_draft = 0;
704 break;
705 }
706 opt_buf[2] = DEFLATE_MAKE_OPT(go->deflate_size);
707 res = ccp_test(pcb, opt_buf, CILEN_DEFLATE, 0);
708 if (res > 0) {
709 break;
710 } else if (res < 0) {
711 go->deflate_draft = 0;
712 break;
713 }
714 go->deflate_size--;
715 }
716 }
717 if (!go->deflate_correct && !go->deflate_draft)
718 go->deflate = 0;
719 }
720#endif /* DEFLATE_SUPPORT */
721#if PREDICTOR_SUPPORT
722 /* FIXME: we don't need to test if predictor is available,
723 * if PREDICTOR_SUPPORT is set, it is.
724 */
725 if (go->predictor_1) {
726 opt_buf[0] = CI_PREDICTOR_1;
727 opt_buf[1] = CILEN_PREDICTOR_1;
728 if (ccp_test(pcb, opt_buf, CILEN_PREDICTOR_1, 0) <= 0)
729 go->predictor_1 = 0;
730 }
731 if (go->predictor_2) {
732 opt_buf[0] = CI_PREDICTOR_2;
733 opt_buf[1] = CILEN_PREDICTOR_2;
734 if (ccp_test(pcb, opt_buf, CILEN_PREDICTOR_2, 0) <= 0)
735 go->predictor_2 = 0;
736 }
737#endif /* PREDICTOR_SUPPORT */
738}
739
740/*
741 * ccp_cilen - Return total length of our configuration info.
742 */
743static int ccp_cilen(fsm *f) {
744 ppp_pcb *pcb = f->pcb;
745 ccp_options *go = &pcb->ccp_gotoptions;
746
747 return 0
748#if BSDCOMPRESS_SUPPORT
749 + (go->bsd_compress? CILEN_BSD_COMPRESS: 0)
750#endif /* BSDCOMPRESS_SUPPORT */
751#if DEFLATE_SUPPORT
752 + (go->deflate && go->deflate_correct? CILEN_DEFLATE: 0)
753 + (go->deflate && go->deflate_draft? CILEN_DEFLATE: 0)
754#endif /* DEFLATE_SUPPORT */
755#if PREDICTOR_SUPPORT
756 + (go->predictor_1? CILEN_PREDICTOR_1: 0)
757 + (go->predictor_2? CILEN_PREDICTOR_2: 0)
758#endif /* PREDICTOR_SUPPORT */
759#if MPPE_SUPPORT
760 + (go->mppe? CILEN_MPPE: 0)
761#endif /* MPPE_SUPPORT */
762 ;
763}
764
765/*
766 * ccp_addci - put our requests in a packet.
767 */
768static void ccp_addci(fsm *f, u_char *p, int *lenp) {
769 ppp_pcb *pcb = f->pcb;
770 ccp_options *go = &pcb->ccp_gotoptions;
771 u_char *p0 = p;
772
773 /*
774 * Add the compression types that we can receive, in decreasing
775 * preference order.
776 */
777#if MPPE_SUPPORT
778 if (go->mppe) {
779 p[0] = CI_MPPE;
780 p[1] = CILEN_MPPE;
781 MPPE_OPTS_TO_CI(go->mppe, &p[2]);
782 mppe_init(pcb, &pcb->mppe_decomp, go->mppe);
783 p += CILEN_MPPE;
784 }
785#endif /* MPPE_SUPPORT */
786#if DEFLATE_SUPPORT
787 if (go->deflate) {
788 if (go->deflate_correct) {
789 p[0] = CI_DEFLATE;
790 p[1] = CILEN_DEFLATE;
791 p[2] = DEFLATE_MAKE_OPT(go->deflate_size);
792 p[3] = DEFLATE_CHK_SEQUENCE;
793 p += CILEN_DEFLATE;
794 }
795 if (go->deflate_draft) {
796 p[0] = CI_DEFLATE_DRAFT;
797 p[1] = CILEN_DEFLATE;
798 p[2] = p[2 - CILEN_DEFLATE];
799 p[3] = DEFLATE_CHK_SEQUENCE;
800 p += CILEN_DEFLATE;
801 }
802 }
803#endif /* DEFLATE_SUPPORT */
804#if BSDCOMPRESS_SUPPORT
805 if (go->bsd_compress) {
806 p[0] = CI_BSD_COMPRESS;
807 p[1] = CILEN_BSD_COMPRESS;
808 p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits);
809 p += CILEN_BSD_COMPRESS;
810 }
811#endif /* BSDCOMPRESS_SUPPORT */
812#if PREDICTOR_SUPPORT
813 /* XXX Should Predictor 2 be preferable to Predictor 1? */
814 if (go->predictor_1) {
815 p[0] = CI_PREDICTOR_1;
816 p[1] = CILEN_PREDICTOR_1;
817 p += CILEN_PREDICTOR_1;
818 }
819 if (go->predictor_2) {
820 p[0] = CI_PREDICTOR_2;
821 p[1] = CILEN_PREDICTOR_2;
822 p += CILEN_PREDICTOR_2;
823 }
824#endif /* PREDICTOR_SUPPORT */
825
826 go->method = (p > p0)? p0[0]: 0;
827
828 *lenp = p - p0;
829}
830
831/*
832 * ccp_ackci - process a received configure-ack, and return
833 * 1 iff the packet was OK.
834 */
835static int ccp_ackci(fsm *f, u_char *p, int len) {
836 ppp_pcb *pcb = f->pcb;
837 ccp_options *go = &pcb->ccp_gotoptions;
838#if BSDCOMPRESS_SUPPORT || PREDICTOR_SUPPORT
839 u_char *p0 = p;
840#endif /* BSDCOMPRESS_SUPPORT || PREDICTOR_SUPPORT */
841
842#if MPPE_SUPPORT
843 if (go->mppe) {
844 u_char opt_buf[CILEN_MPPE];
845
846 opt_buf[0] = CI_MPPE;
847 opt_buf[1] = CILEN_MPPE;
848 MPPE_OPTS_TO_CI(go->mppe, &opt_buf[2]);
849 if (len < CILEN_MPPE || memcmp(opt_buf, p, CILEN_MPPE))
850 return 0;
851 p += CILEN_MPPE;
852 len -= CILEN_MPPE;
853 /* XXX Cope with first/fast ack */
854 if (len == 0)
855 return 1;
856 }
857#endif /* MPPE_SUPPORT */
858#if DEFLATE_SUPPORT
859 if (go->deflate) {
860 if (len < CILEN_DEFLATE
861 || p[0] != (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT)
862 || p[1] != CILEN_DEFLATE
863 || p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
864 || p[3] != DEFLATE_CHK_SEQUENCE)
865 return 0;
866 p += CILEN_DEFLATE;
867 len -= CILEN_DEFLATE;
868 /* XXX Cope with first/fast ack */
869 if (len == 0)
870 return 1;
871 if (go->deflate_correct && go->deflate_draft) {
872 if (len < CILEN_DEFLATE
873 || p[0] != CI_DEFLATE_DRAFT
874 || p[1] != CILEN_DEFLATE
875 || p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
876 || p[3] != DEFLATE_CHK_SEQUENCE)
877 return 0;
878 p += CILEN_DEFLATE;
879 len -= CILEN_DEFLATE;
880 }
881 }
882#endif /* DEFLATE_SUPPORT */
883#if BSDCOMPRESS_SUPPORT
884 if (go->bsd_compress) {
885 if (len < CILEN_BSD_COMPRESS
886 || p[0] != CI_BSD_COMPRESS || p[1] != CILEN_BSD_COMPRESS
887 || p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits))
888 return 0;
889 p += CILEN_BSD_COMPRESS;
890 len -= CILEN_BSD_COMPRESS;
891 /* XXX Cope with first/fast ack */
892 if (p == p0 && len == 0)
893 return 1;
894 }
895#endif /* BSDCOMPRESS_SUPPORT */
896#if PREDICTOR_SUPPORT
897 if (go->predictor_1) {
898 if (len < CILEN_PREDICTOR_1
899 || p[0] != CI_PREDICTOR_1 || p[1] != CILEN_PREDICTOR_1)
900 return 0;
901 p += CILEN_PREDICTOR_1;
902 len -= CILEN_PREDICTOR_1;
903 /* XXX Cope with first/fast ack */
904 if (p == p0 && len == 0)
905 return 1;
906 }
907 if (go->predictor_2) {
908 if (len < CILEN_PREDICTOR_2
909 || p[0] != CI_PREDICTOR_2 || p[1] != CILEN_PREDICTOR_2)
910 return 0;
911 p += CILEN_PREDICTOR_2;
912 len -= CILEN_PREDICTOR_2;
913 /* XXX Cope with first/fast ack */
914 if (p == p0 && len == 0)
915 return 1;
916 }
917#endif /* PREDICTOR_SUPPORT */
918
919 if (len != 0)
920 return 0;
921 return 1;
922}
923
924/*
925 * ccp_nakci - process received configure-nak.
926 * Returns 1 iff the nak was OK.
927 */
928static int ccp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) {
929 ppp_pcb *pcb = f->pcb;
930 ccp_options *go = &pcb->ccp_gotoptions;
931 ccp_options no; /* options we've seen already */
932 ccp_options try_; /* options to ask for next time */
933 LWIP_UNUSED_ARG(treat_as_reject);
934#if !MPPE_SUPPORT && !DEFLATE_SUPPORT && !BSDCOMPRESS_SUPPORT
935 LWIP_UNUSED_ARG(p);
936 LWIP_UNUSED_ARG(len);
937#endif /* !MPPE_SUPPORT && !DEFLATE_SUPPORT && !BSDCOMPRESS_SUPPORT */
938
939 memset(&no, 0, sizeof(no));
940 try_ = *go;
941
942#if MPPE_SUPPORT
943 if (go->mppe && len >= CILEN_MPPE
944 && p[0] == CI_MPPE && p[1] == CILEN_MPPE) {
945 no.mppe = 1;
946 /*
947 * Peer wants us to use a different strength or other setting.
948 * Fail if we aren't willing to use his suggestion.
949 */
950 MPPE_CI_TO_OPTS(&p[2], try_.mppe);
951 if ((try_.mppe & MPPE_OPT_STATEFUL) && pcb->settings.refuse_mppe_stateful) {
952 ppp_error("Refusing MPPE stateful mode offered by peer");
953 try_.mppe = 0;
954 } else if (((go->mppe | MPPE_OPT_STATEFUL) & try_.mppe) != try_.mppe) {
955 /* Peer must have set options we didn't request (suggest) */
956 try_.mppe = 0;
957 }
958
959 if (!try_.mppe) {
960 ppp_error("MPPE required but peer negotiation failed");
961 lcp_close(pcb, "MPPE required but peer negotiation failed");
962 }
963 }
964#endif /* MPPE_SUPPORT */
965#if DEFLATE_SUPPORT
966 if (go->deflate && len >= CILEN_DEFLATE
967 && p[0] == (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT)
968 && p[1] == CILEN_DEFLATE) {
969 no.deflate = 1;
970 /*
971 * Peer wants us to use a different code size or something.
972 * Stop asking for Deflate if we don't understand his suggestion.
973 */
974 if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL
975 || DEFLATE_SIZE(p[2]) < DEFLATE_MIN_WORKS
976 || p[3] != DEFLATE_CHK_SEQUENCE)
977 try_.deflate = 0;
978 else if (DEFLATE_SIZE(p[2]) < go->deflate_size)
979 try_.deflate_size = DEFLATE_SIZE(p[2]);
980 p += CILEN_DEFLATE;
981 len -= CILEN_DEFLATE;
982 if (go->deflate_correct && go->deflate_draft
983 && len >= CILEN_DEFLATE && p[0] == CI_DEFLATE_DRAFT
984 && p[1] == CILEN_DEFLATE) {
985 p += CILEN_DEFLATE;
986 len -= CILEN_DEFLATE;
987 }
988 }
989#endif /* DEFLATE_SUPPORT */
990#if BSDCOMPRESS_SUPPORT
991 if (go->bsd_compress && len >= CILEN_BSD_COMPRESS
992 && p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) {
993 no.bsd_compress = 1;
994 /*
995 * Peer wants us to use a different number of bits
996 * or a different version.
997 */
998 if (BSD_VERSION(p[2]) != BSD_CURRENT_VERSION)
999 try_.bsd_compress = 0;
1000 else if (BSD_NBITS(p[2]) < go->bsd_bits)
1001 try_.bsd_bits = BSD_NBITS(p[2]);
1002 p += CILEN_BSD_COMPRESS;
1003 len -= CILEN_BSD_COMPRESS;
1004 }
1005#endif /* BSDCOMPRESS_SUPPORT */
1006
1007 /*
1008 * Predictor-1 and 2 have no options, so they can't be Naked.
1009 *
1010 * There may be remaining options but we ignore them.
1011 */
1012
1013 if (f->state != PPP_FSM_OPENED)
1014 *go = try_;
1015 return 1;
1016}
1017
1018/*
1019 * ccp_rejci - reject some of our suggested compression methods.
1020 */
1021static int ccp_rejci(fsm *f, u_char *p, int len) {
1022 ppp_pcb *pcb = f->pcb;
1023 ccp_options *go = &pcb->ccp_gotoptions;
1024 ccp_options try_; /* options to request next time */
1025
1026 try_ = *go;
1027
1028 /*
1029 * Cope with empty configure-rejects by ceasing to send
1030 * configure-requests.
1031 */
1032 if (len == 0 && pcb->ccp_all_rejected)
1033 return -1;
1034
1035#if MPPE_SUPPORT
1036 if (go->mppe && len >= CILEN_MPPE
1037 && p[0] == CI_MPPE && p[1] == CILEN_MPPE) {
1038 ppp_error("MPPE required but peer refused");
1039 lcp_close(pcb, "MPPE required but peer refused");
1040 p += CILEN_MPPE;
1041 len -= CILEN_MPPE;
1042 }
1043#endif /* MPPE_SUPPORT */
1044#if DEFLATE_SUPPORT
1045 if (go->deflate_correct && len >= CILEN_DEFLATE
1046 && p[0] == CI_DEFLATE && p[1] == CILEN_DEFLATE) {
1047 if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
1048 || p[3] != DEFLATE_CHK_SEQUENCE)
1049 return 0; /* Rej is bad */
1050 try_.deflate_correct = 0;
1051 p += CILEN_DEFLATE;
1052 len -= CILEN_DEFLATE;
1053 }
1054 if (go->deflate_draft && len >= CILEN_DEFLATE
1055 && p[0] == CI_DEFLATE_DRAFT && p[1] == CILEN_DEFLATE) {
1056 if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
1057 || p[3] != DEFLATE_CHK_SEQUENCE)
1058 return 0; /* Rej is bad */
1059 try_.deflate_draft = 0;
1060 p += CILEN_DEFLATE;
1061 len -= CILEN_DEFLATE;
1062 }
1063 if (!try_.deflate_correct && !try_.deflate_draft)
1064 try_.deflate = 0;
1065#endif /* DEFLATE_SUPPORT */
1066#if BSDCOMPRESS_SUPPORT
1067 if (go->bsd_compress && len >= CILEN_BSD_COMPRESS
1068 && p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) {
1069 if (p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits))
1070 return 0;
1071 try_.bsd_compress = 0;
1072 p += CILEN_BSD_COMPRESS;
1073 len -= CILEN_BSD_COMPRESS;
1074 }
1075#endif /* BSDCOMPRESS_SUPPORT */
1076#if PREDICTOR_SUPPORT
1077 if (go->predictor_1 && len >= CILEN_PREDICTOR_1
1078 && p[0] == CI_PREDICTOR_1 && p[1] == CILEN_PREDICTOR_1) {
1079 try_.predictor_1 = 0;
1080 p += CILEN_PREDICTOR_1;
1081 len -= CILEN_PREDICTOR_1;
1082 }
1083 if (go->predictor_2 && len >= CILEN_PREDICTOR_2
1084 && p[0] == CI_PREDICTOR_2 && p[1] == CILEN_PREDICTOR_2) {
1085 try_.predictor_2 = 0;
1086 p += CILEN_PREDICTOR_2;
1087 len -= CILEN_PREDICTOR_2;
1088 }
1089#endif /* PREDICTOR_SUPPORT */
1090
1091 if (len != 0)
1092 return 0;
1093
1094 if (f->state != PPP_FSM_OPENED)
1095 *go = try_;
1096
1097 return 1;
1098}
1099
1100/*
1101 * ccp_reqci - processed a received configure-request.
1102 * Returns CONFACK, CONFNAK or CONFREJ and the packet modified
1103 * appropriately.
1104 */
1105static int ccp_reqci(fsm *f, u_char *p, int *lenp, int dont_nak) {
1106 ppp_pcb *pcb = f->pcb;
1107 ccp_options *ho = &pcb->ccp_hisoptions;
1108 ccp_options *ao = &pcb->ccp_allowoptions;
1109 int ret, newret;
1110#if DEFLATE_SUPPORT || BSDCOMPRESS_SUPPORT
1111 int res;
1112 int nb;
1113#endif /* DEFLATE_SUPPORT || BSDCOMPRESS_SUPPORT */
1114 u_char *p0, *retp;
1115 int len, clen, type;
1116#if MPPE_SUPPORT
1117 u8_t rej_for_ci_mppe = 1; /* Are we rejecting based on a bad/missing */
1118 /* CI_MPPE, or due to other options? */
1119#endif /* MPPE_SUPPORT */
1120
1121 ret = CONFACK;
1122 retp = p0 = p;
1123 len = *lenp;
1124
1125 memset(ho, 0, sizeof(ccp_options));
1126 ho->method = (len > 0)? p[0]: 0;
1127
1128 while (len > 0) {
1129 newret = CONFACK;
1130 if (len < 2 || p[1] < 2 || p[1] > len) {
1131 /* length is bad */
1132 clen = len;
1133 newret = CONFREJ;
1134
1135 } else {
1136 type = p[0];
1137 clen = p[1];
1138
1139 switch (type) {
1140#if MPPE_SUPPORT
1141 case CI_MPPE:
1142 if (!ao->mppe || clen != CILEN_MPPE) {
1143 newret = CONFREJ;
1144 break;
1145 }
1146 MPPE_CI_TO_OPTS(&p[2], ho->mppe);
1147
1148 /* Nak if anything unsupported or unknown are set. */
1149 if (ho->mppe & MPPE_OPT_UNSUPPORTED) {
1150 newret = CONFNAK;
1151 ho->mppe &= ~MPPE_OPT_UNSUPPORTED;
1152 }
1153 if (ho->mppe & MPPE_OPT_UNKNOWN) {
1154 newret = CONFNAK;
1155 ho->mppe &= ~MPPE_OPT_UNKNOWN;
1156 }
1157
1158 /* Check state opt */
1159 if (ho->mppe & MPPE_OPT_STATEFUL) {
1160 /*
1161 * We can Nak and request stateless, but it's a
1162 * lot easier to just assume the peer will request
1163 * it if he can do it; stateful mode is bad over
1164 * the Internet -- which is where we expect MPPE.
1165 */
1166 if (pcb->settings.refuse_mppe_stateful) {
1167 ppp_error("Refusing MPPE stateful mode offered by peer");
1168 newret = CONFREJ;
1169 break;
1170 }
1171 }
1172
1173 /* Find out which of {S,L} are set. */
1174 if ((ho->mppe & MPPE_OPT_128)
1175 && (ho->mppe & MPPE_OPT_40)) {
1176 /* Both are set, negotiate the strongest. */
1177 newret = CONFNAK;
1178 if (ao->mppe & MPPE_OPT_128)
1179 ho->mppe &= ~MPPE_OPT_40;
1180 else if (ao->mppe & MPPE_OPT_40)
1181 ho->mppe &= ~MPPE_OPT_128;
1182 else {
1183 newret = CONFREJ;
1184 break;
1185 }
1186 } else if (ho->mppe & MPPE_OPT_128) {
1187 if (!(ao->mppe & MPPE_OPT_128)) {
1188 newret = CONFREJ;
1189 break;
1190 }
1191 } else if (ho->mppe & MPPE_OPT_40) {
1192 if (!(ao->mppe & MPPE_OPT_40)) {
1193 newret = CONFREJ;
1194 break;
1195 }
1196 } else {
1197 /* Neither are set. */
1198 /* We cannot accept this. */
1199 newret = CONFNAK;
1200 /* Give the peer our idea of what can be used,
1201 so it can choose and confirm */
1202 ho->mppe = ao->mppe;
1203 }
1204
1205 /* rebuild the opts */
1206 MPPE_OPTS_TO_CI(ho->mppe, &p[2]);
1207 if (newret == CONFACK) {
1208 int mtu;
1209
1210 mppe_init(pcb, &pcb->mppe_comp, ho->mppe);
1211 /*
1212 * We need to decrease the interface MTU by MPPE_PAD
1213 * because MPPE frames **grow**. The kernel [must]
1214 * allocate MPPE_PAD extra bytes in xmit buffers.
1215 */
1216 mtu = netif_get_mtu(pcb);
1217 if (mtu)
1218 netif_set_mtu(pcb, mtu - MPPE_PAD);
1219 else
1220 newret = CONFREJ;
1221 }
1222
1223 /*
1224 * We have accepted MPPE or are willing to negotiate
1225 * MPPE parameters. A CONFREJ is due to subsequent
1226 * (non-MPPE) processing.
1227 */
1228 rej_for_ci_mppe = 0;
1229 break;
1230#endif /* MPPE_SUPPORT */
1231#if DEFLATE_SUPPORT
1232 case CI_DEFLATE:
1233 case CI_DEFLATE_DRAFT:
1234 if (!ao->deflate || clen != CILEN_DEFLATE
1235 || (!ao->deflate_correct && type == CI_DEFLATE)
1236 || (!ao->deflate_draft && type == CI_DEFLATE_DRAFT)) {
1237 newret = CONFREJ;
1238 break;
1239 }
1240
1241 ho->deflate = 1;
1242 ho->deflate_size = nb = DEFLATE_SIZE(p[2]);
1243 if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL
1244 || p[3] != DEFLATE_CHK_SEQUENCE
1245 || nb > ao->deflate_size || nb < DEFLATE_MIN_WORKS) {
1246 newret = CONFNAK;
1247 if (!dont_nak) {
1248 p[2] = DEFLATE_MAKE_OPT(ao->deflate_size);
1249 p[3] = DEFLATE_CHK_SEQUENCE;
1250 /* fall through to test this #bits below */
1251 } else
1252 break;
1253 }
1254
1255 /*
1256 * Check whether we can do Deflate with the window
1257 * size they want. If the window is too big, reduce
1258 * it until the kernel can cope and nak with that.
1259 * We only check this for the first option.
1260 */
1261 if (p == p0) {
1262 for (;;) {
1263 res = ccp_test(pcb, p, CILEN_DEFLATE, 1);
1264 if (res > 0)
1265 break; /* it's OK now */
1266 if (res < 0 || nb == DEFLATE_MIN_WORKS || dont_nak) {
1267 newret = CONFREJ;
1268 p[2] = DEFLATE_MAKE_OPT(ho->deflate_size);
1269 break;
1270 }
1271 newret = CONFNAK;
1272 --nb;
1273 p[2] = DEFLATE_MAKE_OPT(nb);
1274 }
1275 }
1276 break;
1277#endif /* DEFLATE_SUPPORT */
1278#if BSDCOMPRESS_SUPPORT
1279 case CI_BSD_COMPRESS:
1280 if (!ao->bsd_compress || clen != CILEN_BSD_COMPRESS) {
1281 newret = CONFREJ;
1282 break;
1283 }
1284
1285 ho->bsd_compress = 1;
1286 ho->bsd_bits = nb = BSD_NBITS(p[2]);
1287 if (BSD_VERSION(p[2]) != BSD_CURRENT_VERSION
1288 || nb > ao->bsd_bits || nb < BSD_MIN_BITS) {
1289 newret = CONFNAK;
1290 if (!dont_nak) {
1291 p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, ao->bsd_bits);
1292 /* fall through to test this #bits below */
1293 } else
1294 break;
1295 }
1296
1297 /*
1298 * Check whether we can do BSD-Compress with the code
1299 * size they want. If the code size is too big, reduce
1300 * it until the kernel can cope and nak with that.
1301 * We only check this for the first option.
1302 */
1303 if (p == p0) {
1304 for (;;) {
1305 res = ccp_test(pcb, p, CILEN_BSD_COMPRESS, 1);
1306 if (res > 0)
1307 break;
1308 if (res < 0 || nb == BSD_MIN_BITS || dont_nak) {
1309 newret = CONFREJ;
1310 p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION,
1311 ho->bsd_bits);
1312 break;
1313 }
1314 newret = CONFNAK;
1315 --nb;
1316 p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, nb);
1317 }
1318 }
1319 break;
1320#endif /* BSDCOMPRESS_SUPPORT */
1321#if PREDICTOR_SUPPORT
1322 case CI_PREDICTOR_1:
1323 if (!ao->predictor_1 || clen != CILEN_PREDICTOR_1) {
1324 newret = CONFREJ;
1325 break;
1326 }
1327
1328 ho->predictor_1 = 1;
1329 if (p == p0
1330 && ccp_test(pcb, p, CILEN_PREDICTOR_1, 1) <= 0) {
1331 newret = CONFREJ;
1332 }
1333 break;
1334
1335 case CI_PREDICTOR_2:
1336 if (!ao->predictor_2 || clen != CILEN_PREDICTOR_2) {
1337 newret = CONFREJ;
1338 break;
1339 }
1340
1341 ho->predictor_2 = 1;
1342 if (p == p0
1343 && ccp_test(pcb, p, CILEN_PREDICTOR_2, 1) <= 0) {
1344 newret = CONFREJ;
1345 }
1346 break;
1347#endif /* PREDICTOR_SUPPORT */
1348
1349 default:
1350 newret = CONFREJ;
1351 }
1352 }
1353
1354 if (newret == CONFNAK && dont_nak)
1355 newret = CONFREJ;
1356 if (!(newret == CONFACK || (newret == CONFNAK && ret == CONFREJ))) {
1357 /* we're returning this option */
1358 if (newret == CONFREJ && ret == CONFNAK)
1359 retp = p0;
1360 ret = newret;
1361 if (p != retp)
1362 MEMCPY(retp, p, clen);
1363 retp += clen;
1364 }
1365
1366 p += clen;
1367 len -= clen;
1368 }
1369
1370 if (ret != CONFACK) {
1371 if (ret == CONFREJ && *lenp == retp - p0)
1372 pcb->ccp_all_rejected = 1;
1373 else
1374 *lenp = retp - p0;
1375 }
1376#if MPPE_SUPPORT
1377 if (ret == CONFREJ && ao->mppe && rej_for_ci_mppe) {
1378 ppp_error("MPPE required but peer negotiation failed");
1379 lcp_close(pcb, "MPPE required but peer negotiation failed");
1380 }
1381#endif /* MPPE_SUPPORT */
1382 return ret;
1383}
1384
1385/*
1386 * Make a string name for a compression method (or 2).
1387 */
1388static const char *method_name(ccp_options *opt, ccp_options *opt2) {
1389 static char result[64];
1390#if !DEFLATE_SUPPORT && !BSDCOMPRESS_SUPPORT
1391 LWIP_UNUSED_ARG(opt2);
1392#endif /* !DEFLATE_SUPPORT && !BSDCOMPRESS_SUPPORT */
1393
1394 if (!ccp_anycompress(opt))
1395 return "(none)";
1396 switch (opt->method) {
1397#if MPPE_SUPPORT
1398 case CI_MPPE:
1399 {
1400 char *p = result;
1401 char *q = result + sizeof(result); /* 1 past result */
1402
1403 ppp_slprintf(p, q - p, "MPPE ");
1404 p += 5;
1405 if (opt->mppe & MPPE_OPT_128) {
1406 ppp_slprintf(p, q - p, "128-bit ");
1407 p += 8;
1408 }
1409 if (opt->mppe & MPPE_OPT_40) {
1410 ppp_slprintf(p, q - p, "40-bit ");
1411 p += 7;
1412 }
1413 if (opt->mppe & MPPE_OPT_STATEFUL)
1414 ppp_slprintf(p, q - p, "stateful");
1415 else
1416 ppp_slprintf(p, q - p, "stateless");
1417
1418 break;
1419 }
1420#endif /* MPPE_SUPPORT */
1421#if DEFLATE_SUPPORT
1422 case CI_DEFLATE:
1423 case CI_DEFLATE_DRAFT:
1424 if (opt2 != NULL && opt2->deflate_size != opt->deflate_size)
1425 ppp_slprintf(result, sizeof(result), "Deflate%s (%d/%d)",
1426 (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""),
1427 opt->deflate_size, opt2->deflate_size);
1428 else
1429 ppp_slprintf(result, sizeof(result), "Deflate%s (%d)",
1430 (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""),
1431 opt->deflate_size);
1432 break;
1433#endif /* DEFLATE_SUPPORT */
1434#if BSDCOMPRESS_SUPPORT
1435 case CI_BSD_COMPRESS:
1436 if (opt2 != NULL && opt2->bsd_bits != opt->bsd_bits)
1437 ppp_slprintf(result, sizeof(result), "BSD-Compress (%d/%d)",
1438 opt->bsd_bits, opt2->bsd_bits);
1439 else
1440 ppp_slprintf(result, sizeof(result), "BSD-Compress (%d)",
1441 opt->bsd_bits);
1442 break;
1443#endif /* BSDCOMPRESS_SUPPORT */
1444#if PREDICTOR_SUPPORT
1445 case CI_PREDICTOR_1:
1446 return "Predictor 1";
1447 case CI_PREDICTOR_2:
1448 return "Predictor 2";
1449#endif /* PREDICTOR_SUPPORT */
1450 default:
1451 ppp_slprintf(result, sizeof(result), "Method %d", opt->method);
1452 }
1453 return result;
1454}
1455
1456/*
1457 * CCP has come up - inform the kernel driver and log a message.
1458 */
1459static void ccp_up(fsm *f) {
1460 ppp_pcb *pcb = f->pcb;
1461 ccp_options *go = &pcb->ccp_gotoptions;
1462 ccp_options *ho = &pcb->ccp_hisoptions;
1463 char method1[64];
1464
1465 ccp_set(pcb, 1, 1, go->method, ho->method);
1466 if (ccp_anycompress(go)) {
1467 if (ccp_anycompress(ho)) {
1468 if (go->method == ho->method) {
1469 ppp_notice("%s compression enabled", method_name(go, ho));
1470 } else {
1471 ppp_strlcpy(method1, method_name(go, NULL), sizeof(method1));
1472 ppp_notice("%s / %s compression enabled",
1473 method1, method_name(ho, NULL));
1474 }
1475 } else
1476 ppp_notice("%s receive compression enabled", method_name(go, NULL));
1477 } else if (ccp_anycompress(ho))
1478 ppp_notice("%s transmit compression enabled", method_name(ho, NULL));
1479#if MPPE_SUPPORT
1480 if (go->mppe) {
1481 continue_networks(pcb); /* Bring up IP et al */
1482 }
1483#endif /* MPPE_SUPPORT */
1484}
1485
1486/*
1487 * CCP has gone down - inform the kernel driver.
1488 */
1489static void ccp_down(fsm *f) {
1490 ppp_pcb *pcb = f->pcb;
1491#if MPPE_SUPPORT
1492 ccp_options *go = &pcb->ccp_gotoptions;
1493#endif /* MPPE_SUPPORT */
1494
1495 if (pcb->ccp_localstate & RACK_PENDING)
1496 UNTIMEOUT(ccp_rack_timeout, f);
1497 pcb->ccp_localstate = 0;
1498 ccp_set(pcb, 1, 0, 0, 0);
1499#if MPPE_SUPPORT
1500 if (go->mppe) {
1501 go->mppe = 0;
1502 if (pcb->lcp_fsm.state == PPP_FSM_OPENED) {
1503 /* If LCP is not already going down, make sure it does. */
1504 ppp_error("MPPE disabled");
1505 lcp_close(pcb, "MPPE disabled");
1506 }
1507 }
1508#endif /* MPPE_SUPPORT */
1509}
1510
1511#if PRINTPKT_SUPPORT
1512/*
1513 * Print the contents of a CCP packet.
1514 */
1515static const char* const ccp_codenames[] = {
1516 "ConfReq", "ConfAck", "ConfNak", "ConfRej",
1517 "TermReq", "TermAck", "CodeRej",
1518 NULL, NULL, NULL, NULL, NULL, NULL,
1519 "ResetReq", "ResetAck",
1520};
1521
1522static int ccp_printpkt(const u_char *p, int plen, void (*printer) (void *, const char *, ...), void *arg) {
1523 const u_char *p0, *optend;
1524 int code, id, len;
1525 int optlen;
1526
1527 p0 = p;
1528 if (plen < HEADERLEN)
1529 return 0;
1530 code = p[0];
1531 id = p[1];
1532 len = (p[2] << 8) + p[3];
1533 if (len < HEADERLEN || len > plen)
1534 return 0;
1535
1536 if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(ccp_codenames) && ccp_codenames[code-1] != NULL)
1537 printer(arg, " %s", ccp_codenames[code-1]);
1538 else
1539 printer(arg, " code=0x%x", code);
1540 printer(arg, " id=0x%x", id);
1541 len -= HEADERLEN;
1542 p += HEADERLEN;
1543
1544 switch (code) {
1545 case CONFREQ:
1546 case CONFACK:
1547 case CONFNAK:
1548 case CONFREJ:
1549 /* print list of possible compression methods */
1550 while (len >= 2) {
1551 code = p[0];
1552 optlen = p[1];
1553 if (optlen < 2 || optlen > len)
1554 break;
1555 printer(arg, " <");
1556 len -= optlen;
1557 optend = p + optlen;
1558 switch (code) {
1559#if MPPE_SUPPORT
1560 case CI_MPPE:
1561 if (optlen >= CILEN_MPPE) {
1562 u_char mppe_opts;
1563
1564 MPPE_CI_TO_OPTS(&p[2], mppe_opts);
1565 printer(arg, "mppe %s %s %s %s %s %s%s",
1566 (p[2] & MPPE_H_BIT)? "+H": "-H",
1567 (p[5] & MPPE_M_BIT)? "+M": "-M",
1568 (p[5] & MPPE_S_BIT)? "+S": "-S",
1569 (p[5] & MPPE_L_BIT)? "+L": "-L",
1570 (p[5] & MPPE_D_BIT)? "+D": "-D",
1571 (p[5] & MPPE_C_BIT)? "+C": "-C",
1572 (mppe_opts & MPPE_OPT_UNKNOWN)? " +U": "");
1573 if (mppe_opts & MPPE_OPT_UNKNOWN)
1574 printer(arg, " (%.2x %.2x %.2x %.2x)",
1575 p[2], p[3], p[4], p[5]);
1576 p += CILEN_MPPE;
1577 }
1578 break;
1579#endif /* MPPE_SUPPORT */
1580#if DEFLATE_SUPPORT
1581 case CI_DEFLATE:
1582 case CI_DEFLATE_DRAFT:
1583 if (optlen >= CILEN_DEFLATE) {
1584 printer(arg, "deflate%s %d",
1585 (code == CI_DEFLATE_DRAFT? "(old#)": ""),
1586 DEFLATE_SIZE(p[2]));
1587 if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL)
1588 printer(arg, " method %d", DEFLATE_METHOD(p[2]));
1589 if (p[3] != DEFLATE_CHK_SEQUENCE)
1590 printer(arg, " check %d", p[3]);
1591 p += CILEN_DEFLATE;
1592 }
1593 break;
1594#endif /* DEFLATE_SUPPORT */
1595#if BSDCOMPRESS_SUPPORT
1596 case CI_BSD_COMPRESS:
1597 if (optlen >= CILEN_BSD_COMPRESS) {
1598 printer(arg, "bsd v%d %d", BSD_VERSION(p[2]),
1599 BSD_NBITS(p[2]));
1600 p += CILEN_BSD_COMPRESS;
1601 }
1602 break;
1603#endif /* BSDCOMPRESS_SUPPORT */
1604#if PREDICTOR_SUPPORT
1605 case CI_PREDICTOR_1:
1606 if (optlen >= CILEN_PREDICTOR_1) {
1607 printer(arg, "predictor 1");
1608 p += CILEN_PREDICTOR_1;
1609 }
1610 break;
1611 case CI_PREDICTOR_2:
1612 if (optlen >= CILEN_PREDICTOR_2) {
1613 printer(arg, "predictor 2");
1614 p += CILEN_PREDICTOR_2;
1615 }
1616 break;
1617#endif /* PREDICTOR_SUPPORT */
1618 default:
1619 break;
1620 }
1621 while (p < optend)
1622 printer(arg, " %.2x", *p++);
1623 printer(arg, ">");
1624 }
1625 break;
1626
1627 case TERMACK:
1628 case TERMREQ:
1629 if (len > 0 && *p >= ' ' && *p < 0x7f) {
1630 ppp_print_string(p, len, printer, arg);
1631 p += len;
1632 len = 0;
1633 }
1634 break;
1635 default:
1636 break;
1637 }
1638
1639 /* dump out the rest of the packet in hex */
1640 while (--len >= 0)
1641 printer(arg, " %.2x", *p++);
1642
1643 return p - p0;
1644}
1645#endif /* PRINTPKT_SUPPORT */
1646
1647#if PPP_DATAINPUT
1648/*
1649 * We have received a packet that the decompressor failed to
1650 * decompress. Here we would expect to issue a reset-request, but
1651 * Motorola has a patent on resetting the compressor as a result of
1652 * detecting an error in the decompressed data after decompression.
1653 * (See US patent 5,130,993; international patent publication number
1654 * WO 91/10289; Australian patent 73296/91.)
1655 *
1656 * So we ask the kernel whether the error was detected after
1657 * decompression; if it was, we take CCP down, thus disabling
1658 * compression :-(, otherwise we issue the reset-request.
1659 */
1660static void ccp_datainput(ppp_pcb *pcb, u_char *pkt, int len) {
1661 fsm *f;
1662#if MPPE_SUPPORT
1663 ccp_options *go = &pcb->ccp_gotoptions;
1664#endif /* MPPE_SUPPORT */
1665 LWIP_UNUSED_ARG(pkt);
1666 LWIP_UNUSED_ARG(len);
1667
1668 f = &pcb->ccp_fsm;
1669 if (f->state == PPP_FSM_OPENED) {
1670 if (ccp_fatal_error(pcb)) {
1671 /*
1672 * Disable compression by taking CCP down.
1673 */
1674 ppp_error("Lost compression sync: disabling compression");
1675 ccp_close(pcb, "Lost compression sync");
1676#if MPPE_SUPPORT
1677 /*
1678 * If we were doing MPPE, we must also take the link down.
1679 */
1680 if (go->mppe) {
1681 ppp_error("Too many MPPE errors, closing LCP");
1682 lcp_close(pcb, "Too many MPPE errors");
1683 }
1684#endif /* MPPE_SUPPORT */
1685 } else {
1686 /*
1687 * Send a reset-request to reset the peer's compressor.
1688 * We don't do that if we are still waiting for an
1689 * acknowledgement to a previous reset-request.
1690 */
1691 if (!(pcb->ccp_localstate & RACK_PENDING)) {
1692 fsm_sdata(f, CCP_RESETREQ, f->reqid = ++f->id, NULL, 0);
1693 TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT);
1694 pcb->ccp_localstate |= RACK_PENDING;
1695 } else
1696 pcb->ccp_localstate |= RREQ_REPEAT;
1697 }
1698 }
1699}
1700#endif /* PPP_DATAINPUT */
1701
1702/*
1703 * We have received a packet that the decompressor failed to
1704 * decompress. Issue a reset-request.
1705 */
1706void ccp_resetrequest(ppp_pcb *pcb) {
1707 fsm *f = &pcb->ccp_fsm;
1708
1709 if (f->state != PPP_FSM_OPENED)
1710 return;
1711
1712 /*
1713 * Send a reset-request to reset the peer's compressor.
1714 * We don't do that if we are still waiting for an
1715 * acknowledgement to a previous reset-request.
1716 */
1717 if (!(pcb->ccp_localstate & RACK_PENDING)) {
1718 fsm_sdata(f, CCP_RESETREQ, f->reqid = ++f->id, NULL, 0);
1719 TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT);
1720 pcb->ccp_localstate |= RACK_PENDING;
1721 } else
1722 pcb->ccp_localstate |= RREQ_REPEAT;
1723}
1724
1725/*
1726 * Timeout waiting for reset-ack.
1727 */
1728static void ccp_rack_timeout(void *arg) {
1729 fsm *f = (fsm*)arg;
1730 ppp_pcb *pcb = f->pcb;
1731
1732 if (f->state == PPP_FSM_OPENED && (pcb->ccp_localstate & RREQ_REPEAT)) {
1733 fsm_sdata(f, CCP_RESETREQ, f->reqid, NULL, 0);
1734 TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT);
1735 pcb->ccp_localstate &= ~RREQ_REPEAT;
1736 } else
1737 pcb->ccp_localstate &= ~RACK_PENDING;
1738}
1739
1740#endif /* PPP_SUPPORT && CCP_SUPPORT */
Note: See TracBrowser for help on using the repository browser.