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 static const char rcsid
[] = RCSID
;
48 * Command-line options.
50 static int setbsdcomp
__P((char **, option_t
*));
51 static int setdeflate
__P((char **, option_t
*));
53 static option_t ccp_option_list
[] = {
54 { "noccp", o_bool
, &ccp_protent
.enabled_flag
,
55 "Disable CCP negotiation" },
56 { "-ccp", o_bool
, &ccp_protent
.enabled_flag
,
57 "Disable CCP negotiation" },
58 { "bsdcomp", o_special
, (void *)setbsdcomp
,
59 "Request BSD-Compress packet compression" },
60 { "nobsdcomp", o_bool
, &ccp_wantoptions
[0].bsd_compress
,
61 "don't allow BSD-Compress", OPT_A2COPY
,
62 &ccp_allowoptions
[0].bsd_compress
},
63 { "-bsdcomp", o_bool
, &ccp_wantoptions
[0].bsd_compress
,
64 "don't allow BSD-Compress", OPT_A2COPY
,
65 &ccp_allowoptions
[0].bsd_compress
},
66 { "deflate", o_special
, (void *)setdeflate
,
67 "request Deflate compression" },
68 { "nodeflate", o_bool
, &ccp_wantoptions
[0].deflate
,
69 "don't allow Deflate compression", OPT_A2COPY
,
70 &ccp_allowoptions
[0].deflate
},
71 { "-deflate", o_bool
, &ccp_wantoptions
[0].deflate
,
72 "don't allow Deflate compression", OPT_A2COPY
,
73 &ccp_allowoptions
[0].deflate
},
74 { "nodeflatedraft", o_bool
, &ccp_wantoptions
[0].deflate_draft
,
75 "don't use draft deflate #", OPT_A2COPY
,
76 &ccp_allowoptions
[0].deflate_draft
},
77 { "predictor1", o_bool
, &ccp_wantoptions
[0].predictor_1
,
78 "request Predictor-1", 1, &ccp_allowoptions
[0].predictor_1
},
79 { "nopredictor1", o_bool
, &ccp_wantoptions
[0].predictor_1
,
80 "don't allow Predictor-1", OPT_A2COPY
,
81 &ccp_allowoptions
[0].predictor_1
},
82 { "-predictor1", o_bool
, &ccp_wantoptions
[0].predictor_1
,
83 "don't allow Predictor-1", OPT_A2COPY
,
84 &ccp_allowoptions
[0].predictor_1
},
90 * Protocol entry points from main code.
92 static void ccp_init
__P((int unit
));
93 static void ccp_open
__P((int unit
));
94 static void ccp_close
__P((int unit
, char *));
95 static void ccp_lowerup
__P((int unit
));
96 static void ccp_lowerdown
__P((int));
97 static void ccp_input
__P((int unit
, u_char
*pkt
, int len
));
98 static void ccp_protrej
__P((int unit
));
99 static int ccp_printpkt
__P((u_char
*pkt
, int len
,
100 void (*printer
) __P((void *, const char *, ...)),
102 static void ccp_datainput
__P((int unit
, u_char
*pkt
, int len
));
104 struct protent ccp_protent
= {
124 fsm ccp_fsm
[NUM_PPP
];
125 ccp_options ccp_wantoptions
[NUM_PPP
]; /* what to request the peer to use */
126 ccp_options ccp_gotoptions
[NUM_PPP
]; /* what the peer agreed to do */
127 ccp_options ccp_allowoptions
[NUM_PPP
]; /* what we'll agree to do */
128 ccp_options ccp_hisoptions
[NUM_PPP
]; /* what we agreed to do */
131 * Callbacks for fsm code.
133 static void ccp_resetci
__P((fsm
*));
134 static int ccp_cilen
__P((fsm
*));
135 static void ccp_addci
__P((fsm
*, u_char
*, int *));
136 static int ccp_ackci
__P((fsm
*, u_char
*, int));
137 static int ccp_nakci
__P((fsm
*, u_char
*, int));
138 static int ccp_rejci
__P((fsm
*, u_char
*, int));
139 static int ccp_reqci
__P((fsm
*, u_char
*, int *, int));
140 static void ccp_up
__P((fsm
*));
141 static void ccp_down
__P((fsm
*));
142 static int ccp_extcode
__P((fsm
*, int, int, u_char
*, int));
143 static int ccp_codereject
__P((fsm
*p
, int code
, int id
, u_char
*inp
,
146 static fsm_callbacks ccp_callbacks
= {
147 ccp_resetci
, /* Reset our Configuration Information */
148 ccp_cilen
, /* Length of our Configuration Information */
149 ccp_addci
, /* Add our Configuration Information */
150 ccp_ackci
, /* ACK our Configuration Information */
151 ccp_nakci
, /* NAK our Configuration Information */
152 ccp_rejci
, /* Reject our Configuration Information */
153 ccp_reqci
, /* Request peer's Configuration Information */
154 ccp_up
, /* Called when fsm reaches OPENED state */
155 ccp_down
, /* Called when fsm leaves OPENED state */
156 NULL
, /* Called when we want the lower layer up */
157 NULL
, /* Called when we want the lower layer down */
158 NULL
, /* Retransmission is necessary */
159 ccp_extcode
, /* Called to handle LCP-specific codes */
160 "CCP", /* String name of protocol */
161 ccp_codereject
, /* Peer rejected a code number */
167 static void ccp_rack_timeout
__P((void *));
168 static char * method_name
__P((ccp_options
*, ccp_options
*));
171 * Do we want / did we get any compression?
173 #define ANY_COMPRESS(opt) ((opt).deflate || (opt).bsd_compress \
174 || (opt).predictor_1 || (opt).predictor_2)
177 * Local state (mainly for handling reset-reqs and reset-acks).
179 static int ccp_localstate
[NUM_PPP
];
180 #define RACK_PENDING 0x0001 /* waiting for reset-ack */
181 #define RREQ_REPEAT 0x0002 /* send another reset-req if no reset-ack */
182 #define RREQ_REJECTED 0x0004 /* peer code-rejected reset-request */
183 #define RACK_REJECTED 0x0008 /* peer code-rejected reset-ack */
184 #define RREQ_IGNORED 0x0010 /* peer just ignored reset-request */
186 #define RACKTIMEOUT 1 /* time in seconds between Reset-Requests */
188 static int all_rejected
[NUM_PPP
]; /* we rejected all peer's options */
191 static int deflate_tune
= -1; /* compression effort level for deflate */
193 static int deflate_rmax
= DEFLATE_MAX_SIZE
; /* max rbits */
194 static int deflate_amax
= DEFLATE_MAX_SIZE
; /* max abits */
201 setbsdcomp(argv
, opt
)
209 abits
= rbits
= strtol(str
, &endp
, 0);
210 if (endp
!= str
&& *endp
== ',') {
212 abits
= strtol(str
, &endp
, 0);
214 if (*endp
!= '\0' || endp
== str
) {
215 option_error("invalid parameter '%s' for bsdcomp option", *argv
);
218 if ((rbits
!= 0 && (rbits
< BSD_MIN_BITS
|| rbits
> BSD_MAX_BITS
))
219 || (abits
!= 0 && (abits
< BSD_MIN_BITS
|| abits
> BSD_MAX_BITS
))) {
220 option_error("bsdcomp option values must be 0 or %d .. %d",
221 BSD_MIN_BITS
, BSD_MAX_BITS
);
225 ccp_wantoptions
[0].bsd_compress
= 1;
226 ccp_wantoptions
[0].bsd_bits
= rbits
;
228 ccp_wantoptions
[0].bsd_compress
= 0;
230 ccp_allowoptions
[0].bsd_compress
= 1;
231 ccp_allowoptions
[0].bsd_bits
= abits
;
233 ccp_allowoptions
[0].bsd_compress
= 0;
239 setdeflate(argv
, opt
)
243 int rbits
, abits
, def_rmax
, def_amax
;
250 abits
= rbits
= strtol(str
, &endp
, 0);
256 abits
= strtol(str
, &endp
, 0);
259 if (*endp
== ',' && privileged_option
) {
261 deflate_tune
= strtol(str
, &endp
, 0);
264 if (*endp
!= '\0' || endp
== str
) {
265 option_error("invalid parameter '%s' for deflate option", *argv
);
268 if (privileged_option
) {
269 def_rmax
= def_amax
= DEFLATE_MAX_SIZE
;
271 def_rmax
= deflate_rmax
;
272 def_amax
= deflate_amax
;
278 if ((rbits
!= 0 && (rbits
<= DEFLATE_MIN_SIZE
|| rbits
> def_rmax
))
279 || (abits
!= 0 && (abits
<= DEFLATE_MIN_SIZE
|| abits
> def_amax
))) {
280 option_error("deflate option values must be 0 or {%d,%d} .. {%d,%d}",
281 DEFLATE_MIN_SIZE
+1, DEFLATE_MIN_SIZE
+1,
285 if (privileged_option
) {
286 deflate_rmax
= rbits
;
287 deflate_amax
= abits
;
290 ccp_wantoptions
[0].deflate
= 1;
291 ccp_wantoptions
[0].deflate_size
= rbits
;
293 ccp_wantoptions
[0].deflate
= 0;
295 ccp_allowoptions
[0].deflate
= 1;
296 ccp_allowoptions
[0].deflate_size
= abits
;
298 ccp_allowoptions
[0].deflate
= 0;
304 * ccp_init - initialize CCP.
310 fsm
*f
= &ccp_fsm
[unit
];
313 f
->protocol
= PPP_CCP
;
314 f
->callbacks
= &ccp_callbacks
;
316 f
->flags
|= OPT_RESTART
;
318 BZERO(&ccp_wantoptions
[unit
], sizeof(ccp_options
));
319 BZERO(&ccp_gotoptions
[unit
], sizeof(ccp_options
));
320 BZERO(&ccp_allowoptions
[unit
], sizeof(ccp_options
));
321 BZERO(&ccp_hisoptions
[unit
], sizeof(ccp_options
));
323 ccp_wantoptions
[0].deflate
= 1;
324 ccp_wantoptions
[0].deflate_size
= DEFLATE_MAX_SIZE
;
325 ccp_wantoptions
[0].deflate_correct
= 1;
326 ccp_wantoptions
[0].deflate_draft
= 1;
327 ccp_allowoptions
[0].deflate
= 1;
328 ccp_allowoptions
[0].deflate_size
= DEFLATE_MAX_SIZE
;
329 ccp_allowoptions
[0].deflate_correct
= 1;
330 ccp_allowoptions
[0].deflate_draft
= 1;
332 ccp_wantoptions
[0].bsd_compress
= 1;
333 ccp_wantoptions
[0].bsd_bits
= BSD_MAX_BITS
;
334 ccp_allowoptions
[0].bsd_compress
= 1;
335 ccp_allowoptions
[0].bsd_bits
= BSD_MAX_BITS
;
337 ccp_allowoptions
[0].predictor_1
= 1;
341 * ccp_open - CCP is allowed to come up.
347 fsm
*f
= &ccp_fsm
[unit
];
350 * If we haven't gone open yet (first time through), then go open
351 * but not up. Otherwise, skip this to allow reopen to reset the
354 if (f
->state
!= OPENED
)
355 ccp_flags_set(unit
, 1, 0);
358 * Find out which compressors the kernel supports before
359 * deciding whether to open in silent mode.
362 if (!ANY_COMPRESS(ccp_gotoptions
[unit
]))
363 f
->flags
|= OPT_SILENT
;
369 * ccp_close - Terminate CCP.
372 ccp_close(unit
, reason
)
376 ccp_flags_set(unit
, 0, 0);
377 fsm_close(&ccp_fsm
[unit
], reason
);
381 * ccp_lowerup - we may now transmit CCP packets.
387 fsm_lowerup(&ccp_fsm
[unit
]);
391 * ccp_lowerdown - we may not transmit CCP packets.
397 fsm_lowerdown(&ccp_fsm
[unit
]);
401 * ccp_input - process a received CCP packet.
404 ccp_input(unit
, p
, len
)
409 fsm
*f
= &ccp_fsm
[unit
];
413 * Check for a terminate-request so we can print a message.
416 fsm_input(f
, p
, len
);
417 if (oldstate
== OPENED
&& p
[0] == CODE_TERMREQ
&& f
->state
!= OPENED
)
418 notice("Compression disabled by peer.");
421 * If we get a terminate-ack and we're not asking for compression,
422 * close CCP. (Terminate-Request is handled by fsm_input() above.)
424 if (oldstate
== REQSENT
&& p
[0] == CODE_TERMACK
425 && !ANY_COMPRESS(ccp_gotoptions
[unit
]))
426 ccp_close(unit
, "No compression negotiated");
430 * Handle a CCP-specific code.
433 ccp_extcode(f
, code
, id
, p
, len
)
441 /* If not open, then silently ignore. */
442 if (f
->state
!= OPENED
)
444 /* send a reset-ack, which our transmitter module will see and
445 reset its compression state. */
446 fsm_sdata(f
, CCP_RESETACK
, id
, p
, len
);
451 * Note that the compression module isn't picky about ID
454 ccp_localstate
[f
->unit
] &= ~RREQ_IGNORED
& ~RREQ_REJECTED
;
455 if ((ccp_localstate
[f
->unit
] & RACK_PENDING
) && id
== f
->reqid
) {
456 ccp_localstate
[f
->unit
] &= ~RACK_PENDING
& ~RREQ_REPEAT
;
457 UNTIMEOUT(ccp_rack_timeout
, f
);
462 /* Tell fsm to send code reject */
470 * Handle Code-Reject for one of our extended codes by dropping back to
471 * reopen as mechanism to restart compression.
475 ccp_codereject(f
, code
, id
, inp
, len
)
483 if (!(ccp_localstate
[f
->unit
] & RREQ_REJECTED
)) {
484 info("peer has rejected CCP Reset-Request; falling back on Open");
485 if (f
->state
== OPENED
)
488 ccp_localstate
[f
->unit
] |= RREQ_REJECTED
;
493 * Peer must have sent us CCP Reset-Request but then code-rejected when
494 * we sent CCP Reset-Ack. It seems to have changed its mind, and we
495 * have to obey its wishes.
497 ccp_localstate
[f
->unit
] |= RACK_REJECTED
;
498 notice("peer has erroneously rejected CCP Reset-Ack");
499 f
->term_reason
= "peer sent Code-Reject for CCP Reset-Ack";
500 f
->term_reason_len
= strlen(f
->term_reason
);
504 f
->term_reason
= "peer sent invalid Code-Reject";
508 f
->term_reason_len
= strlen(f
->term_reason
);
513 * ccp_protrej - peer doesn't talk CCP.
519 /* Neither open nor up. */
520 ccp_flags_set(unit
, 0, 0);
521 fsm_lowerdown(&ccp_fsm
[unit
]);
525 * ccp_resetci - initialize at start of negotiation.
531 ccp_options
*go
= &ccp_gotoptions
[f
->unit
];
534 *go
= ccp_wantoptions
[f
->unit
];
535 all_rejected
[f
->unit
] = 0;
538 * Check whether the kernel knows about the various
539 * decompression methods we might request.
541 if (go
->bsd_compress
) {
542 opt_buf
[0] = CI_BSD_COMPRESS
;
543 opt_buf
[1] = CILEN_BSD_COMPRESS
;
544 opt_buf
[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION
, BSD_MIN_BITS
);
545 if (ccp_test(f
->unit
, opt_buf
, CILEN_BSD_COMPRESS
, 0) <= 0)
546 go
->bsd_compress
= 0;
549 if (go
->deflate_correct
) {
550 opt_buf
[0] = CI_DEFLATE
;
551 opt_buf
[1] = CILEN_DEFLATE
;
552 opt_buf
[2] = DEFLATE_MAKE_OPT(DEFLATE_MIN_SIZE
+1);
553 opt_buf
[3] = DEFLATE_CHK_SEQUENCE
;
554 if (ccp_test(f
->unit
, opt_buf
, CILEN_DEFLATE
, 0) <= 0)
555 go
->deflate_correct
= 0;
557 if (go
->deflate_draft
) {
558 opt_buf
[0] = CI_DEFLATE_DRAFT
;
559 opt_buf
[1] = CILEN_DEFLATE
;
560 opt_buf
[2] = DEFLATE_MAKE_OPT(DEFLATE_MIN_SIZE
+1);
561 opt_buf
[3] = DEFLATE_CHK_SEQUENCE
;
562 if (ccp_test(f
->unit
, opt_buf
, CILEN_DEFLATE
, 0) <= 0)
563 go
->deflate_draft
= 0;
565 if (!go
->deflate_correct
&& !go
->deflate_draft
)
568 if (go
->predictor_1
) {
569 opt_buf
[0] = CI_PREDICTOR_1
;
570 opt_buf
[1] = CILEN_PREDICTOR_1
;
571 if (ccp_test(f
->unit
, opt_buf
, CILEN_PREDICTOR_1
, 0) <= 0)
574 if (go
->predictor_2
) {
575 opt_buf
[0] = CI_PREDICTOR_2
;
576 opt_buf
[1] = CILEN_PREDICTOR_2
;
577 if (ccp_test(f
->unit
, opt_buf
, CILEN_PREDICTOR_2
, 0) <= 0)
583 * ccp_cilen - Return total length of our configuration info.
589 ccp_options
*go
= &ccp_gotoptions
[f
->unit
];
591 return (go
->bsd_compress
? CILEN_BSD_COMPRESS
: 0)
592 + (go
->deflate
&& go
->deflate_correct
? CILEN_DEFLATE
: 0)
593 + (go
->deflate
&& go
->deflate_draft
? CILEN_DEFLATE
: 0)
594 + (go
->predictor_1
? CILEN_PREDICTOR_1
: 0)
595 + (go
->predictor_2
? CILEN_PREDICTOR_2
: 0);
599 * ccp_addci - put our requests in a packet.
602 ccp_addci(f
, p
, lenp
)
608 ccp_options
*go
= &ccp_gotoptions
[f
->unit
];
612 * Add the compression types that we can receive, in decreasing
613 * preference order. Get the kernel to allocate the first one
614 * in case it gets Acked.
617 p
[0] = go
->deflate_correct
? CI_DEFLATE
: CI_DEFLATE_DRAFT
;
618 p
[1] = CILEN_DEFLATE
;
619 p
[2] = DEFLATE_MAKE_OPT(go
->deflate_size
);
620 p
[3] = DEFLATE_CHK_SEQUENCE
;
622 res
= ccp_test(f
->unit
, p
, CILEN_DEFLATE
, 0);
627 if (res
< 0 || go
->deflate_size
<= DEFLATE_MIN_SIZE
+1) {
632 p
[2] = DEFLATE_MAKE_OPT(go
->deflate_size
);
634 /* If we're offering both, then this is second. */
635 if (p
!= p0
&& go
->deflate_correct
&& go
->deflate_draft
) {
636 p
[0] = CI_DEFLATE_DRAFT
;
637 p
[1] = CILEN_DEFLATE
;
638 p
[2] = p
[2 - CILEN_DEFLATE
];
639 p
[3] = DEFLATE_CHK_SEQUENCE
;
643 if (go
->bsd_compress
) {
644 p
[0] = CI_BSD_COMPRESS
;
645 p
[1] = CILEN_BSD_COMPRESS
;
646 p
[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION
, go
->bsd_bits
);
648 p
+= CILEN_BSD_COMPRESS
; /* not the first option */
651 res
= ccp_test(f
->unit
, p
, CILEN_BSD_COMPRESS
, 0);
653 p
+= CILEN_BSD_COMPRESS
;
656 if (res
< 0 || go
->bsd_bits
<= BSD_MIN_BITS
) {
657 go
->bsd_compress
= 0;
661 p
[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION
, go
->bsd_bits
);
666 * Prefer Predictor-1 over Predictor-2. (The latter requires the use
667 * of LAP-B and has no known implementations.)
669 if (go
->predictor_1
) {
670 p
[0] = CI_PREDICTOR_1
;
671 p
[1] = CILEN_PREDICTOR_1
;
672 if (p
== p0
&& ccp_test(f
->unit
, p
, CILEN_PREDICTOR_1
, 0) <= 0) {
675 p
+= CILEN_PREDICTOR_1
;
678 if (go
->predictor_2
) {
679 p
[0] = CI_PREDICTOR_2
;
680 p
[1] = CILEN_PREDICTOR_2
;
681 if (p
== p0
&& ccp_test(f
->unit
, p
, CILEN_PREDICTOR_2
, 0) <= 0) {
684 p
+= CILEN_PREDICTOR_2
;
688 go
->method
= (p
> p0
)? p0
[0]: -1;
694 * ccp_ackci - process a received configure-ack, and return
695 * 1 iff the packet was OK.
703 ccp_options
*go
= &ccp_gotoptions
[f
->unit
];
706 if (go
->deflate
&& go
->deflate_correct
) {
707 if (len
< CILEN_DEFLATE
708 || p
[0] != CI_DEFLATE
|| p
[1] != CILEN_DEFLATE
709 || p
[2] != DEFLATE_MAKE_OPT(go
->deflate_size
)
710 || p
[3] != DEFLATE_CHK_SEQUENCE
)
712 /* Cope with non-standard first/fast ack */
713 if (p
== p0
&& len
== 0)
716 len
-= CILEN_DEFLATE
;
718 if (go
->deflate
&& go
->deflate_draft
) {
719 if (len
< CILEN_DEFLATE
720 || p
[0] != CI_DEFLATE_DRAFT
|| p
[1] != CILEN_DEFLATE
721 || p
[2] != DEFLATE_MAKE_OPT(go
->deflate_size
)
722 || p
[3] != DEFLATE_CHK_SEQUENCE
)
724 /* Cope with non-standard first/fast ack */
725 if (p
== p0
&& len
== 0)
728 len
-= CILEN_DEFLATE
;
730 if (go
->bsd_compress
) {
731 if (len
< CILEN_BSD_COMPRESS
732 || p
[0] != CI_BSD_COMPRESS
|| p
[1] != CILEN_BSD_COMPRESS
733 || p
[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION
, go
->bsd_bits
))
735 /* Cope with non-standard first/fast ack */
736 if (p
== p0
&& len
== 0)
738 p
+= CILEN_BSD_COMPRESS
;
739 len
-= CILEN_BSD_COMPRESS
;
741 if (go
->predictor_1
) {
742 if (len
< CILEN_PREDICTOR_1
743 || p
[0] != CI_PREDICTOR_1
|| p
[1] != CILEN_PREDICTOR_1
)
745 /* Cope with non-standard first/fast ack */
746 if (p
== p0
&& len
== 0)
748 p
+= CILEN_PREDICTOR_1
;
749 len
-= CILEN_PREDICTOR_1
;
751 if (go
->predictor_2
) {
752 if (len
< CILEN_PREDICTOR_2
753 || p
[0] != CI_PREDICTOR_2
|| p
[1] != CILEN_PREDICTOR_2
)
755 /* Cope with non-standard first/fast ack */
756 if (p
== p0
&& len
== 0)
758 p
+= CILEN_PREDICTOR_2
;
759 len
-= CILEN_PREDICTOR_2
;
762 /* Peer cannot ack something that wasn't sent. */
769 * ccp_nakci - process received configure-nak.
770 * Returns 1 iff the nak was OK.
778 ccp_options
*go
= &ccp_gotoptions
[f
->unit
];
779 ccp_options no
; /* options we've seen already */
780 ccp_options
try; /* options to ask for next time */
782 BZERO(&no
, sizeof(no
));
785 if (go
->deflate
&& go
->deflate_correct
&& len
>= CILEN_DEFLATE
&&
786 p
[0] == CI_DEFLATE
) {
789 * Peer wants us to use a different code size or something.
790 * Stop asking for Deflate if we don't understand its suggestion.
792 if (p
[1] != CILEN_DEFLATE
793 || DEFLATE_METHOD(p
[2]) != DEFLATE_METHOD_VAL
794 || DEFLATE_SIZE(p
[2]) <= DEFLATE_MIN_SIZE
795 || p
[3] != DEFLATE_CHK_SEQUENCE
)
796 try.deflate_correct
= 0;
797 else if (DEFLATE_SIZE(p
[2]) < go
->deflate_size
)
798 try.deflate_size
= DEFLATE_SIZE(p
[2]);
803 if (go
->deflate
&& go
->deflate_draft
&& len
>= CILEN_DEFLATE
&&
804 p
[0] == CI_DEFLATE_DRAFT
) {
807 * Peer wants us to use a different code size or something.
808 * Stop asking for Deflate using the old algorithm number if
809 * we don't understand its suggestion. (Note that this will
810 * happen if the peer is running Magnalink instead of
811 * old-style Deflate.)
813 if (p
[1] != CILEN_DEFLATE
814 || DEFLATE_METHOD(p
[2]) != DEFLATE_METHOD_VAL
815 || DEFLATE_SIZE(p
[2]) <= DEFLATE_MIN_SIZE
816 || p
[3] != DEFLATE_CHK_SEQUENCE
)
817 try.deflate_draft
= 0;
818 else if (DEFLATE_SIZE(p
[2]) < go
->deflate_size
)
819 try.deflate_size
= DEFLATE_SIZE(p
[2]);
824 if (!try.deflate_correct
&& !try.deflate_draft
)
827 if (go
->bsd_compress
&& len
>= CILEN_BSD_COMPRESS
&&
828 p
[0] == CI_BSD_COMPRESS
) {
831 * Peer wants us to use a different number of bits
832 * or a different version.
834 if (p
[1] != CILEN_BSD_COMPRESS
||
835 BSD_VERSION(p
[2]) != BSD_CURRENT_VERSION
)
836 try.bsd_compress
= 0;
837 else if (BSD_NBITS(p
[2]) < go
->bsd_bits
)
838 try.bsd_bits
= BSD_NBITS(p
[2]);
844 * Predictor-1 and 2 have no options, so they can't be Naked.
846 * There may be remaining options but we ignore them.
849 if (f
->state
!= OPENED
)
855 * ccp_rejci - peer rejects some of our suggested compression methods.
863 ccp_options
*go
= &ccp_gotoptions
[f
->unit
];
864 ccp_options
try; /* options to request next time */
869 * Cope with empty configure-rejects by ceasing to send
870 * configure-requests.
872 if (len
== 0 && all_rejected
[f
->unit
])
875 if (go
->deflate
&& go
->deflate_correct
&& len
>= CILEN_DEFLATE
&&
876 p
[0] == CI_DEFLATE
&& p
[1] == CILEN_DEFLATE
) {
877 if (p
[2] != DEFLATE_MAKE_OPT(go
->deflate_size
)
878 || p
[3] != DEFLATE_CHK_SEQUENCE
)
879 return 0; /* Rej is bad */
880 try.deflate_correct
= 0;
882 len
-= CILEN_DEFLATE
;
884 if (go
->deflate
&& go
->deflate_draft
&& len
>= CILEN_DEFLATE
&&
885 p
[0] == CI_DEFLATE_DRAFT
&& p
[1] == CILEN_DEFLATE
) {
886 if (p
[2] != DEFLATE_MAKE_OPT(go
->deflate_size
)
887 || p
[3] != DEFLATE_CHK_SEQUENCE
)
888 return 0; /* Rej is bad */
889 try.deflate_draft
= 0;
891 len
-= CILEN_DEFLATE
;
893 if (!try.deflate_correct
&& !try.deflate_draft
)
895 if (go
->bsd_compress
&& len
>= CILEN_BSD_COMPRESS
896 && p
[0] == CI_BSD_COMPRESS
&& p
[1] == CILEN_BSD_COMPRESS
) {
897 if (p
[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION
, go
->bsd_bits
))
899 try.bsd_compress
= 0;
900 p
+= CILEN_BSD_COMPRESS
;
901 len
-= CILEN_BSD_COMPRESS
;
903 if (go
->predictor_1
&& len
>= CILEN_PREDICTOR_1
904 && p
[0] == CI_PREDICTOR_1
&& p
[1] == CILEN_PREDICTOR_1
) {
906 p
+= CILEN_PREDICTOR_1
;
907 len
-= CILEN_PREDICTOR_1
;
909 if (go
->predictor_2
&& len
>= CILEN_PREDICTOR_2
910 && p
[0] == CI_PREDICTOR_2
&& p
[1] == CILEN_PREDICTOR_2
) {
912 p
+= CILEN_PREDICTOR_2
;
913 len
-= CILEN_PREDICTOR_2
;
919 if (f
->state
!= OPENED
)
926 * ccp_reqci - process a received configure-request.
928 * Returns CODE_CONFACK, CODE_CONFNAK or CODE_CONFREJ and the packet
929 * is modified appropriately.
932 ccp_reqci(f
, p
, lenp
, dont_nak
)
938 int ret
, newret
, res
;
939 u_char
*p0
, *nakp
, *rejp
, *pv
;
940 int len
, clen
, type
, nb
;
941 ccp_options
*ho
= &ccp_hisoptions
[f
->unit
];
942 ccp_options
*ao
= &ccp_allowoptions
[f
->unit
];
949 BZERO(ho
, sizeof(ccp_options
));
950 ho
->method
= (len
> 0)? p
[0]: -1;
952 for (; len
> 0; len
-= clen
, p
+= clen
) {
953 newret
= CODE_CONFACK
;
954 if (len
< 2 || p
[1] > len
) {
956 * RFC 1661 page 40 -- if the option extends beyond the
957 * packet, then discard the entire packet.
968 case CI_DEFLATE_DRAFT
:
970 (!ao
->deflate_correct
&& type
== CI_DEFLATE
) ||
971 (!ao
->deflate_draft
&& type
== CI_DEFLATE_DRAFT
)) {
972 newret
= CODE_CONFREJ
;
977 nb
= clen
< CILEN_DEFLATE
? ao
->deflate_size
: DEFLATE_SIZE(p
[2]);
978 ho
->deflate_size
= nb
;
979 if (clen
!= CILEN_DEFLATE
||
980 DEFLATE_METHOD(p
[2]) != DEFLATE_METHOD_VAL
||
981 p
[3] != DEFLATE_CHK_SEQUENCE
|| nb
> ao
->deflate_size
||
982 nb
<= DEFLATE_MIN_SIZE
) {
983 newret
= CODE_CONFNAK
;
986 if (nb
> ao
->deflate_size
)
987 nb
= ao
->deflate_size
;
988 else if (nb
<= DEFLATE_MIN_SIZE
)
989 nb
= DEFLATE_MIN_SIZE
+1;
992 PUTCHAR(CILEN_DEFLATE
, nakp
);
993 PUTCHAR(DEFLATE_MAKE_OPT(nb
), nakp
);
994 PUTCHAR(DEFLATE_CHK_SEQUENCE
, nakp
);
998 * Check whether we can do Deflate with the window
999 * size they want. If the window is too big, reduce
1000 * it until the kernel can cope and nak with that.
1001 * We only check this for the first option.
1005 res
= ccp_test(f
->unit
, pv
, CILEN_DEFLATE
, 1);
1007 break; /* it's OK now */
1008 if (res
< 0 || nb
<= DEFLATE_MIN_SIZE
+1 || dont_nak
) {
1009 newret
= CODE_CONFREJ
;
1012 if (newret
== CODE_CONFACK
) {
1013 BCOPY(pv
, nakp
, CILEN_DEFLATE
);
1015 nakp
+= CILEN_DEFLATE
;
1016 newret
= CODE_CONFNAK
;
1019 pv
[2] = DEFLATE_MAKE_OPT(nb
);
1022 /* Tune Deflate compression effort. */
1023 if (newret
== CODE_CONFACK
)
1024 ccp_tune(f
->unit
, deflate_tune
);
1029 case CI_BSD_COMPRESS
:
1030 if (!ao
->bsd_compress
) {
1031 newret
= CODE_CONFREJ
;
1035 ho
->bsd_compress
= 1;
1036 nb
= clen
< CILEN_BSD_COMPRESS
? ao
->bsd_bits
: BSD_NBITS(p
[2]);
1038 if (clen
!= CILEN_BSD_COMPRESS
||
1039 BSD_VERSION(p
[2]) != BSD_CURRENT_VERSION
||
1040 nb
> ao
->bsd_bits
|| nb
< BSD_MIN_BITS
) {
1041 newret
= CODE_CONFNAK
;
1044 if (nb
> ao
->bsd_bits
)
1046 else if (nb
< BSD_MIN_BITS
)
1049 PUTCHAR(type
, nakp
);
1050 PUTCHAR(CILEN_BSD_COMPRESS
, nakp
);
1051 PUTCHAR(BSD_MAKE_OPT(BSD_CURRENT_VERSION
, nb
), nakp
);
1055 * Check whether we can do BSD-Compress with the code
1056 * size they want. If the code size is too big, reduce
1057 * it until the kernel can cope and nak with that.
1058 * We only check this for the first option.
1062 res
= ccp_test(f
->unit
, pv
, CILEN_BSD_COMPRESS
, 1);
1065 if (res
< 0 || nb
== BSD_MIN_BITS
|| dont_nak
) {
1066 newret
= CODE_CONFREJ
;
1069 if (newret
== CODE_CONFACK
) {
1070 BCOPY(pv
, nakp
, CILEN_BSD_COMPRESS
);
1072 nakp
+= CILEN_BSD_COMPRESS
;
1073 newret
= CODE_CONFNAK
;
1076 pv
[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION
, nb
);
1081 case CI_PREDICTOR_1
:
1082 if (!ao
->predictor_1
) {
1083 newret
= CODE_CONFREJ
;
1087 ho
->predictor_1
= 1;
1088 if (clen
!= CILEN_PREDICTOR_1
) {
1089 newret
= CODE_CONFNAK
;
1093 PUTCHAR(type
, nakp
);
1094 PUTCHAR(CILEN_PREDICTOR_1
, nakp
);
1097 ccp_test(f
->unit
, pv
, CILEN_PREDICTOR_1
, 1) <= 0) {
1098 newret
= CODE_CONFREJ
;
1102 case CI_PREDICTOR_2
:
1103 if (!ao
->predictor_2
) {
1104 newret
= CODE_CONFREJ
;
1108 ho
->predictor_2
= 1;
1109 if (clen
!= CILEN_PREDICTOR_2
) {
1110 newret
= CODE_CONFNAK
;
1114 PUTCHAR(type
, nakp
);
1115 PUTCHAR(CILEN_PREDICTOR_2
, nakp
);
1118 ccp_test(f
->unit
, p
, CILEN_PREDICTOR_2
, 1) <= 0) {
1119 newret
= CODE_CONFREJ
;
1124 newret
= CODE_CONFREJ
;
1128 /* Cope with confused peers. */
1132 if (newret
== CODE_CONFACK
&& ret
!= CODE_CONFACK
)
1134 if (newret
== CODE_CONFNAK
) {
1136 newret
= CODE_CONFREJ
;
1138 /* Ignore subsequent nakable things if rejecting. */
1139 if (ret
== CODE_CONFREJ
)
1144 if (newret
== CODE_CONFREJ
) {
1147 BCOPY(p
, rejp
, clen
);
1157 *lenp
= nakp
- nak_buffer
;
1158 BCOPY(nak_buffer
, p0
, *lenp
);
1168 * Make a string name for a compression method (or 2).
1171 method_name(opt
, opt2
)
1172 ccp_options
*opt
, *opt2
;
1174 static char result
[64];
1176 if (!ANY_COMPRESS(*opt
))
1178 switch (opt
->method
) {
1180 case CI_DEFLATE_DRAFT
:
1181 if (opt2
!= NULL
&& opt2
->deflate_size
!= opt
->deflate_size
)
1182 (void) slprintf(result
, sizeof(result
), "Deflate%s (%d/%d)",
1183 (opt
->method
== CI_DEFLATE_DRAFT
? "(old#)": ""),
1184 opt
->deflate_size
, opt2
->deflate_size
);
1186 (void) slprintf(result
, sizeof(result
), "Deflate%s (%d)",
1187 (opt
->method
== CI_DEFLATE_DRAFT
? "(old#)": ""),
1190 case CI_BSD_COMPRESS
:
1191 if (opt2
!= NULL
&& opt2
->bsd_bits
!= opt
->bsd_bits
)
1192 (void) slprintf(result
, sizeof(result
), "BSD-Compress (%d/%d)",
1193 opt
->bsd_bits
, opt2
->bsd_bits
);
1195 (void) slprintf(result
, sizeof(result
), "BSD-Compress (%d)",
1198 case CI_PREDICTOR_1
:
1199 return "Predictor 1";
1200 case CI_PREDICTOR_2
:
1201 return "Predictor 2";
1211 (void) slprintf(result
, sizeof(result
), "Method %d", opt
->method
);
1217 * CCP has come up - inform the kernel driver and log a message.
1223 ccp_options
*go
= &ccp_gotoptions
[f
->unit
];
1224 ccp_options
*ho
= &ccp_hisoptions
[f
->unit
];
1228 * We're now open and up (running).
1230 ccp_flags_set(f
->unit
, 1, 1);
1231 if (ANY_COMPRESS(*go
)) {
1232 if (ANY_COMPRESS(*ho
)) {
1233 if (go
->method
== ho
->method
) {
1234 notice("%s compression enabled", method_name(go
, ho
));
1236 (void) strlcpy(method1
, method_name(go
, NULL
), sizeof(method1
));
1237 notice("%s / %s compression enabled",
1238 method1
, method_name(ho
, NULL
));
1241 notice("%s receive decompression enabled", method_name(go
, NULL
));
1242 } else if (ANY_COMPRESS(*ho
))
1243 notice("%s transmit compression enabled", method_name(ho
, NULL
));
1247 * CCP has gone down - inform the kernel driver.
1253 if (ccp_localstate
[f
->unit
] & RACK_PENDING
)
1254 UNTIMEOUT(ccp_rack_timeout
, f
);
1255 /* Don't forget about peer's code rejects or ignoring of requests. */
1256 ccp_localstate
[f
->unit
] &= ~RACK_PENDING
& ~RREQ_REPEAT
;
1257 /* We're still open, but no longer up. */
1258 ccp_flags_set(f
->unit
, 1, 0);
1262 ccp_printpkt(p
, plen
, printer
, arg
)
1265 void (*printer
) __P((void *, const char *, ...));
1268 u_char
*p0
, *optend
, cichar
;
1277 if (plen
< HEADERLEN
) {
1278 printer(arg
, "too short (%d<%d)", plen
, HEADERLEN
);
1285 printer(arg
, " %s id=0x%x", code_name(code
, 1), id
);
1287 if (len
< HEADERLEN
) {
1288 printer(arg
, " header length %d<%d", len
, HEADERLEN
);
1292 printer(arg
, " truncated (%d>%d)", len
, plen
);
1302 /* print list of possible compression methods */
1313 optend
= p
+ optlen
- 2;
1316 case CI_DEFLATE_DRAFT
:
1317 printer(arg
, "deflate%s",
1318 (code
== CI_DEFLATE_DRAFT
? "(old#)": ""));
1319 if (clen
!= CILEN_DEFLATE
)
1320 printer(arg
, " length %d", clen
);
1321 if (optlen
>= CILEN_DEFLATE
) {
1323 printer(arg
, " %d", DEFLATE_SIZE(cichar
));
1324 if (DEFLATE_METHOD(cichar
) != DEFLATE_METHOD_VAL
)
1325 printer(arg
, " method %d", DEFLATE_METHOD(cichar
));
1327 if (cichar
!= DEFLATE_CHK_SEQUENCE
)
1328 printer(arg
, " check %d", cichar
);
1331 case CI_BSD_COMPRESS
:
1332 printer(arg
, "bsd");
1333 if (clen
!= CILEN_BSD_COMPRESS
)
1334 printer(arg
, " length %d", clen
);
1335 if (optlen
>= CILEN_BSD_COMPRESS
) {
1337 printer(arg
, " v%d %d", BSD_VERSION(cichar
),
1341 case CI_PREDICTOR_1
:
1342 printer(arg
, "predictor-1");
1343 if (clen
!= CILEN_PREDICTOR_1
)
1344 printer(arg
, " length %d", clen
);
1346 case CI_PREDICTOR_2
:
1347 printer(arg
, "predictor-2");
1348 if (clen
!= CILEN_PREDICTOR_2
)
1349 printer(arg
, " length %d", clen
);
1353 printer(arg
, "Stac");
1354 if (clen
!= CILEN_STAC
)
1355 printer(arg
, " length %d", clen
);
1356 if (optlen
>= CILEN_STAC
) {
1357 GETSHORT(cishort
, p
);
1359 printer(arg
, " h%d/m%d", cishort
, cichar
);
1365 /* There appears to be no good generic name for this one. */
1366 if (optlen
>= CILEN_MPPC
) {
1368 if (!(cilong
& MPPC_COMP
)) {
1369 if (cilong
& MPPC_MPPE
)
1370 printer(arg
, "MPPE");
1372 printer(arg
, "MS-PPC?");
1374 if (cilong
& MPPC_MPPE
)
1375 printer(arg
, "MPPC+MPPE");
1377 printer(arg
, "MPPC");
1380 printer(arg
, "MS-?");
1382 if (clen
!= CILEN_STAC
)
1383 printer(arg
, " length %d", clen
);
1387 printer(arg
, "typ%d len%d ", code
, clen
);
1392 printer(arg
, " %.8B ...", p
);
1394 printer(arg
, " %.*B", optend
-p
, p
);
1405 GETSHORT(cishort
, p
);
1406 printer(arg
, " history %d", cishort
);
1408 } else if (*p
>= ' ' && *p
< 0x7f) {
1410 print_string((char *)p
, len
, printer
, arg
);
1418 /* dump out the rest of the packet in hex */
1421 printer(arg
, " %.8B ...", p
);
1423 printer(arg
, " %.*B", len
, p
);
1431 * We have received a packet that the decompressor failed to
1432 * decompress. Here we would expect to issue a reset-request, but
1433 * Motorola has a patent on resetting the compressor as a result of
1434 * detecting an error in the decompressed data after decompression.
1435 * (See US patent 5,130,993; international patent publication number
1436 * WO 91/10289; Australian patent 73296/91.)
1438 * So we ask the kernel whether the error was detected after
1439 * decompression; if it was, we take CCP down, thus disabling
1440 * compression :-(, otherwise we issue the reset-request.
1444 ccp_datainput(unit
, pkt
, len
)
1452 if (f
->state
== OPENED
) {
1453 if (ccp_fatal_error(unit
)) {
1455 * Disable compression by taking CCP down.
1457 error("Lost compression sync: disabling compression");
1458 ccp_close(unit
, "Lost compression sync");
1461 * Send a reset-request to reset the peer's compressor, if
1462 * possible. We don't do anything if we are still waiting
1463 * for an acknowledgement to a previous reset-request (to
1464 * avoid flooding the peer). We reopen CCP if the peer
1465 * doesn't like hearing about CCP Reset-Request (Cisco
1466 * sends CCP Code-Reject for Reset-Request). (Reopen
1467 * automatically clears the flags and cancels the
1470 if (ccp_localstate
[f
->unit
] & RREQ_REJECTED
) {
1471 dbglog("reopening CCP to reset peer's compressor");
1473 } else if (ccp_localstate
[f
->unit
] & RACK_PENDING
) {
1474 /* Send another reset request; we're out of sequence. */
1475 ccp_localstate
[f
->unit
] |= RREQ_REPEAT
;
1477 dbglog("sending CCP Reset-Request to reset peer's compressor");
1478 fsm_sdata(f
, CCP_RESETREQ
, f
->reqid
= ++f
->id
, NULL
, 0);
1479 TIMEOUT(ccp_rack_timeout
, f
, RACKTIMEOUT
);
1480 ccp_localstate
[f
->unit
] |= RACK_PENDING
;
1487 * Timeout waiting for reset-ack.
1490 ccp_rack_timeout(arg
)
1495 /* Timeout; no longer pending. */
1496 ccp_localstate
[f
->unit
] &= ~RACK_PENDING
;
1498 /* Frankly, it's a coding flaw if this occurs. */
1499 if (f
->state
!= OPENED
)
1502 if (ccp_localstate
[f
->unit
] & RREQ_IGNORED
) {
1503 info("peer ignored our CCP Reset-Request twice; reopen instead");
1504 ccp_localstate
[f
->unit
] =
1505 (ccp_localstate
[f
->unit
] & ~RREQ_IGNORED
) | RREQ_REJECTED
;
1507 } else if (ccp_localstate
[f
->unit
] & RREQ_REPEAT
) {
1508 dbglog("sending another CCP Reset-Request on timeout");
1509 fsm_sdata(f
, CCP_RESETREQ
, f
->reqid
, NULL
, 0);
1510 TIMEOUT(ccp_rack_timeout
, f
, RACKTIMEOUT
);
1511 ccp_localstate
[f
->unit
] =
1512 (ccp_localstate
[f
->unit
] & ~RREQ_REPEAT
) | RREQ_IGNORED
|
1515 dbglog("timeout waiting for CCP Reset-Ack; hope for the best");
1516 ccp_localstate
[f
->unit
] |= RREQ_IGNORED
;