Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers lwip_ccp.c Source File

lwip_ccp.c

00001 /*
00002  * ccp.c - PPP Compression Control Protocol.
00003  *
00004  * Copyright (c) 1994-2002 Paul Mackerras. All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  *
00010  * 1. Redistributions of source code must retain the above copyright
00011  *    notice, this list of conditions and the following disclaimer.
00012  *
00013  * 2. The name(s) of the authors of this software must not be used to
00014  *    endorse or promote products derived from this software without
00015  *    prior written permission.
00016  *
00017  * 3. Redistributions of any form whatsoever must retain the following
00018  *    acknowledgment:
00019  *    "This product includes software developed by Paul Mackerras
00020  *     <paulus@samba.org>".
00021  *
00022  * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
00023  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00024  * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
00025  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00026  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
00027  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
00028  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00029  */
00030 
00031 #include "netif/ppp/ppp_opts.h"
00032 #if PPP_SUPPORT && CCP_SUPPORT  /* don't build if not configured for use in lwipopts.h */
00033 
00034 #include <stdlib.h>
00035 #include <string.h>
00036 
00037 #include "netif/ppp/ppp_impl.h"
00038 
00039 #include "netif/ppp/fsm.h"
00040 #include "netif/ppp/ccp.h"
00041 
00042 #if MPPE_SUPPORT
00043 #include "netif/ppp/lcp.h"  /* lcp_close(), lcp_fsm */
00044 #include "netif/ppp/mppe.h" /* mppe_init() */
00045 #endif /* MPPE_SUPPORT */
00046 
00047 /*
00048  * Unfortunately there is a bug in zlib which means that using a
00049  * size of 8 (window size = 256) for Deflate compression will cause
00050  * buffer overruns and kernel crashes in the deflate module.
00051  * Until this is fixed we only accept sizes in the range 9 .. 15.
00052  * Thanks to James Carlson for pointing this out.
00053  */
00054 #define DEFLATE_MIN_WORKS   9
00055 
00056 /*
00057  * Command-line options.
00058  */
00059 #if PPP_OPTIONS
00060 static int setbsdcomp (char **);
00061 static int setdeflate (char **);
00062 static char bsd_value[8];
00063 static char deflate_value[8];
00064 
00065 /*
00066  * Option variables.
00067  */
00068 #if MPPE_SUPPORT
00069 bool refuse_mppe_stateful = 1;      /* Allow stateful mode? */
00070 #endif /* MPPE_SUPPORT */
00071 
00072 static option_t ccp_option_list[] = {
00073     { "noccp", o_bool, &ccp_protent.enabled_flag,
00074       "Disable CCP negotiation" },
00075     { "-ccp", o_bool, &ccp_protent.enabled_flag,
00076       "Disable CCP negotiation", OPT_ALIAS },
00077 
00078     { "bsdcomp", o_special, (void *)setbsdcomp,
00079       "Request BSD-Compress packet compression",
00080       OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, bsd_value },
00081     { "nobsdcomp", o_bool, &ccp_wantoptions[0].bsd_compress,
00082       "don't allow BSD-Compress", OPT_PRIOSUB | OPT_A2CLR,
00083       &ccp_allowoptions[0].bsd_compress },
00084     { "-bsdcomp", o_bool, &ccp_wantoptions[0].bsd_compress,
00085       "don't allow BSD-Compress", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR,
00086       &ccp_allowoptions[0].bsd_compress },
00087 
00088     { "deflate", o_special, (void *)setdeflate,
00089       "request Deflate compression",
00090       OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, deflate_value },
00091     { "nodeflate", o_bool, &ccp_wantoptions[0].deflate,
00092       "don't allow Deflate compression", OPT_PRIOSUB | OPT_A2CLR,
00093       &ccp_allowoptions[0].deflate },
00094     { "-deflate", o_bool, &ccp_wantoptions[0].deflate,
00095       "don't allow Deflate compression", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR,
00096       &ccp_allowoptions[0].deflate },
00097 
00098     { "nodeflatedraft", o_bool, &ccp_wantoptions[0].deflate_draft,
00099       "don't use draft deflate #", OPT_A2COPY,
00100       &ccp_allowoptions[0].deflate_draft },
00101 
00102     { "predictor1", o_bool, &ccp_wantoptions[0].predictor_1,
00103       "request Predictor-1", OPT_PRIO | 1 },
00104     { "nopredictor1", o_bool, &ccp_wantoptions[0].predictor_1,
00105       "don't allow Predictor-1", OPT_PRIOSUB | OPT_A2CLR,
00106       &ccp_allowoptions[0].predictor_1 },
00107     { "-predictor1", o_bool, &ccp_wantoptions[0].predictor_1,
00108       "don't allow Predictor-1", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR,
00109       &ccp_allowoptions[0].predictor_1 },
00110 
00111 #if MPPE_SUPPORT
00112     /* MPPE options are symmetrical ... we only set wantoptions here */
00113     { "require-mppe", o_bool, &ccp_wantoptions[0].mppe,
00114       "require MPPE encryption",
00115       OPT_PRIO | MPPE_OPT_40 | MPPE_OPT_128 },
00116     { "+mppe", o_bool, &ccp_wantoptions[0].mppe,
00117       "require MPPE encryption",
00118       OPT_ALIAS | OPT_PRIO | MPPE_OPT_40 | MPPE_OPT_128 },
00119     { "nomppe", o_bool, &ccp_wantoptions[0].mppe,
00120       "don't allow MPPE encryption", OPT_PRIO },
00121     { "-mppe", o_bool, &ccp_wantoptions[0].mppe,
00122       "don't allow MPPE encryption", OPT_ALIAS | OPT_PRIO },
00123 
00124     /* We use ccp_allowoptions[0].mppe as a junk var ... it is reset later */
00125     { "require-mppe-40", o_bool, &ccp_allowoptions[0].mppe,
00126       "require MPPE 40-bit encryption", OPT_PRIO | OPT_A2OR | MPPE_OPT_40,
00127       &ccp_wantoptions[0].mppe },
00128     { "+mppe-40", o_bool, &ccp_allowoptions[0].mppe,
00129       "require MPPE 40-bit encryption", OPT_PRIO | OPT_A2OR | MPPE_OPT_40,
00130       &ccp_wantoptions[0].mppe },
00131     { "nomppe-40", o_bool, &ccp_allowoptions[0].mppe,
00132       "don't allow MPPE 40-bit encryption",
00133       OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_40, &ccp_wantoptions[0].mppe },
00134     { "-mppe-40", o_bool, &ccp_allowoptions[0].mppe,
00135       "don't allow MPPE 40-bit encryption",
00136       OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_40,
00137       &ccp_wantoptions[0].mppe },
00138 
00139     { "require-mppe-128", o_bool, &ccp_allowoptions[0].mppe,
00140       "require MPPE 128-bit encryption", OPT_PRIO | OPT_A2OR | MPPE_OPT_128,
00141       &ccp_wantoptions[0].mppe },
00142     { "+mppe-128", o_bool, &ccp_allowoptions[0].mppe,
00143       "require MPPE 128-bit encryption",
00144       OPT_ALIAS | OPT_PRIO | OPT_A2OR | MPPE_OPT_128,
00145       &ccp_wantoptions[0].mppe },
00146     { "nomppe-128", o_bool, &ccp_allowoptions[0].mppe,
00147       "don't allow MPPE 128-bit encryption",
00148       OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_128, &ccp_wantoptions[0].mppe },
00149     { "-mppe-128", o_bool, &ccp_allowoptions[0].mppe,
00150       "don't allow MPPE 128-bit encryption",
00151       OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_128,
00152       &ccp_wantoptions[0].mppe },
00153 
00154     /* strange one; we always request stateless, but will we allow stateful? */
00155     { "mppe-stateful", o_bool, &refuse_mppe_stateful,
00156       "allow MPPE stateful mode", OPT_PRIO },
00157     { "nomppe-stateful", o_bool, &refuse_mppe_stateful,
00158       "disallow MPPE stateful mode", OPT_PRIO | 1 },
00159 #endif /* MPPE_SUPPORT */
00160 
00161     { NULL }
00162 };
00163 #endif /* PPP_OPTIONS */
00164 
00165 /*
00166  * Protocol entry points from main code.
00167  */
00168 static void ccp_init(ppp_pcb *pcb);
00169 static void ccp_open(ppp_pcb *pcb);
00170 static void ccp_close(ppp_pcb *pcb, const char *reason);
00171 static void ccp_lowerup(ppp_pcb *pcb);
00172 static void ccp_lowerdown(ppp_pcb *pcb);
00173 static void ccp_input(ppp_pcb *pcb, u_char *pkt, int len);
00174 static void ccp_protrej(ppp_pcb *pcb);
00175 #if PRINTPKT_SUPPORT
00176 static int ccp_printpkt(const u_char *p, int plen, void (*printer) (void *, const char *, ...), void *arg);
00177 #endif /* PRINTPKT_SUPPORT */
00178 #if PPP_DATAINPUT
00179 static void ccp_datainput(ppp_pcb *pcb, u_char *pkt, int len);
00180 #endif /* PPP_DATAINPUT */
00181 
00182 const struct protent ccp_protent = {
00183     PPP_CCP,
00184     ccp_init,
00185     ccp_input,
00186     ccp_protrej,
00187     ccp_lowerup,
00188     ccp_lowerdown,
00189     ccp_open,
00190     ccp_close,
00191 #if PRINTPKT_SUPPORT
00192     ccp_printpkt,
00193 #endif /* PRINTPKT_SUPPORT */
00194 #if PPP_DATAINPUT
00195     ccp_datainput,
00196 #endif /* PPP_DATAINPUT */
00197 #if PRINTPKT_SUPPORT
00198     "CCP",
00199     "Compressed",
00200 #endif /* PRINTPKT_SUPPORT */
00201 #if PPP_OPTIONS
00202     ccp_option_list,
00203     NULL,
00204 #endif /* PPP_OPTIONS */
00205 #if DEMAND_SUPPORT
00206     NULL,
00207     NULL
00208 #endif /* DEMAND_SUPPORT */
00209 };
00210 
00211 /*
00212  * Callbacks for fsm code.
00213  */
00214 static void ccp_resetci (fsm *);
00215 static int  ccp_cilen (fsm *);
00216 static void ccp_addci (fsm *, u_char *, int *);
00217 static int  ccp_ackci (fsm *, u_char *, int);
00218 static int  ccp_nakci (fsm *, u_char *, int, int);
00219 static int  ccp_rejci (fsm *, u_char *, int);
00220 static int  ccp_reqci (fsm *, u_char *, int *, int);
00221 static void ccp_up (fsm *);
00222 static void ccp_down (fsm *);
00223 static int  ccp_extcode (fsm *, int, int, u_char *, int);
00224 static void ccp_rack_timeout (void *);
00225 static const char *method_name (ccp_options *, ccp_options *);
00226 
00227 static const fsm_callbacks ccp_callbacks = {
00228     ccp_resetci,
00229     ccp_cilen,
00230     ccp_addci,
00231     ccp_ackci,
00232     ccp_nakci,
00233     ccp_rejci,
00234     ccp_reqci,
00235     ccp_up,
00236     ccp_down,
00237     NULL,
00238     NULL,
00239     NULL,
00240     NULL,
00241     ccp_extcode,
00242     "CCP"
00243 };
00244 
00245 /*
00246  * Do we want / did we get any compression?
00247  */
00248 static int ccp_anycompress(ccp_options *opt) {
00249     return (0
00250 #if DEFLATE_SUPPORT
00251     || (opt)->deflate
00252 #endif /* DEFLATE_SUPPORT */
00253 #if BSDCOMPRESS_SUPPORT
00254     || (opt)->bsd_compress
00255 #endif /* BSDCOMPRESS_SUPPORT */
00256 #if PREDICTOR_SUPPORT
00257     || (opt)->predictor_1 || (opt)->predictor_2
00258 #endif /* PREDICTOR_SUPPORT */
00259 #if MPPE_SUPPORT
00260     || (opt)->mppe
00261 #endif /* MPPE_SUPPORT */
00262     );
00263 }
00264 
00265 /*
00266  * Local state (mainly for handling reset-reqs and reset-acks).
00267  */
00268 #define RACK_PENDING    1   /* waiting for reset-ack */
00269 #define RREQ_REPEAT 2   /* send another reset-req if no reset-ack */
00270 
00271 #define RACKTIMEOUT 1   /* second */
00272 
00273 #if PPP_OPTIONS
00274 /*
00275  * Option parsing
00276  */
00277 static int
00278 setbsdcomp(argv)
00279     char **argv;
00280 {
00281     int rbits, abits;
00282     char *str, *endp;
00283 
00284     str = *argv;
00285     abits = rbits = strtol(str, &endp, 0);
00286     if (endp != str && *endp == ',') {
00287     str = endp + 1;
00288     abits = strtol(str, &endp, 0);
00289     }
00290     if (*endp != 0 || endp == str) {
00291     option_error("invalid parameter '%s' for bsdcomp option", *argv);
00292     return 0;
00293     }
00294     if ((rbits != 0 && (rbits < BSD_MIN_BITS || rbits > BSD_MAX_BITS))
00295     || (abits != 0 && (abits < BSD_MIN_BITS || abits > BSD_MAX_BITS))) {
00296     option_error("bsdcomp option values must be 0 or %d .. %d",
00297              BSD_MIN_BITS, BSD_MAX_BITS);
00298     return 0;
00299     }
00300     if (rbits > 0) {
00301     ccp_wantoptions[0].bsd_compress = 1;
00302     ccp_wantoptions[0].bsd_bits = rbits;
00303     } else
00304     ccp_wantoptions[0].bsd_compress = 0;
00305     if (abits > 0) {
00306     ccp_allowoptions[0].bsd_compress = 1;
00307     ccp_allowoptions[0].bsd_bits = abits;
00308     } else
00309     ccp_allowoptions[0].bsd_compress = 0;
00310     ppp_slprintf(bsd_value, sizeof(bsd_value),
00311          rbits == abits? "%d": "%d,%d", rbits, abits);
00312 
00313     return 1;
00314 }
00315 
00316 static int
00317 setdeflate(argv)
00318     char **argv;
00319 {
00320     int rbits, abits;
00321     char *str, *endp;
00322 
00323     str = *argv;
00324     abits = rbits = strtol(str, &endp, 0);
00325     if (endp != str && *endp == ',') {
00326     str = endp + 1;
00327     abits = strtol(str, &endp, 0);
00328     }
00329     if (*endp != 0 || endp == str) {
00330     option_error("invalid parameter '%s' for deflate option", *argv);
00331     return 0;
00332     }
00333     if ((rbits != 0 && (rbits < DEFLATE_MIN_SIZE || rbits > DEFLATE_MAX_SIZE))
00334     || (abits != 0 && (abits < DEFLATE_MIN_SIZE
00335               || abits > DEFLATE_MAX_SIZE))) {
00336     option_error("deflate option values must be 0 or %d .. %d",
00337              DEFLATE_MIN_SIZE, DEFLATE_MAX_SIZE);
00338     return 0;
00339     }
00340     if (rbits == DEFLATE_MIN_SIZE || abits == DEFLATE_MIN_SIZE) {
00341     if (rbits == DEFLATE_MIN_SIZE)
00342         rbits = DEFLATE_MIN_WORKS;
00343     if (abits == DEFLATE_MIN_SIZE)
00344         abits = DEFLATE_MIN_WORKS;
00345     warn("deflate option value of %d changed to %d to avoid zlib bug",
00346          DEFLATE_MIN_SIZE, DEFLATE_MIN_WORKS);
00347     }
00348     if (rbits > 0) {
00349     ccp_wantoptions[0].deflate = 1;
00350     ccp_wantoptions[0].deflate_size = rbits;
00351     } else
00352     ccp_wantoptions[0].deflate = 0;
00353     if (abits > 0) {
00354     ccp_allowoptions[0].deflate = 1;
00355     ccp_allowoptions[0].deflate_size = abits;
00356     } else
00357     ccp_allowoptions[0].deflate = 0;
00358     ppp_slprintf(deflate_value, sizeof(deflate_value),
00359          rbits == abits? "%d": "%d,%d", rbits, abits);
00360 
00361     return 1;
00362 }
00363 #endif /* PPP_OPTIONS */
00364 
00365 /*
00366  * ccp_init - initialize CCP.
00367  */
00368 static void ccp_init(ppp_pcb *pcb) {
00369     fsm *f = &pcb->ccp_fsm;
00370 
00371     f->pcb = pcb;
00372     f->protocol = PPP_CCP;
00373     f->callbacks = &ccp_callbacks;
00374     fsm_init(f);
00375 
00376 #if 0 /* Not necessary, everything is cleared in ppp_new() */
00377     memset(wo, 0, sizeof(*wo));
00378     memset(go, 0, sizeof(*go));
00379     memset(ao, 0, sizeof(*ao));
00380     memset(ho, 0, sizeof(*ho));
00381 #endif /* 0 */
00382 
00383 #if DEFLATE_SUPPORT
00384     wo->deflate = 1;
00385     wo->deflate_size = DEFLATE_MAX_SIZE;
00386     wo->deflate_correct = 1;
00387     wo->deflate_draft = 1;
00388     ao->deflate = 1;
00389     ao->deflate_size = DEFLATE_MAX_SIZE;
00390     ao->deflate_correct = 1;
00391     ao->deflate_draft = 1;
00392 #endif /* DEFLATE_SUPPORT */
00393 
00394 #if BSDCOMPRESS_SUPPORT
00395     wo->bsd_compress = 1;
00396     wo->bsd_bits = BSD_MAX_BITS;
00397     ao->bsd_compress = 1;
00398     ao->bsd_bits = BSD_MAX_BITS;
00399 #endif /* BSDCOMPRESS_SUPPORT */
00400 
00401 #if PREDICTOR_SUPPORT
00402     ao->predictor_1 = 1;
00403 #endif /* PREDICTOR_SUPPORT */
00404 }
00405 
00406 /*
00407  * ccp_open - CCP is allowed to come up.
00408  */
00409 static void ccp_open(ppp_pcb *pcb) {
00410     fsm *f = &pcb->ccp_fsm;
00411     ccp_options *go = &pcb->ccp_gotoptions;
00412 
00413     if (f->state != PPP_FSM_OPENED)
00414     ccp_set(pcb, 1, 0, 0, 0);
00415 
00416     /*
00417      * Find out which compressors the kernel supports before
00418      * deciding whether to open in silent mode.
00419      */
00420     ccp_resetci(f);
00421     if (!ccp_anycompress(go))
00422     f->flags |= OPT_SILENT;
00423 
00424     fsm_open(f);
00425 }
00426 
00427 /*
00428  * ccp_close - Terminate CCP.
00429  */
00430 static void ccp_close(ppp_pcb *pcb, const char *reason) {
00431     fsm *f = &pcb->ccp_fsm;
00432     ccp_set(pcb, 0, 0, 0, 0);
00433     fsm_close(f, reason);
00434 }
00435 
00436 /*
00437  * ccp_lowerup - we may now transmit CCP packets.
00438  */
00439 static void ccp_lowerup(ppp_pcb *pcb) {
00440     fsm *f = &pcb->ccp_fsm;
00441     fsm_lowerup(f);
00442 }
00443 
00444 /*
00445  * ccp_lowerdown - we may not transmit CCP packets.
00446  */
00447 static void ccp_lowerdown(ppp_pcb *pcb) {
00448     fsm *f = &pcb->ccp_fsm;
00449     fsm_lowerdown(f);
00450 }
00451 
00452 /*
00453  * ccp_input - process a received CCP packet.
00454  */
00455 static void ccp_input(ppp_pcb *pcb, u_char *p, int len) {
00456     fsm *f = &pcb->ccp_fsm;
00457     ccp_options *go = &pcb->ccp_gotoptions;
00458     int oldstate;
00459 
00460     /*
00461      * Check for a terminate-request so we can print a message.
00462      */
00463     oldstate = f->state;
00464     fsm_input(f, p, len);
00465     if (oldstate == PPP_FSM_OPENED && p[0] == TERMREQ && f->state != PPP_FSM_OPENED) {
00466     ppp_notice("Compression disabled by peer.");
00467 #if MPPE_SUPPORT
00468     if (go->mppe) {
00469         ppp_error("MPPE disabled, closing LCP");
00470         lcp_close(pcb, "MPPE disabled by peer");
00471     }
00472 #endif /* MPPE_SUPPORT */
00473     }
00474 
00475     /*
00476      * If we get a terminate-ack and we're not asking for compression,
00477      * close CCP.
00478      */
00479     if (oldstate == PPP_FSM_REQSENT && p[0] == TERMACK
00480     && !ccp_anycompress(go))
00481     ccp_close(pcb, "No compression negotiated");
00482 }
00483 
00484 /*
00485  * Handle a CCP-specific code.
00486  */
00487 static int ccp_extcode(fsm *f, int code, int id, u_char *p, int len) {
00488     ppp_pcb *pcb = f->pcb;
00489     LWIP_UNUSED_ARG(p);
00490     LWIP_UNUSED_ARG(len);
00491 
00492     switch (code) {
00493     case CCP_RESETREQ:
00494     if (f->state != PPP_FSM_OPENED)
00495         break;
00496     ccp_reset_comp(pcb);
00497     /* send a reset-ack, which the transmitter will see and
00498        reset its compression state. */
00499     fsm_sdata(f, CCP_RESETACK, id, NULL, 0);
00500     break;
00501 
00502     case CCP_RESETACK:
00503     if ((pcb->ccp_localstate & RACK_PENDING) && id == f->reqid) {
00504         pcb->ccp_localstate &= ~(RACK_PENDING | RREQ_REPEAT);
00505         UNTIMEOUT(ccp_rack_timeout, f);
00506         ccp_reset_decomp(pcb);
00507     }
00508     break;
00509 
00510     default:
00511     return 0;
00512     }
00513 
00514     return 1;
00515 }
00516 
00517 /*
00518  * ccp_protrej - peer doesn't talk CCP.
00519  */
00520 static void ccp_protrej(ppp_pcb *pcb) {
00521     fsm *f = &pcb->ccp_fsm;
00522 #if MPPE_SUPPORT
00523     ccp_options *go = &pcb->ccp_gotoptions;
00524 #endif /* MPPE_SUPPORT */
00525 
00526     ccp_set(pcb, 0, 0, 0, 0);
00527     fsm_lowerdown(f);
00528 
00529 #if MPPE_SUPPORT
00530     if (go->mppe) {
00531     ppp_error("MPPE required but peer negotiation failed");
00532     lcp_close(pcb, "MPPE required but peer negotiation failed");
00533     }
00534 #endif /* MPPE_SUPPORT */
00535 
00536 }
00537 
00538 /*
00539  * ccp_resetci - initialize at start of negotiation.
00540  */
00541 static void ccp_resetci(fsm *f) {
00542     ppp_pcb *pcb = f->pcb;
00543     ccp_options *go = &pcb->ccp_gotoptions;
00544     ccp_options *wo = &pcb->ccp_wantoptions;
00545 #if MPPE_SUPPORT
00546     ccp_options *ao = &pcb->ccp_allowoptions;
00547 #endif /* MPPE_SUPPORT */
00548 #if DEFLATE_SUPPORT || BSDCOMPRESS_SUPPORT || PREDICTOR_SUPPORT
00549     u_char opt_buf[CCP_MAX_OPTION_LENGTH];
00550 #endif /* DEFLATE_SUPPORT || BSDCOMPRESS_SUPPORT || PREDICTOR_SUPPORT */
00551 #if DEFLATE_SUPPORT || BSDCOMPRESS_SUPPORT
00552     int res;
00553 #endif /* DEFLATE_SUPPORT || BSDCOMPRESS_SUPPORT */
00554 
00555 #if MPPE_SUPPORT
00556     if (pcb->settings.require_mppe) {
00557     wo->mppe = ao->mppe =
00558             (pcb->settings.refuse_mppe_40 ? 0 : MPPE_OPT_40)
00559           | (pcb->settings.refuse_mppe_128 ? 0 : MPPE_OPT_128);
00560     }
00561 #endif /* MPPE_SUPPORT */
00562 
00563     *go = *wo;
00564     pcb->ccp_all_rejected = 0;
00565 
00566 #if MPPE_SUPPORT
00567     if (go->mppe) {
00568     int auth_mschap_bits = pcb->auth_done;
00569     int numbits;
00570 
00571     /*
00572      * Start with a basic sanity check: mschap[v2] auth must be in
00573      * exactly one direction.  RFC 3079 says that the keys are
00574      * 'derived from the credentials of the peer that initiated the call',
00575      * however the PPP protocol doesn't have such a concept, and pppd
00576      * cannot get this info externally.  Instead we do the best we can.
00577      * NB: If MPPE is required, all other compression opts are invalid.
00578      *     So, we return right away if we can't do it.
00579      */
00580 
00581     /* Leave only the mschap auth bits set */
00582     auth_mschap_bits &= (CHAP_MS_WITHPEER  | CHAP_MS_PEER |
00583                  CHAP_MS2_WITHPEER | CHAP_MS2_PEER);
00584     /* Count the mschap auths */
00585     auth_mschap_bits >>= CHAP_MS_SHIFT;
00586     numbits = 0;
00587     do {
00588         numbits += auth_mschap_bits & 1;
00589         auth_mschap_bits >>= 1;
00590     } while (auth_mschap_bits);
00591     if (numbits > 1) {
00592         ppp_error("MPPE required, but auth done in both directions.");
00593         lcp_close(pcb, "MPPE required but not available");
00594         return;
00595     }
00596     if (!numbits) {
00597         ppp_error("MPPE required, but MS-CHAP[v2] auth not performed.");
00598         lcp_close(pcb, "MPPE required but not available");
00599         return;
00600     }
00601 
00602     /* A plugin (eg radius) may not have obtained key material. */
00603     if (!pcb->mppe_keys_set) {
00604         ppp_error("MPPE required, but keys are not available.  "
00605           "Possible plugin problem?");
00606         lcp_close(pcb, "MPPE required but not available");
00607         return;
00608     }
00609 
00610     /* LM auth not supported for MPPE */
00611     if (pcb->auth_done & (CHAP_MS_WITHPEER | CHAP_MS_PEER)) {
00612         /* This might be noise */
00613         if (go->mppe & MPPE_OPT_40) {
00614         ppp_notice("Disabling 40-bit MPPE; MS-CHAP LM not supported");
00615         go->mppe &= ~MPPE_OPT_40;
00616         wo->mppe &= ~MPPE_OPT_40;
00617         }
00618     }
00619 
00620     /* Last check: can we actually negotiate something? */
00621     if (!(go->mppe & (MPPE_OPT_40 | MPPE_OPT_128))) {
00622         /* Could be misconfig, could be 40-bit disabled above. */
00623         ppp_error("MPPE required, but both 40-bit and 128-bit disabled.");
00624         lcp_close(pcb, "MPPE required but not available");
00625         return;
00626     }
00627 
00628     /* sync options */
00629     ao->mppe = go->mppe;
00630     /* MPPE is not compatible with other compression types */
00631 #if BSDCOMPRESS_SUPPORT
00632     ao->bsd_compress = go->bsd_compress = 0;
00633 #endif /* BSDCOMPRESS_SUPPORT */
00634 #if PREDICTOR_SUPPORT
00635     ao->predictor_1  = go->predictor_1  = 0;
00636     ao->predictor_2  = go->predictor_2  = 0;
00637 #endif /* PREDICTOR_SUPPORT */
00638 #if DEFLATE_SUPPORT
00639     ao->deflate      = go->deflate      = 0;
00640 #endif /* DEFLATE_SUPPORT */
00641     }
00642 #endif /* MPPE_SUPPORT */
00643 
00644     /*
00645      * Check whether the kernel knows about the various
00646      * compression methods we might request.
00647      */
00648 #if BSDCOMPRESS_SUPPORT
00649     /* FIXME: we don't need to test if BSD compress is available
00650      * if BSDCOMPRESS_SUPPORT is set, it is.
00651      */
00652     if (go->bsd_compress) {
00653     opt_buf[0] = CI_BSD_COMPRESS;
00654     opt_buf[1] = CILEN_BSD_COMPRESS;
00655     for (;;) {
00656         if (go->bsd_bits < BSD_MIN_BITS) {
00657         go->bsd_compress = 0;
00658         break;
00659         }
00660         opt_buf[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits);
00661         res = ccp_test(pcb, opt_buf, CILEN_BSD_COMPRESS, 0);
00662         if (res > 0) {
00663         break;
00664         } else if (res < 0) {
00665         go->bsd_compress = 0;
00666         break;
00667         }
00668         go->bsd_bits--;
00669     }
00670     }
00671 #endif /* BSDCOMPRESS_SUPPORT */
00672 #if DEFLATE_SUPPORT
00673     /* FIXME: we don't need to test if deflate is available
00674      * if DEFLATE_SUPPORT is set, it is.
00675      */
00676     if (go->deflate) {
00677     if (go->deflate_correct) {
00678         opt_buf[0] = CI_DEFLATE;
00679         opt_buf[1] = CILEN_DEFLATE;
00680         opt_buf[3] = DEFLATE_CHK_SEQUENCE;
00681         for (;;) {
00682         if (go->deflate_size < DEFLATE_MIN_WORKS) {
00683             go->deflate_correct = 0;
00684             break;
00685         }
00686         opt_buf[2] = DEFLATE_MAKE_OPT(go->deflate_size);
00687         res = ccp_test(pcb, opt_buf, CILEN_DEFLATE, 0);
00688         if (res > 0) {
00689             break;
00690         } else if (res < 0) {
00691             go->deflate_correct = 0;
00692             break;
00693         }
00694         go->deflate_size--;
00695         }
00696     }
00697     if (go->deflate_draft) {
00698         opt_buf[0] = CI_DEFLATE_DRAFT;
00699         opt_buf[1] = CILEN_DEFLATE;
00700         opt_buf[3] = DEFLATE_CHK_SEQUENCE;
00701         for (;;) {
00702         if (go->deflate_size < DEFLATE_MIN_WORKS) {
00703             go->deflate_draft = 0;
00704             break;
00705         }
00706         opt_buf[2] = DEFLATE_MAKE_OPT(go->deflate_size);
00707         res = ccp_test(pcb, opt_buf, CILEN_DEFLATE, 0);
00708         if (res > 0) {
00709             break;
00710         } else if (res < 0) {
00711             go->deflate_draft = 0;
00712             break;
00713         }
00714         go->deflate_size--;
00715         }
00716     }
00717     if (!go->deflate_correct && !go->deflate_draft)
00718         go->deflate = 0;
00719     }
00720 #endif /* DEFLATE_SUPPORT */
00721 #if PREDICTOR_SUPPORT
00722     /* FIXME: we don't need to test if predictor is available,
00723      * if PREDICTOR_SUPPORT is set, it is.
00724      */
00725     if (go->predictor_1) {
00726     opt_buf[0] = CI_PREDICTOR_1;
00727     opt_buf[1] = CILEN_PREDICTOR_1;
00728     if (ccp_test(pcb, opt_buf, CILEN_PREDICTOR_1, 0) <= 0)
00729         go->predictor_1 = 0;
00730     }
00731     if (go->predictor_2) {
00732     opt_buf[0] = CI_PREDICTOR_2;
00733     opt_buf[1] = CILEN_PREDICTOR_2;
00734     if (ccp_test(pcb, opt_buf, CILEN_PREDICTOR_2, 0) <= 0)
00735         go->predictor_2 = 0;
00736     }
00737 #endif /* PREDICTOR_SUPPORT */
00738 }
00739 
00740 /*
00741  * ccp_cilen - Return total length of our configuration info.
00742  */
00743 static int ccp_cilen(fsm *f) {
00744     ppp_pcb *pcb = f->pcb;
00745     ccp_options *go = &pcb->ccp_gotoptions;
00746 
00747     return 0
00748 #if BSDCOMPRESS_SUPPORT
00749     + (go->bsd_compress? CILEN_BSD_COMPRESS: 0)
00750 #endif /* BSDCOMPRESS_SUPPORT */
00751 #if DEFLATE_SUPPORT
00752     + (go->deflate && go->deflate_correct? CILEN_DEFLATE: 0)
00753     + (go->deflate && go->deflate_draft? CILEN_DEFLATE: 0)
00754 #endif /* DEFLATE_SUPPORT */
00755 #if PREDICTOR_SUPPORT
00756     + (go->predictor_1? CILEN_PREDICTOR_1: 0)
00757     + (go->predictor_2? CILEN_PREDICTOR_2: 0)
00758 #endif /* PREDICTOR_SUPPORT */
00759 #if MPPE_SUPPORT
00760     + (go->mppe? CILEN_MPPE: 0)
00761 #endif /* MPPE_SUPPORT */
00762     ;
00763 }
00764 
00765 /*
00766  * ccp_addci - put our requests in a packet.
00767  */
00768 static void ccp_addci(fsm *f, u_char *p, int *lenp) {
00769     ppp_pcb *pcb = f->pcb;
00770     ccp_options *go = &pcb->ccp_gotoptions;
00771     u_char *p0 = p;
00772 
00773     /*
00774      * Add the compression types that we can receive, in decreasing
00775      * preference order.
00776      */
00777 #if MPPE_SUPPORT
00778     if (go->mppe) {
00779     p[0] = CI_MPPE;
00780     p[1] = CILEN_MPPE;
00781     MPPE_OPTS_TO_CI(go->mppe, &p[2]);
00782     mppe_init(pcb, &pcb->mppe_decomp, go->mppe);
00783     p += CILEN_MPPE;
00784     }
00785 #endif /* MPPE_SUPPORT */
00786 #if DEFLATE_SUPPORT
00787     if (go->deflate) {
00788     if (go->deflate_correct) {
00789         p[0] = CI_DEFLATE;
00790         p[1] = CILEN_DEFLATE;
00791         p[2] = DEFLATE_MAKE_OPT(go->deflate_size);
00792         p[3] = DEFLATE_CHK_SEQUENCE;
00793         p += CILEN_DEFLATE;
00794     }
00795     if (go->deflate_draft) {
00796         p[0] = CI_DEFLATE_DRAFT;
00797         p[1] = CILEN_DEFLATE;
00798         p[2] = p[2 - CILEN_DEFLATE];
00799         p[3] = DEFLATE_CHK_SEQUENCE;
00800         p += CILEN_DEFLATE;
00801     }
00802     }
00803 #endif /* DEFLATE_SUPPORT */
00804 #if BSDCOMPRESS_SUPPORT
00805     if (go->bsd_compress) {
00806     p[0] = CI_BSD_COMPRESS;
00807     p[1] = CILEN_BSD_COMPRESS;
00808     p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits);
00809     p += CILEN_BSD_COMPRESS;
00810     }
00811 #endif /* BSDCOMPRESS_SUPPORT */
00812 #if PREDICTOR_SUPPORT
00813     /* XXX Should Predictor 2 be preferable to Predictor 1? */
00814     if (go->predictor_1) {
00815     p[0] = CI_PREDICTOR_1;
00816     p[1] = CILEN_PREDICTOR_1;
00817     p += CILEN_PREDICTOR_1;
00818     }
00819     if (go->predictor_2) {
00820     p[0] = CI_PREDICTOR_2;
00821     p[1] = CILEN_PREDICTOR_2;
00822     p += CILEN_PREDICTOR_2;
00823     }
00824 #endif /* PREDICTOR_SUPPORT */
00825 
00826     go->method = (p > p0)? p0[0]: 0;
00827 
00828     *lenp = p - p0;
00829 }
00830 
00831 /*
00832  * ccp_ackci - process a received configure-ack, and return
00833  * 1 iff the packet was OK.
00834  */
00835 static int ccp_ackci(fsm *f, u_char *p, int len) {
00836     ppp_pcb *pcb = f->pcb;
00837     ccp_options *go = &pcb->ccp_gotoptions;
00838 #if BSDCOMPRESS_SUPPORT || PREDICTOR_SUPPORT
00839     u_char *p0 = p;
00840 #endif /* BSDCOMPRESS_SUPPORT || PREDICTOR_SUPPORT */
00841 
00842 #if MPPE_SUPPORT
00843     if (go->mppe) {
00844     u_char opt_buf[CILEN_MPPE];
00845 
00846     opt_buf[0] = CI_MPPE;
00847     opt_buf[1] = CILEN_MPPE;
00848     MPPE_OPTS_TO_CI(go->mppe, &opt_buf[2]);
00849     if (len < CILEN_MPPE || memcmp(opt_buf, p, CILEN_MPPE))
00850         return 0;
00851     p += CILEN_MPPE;
00852     len -= CILEN_MPPE;
00853     /* XXX Cope with first/fast ack */
00854     if (len == 0)
00855         return 1;
00856     }
00857 #endif /* MPPE_SUPPORT */
00858 #if DEFLATE_SUPPORT
00859     if (go->deflate) {
00860     if (len < CILEN_DEFLATE
00861         || p[0] != (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT)
00862         || p[1] != CILEN_DEFLATE
00863         || p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
00864         || p[3] != DEFLATE_CHK_SEQUENCE)
00865         return 0;
00866     p += CILEN_DEFLATE;
00867     len -= CILEN_DEFLATE;
00868     /* XXX Cope with first/fast ack */
00869     if (len == 0)
00870         return 1;
00871     if (go->deflate_correct && go->deflate_draft) {
00872         if (len < CILEN_DEFLATE
00873         || p[0] != CI_DEFLATE_DRAFT
00874         || p[1] != CILEN_DEFLATE
00875         || p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
00876         || p[3] != DEFLATE_CHK_SEQUENCE)
00877         return 0;
00878         p += CILEN_DEFLATE;
00879         len -= CILEN_DEFLATE;
00880     }
00881     }
00882 #endif /* DEFLATE_SUPPORT */
00883 #if BSDCOMPRESS_SUPPORT
00884     if (go->bsd_compress) {
00885     if (len < CILEN_BSD_COMPRESS
00886         || p[0] != CI_BSD_COMPRESS || p[1] != CILEN_BSD_COMPRESS
00887         || p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits))
00888         return 0;
00889     p += CILEN_BSD_COMPRESS;
00890     len -= CILEN_BSD_COMPRESS;
00891     /* XXX Cope with first/fast ack */
00892     if (p == p0 && len == 0)
00893         return 1;
00894     }
00895 #endif /* BSDCOMPRESS_SUPPORT */
00896 #if PREDICTOR_SUPPORT
00897     if (go->predictor_1) {
00898     if (len < CILEN_PREDICTOR_1
00899         || p[0] != CI_PREDICTOR_1 || p[1] != CILEN_PREDICTOR_1)
00900         return 0;
00901     p += CILEN_PREDICTOR_1;
00902     len -= CILEN_PREDICTOR_1;
00903     /* XXX Cope with first/fast ack */
00904     if (p == p0 && len == 0)
00905         return 1;
00906     }
00907     if (go->predictor_2) {
00908     if (len < CILEN_PREDICTOR_2
00909         || p[0] != CI_PREDICTOR_2 || p[1] != CILEN_PREDICTOR_2)
00910         return 0;
00911     p += CILEN_PREDICTOR_2;
00912     len -= CILEN_PREDICTOR_2;
00913     /* XXX Cope with first/fast ack */
00914     if (p == p0 && len == 0)
00915         return 1;
00916     }
00917 #endif /* PREDICTOR_SUPPORT */
00918 
00919     if (len != 0)
00920     return 0;
00921     return 1;
00922 }
00923 
00924 /*
00925  * ccp_nakci - process received configure-nak.
00926  * Returns 1 iff the nak was OK.
00927  */
00928 static int ccp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) {
00929     ppp_pcb *pcb = f->pcb;
00930     ccp_options *go = &pcb->ccp_gotoptions;
00931     ccp_options no;     /* options we've seen already */
00932     ccp_options try_;       /* options to ask for next time */
00933     LWIP_UNUSED_ARG(treat_as_reject);
00934 #if !MPPE_SUPPORT && !DEFLATE_SUPPORT && !BSDCOMPRESS_SUPPORT
00935     LWIP_UNUSED_ARG(p);
00936     LWIP_UNUSED_ARG(len);
00937 #endif /* !MPPE_SUPPORT && !DEFLATE_SUPPORT && !BSDCOMPRESS_SUPPORT */
00938 
00939     memset(&no, 0, sizeof(no));
00940     try_ = *go;
00941 
00942 #if MPPE_SUPPORT
00943     if (go->mppe && len >= CILEN_MPPE
00944     && p[0] == CI_MPPE && p[1] == CILEN_MPPE) {
00945     no.mppe = 1;
00946     /*
00947      * Peer wants us to use a different strength or other setting.
00948      * Fail if we aren't willing to use his suggestion.
00949      */
00950     MPPE_CI_TO_OPTS(&p[2], try_.mppe);
00951     if ((try_.mppe & MPPE_OPT_STATEFUL) && pcb->settings.refuse_mppe_stateful) {
00952         ppp_error("Refusing MPPE stateful mode offered by peer");
00953         try_.mppe = 0;
00954     } else if (((go->mppe | MPPE_OPT_STATEFUL) & try_.mppe) != try_.mppe) {
00955         /* Peer must have set options we didn't request (suggest) */
00956         try_.mppe = 0;
00957     }
00958 
00959     if (!try_.mppe) {
00960         ppp_error("MPPE required but peer negotiation failed");
00961         lcp_close(pcb, "MPPE required but peer negotiation failed");
00962     }
00963     }
00964 #endif /* MPPE_SUPPORT */
00965 #if DEFLATE_SUPPORT
00966     if (go->deflate && len >= CILEN_DEFLATE
00967     && p[0] == (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT)
00968     && p[1] == CILEN_DEFLATE) {
00969     no.deflate = 1;
00970     /*
00971      * Peer wants us to use a different code size or something.
00972      * Stop asking for Deflate if we don't understand his suggestion.
00973      */
00974     if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL
00975         || DEFLATE_SIZE(p[2]) < DEFLATE_MIN_WORKS
00976         || p[3] != DEFLATE_CHK_SEQUENCE)
00977         try_.deflate = 0;
00978     else if (DEFLATE_SIZE(p[2]) < go->deflate_size)
00979         try_.deflate_size = DEFLATE_SIZE(p[2]);
00980     p += CILEN_DEFLATE;
00981     len -= CILEN_DEFLATE;
00982     if (go->deflate_correct && go->deflate_draft
00983         && len >= CILEN_DEFLATE && p[0] == CI_DEFLATE_DRAFT
00984         && p[1] == CILEN_DEFLATE) {
00985         p += CILEN_DEFLATE;
00986         len -= CILEN_DEFLATE;
00987     }
00988     }
00989 #endif /* DEFLATE_SUPPORT */
00990 #if BSDCOMPRESS_SUPPORT
00991     if (go->bsd_compress && len >= CILEN_BSD_COMPRESS
00992     && p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) {
00993     no.bsd_compress = 1;
00994     /*
00995      * Peer wants us to use a different number of bits
00996      * or a different version.
00997      */
00998     if (BSD_VERSION(p[2]) != BSD_CURRENT_VERSION)
00999         try_.bsd_compress = 0;
01000     else if (BSD_NBITS(p[2]) < go->bsd_bits)
01001         try_.bsd_bits = BSD_NBITS(p[2]);
01002     p += CILEN_BSD_COMPRESS;
01003     len -= CILEN_BSD_COMPRESS;
01004     }
01005 #endif /* BSDCOMPRESS_SUPPORT */
01006 
01007     /*
01008      * Predictor-1 and 2 have no options, so they can't be Naked.
01009      *
01010      * There may be remaining options but we ignore them.
01011      */
01012 
01013     if (f->state != PPP_FSM_OPENED)
01014     *go = try_;
01015     return 1;
01016 }
01017 
01018 /*
01019  * ccp_rejci - reject some of our suggested compression methods.
01020  */
01021 static int ccp_rejci(fsm *f, u_char *p, int len) {
01022     ppp_pcb *pcb = f->pcb;
01023     ccp_options *go = &pcb->ccp_gotoptions;
01024     ccp_options try_;       /* options to request next time */
01025 
01026     try_ = *go;
01027 
01028     /*
01029      * Cope with empty configure-rejects by ceasing to send
01030      * configure-requests.
01031      */
01032     if (len == 0 && pcb->ccp_all_rejected)
01033     return -1;
01034 
01035 #if MPPE_SUPPORT
01036     if (go->mppe && len >= CILEN_MPPE
01037     && p[0] == CI_MPPE && p[1] == CILEN_MPPE) {
01038     ppp_error("MPPE required but peer refused");
01039     lcp_close(pcb, "MPPE required but peer refused");
01040     p += CILEN_MPPE;
01041     len -= CILEN_MPPE;
01042     }
01043 #endif /* MPPE_SUPPORT */
01044 #if DEFLATE_SUPPORT
01045     if (go->deflate_correct && len >= CILEN_DEFLATE
01046     && p[0] == CI_DEFLATE && p[1] == CILEN_DEFLATE) {
01047     if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
01048         || p[3] != DEFLATE_CHK_SEQUENCE)
01049         return 0;       /* Rej is bad */
01050     try_.deflate_correct = 0;
01051     p += CILEN_DEFLATE;
01052     len -= CILEN_DEFLATE;
01053     }
01054     if (go->deflate_draft && len >= CILEN_DEFLATE
01055     && p[0] == CI_DEFLATE_DRAFT && p[1] == CILEN_DEFLATE) {
01056     if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
01057         || p[3] != DEFLATE_CHK_SEQUENCE)
01058         return 0;       /* Rej is bad */
01059     try_.deflate_draft = 0;
01060     p += CILEN_DEFLATE;
01061     len -= CILEN_DEFLATE;
01062     }
01063     if (!try_.deflate_correct && !try_.deflate_draft)
01064     try_.deflate = 0;
01065 #endif /* DEFLATE_SUPPORT */
01066 #if BSDCOMPRESS_SUPPORT
01067     if (go->bsd_compress && len >= CILEN_BSD_COMPRESS
01068     && p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) {
01069     if (p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits))
01070         return 0;
01071     try_.bsd_compress = 0;
01072     p += CILEN_BSD_COMPRESS;
01073     len -= CILEN_BSD_COMPRESS;
01074     }
01075 #endif /* BSDCOMPRESS_SUPPORT */
01076 #if PREDICTOR_SUPPORT
01077     if (go->predictor_1 && len >= CILEN_PREDICTOR_1
01078     && p[0] == CI_PREDICTOR_1 && p[1] == CILEN_PREDICTOR_1) {
01079     try_.predictor_1 = 0;
01080     p += CILEN_PREDICTOR_1;
01081     len -= CILEN_PREDICTOR_1;
01082     }
01083     if (go->predictor_2 && len >= CILEN_PREDICTOR_2
01084     && p[0] == CI_PREDICTOR_2 && p[1] == CILEN_PREDICTOR_2) {
01085     try_.predictor_2 = 0;
01086     p += CILEN_PREDICTOR_2;
01087     len -= CILEN_PREDICTOR_2;
01088     }
01089 #endif /* PREDICTOR_SUPPORT */
01090 
01091     if (len != 0)
01092     return 0;
01093 
01094     if (f->state != PPP_FSM_OPENED)
01095     *go = try_;
01096 
01097     return 1;
01098 }
01099 
01100 /*
01101  * ccp_reqci - processed a received configure-request.
01102  * Returns CONFACK, CONFNAK or CONFREJ and the packet modified
01103  * appropriately.
01104  */
01105 static int ccp_reqci(fsm *f, u_char *p, int *lenp, int dont_nak) {
01106     ppp_pcb *pcb = f->pcb;
01107     ccp_options *ho = &pcb->ccp_hisoptions;
01108     ccp_options *ao = &pcb->ccp_allowoptions;
01109     int ret, newret;
01110 #if DEFLATE_SUPPORT || BSDCOMPRESS_SUPPORT
01111     int res;
01112     int nb;
01113 #endif /* DEFLATE_SUPPORT || BSDCOMPRESS_SUPPORT */
01114     u_char *p0, *retp;
01115     int len, clen, type;
01116 #if MPPE_SUPPORT
01117     u8_t rej_for_ci_mppe = 1;   /* Are we rejecting based on a bad/missing */
01118                 /* CI_MPPE, or due to other options?       */
01119 #endif /* MPPE_SUPPORT */
01120 
01121     ret = CONFACK;
01122     retp = p0 = p;
01123     len = *lenp;
01124 
01125     memset(ho, 0, sizeof(ccp_options));
01126     ho->method = (len > 0)? p[0]: 0;
01127 
01128     while (len > 0) {
01129     newret = CONFACK;
01130     if (len < 2 || p[1] < 2 || p[1] > len) {
01131         /* length is bad */
01132         clen = len;
01133         newret = CONFREJ;
01134 
01135     } else {
01136         type = p[0];
01137         clen = p[1];
01138 
01139         switch (type) {
01140 #if MPPE_SUPPORT
01141         case CI_MPPE:
01142         if (!ao->mppe || clen != CILEN_MPPE) {
01143             newret = CONFREJ;
01144             break;
01145         }
01146         MPPE_CI_TO_OPTS(&p[2], ho->mppe);
01147 
01148         /* Nak if anything unsupported or unknown are set. */
01149         if (ho->mppe & MPPE_OPT_UNSUPPORTED) {
01150             newret = CONFNAK;
01151             ho->mppe &= ~MPPE_OPT_UNSUPPORTED;
01152         }
01153         if (ho->mppe & MPPE_OPT_UNKNOWN) {
01154             newret = CONFNAK;
01155             ho->mppe &= ~MPPE_OPT_UNKNOWN;
01156         }
01157 
01158         /* Check state opt */
01159         if (ho->mppe & MPPE_OPT_STATEFUL) {
01160             /*
01161              * We can Nak and request stateless, but it's a
01162              * lot easier to just assume the peer will request
01163              * it if he can do it; stateful mode is bad over
01164              * the Internet -- which is where we expect MPPE.
01165              */
01166            if (pcb->settings.refuse_mppe_stateful) {
01167             ppp_error("Refusing MPPE stateful mode offered by peer");
01168             newret = CONFREJ;
01169             break;
01170             }
01171         }
01172 
01173         /* Find out which of {S,L} are set. */
01174         if ((ho->mppe & MPPE_OPT_128)
01175              && (ho->mppe & MPPE_OPT_40)) {
01176             /* Both are set, negotiate the strongest. */
01177             newret = CONFNAK;
01178             if (ao->mppe & MPPE_OPT_128)
01179             ho->mppe &= ~MPPE_OPT_40;
01180             else if (ao->mppe & MPPE_OPT_40)
01181             ho->mppe &= ~MPPE_OPT_128;
01182             else {
01183             newret = CONFREJ;
01184             break;
01185             }
01186         } else if (ho->mppe & MPPE_OPT_128) {
01187             if (!(ao->mppe & MPPE_OPT_128)) {
01188             newret = CONFREJ;
01189             break;
01190             }
01191         } else if (ho->mppe & MPPE_OPT_40) {
01192             if (!(ao->mppe & MPPE_OPT_40)) {
01193             newret = CONFREJ;
01194             break;
01195             }
01196         } else {
01197             /* Neither are set. */
01198             /* We cannot accept this.  */
01199             newret = CONFNAK;
01200             /* Give the peer our idea of what can be used,
01201                so it can choose and confirm */
01202             ho->mppe = ao->mppe;
01203         }
01204 
01205         /* rebuild the opts */
01206         MPPE_OPTS_TO_CI(ho->mppe, &p[2]);
01207         if (newret == CONFACK) {
01208             int mtu;
01209 
01210             mppe_init(pcb, &pcb->mppe_comp, ho->mppe);
01211             /*
01212              * We need to decrease the interface MTU by MPPE_PAD
01213              * because MPPE frames **grow**.  The kernel [must]
01214              * allocate MPPE_PAD extra bytes in xmit buffers.
01215              */
01216             mtu = netif_get_mtu(pcb);
01217             if (mtu)
01218             netif_set_mtu(pcb, mtu - MPPE_PAD);
01219             else
01220             newret = CONFREJ;
01221         }
01222 
01223         /*
01224          * We have accepted MPPE or are willing to negotiate
01225          * MPPE parameters.  A CONFREJ is due to subsequent
01226          * (non-MPPE) processing.
01227          */
01228         rej_for_ci_mppe = 0;
01229         break;
01230 #endif /* MPPE_SUPPORT */
01231 #if DEFLATE_SUPPORT
01232         case CI_DEFLATE:
01233         case CI_DEFLATE_DRAFT:
01234         if (!ao->deflate || clen != CILEN_DEFLATE
01235             || (!ao->deflate_correct && type == CI_DEFLATE)
01236             || (!ao->deflate_draft && type == CI_DEFLATE_DRAFT)) {
01237             newret = CONFREJ;
01238             break;
01239         }
01240 
01241         ho->deflate = 1;
01242         ho->deflate_size = nb = DEFLATE_SIZE(p[2]);
01243         if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL
01244             || p[3] != DEFLATE_CHK_SEQUENCE
01245             || nb > ao->deflate_size || nb < DEFLATE_MIN_WORKS) {
01246             newret = CONFNAK;
01247             if (!dont_nak) {
01248             p[2] = DEFLATE_MAKE_OPT(ao->deflate_size);
01249             p[3] = DEFLATE_CHK_SEQUENCE;
01250             /* fall through to test this #bits below */
01251             } else
01252             break;
01253         }
01254 
01255         /*
01256          * Check whether we can do Deflate with the window
01257          * size they want.  If the window is too big, reduce
01258          * it until the kernel can cope and nak with that.
01259          * We only check this for the first option.
01260          */
01261         if (p == p0) {
01262             for (;;) {
01263             res = ccp_test(pcb, p, CILEN_DEFLATE, 1);
01264             if (res > 0)
01265                 break;      /* it's OK now */
01266             if (res < 0 || nb == DEFLATE_MIN_WORKS || dont_nak) {
01267                 newret = CONFREJ;
01268                 p[2] = DEFLATE_MAKE_OPT(ho->deflate_size);
01269                 break;
01270             }
01271             newret = CONFNAK;
01272             --nb;
01273             p[2] = DEFLATE_MAKE_OPT(nb);
01274             }
01275         }
01276         break;
01277 #endif /* DEFLATE_SUPPORT */
01278 #if BSDCOMPRESS_SUPPORT
01279         case CI_BSD_COMPRESS:
01280         if (!ao->bsd_compress || clen != CILEN_BSD_COMPRESS) {
01281             newret = CONFREJ;
01282             break;
01283         }
01284 
01285         ho->bsd_compress = 1;
01286         ho->bsd_bits = nb = BSD_NBITS(p[2]);
01287         if (BSD_VERSION(p[2]) != BSD_CURRENT_VERSION
01288             || nb > ao->bsd_bits || nb < BSD_MIN_BITS) {
01289             newret = CONFNAK;
01290             if (!dont_nak) {
01291             p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, ao->bsd_bits);
01292             /* fall through to test this #bits below */
01293             } else
01294             break;
01295         }
01296 
01297         /*
01298          * Check whether we can do BSD-Compress with the code
01299          * size they want.  If the code size is too big, reduce
01300          * it until the kernel can cope and nak with that.
01301          * We only check this for the first option.
01302          */
01303         if (p == p0) {
01304             for (;;) {
01305             res = ccp_test(pcb, p, CILEN_BSD_COMPRESS, 1);
01306             if (res > 0)
01307                 break;
01308             if (res < 0 || nb == BSD_MIN_BITS || dont_nak) {
01309                 newret = CONFREJ;
01310                 p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION,
01311                         ho->bsd_bits);
01312                 break;
01313             }
01314             newret = CONFNAK;
01315             --nb;
01316             p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, nb);
01317             }
01318         }
01319         break;
01320 #endif /* BSDCOMPRESS_SUPPORT */
01321 #if PREDICTOR_SUPPORT
01322         case CI_PREDICTOR_1:
01323         if (!ao->predictor_1 || clen != CILEN_PREDICTOR_1) {
01324             newret = CONFREJ;
01325             break;
01326         }
01327 
01328         ho->predictor_1 = 1;
01329         if (p == p0
01330             && ccp_test(pcb, p, CILEN_PREDICTOR_1, 1) <= 0) {
01331             newret = CONFREJ;
01332         }
01333         break;
01334 
01335         case CI_PREDICTOR_2:
01336         if (!ao->predictor_2 || clen != CILEN_PREDICTOR_2) {
01337             newret = CONFREJ;
01338             break;
01339         }
01340 
01341         ho->predictor_2 = 1;
01342         if (p == p0
01343             && ccp_test(pcb, p, CILEN_PREDICTOR_2, 1) <= 0) {
01344             newret = CONFREJ;
01345         }
01346         break;
01347 #endif /* PREDICTOR_SUPPORT */
01348 
01349         default:
01350         newret = CONFREJ;
01351         }
01352     }
01353 
01354     if (newret == CONFNAK && dont_nak)
01355         newret = CONFREJ;
01356     if (!(newret == CONFACK || (newret == CONFNAK && ret == CONFREJ))) {
01357         /* we're returning this option */
01358         if (newret == CONFREJ && ret == CONFNAK)
01359         retp = p0;
01360         ret = newret;
01361         if (p != retp)
01362         MEMCPY(retp, p, clen);
01363         retp += clen;
01364     }
01365 
01366     p += clen;
01367     len -= clen;
01368     }
01369 
01370     if (ret != CONFACK) {
01371     if (ret == CONFREJ && *lenp == retp - p0)
01372         pcb->ccp_all_rejected = 1;
01373     else
01374         *lenp = retp - p0;
01375     }
01376 #if MPPE_SUPPORT
01377     if (ret == CONFREJ && ao->mppe && rej_for_ci_mppe) {
01378     ppp_error("MPPE required but peer negotiation failed");
01379     lcp_close(pcb, "MPPE required but peer negotiation failed");
01380     }
01381 #endif /* MPPE_SUPPORT */
01382     return ret;
01383 }
01384 
01385 /*
01386  * Make a string name for a compression method (or 2).
01387  */
01388 static const char *method_name(ccp_options *opt, ccp_options *opt2) {
01389     static char result[64];
01390 #if !DEFLATE_SUPPORT && !BSDCOMPRESS_SUPPORT
01391     LWIP_UNUSED_ARG(opt2);
01392 #endif /* !DEFLATE_SUPPORT && !BSDCOMPRESS_SUPPORT */
01393 
01394     if (!ccp_anycompress(opt))
01395     return "(none)";
01396     switch (opt->method) {
01397 #if MPPE_SUPPORT
01398     case CI_MPPE:
01399     {
01400     char *p = result;
01401     char *q = result + sizeof(result); /* 1 past result */
01402 
01403     ppp_slprintf(p, q - p, "MPPE ");
01404     p += 5;
01405     if (opt->mppe & MPPE_OPT_128) {
01406         ppp_slprintf(p, q - p, "128-bit ");
01407         p += 8;
01408     }
01409     if (opt->mppe & MPPE_OPT_40) {
01410         ppp_slprintf(p, q - p, "40-bit ");
01411         p += 7;
01412     }
01413     if (opt->mppe & MPPE_OPT_STATEFUL)
01414         ppp_slprintf(p, q - p, "stateful");
01415     else
01416         ppp_slprintf(p, q - p, "stateless");
01417 
01418     break;
01419     }
01420 #endif /* MPPE_SUPPORT */
01421 #if DEFLATE_SUPPORT
01422     case CI_DEFLATE:
01423     case CI_DEFLATE_DRAFT:
01424     if (opt2 != NULL && opt2->deflate_size != opt->deflate_size)
01425         ppp_slprintf(result, sizeof(result), "Deflate%s (%d/%d)",
01426              (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""),
01427              opt->deflate_size, opt2->deflate_size);
01428     else
01429         ppp_slprintf(result, sizeof(result), "Deflate%s (%d)",
01430              (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""),
01431              opt->deflate_size);
01432     break;
01433 #endif /* DEFLATE_SUPPORT */
01434 #if BSDCOMPRESS_SUPPORT
01435     case CI_BSD_COMPRESS:
01436     if (opt2 != NULL && opt2->bsd_bits != opt->bsd_bits)
01437         ppp_slprintf(result, sizeof(result), "BSD-Compress (%d/%d)",
01438              opt->bsd_bits, opt2->bsd_bits);
01439     else
01440         ppp_slprintf(result, sizeof(result), "BSD-Compress (%d)",
01441              opt->bsd_bits);
01442     break;
01443 #endif /* BSDCOMPRESS_SUPPORT */
01444 #if PREDICTOR_SUPPORT
01445     case CI_PREDICTOR_1:
01446     return "Predictor 1";
01447     case CI_PREDICTOR_2:
01448     return "Predictor 2";
01449 #endif /* PREDICTOR_SUPPORT */
01450     default:
01451     ppp_slprintf(result, sizeof(result), "Method %d", opt->method);
01452     }
01453     return result;
01454 }
01455 
01456 /*
01457  * CCP has come up - inform the kernel driver and log a message.
01458  */
01459 static void ccp_up(fsm *f) {
01460     ppp_pcb *pcb = f->pcb;
01461     ccp_options *go = &pcb->ccp_gotoptions;
01462     ccp_options *ho = &pcb->ccp_hisoptions;
01463     char method1[64];
01464 
01465     ccp_set(pcb, 1, 1, go->method, ho->method);
01466     if (ccp_anycompress(go)) {
01467     if (ccp_anycompress(ho)) {
01468         if (go->method == ho->method) {
01469         ppp_notice("%s compression enabled", method_name(go, ho));
01470         } else {
01471         ppp_strlcpy(method1, method_name(go, NULL), sizeof(method1));
01472         ppp_notice("%s / %s compression enabled",
01473                method1, method_name(ho, NULL));
01474         }
01475     } else
01476         ppp_notice("%s receive compression enabled", method_name(go, NULL));
01477     } else if (ccp_anycompress(ho))
01478     ppp_notice("%s transmit compression enabled", method_name(ho, NULL));
01479 #if MPPE_SUPPORT
01480     if (go->mppe) {
01481     continue_networks(pcb);     /* Bring up IP et al */
01482     }
01483 #endif /* MPPE_SUPPORT */
01484 }
01485 
01486 /*
01487  * CCP has gone down - inform the kernel driver.
01488  */
01489 static void ccp_down(fsm *f) {
01490     ppp_pcb *pcb = f->pcb;
01491 #if MPPE_SUPPORT
01492     ccp_options *go = &pcb->ccp_gotoptions;
01493 #endif /* MPPE_SUPPORT */
01494 
01495     if (pcb->ccp_localstate & RACK_PENDING)
01496     UNTIMEOUT(ccp_rack_timeout, f);
01497     pcb->ccp_localstate = 0;
01498     ccp_set(pcb, 1, 0, 0, 0);
01499 #if MPPE_SUPPORT
01500     if (go->mppe) {
01501     go->mppe = 0;
01502     if (pcb->lcp_fsm.state == PPP_FSM_OPENED) {
01503         /* If LCP is not already going down, make sure it does. */
01504         ppp_error("MPPE disabled");
01505         lcp_close(pcb, "MPPE disabled");
01506     }
01507     }
01508 #endif /* MPPE_SUPPORT */
01509 }
01510 
01511 #if PRINTPKT_SUPPORT
01512 /*
01513  * Print the contents of a CCP packet.
01514  */
01515 static const char* const ccp_codenames[] = {
01516     "ConfReq", "ConfAck", "ConfNak", "ConfRej",
01517     "TermReq", "TermAck", "CodeRej",
01518     NULL, NULL, NULL, NULL, NULL, NULL,
01519     "ResetReq", "ResetAck",
01520 };
01521 
01522 static int ccp_printpkt(const u_char *p, int plen, void (*printer) (void *, const char *, ...), void *arg) {
01523     const u_char *p0, *optend;
01524     int code, id, len;
01525     int optlen;
01526 
01527     p0 = p;
01528     if (plen < HEADERLEN)
01529     return 0;
01530     code = p[0];
01531     id = p[1];
01532     len = (p[2] << 8) + p[3];
01533     if (len < HEADERLEN || len > plen)
01534     return 0;
01535 
01536     if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(ccp_codenames) && ccp_codenames[code-1] != NULL)
01537     printer(arg, " %s", ccp_codenames[code-1]);
01538     else
01539     printer(arg, " code=0x%x", code);
01540     printer(arg, " id=0x%x", id);
01541     len -= HEADERLEN;
01542     p += HEADERLEN;
01543 
01544     switch (code) {
01545     case CONFREQ:
01546     case CONFACK:
01547     case CONFNAK:
01548     case CONFREJ:
01549     /* print list of possible compression methods */
01550     while (len >= 2) {
01551         code = p[0];
01552         optlen = p[1];
01553         if (optlen < 2 || optlen > len)
01554         break;
01555         printer(arg, " <");
01556         len -= optlen;
01557         optend = p + optlen;
01558         switch (code) {
01559 #if MPPE_SUPPORT
01560         case CI_MPPE:
01561         if (optlen >= CILEN_MPPE) {
01562             u_char mppe_opts;
01563 
01564             MPPE_CI_TO_OPTS(&p[2], mppe_opts);
01565             printer(arg, "mppe %s %s %s %s %s %s%s",
01566                 (p[2] & MPPE_H_BIT)? "+H": "-H",
01567                 (p[5] & MPPE_M_BIT)? "+M": "-M",
01568                 (p[5] & MPPE_S_BIT)? "+S": "-S",
01569                 (p[5] & MPPE_L_BIT)? "+L": "-L",
01570                 (p[5] & MPPE_D_BIT)? "+D": "-D",
01571                 (p[5] & MPPE_C_BIT)? "+C": "-C",
01572                 (mppe_opts & MPPE_OPT_UNKNOWN)? " +U": "");
01573             if (mppe_opts & MPPE_OPT_UNKNOWN)
01574             printer(arg, " (%.2x %.2x %.2x %.2x)",
01575                 p[2], p[3], p[4], p[5]);
01576             p += CILEN_MPPE;
01577         }
01578         break;
01579 #endif /* MPPE_SUPPORT */
01580 #if DEFLATE_SUPPORT
01581         case CI_DEFLATE:
01582         case CI_DEFLATE_DRAFT:
01583         if (optlen >= CILEN_DEFLATE) {
01584             printer(arg, "deflate%s %d",
01585                 (code == CI_DEFLATE_DRAFT? "(old#)": ""),
01586                 DEFLATE_SIZE(p[2]));
01587             if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL)
01588             printer(arg, " method %d", DEFLATE_METHOD(p[2]));
01589             if (p[3] != DEFLATE_CHK_SEQUENCE)
01590             printer(arg, " check %d", p[3]);
01591             p += CILEN_DEFLATE;
01592         }
01593         break;
01594 #endif /* DEFLATE_SUPPORT */
01595 #if BSDCOMPRESS_SUPPORT
01596         case CI_BSD_COMPRESS:
01597         if (optlen >= CILEN_BSD_COMPRESS) {
01598             printer(arg, "bsd v%d %d", BSD_VERSION(p[2]),
01599                 BSD_NBITS(p[2]));
01600             p += CILEN_BSD_COMPRESS;
01601         }
01602         break;
01603 #endif /* BSDCOMPRESS_SUPPORT */
01604 #if PREDICTOR_SUPPORT
01605         case CI_PREDICTOR_1:
01606         if (optlen >= CILEN_PREDICTOR_1) {
01607             printer(arg, "predictor 1");
01608             p += CILEN_PREDICTOR_1;
01609         }
01610         break;
01611         case CI_PREDICTOR_2:
01612         if (optlen >= CILEN_PREDICTOR_2) {
01613             printer(arg, "predictor 2");
01614             p += CILEN_PREDICTOR_2;
01615         }
01616         break;
01617 #endif /* PREDICTOR_SUPPORT */
01618         default:
01619                 break;
01620         }
01621         while (p < optend)
01622         printer(arg, " %.2x", *p++);
01623         printer(arg, ">");
01624     }
01625     break;
01626 
01627     case TERMACK:
01628     case TERMREQ:
01629     if (len > 0 && *p >= ' ' && *p < 0x7f) {
01630         ppp_print_string(p, len, printer, arg);
01631         p += len;
01632         len = 0;
01633     }
01634     break;
01635     default:
01636         break;
01637     }
01638 
01639     /* dump out the rest of the packet in hex */
01640     while (--len >= 0)
01641     printer(arg, " %.2x", *p++);
01642 
01643     return p - p0;
01644 }
01645 #endif /* PRINTPKT_SUPPORT */
01646 
01647 #if PPP_DATAINPUT
01648 /*
01649  * We have received a packet that the decompressor failed to
01650  * decompress.  Here we would expect to issue a reset-request, but
01651  * Motorola has a patent on resetting the compressor as a result of
01652  * detecting an error in the decompressed data after decompression.
01653  * (See US patent 5,130,993; international patent publication number
01654  * WO 91/10289; Australian patent 73296/91.)
01655  *
01656  * So we ask the kernel whether the error was detected after
01657  * decompression; if it was, we take CCP down, thus disabling
01658  * compression :-(, otherwise we issue the reset-request.
01659  */
01660 static void ccp_datainput(ppp_pcb *pcb, u_char *pkt, int len) {
01661     fsm *f;
01662 #if MPPE_SUPPORT
01663     ccp_options *go = &pcb->ccp_gotoptions;
01664 #endif /* MPPE_SUPPORT */
01665     LWIP_UNUSED_ARG(pkt);
01666     LWIP_UNUSED_ARG(len);
01667 
01668     f = &pcb->ccp_fsm;
01669     if (f->state == PPP_FSM_OPENED) {
01670     if (ccp_fatal_error(pcb)) {
01671         /*
01672          * Disable compression by taking CCP down.
01673          */
01674         ppp_error("Lost compression sync: disabling compression");
01675         ccp_close(pcb, "Lost compression sync");
01676 #if MPPE_SUPPORT
01677         /*
01678          * If we were doing MPPE, we must also take the link down.
01679          */
01680         if (go->mppe) {
01681         ppp_error("Too many MPPE errors, closing LCP");
01682         lcp_close(pcb, "Too many MPPE errors");
01683         }
01684 #endif /* MPPE_SUPPORT */
01685     } else {
01686         /*
01687          * Send a reset-request to reset the peer's compressor.
01688          * We don't do that if we are still waiting for an
01689          * acknowledgement to a previous reset-request.
01690          */
01691         if (!(pcb->ccp_localstate & RACK_PENDING)) {
01692         fsm_sdata(f, CCP_RESETREQ, f->reqid = ++f->id, NULL, 0);
01693         TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT);
01694         pcb->ccp_localstate |= RACK_PENDING;
01695         } else
01696         pcb->ccp_localstate |= RREQ_REPEAT;
01697     }
01698     }
01699 }
01700 #endif /* PPP_DATAINPUT */
01701 
01702 /*
01703  * We have received a packet that the decompressor failed to
01704  * decompress. Issue a reset-request.
01705  */
01706 void ccp_resetrequest(ppp_pcb *pcb) {
01707     fsm *f = &pcb->ccp_fsm;
01708 
01709     if (f->state != PPP_FSM_OPENED)
01710     return;
01711 
01712     /*
01713      * Send a reset-request to reset the peer's compressor.
01714      * We don't do that if we are still waiting for an
01715      * acknowledgement to a previous reset-request.
01716      */
01717     if (!(pcb->ccp_localstate & RACK_PENDING)) {
01718     fsm_sdata(f, CCP_RESETREQ, f->reqid = ++f->id, NULL, 0);
01719     TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT);
01720     pcb->ccp_localstate |= RACK_PENDING;
01721     } else
01722     pcb->ccp_localstate |= RREQ_REPEAT;
01723 }
01724 
01725 /*
01726  * Timeout waiting for reset-ack.
01727  */
01728 static void ccp_rack_timeout(void *arg) {
01729     fsm *f = (fsm*)arg;
01730     ppp_pcb *pcb = f->pcb;
01731 
01732     if (f->state == PPP_FSM_OPENED && (pcb->ccp_localstate & RREQ_REPEAT)) {
01733     fsm_sdata(f, CCP_RESETREQ, f->reqid, NULL, 0);
01734     TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT);
01735     pcb->ccp_localstate &= ~RREQ_REPEAT;
01736     } else
01737     pcb->ccp_localstate &= ~RACK_PENDING;
01738 }
01739 
01740 #endif /* PPP_SUPPORT && CCP_SUPPORT */