BA
/
BaBoRo1
Embed:
(wiki syntax)
Show/hide line numbers
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 */
Generated on Tue Jul 12 2022 12:21:59 by
