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.
34 #pragma ident "%Z%%M% %I% %E% SMI"
35 #define RCSID "$Id: ccp.c,v 1.30 2000/04/15 01:27:11 masputra Exp $"
43 #include <net/ppp-comp.h>
45 #if !defined(lint) && !defined(_lint)
46 static const char rcsid
[] = RCSID
;
50 * Command-line options.
52 static int setbsdcomp
__P((char **, option_t
*));
53 static int setdeflate
__P((char **, option_t
*));
55 static option_t ccp_option_list
[] = {
56 { "noccp", o_bool
, &ccp_protent
.enabled_flag
,
57 "Disable CCP negotiation" },
58 { "-ccp", o_bool
, &ccp_protent
.enabled_flag
,
59 "Disable CCP negotiation" },
60 { "bsdcomp", o_special
, (void *)setbsdcomp
,
61 "Request BSD-Compress packet compression" },
62 { "nobsdcomp", o_bool
, &ccp_wantoptions
[0].bsd_compress
,
63 "don't allow BSD-Compress", OPT_A2COPY
,
64 &ccp_allowoptions
[0].bsd_compress
},
65 { "-bsdcomp", o_bool
, &ccp_wantoptions
[0].bsd_compress
,
66 "don't allow BSD-Compress", OPT_A2COPY
,
67 &ccp_allowoptions
[0].bsd_compress
},
68 { "deflate", o_special
, (void *)setdeflate
,
69 "request Deflate compression" },
70 { "nodeflate", o_bool
, &ccp_wantoptions
[0].deflate
,
71 "don't allow Deflate compression", OPT_A2COPY
,
72 &ccp_allowoptions
[0].deflate
},
73 { "-deflate", o_bool
, &ccp_wantoptions
[0].deflate
,
74 "don't allow Deflate compression", OPT_A2COPY
,
75 &ccp_allowoptions
[0].deflate
},
76 { "nodeflatedraft", o_bool
, &ccp_wantoptions
[0].deflate_draft
,
77 "don't use draft deflate #", OPT_A2COPY
,
78 &ccp_allowoptions
[0].deflate_draft
},
79 { "predictor1", o_bool
, &ccp_wantoptions
[0].predictor_1
,
80 "request Predictor-1", 1, &ccp_allowoptions
[0].predictor_1
},
81 { "nopredictor1", o_bool
, &ccp_wantoptions
[0].predictor_1
,
82 "don't allow Predictor-1", OPT_A2COPY
,
83 &ccp_allowoptions
[0].predictor_1
},
84 { "-predictor1", o_bool
, &ccp_wantoptions
[0].predictor_1
,
85 "don't allow Predictor-1", OPT_A2COPY
,
86 &ccp_allowoptions
[0].predictor_1
},
92 * Protocol entry points from main code.
94 static void ccp_init
__P((int unit
));
95 static void ccp_open
__P((int unit
));
96 static void ccp_close
__P((int unit
, char *));
97 static void ccp_lowerup
__P((int unit
));
98 static void ccp_lowerdown
__P((int));
99 static void ccp_input
__P((int unit
, u_char
*pkt
, int len
));
100 static void ccp_protrej
__P((int unit
));
101 static int ccp_printpkt
__P((u_char
*pkt
, int len
,
102 void (*printer
) __P((void *, const char *, ...)),
104 static void ccp_datainput
__P((int unit
, u_char
*pkt
, int len
));
106 struct protent ccp_protent
= {
126 fsm ccp_fsm
[NUM_PPP
];
127 ccp_options ccp_wantoptions
[NUM_PPP
]; /* what to request the peer to use */
128 ccp_options ccp_gotoptions
[NUM_PPP
]; /* what the peer agreed to do */
129 ccp_options ccp_allowoptions
[NUM_PPP
]; /* what we'll agree to do */
130 ccp_options ccp_hisoptions
[NUM_PPP
]; /* what we agreed to do */
133 * Callbacks for fsm code.
135 static void ccp_resetci
__P((fsm
*));
136 static int ccp_cilen
__P((fsm
*));
137 static void ccp_addci
__P((fsm
*, u_char
*, int *));
138 static int ccp_ackci
__P((fsm
*, u_char
*, int));
139 static int ccp_nakci
__P((fsm
*, u_char
*, int));
140 static int ccp_rejci
__P((fsm
*, u_char
*, int));
141 static int ccp_reqci
__P((fsm
*, u_char
*, int *, int));
142 static void ccp_up
__P((fsm
*));
143 static void ccp_down
__P((fsm
*));
144 static int ccp_extcode
__P((fsm
*, int, int, u_char
*, int));
145 static int ccp_codereject
__P((fsm
*p
, int code
, int id
, u_char
*inp
,
148 static fsm_callbacks ccp_callbacks
= {
149 ccp_resetci
, /* Reset our Configuration Information */
150 ccp_cilen
, /* Length of our Configuration Information */
151 ccp_addci
, /* Add our Configuration Information */
152 ccp_ackci
, /* ACK our Configuration Information */
153 ccp_nakci
, /* NAK our Configuration Information */
154 ccp_rejci
, /* Reject our Configuration Information */
155 ccp_reqci
, /* Request peer's Configuration Information */
156 ccp_up
, /* Called when fsm reaches OPENED state */
157 ccp_down
, /* Called when fsm leaves OPENED state */
158 NULL
, /* Called when we want the lower layer up */
159 NULL
, /* Called when we want the lower layer down */
160 NULL
, /* Retransmission is necessary */
161 ccp_extcode
, /* Called to handle LCP-specific codes */
162 "CCP", /* String name of protocol */
163 ccp_codereject
, /* Peer rejected a code number */
169 static void ccp_rack_timeout
__P((void *));
170 static char * method_name
__P((ccp_options
*, ccp_options
*));
173 * Do we want / did we get any compression?
175 #define ANY_COMPRESS(opt) ((opt).deflate || (opt).bsd_compress \
176 || (opt).predictor_1 || (opt).predictor_2)
179 * Local state (mainly for handling reset-reqs and reset-acks).
181 static int ccp_localstate
[NUM_PPP
];
182 #define RACK_PENDING 0x0001 /* waiting for reset-ack */
183 #define RREQ_REPEAT 0x0002 /* send another reset-req if no reset-ack */
184 #define RREQ_REJECTED 0x0004 /* peer code-rejected reset-request */
185 #define RACK_REJECTED 0x0008 /* peer code-rejected reset-ack */
186 #define RREQ_IGNORED 0x0010 /* peer just ignored reset-request */
188 #define RACKTIMEOUT 1 /* time in seconds between Reset-Requests */
190 static int all_rejected
[NUM_PPP
]; /* we rejected all peer's options */
193 static int deflate_tune
= -1; /* compression effort level for deflate */
195 static int deflate_rmax
= DEFLATE_MAX_SIZE
; /* max rbits */
196 static int deflate_amax
= DEFLATE_MAX_SIZE
; /* max abits */
203 setbsdcomp(argv
, opt
)
211 abits
= rbits
= strtol(str
, &endp
, 0);
212 if (endp
!= str
&& *endp
== ',') {
214 abits
= strtol(str
, &endp
, 0);
216 if (*endp
!= '\0' || endp
== str
) {
217 option_error("invalid parameter '%s' for bsdcomp option", *argv
);
220 if ((rbits
!= 0 && (rbits
< BSD_MIN_BITS
|| rbits
> BSD_MAX_BITS
))
221 || (abits
!= 0 && (abits
< BSD_MIN_BITS
|| abits
> BSD_MAX_BITS
))) {
222 option_error("bsdcomp option values must be 0 or %d .. %d",
223 BSD_MIN_BITS
, BSD_MAX_BITS
);
227 ccp_wantoptions
[0].bsd_compress
= 1;
228 ccp_wantoptions
[0].bsd_bits
= rbits
;
230 ccp_wantoptions
[0].bsd_compress
= 0;
232 ccp_allowoptions
[0].bsd_compress
= 1;
233 ccp_allowoptions
[0].bsd_bits
= abits
;
235 ccp_allowoptions
[0].bsd_compress
= 0;
241 setdeflate(argv
, opt
)
245 int rbits
, abits
, def_rmax
, def_amax
;
252 abits
= rbits
= strtol(str
, &endp
, 0);
258 abits
= strtol(str
, &endp
, 0);
261 if (*endp
== ',' && privileged_option
) {
263 deflate_tune
= strtol(str
, &endp
, 0);
266 if (*endp
!= '\0' || endp
== str
) {
267 option_error("invalid parameter '%s' for deflate option", *argv
);
270 if (privileged_option
) {
271 def_rmax
= def_amax
= DEFLATE_MAX_SIZE
;
273 def_rmax
= deflate_rmax
;
274 def_amax
= deflate_amax
;
280 if ((rbits
!= 0 && (rbits
<= DEFLATE_MIN_SIZE
|| rbits
> def_rmax
))
281 || (abits
!= 0 && (abits
<= DEFLATE_MIN_SIZE
|| abits
> def_amax
))) {
282 option_error("deflate option values must be 0 or {%d,%d} .. {%d,%d}",
283 DEFLATE_MIN_SIZE
+1, DEFLATE_MIN_SIZE
+1,
287 if (privileged_option
) {
288 deflate_rmax
= rbits
;
289 deflate_amax
= abits
;
292 ccp_wantoptions
[0].deflate
= 1;
293 ccp_wantoptions
[0].deflate_size
= rbits
;
295 ccp_wantoptions
[0].deflate
= 0;
297 ccp_allowoptions
[0].deflate
= 1;
298 ccp_allowoptions
[0].deflate_size
= abits
;
300 ccp_allowoptions
[0].deflate
= 0;
306 * ccp_init - initialize CCP.
312 fsm
*f
= &ccp_fsm
[unit
];
315 f
->protocol
= PPP_CCP
;
316 f
->callbacks
= &ccp_callbacks
;
318 f
->flags
|= OPT_RESTART
;
320 BZERO(&ccp_wantoptions
[unit
], sizeof(ccp_options
));
321 BZERO(&ccp_gotoptions
[unit
], sizeof(ccp_options
));
322 BZERO(&ccp_allowoptions
[unit
], sizeof(ccp_options
));
323 BZERO(&ccp_hisoptions
[unit
], sizeof(ccp_options
));
325 ccp_wantoptions
[0].deflate
= 1;
326 ccp_wantoptions
[0].deflate_size
= DEFLATE_MAX_SIZE
;
327 ccp_wantoptions
[0].deflate_correct
= 1;
328 ccp_wantoptions
[0].deflate_draft
= 1;
329 ccp_allowoptions
[0].deflate
= 1;
330 ccp_allowoptions
[0].deflate_size
= DEFLATE_MAX_SIZE
;
331 ccp_allowoptions
[0].deflate_correct
= 1;
332 ccp_allowoptions
[0].deflate_draft
= 1;
334 ccp_wantoptions
[0].bsd_compress
= 1;
335 ccp_wantoptions
[0].bsd_bits
= BSD_MAX_BITS
;
336 ccp_allowoptions
[0].bsd_compress
= 1;
337 ccp_allowoptions
[0].bsd_bits
= BSD_MAX_BITS
;
339 ccp_allowoptions
[0].predictor_1
= 1;
343 * ccp_open - CCP is allowed to come up.
349 fsm
*f
= &ccp_fsm
[unit
];
352 * If we haven't gone open yet (first time through), then go open
353 * but not up. Otherwise, skip this to allow reopen to reset the
356 if (f
->state
!= OPENED
)
357 ccp_flags_set(unit
, 1, 0);
360 * Find out which compressors the kernel supports before
361 * deciding whether to open in silent mode.
364 if (!ANY_COMPRESS(ccp_gotoptions
[unit
]))
365 f
->flags
|= OPT_SILENT
;
371 * ccp_close - Terminate CCP.
374 ccp_close(unit
, reason
)
378 ccp_flags_set(unit
, 0, 0);
379 fsm_close(&ccp_fsm
[unit
], reason
);
383 * ccp_lowerup - we may now transmit CCP packets.
389 fsm_lowerup(&ccp_fsm
[unit
]);
393 * ccp_lowerdown - we may not transmit CCP packets.
399 fsm_lowerdown(&ccp_fsm
[unit
]);
403 * ccp_input - process a received CCP packet.
406 ccp_input(unit
, p
, len
)
411 fsm
*f
= &ccp_fsm
[unit
];
415 * Check for a terminate-request so we can print a message.
418 fsm_input(f
, p
, len
);
419 if (oldstate
== OPENED
&& p
[0] == CODE_TERMREQ
&& f
->state
!= OPENED
)
420 notice("Compression disabled by peer.");
423 * If we get a terminate-ack and we're not asking for compression,
424 * close CCP. (Terminate-Request is handled by fsm_input() above.)
426 if (oldstate
== REQSENT
&& p
[0] == CODE_TERMACK
427 && !ANY_COMPRESS(ccp_gotoptions
[unit
]))
428 ccp_close(unit
, "No compression negotiated");
432 * Handle a CCP-specific code.
435 ccp_extcode(f
, code
, id
, p
, len
)
443 /* If not open, then silently ignore. */
444 if (f
->state
!= OPENED
)
446 /* send a reset-ack, which our transmitter module will see and
447 reset its compression state. */
448 fsm_sdata(f
, CCP_RESETACK
, id
, p
, len
);
453 * Note that the compression module isn't picky about ID
456 ccp_localstate
[f
->unit
] &= ~RREQ_IGNORED
& ~RREQ_REJECTED
;
457 if ((ccp_localstate
[f
->unit
] & RACK_PENDING
) && id
== f
->reqid
) {
458 ccp_localstate
[f
->unit
] &= ~RACK_PENDING
& ~RREQ_REPEAT
;
459 UNTIMEOUT(ccp_rack_timeout
, f
);
464 /* Tell fsm to send code reject */
472 * Handle Code-Reject for one of our extended codes by dropping back to
473 * reopen as mechanism to restart compression.
477 ccp_codereject(f
, code
, id
, inp
, len
)
485 if (!(ccp_localstate
[f
->unit
] & RREQ_REJECTED
)) {
486 info("peer has rejected CCP Reset-Request; falling back on Open");
487 if (f
->state
== OPENED
)
490 ccp_localstate
[f
->unit
] |= RREQ_REJECTED
;
495 * Peer must have sent us CCP Reset-Request but then code-rejected when
496 * we sent CCP Reset-Ack. It seems to have changed its mind, and we
497 * have to obey its wishes.
499 ccp_localstate
[f
->unit
] |= RACK_REJECTED
;
500 notice("peer has erroneously rejected CCP Reset-Ack");
501 f
->term_reason
= "peer sent Code-Reject for CCP Reset-Ack";
502 f
->term_reason_len
= strlen(f
->term_reason
);
506 f
->term_reason
= "peer sent invalid Code-Reject";
510 f
->term_reason_len
= strlen(f
->term_reason
);
515 * ccp_protrej - peer doesn't talk CCP.
521 /* Neither open nor up. */
522 ccp_flags_set(unit
, 0, 0);
523 fsm_lowerdown(&ccp_fsm
[unit
]);
527 * ccp_resetci - initialize at start of negotiation.
533 ccp_options
*go
= &ccp_gotoptions
[f
->unit
];
536 *go
= ccp_wantoptions
[f
->unit
];
537 all_rejected
[f
->unit
] = 0;
540 * Check whether the kernel knows about the various
541 * decompression methods we might request.
543 if (go
->bsd_compress
) {
544 opt_buf
[0] = CI_BSD_COMPRESS
;
545 opt_buf
[1] = CILEN_BSD_COMPRESS
;
546 opt_buf
[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION
, BSD_MIN_BITS
);
547 if (ccp_test(f
->unit
, opt_buf
, CILEN_BSD_COMPRESS
, 0) <= 0)
548 go
->bsd_compress
= 0;
551 if (go
->deflate_correct
) {
552 opt_buf
[0] = CI_DEFLATE
;
553 opt_buf
[1] = CILEN_DEFLATE
;
554 opt_buf
[2] = DEFLATE_MAKE_OPT(DEFLATE_MIN_SIZE
+1);
555 opt_buf
[3] = DEFLATE_CHK_SEQUENCE
;
556 if (ccp_test(f
->unit
, opt_buf
, CILEN_DEFLATE
, 0) <= 0)
557 go
->deflate_correct
= 0;
559 if (go
->deflate_draft
) {
560 opt_buf
[0] = CI_DEFLATE_DRAFT
;
561 opt_buf
[1] = CILEN_DEFLATE
;
562 opt_buf
[2] = DEFLATE_MAKE_OPT(DEFLATE_MIN_SIZE
+1);
563 opt_buf
[3] = DEFLATE_CHK_SEQUENCE
;
564 if (ccp_test(f
->unit
, opt_buf
, CILEN_DEFLATE
, 0) <= 0)
565 go
->deflate_draft
= 0;
567 if (!go
->deflate_correct
&& !go
->deflate_draft
)
570 if (go
->predictor_1
) {
571 opt_buf
[0] = CI_PREDICTOR_1
;
572 opt_buf
[1] = CILEN_PREDICTOR_1
;
573 if (ccp_test(f
->unit
, opt_buf
, CILEN_PREDICTOR_1
, 0) <= 0)
576 if (go
->predictor_2
) {
577 opt_buf
[0] = CI_PREDICTOR_2
;
578 opt_buf
[1] = CILEN_PREDICTOR_2
;
579 if (ccp_test(f
->unit
, opt_buf
, CILEN_PREDICTOR_2
, 0) <= 0)
585 * ccp_cilen - Return total length of our configuration info.
591 ccp_options
*go
= &ccp_gotoptions
[f
->unit
];
593 return (go
->bsd_compress
? CILEN_BSD_COMPRESS
: 0)
594 + (go
->deflate
&& go
->deflate_correct
? CILEN_DEFLATE
: 0)
595 + (go
->deflate
&& go
->deflate_draft
? CILEN_DEFLATE
: 0)
596 + (go
->predictor_1
? CILEN_PREDICTOR_1
: 0)
597 + (go
->predictor_2
? CILEN_PREDICTOR_2
: 0);
601 * ccp_addci - put our requests in a packet.
604 ccp_addci(f
, p
, lenp
)
610 ccp_options
*go
= &ccp_gotoptions
[f
->unit
];
614 * Add the compression types that we can receive, in decreasing
615 * preference order. Get the kernel to allocate the first one
616 * in case it gets Acked.
619 p
[0] = go
->deflate_correct
? CI_DEFLATE
: CI_DEFLATE_DRAFT
;
620 p
[1] = CILEN_DEFLATE
;
621 p
[2] = DEFLATE_MAKE_OPT(go
->deflate_size
);
622 p
[3] = DEFLATE_CHK_SEQUENCE
;
624 res
= ccp_test(f
->unit
, p
, CILEN_DEFLATE
, 0);
629 if (res
< 0 || go
->deflate_size
<= DEFLATE_MIN_SIZE
+1) {
634 p
[2] = DEFLATE_MAKE_OPT(go
->deflate_size
);
636 /* If we're offering both, then this is second. */
637 if (p
!= p0
&& go
->deflate_correct
&& go
->deflate_draft
) {
638 p
[0] = CI_DEFLATE_DRAFT
;
639 p
[1] = CILEN_DEFLATE
;
640 p
[2] = p
[2 - CILEN_DEFLATE
];
641 p
[3] = DEFLATE_CHK_SEQUENCE
;
645 if (go
->bsd_compress
) {
646 p
[0] = CI_BSD_COMPRESS
;
647 p
[1] = CILEN_BSD_COMPRESS
;
648 p
[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION
, go
->bsd_bits
);
650 p
+= CILEN_BSD_COMPRESS
; /* not the first option */
653 res
= ccp_test(f
->unit
, p
, CILEN_BSD_COMPRESS
, 0);
655 p
+= CILEN_BSD_COMPRESS
;
658 if (res
< 0 || go
->bsd_bits
<= BSD_MIN_BITS
) {
659 go
->bsd_compress
= 0;
663 p
[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION
, go
->bsd_bits
);
668 * Prefer Predictor-1 over Predictor-2. (The latter requires the use
669 * of LAP-B and has no known implementations.)
671 if (go
->predictor_1
) {
672 p
[0] = CI_PREDICTOR_1
;
673 p
[1] = CILEN_PREDICTOR_1
;
674 if (p
== p0
&& ccp_test(f
->unit
, p
, CILEN_PREDICTOR_1
, 0) <= 0) {
677 p
+= CILEN_PREDICTOR_1
;
680 if (go
->predictor_2
) {
681 p
[0] = CI_PREDICTOR_2
;
682 p
[1] = CILEN_PREDICTOR_2
;
683 if (p
== p0
&& ccp_test(f
->unit
, p
, CILEN_PREDICTOR_2
, 0) <= 0) {
686 p
+= CILEN_PREDICTOR_2
;
690 go
->method
= (p
> p0
)? p0
[0]: -1;
696 * ccp_ackci - process a received configure-ack, and return
697 * 1 iff the packet was OK.
705 ccp_options
*go
= &ccp_gotoptions
[f
->unit
];
708 if (go
->deflate
&& go
->deflate_correct
) {
709 if (len
< CILEN_DEFLATE
710 || p
[0] != CI_DEFLATE
|| p
[1] != CILEN_DEFLATE
711 || p
[2] != DEFLATE_MAKE_OPT(go
->deflate_size
)
712 || p
[3] != DEFLATE_CHK_SEQUENCE
)
714 /* Cope with non-standard first/fast ack */
715 if (p
== p0
&& len
== 0)
718 len
-= CILEN_DEFLATE
;
720 if (go
->deflate
&& go
->deflate_draft
) {
721 if (len
< CILEN_DEFLATE
722 || p
[0] != CI_DEFLATE_DRAFT
|| p
[1] != CILEN_DEFLATE
723 || p
[2] != DEFLATE_MAKE_OPT(go
->deflate_size
)
724 || p
[3] != DEFLATE_CHK_SEQUENCE
)
726 /* Cope with non-standard first/fast ack */
727 if (p
== p0
&& len
== 0)
730 len
-= CILEN_DEFLATE
;
732 if (go
->bsd_compress
) {
733 if (len
< CILEN_BSD_COMPRESS
734 || p
[0] != CI_BSD_COMPRESS
|| p
[1] != CILEN_BSD_COMPRESS
735 || p
[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION
, go
->bsd_bits
))
737 /* Cope with non-standard first/fast ack */
738 if (p
== p0
&& len
== 0)
740 p
+= CILEN_BSD_COMPRESS
;
741 len
-= CILEN_BSD_COMPRESS
;
743 if (go
->predictor_1
) {
744 if (len
< CILEN_PREDICTOR_1
745 || p
[0] != CI_PREDICTOR_1
|| p
[1] != CILEN_PREDICTOR_1
)
747 /* Cope with non-standard first/fast ack */
748 if (p
== p0
&& len
== 0)
750 p
+= CILEN_PREDICTOR_1
;
751 len
-= CILEN_PREDICTOR_1
;
753 if (go
->predictor_2
) {
754 if (len
< CILEN_PREDICTOR_2
755 || p
[0] != CI_PREDICTOR_2
|| p
[1] != CILEN_PREDICTOR_2
)
757 /* Cope with non-standard first/fast ack */
758 if (p
== p0
&& len
== 0)
760 p
+= CILEN_PREDICTOR_2
;
761 len
-= CILEN_PREDICTOR_2
;
764 /* Peer cannot ack something that wasn't sent. */
771 * ccp_nakci - process received configure-nak.
772 * Returns 1 iff the nak was OK.
780 ccp_options
*go
= &ccp_gotoptions
[f
->unit
];
781 ccp_options no
; /* options we've seen already */
782 ccp_options
try; /* options to ask for next time */
784 BZERO(&no
, sizeof(no
));
787 if (go
->deflate
&& go
->deflate_correct
&& len
>= CILEN_DEFLATE
&&
788 p
[0] == CI_DEFLATE
) {
791 * Peer wants us to use a different code size or something.
792 * Stop asking for Deflate if we don't understand its suggestion.
794 if (p
[1] != CILEN_DEFLATE
795 || DEFLATE_METHOD(p
[2]) != DEFLATE_METHOD_VAL
796 || DEFLATE_SIZE(p
[2]) <= DEFLATE_MIN_SIZE
797 || p
[3] != DEFLATE_CHK_SEQUENCE
)
798 try.deflate_correct
= 0;
799 else if (DEFLATE_SIZE(p
[2]) < go
->deflate_size
)
800 try.deflate_size
= DEFLATE_SIZE(p
[2]);
805 if (go
->deflate
&& go
->deflate_draft
&& len
>= CILEN_DEFLATE
&&
806 p
[0] == CI_DEFLATE_DRAFT
) {
809 * Peer wants us to use a different code size or something.
810 * Stop asking for Deflate using the old algorithm number if
811 * we don't understand its suggestion. (Note that this will
812 * happen if the peer is running Magnalink instead of
813 * old-style Deflate.)
815 if (p
[1] != CILEN_DEFLATE
816 || DEFLATE_METHOD(p
[2]) != DEFLATE_METHOD_VAL
817 || DEFLATE_SIZE(p
[2]) <= DEFLATE_MIN_SIZE
818 || p
[3] != DEFLATE_CHK_SEQUENCE
)
819 try.deflate_draft
= 0;
820 else if (DEFLATE_SIZE(p
[2]) < go
->deflate_size
)
821 try.deflate_size
= DEFLATE_SIZE(p
[2]);
826 if (!try.deflate_correct
&& !try.deflate_draft
)
829 if (go
->bsd_compress
&& len
>= CILEN_BSD_COMPRESS
&&
830 p
[0] == CI_BSD_COMPRESS
) {
833 * Peer wants us to use a different number of bits
834 * or a different version.
836 if (p
[1] != CILEN_BSD_COMPRESS
||
837 BSD_VERSION(p
[2]) != BSD_CURRENT_VERSION
)
838 try.bsd_compress
= 0;
839 else if (BSD_NBITS(p
[2]) < go
->bsd_bits
)
840 try.bsd_bits
= BSD_NBITS(p
[2]);
846 * Predictor-1 and 2 have no options, so they can't be Naked.
848 * There may be remaining options but we ignore them.
851 if (f
->state
!= OPENED
)
857 * ccp_rejci - peer rejects some of our suggested compression methods.
865 ccp_options
*go
= &ccp_gotoptions
[f
->unit
];
866 ccp_options
try; /* options to request next time */
871 * Cope with empty configure-rejects by ceasing to send
872 * configure-requests.
874 if (len
== 0 && all_rejected
[f
->unit
])
877 if (go
->deflate
&& go
->deflate_correct
&& len
>= CILEN_DEFLATE
&&
878 p
[0] == CI_DEFLATE
&& p
[1] == CILEN_DEFLATE
) {
879 if (p
[2] != DEFLATE_MAKE_OPT(go
->deflate_size
)
880 || p
[3] != DEFLATE_CHK_SEQUENCE
)
881 return 0; /* Rej is bad */
882 try.deflate_correct
= 0;
884 len
-= CILEN_DEFLATE
;
886 if (go
->deflate
&& go
->deflate_draft
&& len
>= CILEN_DEFLATE
&&
887 p
[0] == CI_DEFLATE_DRAFT
&& p
[1] == CILEN_DEFLATE
) {
888 if (p
[2] != DEFLATE_MAKE_OPT(go
->deflate_size
)
889 || p
[3] != DEFLATE_CHK_SEQUENCE
)
890 return 0; /* Rej is bad */
891 try.deflate_draft
= 0;
893 len
-= CILEN_DEFLATE
;
895 if (!try.deflate_correct
&& !try.deflate_draft
)
897 if (go
->bsd_compress
&& len
>= CILEN_BSD_COMPRESS
898 && p
[0] == CI_BSD_COMPRESS
&& p
[1] == CILEN_BSD_COMPRESS
) {
899 if (p
[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION
, go
->bsd_bits
))
901 try.bsd_compress
= 0;
902 p
+= CILEN_BSD_COMPRESS
;
903 len
-= CILEN_BSD_COMPRESS
;
905 if (go
->predictor_1
&& len
>= CILEN_PREDICTOR_1
906 && p
[0] == CI_PREDICTOR_1
&& p
[1] == CILEN_PREDICTOR_1
) {
908 p
+= CILEN_PREDICTOR_1
;
909 len
-= CILEN_PREDICTOR_1
;
911 if (go
->predictor_2
&& len
>= CILEN_PREDICTOR_2
912 && p
[0] == CI_PREDICTOR_2
&& p
[1] == CILEN_PREDICTOR_2
) {
914 p
+= CILEN_PREDICTOR_2
;
915 len
-= CILEN_PREDICTOR_2
;
921 if (f
->state
!= OPENED
)
928 * ccp_reqci - process a received configure-request.
930 * Returns CODE_CONFACK, CODE_CONFNAK or CODE_CONFREJ and the packet
931 * is modified appropriately.
934 ccp_reqci(f
, p
, lenp
, dont_nak
)
940 int ret
, newret
, res
;
941 u_char
*p0
, *nakp
, *rejp
, *pv
;
942 int len
, clen
, type
, nb
;
943 ccp_options
*ho
= &ccp_hisoptions
[f
->unit
];
944 ccp_options
*ao
= &ccp_allowoptions
[f
->unit
];
951 BZERO(ho
, sizeof(ccp_options
));
952 ho
->method
= (len
> 0)? p
[0]: -1;
954 for (; len
> 0; len
-= clen
, p
+= clen
) {
955 newret
= CODE_CONFACK
;
956 if (len
< 2 || p
[1] > len
) {
958 * RFC 1661 page 40 -- if the option extends beyond the
959 * packet, then discard the entire packet.
970 case CI_DEFLATE_DRAFT
:
972 (!ao
->deflate_correct
&& type
== CI_DEFLATE
) ||
973 (!ao
->deflate_draft
&& type
== CI_DEFLATE_DRAFT
)) {
974 newret
= CODE_CONFREJ
;
979 nb
= clen
< CILEN_DEFLATE
? ao
->deflate_size
: DEFLATE_SIZE(p
[2]);
980 ho
->deflate_size
= nb
;
981 if (clen
!= CILEN_DEFLATE
||
982 DEFLATE_METHOD(p
[2]) != DEFLATE_METHOD_VAL
||
983 p
[3] != DEFLATE_CHK_SEQUENCE
|| nb
> ao
->deflate_size
||
984 nb
<= DEFLATE_MIN_SIZE
) {
985 newret
= CODE_CONFNAK
;
988 if (nb
> ao
->deflate_size
)
989 nb
= ao
->deflate_size
;
990 else if (nb
<= DEFLATE_MIN_SIZE
)
991 nb
= DEFLATE_MIN_SIZE
+1;
994 PUTCHAR(CILEN_DEFLATE
, nakp
);
995 PUTCHAR(DEFLATE_MAKE_OPT(nb
), nakp
);
996 PUTCHAR(DEFLATE_CHK_SEQUENCE
, nakp
);
1000 * Check whether we can do Deflate with the window
1001 * size they want. If the window is too big, reduce
1002 * it until the kernel can cope and nak with that.
1003 * We only check this for the first option.
1007 res
= ccp_test(f
->unit
, pv
, CILEN_DEFLATE
, 1);
1009 break; /* it's OK now */
1010 if (res
< 0 || nb
<= DEFLATE_MIN_SIZE
+1 || dont_nak
) {
1011 newret
= CODE_CONFREJ
;
1014 if (newret
== CODE_CONFACK
) {
1015 BCOPY(pv
, nakp
, CILEN_DEFLATE
);
1017 nakp
+= CILEN_DEFLATE
;
1018 newret
= CODE_CONFNAK
;
1021 pv
[2] = DEFLATE_MAKE_OPT(nb
);
1024 /* Tune Deflate compression effort. */
1025 if (newret
== CODE_CONFACK
)
1026 ccp_tune(f
->unit
, deflate_tune
);
1031 case CI_BSD_COMPRESS
:
1032 if (!ao
->bsd_compress
) {
1033 newret
= CODE_CONFREJ
;
1037 ho
->bsd_compress
= 1;
1038 nb
= clen
< CILEN_BSD_COMPRESS
? ao
->bsd_bits
: BSD_NBITS(p
[2]);
1040 if (clen
!= CILEN_BSD_COMPRESS
||
1041 BSD_VERSION(p
[2]) != BSD_CURRENT_VERSION
||
1042 nb
> ao
->bsd_bits
|| nb
< BSD_MIN_BITS
) {
1043 newret
= CODE_CONFNAK
;
1046 if (nb
> ao
->bsd_bits
)
1048 else if (nb
< BSD_MIN_BITS
)
1051 PUTCHAR(type
, nakp
);
1052 PUTCHAR(CILEN_BSD_COMPRESS
, nakp
);
1053 PUTCHAR(BSD_MAKE_OPT(BSD_CURRENT_VERSION
, nb
), nakp
);
1057 * Check whether we can do BSD-Compress with the code
1058 * size they want. If the code size is too big, reduce
1059 * it until the kernel can cope and nak with that.
1060 * We only check this for the first option.
1064 res
= ccp_test(f
->unit
, pv
, CILEN_BSD_COMPRESS
, 1);
1067 if (res
< 0 || nb
== BSD_MIN_BITS
|| dont_nak
) {
1068 newret
= CODE_CONFREJ
;
1071 if (newret
== CODE_CONFACK
) {
1072 BCOPY(pv
, nakp
, CILEN_BSD_COMPRESS
);
1074 nakp
+= CILEN_BSD_COMPRESS
;
1075 newret
= CODE_CONFNAK
;
1078 pv
[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION
, nb
);
1083 case CI_PREDICTOR_1
:
1084 if (!ao
->predictor_1
) {
1085 newret
= CODE_CONFREJ
;
1089 ho
->predictor_1
= 1;
1090 if (clen
!= CILEN_PREDICTOR_1
) {
1091 newret
= CODE_CONFNAK
;
1095 PUTCHAR(type
, nakp
);
1096 PUTCHAR(CILEN_PREDICTOR_1
, nakp
);
1099 ccp_test(f
->unit
, pv
, CILEN_PREDICTOR_1
, 1) <= 0) {
1100 newret
= CODE_CONFREJ
;
1104 case CI_PREDICTOR_2
:
1105 if (!ao
->predictor_2
) {
1106 newret
= CODE_CONFREJ
;
1110 ho
->predictor_2
= 1;
1111 if (clen
!= CILEN_PREDICTOR_2
) {
1112 newret
= CODE_CONFNAK
;
1116 PUTCHAR(type
, nakp
);
1117 PUTCHAR(CILEN_PREDICTOR_2
, nakp
);
1120 ccp_test(f
->unit
, p
, CILEN_PREDICTOR_2
, 1) <= 0) {
1121 newret
= CODE_CONFREJ
;
1126 newret
= CODE_CONFREJ
;
1130 /* Cope with confused peers. */
1134 if (newret
== CODE_CONFACK
&& ret
!= CODE_CONFACK
)
1136 if (newret
== CODE_CONFNAK
) {
1138 newret
= CODE_CONFREJ
;
1140 /* Ignore subsequent nakable things if rejecting. */
1141 if (ret
== CODE_CONFREJ
)
1146 if (newret
== CODE_CONFREJ
) {
1149 BCOPY(p
, rejp
, clen
);
1159 *lenp
= nakp
- nak_buffer
;
1160 BCOPY(nak_buffer
, p0
, *lenp
);
1170 * Make a string name for a compression method (or 2).
1173 method_name(opt
, opt2
)
1174 ccp_options
*opt
, *opt2
;
1176 static char result
[64];
1178 if (!ANY_COMPRESS(*opt
))
1180 switch (opt
->method
) {
1182 case CI_DEFLATE_DRAFT
:
1183 if (opt2
!= NULL
&& opt2
->deflate_size
!= opt
->deflate_size
)
1184 (void) slprintf(result
, sizeof(result
), "Deflate%s (%d/%d)",
1185 (opt
->method
== CI_DEFLATE_DRAFT
? "(old#)": ""),
1186 opt
->deflate_size
, opt2
->deflate_size
);
1188 (void) slprintf(result
, sizeof(result
), "Deflate%s (%d)",
1189 (opt
->method
== CI_DEFLATE_DRAFT
? "(old#)": ""),
1192 case CI_BSD_COMPRESS
:
1193 if (opt2
!= NULL
&& opt2
->bsd_bits
!= opt
->bsd_bits
)
1194 (void) slprintf(result
, sizeof(result
), "BSD-Compress (%d/%d)",
1195 opt
->bsd_bits
, opt2
->bsd_bits
);
1197 (void) slprintf(result
, sizeof(result
), "BSD-Compress (%d)",
1200 case CI_PREDICTOR_1
:
1201 return "Predictor 1";
1202 case CI_PREDICTOR_2
:
1203 return "Predictor 2";
1213 (void) slprintf(result
, sizeof(result
), "Method %d", opt
->method
);
1219 * CCP has come up - inform the kernel driver and log a message.
1225 ccp_options
*go
= &ccp_gotoptions
[f
->unit
];
1226 ccp_options
*ho
= &ccp_hisoptions
[f
->unit
];
1230 * We're now open and up (running).
1232 ccp_flags_set(f
->unit
, 1, 1);
1233 if (ANY_COMPRESS(*go
)) {
1234 if (ANY_COMPRESS(*ho
)) {
1235 if (go
->method
== ho
->method
) {
1236 notice("%s compression enabled", method_name(go
, ho
));
1238 (void) strlcpy(method1
, method_name(go
, NULL
), sizeof(method1
));
1239 notice("%s / %s compression enabled",
1240 method1
, method_name(ho
, NULL
));
1243 notice("%s receive decompression enabled", method_name(go
, NULL
));
1244 } else if (ANY_COMPRESS(*ho
))
1245 notice("%s transmit compression enabled", method_name(ho
, NULL
));
1249 * CCP has gone down - inform the kernel driver.
1255 if (ccp_localstate
[f
->unit
] & RACK_PENDING
)
1256 UNTIMEOUT(ccp_rack_timeout
, f
);
1257 /* Don't forget about peer's code rejects or ignoring of requests. */
1258 ccp_localstate
[f
->unit
] &= ~RACK_PENDING
& ~RREQ_REPEAT
;
1259 /* We're still open, but no longer up. */
1260 ccp_flags_set(f
->unit
, 1, 0);
1264 ccp_printpkt(p
, plen
, printer
, arg
)
1267 void (*printer
) __P((void *, const char *, ...));
1270 u_char
*p0
, *optend
, cichar
;
1279 if (plen
< HEADERLEN
) {
1280 printer(arg
, "too short (%d<%d)", plen
, HEADERLEN
);
1287 printer(arg
, " %s id=0x%x", code_name(code
, 1), id
);
1289 if (len
< HEADERLEN
) {
1290 printer(arg
, " header length %d<%d", len
, HEADERLEN
);
1294 printer(arg
, " truncated (%d>%d)", len
, plen
);
1304 /* print list of possible compression methods */
1315 optend
= p
+ optlen
- 2;
1318 case CI_DEFLATE_DRAFT
:
1319 printer(arg
, "deflate%s",
1320 (code
== CI_DEFLATE_DRAFT
? "(old#)": ""));
1321 if (clen
!= CILEN_DEFLATE
)
1322 printer(arg
, " length %d", clen
);
1323 if (optlen
>= CILEN_DEFLATE
) {
1325 printer(arg
, " %d", DEFLATE_SIZE(cichar
));
1326 if (DEFLATE_METHOD(cichar
) != DEFLATE_METHOD_VAL
)
1327 printer(arg
, " method %d", DEFLATE_METHOD(cichar
));
1329 if (cichar
!= DEFLATE_CHK_SEQUENCE
)
1330 printer(arg
, " check %d", cichar
);
1333 case CI_BSD_COMPRESS
:
1334 printer(arg
, "bsd");
1335 if (clen
!= CILEN_BSD_COMPRESS
)
1336 printer(arg
, " length %d", clen
);
1337 if (optlen
>= CILEN_BSD_COMPRESS
) {
1339 printer(arg
, " v%d %d", BSD_VERSION(cichar
),
1343 case CI_PREDICTOR_1
:
1344 printer(arg
, "predictor-1");
1345 if (clen
!= CILEN_PREDICTOR_1
)
1346 printer(arg
, " length %d", clen
);
1348 case CI_PREDICTOR_2
:
1349 printer(arg
, "predictor-2");
1350 if (clen
!= CILEN_PREDICTOR_2
)
1351 printer(arg
, " length %d", clen
);
1355 printer(arg
, "Stac");
1356 if (clen
!= CILEN_STAC
)
1357 printer(arg
, " length %d", clen
);
1358 if (optlen
>= CILEN_STAC
) {
1359 GETSHORT(cishort
, p
);
1361 printer(arg
, " h%d/m%d", cishort
, cichar
);
1367 /* There appears to be no good generic name for this one. */
1368 if (optlen
>= CILEN_MPPC
) {
1370 if (!(cilong
& MPPC_COMP
)) {
1371 if (cilong
& MPPC_MPPE
)
1372 printer(arg
, "MPPE");
1374 printer(arg
, "MS-PPC?");
1376 if (cilong
& MPPC_MPPE
)
1377 printer(arg
, "MPPC+MPPE");
1379 printer(arg
, "MPPC");
1382 printer(arg
, "MS-?");
1384 if (clen
!= CILEN_STAC
)
1385 printer(arg
, " length %d", clen
);
1389 printer(arg
, "typ%d len%d ", code
, clen
);
1394 printer(arg
, " %.8B ...", p
);
1396 printer(arg
, " %.*B", optend
-p
, p
);
1407 GETSHORT(cishort
, p
);
1408 printer(arg
, " history %d", cishort
);
1410 } else if (*p
>= ' ' && *p
< 0x7f) {
1412 print_string((char *)p
, len
, printer
, arg
);
1420 /* dump out the rest of the packet in hex */
1423 printer(arg
, " %.8B ...", p
);
1425 printer(arg
, " %.*B", len
, p
);
1433 * We have received a packet that the decompressor failed to
1434 * decompress. Here we would expect to issue a reset-request, but
1435 * Motorola has a patent on resetting the compressor as a result of
1436 * detecting an error in the decompressed data after decompression.
1437 * (See US patent 5,130,993; international patent publication number
1438 * WO 91/10289; Australian patent 73296/91.)
1440 * So we ask the kernel whether the error was detected after
1441 * decompression; if it was, we take CCP down, thus disabling
1442 * compression :-(, otherwise we issue the reset-request.
1446 ccp_datainput(unit
, pkt
, len
)
1454 if (f
->state
== OPENED
) {
1455 if (ccp_fatal_error(unit
)) {
1457 * Disable compression by taking CCP down.
1459 error("Lost compression sync: disabling compression");
1460 ccp_close(unit
, "Lost compression sync");
1463 * Send a reset-request to reset the peer's compressor, if
1464 * possible. We don't do anything if we are still waiting
1465 * for an acknowledgement to a previous reset-request (to
1466 * avoid flooding the peer). We reopen CCP if the peer
1467 * doesn't like hearing about CCP Reset-Request (Cisco
1468 * sends CCP Code-Reject for Reset-Request). (Reopen
1469 * automatically clears the flags and cancels the
1472 if (ccp_localstate
[f
->unit
] & RREQ_REJECTED
) {
1473 dbglog("reopening CCP to reset peer's compressor");
1475 } else if (ccp_localstate
[f
->unit
] & RACK_PENDING
) {
1476 /* Send another reset request; we're out of sequence. */
1477 ccp_localstate
[f
->unit
] |= RREQ_REPEAT
;
1479 dbglog("sending CCP Reset-Request to reset peer's compressor");
1480 fsm_sdata(f
, CCP_RESETREQ
, f
->reqid
= ++f
->id
, NULL
, 0);
1481 TIMEOUT(ccp_rack_timeout
, f
, RACKTIMEOUT
);
1482 ccp_localstate
[f
->unit
] |= RACK_PENDING
;
1489 * Timeout waiting for reset-ack.
1492 ccp_rack_timeout(arg
)
1497 /* Timeout; no longer pending. */
1498 ccp_localstate
[f
->unit
] &= ~RACK_PENDING
;
1500 /* Frankly, it's a coding flaw if this occurs. */
1501 if (f
->state
!= OPENED
)
1504 if (ccp_localstate
[f
->unit
] & RREQ_IGNORED
) {
1505 info("peer ignored our CCP Reset-Request twice; reopen instead");
1506 ccp_localstate
[f
->unit
] =
1507 (ccp_localstate
[f
->unit
] & ~RREQ_IGNORED
) | RREQ_REJECTED
;
1509 } else if (ccp_localstate
[f
->unit
] & RREQ_REPEAT
) {
1510 dbglog("sending another CCP Reset-Request on timeout");
1511 fsm_sdata(f
, CCP_RESETREQ
, f
->reqid
, NULL
, 0);
1512 TIMEOUT(ccp_rack_timeout
, f
, RACKTIMEOUT
);
1513 ccp_localstate
[f
->unit
] =
1514 (ccp_localstate
[f
->unit
] & ~RREQ_REPEAT
) | RREQ_IGNORED
|
1517 dbglog("timeout waiting for CCP Reset-Ack; hope for the best");
1518 ccp_localstate
[f
->unit
] |= RREQ_IGNORED
;