2 * ccp.c - PPP Compression Control Protocol.
4 * Copyright (c) 2000 by Sun Microsystems, Inc.
7 * Copyright (c) 1994 The Australian National University.
10 * Permission to use, copy, modify, and distribute this software and its
11 * documentation is hereby granted, provided that the above copyright
12 * notice appears in all copies. This software is provided without any
13 * warranty, express or implied. The Australian National University
14 * makes no representations about the suitability of this software for
17 * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
18 * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
19 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
20 * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
23 * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
24 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
25 * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
26 * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
27 * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
31 * Copyright (c) 2016 by Delphix. All rights reserved.
40 #include <net/ppp-comp.h>
43 * Command-line options.
45 static int setbsdcomp
__P((char **, option_t
*));
46 static int setdeflate
__P((char **, option_t
*));
48 static option_t ccp_option_list
[] = {
49 { "noccp", o_bool
, &ccp_protent
.enabled_flag
,
50 "Disable CCP negotiation" },
51 { "-ccp", o_bool
, &ccp_protent
.enabled_flag
,
52 "Disable CCP negotiation" },
53 { "bsdcomp", o_special
, (void *)setbsdcomp
,
54 "Request BSD-Compress packet compression" },
55 { "nobsdcomp", o_bool
, &ccp_wantoptions
[0].bsd_compress
,
56 "don't allow BSD-Compress", OPT_A2COPY
,
57 &ccp_allowoptions
[0].bsd_compress
},
58 { "-bsdcomp", o_bool
, &ccp_wantoptions
[0].bsd_compress
,
59 "don't allow BSD-Compress", OPT_A2COPY
,
60 &ccp_allowoptions
[0].bsd_compress
},
61 { "deflate", o_special
, (void *)setdeflate
,
62 "request Deflate compression" },
63 { "nodeflate", o_bool
, &ccp_wantoptions
[0].deflate
,
64 "don't allow Deflate compression", OPT_A2COPY
,
65 &ccp_allowoptions
[0].deflate
},
66 { "-deflate", o_bool
, &ccp_wantoptions
[0].deflate
,
67 "don't allow Deflate compression", OPT_A2COPY
,
68 &ccp_allowoptions
[0].deflate
},
69 { "nodeflatedraft", o_bool
, &ccp_wantoptions
[0].deflate_draft
,
70 "don't use draft deflate #", OPT_A2COPY
,
71 &ccp_allowoptions
[0].deflate_draft
},
72 { "predictor1", o_bool
, &ccp_wantoptions
[0].predictor_1
,
73 "request Predictor-1", 1, &ccp_allowoptions
[0].predictor_1
},
74 { "nopredictor1", o_bool
, &ccp_wantoptions
[0].predictor_1
,
75 "don't allow Predictor-1", OPT_A2COPY
,
76 &ccp_allowoptions
[0].predictor_1
},
77 { "-predictor1", o_bool
, &ccp_wantoptions
[0].predictor_1
,
78 "don't allow Predictor-1", OPT_A2COPY
,
79 &ccp_allowoptions
[0].predictor_1
},
85 * Protocol entry points from main code.
87 static void ccp_init
__P((int unit
));
88 static void ccp_open
__P((int unit
));
89 static void ccp_close
__P((int unit
, char *));
90 static void ccp_lowerup
__P((int unit
));
91 static void ccp_lowerdown
__P((int));
92 static void ccp_input
__P((int unit
, u_char
*pkt
, int len
));
93 static void ccp_protrej
__P((int unit
));
94 static int ccp_printpkt
__P((u_char
*pkt
, int len
,
95 void (*printer
) __P((void *, const char *, ...)),
97 static void ccp_datainput
__P((int unit
, u_char
*pkt
, int len
));
99 struct protent ccp_protent
= {
119 fsm ccp_fsm
[NUM_PPP
];
120 ccp_options ccp_wantoptions
[NUM_PPP
]; /* what to request the peer to use */
121 ccp_options ccp_gotoptions
[NUM_PPP
]; /* what the peer agreed to do */
122 ccp_options ccp_allowoptions
[NUM_PPP
]; /* what we'll agree to do */
123 ccp_options ccp_hisoptions
[NUM_PPP
]; /* what we agreed to do */
126 * Callbacks for fsm code.
128 static void ccp_resetci
__P((fsm
*));
129 static int ccp_cilen
__P((fsm
*));
130 static void ccp_addci
__P((fsm
*, u_char
*, int *));
131 static int ccp_ackci
__P((fsm
*, u_char
*, int));
132 static int ccp_nakci
__P((fsm
*, u_char
*, int));
133 static int ccp_rejci
__P((fsm
*, u_char
*, int));
134 static int ccp_reqci
__P((fsm
*, u_char
*, int *, int));
135 static void ccp_up
__P((fsm
*));
136 static void ccp_down
__P((fsm
*));
137 static int ccp_extcode
__P((fsm
*, int, int, u_char
*, int));
138 static int ccp_codereject
__P((fsm
*p
, int code
, int id
, u_char
*inp
,
141 static fsm_callbacks ccp_callbacks
= {
142 ccp_resetci
, /* Reset our Configuration Information */
143 ccp_cilen
, /* Length of our Configuration Information */
144 ccp_addci
, /* Add our Configuration Information */
145 ccp_ackci
, /* ACK our Configuration Information */
146 ccp_nakci
, /* NAK our Configuration Information */
147 ccp_rejci
, /* Reject our Configuration Information */
148 ccp_reqci
, /* Request peer's Configuration Information */
149 ccp_up
, /* Called when fsm reaches OPENED state */
150 ccp_down
, /* Called when fsm leaves OPENED state */
151 NULL
, /* Called when we want the lower layer up */
152 NULL
, /* Called when we want the lower layer down */
153 NULL
, /* Retransmission is necessary */
154 ccp_extcode
, /* Called to handle LCP-specific codes */
155 "CCP", /* String name of protocol */
156 ccp_codereject
, /* Peer rejected a code number */
162 static void ccp_rack_timeout
__P((void *));
163 static char * method_name
__P((ccp_options
*, ccp_options
*));
166 * Do we want / did we get any compression?
168 #define ANY_COMPRESS(opt) ((opt).deflate || (opt).bsd_compress \
169 || (opt).predictor_1 || (opt).predictor_2)
172 * Local state (mainly for handling reset-reqs and reset-acks).
174 static int ccp_localstate
[NUM_PPP
];
175 #define RACK_PENDING 0x0001 /* waiting for reset-ack */
176 #define RREQ_REPEAT 0x0002 /* send another reset-req if no reset-ack */
177 #define RREQ_REJECTED 0x0004 /* peer code-rejected reset-request */
178 #define RACK_REJECTED 0x0008 /* peer code-rejected reset-ack */
179 #define RREQ_IGNORED 0x0010 /* peer just ignored reset-request */
181 #define RACKTIMEOUT 1 /* time in seconds between Reset-Requests */
183 static int all_rejected
[NUM_PPP
]; /* we rejected all peer's options */
186 static int deflate_tune
= -1; /* compression effort level for deflate */
188 static int deflate_rmax
= DEFLATE_MAX_SIZE
; /* max rbits */
189 static int deflate_amax
= DEFLATE_MAX_SIZE
; /* max abits */
196 setbsdcomp(argv
, opt
)
204 abits
= rbits
= strtol(str
, &endp
, 0);
205 if (endp
!= str
&& *endp
== ',') {
207 abits
= strtol(str
, &endp
, 0);
209 if (*endp
!= '\0' || endp
== str
) {
210 option_error("invalid parameter '%s' for bsdcomp option", *argv
);
213 if ((rbits
!= 0 && (rbits
< BSD_MIN_BITS
|| rbits
> BSD_MAX_BITS
))
214 || (abits
!= 0 && (abits
< BSD_MIN_BITS
|| abits
> BSD_MAX_BITS
))) {
215 option_error("bsdcomp option values must be 0 or %d .. %d",
216 BSD_MIN_BITS
, BSD_MAX_BITS
);
220 ccp_wantoptions
[0].bsd_compress
= 1;
221 ccp_wantoptions
[0].bsd_bits
= rbits
;
223 ccp_wantoptions
[0].bsd_compress
= 0;
225 ccp_allowoptions
[0].bsd_compress
= 1;
226 ccp_allowoptions
[0].bsd_bits
= abits
;
228 ccp_allowoptions
[0].bsd_compress
= 0;
234 setdeflate(argv
, opt
)
238 int rbits
, abits
, def_rmax
, def_amax
;
245 abits
= rbits
= strtol(str
, &endp
, 0);
251 abits
= strtol(str
, &endp
, 0);
254 if (*endp
== ',' && privileged_option
) {
256 deflate_tune
= strtol(str
, &endp
, 0);
259 if (*endp
!= '\0' || endp
== str
) {
260 option_error("invalid parameter '%s' for deflate option", *argv
);
263 if (privileged_option
) {
264 def_rmax
= def_amax
= DEFLATE_MAX_SIZE
;
266 def_rmax
= deflate_rmax
;
267 def_amax
= deflate_amax
;
273 if ((rbits
!= 0 && (rbits
<= DEFLATE_MIN_SIZE
|| rbits
> def_rmax
))
274 || (abits
!= 0 && (abits
<= DEFLATE_MIN_SIZE
|| abits
> def_amax
))) {
275 option_error("deflate option values must be 0 or {%d,%d} .. {%d,%d}",
276 DEFLATE_MIN_SIZE
+1, DEFLATE_MIN_SIZE
+1,
280 if (privileged_option
) {
281 deflate_rmax
= rbits
;
282 deflate_amax
= abits
;
285 ccp_wantoptions
[0].deflate
= 1;
286 ccp_wantoptions
[0].deflate_size
= rbits
;
288 ccp_wantoptions
[0].deflate
= 0;
290 ccp_allowoptions
[0].deflate
= 1;
291 ccp_allowoptions
[0].deflate_size
= abits
;
293 ccp_allowoptions
[0].deflate
= 0;
299 * ccp_init - initialize CCP.
305 fsm
*f
= &ccp_fsm
[unit
];
308 f
->protocol
= PPP_CCP
;
309 f
->callbacks
= &ccp_callbacks
;
311 f
->flags
|= OPT_RESTART
;
313 BZERO(&ccp_wantoptions
[unit
], sizeof(ccp_options
));
314 BZERO(&ccp_gotoptions
[unit
], sizeof(ccp_options
));
315 BZERO(&ccp_allowoptions
[unit
], sizeof(ccp_options
));
316 BZERO(&ccp_hisoptions
[unit
], sizeof(ccp_options
));
318 ccp_wantoptions
[0].deflate
= 1;
319 ccp_wantoptions
[0].deflate_size
= DEFLATE_MAX_SIZE
;
320 ccp_wantoptions
[0].deflate_correct
= 1;
321 ccp_wantoptions
[0].deflate_draft
= 1;
322 ccp_allowoptions
[0].deflate
= 1;
323 ccp_allowoptions
[0].deflate_size
= DEFLATE_MAX_SIZE
;
324 ccp_allowoptions
[0].deflate_correct
= 1;
325 ccp_allowoptions
[0].deflate_draft
= 1;
327 ccp_wantoptions
[0].bsd_compress
= 1;
328 ccp_wantoptions
[0].bsd_bits
= BSD_MAX_BITS
;
329 ccp_allowoptions
[0].bsd_compress
= 1;
330 ccp_allowoptions
[0].bsd_bits
= BSD_MAX_BITS
;
332 ccp_allowoptions
[0].predictor_1
= 1;
336 * ccp_open - CCP is allowed to come up.
342 fsm
*f
= &ccp_fsm
[unit
];
345 * If we haven't gone open yet (first time through), then go open
346 * but not up. Otherwise, skip this to allow reopen to reset the
349 if (f
->state
!= OPENED
)
350 ccp_flags_set(unit
, 1, 0);
353 * Find out which compressors the kernel supports before
354 * deciding whether to open in silent mode.
357 if (!ANY_COMPRESS(ccp_gotoptions
[unit
]))
358 f
->flags
|= OPT_SILENT
;
364 * ccp_close - Terminate CCP.
367 ccp_close(unit
, reason
)
371 ccp_flags_set(unit
, 0, 0);
372 fsm_close(&ccp_fsm
[unit
], reason
);
376 * ccp_lowerup - we may now transmit CCP packets.
382 fsm_lowerup(&ccp_fsm
[unit
]);
386 * ccp_lowerdown - we may not transmit CCP packets.
392 fsm_lowerdown(&ccp_fsm
[unit
]);
396 * ccp_input - process a received CCP packet.
399 ccp_input(unit
, p
, len
)
404 fsm
*f
= &ccp_fsm
[unit
];
408 * Check for a terminate-request so we can print a message.
411 fsm_input(f
, p
, len
);
412 if (oldstate
== OPENED
&& p
[0] == CODE_TERMREQ
&& f
->state
!= OPENED
)
413 notice("Compression disabled by peer.");
416 * If we get a terminate-ack and we're not asking for compression,
417 * close CCP. (Terminate-Request is handled by fsm_input() above.)
419 if (oldstate
== REQSENT
&& p
[0] == CODE_TERMACK
420 && !ANY_COMPRESS(ccp_gotoptions
[unit
]))
421 ccp_close(unit
, "No compression negotiated");
425 * Handle a CCP-specific code.
428 ccp_extcode(f
, code
, id
, p
, len
)
436 /* If not open, then silently ignore. */
437 if (f
->state
!= OPENED
)
439 /* send a reset-ack, which our transmitter module will see and
440 reset its compression state. */
441 fsm_sdata(f
, CCP_RESETACK
, id
, p
, len
);
446 * Note that the compression module isn't picky about ID
449 ccp_localstate
[f
->unit
] &= ~RREQ_IGNORED
& ~RREQ_REJECTED
;
450 if ((ccp_localstate
[f
->unit
] & RACK_PENDING
) && id
== f
->reqid
) {
451 ccp_localstate
[f
->unit
] &= ~RACK_PENDING
& ~RREQ_REPEAT
;
452 UNTIMEOUT(ccp_rack_timeout
, f
);
457 /* Tell fsm to send code reject */
465 * Handle Code-Reject for one of our extended codes by dropping back to
466 * reopen as mechanism to restart compression.
470 ccp_codereject(f
, code
, id
, inp
, len
)
478 if (!(ccp_localstate
[f
->unit
] & RREQ_REJECTED
)) {
479 info("peer has rejected CCP Reset-Request; falling back on Open");
480 if (f
->state
== OPENED
)
483 ccp_localstate
[f
->unit
] |= RREQ_REJECTED
;
488 * Peer must have sent us CCP Reset-Request but then code-rejected when
489 * we sent CCP Reset-Ack. It seems to have changed its mind, and we
490 * have to obey its wishes.
492 ccp_localstate
[f
->unit
] |= RACK_REJECTED
;
493 notice("peer has erroneously rejected CCP Reset-Ack");
494 f
->term_reason
= "peer sent Code-Reject for CCP Reset-Ack";
495 f
->term_reason_len
= strlen(f
->term_reason
);
499 f
->term_reason
= "peer sent invalid Code-Reject";
503 f
->term_reason_len
= strlen(f
->term_reason
);
508 * ccp_protrej - peer doesn't talk CCP.
514 /* Neither open nor up. */
515 ccp_flags_set(unit
, 0, 0);
516 fsm_lowerdown(&ccp_fsm
[unit
]);
520 * ccp_resetci - initialize at start of negotiation.
526 ccp_options
*go
= &ccp_gotoptions
[f
->unit
];
529 *go
= ccp_wantoptions
[f
->unit
];
530 all_rejected
[f
->unit
] = 0;
533 * Check whether the kernel knows about the various
534 * decompression methods we might request.
536 if (go
->bsd_compress
) {
537 opt_buf
[0] = CI_BSD_COMPRESS
;
538 opt_buf
[1] = CILEN_BSD_COMPRESS
;
539 opt_buf
[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION
, BSD_MIN_BITS
);
540 if (ccp_test(f
->unit
, opt_buf
, CILEN_BSD_COMPRESS
, 0) <= 0)
541 go
->bsd_compress
= 0;
544 if (go
->deflate_correct
) {
545 opt_buf
[0] = CI_DEFLATE
;
546 opt_buf
[1] = CILEN_DEFLATE
;
547 opt_buf
[2] = DEFLATE_MAKE_OPT(DEFLATE_MIN_SIZE
+1);
548 opt_buf
[3] = DEFLATE_CHK_SEQUENCE
;
549 if (ccp_test(f
->unit
, opt_buf
, CILEN_DEFLATE
, 0) <= 0)
550 go
->deflate_correct
= 0;
552 if (go
->deflate_draft
) {
553 opt_buf
[0] = CI_DEFLATE_DRAFT
;
554 opt_buf
[1] = CILEN_DEFLATE
;
555 opt_buf
[2] = DEFLATE_MAKE_OPT(DEFLATE_MIN_SIZE
+1);
556 opt_buf
[3] = DEFLATE_CHK_SEQUENCE
;
557 if (ccp_test(f
->unit
, opt_buf
, CILEN_DEFLATE
, 0) <= 0)
558 go
->deflate_draft
= 0;
560 if (!go
->deflate_correct
&& !go
->deflate_draft
)
563 if (go
->predictor_1
) {
564 opt_buf
[0] = CI_PREDICTOR_1
;
565 opt_buf
[1] = CILEN_PREDICTOR_1
;
566 if (ccp_test(f
->unit
, opt_buf
, CILEN_PREDICTOR_1
, 0) <= 0)
569 if (go
->predictor_2
) {
570 opt_buf
[0] = CI_PREDICTOR_2
;
571 opt_buf
[1] = CILEN_PREDICTOR_2
;
572 if (ccp_test(f
->unit
, opt_buf
, CILEN_PREDICTOR_2
, 0) <= 0)
578 * ccp_cilen - Return total length of our configuration info.
584 ccp_options
*go
= &ccp_gotoptions
[f
->unit
];
586 return (go
->bsd_compress
? CILEN_BSD_COMPRESS
: 0)
587 + (go
->deflate
&& go
->deflate_correct
? CILEN_DEFLATE
: 0)
588 + (go
->deflate
&& go
->deflate_draft
? CILEN_DEFLATE
: 0)
589 + (go
->predictor_1
? CILEN_PREDICTOR_1
: 0)
590 + (go
->predictor_2
? CILEN_PREDICTOR_2
: 0);
594 * ccp_addci - put our requests in a packet.
597 ccp_addci(f
, p
, lenp
)
603 ccp_options
*go
= &ccp_gotoptions
[f
->unit
];
607 * Add the compression types that we can receive, in decreasing
608 * preference order. Get the kernel to allocate the first one
609 * in case it gets Acked.
612 p
[0] = go
->deflate_correct
? CI_DEFLATE
: CI_DEFLATE_DRAFT
;
613 p
[1] = CILEN_DEFLATE
;
614 p
[2] = DEFLATE_MAKE_OPT(go
->deflate_size
);
615 p
[3] = DEFLATE_CHK_SEQUENCE
;
617 res
= ccp_test(f
->unit
, p
, CILEN_DEFLATE
, 0);
622 if (res
< 0 || go
->deflate_size
<= DEFLATE_MIN_SIZE
+1) {
627 p
[2] = DEFLATE_MAKE_OPT(go
->deflate_size
);
629 /* If we're offering both, then this is second. */
630 if (p
!= p0
&& go
->deflate_correct
&& go
->deflate_draft
) {
631 p
[0] = CI_DEFLATE_DRAFT
;
632 p
[1] = CILEN_DEFLATE
;
633 p
[2] = p
[2 - CILEN_DEFLATE
];
634 p
[3] = DEFLATE_CHK_SEQUENCE
;
638 if (go
->bsd_compress
) {
639 p
[0] = CI_BSD_COMPRESS
;
640 p
[1] = CILEN_BSD_COMPRESS
;
641 p
[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION
, go
->bsd_bits
);
643 p
+= CILEN_BSD_COMPRESS
; /* not the first option */
646 res
= ccp_test(f
->unit
, p
, CILEN_BSD_COMPRESS
, 0);
648 p
+= CILEN_BSD_COMPRESS
;
651 if (res
< 0 || go
->bsd_bits
<= BSD_MIN_BITS
) {
652 go
->bsd_compress
= 0;
656 p
[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION
, go
->bsd_bits
);
661 * Prefer Predictor-1 over Predictor-2. (The latter requires the use
662 * of LAP-B and has no known implementations.)
664 if (go
->predictor_1
) {
665 p
[0] = CI_PREDICTOR_1
;
666 p
[1] = CILEN_PREDICTOR_1
;
667 if (p
== p0
&& ccp_test(f
->unit
, p
, CILEN_PREDICTOR_1
, 0) <= 0) {
670 p
+= CILEN_PREDICTOR_1
;
673 if (go
->predictor_2
) {
674 p
[0] = CI_PREDICTOR_2
;
675 p
[1] = CILEN_PREDICTOR_2
;
676 if (p
== p0
&& ccp_test(f
->unit
, p
, CILEN_PREDICTOR_2
, 0) <= 0) {
679 p
+= CILEN_PREDICTOR_2
;
683 go
->method
= (p
> p0
)? p0
[0]: -1;
689 * ccp_ackci - process a received configure-ack, and return
690 * 1 iff the packet was OK.
698 ccp_options
*go
= &ccp_gotoptions
[f
->unit
];
701 if (go
->deflate
&& go
->deflate_correct
) {
702 if (len
< CILEN_DEFLATE
703 || p
[0] != CI_DEFLATE
|| p
[1] != CILEN_DEFLATE
704 || p
[2] != DEFLATE_MAKE_OPT(go
->deflate_size
)
705 || p
[3] != DEFLATE_CHK_SEQUENCE
)
707 /* Cope with non-standard first/fast ack */
708 if (p
== p0
&& len
== 0)
711 len
-= CILEN_DEFLATE
;
713 if (go
->deflate
&& go
->deflate_draft
) {
714 if (len
< CILEN_DEFLATE
715 || p
[0] != CI_DEFLATE_DRAFT
|| p
[1] != CILEN_DEFLATE
716 || p
[2] != DEFLATE_MAKE_OPT(go
->deflate_size
)
717 || p
[3] != DEFLATE_CHK_SEQUENCE
)
719 /* Cope with non-standard first/fast ack */
720 if (p
== p0
&& len
== 0)
723 len
-= CILEN_DEFLATE
;
725 if (go
->bsd_compress
) {
726 if (len
< CILEN_BSD_COMPRESS
727 || p
[0] != CI_BSD_COMPRESS
|| p
[1] != CILEN_BSD_COMPRESS
728 || p
[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION
, go
->bsd_bits
))
730 /* Cope with non-standard first/fast ack */
731 if (p
== p0
&& len
== 0)
733 p
+= CILEN_BSD_COMPRESS
;
734 len
-= CILEN_BSD_COMPRESS
;
736 if (go
->predictor_1
) {
737 if (len
< CILEN_PREDICTOR_1
738 || p
[0] != CI_PREDICTOR_1
|| p
[1] != CILEN_PREDICTOR_1
)
740 /* Cope with non-standard first/fast ack */
741 if (p
== p0
&& len
== 0)
743 p
+= CILEN_PREDICTOR_1
;
744 len
-= CILEN_PREDICTOR_1
;
746 if (go
->predictor_2
) {
747 if (len
< CILEN_PREDICTOR_2
748 || p
[0] != CI_PREDICTOR_2
|| p
[1] != CILEN_PREDICTOR_2
)
750 /* Cope with non-standard first/fast ack */
751 if (p
== p0
&& len
== 0)
753 p
+= CILEN_PREDICTOR_2
;
754 len
-= CILEN_PREDICTOR_2
;
757 /* Peer cannot ack something that wasn't sent. */
764 * ccp_nakci - process received configure-nak.
765 * Returns 1 iff the nak was OK.
773 ccp_options
*go
= &ccp_gotoptions
[f
->unit
];
774 ccp_options no
; /* options we've seen already */
775 ccp_options
try; /* options to ask for next time */
777 BZERO(&no
, sizeof(no
));
780 if (go
->deflate
&& go
->deflate_correct
&& len
>= CILEN_DEFLATE
&&
781 p
[0] == CI_DEFLATE
) {
784 * Peer wants us to use a different code size or something.
785 * Stop asking for Deflate if we don't understand its suggestion.
787 if (p
[1] != CILEN_DEFLATE
788 || DEFLATE_METHOD(p
[2]) != DEFLATE_METHOD_VAL
789 || DEFLATE_SIZE(p
[2]) <= DEFLATE_MIN_SIZE
790 || p
[3] != DEFLATE_CHK_SEQUENCE
)
791 try.deflate_correct
= 0;
792 else if (DEFLATE_SIZE(p
[2]) < go
->deflate_size
)
793 try.deflate_size
= DEFLATE_SIZE(p
[2]);
798 if (go
->deflate
&& go
->deflate_draft
&& len
>= CILEN_DEFLATE
&&
799 p
[0] == CI_DEFLATE_DRAFT
) {
802 * Peer wants us to use a different code size or something.
803 * Stop asking for Deflate using the old algorithm number if
804 * we don't understand its suggestion. (Note that this will
805 * happen if the peer is running Magnalink instead of
806 * old-style Deflate.)
808 if (p
[1] != CILEN_DEFLATE
809 || DEFLATE_METHOD(p
[2]) != DEFLATE_METHOD_VAL
810 || DEFLATE_SIZE(p
[2]) <= DEFLATE_MIN_SIZE
811 || p
[3] != DEFLATE_CHK_SEQUENCE
)
812 try.deflate_draft
= 0;
813 else if (DEFLATE_SIZE(p
[2]) < go
->deflate_size
)
814 try.deflate_size
= DEFLATE_SIZE(p
[2]);
819 if (!try.deflate_correct
&& !try.deflate_draft
)
822 if (go
->bsd_compress
&& len
>= CILEN_BSD_COMPRESS
&&
823 p
[0] == CI_BSD_COMPRESS
) {
826 * Peer wants us to use a different number of bits
827 * or a different version.
829 if (p
[1] != CILEN_BSD_COMPRESS
||
830 BSD_VERSION(p
[2]) != BSD_CURRENT_VERSION
)
831 try.bsd_compress
= 0;
832 else if (BSD_NBITS(p
[2]) < go
->bsd_bits
)
833 try.bsd_bits
= BSD_NBITS(p
[2]);
839 * Predictor-1 and 2 have no options, so they can't be Naked.
841 * There may be remaining options but we ignore them.
844 if (f
->state
!= OPENED
)
850 * ccp_rejci - peer rejects some of our suggested compression methods.
858 ccp_options
*go
= &ccp_gotoptions
[f
->unit
];
859 ccp_options
try; /* options to request next time */
864 * Cope with empty configure-rejects by ceasing to send
865 * configure-requests.
867 if (len
== 0 && all_rejected
[f
->unit
])
870 if (go
->deflate
&& go
->deflate_correct
&& len
>= CILEN_DEFLATE
&&
871 p
[0] == CI_DEFLATE
&& p
[1] == CILEN_DEFLATE
) {
872 if (p
[2] != DEFLATE_MAKE_OPT(go
->deflate_size
)
873 || p
[3] != DEFLATE_CHK_SEQUENCE
)
874 return 0; /* Rej is bad */
875 try.deflate_correct
= 0;
877 len
-= CILEN_DEFLATE
;
879 if (go
->deflate
&& go
->deflate_draft
&& len
>= CILEN_DEFLATE
&&
880 p
[0] == CI_DEFLATE_DRAFT
&& p
[1] == CILEN_DEFLATE
) {
881 if (p
[2] != DEFLATE_MAKE_OPT(go
->deflate_size
)
882 || p
[3] != DEFLATE_CHK_SEQUENCE
)
883 return 0; /* Rej is bad */
884 try.deflate_draft
= 0;
886 len
-= CILEN_DEFLATE
;
888 if (!try.deflate_correct
&& !try.deflate_draft
)
890 if (go
->bsd_compress
&& len
>= CILEN_BSD_COMPRESS
891 && p
[0] == CI_BSD_COMPRESS
&& p
[1] == CILEN_BSD_COMPRESS
) {
892 if (p
[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION
, go
->bsd_bits
))
894 try.bsd_compress
= 0;
895 p
+= CILEN_BSD_COMPRESS
;
896 len
-= CILEN_BSD_COMPRESS
;
898 if (go
->predictor_1
&& len
>= CILEN_PREDICTOR_1
899 && p
[0] == CI_PREDICTOR_1
&& p
[1] == CILEN_PREDICTOR_1
) {
901 p
+= CILEN_PREDICTOR_1
;
902 len
-= CILEN_PREDICTOR_1
;
904 if (go
->predictor_2
&& len
>= CILEN_PREDICTOR_2
905 && p
[0] == CI_PREDICTOR_2
&& p
[1] == CILEN_PREDICTOR_2
) {
907 p
+= CILEN_PREDICTOR_2
;
908 len
-= CILEN_PREDICTOR_2
;
914 if (f
->state
!= OPENED
)
921 * ccp_reqci - process a received configure-request.
923 * Returns CODE_CONFACK, CODE_CONFNAK or CODE_CONFREJ and the packet
924 * is modified appropriately.
927 ccp_reqci(f
, p
, lenp
, dont_nak
)
933 int ret
, newret
, res
;
934 u_char
*p0
, *nakp
, *rejp
, *pv
;
935 int len
, clen
, type
, nb
;
936 ccp_options
*ho
= &ccp_hisoptions
[f
->unit
];
937 ccp_options
*ao
= &ccp_allowoptions
[f
->unit
];
944 BZERO(ho
, sizeof(ccp_options
));
945 ho
->method
= (len
> 0)? p
[0]: -1;
947 for (; len
> 0; len
-= clen
, p
+= clen
) {
948 newret
= CODE_CONFACK
;
949 if (len
< 2 || p
[1] > len
) {
951 * RFC 1661 page 40 -- if the option extends beyond the
952 * packet, then discard the entire packet.
963 case CI_DEFLATE_DRAFT
:
965 (!ao
->deflate_correct
&& type
== CI_DEFLATE
) ||
966 (!ao
->deflate_draft
&& type
== CI_DEFLATE_DRAFT
)) {
967 newret
= CODE_CONFREJ
;
972 nb
= clen
< CILEN_DEFLATE
? ao
->deflate_size
: DEFLATE_SIZE(p
[2]);
973 ho
->deflate_size
= nb
;
974 if (clen
!= CILEN_DEFLATE
||
975 DEFLATE_METHOD(p
[2]) != DEFLATE_METHOD_VAL
||
976 p
[3] != DEFLATE_CHK_SEQUENCE
|| nb
> ao
->deflate_size
||
977 nb
<= DEFLATE_MIN_SIZE
) {
978 newret
= CODE_CONFNAK
;
981 if (nb
> ao
->deflate_size
)
982 nb
= ao
->deflate_size
;
983 else if (nb
<= DEFLATE_MIN_SIZE
)
984 nb
= DEFLATE_MIN_SIZE
+1;
987 PUTCHAR(CILEN_DEFLATE
, nakp
);
988 PUTCHAR(DEFLATE_MAKE_OPT(nb
), nakp
);
989 PUTCHAR(DEFLATE_CHK_SEQUENCE
, nakp
);
993 * Check whether we can do Deflate with the window
994 * size they want. If the window is too big, reduce
995 * it until the kernel can cope and nak with that.
996 * We only check this for the first option.
1000 res
= ccp_test(f
->unit
, pv
, CILEN_DEFLATE
, 1);
1002 break; /* it's OK now */
1003 if (res
< 0 || nb
<= DEFLATE_MIN_SIZE
+1 || dont_nak
) {
1004 newret
= CODE_CONFREJ
;
1007 if (newret
== CODE_CONFACK
) {
1008 BCOPY(pv
, nakp
, CILEN_DEFLATE
);
1010 nakp
+= CILEN_DEFLATE
;
1011 newret
= CODE_CONFNAK
;
1014 pv
[2] = DEFLATE_MAKE_OPT(nb
);
1017 /* Tune Deflate compression effort. */
1018 if (newret
== CODE_CONFACK
)
1019 ccp_tune(f
->unit
, deflate_tune
);
1024 case CI_BSD_COMPRESS
:
1025 if (!ao
->bsd_compress
) {
1026 newret
= CODE_CONFREJ
;
1030 ho
->bsd_compress
= 1;
1031 nb
= clen
< CILEN_BSD_COMPRESS
? ao
->bsd_bits
: BSD_NBITS(p
[2]);
1033 if (clen
!= CILEN_BSD_COMPRESS
||
1034 BSD_VERSION(p
[2]) != BSD_CURRENT_VERSION
||
1035 nb
> ao
->bsd_bits
|| nb
< BSD_MIN_BITS
) {
1036 newret
= CODE_CONFNAK
;
1039 if (nb
> ao
->bsd_bits
)
1041 else if (nb
< BSD_MIN_BITS
)
1044 PUTCHAR(type
, nakp
);
1045 PUTCHAR(CILEN_BSD_COMPRESS
, nakp
);
1046 PUTCHAR(BSD_MAKE_OPT(BSD_CURRENT_VERSION
, nb
), nakp
);
1050 * Check whether we can do BSD-Compress with the code
1051 * size they want. If the code size is too big, reduce
1052 * it until the kernel can cope and nak with that.
1053 * We only check this for the first option.
1057 res
= ccp_test(f
->unit
, pv
, CILEN_BSD_COMPRESS
, 1);
1060 if (res
< 0 || nb
== BSD_MIN_BITS
|| dont_nak
) {
1061 newret
= CODE_CONFREJ
;
1064 if (newret
== CODE_CONFACK
) {
1065 BCOPY(pv
, nakp
, CILEN_BSD_COMPRESS
);
1067 nakp
+= CILEN_BSD_COMPRESS
;
1068 newret
= CODE_CONFNAK
;
1071 pv
[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION
, nb
);
1076 case CI_PREDICTOR_1
:
1077 if (!ao
->predictor_1
) {
1078 newret
= CODE_CONFREJ
;
1082 ho
->predictor_1
= 1;
1083 if (clen
!= CILEN_PREDICTOR_1
) {
1084 newret
= CODE_CONFNAK
;
1088 PUTCHAR(type
, nakp
);
1089 PUTCHAR(CILEN_PREDICTOR_1
, nakp
);
1092 ccp_test(f
->unit
, pv
, CILEN_PREDICTOR_1
, 1) <= 0) {
1093 newret
= CODE_CONFREJ
;
1097 case CI_PREDICTOR_2
:
1098 if (!ao
->predictor_2
) {
1099 newret
= CODE_CONFREJ
;
1103 ho
->predictor_2
= 1;
1104 if (clen
!= CILEN_PREDICTOR_2
) {
1105 newret
= CODE_CONFNAK
;
1109 PUTCHAR(type
, nakp
);
1110 PUTCHAR(CILEN_PREDICTOR_2
, nakp
);
1113 ccp_test(f
->unit
, p
, CILEN_PREDICTOR_2
, 1) <= 0) {
1114 newret
= CODE_CONFREJ
;
1119 newret
= CODE_CONFREJ
;
1123 /* Cope with confused peers. */
1127 if (newret
== CODE_CONFACK
&& ret
!= CODE_CONFACK
)
1129 if (newret
== CODE_CONFNAK
) {
1131 newret
= CODE_CONFREJ
;
1133 /* Ignore subsequent nakable things if rejecting. */
1134 if (ret
== CODE_CONFREJ
)
1139 if (newret
== CODE_CONFREJ
) {
1142 BCOPY(p
, rejp
, clen
);
1152 *lenp
= nakp
- nak_buffer
;
1153 BCOPY(nak_buffer
, p0
, *lenp
);
1163 * Make a string name for a compression method (or 2).
1166 method_name(opt
, opt2
)
1167 ccp_options
*opt
, *opt2
;
1169 static char result
[64];
1171 if (!ANY_COMPRESS(*opt
))
1173 switch (opt
->method
) {
1175 case CI_DEFLATE_DRAFT
:
1176 if (opt2
!= NULL
&& opt2
->deflate_size
!= opt
->deflate_size
)
1177 (void) slprintf(result
, sizeof(result
), "Deflate%s (%d/%d)",
1178 (opt
->method
== CI_DEFLATE_DRAFT
? "(old#)": ""),
1179 opt
->deflate_size
, opt2
->deflate_size
);
1181 (void) slprintf(result
, sizeof(result
), "Deflate%s (%d)",
1182 (opt
->method
== CI_DEFLATE_DRAFT
? "(old#)": ""),
1185 case CI_BSD_COMPRESS
:
1186 if (opt2
!= NULL
&& opt2
->bsd_bits
!= opt
->bsd_bits
)
1187 (void) slprintf(result
, sizeof(result
), "BSD-Compress (%d/%d)",
1188 opt
->bsd_bits
, opt2
->bsd_bits
);
1190 (void) slprintf(result
, sizeof(result
), "BSD-Compress (%d)",
1193 case CI_PREDICTOR_1
:
1194 return "Predictor 1";
1195 case CI_PREDICTOR_2
:
1196 return "Predictor 2";
1206 (void) slprintf(result
, sizeof(result
), "Method %d", opt
->method
);
1212 * CCP has come up - inform the kernel driver and log a message.
1218 ccp_options
*go
= &ccp_gotoptions
[f
->unit
];
1219 ccp_options
*ho
= &ccp_hisoptions
[f
->unit
];
1223 * We're now open and up (running).
1225 ccp_flags_set(f
->unit
, 1, 1);
1226 if (ANY_COMPRESS(*go
)) {
1227 if (ANY_COMPRESS(*ho
)) {
1228 if (go
->method
== ho
->method
) {
1229 notice("%s compression enabled", method_name(go
, ho
));
1231 (void) strlcpy(method1
, method_name(go
, NULL
), sizeof(method1
));
1232 notice("%s / %s compression enabled",
1233 method1
, method_name(ho
, NULL
));
1236 notice("%s receive decompression enabled", method_name(go
, NULL
));
1237 } else if (ANY_COMPRESS(*ho
))
1238 notice("%s transmit compression enabled", method_name(ho
, NULL
));
1242 * CCP has gone down - inform the kernel driver.
1248 if (ccp_localstate
[f
->unit
] & RACK_PENDING
)
1249 UNTIMEOUT(ccp_rack_timeout
, f
);
1250 /* Don't forget about peer's code rejects or ignoring of requests. */
1251 ccp_localstate
[f
->unit
] &= ~RACK_PENDING
& ~RREQ_REPEAT
;
1252 /* We're still open, but no longer up. */
1253 ccp_flags_set(f
->unit
, 1, 0);
1257 ccp_printpkt(p
, plen
, printer
, arg
)
1260 void (*printer
) __P((void *, const char *, ...));
1263 u_char
*p0
, *optend
, cichar
;
1272 if (plen
< HEADERLEN
) {
1273 printer(arg
, "too short (%d<%d)", plen
, HEADERLEN
);
1280 printer(arg
, " %s id=0x%x", code_name(code
, 1), id
);
1282 if (len
< HEADERLEN
) {
1283 printer(arg
, " header length %d<%d", len
, HEADERLEN
);
1287 printer(arg
, " truncated (%d>%d)", len
, plen
);
1297 /* print list of possible compression methods */
1308 optend
= p
+ optlen
- 2;
1311 case CI_DEFLATE_DRAFT
:
1312 printer(arg
, "deflate%s",
1313 (code
== CI_DEFLATE_DRAFT
? "(old#)": ""));
1314 if (clen
!= CILEN_DEFLATE
)
1315 printer(arg
, " length %d", clen
);
1316 if (optlen
>= CILEN_DEFLATE
) {
1318 printer(arg
, " %d", DEFLATE_SIZE(cichar
));
1319 if (DEFLATE_METHOD(cichar
) != DEFLATE_METHOD_VAL
)
1320 printer(arg
, " method %d", DEFLATE_METHOD(cichar
));
1322 if (cichar
!= DEFLATE_CHK_SEQUENCE
)
1323 printer(arg
, " check %d", cichar
);
1326 case CI_BSD_COMPRESS
:
1327 printer(arg
, "bsd");
1328 if (clen
!= CILEN_BSD_COMPRESS
)
1329 printer(arg
, " length %d", clen
);
1330 if (optlen
>= CILEN_BSD_COMPRESS
) {
1332 printer(arg
, " v%d %d", BSD_VERSION(cichar
),
1336 case CI_PREDICTOR_1
:
1337 printer(arg
, "predictor-1");
1338 if (clen
!= CILEN_PREDICTOR_1
)
1339 printer(arg
, " length %d", clen
);
1341 case CI_PREDICTOR_2
:
1342 printer(arg
, "predictor-2");
1343 if (clen
!= CILEN_PREDICTOR_2
)
1344 printer(arg
, " length %d", clen
);
1348 printer(arg
, "Stac");
1349 if (clen
!= CILEN_STAC
)
1350 printer(arg
, " length %d", clen
);
1351 if (optlen
>= CILEN_STAC
) {
1352 GETSHORT(cishort
, p
);
1354 printer(arg
, " h%d/m%d", cishort
, cichar
);
1360 /* There appears to be no good generic name for this one. */
1361 if (optlen
>= CILEN_MPPC
) {
1363 if (!(cilong
& MPPC_COMP
)) {
1364 if (cilong
& MPPC_MPPE
)
1365 printer(arg
, "MPPE");
1367 printer(arg
, "MS-PPC?");
1369 if (cilong
& MPPC_MPPE
)
1370 printer(arg
, "MPPC+MPPE");
1372 printer(arg
, "MPPC");
1375 printer(arg
, "MS-?");
1377 if (clen
!= CILEN_STAC
)
1378 printer(arg
, " length %d", clen
);
1382 printer(arg
, "typ%d len%d ", code
, clen
);
1387 printer(arg
, " %.8B ...", p
);
1389 printer(arg
, " %.*B", optend
-p
, p
);
1400 GETSHORT(cishort
, p
);
1401 printer(arg
, " history %d", cishort
);
1403 } else if (*p
>= ' ' && *p
< 0x7f) {
1405 print_string((char *)p
, len
, printer
, arg
);
1413 /* dump out the rest of the packet in hex */
1416 printer(arg
, " %.8B ...", p
);
1418 printer(arg
, " %.*B", len
, p
);
1426 * We have received a packet that the decompressor failed to
1427 * decompress. Here we would expect to issue a reset-request, but
1428 * Motorola has a patent on resetting the compressor as a result of
1429 * detecting an error in the decompressed data after decompression.
1430 * (See US patent 5,130,993; international patent publication number
1431 * WO 91/10289; Australian patent 73296/91.)
1433 * So we ask the kernel whether the error was detected after
1434 * decompression; if it was, we take CCP down, thus disabling
1435 * compression :-(, otherwise we issue the reset-request.
1439 ccp_datainput(unit
, pkt
, len
)
1447 if (f
->state
== OPENED
) {
1448 if (ccp_fatal_error(unit
)) {
1450 * Disable compression by taking CCP down.
1452 error("Lost compression sync: disabling compression");
1453 ccp_close(unit
, "Lost compression sync");
1456 * Send a reset-request to reset the peer's compressor, if
1457 * possible. We don't do anything if we are still waiting
1458 * for an acknowledgement to a previous reset-request (to
1459 * avoid flooding the peer). We reopen CCP if the peer
1460 * doesn't like hearing about CCP Reset-Request (Cisco
1461 * sends CCP Code-Reject for Reset-Request). (Reopen
1462 * automatically clears the flags and cancels the
1465 if (ccp_localstate
[f
->unit
] & RREQ_REJECTED
) {
1466 dbglog("reopening CCP to reset peer's compressor");
1468 } else if (ccp_localstate
[f
->unit
] & RACK_PENDING
) {
1469 /* Send another reset request; we're out of sequence. */
1470 ccp_localstate
[f
->unit
] |= RREQ_REPEAT
;
1472 dbglog("sending CCP Reset-Request to reset peer's compressor");
1473 fsm_sdata(f
, CCP_RESETREQ
, f
->reqid
= ++f
->id
, NULL
, 0);
1474 TIMEOUT(ccp_rack_timeout
, f
, RACKTIMEOUT
);
1475 ccp_localstate
[f
->unit
] |= RACK_PENDING
;
1482 * Timeout waiting for reset-ack.
1485 ccp_rack_timeout(arg
)
1490 /* Timeout; no longer pending. */
1491 ccp_localstate
[f
->unit
] &= ~RACK_PENDING
;
1493 /* Frankly, it's a coding flaw if this occurs. */
1494 if (f
->state
!= OPENED
)
1497 if (ccp_localstate
[f
->unit
] & RREQ_IGNORED
) {
1498 info("peer ignored our CCP Reset-Request twice; reopen instead");
1499 ccp_localstate
[f
->unit
] =
1500 (ccp_localstate
[f
->unit
] & ~RREQ_IGNORED
) | RREQ_REJECTED
;
1502 } else if (ccp_localstate
[f
->unit
] & RREQ_REPEAT
) {
1503 dbglog("sending another CCP Reset-Request on timeout");
1504 fsm_sdata(f
, CCP_RESETREQ
, f
->reqid
, NULL
, 0);
1505 TIMEOUT(ccp_rack_timeout
, f
, RACKTIMEOUT
);
1506 ccp_localstate
[f
->unit
] =
1507 (ccp_localstate
[f
->unit
] & ~RREQ_REPEAT
) | RREQ_IGNORED
|
1510 dbglog("timeout waiting for CCP Reset-Ack; hope for the best");
1511 ccp_localstate
[f
->unit
] |= RREQ_IGNORED
;