blob: af26573b558c02fb237d7547445f7f4ec60318e8 [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001/*
2 * ccp.c - PPP Compression Control Protocol.
3 *
4 * Copyright (c) 1994 The Australian National University.
5 * All rights reserved.
6 *
7 * Permission to use, copy, modify, and distribute this software and its
8 * documentation is hereby granted, provided that the above copyright
9 * notice appears in all copies. This software is provided without any
10 * warranty, express or implied. The Australian National University
11 * makes no representations about the suitability of this software for
12 * any purpose.
13 *
14 * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
15 * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
16 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
17 * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
18 * OF SUCH DAMAGE.
19 *
20 * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
21 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
22 * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
23 * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
24 * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
25 * OR MODIFICATIONS.
26 */
27
28#define RCSID "$Id: ccp.c,v 1.1 2008-08-04 06:11:51 winfred Exp $"
29
30#include <stdlib.h>
31#include <string.h>
32
33#include <pppd.h>
34#include "fsm.h"
35#include "ccp.h"
36#ifdef MPPE
37#include "mppe.h"
38#endif
39#include <net/ppp-comp.h>
40
41static const char rcsid[] = RCSID;
42
43/*
44 * Unfortunately there is a bug in zlib which means that using a
45 * size of 8 (window size = 256) for Deflate compression will cause
46 * buffer overruns and kernel crashes in the deflate module.
47 * Until this is fixed we only accept sizes in the range 9 .. 15.
48 * Thanks to James Carlson for pointing this out.
49 */
50#define DEFLATE_MIN_WORKS 9
51
52/*
53 * Command-line options.
54 */
55static int setbsdcomp __P((char **));
56static int setdeflate __P((char **));
57static char bsd_value[8];
58static char deflate_value[8];
59
60static option_t ccp_option_list[] = {
61 { "noccp", o_bool, &ccp_protent.enabled_flag,
62 "Disable CCP negotiation" },
63 { "-ccp", o_bool, &ccp_protent.enabled_flag,
64 "Disable CCP negotiation", OPT_ALIAS },
65
66 { "bsdcomp", o_special, (void *)setbsdcomp,
67 "Request BSD-Compress packet compression",
68 OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, bsd_value },
69 { "nobsdcomp", o_bool, &ccp_wantoptions[0].bsd_compress,
70 "don't allow BSD-Compress", OPT_PRIOSUB | OPT_A2CLR,
71 &ccp_allowoptions[0].bsd_compress },
72 { "-bsdcomp", o_bool, &ccp_wantoptions[0].bsd_compress,
73 "don't allow BSD-Compress", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR,
74 &ccp_allowoptions[0].bsd_compress },
75
76 { "deflate", o_special, (void *)setdeflate,
77 "request Deflate compression",
78 OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, deflate_value },
79 { "nodeflate", o_bool, &ccp_wantoptions[0].deflate,
80 "don't allow Deflate compression", OPT_PRIOSUB | OPT_A2CLR,
81 &ccp_allowoptions[0].deflate },
82 { "-deflate", o_bool, &ccp_wantoptions[0].deflate,
83 "don't allow Deflate compression", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR,
84 &ccp_allowoptions[0].deflate },
85
86 { "nodeflatedraft", o_bool, &ccp_wantoptions[0].deflate_draft,
87 "don't use draft deflate #", OPT_A2COPY,
88 &ccp_allowoptions[0].deflate_draft },
89
90 { "predictor1", o_bool, &ccp_wantoptions[0].predictor_1,
91 "request Predictor-1", 1, &ccp_allowoptions[0].predictor_1, OPT_PRIO },
92 { "nopredictor1", o_bool, &ccp_wantoptions[0].predictor_1,
93 "don't allow Predictor-1", OPT_PRIOSUB | OPT_A2CLR,
94 &ccp_allowoptions[0].predictor_1 },
95 { "-predictor1", o_bool, &ccp_wantoptions[0].predictor_1,
96 "don't allow Predictor-1", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR,
97 &ccp_allowoptions[0].predictor_1 },
98#ifdef MPPE
99 { "mppe-40", o_special_noarg, setmppe_40,
100 "Allow 40 bit MPPE encryption" },
101 { "+mppe-40", o_special_noarg, setmppe_40,
102 "Allow 40 bit MPPE encryption" },
103 { "nomppe-40", o_special_noarg, setnomppe_40,
104 "Disallow 40 bit MPPE encryption" },
105 { "-mppe-40", o_special_noarg, setnomppe_40,
106 "Disallow 40 bit MPPE encryption" },
107 { "mppe-128", o_special_noarg, setmppe_128,
108 "Allow 128 bit MPPE encryption" },
109 { "+mppe-128", o_special_noarg, setmppe_128,
110 "Allow 128 bit MPPE encryption" },
111 { "nomppe-128", o_special_noarg, setnomppe_128,
112 "Disallow 128 bit MPPE encryption" },
113 { "-mppe-128", o_special_noarg, setnomppe_128,
114 "Disallow 128 bit MPPE encryption" },
115 { "mppe-stateless", o_special_noarg, setmppe_stateless,
116 "Allow stateless MPPE encryption" },
117 { "+mppe-stateless", o_special_noarg, setmppe_stateless,
118 "Allow stateless MPPE encryption" },
119 { "nomppe-stateless", o_special_noarg, setnomppe_stateless,
120 "Disallow stateless MPPE encryption" },
121 { "-mppe-stateless", o_special_noarg, setnomppe_stateless,
122 "Disallow stateless MPPE encryption" },
123#endif
124
125 { NULL }
126};
127
128/*
129 * Protocol entry points from main code.
130 */
131static void ccp_init __P((int unit));
132static void ccp_open __P((int unit));
133static void ccp_close __P((int unit, char *));
134static void ccp_lowerup __P((int unit));
135static void ccp_lowerdown __P((int));
136static void ccp_input __P((int unit, u_char *pkt, int len));
137static void ccp_protrej __P((int unit));
138static int ccp_printpkt __P((u_char *pkt, int len,
139 void (*printer) __P((void *, char *, ...)),
140 void *arg));
141static void ccp_datainput __P((int unit, u_char *pkt, int len));
142
143struct protent ccp_protent = {
144 PPP_CCP,
145 ccp_init,
146 ccp_input,
147 ccp_protrej,
148 ccp_lowerup,
149 ccp_lowerdown,
150 ccp_open,
151 ccp_close,
152 ccp_printpkt,
153 ccp_datainput,
154 1,
155 "CCP",
156 "Compressed",
157 ccp_option_list,
158 NULL,
159 NULL,
160 NULL
161};
162
163fsm ccp_fsm[NUM_PPP];
164ccp_options ccp_wantoptions[NUM_PPP]; /* what to request the peer to use */
165ccp_options ccp_gotoptions[NUM_PPP]; /* what the peer agreed to do */
166ccp_options ccp_allowoptions[NUM_PPP]; /* what we'll agree to do */
167ccp_options ccp_hisoptions[NUM_PPP]; /* what we agreed to do */
168
169/*
170 * Callbacks for fsm code.
171 */
172static void ccp_resetci __P((fsm *));
173static int ccp_cilen __P((fsm *));
174static void ccp_addci __P((fsm *, u_char *, int *));
175static int ccp_ackci __P((fsm *, u_char *, int));
176static int ccp_nakci __P((fsm *, u_char *, int));
177static int ccp_rejci __P((fsm *, u_char *, int));
178static int ccp_reqci __P((fsm *, u_char *, int *, int));
179static void ccp_up __P((fsm *));
180static void ccp_down __P((fsm *));
181static int ccp_extcode __P((fsm *, int, int, u_char *, int));
182static void ccp_rack_timeout __P((void *));
183static char *method_name __P((ccp_options *, ccp_options *));
184
185static fsm_callbacks ccp_callbacks = {
186 ccp_resetci,
187 ccp_cilen,
188 ccp_addci,
189 ccp_ackci,
190 ccp_nakci,
191 ccp_rejci,
192 ccp_reqci,
193 ccp_up,
194 ccp_down,
195 NULL,
196 NULL,
197 NULL,
198 NULL,
199 ccp_extcode,
200 "CCP"
201};
202
203/*
204 * Do we want / did we get any compression?
205 */
206#define ANY_COMPRESS(opt) ((opt).deflate || (opt).bsd_compress \
207 || (opt).predictor_1 || (opt).predictor_2 \
208 || (opt).mppe )
209
210/*
211 * Local state (mainly for handling reset-reqs and reset-acks).
212 */
213static int ccp_localstate[NUM_PPP];
214#define RACK_PENDING 1 /* waiting for reset-ack */
215#define RREQ_REPEAT 2 /* send another reset-req if no reset-ack */
216
217#define RACKTIMEOUT 1 /* second */
218
219static int all_rejected[NUM_PPP]; /* we rejected all peer's options */
220
221/*
222 * Option parsing.
223 */
224static int
225setbsdcomp(argv)
226 char **argv;
227{
228 int rbits, abits;
229 char *str, *endp;
230
231 str = *argv;
232 abits = rbits = strtol(str, &endp, 0);
233 if (endp != str && *endp == ',') {
234 str = endp + 1;
235 abits = strtol(str, &endp, 0);
236 }
237 if (*endp != 0 || endp == str) {
238 option_error("invalid parameter '%s' for bsdcomp option", *argv);
239 return 0;
240 }
241 if ((rbits != 0 && (rbits < BSD_MIN_BITS || rbits > BSD_MAX_BITS))
242 || (abits != 0 && (abits < BSD_MIN_BITS || abits > BSD_MAX_BITS))) {
243 option_error("bsdcomp option values must be 0 or %d .. %d",
244 BSD_MIN_BITS, BSD_MAX_BITS);
245 return 0;
246 }
247 if (rbits > 0) {
248 ccp_wantoptions[0].bsd_compress = 1;
249 ccp_wantoptions[0].bsd_bits = rbits;
250 } else
251 ccp_wantoptions[0].bsd_compress = 0;
252 if (abits > 0) {
253 ccp_allowoptions[0].bsd_compress = 1;
254 ccp_allowoptions[0].bsd_bits = abits;
255 } else
256 ccp_allowoptions[0].bsd_compress = 0;
257 slprintf(bsd_value, sizeof(bsd_value),
258 rbits == abits? "%d": "%d,%d", rbits, abits);
259
260 return 1;
261}
262
263static int
264setdeflate(argv)
265 char **argv;
266{
267 int rbits, abits;
268 char *str, *endp;
269
270 str = *argv;
271 abits = rbits = strtol(str, &endp, 0);
272 if (endp != str && *endp == ',') {
273 str = endp + 1;
274 abits = strtol(str, &endp, 0);
275 }
276 if (*endp != 0 || endp == str) {
277 option_error("invalid parameter '%s' for deflate option", *argv);
278 return 0;
279 }
280 if ((rbits != 0 && (rbits < DEFLATE_MIN_SIZE || rbits > DEFLATE_MAX_SIZE))
281 || (abits != 0 && (abits < DEFLATE_MIN_SIZE
282 || abits > DEFLATE_MAX_SIZE))) {
283 option_error("deflate option values must be 0 or %d .. %d",
284 DEFLATE_MIN_SIZE, DEFLATE_MAX_SIZE);
285 return 0;
286 }
287 if (rbits == DEFLATE_MIN_SIZE || abits == DEFLATE_MIN_SIZE) {
288 if (rbits == DEFLATE_MIN_SIZE)
289 rbits = DEFLATE_MIN_WORKS;
290 if (abits == DEFLATE_MIN_SIZE)
291 abits = DEFLATE_MIN_WORKS;
292 warn("deflate option value of %d changed to %d to avoid zlib bug",
293 DEFLATE_MIN_SIZE, DEFLATE_MIN_WORKS);
294 }
295 if (rbits > 0) {
296 ccp_wantoptions[0].deflate = 1;
297 ccp_wantoptions[0].deflate_size = rbits;
298 } else
299 ccp_wantoptions[0].deflate = 0;
300 if (abits > 0) {
301 ccp_allowoptions[0].deflate = 1;
302 ccp_allowoptions[0].deflate_size = abits;
303 } else
304 ccp_allowoptions[0].deflate = 0;
305 slprintf(deflate_value, sizeof(deflate_value),
306 rbits == abits? "%d": "%d,%d", rbits, abits);
307
308 return 1;
309}
310
311/*
312 * ccp_init - initialize CCP.
313 */
314static void
315ccp_init(unit)
316 int unit;
317{
318 fsm *f = &ccp_fsm[unit];
319
320 f->unit = unit;
321 f->protocol = PPP_CCP;
322 f->callbacks = &ccp_callbacks;
323 fsm_init(f);
324
325 memset(&ccp_wantoptions[unit], 0, sizeof(ccp_options));
326 memset(&ccp_gotoptions[unit], 0, sizeof(ccp_options));
327 memset(&ccp_allowoptions[unit], 0, sizeof(ccp_options));
328 memset(&ccp_hisoptions[unit], 0, sizeof(ccp_options));
329
330 ccp_wantoptions[0].deflate = 1;
331 ccp_wantoptions[0].deflate_size = DEFLATE_MAX_SIZE;
332 ccp_wantoptions[0].deflate_correct = 1;
333 ccp_wantoptions[0].deflate_draft = 1;
334 ccp_allowoptions[0].deflate = 1;
335 ccp_allowoptions[0].deflate_size = DEFLATE_MAX_SIZE;
336 ccp_allowoptions[0].deflate_correct = 1;
337 ccp_allowoptions[0].deflate_draft = 1;
338
339 ccp_wantoptions[0].bsd_compress = 1;
340 ccp_wantoptions[0].bsd_bits = BSD_MAX_BITS;
341 ccp_allowoptions[0].bsd_compress = 1;
342 ccp_allowoptions[0].bsd_bits = BSD_MAX_BITS;
343
344 ccp_allowoptions[0].predictor_1 = 1;
345#ifdef MPPE
346 ccp_wantoptions[0].mppe = 0;
347 ccp_wantoptions[0].mppe_stateless = 0;
348 ccp_wantoptions[0].mppe_40 = 0;
349 ccp_wantoptions[0].mppe_128 = 0;
350 ccp_allowoptions[0].mppe_stateless = 1;
351 ccp_allowoptions[0].mppe = 1;
352 ccp_allowoptions[0].mppe_40 = 1;
353 ccp_allowoptions[0].mppe_128 = 1;
354#endif /* MPPE*/
355}
356
357/*
358 * ccp_open - CCP is allowed to come up.
359 */
360static void
361ccp_open(unit)
362 int unit;
363{
364 fsm *f = &ccp_fsm[unit];
365
366 if (f->state != OPENED)
367 ccp_flags_set(unit, 1, 0);
368
369 /*
370 * Find out which compressors the kernel supports before
371 * deciding whether to open in silent mode.
372 */
373 ccp_resetci(f);
374 if (!ANY_COMPRESS(ccp_gotoptions[unit]))
375 f->flags |= OPT_SILENT;
376
377 fsm_open(f);
378}
379
380/*
381 * ccp_close - Terminate CCP.
382 */
383static void
384ccp_close(unit, reason)
385 int unit;
386 char *reason;
387{
388 ccp_flags_set(unit, 0, 0);
389 fsm_close(&ccp_fsm[unit], reason);
390}
391
392/*
393 * ccp_lowerup - we may now transmit CCP packets.
394 */
395static void
396ccp_lowerup(unit)
397 int unit;
398{
399 fsm_lowerup(&ccp_fsm[unit]);
400}
401
402/*
403 * ccp_lowerdown - we may not transmit CCP packets.
404 */
405static void
406ccp_lowerdown(unit)
407 int unit;
408{
409 fsm_lowerdown(&ccp_fsm[unit]);
410}
411
412/*
413 * ccp_input - process a received CCP packet.
414 */
415static void
416ccp_input(unit, p, len)
417 int unit;
418 u_char *p;
419 int len;
420{
421 fsm *f = &ccp_fsm[unit];
422 int oldstate;
423
424 /*
425 * Check for a terminate-request so we can print a message.
426 */
427 oldstate = f->state;
428 fsm_input(f, p, len);
429 if (oldstate == OPENED && p[0] == TERMREQ && f->state != OPENED)
430 notice("Compression disabled by peer.");
431
432 /*
433 * If we get a terminate-ack and we're not asking for compression,
434 * close CCP.
435 */
436 if (oldstate == REQSENT && p[0] == TERMACK
437 && !ANY_COMPRESS(ccp_gotoptions[unit]))
438 ccp_close(unit, "No compression negotiated");
439}
440
441/*
442 * Handle a CCP-specific code.
443 */
444static int
445ccp_extcode(f, code, id, p, len)
446 fsm *f;
447 int code, id;
448 u_char *p;
449 int len;
450{
451 switch (code) {
452 case CCP_RESETREQ:
453 if (f->state != OPENED)
454 break;
455 /* send a reset-ack, which the transmitter will see and
456 reset its compression state. */
457 fsm_sdata(f, CCP_RESETACK, id, NULL, 0);
458 break;
459
460 case CCP_RESETACK:
461 if (ccp_localstate[f->unit] & RACK_PENDING && id == f->reqid) {
462 ccp_localstate[f->unit] &= ~(RACK_PENDING | RREQ_REPEAT);
463 UNTIMEOUT(ccp_rack_timeout, f);
464 }
465 break;
466
467 default:
468 return 0;
469 }
470
471 return 1;
472}
473
474/*
475 * ccp_protrej - peer doesn't talk CCP.
476 */
477static void
478ccp_protrej(unit)
479 int unit;
480{
481 ccp_flags_set(unit, 0, 0);
482 fsm_lowerdown(&ccp_fsm[unit]);
483}
484
485/*
486 * ccp_resetci - initialize at start of negotiation.
487 */
488static void
489ccp_resetci(f)
490 fsm *f;
491{
492 ccp_options *go = &ccp_gotoptions[f->unit];
493 u_char opt_buf[256];
494
495 *go = ccp_wantoptions[f->unit];
496 all_rejected[f->unit] = 0;
497
498 /*
499 * Check whether the kernel knows about the various
500 * compression methods we might request.
501 */
502 if (go->bsd_compress) {
503 opt_buf[0] = CI_BSD_COMPRESS;
504 opt_buf[1] = CILEN_BSD_COMPRESS;
505 opt_buf[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, BSD_MIN_BITS);
506 if (ccp_test(f->unit, opt_buf, CILEN_BSD_COMPRESS, 0) <= 0)
507 go->bsd_compress = 0;
508 }
509#ifdef MPPE
510 if (go->mppe) {
511 opt_buf[0] = CI_MPPE;
512 opt_buf[1] = CILEN_MPPE;
513 opt_buf[2] = 0;
514 /* keysize is 8 here */
515 BCOPY(mppe_master_send_key_40, opt_buf+3, 8);
516 BCOPY(mppe_master_recv_key_40, opt_buf+11, 8);
517 if (ccp_test(f->unit, opt_buf, (2*8)+3, 0) <= 0)
518 go->mppe = 0;
519 }
520#endif /*MPPE*/
521 if (go->deflate) {
522 if (go->deflate_correct) {
523 opt_buf[0] = CI_DEFLATE;
524 opt_buf[1] = CILEN_DEFLATE;
525 opt_buf[2] = DEFLATE_MAKE_OPT(DEFLATE_MIN_WORKS);
526 opt_buf[3] = DEFLATE_CHK_SEQUENCE;
527 if (ccp_test(f->unit, opt_buf, CILEN_DEFLATE, 0) <= 0)
528 go->deflate_correct = 0;
529 }
530 if (go->deflate_draft) {
531 opt_buf[0] = CI_DEFLATE_DRAFT;
532 opt_buf[1] = CILEN_DEFLATE;
533 opt_buf[2] = DEFLATE_MAKE_OPT(DEFLATE_MIN_WORKS);
534 opt_buf[3] = DEFLATE_CHK_SEQUENCE;
535 if (ccp_test(f->unit, opt_buf, CILEN_DEFLATE, 0) <= 0)
536 go->deflate_draft = 0;
537 }
538 if (!go->deflate_correct && !go->deflate_draft)
539 go->deflate = 0;
540 }
541 if (go->predictor_1) {
542 opt_buf[0] = CI_PREDICTOR_1;
543 opt_buf[1] = CILEN_PREDICTOR_1;
544 if (ccp_test(f->unit, opt_buf, CILEN_PREDICTOR_1, 0) <= 0)
545 go->predictor_1 = 0;
546 }
547 if (go->predictor_2) {
548 opt_buf[0] = CI_PREDICTOR_2;
549 opt_buf[1] = CILEN_PREDICTOR_2;
550 if (ccp_test(f->unit, opt_buf, CILEN_PREDICTOR_2, 0) <= 0)
551 go->predictor_2 = 0;
552 }
553}
554
555/*
556 * ccp_cilen - Return total length of our configuration info.
557 */
558static int
559ccp_cilen(f)
560 fsm *f;
561{
562 ccp_options *go = &ccp_gotoptions[f->unit];
563
564 return (go->bsd_compress? CILEN_BSD_COMPRESS: 0)
565 + (go->deflate? CILEN_DEFLATE: 0)
566 + (go->predictor_1? CILEN_PREDICTOR_1: 0)
567 + (go->predictor_2? CILEN_PREDICTOR_2: 0)
568 + (go->mppe? CILEN_MPPE: 0);
569}
570
571/*
572 * ccp_addci - put our requests in a packet.
573 */
574static void
575ccp_addci(f, p, lenp)
576 fsm *f;
577 u_char *p;
578 int *lenp;
579{
580 int res;
581 ccp_options *go = &ccp_gotoptions[f->unit];
582 u_char *p0 = p;
583
584 /*
585 * Add the compression types that we can receive, in decreasing
586 * preference order. Get the kernel to allocate the first one
587 * in case it gets Acked.
588 */
589 if (go->deflate) {
590 p[0] = go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT;
591 p[1] = CILEN_DEFLATE;
592 p[2] = DEFLATE_MAKE_OPT(go->deflate_size);
593 p[3] = DEFLATE_CHK_SEQUENCE;
594 for (;;) {
595 res = ccp_test(f->unit, p, CILEN_DEFLATE, 0);
596 if (res > 0) {
597 p += CILEN_DEFLATE;
598 break;
599 }
600 if (res < 0 || go->deflate_size <= DEFLATE_MIN_WORKS) {
601 go->deflate = 0;
602 break;
603 }
604 --go->deflate_size;
605 p[2] = DEFLATE_MAKE_OPT(go->deflate_size);
606 }
607 if (p != p0 && go->deflate_correct && go->deflate_draft) {
608 p[0] = CI_DEFLATE_DRAFT;
609 p[1] = CILEN_DEFLATE;
610 p[2] = p[2 - CILEN_DEFLATE];
611 p[3] = DEFLATE_CHK_SEQUENCE;
612 p += CILEN_DEFLATE;
613 }
614 }
615#ifdef MPPE
616 if (go->mppe) {
617 u_char opt_buf[64];
618 u_int keysize = 0;
619
620 if(!mppe_allowed)
621 go->mppe_stateless = go->mppe_40 = go->mppe_128 = 0;
622 p[0]=CI_MPPE;
623 p[1]=CILEN_MPPE;
624 p[2]=(go->mppe_stateless ? MPPE_STATELESS : 0);
625 p[3]=0;
626 p[4]=0;
627 p[5]=(go->mppe_40 ? MPPE_40BIT : 0) | (go->mppe_128 ? MPPE_128BIT : 0);
628 if(p[5] & MPPE_40BIT) {
629 keysize = 8;
630 BCOPY(mppe_master_send_key_40, opt_buf+3, keysize);
631 BCOPY(mppe_master_recv_key_40, opt_buf+11, keysize);
632 } else if(p[5] & MPPE_128BIT) {
633 keysize = 16;
634 BCOPY(mppe_master_send_key_128, opt_buf+3, keysize);
635 BCOPY(mppe_master_recv_key_128, opt_buf+19, keysize);
636 }
637 if(p[5] != 0) {
638 opt_buf[0]=CI_MPPE;
639 opt_buf[1]=CILEN_MPPE;
640 opt_buf[2] = (go->mppe_stateless) ? 1 : 0;
641 res = ccp_test(f->unit, opt_buf, (2*keysize)+3, 0);
642 } else {
643 res = -1;
644 }
645 if (res > 0) {
646 p += CILEN_MPPE;
647 }
648 }
649#endif /* MPPE*/
650 if (go->bsd_compress) {
651 p[0] = CI_BSD_COMPRESS;
652 p[1] = CILEN_BSD_COMPRESS;
653 p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits);
654 if (p != p0) {
655 p += CILEN_BSD_COMPRESS; /* not the first option */
656 } else {
657 for (;;) {
658 res = ccp_test(f->unit, p, CILEN_BSD_COMPRESS, 0);
659 if (res > 0) {
660 p += CILEN_BSD_COMPRESS;
661 break;
662 }
663 if (res < 0 || go->bsd_bits <= BSD_MIN_BITS) {
664 go->bsd_compress = 0;
665 break;
666 }
667 --go->bsd_bits;
668 p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits);
669 }
670 }
671 }
672 if (go->predictor_1) {
673 p[0] = CI_PREDICTOR_1;
674 p[1] = CILEN_PREDICTOR_1;
675 if (p == p0 && ccp_test(f->unit, p, CILEN_PREDICTOR_1, 0) <= 0) {
676 go->predictor_1 = 0;
677 } else {
678 p += CILEN_PREDICTOR_1;
679 }
680 }
681 if (go->predictor_2) {
682 p[0] = CI_PREDICTOR_2;
683 p[1] = CILEN_PREDICTOR_2;
684 if (p == p0 && ccp_test(f->unit, p, CILEN_PREDICTOR_2, 0) <= 0) {
685 go->predictor_2 = 0;
686 } else {
687 p += CILEN_PREDICTOR_2;
688 }
689 }
690
691 go->method = (p > p0)? p0[0]: -1;
692
693 *lenp = p - p0;
694}
695
696/*
697 * ccp_ackci - process a received configure-ack, and return
698 * 1 iff the packet was OK.
699 */
700static int
701ccp_ackci(f, p, len)
702 fsm *f;
703 u_char *p;
704 int len;
705{
706 ccp_options *go = &ccp_gotoptions[f->unit];
707 u_char *p0 = p;
708
709 if (go->deflate) {
710 if (len < CILEN_DEFLATE
711 || p[0] != (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT)
712 || p[1] != CILEN_DEFLATE
713 || p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
714 || p[3] != DEFLATE_CHK_SEQUENCE)
715 return 0;
716 p += CILEN_DEFLATE;
717 len -= CILEN_DEFLATE;
718 if (len == 0)
719 return 1;
720 if (go->deflate_correct && go->deflate_draft) {
721 if (len < CILEN_DEFLATE
722 || p[0] != CI_DEFLATE_DRAFT
723 || p[1] != CILEN_DEFLATE
724 || p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
725 || p[3] != DEFLATE_CHK_SEQUENCE)
726 return 0;
727 p += CILEN_DEFLATE;
728 len -= CILEN_DEFLATE;
729 }
730 }
731#ifdef MPPE
732 if (go->mppe) {
733 if ( len < CILEN_MPPE
734 || p[1] != CILEN_MPPE || p[0] != CI_MPPE
735 || p[2] != (go->mppe_stateless ? MPPE_STATELESS : 0)
736 || p[3] != 0
737 || p[4] != 0
738 || p[5] != ((go->mppe_40 ? MPPE_40BIT : 0) | (go->mppe_128 ? MPPE_128BIT : 0)))
739 return 0;
740 p += CILEN_MPPE;
741 len -= CILEN_MPPE;
742 /* Cope with first/fast ack */
743 if (len == 0)
744 return 1;
745 }
746#endif /* MPPE */
747 if (go->bsd_compress) {
748 if (len < CILEN_BSD_COMPRESS
749 || p[0] != CI_BSD_COMPRESS || p[1] != CILEN_BSD_COMPRESS
750 || p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits))
751 return 0;
752 p += CILEN_BSD_COMPRESS;
753 len -= CILEN_BSD_COMPRESS;
754 if (p == p0 && len == 0)
755 return 1;
756 }
757 if (go->predictor_1) {
758 if (len < CILEN_PREDICTOR_1
759 || p[0] != CI_PREDICTOR_1 || p[1] != CILEN_PREDICTOR_1)
760 return 0;
761 p += CILEN_PREDICTOR_1;
762 len -= CILEN_PREDICTOR_1;
763 if (p == p0 && len == 0)
764 return 1;
765 }
766 if (go->predictor_2) {
767 if (len < CILEN_PREDICTOR_2
768 || p[0] != CI_PREDICTOR_2 || p[1] != CILEN_PREDICTOR_2)
769 return 0;
770 p += CILEN_PREDICTOR_2;
771 len -= CILEN_PREDICTOR_2;
772 if (p == p0 && len == 0)
773 return 1;
774 }
775
776 if (len != 0)
777 return 0;
778 return 1;
779}
780
781/*
782 * ccp_nakci - process received configure-nak.
783 * Returns 1 iff the nak was OK.
784 */
785static int
786ccp_nakci(f, p, len)
787 fsm *f;
788 u_char *p;
789 int len;
790{
791 ccp_options *go = &ccp_gotoptions[f->unit];
792 ccp_options no; /* options we've seen already */
793 ccp_options try; /* options to ask for next time */
794
795 memset(&no, 0, sizeof(no));
796 try = *go;
797
798 if (go->deflate && len >= CILEN_DEFLATE
799 && p[0] == (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT)
800 && p[1] == CILEN_DEFLATE) {
801 no.deflate = 1;
802 /*
803 * Peer wants us to use a different code size or something.
804 * Stop asking for Deflate if we don't understand his suggestion.
805 */
806 if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL
807 || DEFLATE_SIZE(p[2]) < DEFLATE_MIN_WORKS
808 || p[3] != DEFLATE_CHK_SEQUENCE)
809 try.deflate = 0;
810 else if (DEFLATE_SIZE(p[2]) < go->deflate_size)
811 try.deflate_size = DEFLATE_SIZE(p[2]);
812 p += CILEN_DEFLATE;
813 len -= CILEN_DEFLATE;
814 if (go->deflate_correct && go->deflate_draft
815 && len >= CILEN_DEFLATE && p[0] == CI_DEFLATE_DRAFT
816 && p[1] == CILEN_DEFLATE) {
817 p += CILEN_DEFLATE;
818 len -= CILEN_DEFLATE;
819 }
820 }
821
822#ifdef MPPE
823 if (len >= CILEN_MPPE && p[0] == CI_MPPE && p[1] == CILEN_MPPE) {
824 no.mppe = 1;
825 if((p[5] & MPPE_128BIT) == 0)
826 try.mppe_128 = 0;
827 if((p[5] & MPPE_40BIT) == 0)
828 try.mppe_40 = 0;
829 if((p[2] & MPPE_STATELESS) == 0)
830 try.mppe_stateless = 0;
831 if(!try.mppe_128 && !try.mppe_40) {
832 no.mppe = 0;
833 try.mppe = 0;
834 }
835 p += CILEN_MPPE;
836 len -= CILEN_MPPE;
837 }
838#endif /* MPPE */
839
840 if (go->bsd_compress && len >= CILEN_BSD_COMPRESS
841 && p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) {
842 no.bsd_compress = 1;
843 /*
844 * Peer wants us to use a different number of bits
845 * or a different version.
846 */
847 if (BSD_VERSION(p[2]) != BSD_CURRENT_VERSION)
848 try.bsd_compress = 0;
849 else if (BSD_NBITS(p[2]) < go->bsd_bits)
850 try.bsd_bits = BSD_NBITS(p[2]);
851 p += CILEN_BSD_COMPRESS;
852 len -= CILEN_BSD_COMPRESS;
853 }
854
855 /*
856 * Predictor-1 and 2 have no options, so they can't be Naked.
857 *
858 * There may be remaining options but we ignore them.
859 */
860
861 if (f->state != OPENED)
862 *go = try;
863 return 1;
864}
865
866/*
867 * ccp_rejci - reject some of our suggested compression methods.
868 */
869static int
870ccp_rejci(f, p, len)
871 fsm *f;
872 u_char *p;
873 int len;
874{
875 ccp_options *go = &ccp_gotoptions[f->unit];
876 ccp_options try; /* options to request next time */
877
878 try = *go;
879
880 /*
881 * Cope with empty configure-rejects by ceasing to send
882 * configure-requests.
883 */
884 if (len == 0 && all_rejected[f->unit])
885 return -1;
886
887 if (go->deflate && len >= CILEN_DEFLATE
888 && p[0] == (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT)
889 && p[1] == CILEN_DEFLATE) {
890 if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
891 || p[3] != DEFLATE_CHK_SEQUENCE)
892 return 0; /* Rej is bad */
893 if (go->deflate_correct)
894 try.deflate_correct = 0;
895 else
896 try.deflate_draft = 0;
897 p += CILEN_DEFLATE;
898 len -= CILEN_DEFLATE;
899 if (go->deflate_correct && go->deflate_draft
900 && len >= CILEN_DEFLATE && p[0] == CI_DEFLATE_DRAFT
901 && p[1] == CILEN_DEFLATE) {
902 if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
903 || p[3] != DEFLATE_CHK_SEQUENCE)
904 return 0; /* Rej is bad */
905 try.deflate_draft = 0;
906 p += CILEN_DEFLATE;
907 len -= CILEN_DEFLATE;
908 }
909 if (!try.deflate_correct && !try.deflate_draft)
910 try.deflate = 0;
911 }
912#ifdef MPPE
913 if (go->mppe && len >= CILEN_MPPE
914 && p[0] == CI_MPPE && p[1] == CILEN_MPPE) {
915 try.mppe = 0;
916 p += CILEN_MPPE;
917 len -= CILEN_MPPE;
918 }
919#endif /*MPPE*/
920 if (go->bsd_compress && len >= CILEN_BSD_COMPRESS
921 && p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) {
922 if (p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits))
923 return 0;
924 try.bsd_compress = 0;
925 p += CILEN_BSD_COMPRESS;
926 len -= CILEN_BSD_COMPRESS;
927 }
928 if (go->predictor_1 && len >= CILEN_PREDICTOR_1
929 && p[0] == CI_PREDICTOR_1 && p[1] == CILEN_PREDICTOR_1) {
930 try.predictor_1 = 0;
931 p += CILEN_PREDICTOR_1;
932 len -= CILEN_PREDICTOR_1;
933 }
934 if (go->predictor_2 && len >= CILEN_PREDICTOR_2
935 && p[0] == CI_PREDICTOR_2 && p[1] == CILEN_PREDICTOR_2) {
936 try.predictor_2 = 0;
937 p += CILEN_PREDICTOR_2;
938 len -= CILEN_PREDICTOR_2;
939 }
940
941 if (len != 0)
942 return 0;
943
944 if (f->state != OPENED)
945 *go = try;
946
947 return 1;
948}
949
950/*
951 * ccp_reqci - processed a received configure-request.
952 * Returns CONFACK, CONFNAK or CONFREJ and the packet modified
953 * appropriately.
954 */
955static int
956ccp_reqci(f, p, lenp, dont_nak)
957 fsm *f;
958 u_char *p;
959 int *lenp;
960 int dont_nak;
961{
962 int ret, newret, res;
963 u_char *p0, *retp;
964 int len, clen, type, nb;
965 ccp_options *ho = &ccp_hisoptions[f->unit];
966 ccp_options *ao = &ccp_allowoptions[f->unit];
967
968 ret = CONFACK;
969 retp = p0 = p;
970 len = *lenp;
971
972 memset(ho, 0, sizeof(ccp_options));
973 ho->method = (len > 0)? p[0]: -1;
974
975 while (len > 0) {
976 newret = CONFACK;
977 if (len < 2 || p[1] < 2 || p[1] > len) {
978 /* length is bad */
979 clen = len;
980 newret = CONFREJ;
981
982 } else {
983 type = p[0];
984 clen = p[1];
985
986 switch (type) {
987 case CI_DEFLATE:
988 case CI_DEFLATE_DRAFT:
989 if (!ao->deflate || clen != CILEN_DEFLATE
990 || (!ao->deflate_correct && type == CI_DEFLATE)
991 || (!ao->deflate_draft && type == CI_DEFLATE_DRAFT)) {
992 newret = CONFREJ;
993 break;
994 }
995
996 ho->deflate = 1;
997 ho->deflate_size = nb = DEFLATE_SIZE(p[2]);
998 if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL
999 || p[3] != DEFLATE_CHK_SEQUENCE
1000 || nb > ao->deflate_size || nb < DEFLATE_MIN_WORKS) {
1001 newret = CONFNAK;
1002 if (!dont_nak) {
1003 p[2] = DEFLATE_MAKE_OPT(ao->deflate_size);
1004 p[3] = DEFLATE_CHK_SEQUENCE;
1005 /* fall through to test this #bits below */
1006 } else
1007 break;
1008 }
1009
1010 /*
1011 * Check whether we can do Deflate with the window
1012 * size they want. If the window is too big, reduce
1013 * it until the kernel can cope and nak with that.
1014 * We only check this for the first option.
1015 */
1016 if (p == p0) {
1017 for (;;) {
1018 res = ccp_test(f->unit, p, CILEN_DEFLATE, 1);
1019 if (res > 0)
1020 break; /* it's OK now */
1021 if (res < 0 || nb == DEFLATE_MIN_WORKS || dont_nak) {
1022 newret = CONFREJ;
1023 p[2] = DEFLATE_MAKE_OPT(ho->deflate_size);
1024 break;
1025 }
1026 newret = CONFNAK;
1027 --nb;
1028 p[2] = DEFLATE_MAKE_OPT(nb);
1029 }
1030 }
1031 break;
1032
1033#ifdef MPPE
1034 case CI_MPPE:
1035 if (!ao->mppe || clen != CILEN_MPPE) {
1036 newret = CONFREJ;
1037 break;
1038 }
1039 if(!mppe_allowed)
1040 {
1041 newret = CONFREJ;
1042 break;
1043 }
1044 ho->mppe = 1;
1045 if((p[5]&(MPPE_40BIT|MPPE_128BIT)) == (MPPE_40BIT|MPPE_128BIT))
1046 {
1047 /* if both are available, select the stronger */
1048 p[5] &= ~MPPE_40BIT;
1049 newret = CONFNAK;
1050 }
1051 if((p[2] & ~MPPE_STATELESS) != 0
1052 || p[3] != 0
1053 || p[4] != 0
1054 || (p[5] & ~(MPPE_40BIT | MPPE_128BIT)) != 0)
1055 {
1056 ccp_options *wo = &ccp_wantoptions[f->unit];
1057 /* not sure what they want, tell 'em what we got */
1058 p[2] &= MPPE_STATELESS;
1059 p[3] &= 0;
1060 p[4] &= 0;
1061 p[5] &= MPPE_40BIT | MPPE_128BIT;
1062 if(wo->mppe_40)
1063 p[5] |= MPPE_40BIT;
1064 if(wo->mppe_128)
1065 p[5] |= MPPE_128BIT;
1066 newret = CONFNAK;
1067 }
1068
1069 if((newret == CONFACK) || (newret == CONFNAK))
1070 {
1071 /*
1072 * The kernel ppp driver needs the session key
1073 * which is not sent via CCP :(
1074 */
1075 unsigned int keysize;
1076 unsigned char opt_buf[64];
1077 opt_buf[0] = CI_MPPE;
1078 opt_buf[1] = CILEN_MPPE;
1079 if(p[2] & MPPE_STATELESS) {
1080 ho->mppe_stateless=1;
1081 opt_buf[2] = MPPE_STATELESS;
1082 }
1083 /* push in our send/receive keys */
1084 if(p[5] & MPPE_40BIT) {
1085 ho->mppe_40 = 1;
1086 keysize = 8;
1087 BCOPY(mppe_master_send_key_40, opt_buf+3, keysize);
1088 BCOPY(mppe_master_recv_key_40, opt_buf+11, keysize);
1089 } else if(p[5] & MPPE_128BIT) {
1090 ho->mppe_128 = 1;
1091 keysize = 16;
1092 BCOPY(mppe_master_send_key_128, opt_buf+3, keysize);
1093 BCOPY(mppe_master_recv_key_128, opt_buf+19, keysize);
1094 } else {
1095 ho->mppe = 0;
1096 newret = CONFREJ;
1097 break;
1098 }
1099 /* call ioctl and pass this nasty stuff to the kernel */
1100 if (ccp_test(f->unit, opt_buf, (2*keysize)+3, 1) <= 0){
1101 ho->mppe = 0;
1102 newret = CONFREJ;
1103 break;
1104 }
1105 }
1106 break;
1107#endif /* MPPE */
1108
1109 case CI_BSD_COMPRESS:
1110 if (!ao->bsd_compress || clen != CILEN_BSD_COMPRESS) {
1111 newret = CONFREJ;
1112 break;
1113 }
1114
1115 ho->bsd_compress = 1;
1116 ho->bsd_bits = nb = BSD_NBITS(p[2]);
1117 if (BSD_VERSION(p[2]) != BSD_CURRENT_VERSION
1118 || nb > ao->bsd_bits || nb < BSD_MIN_BITS) {
1119 newret = CONFNAK;
1120 if (!dont_nak) {
1121 p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, ao->bsd_bits);
1122 /* fall through to test this #bits below */
1123 } else
1124 break;
1125 }
1126
1127 /*
1128 * Check whether we can do BSD-Compress with the code
1129 * size they want. If the code size is too big, reduce
1130 * it until the kernel can cope and nak with that.
1131 * We only check this for the first option.
1132 */
1133 if (p == p0) {
1134 for (;;) {
1135 res = ccp_test(f->unit, p, CILEN_BSD_COMPRESS, 1);
1136 if (res > 0)
1137 break;
1138 if (res < 0 || nb == BSD_MIN_BITS || dont_nak) {
1139 newret = CONFREJ;
1140 p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION,
1141 ho->bsd_bits);
1142 break;
1143 }
1144 newret = CONFNAK;
1145 --nb;
1146 p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, nb);
1147 }
1148 }
1149 break;
1150
1151 case CI_PREDICTOR_1:
1152 if (!ao->predictor_1 || clen != CILEN_PREDICTOR_1) {
1153 newret = CONFREJ;
1154 break;
1155 }
1156
1157 ho->predictor_1 = 1;
1158 if (p == p0
1159 && ccp_test(f->unit, p, CILEN_PREDICTOR_1, 1) <= 0) {
1160 newret = CONFREJ;
1161 }
1162 break;
1163
1164 case CI_PREDICTOR_2:
1165 if (!ao->predictor_2 || clen != CILEN_PREDICTOR_2) {
1166 newret = CONFREJ;
1167 break;
1168 }
1169
1170 ho->predictor_2 = 1;
1171 if (p == p0
1172 && ccp_test(f->unit, p, CILEN_PREDICTOR_2, 1) <= 0) {
1173 newret = CONFREJ;
1174 }
1175 break;
1176
1177 default:
1178 newret = CONFREJ;
1179 }
1180 }
1181
1182 if (newret == CONFNAK && dont_nak)
1183 newret = CONFREJ;
1184 if (!(newret == CONFACK || (newret == CONFNAK && ret == CONFREJ))) {
1185 /* we're returning this option */
1186 if (newret == CONFREJ && ret == CONFNAK)
1187 retp = p0;
1188 ret = newret;
1189 if (p != retp)
1190 BCOPY(p, retp, clen);
1191 retp += clen;
1192 }
1193
1194 p += clen;
1195 len -= clen;
1196 }
1197
1198 if (ret != CONFACK) {
1199 if (ret == CONFREJ && *lenp == retp - p0)
1200 all_rejected[f->unit] = 1;
1201 else
1202 *lenp = retp - p0;
1203 }
1204 return ret;
1205}
1206
1207/*
1208 * Make a string name for a compression method (or 2).
1209 */
1210static char *
1211method_name(opt, opt2)
1212 ccp_options *opt, *opt2;
1213{
1214 static char result[64];
1215
1216 if (!ANY_COMPRESS(*opt))
1217 return "(none)";
1218 switch (opt->method) {
1219 case CI_DEFLATE:
1220 case CI_DEFLATE_DRAFT:
1221 if (opt2 != NULL && opt2->deflate_size != opt->deflate_size)
1222 slprintf(result, sizeof(result), "Deflate%s (%d/%d)",
1223 (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""),
1224 opt->deflate_size, opt2->deflate_size);
1225 else
1226 slprintf(result, sizeof(result), "Deflate%s (%d)",
1227 (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""),
1228 opt->deflate_size);
1229 break;
1230#ifdef MPPE
1231 case CI_MPPE:
1232 if (opt->mppe_40) {
1233 if (opt->mppe_stateless) {
1234 return "MPPE 40 bit, stateless";
1235 } else {
1236 return "MPPE 40 bit, non-stateless";
1237 }
1238 } else if (opt->mppe_128) {
1239 if (opt->mppe_stateless) {
1240 return "MPPE 128 bit, stateless";
1241 } else {
1242 return "MPPE 128 bit, non-stateless";
1243 }
1244 } else {
1245 if (opt->mppe_stateless) {
1246 return "MPPE unknown strength, stateless";
1247 } else {
1248 return "MPPE unknown strength, stateless";
1249 }
1250 }
1251#endif
1252 case CI_LZS:
1253 return "Stac LZS";
1254 case CI_BSD_COMPRESS:
1255 if (opt2 != NULL && opt2->bsd_bits != opt->bsd_bits)
1256 slprintf(result, sizeof(result), "BSD-Compress (%d/%d)",
1257 opt->bsd_bits, opt2->bsd_bits);
1258 else
1259 slprintf(result, sizeof(result), "BSD-Compress (%d)",
1260 opt->bsd_bits);
1261 break;
1262 case CI_PREDICTOR_1:
1263 return "Predictor 1";
1264 case CI_PREDICTOR_2:
1265 return "Predictor 2";
1266 default:
1267 slprintf(result, sizeof(result), "Method %d", opt->method);
1268 }
1269 return result;
1270}
1271
1272/*
1273 * CCP has come up - inform the kernel driver and log a message.
1274 */
1275static void
1276ccp_up(f)
1277 fsm *f;
1278{
1279 ccp_options *go = &ccp_gotoptions[f->unit];
1280 ccp_options *ho = &ccp_hisoptions[f->unit];
1281 char method1[64];
1282
1283 ccp_flags_set(f->unit, 1, 1);
1284 if (ANY_COMPRESS(*go)) {
1285 if (ANY_COMPRESS(*ho)) {
1286 if (go->method == ho->method) {
1287 notice("%s compression enabled", method_name(go, ho));
1288 } else {
1289 strlcpy(method1, method_name(go, NULL), sizeof(method1));
1290 notice("%s / %s compression enabled",
1291 method1, method_name(ho, NULL));
1292 }
1293 } else
1294 notice("%s receive compression enabled", method_name(go, NULL));
1295 } else if (ANY_COMPRESS(*ho))
1296 notice("%s transmit compression enabled", method_name(ho, NULL));
1297}
1298
1299/*
1300 * CCP has gone down - inform the kernel driver.
1301 */
1302static void
1303ccp_down(f)
1304 fsm *f;
1305{
1306 if (ccp_localstate[f->unit] & RACK_PENDING)
1307 UNTIMEOUT(ccp_rack_timeout, f);
1308 ccp_localstate[f->unit] = 0;
1309 ccp_flags_set(f->unit, 1, 0);
1310}
1311
1312/*
1313 * Print the contents of a CCP packet.
1314 */
1315static char *ccp_codenames[] = {
1316 "ConfReq", "ConfAck", "ConfNak", "ConfRej",
1317 "TermReq", "TermAck", "CodeRej",
1318 NULL, NULL, NULL, NULL, NULL, NULL,
1319 "ResetReq", "ResetAck",
1320};
1321
1322static int
1323ccp_printpkt(p, plen, printer, arg)
1324 u_char *p;
1325 int plen;
1326 void (*printer) __P((void *, char *, ...));
1327 void *arg;
1328{
1329 u_char *p0, *optend;
1330 int code, id, len;
1331 int optlen;
1332
1333 p0 = p;
1334 if (plen < HEADERLEN)
1335 return 0;
1336 code = p[0];
1337 id = p[1];
1338 len = (p[2] << 8) + p[3];
1339 if (len < HEADERLEN || len > plen)
1340 return 0;
1341
1342 if (code >= 1 && code <= sizeof(ccp_codenames) / sizeof(char *)
1343 && ccp_codenames[code-1] != NULL)
1344 printer(arg, " %s", ccp_codenames[code-1]);
1345 else
1346 printer(arg, " code=0x%x", code);
1347 printer(arg, " id=0x%x", id);
1348 len -= HEADERLEN;
1349 p += HEADERLEN;
1350
1351 switch (code) {
1352 case CONFREQ:
1353 case CONFACK:
1354 case CONFNAK:
1355 case CONFREJ:
1356 /* print list of possible compression methods */
1357 while (len >= 2) {
1358 code = p[0];
1359 optlen = p[1];
1360 if (optlen < 2 || optlen > len)
1361 break;
1362 printer(arg, " <");
1363 len -= optlen;
1364 optend = p + optlen;
1365 switch (code) {
1366 case CI_DEFLATE:
1367 case CI_DEFLATE_DRAFT:
1368 if (optlen >= CILEN_DEFLATE) {
1369 printer(arg, "deflate%s %d",
1370 (code == CI_DEFLATE_DRAFT? "(old#)": ""),
1371 DEFLATE_SIZE(p[2]));
1372 if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL)
1373 printer(arg, " method %d", DEFLATE_METHOD(p[2]));
1374 if (p[3] != DEFLATE_CHK_SEQUENCE)
1375 printer(arg, " check %d", p[3]);
1376 p += CILEN_DEFLATE;
1377 }
1378 break;
1379 case CI_BSD_COMPRESS:
1380 if (optlen >= CILEN_BSD_COMPRESS) {
1381 printer(arg, "bsd v%d %d", BSD_VERSION(p[2]),
1382 BSD_NBITS(p[2]));
1383 p += CILEN_BSD_COMPRESS;
1384 }
1385 break;
1386 case CI_PREDICTOR_1:
1387 if (optlen >= CILEN_PREDICTOR_1) {
1388 printer(arg, "predictor 1");
1389 p += CILEN_PREDICTOR_1;
1390 }
1391 break;
1392 case CI_MPPE:
1393 if (optlen >= CILEN_MPPE) {
1394 printer(arg, "mppe %x %x %x %x",p[2],p[3],p[4],p[5]);
1395 p += CILEN_MPPE;
1396 }
1397 break;
1398 case CI_LZS:
1399 if (optlen >= CILEN_LZS) {
1400 printer(arg, "lzs %x %x %x", p[2], p[3], p[4]);
1401 p += CILEN_LZS;
1402 }
1403 break;
1404 case CI_PREDICTOR_2:
1405 if (optlen >= CILEN_PREDICTOR_2) {
1406 printer(arg, "predictor 2");
1407 p += CILEN_PREDICTOR_2;
1408 }
1409 break;
1410 }
1411 while (p < optend)
1412 printer(arg, " %.2x", *p++);
1413 printer(arg, ">");
1414 }
1415 break;
1416
1417 case TERMACK:
1418 case TERMREQ:
1419 if (len > 0 && *p >= ' ' && *p < 0x7f) {
1420 print_string((char *)p, len, printer, arg);
1421 p += len;
1422 len = 0;
1423 }
1424 break;
1425 }
1426
1427 /* dump out the rest of the packet in hex */
1428 while (--len >= 0)
1429 printer(arg, " %.2x", *p++);
1430
1431 return p - p0;
1432}
1433
1434/*
1435 * We have received a packet that the decompressor failed to
1436 * decompress. Here we would expect to issue a reset-request, but
1437 * Motorola has a patent on resetting the compressor as a result of
1438 * detecting an error in the decompressed data after decompression.
1439 * (See US patent 5,130,993; international patent publication number
1440 * WO 91/10289; Australian patent 73296/91.)
1441 *
1442 * So we ask the kernel whether the error was detected after
1443 * decompression; if it was, we take CCP down, thus disabling
1444 * compression :-(, otherwise we issue the reset-request.
1445 */
1446static void
1447ccp_datainput(unit, pkt, len)
1448 int unit;
1449 u_char *pkt;
1450 int len;
1451{
1452 fsm *f;
1453
1454 f = &ccp_fsm[unit];
1455 if (f->state == OPENED) {
1456 if (ccp_fatal_error(unit)) {
1457 /*
1458 * Disable compression by taking CCP down.
1459 */
1460 error("Lost compression sync: disabling compression");
1461 ccp_close(unit, "Lost compression sync");
1462 } else {
1463 /* MPPE/MPPC does not requires CCP_RESETREQ */
1464 if (ccp_gotoptions[f->unit].method == CI_MPPE)
1465 return;
1466 /*
1467 * Send a reset-request to reset the peer's compressor.
1468 * We don't do that if we are still waiting for an
1469 * acknowledgement to a previous reset-request.
1470 */
1471 if (!(ccp_localstate[f->unit] & RACK_PENDING)) {
1472 fsm_sdata(f, CCP_RESETREQ, f->reqid = ++f->id, NULL, 0);
1473 TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT);
1474 ccp_localstate[f->unit] |= RACK_PENDING;
1475 } else
1476 ccp_localstate[f->unit] |= RREQ_REPEAT;
1477 }
1478 }
1479}
1480
1481/*
1482 * Timeout waiting for reset-ack.
1483 */
1484static void
1485ccp_rack_timeout(arg)
1486 void *arg;
1487{
1488 fsm *f = arg;
1489
1490 if (f->state == OPENED && ccp_localstate[f->unit] & RREQ_REPEAT) {
1491 fsm_sdata(f, CCP_RESETREQ, f->reqid, NULL, 0);
1492 TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT);
1493 ccp_localstate[f->unit] &= ~RREQ_REPEAT;
1494 } else
1495 ccp_localstate[f->unit] &= ~RACK_PENDING;
1496}
1497