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