17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * ccp.c - PPP Compression Control Protocol.
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * Copyright (c) 2000 by Sun Microsystems, Inc.
57c478bd9Sstevel@tonic-gate  * All rights reserved.
67c478bd9Sstevel@tonic-gate  *
77c478bd9Sstevel@tonic-gate  * Copyright (c) 1994 The Australian National University.
87c478bd9Sstevel@tonic-gate  * All rights reserved.
97c478bd9Sstevel@tonic-gate  *
107c478bd9Sstevel@tonic-gate  * Permission to use, copy, modify, and distribute this software and its
117c478bd9Sstevel@tonic-gate  * documentation is hereby granted, provided that the above copyright
127c478bd9Sstevel@tonic-gate  * notice appears in all copies.  This software is provided without any
137c478bd9Sstevel@tonic-gate  * warranty, express or implied. The Australian National University
147c478bd9Sstevel@tonic-gate  * makes no representations about the suitability of this software for
157c478bd9Sstevel@tonic-gate  * any purpose.
167c478bd9Sstevel@tonic-gate  *
177c478bd9Sstevel@tonic-gate  * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
187c478bd9Sstevel@tonic-gate  * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
197c478bd9Sstevel@tonic-gate  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
207c478bd9Sstevel@tonic-gate  * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
217c478bd9Sstevel@tonic-gate  * OF SUCH DAMAGE.
227c478bd9Sstevel@tonic-gate  *
237c478bd9Sstevel@tonic-gate  * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
247c478bd9Sstevel@tonic-gate  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
257c478bd9Sstevel@tonic-gate  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
267c478bd9Sstevel@tonic-gate  * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
277c478bd9Sstevel@tonic-gate  * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
287c478bd9Sstevel@tonic-gate  * OR MODIFICATIONS.
297c478bd9Sstevel@tonic-gate  */
30*48bbca81SDaniel Hoffman /*
31*48bbca81SDaniel Hoffman  * Copyright (c) 2016 by Delphix. All rights reserved.
32*48bbca81SDaniel Hoffman  */
337c478bd9Sstevel@tonic-gate 
347c478bd9Sstevel@tonic-gate #include <stdlib.h>
357c478bd9Sstevel@tonic-gate #include <string.h>
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate #include "pppd.h"
387c478bd9Sstevel@tonic-gate #include "fsm.h"
397c478bd9Sstevel@tonic-gate #include "ccp.h"
407c478bd9Sstevel@tonic-gate #include <net/ppp-comp.h>
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate /*
437c478bd9Sstevel@tonic-gate  * Command-line options.
447c478bd9Sstevel@tonic-gate  */
457c478bd9Sstevel@tonic-gate static int setbsdcomp __P((char **, option_t *));
467c478bd9Sstevel@tonic-gate static int setdeflate __P((char **, option_t *));
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate static option_t ccp_option_list[] = {
497c478bd9Sstevel@tonic-gate     { "noccp", o_bool, &ccp_protent.enabled_flag,
507c478bd9Sstevel@tonic-gate       "Disable CCP negotiation" },
517c478bd9Sstevel@tonic-gate     { "-ccp", o_bool, &ccp_protent.enabled_flag,
527c478bd9Sstevel@tonic-gate       "Disable CCP negotiation" },
537c478bd9Sstevel@tonic-gate     { "bsdcomp", o_special, (void *)setbsdcomp,
547c478bd9Sstevel@tonic-gate       "Request BSD-Compress packet compression" },
557c478bd9Sstevel@tonic-gate     { "nobsdcomp", o_bool, &ccp_wantoptions[0].bsd_compress,
567c478bd9Sstevel@tonic-gate       "don't allow BSD-Compress", OPT_A2COPY,
577c478bd9Sstevel@tonic-gate       &ccp_allowoptions[0].bsd_compress },
587c478bd9Sstevel@tonic-gate     { "-bsdcomp", o_bool, &ccp_wantoptions[0].bsd_compress,
597c478bd9Sstevel@tonic-gate       "don't allow BSD-Compress", OPT_A2COPY,
607c478bd9Sstevel@tonic-gate       &ccp_allowoptions[0].bsd_compress },
617c478bd9Sstevel@tonic-gate     { "deflate", o_special, (void *)setdeflate,
627c478bd9Sstevel@tonic-gate       "request Deflate compression" },
637c478bd9Sstevel@tonic-gate     { "nodeflate", o_bool, &ccp_wantoptions[0].deflate,
647c478bd9Sstevel@tonic-gate       "don't allow Deflate compression", OPT_A2COPY,
657c478bd9Sstevel@tonic-gate       &ccp_allowoptions[0].deflate },
667c478bd9Sstevel@tonic-gate     { "-deflate", o_bool, &ccp_wantoptions[0].deflate,
677c478bd9Sstevel@tonic-gate       "don't allow Deflate compression", OPT_A2COPY,
687c478bd9Sstevel@tonic-gate       &ccp_allowoptions[0].deflate },
697c478bd9Sstevel@tonic-gate     { "nodeflatedraft", o_bool, &ccp_wantoptions[0].deflate_draft,
707c478bd9Sstevel@tonic-gate       "don't use draft deflate #", OPT_A2COPY,
717c478bd9Sstevel@tonic-gate       &ccp_allowoptions[0].deflate_draft },
727c478bd9Sstevel@tonic-gate     { "predictor1", o_bool, &ccp_wantoptions[0].predictor_1,
737c478bd9Sstevel@tonic-gate       "request Predictor-1", 1, &ccp_allowoptions[0].predictor_1 },
747c478bd9Sstevel@tonic-gate     { "nopredictor1", o_bool, &ccp_wantoptions[0].predictor_1,
757c478bd9Sstevel@tonic-gate       "don't allow Predictor-1", OPT_A2COPY,
767c478bd9Sstevel@tonic-gate       &ccp_allowoptions[0].predictor_1 },
777c478bd9Sstevel@tonic-gate     { "-predictor1", o_bool, &ccp_wantoptions[0].predictor_1,
787c478bd9Sstevel@tonic-gate       "don't allow Predictor-1", OPT_A2COPY,
797c478bd9Sstevel@tonic-gate       &ccp_allowoptions[0].predictor_1 },
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate     { NULL }
827c478bd9Sstevel@tonic-gate };
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate /*
857c478bd9Sstevel@tonic-gate  * Protocol entry points from main code.
867c478bd9Sstevel@tonic-gate  */
877c478bd9Sstevel@tonic-gate static void ccp_init __P((int unit));
887c478bd9Sstevel@tonic-gate static void ccp_open __P((int unit));
897c478bd9Sstevel@tonic-gate static void ccp_close __P((int unit, char *));
907c478bd9Sstevel@tonic-gate static void ccp_lowerup __P((int unit));
917c478bd9Sstevel@tonic-gate static void ccp_lowerdown __P((int));
927c478bd9Sstevel@tonic-gate static void ccp_input __P((int unit, u_char *pkt, int len));
937c478bd9Sstevel@tonic-gate static void ccp_protrej __P((int unit));
947c478bd9Sstevel@tonic-gate static int  ccp_printpkt __P((u_char *pkt, int len,
957c478bd9Sstevel@tonic-gate 			      void (*printer) __P((void *, const char *, ...)),
967c478bd9Sstevel@tonic-gate 			      void *arg));
977c478bd9Sstevel@tonic-gate static void ccp_datainput __P((int unit, u_char *pkt, int len));
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate struct protent ccp_protent = {
1007c478bd9Sstevel@tonic-gate     PPP_CCP,
1017c478bd9Sstevel@tonic-gate     ccp_init,
1027c478bd9Sstevel@tonic-gate     ccp_input,
1037c478bd9Sstevel@tonic-gate     ccp_protrej,
1047c478bd9Sstevel@tonic-gate     ccp_lowerup,
1057c478bd9Sstevel@tonic-gate     ccp_lowerdown,
1067c478bd9Sstevel@tonic-gate     ccp_open,
1077c478bd9Sstevel@tonic-gate     ccp_close,
1087c478bd9Sstevel@tonic-gate     ccp_printpkt,
1097c478bd9Sstevel@tonic-gate     ccp_datainput,
1107c478bd9Sstevel@tonic-gate     1,
1117c478bd9Sstevel@tonic-gate     "CCP",
1127c478bd9Sstevel@tonic-gate     "Compressed",
1137c478bd9Sstevel@tonic-gate     ccp_option_list,
1147c478bd9Sstevel@tonic-gate     NULL,
1157c478bd9Sstevel@tonic-gate     NULL,
1167c478bd9Sstevel@tonic-gate     NULL
1177c478bd9Sstevel@tonic-gate };
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate fsm ccp_fsm[NUM_PPP];
1207c478bd9Sstevel@tonic-gate ccp_options ccp_wantoptions[NUM_PPP];	/* what to request the peer to use */
1217c478bd9Sstevel@tonic-gate ccp_options ccp_gotoptions[NUM_PPP];	/* what the peer agreed to do */
1227c478bd9Sstevel@tonic-gate ccp_options ccp_allowoptions[NUM_PPP];	/* what we'll agree to do */
1237c478bd9Sstevel@tonic-gate ccp_options ccp_hisoptions[NUM_PPP];	/* what we agreed to do */
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate /*
1267c478bd9Sstevel@tonic-gate  * Callbacks for fsm code.
1277c478bd9Sstevel@tonic-gate  */
1287c478bd9Sstevel@tonic-gate static void ccp_resetci __P((fsm *));
1297c478bd9Sstevel@tonic-gate static int  ccp_cilen __P((fsm *));
1307c478bd9Sstevel@tonic-gate static void ccp_addci __P((fsm *, u_char *, int *));
1317c478bd9Sstevel@tonic-gate static int  ccp_ackci __P((fsm *, u_char *, int));
1327c478bd9Sstevel@tonic-gate static int  ccp_nakci __P((fsm *, u_char *, int));
1337c478bd9Sstevel@tonic-gate static int  ccp_rejci __P((fsm *, u_char *, int));
1347c478bd9Sstevel@tonic-gate static int  ccp_reqci __P((fsm *, u_char *, int *, int));
1357c478bd9Sstevel@tonic-gate static void ccp_up __P((fsm *));
1367c478bd9Sstevel@tonic-gate static void ccp_down __P((fsm *));
1377c478bd9Sstevel@tonic-gate static int  ccp_extcode __P((fsm *, int, int, u_char *, int));
1387c478bd9Sstevel@tonic-gate static int  ccp_codereject __P((fsm *p, int code, int id, u_char *inp,
1397c478bd9Sstevel@tonic-gate     int len));
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate static fsm_callbacks ccp_callbacks = {
1427c478bd9Sstevel@tonic-gate     ccp_resetci,		/* Reset our Configuration Information */
1437c478bd9Sstevel@tonic-gate     ccp_cilen,                  /* Length of our Configuration Information */
1447c478bd9Sstevel@tonic-gate     ccp_addci,                  /* Add our Configuration Information */
1457c478bd9Sstevel@tonic-gate     ccp_ackci,                  /* ACK our Configuration Information */
1467c478bd9Sstevel@tonic-gate     ccp_nakci,                  /* NAK our Configuration Information */
1477c478bd9Sstevel@tonic-gate     ccp_rejci,                  /* Reject our Configuration Information */
1487c478bd9Sstevel@tonic-gate     ccp_reqci,                  /* Request peer's Configuration Information */
1497c478bd9Sstevel@tonic-gate     ccp_up,                     /* Called when fsm reaches OPENED state */
1507c478bd9Sstevel@tonic-gate     ccp_down,                   /* Called when fsm leaves OPENED state */
1517c478bd9Sstevel@tonic-gate     NULL,                       /* Called when we want the lower layer up */
1527c478bd9Sstevel@tonic-gate     NULL,                       /* Called when we want the lower layer down */
1537c478bd9Sstevel@tonic-gate     NULL,			/* Retransmission is necessary */
1547c478bd9Sstevel@tonic-gate     ccp_extcode,                /* Called to handle LCP-specific codes */
1557c478bd9Sstevel@tonic-gate     "CCP",			/* String name of protocol */
1567c478bd9Sstevel@tonic-gate     ccp_codereject,             /* Peer rejected a code number */
1577c478bd9Sstevel@tonic-gate };
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate /*
1607c478bd9Sstevel@tonic-gate  * Local statics.
1617c478bd9Sstevel@tonic-gate  */
1627c478bd9Sstevel@tonic-gate static void ccp_rack_timeout __P((void *));
1637c478bd9Sstevel@tonic-gate static char * method_name __P((ccp_options *, ccp_options *));
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate /*
1667c478bd9Sstevel@tonic-gate  * Do we want / did we get any compression?
1677c478bd9Sstevel@tonic-gate  */
1687c478bd9Sstevel@tonic-gate #define ANY_COMPRESS(opt)	((opt).deflate || (opt).bsd_compress \
1697c478bd9Sstevel@tonic-gate 				 || (opt).predictor_1 || (opt).predictor_2)
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate /*
1727c478bd9Sstevel@tonic-gate  * Local state (mainly for handling reset-reqs and reset-acks).
1737c478bd9Sstevel@tonic-gate  */
1747c478bd9Sstevel@tonic-gate static int ccp_localstate[NUM_PPP];
1757c478bd9Sstevel@tonic-gate #define RACK_PENDING	0x0001	/* waiting for reset-ack */
1767c478bd9Sstevel@tonic-gate #define RREQ_REPEAT	0x0002	/* send another reset-req if no reset-ack */
1777c478bd9Sstevel@tonic-gate #define RREQ_REJECTED	0x0004	/* peer code-rejected reset-request */
1787c478bd9Sstevel@tonic-gate #define RACK_REJECTED	0x0008	/* peer code-rejected reset-ack */
1797c478bd9Sstevel@tonic-gate #define RREQ_IGNORED	0x0010	/* peer just ignored reset-request */
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate #define RACKTIMEOUT	1	/* time in seconds between Reset-Requests */
1827c478bd9Sstevel@tonic-gate 
1837c478bd9Sstevel@tonic-gate static int all_rejected[NUM_PPP];	/* we rejected all peer's options */
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate #ifdef COMP_TUNE
1867c478bd9Sstevel@tonic-gate static int deflate_tune = -1;	/* compression effort level for deflate */
1877c478bd9Sstevel@tonic-gate #endif
1887c478bd9Sstevel@tonic-gate static int deflate_rmax = DEFLATE_MAX_SIZE;	/* max rbits */
1897c478bd9Sstevel@tonic-gate static int deflate_amax = DEFLATE_MAX_SIZE;	/* max abits */
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate /*
1927c478bd9Sstevel@tonic-gate  * Option parsing.
1937c478bd9Sstevel@tonic-gate  */
1947c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1957c478bd9Sstevel@tonic-gate static int
setbsdcomp(argv,opt)1967c478bd9Sstevel@tonic-gate setbsdcomp(argv, opt)
1977c478bd9Sstevel@tonic-gate     char **argv;
1987c478bd9Sstevel@tonic-gate     option_t *opt;
1997c478bd9Sstevel@tonic-gate {
2007c478bd9Sstevel@tonic-gate     int rbits, abits;
2017c478bd9Sstevel@tonic-gate     char *str, *endp;
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate     str = *argv;
2047c478bd9Sstevel@tonic-gate     abits = rbits = strtol(str, &endp, 0);
2057c478bd9Sstevel@tonic-gate     if (endp != str && *endp == ',') {
2067c478bd9Sstevel@tonic-gate 	str = endp + 1;
2077c478bd9Sstevel@tonic-gate 	abits = strtol(str, &endp, 0);
2087c478bd9Sstevel@tonic-gate     }
2097c478bd9Sstevel@tonic-gate     if (*endp != '\0' || endp == str) {
2107c478bd9Sstevel@tonic-gate 	option_error("invalid parameter '%s' for bsdcomp option", *argv);
2117c478bd9Sstevel@tonic-gate 	return 0;
2127c478bd9Sstevel@tonic-gate     }
2137c478bd9Sstevel@tonic-gate     if ((rbits != 0 && (rbits < BSD_MIN_BITS || rbits > BSD_MAX_BITS))
2147c478bd9Sstevel@tonic-gate 	|| (abits != 0 && (abits < BSD_MIN_BITS || abits > BSD_MAX_BITS))) {
2157c478bd9Sstevel@tonic-gate 	option_error("bsdcomp option values must be 0 or %d .. %d",
2167c478bd9Sstevel@tonic-gate 		     BSD_MIN_BITS, BSD_MAX_BITS);
2177c478bd9Sstevel@tonic-gate 	return 0;
2187c478bd9Sstevel@tonic-gate     }
2197c478bd9Sstevel@tonic-gate     if (rbits > 0) {
2207c478bd9Sstevel@tonic-gate 	ccp_wantoptions[0].bsd_compress = 1;
2217c478bd9Sstevel@tonic-gate 	ccp_wantoptions[0].bsd_bits = rbits;
2227c478bd9Sstevel@tonic-gate     } else
2237c478bd9Sstevel@tonic-gate 	ccp_wantoptions[0].bsd_compress = 0;
2247c478bd9Sstevel@tonic-gate     if (abits > 0) {
2257c478bd9Sstevel@tonic-gate 	ccp_allowoptions[0].bsd_compress = 1;
2267c478bd9Sstevel@tonic-gate 	ccp_allowoptions[0].bsd_bits = abits;
2277c478bd9Sstevel@tonic-gate     } else
2287c478bd9Sstevel@tonic-gate 	ccp_allowoptions[0].bsd_compress = 0;
2297c478bd9Sstevel@tonic-gate     return 1;
2307c478bd9Sstevel@tonic-gate }
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2337c478bd9Sstevel@tonic-gate static int
setdeflate(argv,opt)2347c478bd9Sstevel@tonic-gate setdeflate(argv, opt)
2357c478bd9Sstevel@tonic-gate     char **argv;
2367c478bd9Sstevel@tonic-gate     option_t *opt;
2377c478bd9Sstevel@tonic-gate {
2387c478bd9Sstevel@tonic-gate     int rbits, abits, def_rmax, def_amax;
2397c478bd9Sstevel@tonic-gate     char *str, *endp;
2407c478bd9Sstevel@tonic-gate 
2417c478bd9Sstevel@tonic-gate     str = endp = *argv;
2427c478bd9Sstevel@tonic-gate     if (*str == ',')
2437c478bd9Sstevel@tonic-gate 	abits = rbits = -1;
2447c478bd9Sstevel@tonic-gate     else
2457c478bd9Sstevel@tonic-gate 	abits = rbits = strtol(str, &endp, 0);
2467c478bd9Sstevel@tonic-gate     if (*endp == ',') {
2477c478bd9Sstevel@tonic-gate 	str = ++endp;
2487c478bd9Sstevel@tonic-gate 	if (*str == ',')
2497c478bd9Sstevel@tonic-gate 	    abits = rbits;
2507c478bd9Sstevel@tonic-gate 	else
2517c478bd9Sstevel@tonic-gate 	    abits = strtol(str, &endp, 0);
2527c478bd9Sstevel@tonic-gate     }
2537c478bd9Sstevel@tonic-gate #ifdef COMP_TUNE
2547c478bd9Sstevel@tonic-gate     if (*endp == ',' && privileged_option) {
2557c478bd9Sstevel@tonic-gate 	str = ++endp;
2567c478bd9Sstevel@tonic-gate 	deflate_tune = strtol(str, &endp, 0);
2577c478bd9Sstevel@tonic-gate     }
2587c478bd9Sstevel@tonic-gate #endif
2597c478bd9Sstevel@tonic-gate     if (*endp != '\0' || endp == str) {
2607c478bd9Sstevel@tonic-gate 	option_error("invalid parameter '%s' for deflate option", *argv);
2617c478bd9Sstevel@tonic-gate 	return 0;
2627c478bd9Sstevel@tonic-gate     }
2637c478bd9Sstevel@tonic-gate     if (privileged_option) {
2647c478bd9Sstevel@tonic-gate 	def_rmax = def_amax = DEFLATE_MAX_SIZE;
2657c478bd9Sstevel@tonic-gate     } else {
2667c478bd9Sstevel@tonic-gate 	def_rmax = deflate_rmax;
2677c478bd9Sstevel@tonic-gate 	def_amax = deflate_amax;
2687c478bd9Sstevel@tonic-gate     }
2697c478bd9Sstevel@tonic-gate     if (rbits < 0)
2707c478bd9Sstevel@tonic-gate 	rbits = def_rmax;
2717c478bd9Sstevel@tonic-gate     if (abits < 0)
2727c478bd9Sstevel@tonic-gate 	abits = def_amax;
2737c478bd9Sstevel@tonic-gate     if ((rbits != 0 && (rbits <= DEFLATE_MIN_SIZE || rbits > def_rmax))
2747c478bd9Sstevel@tonic-gate 	|| (abits != 0 && (abits <= DEFLATE_MIN_SIZE || abits > def_amax))) {
2757c478bd9Sstevel@tonic-gate 	option_error("deflate option values must be 0 or {%d,%d} .. {%d,%d}",
276*48bbca81SDaniel Hoffman 		     DEFLATE_MIN_SIZE+1, DEFLATE_MIN_SIZE+1,
2777c478bd9Sstevel@tonic-gate 		     def_rmax, def_amax);
2787c478bd9Sstevel@tonic-gate 	return 0;
2797c478bd9Sstevel@tonic-gate     }
2807c478bd9Sstevel@tonic-gate     if (privileged_option) {
2817c478bd9Sstevel@tonic-gate 	deflate_rmax = rbits;
2827c478bd9Sstevel@tonic-gate 	deflate_amax = abits;
2837c478bd9Sstevel@tonic-gate     }
2847c478bd9Sstevel@tonic-gate     if (rbits > 0) {
2857c478bd9Sstevel@tonic-gate 	ccp_wantoptions[0].deflate = 1;
2867c478bd9Sstevel@tonic-gate 	ccp_wantoptions[0].deflate_size = rbits;
2877c478bd9Sstevel@tonic-gate     } else
2887c478bd9Sstevel@tonic-gate 	ccp_wantoptions[0].deflate = 0;
2897c478bd9Sstevel@tonic-gate     if (abits > 0) {
2907c478bd9Sstevel@tonic-gate 	ccp_allowoptions[0].deflate = 1;
2917c478bd9Sstevel@tonic-gate 	ccp_allowoptions[0].deflate_size = abits;
2927c478bd9Sstevel@tonic-gate     } else
2937c478bd9Sstevel@tonic-gate 	ccp_allowoptions[0].deflate = 0;
2947c478bd9Sstevel@tonic-gate     return 1;
2957c478bd9Sstevel@tonic-gate }
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate /*
2997c478bd9Sstevel@tonic-gate  * ccp_init - initialize CCP.
3007c478bd9Sstevel@tonic-gate  */
3017c478bd9Sstevel@tonic-gate static void
ccp_init(unit)3027c478bd9Sstevel@tonic-gate ccp_init(unit)
3037c478bd9Sstevel@tonic-gate     int unit;
3047c478bd9Sstevel@tonic-gate {
3057c478bd9Sstevel@tonic-gate     fsm *f = &ccp_fsm[unit];
3067c478bd9Sstevel@tonic-gate 
3077c478bd9Sstevel@tonic-gate     f->unit = unit;
3087c478bd9Sstevel@tonic-gate     f->protocol = PPP_CCP;
3097c478bd9Sstevel@tonic-gate     f->callbacks = &ccp_callbacks;
3107c478bd9Sstevel@tonic-gate     fsm_init(f);
3117c478bd9Sstevel@tonic-gate     f->flags |= OPT_RESTART;
3127c478bd9Sstevel@tonic-gate 
3137c478bd9Sstevel@tonic-gate     BZERO(&ccp_wantoptions[unit],  sizeof(ccp_options));
3147c478bd9Sstevel@tonic-gate     BZERO(&ccp_gotoptions[unit],   sizeof(ccp_options));
3157c478bd9Sstevel@tonic-gate     BZERO(&ccp_allowoptions[unit], sizeof(ccp_options));
3167c478bd9Sstevel@tonic-gate     BZERO(&ccp_hisoptions[unit],   sizeof(ccp_options));
3177c478bd9Sstevel@tonic-gate 
3187c478bd9Sstevel@tonic-gate     ccp_wantoptions[0].deflate = 1;
3197c478bd9Sstevel@tonic-gate     ccp_wantoptions[0].deflate_size = DEFLATE_MAX_SIZE;
3207c478bd9Sstevel@tonic-gate     ccp_wantoptions[0].deflate_correct = 1;
3217c478bd9Sstevel@tonic-gate     ccp_wantoptions[0].deflate_draft = 1;
3227c478bd9Sstevel@tonic-gate     ccp_allowoptions[0].deflate = 1;
3237c478bd9Sstevel@tonic-gate     ccp_allowoptions[0].deflate_size = DEFLATE_MAX_SIZE;
3247c478bd9Sstevel@tonic-gate     ccp_allowoptions[0].deflate_correct = 1;
3257c478bd9Sstevel@tonic-gate     ccp_allowoptions[0].deflate_draft = 1;
3267c478bd9Sstevel@tonic-gate 
3277c478bd9Sstevel@tonic-gate     ccp_wantoptions[0].bsd_compress = 1;
3287c478bd9Sstevel@tonic-gate     ccp_wantoptions[0].bsd_bits = BSD_MAX_BITS;
3297c478bd9Sstevel@tonic-gate     ccp_allowoptions[0].bsd_compress = 1;
3307c478bd9Sstevel@tonic-gate     ccp_allowoptions[0].bsd_bits = BSD_MAX_BITS;
3317c478bd9Sstevel@tonic-gate 
3327c478bd9Sstevel@tonic-gate     ccp_allowoptions[0].predictor_1 = 1;
3337c478bd9Sstevel@tonic-gate }
3347c478bd9Sstevel@tonic-gate 
3357c478bd9Sstevel@tonic-gate /*
3367c478bd9Sstevel@tonic-gate  * ccp_open - CCP is allowed to come up.
3377c478bd9Sstevel@tonic-gate  */
3387c478bd9Sstevel@tonic-gate static void
ccp_open(unit)3397c478bd9Sstevel@tonic-gate ccp_open(unit)
3407c478bd9Sstevel@tonic-gate     int unit;
3417c478bd9Sstevel@tonic-gate {
3427c478bd9Sstevel@tonic-gate     fsm *f = &ccp_fsm[unit];
3437c478bd9Sstevel@tonic-gate 
3447c478bd9Sstevel@tonic-gate     /*
3457c478bd9Sstevel@tonic-gate      * If we haven't gone open yet (first time through), then go open
3467c478bd9Sstevel@tonic-gate      * but not up.  Otherwise, skip this to allow reopen to reset the
3477c478bd9Sstevel@tonic-gate      * compressor.
3487c478bd9Sstevel@tonic-gate      */
3497c478bd9Sstevel@tonic-gate     if (f->state != OPENED)
3507c478bd9Sstevel@tonic-gate 	ccp_flags_set(unit, 1, 0);
3517c478bd9Sstevel@tonic-gate 
3527c478bd9Sstevel@tonic-gate     /*
3537c478bd9Sstevel@tonic-gate      * Find out which compressors the kernel supports before
3547c478bd9Sstevel@tonic-gate      * deciding whether to open in silent mode.
3557c478bd9Sstevel@tonic-gate      */
3567c478bd9Sstevel@tonic-gate     ccp_resetci(f);
3577c478bd9Sstevel@tonic-gate     if (!ANY_COMPRESS(ccp_gotoptions[unit]))
3587c478bd9Sstevel@tonic-gate 	f->flags |= OPT_SILENT;
3597c478bd9Sstevel@tonic-gate 
3607c478bd9Sstevel@tonic-gate     fsm_open(f);
3617c478bd9Sstevel@tonic-gate }
3627c478bd9Sstevel@tonic-gate 
3637c478bd9Sstevel@tonic-gate /*
3647c478bd9Sstevel@tonic-gate  * ccp_close - Terminate CCP.
3657c478bd9Sstevel@tonic-gate  */
3667c478bd9Sstevel@tonic-gate static void
ccp_close(unit,reason)3677c478bd9Sstevel@tonic-gate ccp_close(unit, reason)
3687c478bd9Sstevel@tonic-gate     int unit;
3697c478bd9Sstevel@tonic-gate     char *reason;
3707c478bd9Sstevel@tonic-gate {
3717c478bd9Sstevel@tonic-gate     ccp_flags_set(unit, 0, 0);
3727c478bd9Sstevel@tonic-gate     fsm_close(&ccp_fsm[unit], reason);
3737c478bd9Sstevel@tonic-gate }
3747c478bd9Sstevel@tonic-gate 
3757c478bd9Sstevel@tonic-gate /*
3767c478bd9Sstevel@tonic-gate  * ccp_lowerup - we may now transmit CCP packets.
3777c478bd9Sstevel@tonic-gate  */
3787c478bd9Sstevel@tonic-gate static void
ccp_lowerup(unit)3797c478bd9Sstevel@tonic-gate ccp_lowerup(unit)
3807c478bd9Sstevel@tonic-gate     int unit;
3817c478bd9Sstevel@tonic-gate {
3827c478bd9Sstevel@tonic-gate     fsm_lowerup(&ccp_fsm[unit]);
3837c478bd9Sstevel@tonic-gate }
3847c478bd9Sstevel@tonic-gate 
3857c478bd9Sstevel@tonic-gate /*
3867c478bd9Sstevel@tonic-gate  * ccp_lowerdown - we may not transmit CCP packets.
3877c478bd9Sstevel@tonic-gate  */
3887c478bd9Sstevel@tonic-gate static void
ccp_lowerdown(unit)3897c478bd9Sstevel@tonic-gate ccp_lowerdown(unit)
3907c478bd9Sstevel@tonic-gate     int unit;
3917c478bd9Sstevel@tonic-gate {
3927c478bd9Sstevel@tonic-gate     fsm_lowerdown(&ccp_fsm[unit]);
3937c478bd9Sstevel@tonic-gate }
3947c478bd9Sstevel@tonic-gate 
3957c478bd9Sstevel@tonic-gate /*
3967c478bd9Sstevel@tonic-gate  * ccp_input - process a received CCP packet.
3977c478bd9Sstevel@tonic-gate  */
3987c478bd9Sstevel@tonic-gate static void
ccp_input(unit,p,len)3997c478bd9Sstevel@tonic-gate ccp_input(unit, p, len)
4007c478bd9Sstevel@tonic-gate     int unit;
4017c478bd9Sstevel@tonic-gate     u_char *p;
4027c478bd9Sstevel@tonic-gate     int len;
4037c478bd9Sstevel@tonic-gate {
4047c478bd9Sstevel@tonic-gate     fsm *f = &ccp_fsm[unit];
4057c478bd9Sstevel@tonic-gate     int oldstate;
4067c478bd9Sstevel@tonic-gate 
4077c478bd9Sstevel@tonic-gate     /*
4087c478bd9Sstevel@tonic-gate      * Check for a terminate-request so we can print a message.
4097c478bd9Sstevel@tonic-gate      */
4107c478bd9Sstevel@tonic-gate     oldstate = f->state;
4117c478bd9Sstevel@tonic-gate     fsm_input(f, p, len);
4127c478bd9Sstevel@tonic-gate     if (oldstate == OPENED && p[0] == CODE_TERMREQ && f->state != OPENED)
4137c478bd9Sstevel@tonic-gate 	notice("Compression disabled by peer.");
4147c478bd9Sstevel@tonic-gate 
4157c478bd9Sstevel@tonic-gate     /*
4167c478bd9Sstevel@tonic-gate      * If we get a terminate-ack and we're not asking for compression,
4177c478bd9Sstevel@tonic-gate      * close CCP.  (Terminate-Request is handled by fsm_input() above.)
4187c478bd9Sstevel@tonic-gate      */
4197c478bd9Sstevel@tonic-gate     if (oldstate == REQSENT && p[0] == CODE_TERMACK
4207c478bd9Sstevel@tonic-gate 	&& !ANY_COMPRESS(ccp_gotoptions[unit]))
4217c478bd9Sstevel@tonic-gate 	ccp_close(unit, "No compression negotiated");
4227c478bd9Sstevel@tonic-gate }
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate /*
4257c478bd9Sstevel@tonic-gate  * Handle a CCP-specific code.
4267c478bd9Sstevel@tonic-gate  */
4277c478bd9Sstevel@tonic-gate static int
ccp_extcode(f,code,id,p,len)4287c478bd9Sstevel@tonic-gate ccp_extcode(f, code, id, p, len)
4297c478bd9Sstevel@tonic-gate     fsm *f;
4307c478bd9Sstevel@tonic-gate     int code, id;
4317c478bd9Sstevel@tonic-gate     u_char *p;
4327c478bd9Sstevel@tonic-gate     int len;
4337c478bd9Sstevel@tonic-gate {
4347c478bd9Sstevel@tonic-gate     switch (code) {
4357c478bd9Sstevel@tonic-gate     case CCP_RESETREQ:
4367c478bd9Sstevel@tonic-gate 	/* If not open, then silently ignore. */
4377c478bd9Sstevel@tonic-gate 	if (f->state != OPENED)
4387c478bd9Sstevel@tonic-gate 	    break;
4397c478bd9Sstevel@tonic-gate 	/* send a reset-ack, which our transmitter module will see and
4407c478bd9Sstevel@tonic-gate 	   reset its compression state. */
4417c478bd9Sstevel@tonic-gate 	fsm_sdata(f, CCP_RESETACK, id, p, len);
4427c478bd9Sstevel@tonic-gate 	break;
4437c478bd9Sstevel@tonic-gate 
4447c478bd9Sstevel@tonic-gate     case CCP_RESETACK:
4457c478bd9Sstevel@tonic-gate 	/*
4467c478bd9Sstevel@tonic-gate 	 * Note that the compression module isn't picky about ID
4477c478bd9Sstevel@tonic-gate 	 * numbers and such.
4487c478bd9Sstevel@tonic-gate 	 */
4497c478bd9Sstevel@tonic-gate 	ccp_localstate[f->unit] &= ~RREQ_IGNORED & ~RREQ_REJECTED;
4507c478bd9Sstevel@tonic-gate 	if ((ccp_localstate[f->unit] & RACK_PENDING) && id == f->reqid) {
4517c478bd9Sstevel@tonic-gate 	    ccp_localstate[f->unit] &= ~RACK_PENDING & ~RREQ_REPEAT;
4527c478bd9Sstevel@tonic-gate 	    UNTIMEOUT(ccp_rack_timeout, f);
4537c478bd9Sstevel@tonic-gate 	}
4547c478bd9Sstevel@tonic-gate 	break;
4557c478bd9Sstevel@tonic-gate 
4567c478bd9Sstevel@tonic-gate     default:
4577c478bd9Sstevel@tonic-gate 	/* Tell fsm to send code reject */
4587c478bd9Sstevel@tonic-gate 	return (0);
4597c478bd9Sstevel@tonic-gate     }
4607c478bd9Sstevel@tonic-gate 
4617c478bd9Sstevel@tonic-gate     return (1);
4627c478bd9Sstevel@tonic-gate }
4637c478bd9Sstevel@tonic-gate 
4647c478bd9Sstevel@tonic-gate /*
4657c478bd9Sstevel@tonic-gate  * Handle Code-Reject for one of our extended codes by dropping back to
4667c478bd9Sstevel@tonic-gate  * reopen as mechanism to restart compression.
4677c478bd9Sstevel@tonic-gate  */
4687c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4697c478bd9Sstevel@tonic-gate static int
ccp_codereject(f,code,id,inp,len)4707c478bd9Sstevel@tonic-gate ccp_codereject(f, code, id, inp, len)
4717c478bd9Sstevel@tonic-gate     fsm *f;
4727c478bd9Sstevel@tonic-gate     int code, id;
4737c478bd9Sstevel@tonic-gate     u_char *inp;
4747c478bd9Sstevel@tonic-gate     int len;
4757c478bd9Sstevel@tonic-gate {
4767c478bd9Sstevel@tonic-gate     switch (code) {
4777c478bd9Sstevel@tonic-gate     case CCP_RESETREQ:
4787c478bd9Sstevel@tonic-gate 	if (!(ccp_localstate[f->unit] & RREQ_REJECTED)) {
4797c478bd9Sstevel@tonic-gate 	    info("peer has rejected CCP Reset-Request; falling back on Open");
4807c478bd9Sstevel@tonic-gate 	    if (f->state == OPENED)
4817c478bd9Sstevel@tonic-gate 		ccp_open(f->unit);
4827c478bd9Sstevel@tonic-gate 	}
4837c478bd9Sstevel@tonic-gate 	ccp_localstate[f->unit] |= RREQ_REJECTED;
4847c478bd9Sstevel@tonic-gate 	return (0);
4857c478bd9Sstevel@tonic-gate 
4867c478bd9Sstevel@tonic-gate     case CCP_RESETACK:
4877c478bd9Sstevel@tonic-gate 	/*
488*48bbca81SDaniel Hoffman 	 * Peer must have sent us CCP Reset-Request but then code-rejected when
489*48bbca81SDaniel Hoffman 	 * we sent CCP Reset-Ack.  It seems to have changed its mind, and we
490*48bbca81SDaniel Hoffman 	 * have to obey its wishes.
4917c478bd9Sstevel@tonic-gate 	 */
4927c478bd9Sstevel@tonic-gate 	ccp_localstate[f->unit] |= RACK_REJECTED;
4937c478bd9Sstevel@tonic-gate 	notice("peer has erroneously rejected CCP Reset-Ack");
4947c478bd9Sstevel@tonic-gate 	f->term_reason = "peer sent Code-Reject for CCP Reset-Ack";
4957c478bd9Sstevel@tonic-gate 	f->term_reason_len = strlen(f->term_reason);
4967c478bd9Sstevel@tonic-gate 	break;
4977c478bd9Sstevel@tonic-gate 
4987c478bd9Sstevel@tonic-gate     default:
4997c478bd9Sstevel@tonic-gate 	f->term_reason = "peer sent invalid Code-Reject";
5007c478bd9Sstevel@tonic-gate 	break;
5017c478bd9Sstevel@tonic-gate     }
5027c478bd9Sstevel@tonic-gate 
5037c478bd9Sstevel@tonic-gate     f->term_reason_len = strlen(f->term_reason);
5047c478bd9Sstevel@tonic-gate     return (1);
5057c478bd9Sstevel@tonic-gate }
5067c478bd9Sstevel@tonic-gate 
5077c478bd9Sstevel@tonic-gate /*
5087c478bd9Sstevel@tonic-gate  * ccp_protrej - peer doesn't talk CCP.
5097c478bd9Sstevel@tonic-gate  */
5107c478bd9Sstevel@tonic-gate static void
ccp_protrej(unit)5117c478bd9Sstevel@tonic-gate ccp_protrej(unit)
5127c478bd9Sstevel@tonic-gate     int unit;
5137c478bd9Sstevel@tonic-gate {
5147c478bd9Sstevel@tonic-gate     /* Neither open nor up. */
5157c478bd9Sstevel@tonic-gate     ccp_flags_set(unit, 0, 0);
5167c478bd9Sstevel@tonic-gate     fsm_lowerdown(&ccp_fsm[unit]);
5177c478bd9Sstevel@tonic-gate }
5187c478bd9Sstevel@tonic-gate 
5197c478bd9Sstevel@tonic-gate /*
5207c478bd9Sstevel@tonic-gate  * ccp_resetci - initialize at start of negotiation.
5217c478bd9Sstevel@tonic-gate  */
5227c478bd9Sstevel@tonic-gate static void
ccp_resetci(f)5237c478bd9Sstevel@tonic-gate ccp_resetci(f)
5247c478bd9Sstevel@tonic-gate     fsm *f;
5257c478bd9Sstevel@tonic-gate {
5267c478bd9Sstevel@tonic-gate     ccp_options *go = &ccp_gotoptions[f->unit];
5277c478bd9Sstevel@tonic-gate     u_char opt_buf[16];
5287c478bd9Sstevel@tonic-gate 
5297c478bd9Sstevel@tonic-gate     *go = ccp_wantoptions[f->unit];
5307c478bd9Sstevel@tonic-gate     all_rejected[f->unit] = 0;
5317c478bd9Sstevel@tonic-gate 
5327c478bd9Sstevel@tonic-gate     /*
5337c478bd9Sstevel@tonic-gate      * Check whether the kernel knows about the various
5347c478bd9Sstevel@tonic-gate      * decompression methods we might request.
5357c478bd9Sstevel@tonic-gate      */
5367c478bd9Sstevel@tonic-gate     if (go->bsd_compress) {
5377c478bd9Sstevel@tonic-gate 	opt_buf[0] = CI_BSD_COMPRESS;
5387c478bd9Sstevel@tonic-gate 	opt_buf[1] = CILEN_BSD_COMPRESS;
5397c478bd9Sstevel@tonic-gate 	opt_buf[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, BSD_MIN_BITS);
5407c478bd9Sstevel@tonic-gate 	if (ccp_test(f->unit, opt_buf, CILEN_BSD_COMPRESS, 0) <= 0)
5417c478bd9Sstevel@tonic-gate 	    go->bsd_compress = 0;
5427c478bd9Sstevel@tonic-gate     }
5437c478bd9Sstevel@tonic-gate     if (go->deflate) {
5447c478bd9Sstevel@tonic-gate 	if (go->deflate_correct) {
5457c478bd9Sstevel@tonic-gate 	    opt_buf[0] = CI_DEFLATE;
5467c478bd9Sstevel@tonic-gate 	    opt_buf[1] = CILEN_DEFLATE;
5477c478bd9Sstevel@tonic-gate 	    opt_buf[2] = DEFLATE_MAKE_OPT(DEFLATE_MIN_SIZE+1);
5487c478bd9Sstevel@tonic-gate 	    opt_buf[3] = DEFLATE_CHK_SEQUENCE;
5497c478bd9Sstevel@tonic-gate 	    if (ccp_test(f->unit, opt_buf, CILEN_DEFLATE, 0) <= 0)
5507c478bd9Sstevel@tonic-gate 		go->deflate_correct = 0;
5517c478bd9Sstevel@tonic-gate 	}
5527c478bd9Sstevel@tonic-gate 	if (go->deflate_draft) {
5537c478bd9Sstevel@tonic-gate 	    opt_buf[0] = CI_DEFLATE_DRAFT;
5547c478bd9Sstevel@tonic-gate 	    opt_buf[1] = CILEN_DEFLATE;
5557c478bd9Sstevel@tonic-gate 	    opt_buf[2] = DEFLATE_MAKE_OPT(DEFLATE_MIN_SIZE+1);
5567c478bd9Sstevel@tonic-gate 	    opt_buf[3] = DEFLATE_CHK_SEQUENCE;
5577c478bd9Sstevel@tonic-gate 	    if (ccp_test(f->unit, opt_buf, CILEN_DEFLATE, 0) <= 0)
5587c478bd9Sstevel@tonic-gate 		go->deflate_draft = 0;
5597c478bd9Sstevel@tonic-gate 	}
5607c478bd9Sstevel@tonic-gate 	if (!go->deflate_correct && !go->deflate_draft)
5617c478bd9Sstevel@tonic-gate 	    go->deflate = 0;
5627c478bd9Sstevel@tonic-gate     }
5637c478bd9Sstevel@tonic-gate     if (go->predictor_1) {
5647c478bd9Sstevel@tonic-gate 	opt_buf[0] = CI_PREDICTOR_1;
5657c478bd9Sstevel@tonic-gate 	opt_buf[1] = CILEN_PREDICTOR_1;
5667c478bd9Sstevel@tonic-gate 	if (ccp_test(f->unit, opt_buf, CILEN_PREDICTOR_1, 0) <= 0)
5677c478bd9Sstevel@tonic-gate 	    go->predictor_1 = 0;
5687c478bd9Sstevel@tonic-gate     }
5697c478bd9Sstevel@tonic-gate     if (go->predictor_2) {
5707c478bd9Sstevel@tonic-gate 	opt_buf[0] = CI_PREDICTOR_2;
5717c478bd9Sstevel@tonic-gate 	opt_buf[1] = CILEN_PREDICTOR_2;
5727c478bd9Sstevel@tonic-gate 	if (ccp_test(f->unit, opt_buf, CILEN_PREDICTOR_2, 0) <= 0)
5737c478bd9Sstevel@tonic-gate 	    go->predictor_2 = 0;
5747c478bd9Sstevel@tonic-gate     }
5757c478bd9Sstevel@tonic-gate }
5767c478bd9Sstevel@tonic-gate 
5777c478bd9Sstevel@tonic-gate /*
5787c478bd9Sstevel@tonic-gate  * ccp_cilen - Return total length of our configuration info.
5797c478bd9Sstevel@tonic-gate  */
5807c478bd9Sstevel@tonic-gate static int
ccp_cilen(f)5817c478bd9Sstevel@tonic-gate ccp_cilen(f)
5827c478bd9Sstevel@tonic-gate     fsm *f;
5837c478bd9Sstevel@tonic-gate {
5847c478bd9Sstevel@tonic-gate     ccp_options *go = &ccp_gotoptions[f->unit];
5857c478bd9Sstevel@tonic-gate 
5867c478bd9Sstevel@tonic-gate     return (go->bsd_compress? CILEN_BSD_COMPRESS: 0)
5877c478bd9Sstevel@tonic-gate 	+ (go->deflate && go->deflate_correct ? CILEN_DEFLATE : 0)
5887c478bd9Sstevel@tonic-gate 	+ (go->deflate && go->deflate_draft ? CILEN_DEFLATE : 0)
5897c478bd9Sstevel@tonic-gate 	+ (go->predictor_1? CILEN_PREDICTOR_1: 0)
5907c478bd9Sstevel@tonic-gate 	+ (go->predictor_2? CILEN_PREDICTOR_2: 0);
5917c478bd9Sstevel@tonic-gate }
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate /*
5947c478bd9Sstevel@tonic-gate  * ccp_addci - put our requests in a packet.
5957c478bd9Sstevel@tonic-gate  */
5967c478bd9Sstevel@tonic-gate static void
ccp_addci(f,p,lenp)5977c478bd9Sstevel@tonic-gate ccp_addci(f, p, lenp)
5987c478bd9Sstevel@tonic-gate     fsm *f;
5997c478bd9Sstevel@tonic-gate     u_char *p;
6007c478bd9Sstevel@tonic-gate     int *lenp;
6017c478bd9Sstevel@tonic-gate {
6027c478bd9Sstevel@tonic-gate     int res;
6037c478bd9Sstevel@tonic-gate     ccp_options *go = &ccp_gotoptions[f->unit];
6047c478bd9Sstevel@tonic-gate     u_char *p0 = p;
6057c478bd9Sstevel@tonic-gate 
6067c478bd9Sstevel@tonic-gate     /*
6077c478bd9Sstevel@tonic-gate      * Add the compression types that we can receive, in decreasing
6087c478bd9Sstevel@tonic-gate      * preference order.  Get the kernel to allocate the first one
6097c478bd9Sstevel@tonic-gate      * in case it gets Acked.
6107c478bd9Sstevel@tonic-gate      */
6117c478bd9Sstevel@tonic-gate     if (go->deflate) {
6127c478bd9Sstevel@tonic-gate 	p[0] = go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT;
6137c478bd9Sstevel@tonic-gate 	p[1] = CILEN_DEFLATE;
6147c478bd9Sstevel@tonic-gate 	p[2] = DEFLATE_MAKE_OPT(go->deflate_size);
6157c478bd9Sstevel@tonic-gate 	p[3] = DEFLATE_CHK_SEQUENCE;
6167c478bd9Sstevel@tonic-gate 	for (;;) {
6177c478bd9Sstevel@tonic-gate 	    res = ccp_test(f->unit, p, CILEN_DEFLATE, 0);
6187c478bd9Sstevel@tonic-gate 	    if (res > 0) {
6197c478bd9Sstevel@tonic-gate 		p += CILEN_DEFLATE;
6207c478bd9Sstevel@tonic-gate 		break;
6217c478bd9Sstevel@tonic-gate 	    }
6227c478bd9Sstevel@tonic-gate 	    if (res < 0 || go->deflate_size <= DEFLATE_MIN_SIZE+1) {
6237c478bd9Sstevel@tonic-gate 		go->deflate = 0;
6247c478bd9Sstevel@tonic-gate 		break;
6257c478bd9Sstevel@tonic-gate 	    }
6267c478bd9Sstevel@tonic-gate 	    --go->deflate_size;
6277c478bd9Sstevel@tonic-gate 	    p[2] = DEFLATE_MAKE_OPT(go->deflate_size);
6287c478bd9Sstevel@tonic-gate 	}
6297c478bd9Sstevel@tonic-gate 	/* If we're offering both, then this is second. */
6307c478bd9Sstevel@tonic-gate 	if (p != p0 && go->deflate_correct && go->deflate_draft) {
6317c478bd9Sstevel@tonic-gate 	    p[0] = CI_DEFLATE_DRAFT;
6327c478bd9Sstevel@tonic-gate 	    p[1] = CILEN_DEFLATE;
6337c478bd9Sstevel@tonic-gate 	    p[2] = p[2 - CILEN_DEFLATE];
6347c478bd9Sstevel@tonic-gate 	    p[3] = DEFLATE_CHK_SEQUENCE;
6357c478bd9Sstevel@tonic-gate 	    p += CILEN_DEFLATE;
6367c478bd9Sstevel@tonic-gate 	}
6377c478bd9Sstevel@tonic-gate     }
6387c478bd9Sstevel@tonic-gate     if (go->bsd_compress) {
6397c478bd9Sstevel@tonic-gate 	p[0] = CI_BSD_COMPRESS;
6407c478bd9Sstevel@tonic-gate 	p[1] = CILEN_BSD_COMPRESS;
6417c478bd9Sstevel@tonic-gate 	p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits);
6427c478bd9Sstevel@tonic-gate 	if (p != p0) {
6437c478bd9Sstevel@tonic-gate 	    p += CILEN_BSD_COMPRESS;	/* not the first option */
6447c478bd9Sstevel@tonic-gate 	} else {
6457c478bd9Sstevel@tonic-gate 	    for (;;) {
6467c478bd9Sstevel@tonic-gate 		res = ccp_test(f->unit, p, CILEN_BSD_COMPRESS, 0);
6477c478bd9Sstevel@tonic-gate 		if (res > 0) {
6487c478bd9Sstevel@tonic-gate 		    p += CILEN_BSD_COMPRESS;
6497c478bd9Sstevel@tonic-gate 		    break;
6507c478bd9Sstevel@tonic-gate 		}
6517c478bd9Sstevel@tonic-gate 		if (res < 0 || go->bsd_bits <= BSD_MIN_BITS) {
6527c478bd9Sstevel@tonic-gate 		    go->bsd_compress = 0;
6537c478bd9Sstevel@tonic-gate 		    break;
6547c478bd9Sstevel@tonic-gate 		}
6557c478bd9Sstevel@tonic-gate 		--go->bsd_bits;
6567c478bd9Sstevel@tonic-gate 		p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits);
6577c478bd9Sstevel@tonic-gate 	    }
6587c478bd9Sstevel@tonic-gate 	}
6597c478bd9Sstevel@tonic-gate     }
6607c478bd9Sstevel@tonic-gate     /*
6617c478bd9Sstevel@tonic-gate      * Prefer Predictor-1 over Predictor-2.  (The latter requires the use
6627c478bd9Sstevel@tonic-gate      * of LAP-B and has no known implementations.)
6637c478bd9Sstevel@tonic-gate      */
6647c478bd9Sstevel@tonic-gate     if (go->predictor_1) {
6657c478bd9Sstevel@tonic-gate 	p[0] = CI_PREDICTOR_1;
6667c478bd9Sstevel@tonic-gate 	p[1] = CILEN_PREDICTOR_1;
6677c478bd9Sstevel@tonic-gate 	if (p == p0 && ccp_test(f->unit, p, CILEN_PREDICTOR_1, 0) <= 0) {
6687c478bd9Sstevel@tonic-gate 	    go->predictor_1 = 0;
6697c478bd9Sstevel@tonic-gate 	} else {
6707c478bd9Sstevel@tonic-gate 	    p += CILEN_PREDICTOR_1;
6717c478bd9Sstevel@tonic-gate 	}
6727c478bd9Sstevel@tonic-gate     }
6737c478bd9Sstevel@tonic-gate     if (go->predictor_2) {
6747c478bd9Sstevel@tonic-gate 	p[0] = CI_PREDICTOR_2;
6757c478bd9Sstevel@tonic-gate 	p[1] = CILEN_PREDICTOR_2;
6767c478bd9Sstevel@tonic-gate 	if (p == p0 && ccp_test(f->unit, p, CILEN_PREDICTOR_2, 0) <= 0) {
6777c478bd9Sstevel@tonic-gate 	    go->predictor_2 = 0;
6787c478bd9Sstevel@tonic-gate 	} else {
6797c478bd9Sstevel@tonic-gate 	    p += CILEN_PREDICTOR_2;
6807c478bd9Sstevel@tonic-gate 	}
6817c478bd9Sstevel@tonic-gate     }
6827c478bd9Sstevel@tonic-gate 
6837c478bd9Sstevel@tonic-gate     go->method = (p > p0)? p0[0]: -1;
6847c478bd9Sstevel@tonic-gate 
6857c478bd9Sstevel@tonic-gate     *lenp = p - p0;
6867c478bd9Sstevel@tonic-gate }
6877c478bd9Sstevel@tonic-gate 
6887c478bd9Sstevel@tonic-gate /*
6897c478bd9Sstevel@tonic-gate  * ccp_ackci - process a received configure-ack, and return
6907c478bd9Sstevel@tonic-gate  * 1 iff the packet was OK.
6917c478bd9Sstevel@tonic-gate  */
6927c478bd9Sstevel@tonic-gate static int
ccp_ackci(f,p,len)6937c478bd9Sstevel@tonic-gate ccp_ackci(f, p, len)
6947c478bd9Sstevel@tonic-gate     fsm *f;
6957c478bd9Sstevel@tonic-gate     u_char *p;
6967c478bd9Sstevel@tonic-gate     int len;
6977c478bd9Sstevel@tonic-gate {
6987c478bd9Sstevel@tonic-gate     ccp_options *go = &ccp_gotoptions[f->unit];
6997c478bd9Sstevel@tonic-gate     u_char *p0 = p;
7007c478bd9Sstevel@tonic-gate 
7017c478bd9Sstevel@tonic-gate     if (go->deflate && go->deflate_correct) {
7027c478bd9Sstevel@tonic-gate 	if (len < CILEN_DEFLATE
7037c478bd9Sstevel@tonic-gate 	    || p[0] != CI_DEFLATE || p[1] != CILEN_DEFLATE
7047c478bd9Sstevel@tonic-gate 	    || p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
7057c478bd9Sstevel@tonic-gate 	    || p[3] != DEFLATE_CHK_SEQUENCE)
7067c478bd9Sstevel@tonic-gate 	    return 0;
7077c478bd9Sstevel@tonic-gate 	/* Cope with non-standard first/fast ack */
7087c478bd9Sstevel@tonic-gate 	if (p == p0 && len == 0)
7097c478bd9Sstevel@tonic-gate 	    return 1;
7107c478bd9Sstevel@tonic-gate 	p += CILEN_DEFLATE;
7117c478bd9Sstevel@tonic-gate 	len -= CILEN_DEFLATE;
7127c478bd9Sstevel@tonic-gate     }
7137c478bd9Sstevel@tonic-gate     if (go->deflate && go->deflate_draft) {
7147c478bd9Sstevel@tonic-gate 	if (len < CILEN_DEFLATE
7157c478bd9Sstevel@tonic-gate 	    || p[0] != CI_DEFLATE_DRAFT || p[1] != CILEN_DEFLATE
7167c478bd9Sstevel@tonic-gate 	    || p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
7177c478bd9Sstevel@tonic-gate 	    || p[3] != DEFLATE_CHK_SEQUENCE)
7187c478bd9Sstevel@tonic-gate 	    return 0;
7197c478bd9Sstevel@tonic-gate 	/* Cope with non-standard first/fast ack */
7207c478bd9Sstevel@tonic-gate 	if (p == p0 && len == 0)
7217c478bd9Sstevel@tonic-gate 	    return 1;
7227c478bd9Sstevel@tonic-gate 	p += CILEN_DEFLATE;
7237c478bd9Sstevel@tonic-gate 	len -= CILEN_DEFLATE;
7247c478bd9Sstevel@tonic-gate     }
7257c478bd9Sstevel@tonic-gate     if (go->bsd_compress) {
7267c478bd9Sstevel@tonic-gate 	if (len < CILEN_BSD_COMPRESS
7277c478bd9Sstevel@tonic-gate 	    || p[0] != CI_BSD_COMPRESS || p[1] != CILEN_BSD_COMPRESS
7287c478bd9Sstevel@tonic-gate 	    || p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits))
7297c478bd9Sstevel@tonic-gate 	    return 0;
7307c478bd9Sstevel@tonic-gate 	/* Cope with non-standard first/fast ack */
7317c478bd9Sstevel@tonic-gate 	if (p == p0 && len == 0)
7327c478bd9Sstevel@tonic-gate 	    return 1;
7337c478bd9Sstevel@tonic-gate 	p += CILEN_BSD_COMPRESS;
7347c478bd9Sstevel@tonic-gate 	len -= CILEN_BSD_COMPRESS;
7357c478bd9Sstevel@tonic-gate     }
7367c478bd9Sstevel@tonic-gate     if (go->predictor_1) {
7377c478bd9Sstevel@tonic-gate 	if (len < CILEN_PREDICTOR_1
7387c478bd9Sstevel@tonic-gate 	    || p[0] != CI_PREDICTOR_1 || p[1] != CILEN_PREDICTOR_1)
7397c478bd9Sstevel@tonic-gate 	    return 0;
7407c478bd9Sstevel@tonic-gate 	/* Cope with non-standard first/fast ack */
7417c478bd9Sstevel@tonic-gate 	if (p == p0 && len == 0)
7427c478bd9Sstevel@tonic-gate 	    return 1;
7437c478bd9Sstevel@tonic-gate 	p += CILEN_PREDICTOR_1;
7447c478bd9Sstevel@tonic-gate 	len -= CILEN_PREDICTOR_1;
7457c478bd9Sstevel@tonic-gate     }
7467c478bd9Sstevel@tonic-gate     if (go->predictor_2) {
7477c478bd9Sstevel@tonic-gate 	if (len < CILEN_PREDICTOR_2
7487c478bd9Sstevel@tonic-gate 	    || p[0] != CI_PREDICTOR_2 || p[1] != CILEN_PREDICTOR_2)
7497c478bd9Sstevel@tonic-gate 	    return 0;
7507c478bd9Sstevel@tonic-gate 	/* Cope with non-standard first/fast ack */
7517c478bd9Sstevel@tonic-gate 	if (p == p0 && len == 0)
7527c478bd9Sstevel@tonic-gate 	    return 1;
7537c478bd9Sstevel@tonic-gate 	p += CILEN_PREDICTOR_2;
7547c478bd9Sstevel@tonic-gate 	len -= CILEN_PREDICTOR_2;
7557c478bd9Sstevel@tonic-gate     }
7567c478bd9Sstevel@tonic-gate 
7577c478bd9Sstevel@tonic-gate     /* Peer cannot ack something that wasn't sent. */
7587c478bd9Sstevel@tonic-gate     if (len != 0)
7597c478bd9Sstevel@tonic-gate 	return 0;
7607c478bd9Sstevel@tonic-gate     return 1;
7617c478bd9Sstevel@tonic-gate }
7627c478bd9Sstevel@tonic-gate 
7637c478bd9Sstevel@tonic-gate /*
7647c478bd9Sstevel@tonic-gate  * ccp_nakci - process received configure-nak.
7657c478bd9Sstevel@tonic-gate  * Returns 1 iff the nak was OK.
7667c478bd9Sstevel@tonic-gate  */
7677c478bd9Sstevel@tonic-gate static int
ccp_nakci(f,p,len)7687c478bd9Sstevel@tonic-gate ccp_nakci(f, p, len)
7697c478bd9Sstevel@tonic-gate     fsm *f;
7707c478bd9Sstevel@tonic-gate     u_char *p;
7717c478bd9Sstevel@tonic-gate     int len;
7727c478bd9Sstevel@tonic-gate {
7737c478bd9Sstevel@tonic-gate     ccp_options *go = &ccp_gotoptions[f->unit];
7747c478bd9Sstevel@tonic-gate     ccp_options no;		/* options we've seen already */
7757c478bd9Sstevel@tonic-gate     ccp_options try;		/* options to ask for next time */
7767c478bd9Sstevel@tonic-gate 
7777c478bd9Sstevel@tonic-gate     BZERO(&no, sizeof(no));
7787c478bd9Sstevel@tonic-gate     try = *go;
7797c478bd9Sstevel@tonic-gate 
7807c478bd9Sstevel@tonic-gate     if (go->deflate && go->deflate_correct && len >= CILEN_DEFLATE &&
7817c478bd9Sstevel@tonic-gate 	p[0] == CI_DEFLATE) {
7827c478bd9Sstevel@tonic-gate 	no.deflate = 1;
7837c478bd9Sstevel@tonic-gate 	/*
7847c478bd9Sstevel@tonic-gate 	 * Peer wants us to use a different code size or something.
785*48bbca81SDaniel Hoffman 	 * Stop asking for Deflate if we don't understand its suggestion.
7867c478bd9Sstevel@tonic-gate 	 */
7877c478bd9Sstevel@tonic-gate 	if (p[1] != CILEN_DEFLATE
7887c478bd9Sstevel@tonic-gate 	    || DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL
7897c478bd9Sstevel@tonic-gate 	    || DEFLATE_SIZE(p[2]) <= DEFLATE_MIN_SIZE
7907c478bd9Sstevel@tonic-gate 	    || p[3] != DEFLATE_CHK_SEQUENCE)
7917c478bd9Sstevel@tonic-gate 	    try.deflate_correct = 0;
7927c478bd9Sstevel@tonic-gate 	else if (DEFLATE_SIZE(p[2]) < go->deflate_size)
7937c478bd9Sstevel@tonic-gate 	    try.deflate_size = DEFLATE_SIZE(p[2]);
7947c478bd9Sstevel@tonic-gate 	len -= p[1];
7957c478bd9Sstevel@tonic-gate 	p += p[1];
7967c478bd9Sstevel@tonic-gate     }
7977c478bd9Sstevel@tonic-gate 
7987c478bd9Sstevel@tonic-gate     if (go->deflate && go->deflate_draft && len >= CILEN_DEFLATE &&
7997c478bd9Sstevel@tonic-gate 	p[0] == CI_DEFLATE_DRAFT) {
8007c478bd9Sstevel@tonic-gate 	no.deflate = 1;
8017c478bd9Sstevel@tonic-gate 	/*
8027c478bd9Sstevel@tonic-gate 	 * Peer wants us to use a different code size or something.
8037c478bd9Sstevel@tonic-gate 	 * Stop asking for Deflate using the old algorithm number if
804*48bbca81SDaniel Hoffman 	 * we don't understand its suggestion.  (Note that this will
8057c478bd9Sstevel@tonic-gate 	 * happen if the peer is running Magnalink instead of
8067c478bd9Sstevel@tonic-gate 	 * old-style Deflate.)
8077c478bd9Sstevel@tonic-gate 	 */
8087c478bd9Sstevel@tonic-gate 	if (p[1] != CILEN_DEFLATE
8097c478bd9Sstevel@tonic-gate 	    || DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL
8107c478bd9Sstevel@tonic-gate 	    || DEFLATE_SIZE(p[2]) <= DEFLATE_MIN_SIZE
8117c478bd9Sstevel@tonic-gate 	    || p[3] != DEFLATE_CHK_SEQUENCE)
8127c478bd9Sstevel@tonic-gate 	    try.deflate_draft = 0;
8137c478bd9Sstevel@tonic-gate 	else if (DEFLATE_SIZE(p[2]) < go->deflate_size)
8147c478bd9Sstevel@tonic-gate 	    try.deflate_size = DEFLATE_SIZE(p[2]);
8157c478bd9Sstevel@tonic-gate 	len -= p[1];
8167c478bd9Sstevel@tonic-gate 	p += p[1];
8177c478bd9Sstevel@tonic-gate     }
8187c478bd9Sstevel@tonic-gate 
8197c478bd9Sstevel@tonic-gate     if (!try.deflate_correct && !try.deflate_draft)
8207c478bd9Sstevel@tonic-gate 	try.deflate = 0;
8217c478bd9Sstevel@tonic-gate 
8227c478bd9Sstevel@tonic-gate     if (go->bsd_compress && len >= CILEN_BSD_COMPRESS &&
8237c478bd9Sstevel@tonic-gate 	p[0] == CI_BSD_COMPRESS) {
8247c478bd9Sstevel@tonic-gate 	no.bsd_compress = 1;
8257c478bd9Sstevel@tonic-gate 	/*
8267c478bd9Sstevel@tonic-gate 	 * Peer wants us to use a different number of bits
8277c478bd9Sstevel@tonic-gate 	 * or a different version.
8287c478bd9Sstevel@tonic-gate 	 */
8297c478bd9Sstevel@tonic-gate 	if (p[1] != CILEN_BSD_COMPRESS ||
8307c478bd9Sstevel@tonic-gate 	    BSD_VERSION(p[2]) != BSD_CURRENT_VERSION)
8317c478bd9Sstevel@tonic-gate 	    try.bsd_compress = 0;
8327c478bd9Sstevel@tonic-gate 	else if (BSD_NBITS(p[2]) < go->bsd_bits)
8337c478bd9Sstevel@tonic-gate 	    try.bsd_bits = BSD_NBITS(p[2]);
8347c478bd9Sstevel@tonic-gate 	len -= p[1];
8357c478bd9Sstevel@tonic-gate 	p += p[1];
8367c478bd9Sstevel@tonic-gate     }
8377c478bd9Sstevel@tonic-gate 
8387c478bd9Sstevel@tonic-gate     /*
8397c478bd9Sstevel@tonic-gate      * Predictor-1 and 2 have no options, so they can't be Naked.
8407c478bd9Sstevel@tonic-gate      *
8417c478bd9Sstevel@tonic-gate      * There may be remaining options but we ignore them.
8427c478bd9Sstevel@tonic-gate      */
8437c478bd9Sstevel@tonic-gate 
8447c478bd9Sstevel@tonic-gate     if (f->state != OPENED)
8457c478bd9Sstevel@tonic-gate 	*go = try;
8467c478bd9Sstevel@tonic-gate     return 1;
8477c478bd9Sstevel@tonic-gate }
8487c478bd9Sstevel@tonic-gate 
8497c478bd9Sstevel@tonic-gate /*
8507c478bd9Sstevel@tonic-gate  * ccp_rejci - peer rejects some of our suggested compression methods.
8517c478bd9Sstevel@tonic-gate  */
8527c478bd9Sstevel@tonic-gate static int
ccp_rejci(f,p,len)8537c478bd9Sstevel@tonic-gate ccp_rejci(f, p, len)
8547c478bd9Sstevel@tonic-gate     fsm *f;
8557c478bd9Sstevel@tonic-gate     u_char *p;
8567c478bd9Sstevel@tonic-gate     int len;
8577c478bd9Sstevel@tonic-gate {
8587c478bd9Sstevel@tonic-gate     ccp_options *go = &ccp_gotoptions[f->unit];
8597c478bd9Sstevel@tonic-gate     ccp_options try;		/* options to request next time */
8607c478bd9Sstevel@tonic-gate 
8617c478bd9Sstevel@tonic-gate     try = *go;
8627c478bd9Sstevel@tonic-gate 
8637c478bd9Sstevel@tonic-gate     /*
8647c478bd9Sstevel@tonic-gate      * Cope with empty configure-rejects by ceasing to send
8657c478bd9Sstevel@tonic-gate      * configure-requests.
8667c478bd9Sstevel@tonic-gate      */
8677c478bd9Sstevel@tonic-gate     if (len == 0 && all_rejected[f->unit])
8687c478bd9Sstevel@tonic-gate 	return -1;
8697c478bd9Sstevel@tonic-gate 
8707c478bd9Sstevel@tonic-gate     if (go->deflate && go->deflate_correct && len >= CILEN_DEFLATE &&
8717c478bd9Sstevel@tonic-gate 	p[0] == CI_DEFLATE && p[1] == CILEN_DEFLATE) {
8727c478bd9Sstevel@tonic-gate 	if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
8737c478bd9Sstevel@tonic-gate 	    || p[3] != DEFLATE_CHK_SEQUENCE)
8747c478bd9Sstevel@tonic-gate 	    return 0;		/* Rej is bad */
8757c478bd9Sstevel@tonic-gate 	try.deflate_correct = 0;
8767c478bd9Sstevel@tonic-gate 	p += CILEN_DEFLATE;
8777c478bd9Sstevel@tonic-gate 	len -= CILEN_DEFLATE;
8787c478bd9Sstevel@tonic-gate     }
8797c478bd9Sstevel@tonic-gate     if (go->deflate && go->deflate_draft && len >= CILEN_DEFLATE &&
8807c478bd9Sstevel@tonic-gate 	p[0] == CI_DEFLATE_DRAFT && p[1] == CILEN_DEFLATE) {
8817c478bd9Sstevel@tonic-gate 	if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
8827c478bd9Sstevel@tonic-gate 	    || p[3] != DEFLATE_CHK_SEQUENCE)
8837c478bd9Sstevel@tonic-gate 	    return 0;		/* Rej is bad */
8847c478bd9Sstevel@tonic-gate 	try.deflate_draft = 0;
8857c478bd9Sstevel@tonic-gate 	p += CILEN_DEFLATE;
8867c478bd9Sstevel@tonic-gate 	len -= CILEN_DEFLATE;
8877c478bd9Sstevel@tonic-gate     }
8887c478bd9Sstevel@tonic-gate     if (!try.deflate_correct && !try.deflate_draft)
8897c478bd9Sstevel@tonic-gate 	try.deflate = 0;
8907c478bd9Sstevel@tonic-gate     if (go->bsd_compress && len >= CILEN_BSD_COMPRESS
8917c478bd9Sstevel@tonic-gate 	&& p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) {
8927c478bd9Sstevel@tonic-gate 	if (p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits))
8937c478bd9Sstevel@tonic-gate 	    return 0;
8947c478bd9Sstevel@tonic-gate 	try.bsd_compress = 0;
8957c478bd9Sstevel@tonic-gate 	p += CILEN_BSD_COMPRESS;
8967c478bd9Sstevel@tonic-gate 	len -= CILEN_BSD_COMPRESS;
8977c478bd9Sstevel@tonic-gate     }
8987c478bd9Sstevel@tonic-gate     if (go->predictor_1 && len >= CILEN_PREDICTOR_1
8997c478bd9Sstevel@tonic-gate 	&& p[0] == CI_PREDICTOR_1 && p[1] == CILEN_PREDICTOR_1) {
9007c478bd9Sstevel@tonic-gate 	try.predictor_1 = 0;
9017c478bd9Sstevel@tonic-gate 	p += CILEN_PREDICTOR_1;
9027c478bd9Sstevel@tonic-gate 	len -= CILEN_PREDICTOR_1;
9037c478bd9Sstevel@tonic-gate     }
9047c478bd9Sstevel@tonic-gate     if (go->predictor_2 && len >= CILEN_PREDICTOR_2
9057c478bd9Sstevel@tonic-gate 	&& p[0] == CI_PREDICTOR_2 && p[1] == CILEN_PREDICTOR_2) {
9067c478bd9Sstevel@tonic-gate 	try.predictor_2 = 0;
9077c478bd9Sstevel@tonic-gate 	p += CILEN_PREDICTOR_2;
9087c478bd9Sstevel@tonic-gate 	len -= CILEN_PREDICTOR_2;
9097c478bd9Sstevel@tonic-gate     }
9107c478bd9Sstevel@tonic-gate 
9117c478bd9Sstevel@tonic-gate     if (len != 0)
9127c478bd9Sstevel@tonic-gate 	return 0;
9137c478bd9Sstevel@tonic-gate 
9147c478bd9Sstevel@tonic-gate     if (f->state != OPENED)
9157c478bd9Sstevel@tonic-gate 	*go = try;
9167c478bd9Sstevel@tonic-gate 
9177c478bd9Sstevel@tonic-gate     return 1;
9187c478bd9Sstevel@tonic-gate }
9197c478bd9Sstevel@tonic-gate 
9207c478bd9Sstevel@tonic-gate /*
9217c478bd9Sstevel@tonic-gate  * ccp_reqci - process a received configure-request.
9227c478bd9Sstevel@tonic-gate  *
9237c478bd9Sstevel@tonic-gate  * Returns CODE_CONFACK, CODE_CONFNAK or CODE_CONFREJ and the packet
9247c478bd9Sstevel@tonic-gate  * is modified appropriately.
9257c478bd9Sstevel@tonic-gate  */
9267c478bd9Sstevel@tonic-gate static int
ccp_reqci(f,p,lenp,dont_nak)9277c478bd9Sstevel@tonic-gate ccp_reqci(f, p, lenp, dont_nak)
9287c478bd9Sstevel@tonic-gate     fsm *f;
9297c478bd9Sstevel@tonic-gate     u_char *p;
9307c478bd9Sstevel@tonic-gate     int *lenp;
9317c478bd9Sstevel@tonic-gate     int dont_nak;
9327c478bd9Sstevel@tonic-gate {
9337c478bd9Sstevel@tonic-gate     int ret, newret, res;
9347c478bd9Sstevel@tonic-gate     u_char *p0, *nakp, *rejp, *pv;
9357c478bd9Sstevel@tonic-gate     int len, clen, type, nb;
9367c478bd9Sstevel@tonic-gate     ccp_options *ho = &ccp_hisoptions[f->unit];
9377c478bd9Sstevel@tonic-gate     ccp_options *ao = &ccp_allowoptions[f->unit];
9387c478bd9Sstevel@tonic-gate 
9397c478bd9Sstevel@tonic-gate     ret = CODE_CONFACK;
9407c478bd9Sstevel@tonic-gate     rejp = p0 = p;
9417c478bd9Sstevel@tonic-gate     nakp = nak_buffer;
9427c478bd9Sstevel@tonic-gate     len = *lenp;
9437c478bd9Sstevel@tonic-gate 
9447c478bd9Sstevel@tonic-gate     BZERO(ho, sizeof(ccp_options));
9457c478bd9Sstevel@tonic-gate     ho->method = (len > 0)? p[0]: -1;
9467c478bd9Sstevel@tonic-gate 
9477c478bd9Sstevel@tonic-gate     for (; len > 0; len -= clen, p += clen) {
9487c478bd9Sstevel@tonic-gate 	newret = CODE_CONFACK;
9497c478bd9Sstevel@tonic-gate 	if (len < 2 || p[1] > len) {
9507c478bd9Sstevel@tonic-gate 	    /*
9517c478bd9Sstevel@tonic-gate 	     * RFC 1661 page 40 -- if the option extends beyond the
9527c478bd9Sstevel@tonic-gate 	     * packet, then discard the entire packet.
9537c478bd9Sstevel@tonic-gate 	     */
9547c478bd9Sstevel@tonic-gate 	    return (0);
9557c478bd9Sstevel@tonic-gate 	}
9567c478bd9Sstevel@tonic-gate 
9577c478bd9Sstevel@tonic-gate 	type = p[0];
9587c478bd9Sstevel@tonic-gate 	clen = p[1];
9597c478bd9Sstevel@tonic-gate 
9607c478bd9Sstevel@tonic-gate 	pv = p;
9617c478bd9Sstevel@tonic-gate 	switch (type) {
9627c478bd9Sstevel@tonic-gate 	case CI_DEFLATE:
9637c478bd9Sstevel@tonic-gate 	case CI_DEFLATE_DRAFT:
9647c478bd9Sstevel@tonic-gate 	    if (!ao->deflate ||
9657c478bd9Sstevel@tonic-gate 		(!ao->deflate_correct && type == CI_DEFLATE) ||
9667c478bd9Sstevel@tonic-gate 		(!ao->deflate_draft && type == CI_DEFLATE_DRAFT)) {
9677c478bd9Sstevel@tonic-gate 		newret = CODE_CONFREJ;
9687c478bd9Sstevel@tonic-gate 		break;
9697c478bd9Sstevel@tonic-gate 	    }
9707c478bd9Sstevel@tonic-gate 
9717c478bd9Sstevel@tonic-gate 	    ho->deflate = 1;
9727c478bd9Sstevel@tonic-gate 	    nb = clen < CILEN_DEFLATE ? ao->deflate_size : DEFLATE_SIZE(p[2]);
9737c478bd9Sstevel@tonic-gate 	    ho->deflate_size = nb;
9747c478bd9Sstevel@tonic-gate 	    if (clen != CILEN_DEFLATE ||
9757c478bd9Sstevel@tonic-gate 		DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL ||
9767c478bd9Sstevel@tonic-gate 		p[3] != DEFLATE_CHK_SEQUENCE || nb > ao->deflate_size ||
9777c478bd9Sstevel@tonic-gate 		nb <= DEFLATE_MIN_SIZE) {
9787c478bd9Sstevel@tonic-gate 		newret = CODE_CONFNAK;
9797c478bd9Sstevel@tonic-gate 		if (dont_nak)
9807c478bd9Sstevel@tonic-gate 		    break;
9817c478bd9Sstevel@tonic-gate 		if (nb > ao->deflate_size)
9827c478bd9Sstevel@tonic-gate 		    nb = ao->deflate_size;
9837c478bd9Sstevel@tonic-gate 		else if (nb <= DEFLATE_MIN_SIZE)
9847c478bd9Sstevel@tonic-gate 		    nb = DEFLATE_MIN_SIZE+1;
9857c478bd9Sstevel@tonic-gate 		pv = nakp;
9867c478bd9Sstevel@tonic-gate 		PUTCHAR(type, nakp);
9877c478bd9Sstevel@tonic-gate 		PUTCHAR(CILEN_DEFLATE, nakp);
9887c478bd9Sstevel@tonic-gate 		PUTCHAR(DEFLATE_MAKE_OPT(nb), nakp);
9897c478bd9Sstevel@tonic-gate 		PUTCHAR(DEFLATE_CHK_SEQUENCE, nakp);
9907c478bd9Sstevel@tonic-gate 	    }
9917c478bd9Sstevel@tonic-gate 
9927c478bd9Sstevel@tonic-gate 	    /*
9937c478bd9Sstevel@tonic-gate 	     * Check whether we can do Deflate with the window
9947c478bd9Sstevel@tonic-gate 	     * size they want.  If the window is too big, reduce
9957c478bd9Sstevel@tonic-gate 	     * it until the kernel can cope and nak with that.
9967c478bd9Sstevel@tonic-gate 	     * We only check this for the first option.
9977c478bd9Sstevel@tonic-gate 	     */
9987c478bd9Sstevel@tonic-gate 	    if (p == p0) {
9997c478bd9Sstevel@tonic-gate 		for (;;) {
10007c478bd9Sstevel@tonic-gate 		    res = ccp_test(f->unit, pv, CILEN_DEFLATE, 1);
10017c478bd9Sstevel@tonic-gate 		    if (res > 0)
10027c478bd9Sstevel@tonic-gate 			break;		/* it's OK now */
10037c478bd9Sstevel@tonic-gate 		    if (res < 0 || nb <= DEFLATE_MIN_SIZE+1 || dont_nak) {
10047c478bd9Sstevel@tonic-gate 			newret = CODE_CONFREJ;
10057c478bd9Sstevel@tonic-gate 			break;
10067c478bd9Sstevel@tonic-gate 		    }
10077c478bd9Sstevel@tonic-gate 		    if (newret == CODE_CONFACK) {
10087c478bd9Sstevel@tonic-gate 			BCOPY(pv, nakp, CILEN_DEFLATE);
10097c478bd9Sstevel@tonic-gate 			pv = nakp;
10107c478bd9Sstevel@tonic-gate 			nakp += CILEN_DEFLATE;
10117c478bd9Sstevel@tonic-gate 			newret = CODE_CONFNAK;
10127c478bd9Sstevel@tonic-gate 		    }
10137c478bd9Sstevel@tonic-gate 		    --nb;
10147c478bd9Sstevel@tonic-gate 		    pv[2] = DEFLATE_MAKE_OPT(nb);
10157c478bd9Sstevel@tonic-gate 		}
10167c478bd9Sstevel@tonic-gate #ifdef COMP_TUNE
10177c478bd9Sstevel@tonic-gate 		/* Tune Deflate compression effort. */
10187c478bd9Sstevel@tonic-gate 		if (newret == CODE_CONFACK)
10197c478bd9Sstevel@tonic-gate 		    ccp_tune(f->unit, deflate_tune);
10207c478bd9Sstevel@tonic-gate #endif
10217c478bd9Sstevel@tonic-gate 	    }
10227c478bd9Sstevel@tonic-gate 	    break;
10237c478bd9Sstevel@tonic-gate 
10247c478bd9Sstevel@tonic-gate 	case CI_BSD_COMPRESS:
10257c478bd9Sstevel@tonic-gate 	    if (!ao->bsd_compress) {
10267c478bd9Sstevel@tonic-gate 		newret = CODE_CONFREJ;
10277c478bd9Sstevel@tonic-gate 		break;
10287c478bd9Sstevel@tonic-gate 	    }
10297c478bd9Sstevel@tonic-gate 
10307c478bd9Sstevel@tonic-gate 	    ho->bsd_compress = 1;
10317c478bd9Sstevel@tonic-gate 	    nb = clen < CILEN_BSD_COMPRESS ? ao->bsd_bits : BSD_NBITS(p[2]);
10327c478bd9Sstevel@tonic-gate 	    ho->bsd_bits = nb;
10337c478bd9Sstevel@tonic-gate 	    if (clen != CILEN_BSD_COMPRESS ||
10347c478bd9Sstevel@tonic-gate 		BSD_VERSION(p[2]) != BSD_CURRENT_VERSION ||
10357c478bd9Sstevel@tonic-gate 		nb > ao->bsd_bits || nb < BSD_MIN_BITS) {
10367c478bd9Sstevel@tonic-gate 		newret = CODE_CONFNAK;
10377c478bd9Sstevel@tonic-gate 		if (dont_nak)
10387c478bd9Sstevel@tonic-gate 		    break;
10397c478bd9Sstevel@tonic-gate 		if (nb > ao->bsd_bits)
10407c478bd9Sstevel@tonic-gate 		    nb = ao->bsd_bits;
10417c478bd9Sstevel@tonic-gate 		else if (nb < BSD_MIN_BITS)
10427c478bd9Sstevel@tonic-gate 		    nb = BSD_MIN_BITS;
10437c478bd9Sstevel@tonic-gate 		pv = nakp;
10447c478bd9Sstevel@tonic-gate 		PUTCHAR(type, nakp);
10457c478bd9Sstevel@tonic-gate 		PUTCHAR(CILEN_BSD_COMPRESS, nakp);
10467c478bd9Sstevel@tonic-gate 		PUTCHAR(BSD_MAKE_OPT(BSD_CURRENT_VERSION, nb), nakp);
10477c478bd9Sstevel@tonic-gate 	    }
10487c478bd9Sstevel@tonic-gate 
10497c478bd9Sstevel@tonic-gate 	    /*
10507c478bd9Sstevel@tonic-gate 	     * Check whether we can do BSD-Compress with the code
10517c478bd9Sstevel@tonic-gate 	     * size they want.  If the code size is too big, reduce
10527c478bd9Sstevel@tonic-gate 	     * it until the kernel can cope and nak with that.
10537c478bd9Sstevel@tonic-gate 	     * We only check this for the first option.
10547c478bd9Sstevel@tonic-gate 	     */
10557c478bd9Sstevel@tonic-gate 	    if (p == p0) {
10567c478bd9Sstevel@tonic-gate 		for (;;) {
10577c478bd9Sstevel@tonic-gate 		    res = ccp_test(f->unit, pv, CILEN_BSD_COMPRESS, 1);
10587c478bd9Sstevel@tonic-gate 		    if (res > 0)
10597c478bd9Sstevel@tonic-gate 			break;
10607c478bd9Sstevel@tonic-gate 		    if (res < 0 || nb == BSD_MIN_BITS || dont_nak) {
10617c478bd9Sstevel@tonic-gate 			newret = CODE_CONFREJ;
10627c478bd9Sstevel@tonic-gate 			break;
10637c478bd9Sstevel@tonic-gate 		    }
10647c478bd9Sstevel@tonic-gate 		    if (newret == CODE_CONFACK) {
10657c478bd9Sstevel@tonic-gate 			BCOPY(pv, nakp, CILEN_BSD_COMPRESS);
10667c478bd9Sstevel@tonic-gate 			pv = nakp;
10677c478bd9Sstevel@tonic-gate 			nakp += CILEN_BSD_COMPRESS;
10687c478bd9Sstevel@tonic-gate 			newret = CODE_CONFNAK;
10697c478bd9Sstevel@tonic-gate 		    }
10707c478bd9Sstevel@tonic-gate 		    --nb;
10717c478bd9Sstevel@tonic-gate 		    pv[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, nb);
10727c478bd9Sstevel@tonic-gate 		}
10737c478bd9Sstevel@tonic-gate 	    }
10747c478bd9Sstevel@tonic-gate 	    break;
10757c478bd9Sstevel@tonic-gate 
10767c478bd9Sstevel@tonic-gate 	case CI_PREDICTOR_1:
10777c478bd9Sstevel@tonic-gate 	    if (!ao->predictor_1) {
10787c478bd9Sstevel@tonic-gate 		newret = CODE_CONFREJ;
10797c478bd9Sstevel@tonic-gate 		break;
10807c478bd9Sstevel@tonic-gate 	    }
10817c478bd9Sstevel@tonic-gate 
10827c478bd9Sstevel@tonic-gate 	    ho->predictor_1 = 1;
10837c478bd9Sstevel@tonic-gate 	    if (clen != CILEN_PREDICTOR_1) {
10847c478bd9Sstevel@tonic-gate 		newret = CODE_CONFNAK;
10857c478bd9Sstevel@tonic-gate 		if (dont_nak)
10867c478bd9Sstevel@tonic-gate 		    break;
10877c478bd9Sstevel@tonic-gate 		pv = nakp;
10887c478bd9Sstevel@tonic-gate 		PUTCHAR(type, nakp);
10897c478bd9Sstevel@tonic-gate 		PUTCHAR(CILEN_PREDICTOR_1, nakp);
10907c478bd9Sstevel@tonic-gate 	    }
10917c478bd9Sstevel@tonic-gate 	    if (p == p0 &&
10927c478bd9Sstevel@tonic-gate 		ccp_test(f->unit, pv, CILEN_PREDICTOR_1, 1) <= 0) {
10937c478bd9Sstevel@tonic-gate 		newret = CODE_CONFREJ;
10947c478bd9Sstevel@tonic-gate 	    }
10957c478bd9Sstevel@tonic-gate 	    break;
10967c478bd9Sstevel@tonic-gate 
10977c478bd9Sstevel@tonic-gate 	case CI_PREDICTOR_2:
10987c478bd9Sstevel@tonic-gate 	    if (!ao->predictor_2) {
10997c478bd9Sstevel@tonic-gate 		newret = CODE_CONFREJ;
11007c478bd9Sstevel@tonic-gate 		break;
11017c478bd9Sstevel@tonic-gate 	    }
11027c478bd9Sstevel@tonic-gate 
11037c478bd9Sstevel@tonic-gate 	    ho->predictor_2 = 1;
11047c478bd9Sstevel@tonic-gate 	    if (clen != CILEN_PREDICTOR_2) {
11057c478bd9Sstevel@tonic-gate 		newret = CODE_CONFNAK;
11067c478bd9Sstevel@tonic-gate 		if (dont_nak)
11077c478bd9Sstevel@tonic-gate 		    break;
11087c478bd9Sstevel@tonic-gate 		pv = nakp;
11097c478bd9Sstevel@tonic-gate 		PUTCHAR(type, nakp);
11107c478bd9Sstevel@tonic-gate 		PUTCHAR(CILEN_PREDICTOR_2, nakp);
11117c478bd9Sstevel@tonic-gate 	    }
11127c478bd9Sstevel@tonic-gate 	    if (p == p0 &&
11137c478bd9Sstevel@tonic-gate 		ccp_test(f->unit, p, CILEN_PREDICTOR_2, 1) <= 0) {
11147c478bd9Sstevel@tonic-gate 		newret = CODE_CONFREJ;
11157c478bd9Sstevel@tonic-gate 	    }
11167c478bd9Sstevel@tonic-gate 	    break;
11177c478bd9Sstevel@tonic-gate 
11187c478bd9Sstevel@tonic-gate 	default:
11197c478bd9Sstevel@tonic-gate 	    newret = CODE_CONFREJ;
11207c478bd9Sstevel@tonic-gate 	    break;
11217c478bd9Sstevel@tonic-gate 	}
11227c478bd9Sstevel@tonic-gate 
11237c478bd9Sstevel@tonic-gate 	/* Cope with confused peers. */
11247c478bd9Sstevel@tonic-gate 	if (clen < 2)
11257c478bd9Sstevel@tonic-gate 	    clen = 2;
11267c478bd9Sstevel@tonic-gate 
11277c478bd9Sstevel@tonic-gate 	if (newret == CODE_CONFACK && ret != CODE_CONFACK)
11287c478bd9Sstevel@tonic-gate 	    continue;
11297c478bd9Sstevel@tonic-gate 	if (newret == CODE_CONFNAK) {
11307c478bd9Sstevel@tonic-gate 	    if (dont_nak) {
11317c478bd9Sstevel@tonic-gate 		newret = CODE_CONFREJ;
11327c478bd9Sstevel@tonic-gate 	    } else {
11337c478bd9Sstevel@tonic-gate 		/* Ignore subsequent nakable things if rejecting. */
11347c478bd9Sstevel@tonic-gate 		if (ret == CODE_CONFREJ)
11357c478bd9Sstevel@tonic-gate 		    continue;
11367c478bd9Sstevel@tonic-gate 		ret = CODE_CONFNAK;
11377c478bd9Sstevel@tonic-gate 	    }
11387c478bd9Sstevel@tonic-gate 	}
11397c478bd9Sstevel@tonic-gate 	if (newret == CODE_CONFREJ) {
11407c478bd9Sstevel@tonic-gate 	    ret = CODE_CONFREJ;
11417c478bd9Sstevel@tonic-gate 	    if (p != rejp)
11427c478bd9Sstevel@tonic-gate 		BCOPY(p, rejp, clen);
11437c478bd9Sstevel@tonic-gate 	    rejp += clen;
11447c478bd9Sstevel@tonic-gate 	}
11457c478bd9Sstevel@tonic-gate     }
11467c478bd9Sstevel@tonic-gate 
11477c478bd9Sstevel@tonic-gate     switch (ret) {
11487c478bd9Sstevel@tonic-gate     case CODE_CONFACK:
11497c478bd9Sstevel@tonic-gate 	*lenp = p - p0;
11507c478bd9Sstevel@tonic-gate 	break;
11517c478bd9Sstevel@tonic-gate     case CODE_CONFNAK:
11527c478bd9Sstevel@tonic-gate 	*lenp = nakp - nak_buffer;
11537c478bd9Sstevel@tonic-gate 	BCOPY(nak_buffer, p0, *lenp);
11547c478bd9Sstevel@tonic-gate 	break;
11557c478bd9Sstevel@tonic-gate     case CODE_CONFREJ:
11567c478bd9Sstevel@tonic-gate 	*lenp = rejp - p0;
11577c478bd9Sstevel@tonic-gate 	break;
11587c478bd9Sstevel@tonic-gate     }
11597c478bd9Sstevel@tonic-gate     return ret;
11607c478bd9Sstevel@tonic-gate }
11617c478bd9Sstevel@tonic-gate 
11627c478bd9Sstevel@tonic-gate /*
11637c478bd9Sstevel@tonic-gate  * Make a string name for a compression method (or 2).
11647c478bd9Sstevel@tonic-gate  */
11657c478bd9Sstevel@tonic-gate static char *
method_name(opt,opt2)11667c478bd9Sstevel@tonic-gate method_name(opt, opt2)
11677c478bd9Sstevel@tonic-gate     ccp_options *opt, *opt2;
11687c478bd9Sstevel@tonic-gate {
11697c478bd9Sstevel@tonic-gate     static char result[64];
11707c478bd9Sstevel@tonic-gate 
11717c478bd9Sstevel@tonic-gate     if (!ANY_COMPRESS(*opt))
11727c478bd9Sstevel@tonic-gate 	return "(none)";
11737c478bd9Sstevel@tonic-gate     switch (opt->method) {
11747c478bd9Sstevel@tonic-gate     case CI_DEFLATE:
11757c478bd9Sstevel@tonic-gate     case CI_DEFLATE_DRAFT:
11767c478bd9Sstevel@tonic-gate 	if (opt2 != NULL && opt2->deflate_size != opt->deflate_size)
11777c478bd9Sstevel@tonic-gate 	    (void) slprintf(result, sizeof(result), "Deflate%s (%d/%d)",
11787c478bd9Sstevel@tonic-gate 		     (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""),
11797c478bd9Sstevel@tonic-gate 		     opt->deflate_size, opt2->deflate_size);
11807c478bd9Sstevel@tonic-gate 	else
11817c478bd9Sstevel@tonic-gate 	    (void) slprintf(result, sizeof(result), "Deflate%s (%d)",
11827c478bd9Sstevel@tonic-gate 		     (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""),
11837c478bd9Sstevel@tonic-gate 		     opt->deflate_size);
11847c478bd9Sstevel@tonic-gate 	break;
11857c478bd9Sstevel@tonic-gate     case CI_BSD_COMPRESS:
11867c478bd9Sstevel@tonic-gate 	if (opt2 != NULL && opt2->bsd_bits != opt->bsd_bits)
11877c478bd9Sstevel@tonic-gate 	    (void) slprintf(result, sizeof(result), "BSD-Compress (%d/%d)",
11887c478bd9Sstevel@tonic-gate 		     opt->bsd_bits, opt2->bsd_bits);
11897c478bd9Sstevel@tonic-gate 	else
11907c478bd9Sstevel@tonic-gate 	    (void) slprintf(result, sizeof(result), "BSD-Compress (%d)",
11917c478bd9Sstevel@tonic-gate 		     opt->bsd_bits);
11927c478bd9Sstevel@tonic-gate 	break;
11937c478bd9Sstevel@tonic-gate     case CI_PREDICTOR_1:
11947c478bd9Sstevel@tonic-gate 	return "Predictor 1";
11957c478bd9Sstevel@tonic-gate     case CI_PREDICTOR_2:
11967c478bd9Sstevel@tonic-gate 	return "Predictor 2";
11977c478bd9Sstevel@tonic-gate #ifdef CI_STAC
11987c478bd9Sstevel@tonic-gate     case CI_STAC:
11997c478bd9Sstevel@tonic-gate 	return "Stac";
12007c478bd9Sstevel@tonic-gate #endif
12017c478bd9Sstevel@tonic-gate #ifdef CI_MPPC
12027c478bd9Sstevel@tonic-gate     case CI_MPPC:
12037c478bd9Sstevel@tonic-gate 	return "MS-PPC";
12047c478bd9Sstevel@tonic-gate #endif
12057c478bd9Sstevel@tonic-gate     default:
12067c478bd9Sstevel@tonic-gate 	(void) slprintf(result, sizeof(result), "Method %d", opt->method);
12077c478bd9Sstevel@tonic-gate     }
12087c478bd9Sstevel@tonic-gate     return result;
12097c478bd9Sstevel@tonic-gate }
12107c478bd9Sstevel@tonic-gate 
12117c478bd9Sstevel@tonic-gate /*
12127c478bd9Sstevel@tonic-gate  * CCP has come up - inform the kernel driver and log a message.
12137c478bd9Sstevel@tonic-gate  */
12147c478bd9Sstevel@tonic-gate static void
ccp_up(f)12157c478bd9Sstevel@tonic-gate ccp_up(f)
12167c478bd9Sstevel@tonic-gate     fsm *f;
12177c478bd9Sstevel@tonic-gate {
12187c478bd9Sstevel@tonic-gate     ccp_options *go = &ccp_gotoptions[f->unit];
12197c478bd9Sstevel@tonic-gate     ccp_options *ho = &ccp_hisoptions[f->unit];
12207c478bd9Sstevel@tonic-gate     char method1[64];
12217c478bd9Sstevel@tonic-gate 
12227c478bd9Sstevel@tonic-gate     /*
12237c478bd9Sstevel@tonic-gate      * We're now open and up (running).
12247c478bd9Sstevel@tonic-gate      */
12257c478bd9Sstevel@tonic-gate     ccp_flags_set(f->unit, 1, 1);
12267c478bd9Sstevel@tonic-gate     if (ANY_COMPRESS(*go)) {
12277c478bd9Sstevel@tonic-gate 	if (ANY_COMPRESS(*ho)) {
12287c478bd9Sstevel@tonic-gate 	    if (go->method == ho->method) {
12297c478bd9Sstevel@tonic-gate 		notice("%s compression enabled", method_name(go, ho));
12307c478bd9Sstevel@tonic-gate 	    } else {
12317c478bd9Sstevel@tonic-gate 		(void) strlcpy(method1, method_name(go, NULL), sizeof(method1));
12327c478bd9Sstevel@tonic-gate 		notice("%s / %s compression enabled",
12337c478bd9Sstevel@tonic-gate 		       method1, method_name(ho, NULL));
12347c478bd9Sstevel@tonic-gate 	    }
12357c478bd9Sstevel@tonic-gate 	} else
12367c478bd9Sstevel@tonic-gate 	    notice("%s receive decompression enabled", method_name(go, NULL));
12377c478bd9Sstevel@tonic-gate     } else if (ANY_COMPRESS(*ho))
12387c478bd9Sstevel@tonic-gate 	notice("%s transmit compression enabled", method_name(ho, NULL));
12397c478bd9Sstevel@tonic-gate }
12407c478bd9Sstevel@tonic-gate 
12417c478bd9Sstevel@tonic-gate /*
12427c478bd9Sstevel@tonic-gate  * CCP has gone down - inform the kernel driver.
12437c478bd9Sstevel@tonic-gate  */
12447c478bd9Sstevel@tonic-gate static void
ccp_down(f)12457c478bd9Sstevel@tonic-gate ccp_down(f)
12467c478bd9Sstevel@tonic-gate     fsm *f;
12477c478bd9Sstevel@tonic-gate {
12487c478bd9Sstevel@tonic-gate     if (ccp_localstate[f->unit] & RACK_PENDING)
12497c478bd9Sstevel@tonic-gate 	UNTIMEOUT(ccp_rack_timeout, f);
12507c478bd9Sstevel@tonic-gate     /* Don't forget about peer's code rejects or ignoring of requests. */
12517c478bd9Sstevel@tonic-gate     ccp_localstate[f->unit] &= ~RACK_PENDING & ~RREQ_REPEAT;
12527c478bd9Sstevel@tonic-gate     /* We're still open, but no longer up. */
12537c478bd9Sstevel@tonic-gate     ccp_flags_set(f->unit, 1, 0);
12547c478bd9Sstevel@tonic-gate }
12557c478bd9Sstevel@tonic-gate 
12567c478bd9Sstevel@tonic-gate static int
ccp_printpkt(p,plen,printer,arg)12577c478bd9Sstevel@tonic-gate ccp_printpkt(p, plen, printer, arg)
12587c478bd9Sstevel@tonic-gate     u_char *p;
12597c478bd9Sstevel@tonic-gate     int plen;
12607c478bd9Sstevel@tonic-gate     void (*printer) __P((void *, const char *, ...));
12617c478bd9Sstevel@tonic-gate     void *arg;
12627c478bd9Sstevel@tonic-gate {
12637c478bd9Sstevel@tonic-gate     u_char *p0, *optend, cichar;
12647c478bd9Sstevel@tonic-gate     int code, id, len;
12657c478bd9Sstevel@tonic-gate     int optlen, clen;
12667c478bd9Sstevel@tonic-gate     u_short cishort;
12677c478bd9Sstevel@tonic-gate #ifdef CI_MPPC
12687c478bd9Sstevel@tonic-gate     u_int32_t cilong;
12697c478bd9Sstevel@tonic-gate #endif
12707c478bd9Sstevel@tonic-gate 
12717c478bd9Sstevel@tonic-gate     p0 = p;
12727c478bd9Sstevel@tonic-gate     if (plen < HEADERLEN) {
12737c478bd9Sstevel@tonic-gate 	printer(arg, "too short (%d<%d)", plen, HEADERLEN);
12747c478bd9Sstevel@tonic-gate 	return (0);
12757c478bd9Sstevel@tonic-gate     }
12767c478bd9Sstevel@tonic-gate     GETCHAR(code, p);
12777c478bd9Sstevel@tonic-gate     GETCHAR(id, p);
12787c478bd9Sstevel@tonic-gate     GETSHORT(len, p);
12797c478bd9Sstevel@tonic-gate 
12807c478bd9Sstevel@tonic-gate     printer(arg, " %s id=0x%x", code_name(code, 1), id);
12817c478bd9Sstevel@tonic-gate 
12827c478bd9Sstevel@tonic-gate     if (len < HEADERLEN) {
12837c478bd9Sstevel@tonic-gate 	printer(arg, " header length %d<%d", len, HEADERLEN);
12847c478bd9Sstevel@tonic-gate 	return (HEADERLEN);
12857c478bd9Sstevel@tonic-gate     }
12867c478bd9Sstevel@tonic-gate     if (len > plen) {
12877c478bd9Sstevel@tonic-gate 	printer(arg, " truncated (%d>%d)", len, plen);
12887c478bd9Sstevel@tonic-gate 	len = plen;
12897c478bd9Sstevel@tonic-gate     }
12907c478bd9Sstevel@tonic-gate     len -= HEADERLEN;
12917c478bd9Sstevel@tonic-gate 
12927c478bd9Sstevel@tonic-gate     switch (code) {
12937c478bd9Sstevel@tonic-gate     case CODE_CONFREQ:
12947c478bd9Sstevel@tonic-gate     case CODE_CONFACK:
12957c478bd9Sstevel@tonic-gate     case CODE_CONFNAK:
12967c478bd9Sstevel@tonic-gate     case CODE_CONFREJ:
12977c478bd9Sstevel@tonic-gate 	/* print list of possible compression methods */
12987c478bd9Sstevel@tonic-gate 	while (len >= 2) {
12997c478bd9Sstevel@tonic-gate 	    GETCHAR(code, p);
13007c478bd9Sstevel@tonic-gate 	    GETCHAR(clen, p);
13017c478bd9Sstevel@tonic-gate 	    optlen = clen;
13027c478bd9Sstevel@tonic-gate 	    printer(arg, " <");
13037c478bd9Sstevel@tonic-gate 	    if (optlen > len)
13047c478bd9Sstevel@tonic-gate 		optlen = len;
13057c478bd9Sstevel@tonic-gate 	    if (optlen < 2)
13067c478bd9Sstevel@tonic-gate 		optlen = 2;
13077c478bd9Sstevel@tonic-gate 	    len -= optlen;
13087c478bd9Sstevel@tonic-gate 	    optend = p + optlen - 2;
13097c478bd9Sstevel@tonic-gate 	    switch (code) {
13107c478bd9Sstevel@tonic-gate 	    case CI_DEFLATE:
13117c478bd9Sstevel@tonic-gate 	    case CI_DEFLATE_DRAFT:
13127c478bd9Sstevel@tonic-gate 		printer(arg, "deflate%s",
13137c478bd9Sstevel@tonic-gate 		    (code == CI_DEFLATE_DRAFT? "(old#)": ""));
13147c478bd9Sstevel@tonic-gate 		if (clen != CILEN_DEFLATE)
13157c478bd9Sstevel@tonic-gate 		    printer(arg, " length %d", clen);
13167c478bd9Sstevel@tonic-gate 		if (optlen >= CILEN_DEFLATE) {
13177c478bd9Sstevel@tonic-gate 		    GETCHAR(cichar, p);
13187c478bd9Sstevel@tonic-gate 		    printer(arg, " %d", DEFLATE_SIZE(cichar));
13197c478bd9Sstevel@tonic-gate 		    if (DEFLATE_METHOD(cichar) != DEFLATE_METHOD_VAL)
13207c478bd9Sstevel@tonic-gate 			printer(arg, " method %d", DEFLATE_METHOD(cichar));
13217c478bd9Sstevel@tonic-gate 		    GETCHAR(cichar, p);
13227c478bd9Sstevel@tonic-gate 		    if (cichar != DEFLATE_CHK_SEQUENCE)
13237c478bd9Sstevel@tonic-gate 			printer(arg, " check %d", cichar);
13247c478bd9Sstevel@tonic-gate 		}
13257c478bd9Sstevel@tonic-gate 		break;
13267c478bd9Sstevel@tonic-gate 	    case CI_BSD_COMPRESS:
13277c478bd9Sstevel@tonic-gate 		printer(arg, "bsd");
13287c478bd9Sstevel@tonic-gate 		if (clen != CILEN_BSD_COMPRESS)
13297c478bd9Sstevel@tonic-gate 		    printer(arg, " length %d", clen);
13307c478bd9Sstevel@tonic-gate 		if (optlen >= CILEN_BSD_COMPRESS) {
13317c478bd9Sstevel@tonic-gate 		    GETCHAR(cichar, p);
13327c478bd9Sstevel@tonic-gate 		    printer(arg, " v%d %d", BSD_VERSION(cichar),
13337c478bd9Sstevel@tonic-gate 			BSD_NBITS(cichar));
13347c478bd9Sstevel@tonic-gate 		}
13357c478bd9Sstevel@tonic-gate 		break;
13367c478bd9Sstevel@tonic-gate 	    case CI_PREDICTOR_1:
13377c478bd9Sstevel@tonic-gate 		printer(arg, "predictor-1");
13387c478bd9Sstevel@tonic-gate 		if (clen != CILEN_PREDICTOR_1)
13397c478bd9Sstevel@tonic-gate 		    printer(arg, " length %d", clen);
13407c478bd9Sstevel@tonic-gate 		break;
13417c478bd9Sstevel@tonic-gate 	    case CI_PREDICTOR_2:
13427c478bd9Sstevel@tonic-gate 		printer(arg, "predictor-2");
13437c478bd9Sstevel@tonic-gate 		if (clen != CILEN_PREDICTOR_2)
13447c478bd9Sstevel@tonic-gate 		    printer(arg, " length %d", clen);
13457c478bd9Sstevel@tonic-gate 		break;
13467c478bd9Sstevel@tonic-gate #ifdef CI_STAC
13477c478bd9Sstevel@tonic-gate 	    case CI_STAC:
13487c478bd9Sstevel@tonic-gate 		printer(arg, "Stac");
13497c478bd9Sstevel@tonic-gate 		if (clen != CILEN_STAC)
13507c478bd9Sstevel@tonic-gate 		    printer(arg, " length %d", clen);
13517c478bd9Sstevel@tonic-gate 		if (optlen >= CILEN_STAC) {
13527c478bd9Sstevel@tonic-gate 		    GETSHORT(cishort, p);
13537c478bd9Sstevel@tonic-gate 		    GETCHAR(cichar, p);
13547c478bd9Sstevel@tonic-gate 		    printer(arg, " h%d/m%d", cishort, cichar);
13557c478bd9Sstevel@tonic-gate 		}
13567c478bd9Sstevel@tonic-gate 		break;
13577c478bd9Sstevel@tonic-gate #endif
13587c478bd9Sstevel@tonic-gate #ifdef CI_MPPC
13597c478bd9Sstevel@tonic-gate 	    case CI_MPPC:
13607c478bd9Sstevel@tonic-gate 		/* There appears to be no good generic name for this one. */
13617c478bd9Sstevel@tonic-gate 		if (optlen >= CILEN_MPPC) {
13627c478bd9Sstevel@tonic-gate 		    GETLONG(cilong, p);
13637c478bd9Sstevel@tonic-gate 		    if (!(cilong & MPPC_COMP)) {
13647c478bd9Sstevel@tonic-gate 			if (cilong & MPPC_MPPE)
13657c478bd9Sstevel@tonic-gate 			    printer(arg, "MPPE");
13667c478bd9Sstevel@tonic-gate 			else
13677c478bd9Sstevel@tonic-gate 			    printer(arg, "MS-PPC?");
13687c478bd9Sstevel@tonic-gate 		    } else {
13697c478bd9Sstevel@tonic-gate 			if (cilong & MPPC_MPPE)
13707c478bd9Sstevel@tonic-gate 			    printer(arg, "MPPC+MPPE");
13717c478bd9Sstevel@tonic-gate 			else
13727c478bd9Sstevel@tonic-gate 			    printer(arg, "MPPC");
13737c478bd9Sstevel@tonic-gate 		    }
13747c478bd9Sstevel@tonic-gate 		} else {
13757c478bd9Sstevel@tonic-gate 		    printer(arg, "MS-?");
13767c478bd9Sstevel@tonic-gate 		}
13777c478bd9Sstevel@tonic-gate 		if (clen != CILEN_STAC)
13787c478bd9Sstevel@tonic-gate 		    printer(arg, " length %d", clen);
13797c478bd9Sstevel@tonic-gate 		break;
13807c478bd9Sstevel@tonic-gate #endif
13817c478bd9Sstevel@tonic-gate 	    default:
13827c478bd9Sstevel@tonic-gate 		printer(arg, "typ%d len%d ", code, clen);
13837c478bd9Sstevel@tonic-gate 		break;
13847c478bd9Sstevel@tonic-gate 	    }
13857c478bd9Sstevel@tonic-gate 	    if (p < optend) {
13867c478bd9Sstevel@tonic-gate 		if (p+8 < optend)
13877c478bd9Sstevel@tonic-gate 		    printer(arg, " %.8B ...", p);
13887c478bd9Sstevel@tonic-gate 		else
13897c478bd9Sstevel@tonic-gate 		    printer(arg, " %.*B", optend-p, p);
13907c478bd9Sstevel@tonic-gate 		p = optend;
13917c478bd9Sstevel@tonic-gate 	    }
13927c478bd9Sstevel@tonic-gate 	    printer(arg, ">");
13937c478bd9Sstevel@tonic-gate 	}
13947c478bd9Sstevel@tonic-gate 	break;
13957c478bd9Sstevel@tonic-gate 
13967c478bd9Sstevel@tonic-gate     case CODE_TERMACK:
13977c478bd9Sstevel@tonic-gate     case CODE_TERMREQ:
13987c478bd9Sstevel@tonic-gate 	if (len > 0) {
13997c478bd9Sstevel@tonic-gate 	    if (len == 2) {
14007c478bd9Sstevel@tonic-gate 		GETSHORT(cishort, p);
14017c478bd9Sstevel@tonic-gate 		printer(arg, " history %d", cishort);
14027c478bd9Sstevel@tonic-gate 		len = 0;
14037c478bd9Sstevel@tonic-gate 	    } else if (*p >= ' ' && *p < 0x7f) {
14047c478bd9Sstevel@tonic-gate 		printer(arg, " ");
14057c478bd9Sstevel@tonic-gate 		print_string((char *)p, len, printer, arg);
14067c478bd9Sstevel@tonic-gate 		p += len;
14077c478bd9Sstevel@tonic-gate 		len = 0;
14087c478bd9Sstevel@tonic-gate 	    }
14097c478bd9Sstevel@tonic-gate 	}
14107c478bd9Sstevel@tonic-gate 	break;
14117c478bd9Sstevel@tonic-gate     }
14127c478bd9Sstevel@tonic-gate 
14137c478bd9Sstevel@tonic-gate     /* dump out the rest of the packet in hex */
14147c478bd9Sstevel@tonic-gate     if (len > 0) {
14157c478bd9Sstevel@tonic-gate 	if (len > 8)
14167c478bd9Sstevel@tonic-gate 	    printer(arg, " %.8B ...", p);
14177c478bd9Sstevel@tonic-gate 	else
14187c478bd9Sstevel@tonic-gate 	    printer(arg, " %.*B", len, p);
14197c478bd9Sstevel@tonic-gate 	p += len;
14207c478bd9Sstevel@tonic-gate     }
14217c478bd9Sstevel@tonic-gate 
14227c478bd9Sstevel@tonic-gate     return p - p0;
14237c478bd9Sstevel@tonic-gate }
14247c478bd9Sstevel@tonic-gate 
14257c478bd9Sstevel@tonic-gate /*
14267c478bd9Sstevel@tonic-gate  * We have received a packet that the decompressor failed to
14277c478bd9Sstevel@tonic-gate  * decompress.  Here we would expect to issue a reset-request, but
14287c478bd9Sstevel@tonic-gate  * Motorola has a patent on resetting the compressor as a result of
14297c478bd9Sstevel@tonic-gate  * detecting an error in the decompressed data after decompression.
14307c478bd9Sstevel@tonic-gate  * (See US patent 5,130,993; international patent publication number
14317c478bd9Sstevel@tonic-gate  * WO 91/10289; Australian patent 73296/91.)
14327c478bd9Sstevel@tonic-gate  *
14337c478bd9Sstevel@tonic-gate  * So we ask the kernel whether the error was detected after
14347c478bd9Sstevel@tonic-gate  * decompression; if it was, we take CCP down, thus disabling
14357c478bd9Sstevel@tonic-gate  * compression :-(, otherwise we issue the reset-request.
14367c478bd9Sstevel@tonic-gate  */
14377c478bd9Sstevel@tonic-gate /*ARGSUSED*/
14387c478bd9Sstevel@tonic-gate static void
ccp_datainput(unit,pkt,len)14397c478bd9Sstevel@tonic-gate ccp_datainput(unit, pkt, len)
14407c478bd9Sstevel@tonic-gate     int unit;
14417c478bd9Sstevel@tonic-gate     u_char *pkt;
14427c478bd9Sstevel@tonic-gate     int len;
14437c478bd9Sstevel@tonic-gate {
14447c478bd9Sstevel@tonic-gate     fsm *f;
14457c478bd9Sstevel@tonic-gate 
14467c478bd9Sstevel@tonic-gate     f = &ccp_fsm[unit];
14477c478bd9Sstevel@tonic-gate     if (f->state == OPENED) {
14487c478bd9Sstevel@tonic-gate 	if (ccp_fatal_error(unit)) {
14497c478bd9Sstevel@tonic-gate 	    /*
14507c478bd9Sstevel@tonic-gate 	     * Disable compression by taking CCP down.
14517c478bd9Sstevel@tonic-gate 	     */
14527c478bd9Sstevel@tonic-gate 	    error("Lost compression sync: disabling compression");
14537c478bd9Sstevel@tonic-gate 	    ccp_close(unit, "Lost compression sync");
14547c478bd9Sstevel@tonic-gate 	} else {
14557c478bd9Sstevel@tonic-gate 	    /*
14567c478bd9Sstevel@tonic-gate 	     * Send a reset-request to reset the peer's compressor, if
14577c478bd9Sstevel@tonic-gate 	     * possible.  We don't do anything if we are still waiting
14587c478bd9Sstevel@tonic-gate 	     * for an acknowledgement to a previous reset-request (to
14597c478bd9Sstevel@tonic-gate 	     * avoid flooding the peer).  We reopen CCP if the peer
14607c478bd9Sstevel@tonic-gate 	     * doesn't like hearing about CCP Reset-Request (Cisco
14617c478bd9Sstevel@tonic-gate 	     * sends CCP Code-Reject for Reset-Request).  (Reopen
14627c478bd9Sstevel@tonic-gate 	     * automatically clears the flags and cancels the
14637c478bd9Sstevel@tonic-gate 	     * timeout.)
14647c478bd9Sstevel@tonic-gate 	     */
14657c478bd9Sstevel@tonic-gate 	    if (ccp_localstate[f->unit] & RREQ_REJECTED) {
14667c478bd9Sstevel@tonic-gate 		dbglog("reopening CCP to reset peer's compressor");
14677c478bd9Sstevel@tonic-gate 		ccp_open(f->unit);
14687c478bd9Sstevel@tonic-gate 	    } else if (ccp_localstate[f->unit] & RACK_PENDING) {
14697c478bd9Sstevel@tonic-gate 		/* Send another reset request; we're out of sequence. */
14707c478bd9Sstevel@tonic-gate 		ccp_localstate[f->unit] |= RREQ_REPEAT;
14717c478bd9Sstevel@tonic-gate 	    } else {
14727c478bd9Sstevel@tonic-gate 		dbglog("sending CCP Reset-Request to reset peer's compressor");
14737c478bd9Sstevel@tonic-gate 		fsm_sdata(f, CCP_RESETREQ, f->reqid = ++f->id, NULL, 0);
14747c478bd9Sstevel@tonic-gate 		TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT);
14757c478bd9Sstevel@tonic-gate 		ccp_localstate[f->unit] |= RACK_PENDING;
14767c478bd9Sstevel@tonic-gate 	    }
14777c478bd9Sstevel@tonic-gate 	}
14787c478bd9Sstevel@tonic-gate     }
14797c478bd9Sstevel@tonic-gate }
14807c478bd9Sstevel@tonic-gate 
14817c478bd9Sstevel@tonic-gate /*
14827c478bd9Sstevel@tonic-gate  * Timeout waiting for reset-ack.
14837c478bd9Sstevel@tonic-gate  */
14847c478bd9Sstevel@tonic-gate static void
ccp_rack_timeout(arg)14857c478bd9Sstevel@tonic-gate ccp_rack_timeout(arg)
14867c478bd9Sstevel@tonic-gate     void *arg;
14877c478bd9Sstevel@tonic-gate {
14887c478bd9Sstevel@tonic-gate     fsm *f = arg;
14897c478bd9Sstevel@tonic-gate 
14907c478bd9Sstevel@tonic-gate     /* Timeout; no longer pending. */
14917c478bd9Sstevel@tonic-gate     ccp_localstate[f->unit] &= ~RACK_PENDING;
14927c478bd9Sstevel@tonic-gate 
14937c478bd9Sstevel@tonic-gate     /* Frankly, it's a coding flaw if this occurs. */
14947c478bd9Sstevel@tonic-gate     if (f->state != OPENED)
14957c478bd9Sstevel@tonic-gate 	return;
14967c478bd9Sstevel@tonic-gate 
14977c478bd9Sstevel@tonic-gate     if (ccp_localstate[f->unit] & RREQ_IGNORED) {
14987c478bd9Sstevel@tonic-gate 	info("peer ignored our CCP Reset-Request twice; reopen instead");
14997c478bd9Sstevel@tonic-gate 	ccp_localstate[f->unit] =
15007c478bd9Sstevel@tonic-gate 	    (ccp_localstate[f->unit] & ~RREQ_IGNORED) | RREQ_REJECTED;
15017c478bd9Sstevel@tonic-gate 	ccp_open(f->unit);
15027c478bd9Sstevel@tonic-gate     } else if (ccp_localstate[f->unit] & RREQ_REPEAT) {
15037c478bd9Sstevel@tonic-gate 	dbglog("sending another CCP Reset-Request on timeout");
15047c478bd9Sstevel@tonic-gate 	fsm_sdata(f, CCP_RESETREQ, f->reqid, NULL, 0);
15057c478bd9Sstevel@tonic-gate 	TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT);
15067c478bd9Sstevel@tonic-gate 	ccp_localstate[f->unit] =
15077c478bd9Sstevel@tonic-gate 	    (ccp_localstate[f->unit] & ~RREQ_REPEAT) | RREQ_IGNORED |
15087c478bd9Sstevel@tonic-gate 	    RACK_PENDING;
15097c478bd9Sstevel@tonic-gate     } else {
15107c478bd9Sstevel@tonic-gate 	dbglog("timeout waiting for CCP Reset-Ack; hope for the best");
15117c478bd9Sstevel@tonic-gate 	ccp_localstate[f->unit] |= RREQ_IGNORED;
15127c478bd9Sstevel@tonic-gate     }
15137c478bd9Sstevel@tonic-gate }
1514