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