lwip-1.4.1 (partial)
Embed:
(wiki syntax)
Show/hide line numbers
lcp.c
00001 /***************************************************************************** 00002 * lcp.c - Network Link Control Protocol program file. 00003 * 00004 * Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. 00005 * portions Copyright (c) 1997 by Global Election Systems Inc. 00006 * 00007 * The authors hereby grant permission to use, copy, modify, distribute, 00008 * and license this software and its documentation for any purpose, provided 00009 * that existing copyright notices are retained in all copies and that this 00010 * notice and the following disclaimer are included verbatim in any 00011 * distributions. No written agreement, license, or royalty fee is required 00012 * for any of the authorized uses. 00013 * 00014 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR 00015 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00016 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 00017 * IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00018 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 00019 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00020 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00021 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00022 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 00023 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00024 * 00025 ****************************************************************************** 00026 * REVISION HISTORY 00027 * 00028 * 03-01-01 Marc Boucher <marc@mbsi.ca> 00029 * Ported to lwIP. 00030 * 97-12-01 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc. 00031 * Original. 00032 *****************************************************************************/ 00033 00034 /* 00035 * lcp.c - PPP Link Control Protocol. 00036 * 00037 * Copyright (c) 1989 Carnegie Mellon University. 00038 * All rights reserved. 00039 * 00040 * Redistribution and use in source and binary forms are permitted 00041 * provided that the above copyright notice and this paragraph are 00042 * duplicated in all such forms and that any documentation, 00043 * advertising materials, and other materials related to such 00044 * distribution and use acknowledge that the software was developed 00045 * by Carnegie Mellon University. The name of the 00046 * University may not be used to endorse or promote products derived 00047 * from this software without specific prior written permission. 00048 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 00049 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 00050 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00051 */ 00052 00053 00054 #include "lwip/opt.h" 00055 00056 #if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ 00057 00058 #include "ppp_impl.h" 00059 #include "pppdebug.h" 00060 00061 #include "fsm.h" 00062 #include "chap.h" 00063 #include "magic.h" 00064 #include "auth.h" 00065 #include "lcp.h" 00066 00067 #include <string.h> 00068 00069 #if PPPOE_SUPPORT 00070 #include "netif/ppp_oe.h" 00071 #else 00072 #define PPPOE_MAXMTU PPP_MAXMRU 00073 #endif 00074 00075 #if 0 /* UNUSED */ 00076 /* 00077 * LCP-related command-line options. 00078 */ 00079 int lcp_echo_interval = 0; /* Interval between LCP echo-requests */ 00080 int lcp_echo_fails = 0; /* Tolerance to unanswered echo-requests */ 00081 bool lax_recv = 0; /* accept control chars in asyncmap */ 00082 00083 static int setescape (char **); 00084 00085 static option_t lcp_option_list[] = { 00086 /* LCP options */ 00087 /* list stripped for simplicity */ 00088 {NULL} 00089 }; 00090 #endif /* UNUSED */ 00091 00092 /* options */ 00093 LinkPhase lcp_phase[NUM_PPP]; /* Phase of link session (RFC 1661) */ 00094 static u_int lcp_echo_interval = LCP_ECHOINTERVAL; /* Interval between LCP echo-requests */ 00095 static u_int lcp_echo_fails = LCP_MAXECHOFAILS; /* Tolerance to unanswered echo-requests */ 00096 00097 /* global vars */ 00098 static fsm lcp_fsm[NUM_PPP]; /* LCP fsm structure (global)*/ 00099 lcp_options lcp_wantoptions[NUM_PPP]; /* Options that we want to request */ 00100 lcp_options lcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */ 00101 lcp_options lcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */ 00102 lcp_options lcp_hisoptions[NUM_PPP]; /* Options that we ack'd */ 00103 ext_accm xmit_accm[NUM_PPP]; /* extended transmit ACCM */ 00104 00105 static u32_t lcp_echos_pending = 0; /* Number of outstanding echo msgs */ 00106 static u32_t lcp_echo_number = 0; /* ID number of next echo frame */ 00107 static u32_t lcp_echo_timer_running = 0; /* TRUE if a timer is running */ 00108 00109 /* @todo: do we really need such a large buffer? The typical 1500 bytes seem too much. */ 00110 static u_char nak_buffer[PPP_MRU]; /* where we construct a nak packet */ 00111 00112 /* 00113 * Callbacks for fsm code. (CI = Configuration Information) 00114 */ 00115 static void lcp_resetci (fsm*); /* Reset our CI */ 00116 static int lcp_cilen (fsm*); /* Return length of our CI */ 00117 static void lcp_addci (fsm*, u_char*, int*); /* Add our CI to pkt */ 00118 static int lcp_ackci (fsm*, u_char*, int); /* Peer ack'd our CI */ 00119 static int lcp_nakci (fsm*, u_char*, int); /* Peer nak'd our CI */ 00120 static int lcp_rejci (fsm*, u_char*, int); /* Peer rej'd our CI */ 00121 static int lcp_reqci (fsm*, u_char*, int*, int); /* Rcv peer CI */ 00122 static void lcp_up (fsm*); /* We're UP */ 00123 static void lcp_down (fsm*); /* We're DOWN */ 00124 static void lcp_starting (fsm*); /* We need lower layer up */ 00125 static void lcp_finished (fsm*); /* We need lower layer down */ 00126 static int lcp_extcode (fsm*, int, u_char, u_char*, int); 00127 static void lcp_rprotrej (fsm*, u_char*, int); 00128 00129 /* 00130 * routines to send LCP echos to peer 00131 */ 00132 00133 static void lcp_echo_lowerup (int); 00134 static void lcp_echo_lowerdown (int); 00135 static void LcpEchoTimeout (void*); 00136 static void lcp_received_echo_reply (fsm*, int, u_char*, int); 00137 static void LcpSendEchoRequest (fsm*); 00138 static void LcpLinkFailure (fsm*); 00139 static void LcpEchoCheck (fsm*); 00140 00141 static fsm_callbacks lcp_callbacks = { /* LCP callback routines */ 00142 lcp_resetci, /* Reset our Configuration Information */ 00143 lcp_cilen, /* Length of our Configuration Information */ 00144 lcp_addci, /* Add our Configuration Information */ 00145 lcp_ackci, /* ACK our Configuration Information */ 00146 lcp_nakci, /* NAK our Configuration Information */ 00147 lcp_rejci, /* Reject our Configuration Information */ 00148 lcp_reqci, /* Request peer's Configuration Information */ 00149 lcp_up, /* Called when fsm reaches LS_OPENED state */ 00150 lcp_down, /* Called when fsm leaves LS_OPENED state */ 00151 lcp_starting, /* Called when we want the lower layer up */ 00152 lcp_finished, /* Called when we want the lower layer down */ 00153 NULL, /* Called when Protocol-Reject received */ 00154 NULL, /* Retransmission is necessary */ 00155 lcp_extcode, /* Called to handle LCP-specific codes */ 00156 "LCP" /* String name of protocol */ 00157 }; 00158 00159 /* 00160 * Protocol entry points. 00161 * Some of these are called directly. 00162 */ 00163 00164 static void lcp_input (int, u_char *, int); 00165 static void lcp_protrej (int); 00166 00167 struct protent lcp_protent = { 00168 PPP_LCP, 00169 lcp_init, 00170 lcp_input, 00171 lcp_protrej, 00172 lcp_lowerup, 00173 lcp_lowerdown, 00174 lcp_open, 00175 lcp_close, 00176 #if PPP_ADDITIONAL_CALLBACKS 00177 lcp_printpkt, 00178 NULL, 00179 #endif /* PPP_ADDITIONAL_CALLBACKS */ 00180 1, 00181 "LCP", 00182 #if PPP_ADDITIONAL_CALLBACKS 00183 NULL, 00184 NULL, 00185 NULL 00186 #endif /* PPP_ADDITIONAL_CALLBACKS */ 00187 }; 00188 00189 int lcp_loopbackfail = DEFLOOPBACKFAIL; 00190 00191 /* 00192 * Length of each type of configuration option (in octets) 00193 */ 00194 #define CILEN_VOID 2 00195 #define CILEN_CHAR 3 00196 #define CILEN_SHORT 4 /* CILEN_VOID + sizeof(short) */ 00197 #define CILEN_CHAP 5 /* CILEN_VOID + sizeof(short) + 1 */ 00198 #define CILEN_LONG 6 /* CILEN_VOID + sizeof(long) */ 00199 #define CILEN_LQR 8 /* CILEN_VOID + sizeof(short) + sizeof(long) */ 00200 #define CILEN_CBCP 3 00201 00202 #define CODENAME(x) ((x) == CONFACK ? "ACK" : (x) == CONFNAK ? "NAK" : "REJ") 00203 00204 #if 0 /* UNUSED */ 00205 /* 00206 * setescape - add chars to the set we escape on transmission. 00207 */ 00208 static int 00209 setescape(argv) 00210 char **argv; 00211 { 00212 int n, ret; 00213 char *p, *endp; 00214 00215 p = *argv; 00216 ret = 1; 00217 while (*p) { 00218 n = strtol(p, &endp, 16); 00219 if (p == endp) { 00220 option_error("escape parameter contains invalid hex number '%s'", p); 00221 return 0; 00222 } 00223 p = endp; 00224 if (n < 0 || n == 0x5E || n > 0xFF) { 00225 option_error("can't escape character 0x%x", n); 00226 ret = 0; 00227 } else 00228 xmit_accm[0][n >> 5] |= 1 << (n & 0x1F); 00229 while (*p == ',' || *p == ' ') 00230 ++p; 00231 } 00232 return ret; 00233 } 00234 #endif /* UNUSED */ 00235 00236 /* 00237 * lcp_init - Initialize LCP. 00238 */ 00239 void 00240 lcp_init(int unit) 00241 { 00242 fsm *f = &lcp_fsm[unit]; 00243 lcp_options *wo = &lcp_wantoptions[unit]; 00244 lcp_options *ao = &lcp_allowoptions[unit]; 00245 00246 f->unit = unit; 00247 f->protocol = PPP_LCP; 00248 f->callbacks = &lcp_callbacks; 00249 00250 fsm_init(f); 00251 00252 wo->passive = 0; 00253 wo->silent = 0; 00254 wo->restart = 0; /* Set to 1 in kernels or multi-line implementations */ 00255 wo->neg_mru = 1; 00256 wo->mru = PPP_DEFMRU; 00257 wo->neg_asyncmap = 1; 00258 wo->asyncmap = 0x00000000l; /* Assume don't need to escape any ctl chars. */ 00259 wo->neg_chap = 0; /* Set to 1 on server */ 00260 wo->neg_upap = 0; /* Set to 1 on server */ 00261 wo->chap_mdtype = CHAP_DIGEST_MD5; 00262 wo->neg_magicnumber = 1; 00263 wo->neg_pcompression = 1; 00264 wo->neg_accompression = 1; 00265 wo->neg_lqr = 0; /* no LQR implementation yet */ 00266 wo->neg_cbcp = 0; 00267 00268 ao->neg_mru = 1; 00269 ao->mru = PPP_MAXMRU; 00270 ao->neg_asyncmap = 1; 00271 ao->asyncmap = 0x00000000l; /* Assume don't need to escape any ctl chars. */ 00272 ao->neg_chap = (CHAP_SUPPORT != 0); 00273 ao->chap_mdtype = CHAP_DIGEST_MD5; 00274 ao->neg_upap = (PAP_SUPPORT != 0); 00275 ao->neg_magicnumber = 1; 00276 ao->neg_pcompression = 1; 00277 ao->neg_accompression = 1; 00278 ao->neg_lqr = 0; /* no LQR implementation yet */ 00279 ao->neg_cbcp = (CBCP_SUPPORT != 0); 00280 00281 /* 00282 * Set transmit escape for the flag and escape characters plus anything 00283 * set for the allowable options. 00284 */ 00285 memset(xmit_accm[unit], 0, sizeof(xmit_accm[0])); 00286 xmit_accm[unit][15] = 0x60; 00287 xmit_accm[unit][0] = (u_char)((ao->asyncmap & 0xFF)); 00288 xmit_accm[unit][1] = (u_char)((ao->asyncmap >> 8) & 0xFF); 00289 xmit_accm[unit][2] = (u_char)((ao->asyncmap >> 16) & 0xFF); 00290 xmit_accm[unit][3] = (u_char)((ao->asyncmap >> 24) & 0xFF); 00291 LCPDEBUG(LOG_INFO, ("lcp_init: xmit_accm=%X %X %X %X\n", 00292 xmit_accm[unit][0], 00293 xmit_accm[unit][1], 00294 xmit_accm[unit][2], 00295 xmit_accm[unit][3])); 00296 00297 lcp_phase[unit] = PHASE_INITIALIZE; 00298 } 00299 00300 00301 /* 00302 * lcp_open - LCP is allowed to come up. 00303 */ 00304 void 00305 lcp_open(int unit) 00306 { 00307 fsm *f = &lcp_fsm[unit]; 00308 lcp_options *wo = &lcp_wantoptions[unit]; 00309 00310 f->flags = 0; 00311 if (wo->passive) { 00312 f->flags |= OPT_PASSIVE; 00313 } 00314 if (wo->silent) { 00315 f->flags |= OPT_SILENT; 00316 } 00317 fsm_open(f); 00318 00319 lcp_phase[unit] = PHASE_ESTABLISH; 00320 } 00321 00322 00323 /* 00324 * lcp_close - Take LCP down. 00325 */ 00326 void 00327 lcp_close(int unit, char *reason) 00328 { 00329 fsm *f = &lcp_fsm[unit]; 00330 00331 if (lcp_phase[unit] != PHASE_DEAD) { 00332 lcp_phase[unit] = PHASE_TERMINATE; 00333 } 00334 if (f->state == LS_STOPPED && f->flags & (OPT_PASSIVE|OPT_SILENT)) { 00335 /* 00336 * This action is not strictly according to the FSM in RFC1548, 00337 * but it does mean that the program terminates if you do an 00338 * lcp_close() in passive/silent mode when a connection hasn't 00339 * been established. 00340 */ 00341 f->state = LS_CLOSED; 00342 lcp_finished(f); 00343 } else { 00344 fsm_close(f, reason); 00345 } 00346 } 00347 00348 00349 /* 00350 * lcp_lowerup - The lower layer is up. 00351 */ 00352 void 00353 lcp_lowerup(int unit) 00354 { 00355 lcp_options *wo = &lcp_wantoptions[unit]; 00356 00357 /* 00358 * Don't use A/C or protocol compression on transmission, 00359 * but accept A/C and protocol compressed packets 00360 * if we are going to ask for A/C and protocol compression. 00361 */ 00362 ppp_set_xaccm(unit, &xmit_accm[unit]); 00363 ppp_send_config(unit, PPP_MRU, 0xffffffffl, 0, 0); 00364 ppp_recv_config(unit, PPP_MRU, 0x00000000l, 00365 wo->neg_pcompression, wo->neg_accompression); 00366 peer_mru[unit] = PPP_MRU; 00367 lcp_allowoptions[unit].asyncmap = (u_long)xmit_accm[unit][0] 00368 | ((u_long)xmit_accm[unit][1] << 8) 00369 | ((u_long)xmit_accm[unit][2] << 16) 00370 | ((u_long)xmit_accm[unit][3] << 24); 00371 LCPDEBUG(LOG_INFO, ("lcp_lowerup: asyncmap=%X %X %X %X\n", 00372 xmit_accm[unit][3], 00373 xmit_accm[unit][2], 00374 xmit_accm[unit][1], 00375 xmit_accm[unit][0])); 00376 00377 fsm_lowerup(&lcp_fsm[unit]); 00378 } 00379 00380 00381 /* 00382 * lcp_lowerdown - The lower layer is down. 00383 */ 00384 void 00385 lcp_lowerdown(int unit) 00386 { 00387 fsm_lowerdown(&lcp_fsm[unit]); 00388 } 00389 00390 00391 /* 00392 * lcp_input - Input LCP packet. 00393 */ 00394 static void 00395 lcp_input(int unit, u_char *p, int len) 00396 { 00397 fsm *f = &lcp_fsm[unit]; 00398 00399 fsm_input(f, p, len); 00400 } 00401 00402 00403 /* 00404 * lcp_extcode - Handle a LCP-specific code. 00405 */ 00406 static int 00407 lcp_extcode(fsm *f, int code, u_char id, u_char *inp, int len) 00408 { 00409 u_char *magp; 00410 00411 switch( code ){ 00412 case PROTREJ: 00413 lcp_rprotrej(f, inp, len); 00414 break; 00415 00416 case ECHOREQ: 00417 if (f->state != LS_OPENED) { 00418 break; 00419 } 00420 LCPDEBUG(LOG_INFO, ("lcp: Echo-Request, Rcvd id %d\n", id)); 00421 magp = inp; 00422 PUTLONG(lcp_gotoptions[f->unit].magicnumber, magp); 00423 fsm_sdata(f, ECHOREP, id, inp, len); 00424 break; 00425 00426 case ECHOREP: 00427 lcp_received_echo_reply(f, id, inp, len); 00428 break; 00429 00430 case DISCREQ: 00431 break; 00432 00433 default: 00434 return 0; 00435 } 00436 return 1; 00437 } 00438 00439 00440 /* 00441 * lcp_rprotrej - Receive an Protocol-Reject. 00442 * 00443 * Figure out which protocol is rejected and inform it. 00444 */ 00445 static void 00446 lcp_rprotrej(fsm *f, u_char *inp, int len) 00447 { 00448 int i; 00449 struct protent *protp; 00450 u_short prot; 00451 00452 if (len < (int)sizeof (u_short)) { 00453 LCPDEBUG(LOG_INFO, ("lcp_rprotrej: Rcvd short Protocol-Reject packet!\n")); 00454 return; 00455 } 00456 00457 GETSHORT(prot, inp); 00458 00459 LCPDEBUG(LOG_INFO, ("lcp_rprotrej: Rcvd Protocol-Reject packet for %x!\n", prot)); 00460 00461 /* 00462 * Protocol-Reject packets received in any state other than the LCP 00463 * LS_OPENED state SHOULD be silently discarded. 00464 */ 00465 if( f->state != LS_OPENED ) { 00466 LCPDEBUG(LOG_INFO, ("Protocol-Reject discarded: LCP in state %d\n", f->state)); 00467 return; 00468 } 00469 00470 /* 00471 * Upcall the proper Protocol-Reject routine. 00472 */ 00473 for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) { 00474 if (protp->protocol == prot && protp->enabled_flag) { 00475 (*protp->protrej)(f->unit); 00476 return; 00477 } 00478 } 00479 00480 LCPDEBUG(LOG_WARNING, ("Protocol-Reject for unsupported protocol 0x%x\n", prot)); 00481 } 00482 00483 00484 /* 00485 * lcp_protrej - A Protocol-Reject was received. 00486 */ 00487 static void 00488 lcp_protrej(int unit) 00489 { 00490 LWIP_UNUSED_ARG(unit); 00491 /* 00492 * Can't reject LCP! 00493 */ 00494 LCPDEBUG(LOG_WARNING, ("lcp_protrej: Received Protocol-Reject for LCP!\n")); 00495 fsm_protreject(&lcp_fsm[unit]); 00496 } 00497 00498 00499 /* 00500 * lcp_sprotrej - Send a Protocol-Reject for some protocol. 00501 */ 00502 void 00503 lcp_sprotrej(int unit, u_char *p, int len) 00504 { 00505 /* 00506 * Send back the protocol and the information field of the 00507 * rejected packet. We only get here if LCP is in the LS_OPENED state. 00508 */ 00509 00510 fsm_sdata(&lcp_fsm[unit], PROTREJ, ++lcp_fsm[unit].id, p, len); 00511 } 00512 00513 00514 /* 00515 * lcp_resetci - Reset our CI. 00516 */ 00517 static void 00518 lcp_resetci(fsm *f) 00519 { 00520 lcp_wantoptions[f->unit].magicnumber = magic(); 00521 lcp_wantoptions[f->unit].numloops = 0; 00522 lcp_gotoptions[f->unit] = lcp_wantoptions[f->unit]; 00523 peer_mru[f->unit] = PPP_MRU; 00524 auth_reset(f->unit); 00525 } 00526 00527 00528 /* 00529 * lcp_cilen - Return length of our CI. 00530 */ 00531 static int 00532 lcp_cilen(fsm *f) 00533 { 00534 lcp_options *go = &lcp_gotoptions[f->unit]; 00535 00536 #define LENCIVOID(neg) ((neg) ? CILEN_VOID : 0) 00537 #define LENCICHAP(neg) ((neg) ? CILEN_CHAP : 0) 00538 #define LENCISHORT(neg) ((neg) ? CILEN_SHORT : 0) 00539 #define LENCILONG(neg) ((neg) ? CILEN_LONG : 0) 00540 #define LENCILQR(neg) ((neg) ? CILEN_LQR: 0) 00541 #define LENCICBCP(neg) ((neg) ? CILEN_CBCP: 0) 00542 /* 00543 * NB: we only ask for one of CHAP and UPAP, even if we will 00544 * accept either. 00545 */ 00546 return (LENCISHORT(go->neg_mru && go->mru != PPP_DEFMRU) + 00547 LENCILONG(go->neg_asyncmap && go->asyncmap != 0xFFFFFFFFl) + 00548 LENCICHAP(go->neg_chap) + 00549 LENCISHORT(!go->neg_chap && go->neg_upap) + 00550 LENCILQR(go->neg_lqr) + 00551 LENCICBCP(go->neg_cbcp) + 00552 LENCILONG(go->neg_magicnumber) + 00553 LENCIVOID(go->neg_pcompression) + 00554 LENCIVOID(go->neg_accompression)); 00555 } 00556 00557 00558 /* 00559 * lcp_addci - Add our desired CIs to a packet. 00560 */ 00561 static void 00562 lcp_addci(fsm *f, u_char *ucp, int *lenp) 00563 { 00564 lcp_options *go = &lcp_gotoptions[f->unit]; 00565 u_char *start_ucp = ucp; 00566 00567 #define ADDCIVOID(opt, neg) \ 00568 if (neg) { \ 00569 LCPDEBUG(LOG_INFO, ("lcp_addci: opt=%d\n", opt)); \ 00570 PUTCHAR(opt, ucp); \ 00571 PUTCHAR(CILEN_VOID, ucp); \ 00572 } 00573 #define ADDCISHORT(opt, neg, val) \ 00574 if (neg) { \ 00575 LCPDEBUG(LOG_INFO, ("lcp_addci: INT opt=%d %X\n", opt, val)); \ 00576 PUTCHAR(opt, ucp); \ 00577 PUTCHAR(CILEN_SHORT, ucp); \ 00578 PUTSHORT(val, ucp); \ 00579 } 00580 #define ADDCICHAP(opt, neg, val, digest) \ 00581 if (neg) { \ 00582 LCPDEBUG(LOG_INFO, ("lcp_addci: CHAP opt=%d %X\n", opt, val)); \ 00583 PUTCHAR(opt, ucp); \ 00584 PUTCHAR(CILEN_CHAP, ucp); \ 00585 PUTSHORT(val, ucp); \ 00586 PUTCHAR(digest, ucp); \ 00587 } 00588 #define ADDCILONG(opt, neg, val) \ 00589 if (neg) { \ 00590 LCPDEBUG(LOG_INFO, ("lcp_addci: L opt=%d %lX\n", opt, val)); \ 00591 PUTCHAR(opt, ucp); \ 00592 PUTCHAR(CILEN_LONG, ucp); \ 00593 PUTLONG(val, ucp); \ 00594 } 00595 #define ADDCILQR(opt, neg, val) \ 00596 if (neg) { \ 00597 LCPDEBUG(LOG_INFO, ("lcp_addci: LQR opt=%d %lX\n", opt, val)); \ 00598 PUTCHAR(opt, ucp); \ 00599 PUTCHAR(CILEN_LQR, ucp); \ 00600 PUTSHORT(PPP_LQR, ucp); \ 00601 PUTLONG(val, ucp); \ 00602 } 00603 #define ADDCICHAR(opt, neg, val) \ 00604 if (neg) { \ 00605 LCPDEBUG(LOG_INFO, ("lcp_addci: CHAR opt=%d %X '%z'\n", opt, val, val)); \ 00606 PUTCHAR(opt, ucp); \ 00607 PUTCHAR(CILEN_CHAR, ucp); \ 00608 PUTCHAR(val, ucp); \ 00609 } 00610 00611 ADDCISHORT(CI_MRU, go->neg_mru && go->mru != PPP_DEFMRU, go->mru); 00612 ADDCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFFl, go->asyncmap); 00613 ADDCICHAP(CI_AUTHTYPE, go->neg_chap, PPP_CHAP, go->chap_mdtype); 00614 ADDCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP); 00615 ADDCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period); 00616 ADDCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT); 00617 ADDCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber); 00618 ADDCIVOID(CI_PCOMPRESSION, go->neg_pcompression); 00619 ADDCIVOID(CI_ACCOMPRESSION, go->neg_accompression); 00620 00621 if (ucp - start_ucp != *lenp) { 00622 /* this should never happen, because peer_mtu should be 1500 */ 00623 LCPDEBUG(LOG_ERR, ("Bug in lcp_addci: wrong length\n")); 00624 } 00625 } 00626 00627 00628 /* 00629 * lcp_ackci - Ack our CIs. 00630 * This should not modify any state if the Ack is bad. 00631 * 00632 * Returns: 00633 * 0 - Ack was bad. 00634 * 1 - Ack was good. 00635 */ 00636 static int 00637 lcp_ackci(fsm *f, u_char *p, int len) 00638 { 00639 lcp_options *go = &lcp_gotoptions[f->unit]; 00640 u_char cilen, citype, cichar; 00641 u_short cishort; 00642 u32_t cilong; 00643 00644 /* 00645 * CIs must be in exactly the same order that we sent. 00646 * Check packet length and CI length at each step. 00647 * If we find any deviations, then this packet is bad. 00648 */ 00649 #define ACKCIVOID(opt, neg) \ 00650 if (neg) { \ 00651 if ((len -= CILEN_VOID) < 0) \ 00652 goto bad; \ 00653 GETCHAR(citype, p); \ 00654 GETCHAR(cilen, p); \ 00655 if (cilen != CILEN_VOID || citype != opt) \ 00656 goto bad; \ 00657 } 00658 #define ACKCISHORT(opt, neg, val) \ 00659 if (neg) { \ 00660 if ((len -= CILEN_SHORT) < 0) \ 00661 goto bad; \ 00662 GETCHAR(citype, p); \ 00663 GETCHAR(cilen, p); \ 00664 if (cilen != CILEN_SHORT || citype != opt) \ 00665 goto bad; \ 00666 GETSHORT(cishort, p); \ 00667 if (cishort != val) \ 00668 goto bad; \ 00669 } 00670 #define ACKCICHAR(opt, neg, val) \ 00671 if (neg) { \ 00672 if ((len -= CILEN_CHAR) < 0) \ 00673 goto bad; \ 00674 GETCHAR(citype, p); \ 00675 GETCHAR(cilen, p); \ 00676 if (cilen != CILEN_CHAR || citype != opt) \ 00677 goto bad; \ 00678 GETCHAR(cichar, p); \ 00679 if (cichar != val) \ 00680 goto bad; \ 00681 } 00682 #define ACKCICHAP(opt, neg, val, digest) \ 00683 if (neg) { \ 00684 if ((len -= CILEN_CHAP) < 0) \ 00685 goto bad; \ 00686 GETCHAR(citype, p); \ 00687 GETCHAR(cilen, p); \ 00688 if (cilen != CILEN_CHAP || citype != opt) \ 00689 goto bad; \ 00690 GETSHORT(cishort, p); \ 00691 if (cishort != val) \ 00692 goto bad; \ 00693 GETCHAR(cichar, p); \ 00694 if (cichar != digest) \ 00695 goto bad; \ 00696 } 00697 #define ACKCILONG(opt, neg, val) \ 00698 if (neg) { \ 00699 if ((len -= CILEN_LONG) < 0) \ 00700 goto bad; \ 00701 GETCHAR(citype, p); \ 00702 GETCHAR(cilen, p); \ 00703 if (cilen != CILEN_LONG || citype != opt) \ 00704 goto bad; \ 00705 GETLONG(cilong, p); \ 00706 if (cilong != val) \ 00707 goto bad; \ 00708 } 00709 #define ACKCILQR(opt, neg, val) \ 00710 if (neg) { \ 00711 if ((len -= CILEN_LQR) < 0) \ 00712 goto bad; \ 00713 GETCHAR(citype, p); \ 00714 GETCHAR(cilen, p); \ 00715 if (cilen != CILEN_LQR || citype != opt) \ 00716 goto bad; \ 00717 GETSHORT(cishort, p); \ 00718 if (cishort != PPP_LQR) \ 00719 goto bad; \ 00720 GETLONG(cilong, p); \ 00721 if (cilong != val) \ 00722 goto bad; \ 00723 } 00724 00725 ACKCISHORT(CI_MRU, go->neg_mru && go->mru != PPP_DEFMRU, go->mru); 00726 ACKCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFFl, go->asyncmap); 00727 ACKCICHAP(CI_AUTHTYPE, go->neg_chap, PPP_CHAP, go->chap_mdtype); 00728 ACKCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP); 00729 ACKCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period); 00730 ACKCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT); 00731 ACKCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber); 00732 ACKCIVOID(CI_PCOMPRESSION, go->neg_pcompression); 00733 ACKCIVOID(CI_ACCOMPRESSION, go->neg_accompression); 00734 00735 /* 00736 * If there are any remaining CIs, then this packet is bad. 00737 */ 00738 if (len != 0) { 00739 goto bad; 00740 } 00741 LCPDEBUG(LOG_INFO, ("lcp_acki: Ack\n")); 00742 return (1); 00743 bad: 00744 LCPDEBUG(LOG_WARNING, ("lcp_acki: received bad Ack!\n")); 00745 return (0); 00746 } 00747 00748 00749 /* 00750 * lcp_nakci - Peer has sent a NAK for some of our CIs. 00751 * This should not modify any state if the Nak is bad 00752 * or if LCP is in the LS_OPENED state. 00753 * 00754 * Returns: 00755 * 0 - Nak was bad. 00756 * 1 - Nak was good. 00757 */ 00758 static int 00759 lcp_nakci(fsm *f, u_char *p, int len) 00760 { 00761 lcp_options *go = &lcp_gotoptions[f->unit]; 00762 lcp_options *wo = &lcp_wantoptions[f->unit]; 00763 u_char citype, cichar, *next; 00764 u_short cishort; 00765 u32_t cilong; 00766 lcp_options no; /* options we've seen Naks for */ 00767 lcp_options try; /* options to request next time */ 00768 int looped_back = 0; 00769 int cilen; 00770 00771 BZERO(&no, sizeof(no)); 00772 try = *go; 00773 00774 /* 00775 * Any Nak'd CIs must be in exactly the same order that we sent. 00776 * Check packet length and CI length at each step. 00777 * If we find any deviations, then this packet is bad. 00778 */ 00779 #define NAKCIVOID(opt, neg, code) \ 00780 if (go->neg && \ 00781 len >= CILEN_VOID && \ 00782 p[1] == CILEN_VOID && \ 00783 p[0] == opt) { \ 00784 len -= CILEN_VOID; \ 00785 INCPTR(CILEN_VOID, p); \ 00786 no.neg = 1; \ 00787 code \ 00788 } 00789 #define NAKCICHAP(opt, neg, code) \ 00790 if (go->neg && \ 00791 len >= CILEN_CHAP && \ 00792 p[1] == CILEN_CHAP && \ 00793 p[0] == opt) { \ 00794 len -= CILEN_CHAP; \ 00795 INCPTR(2, p); \ 00796 GETSHORT(cishort, p); \ 00797 GETCHAR(cichar, p); \ 00798 no.neg = 1; \ 00799 code \ 00800 } 00801 #define NAKCICHAR(opt, neg, code) \ 00802 if (go->neg && \ 00803 len >= CILEN_CHAR && \ 00804 p[1] == CILEN_CHAR && \ 00805 p[0] == opt) { \ 00806 len -= CILEN_CHAR; \ 00807 INCPTR(2, p); \ 00808 GETCHAR(cichar, p); \ 00809 no.neg = 1; \ 00810 code \ 00811 } 00812 #define NAKCISHORT(opt, neg, code) \ 00813 if (go->neg && \ 00814 len >= CILEN_SHORT && \ 00815 p[1] == CILEN_SHORT && \ 00816 p[0] == opt) { \ 00817 len -= CILEN_SHORT; \ 00818 INCPTR(2, p); \ 00819 GETSHORT(cishort, p); \ 00820 no.neg = 1; \ 00821 code \ 00822 } 00823 #define NAKCILONG(opt, neg, code) \ 00824 if (go->neg && \ 00825 len >= CILEN_LONG && \ 00826 p[1] == CILEN_LONG && \ 00827 p[0] == opt) { \ 00828 len -= CILEN_LONG; \ 00829 INCPTR(2, p); \ 00830 GETLONG(cilong, p); \ 00831 no.neg = 1; \ 00832 code \ 00833 } 00834 #define NAKCILQR(opt, neg, code) \ 00835 if (go->neg && \ 00836 len >= CILEN_LQR && \ 00837 p[1] == CILEN_LQR && \ 00838 p[0] == opt) { \ 00839 len -= CILEN_LQR; \ 00840 INCPTR(2, p); \ 00841 GETSHORT(cishort, p); \ 00842 GETLONG(cilong, p); \ 00843 no.neg = 1; \ 00844 code \ 00845 } 00846 00847 /* 00848 * We don't care if they want to send us smaller packets than 00849 * we want. Therefore, accept any MRU less than what we asked for, 00850 * but then ignore the new value when setting the MRU in the kernel. 00851 * If they send us a bigger MRU than what we asked, accept it, up to 00852 * the limit of the default MRU we'd get if we didn't negotiate. 00853 */ 00854 if (go->neg_mru && go->mru != PPP_DEFMRU) { 00855 NAKCISHORT(CI_MRU, neg_mru, 00856 if (cishort <= wo->mru || cishort < PPP_DEFMRU) { 00857 try.mru = cishort; 00858 } 00859 ); 00860 } 00861 00862 /* 00863 * Add any characters they want to our (receive-side) asyncmap. 00864 */ 00865 if (go->neg_asyncmap && go->asyncmap != 0xFFFFFFFFl) { 00866 NAKCILONG(CI_ASYNCMAP, neg_asyncmap, 00867 try.asyncmap = go->asyncmap | cilong; 00868 ); 00869 } 00870 00871 /* 00872 * If they've nak'd our authentication-protocol, check whether 00873 * they are proposing a different protocol, or a different 00874 * hash algorithm for CHAP. 00875 */ 00876 if ((go->neg_chap || go->neg_upap) 00877 && len >= CILEN_SHORT 00878 && p[0] == CI_AUTHTYPE && p[1] >= CILEN_SHORT && p[1] <= len) { 00879 cilen = p[1]; 00880 len -= cilen; 00881 no.neg_chap = go->neg_chap; 00882 no.neg_upap = go->neg_upap; 00883 INCPTR(2, p); 00884 GETSHORT(cishort, p); 00885 if (cishort == PPP_PAP && cilen == CILEN_SHORT) { 00886 /* 00887 * If we were asking for CHAP, they obviously don't want to do it. 00888 * If we weren't asking for CHAP, then we were asking for PAP, 00889 * in which case this Nak is bad. 00890 */ 00891 if (!go->neg_chap) { 00892 goto bad; 00893 } 00894 try.neg_chap = 0; 00895 00896 } else if (cishort == PPP_CHAP && cilen == CILEN_CHAP) { 00897 GETCHAR(cichar, p); 00898 if (go->neg_chap) { 00899 /* 00900 * We were asking for CHAP/MD5; they must want a different 00901 * algorithm. If they can't do MD5, we'll have to stop 00902 * asking for CHAP. 00903 */ 00904 if (cichar != go->chap_mdtype) { 00905 try.neg_chap = 0; 00906 } 00907 } else { 00908 /* 00909 * Stop asking for PAP if we were asking for it. 00910 */ 00911 try.neg_upap = 0; 00912 } 00913 00914 } else { 00915 /* 00916 * We don't recognize what they're suggesting. 00917 * Stop asking for what we were asking for. 00918 */ 00919 if (go->neg_chap) { 00920 try.neg_chap = 0; 00921 } else { 00922 try.neg_upap = 0; 00923 } 00924 p += cilen - CILEN_SHORT; 00925 } 00926 } 00927 00928 /* 00929 * If they can't cope with our link quality protocol, we'll have 00930 * to stop asking for LQR. We haven't got any other protocol. 00931 * If they Nak the reporting period, take their value XXX ? 00932 */ 00933 NAKCILQR(CI_QUALITY, neg_lqr, 00934 if (cishort != PPP_LQR) { 00935 try.neg_lqr = 0; 00936 } else { 00937 try.lqr_period = cilong; 00938 } 00939 ); 00940 00941 /* 00942 * Only implementing CBCP...not the rest of the callback options 00943 */ 00944 NAKCICHAR(CI_CALLBACK, neg_cbcp, 00945 try.neg_cbcp = 0; 00946 ); 00947 00948 /* 00949 * Check for a looped-back line. 00950 */ 00951 NAKCILONG(CI_MAGICNUMBER, neg_magicnumber, 00952 try.magicnumber = magic(); 00953 looped_back = 1; 00954 ); 00955 00956 /* 00957 * Peer shouldn't send Nak for protocol compression or 00958 * address/control compression requests; they should send 00959 * a Reject instead. If they send a Nak, treat it as a Reject. 00960 */ 00961 NAKCIVOID(CI_PCOMPRESSION, neg_pcompression, 00962 try.neg_pcompression = 0; 00963 ); 00964 NAKCIVOID(CI_ACCOMPRESSION, neg_accompression, 00965 try.neg_accompression = 0; 00966 ); 00967 00968 /* 00969 * There may be remaining CIs, if the peer is requesting negotiation 00970 * on an option that we didn't include in our request packet. 00971 * If we see an option that we requested, or one we've already seen 00972 * in this packet, then this packet is bad. 00973 * If we wanted to respond by starting to negotiate on the requested 00974 * option(s), we could, but we don't, because except for the 00975 * authentication type and quality protocol, if we are not negotiating 00976 * an option, it is because we were told not to. 00977 * For the authentication type, the Nak from the peer means 00978 * `let me authenticate myself with you' which is a bit pointless. 00979 * For the quality protocol, the Nak means `ask me to send you quality 00980 * reports', but if we didn't ask for them, we don't want them. 00981 * An option we don't recognize represents the peer asking to 00982 * negotiate some option we don't support, so ignore it. 00983 */ 00984 while (len > CILEN_VOID) { 00985 GETCHAR(citype, p); 00986 GETCHAR(cilen, p); 00987 if (cilen < CILEN_VOID || (len -= cilen) < 0) { 00988 goto bad; 00989 } 00990 next = p + cilen - 2; 00991 00992 switch (citype) { 00993 case CI_MRU: 00994 if ((go->neg_mru && go->mru != PPP_DEFMRU) 00995 || no.neg_mru || cilen != CILEN_SHORT) { 00996 goto bad; 00997 } 00998 GETSHORT(cishort, p); 00999 if (cishort < PPP_DEFMRU) { 01000 try.mru = cishort; 01001 } 01002 break; 01003 case CI_ASYNCMAP: 01004 if ((go->neg_asyncmap && go->asyncmap != 0xFFFFFFFFl) 01005 || no.neg_asyncmap || cilen != CILEN_LONG) { 01006 goto bad; 01007 } 01008 break; 01009 case CI_AUTHTYPE: 01010 if (go->neg_chap || no.neg_chap || go->neg_upap || no.neg_upap) { 01011 goto bad; 01012 } 01013 break; 01014 case CI_MAGICNUMBER: 01015 if (go->neg_magicnumber || no.neg_magicnumber || 01016 cilen != CILEN_LONG) { 01017 goto bad; 01018 } 01019 break; 01020 case CI_PCOMPRESSION: 01021 if (go->neg_pcompression || no.neg_pcompression 01022 || cilen != CILEN_VOID) { 01023 goto bad; 01024 } 01025 break; 01026 case CI_ACCOMPRESSION: 01027 if (go->neg_accompression || no.neg_accompression 01028 || cilen != CILEN_VOID) { 01029 goto bad; 01030 } 01031 break; 01032 case CI_QUALITY: 01033 if (go->neg_lqr || no.neg_lqr || cilen != CILEN_LQR) { 01034 goto bad; 01035 } 01036 break; 01037 } 01038 p = next; 01039 } 01040 01041 /* If there is still anything left, this packet is bad. */ 01042 if (len != 0) { 01043 goto bad; 01044 } 01045 01046 /* 01047 * OK, the Nak is good. Now we can update state. 01048 */ 01049 if (f->state != LS_OPENED) { 01050 if (looped_back) { 01051 if (++try.numloops >= lcp_loopbackfail) { 01052 LCPDEBUG(LOG_NOTICE, ("Serial line is looped back.\n")); 01053 lcp_close(f->unit, "Loopback detected"); 01054 } 01055 } else { 01056 try.numloops = 0; 01057 } 01058 *go = try; 01059 } 01060 01061 return 1; 01062 01063 bad: 01064 LCPDEBUG(LOG_WARNING, ("lcp_nakci: received bad Nak!\n")); 01065 return 0; 01066 } 01067 01068 01069 /* 01070 * lcp_rejci - Peer has Rejected some of our CIs. 01071 * This should not modify any state if the Reject is bad 01072 * or if LCP is in the LS_OPENED state. 01073 * 01074 * Returns: 01075 * 0 - Reject was bad. 01076 * 1 - Reject was good. 01077 */ 01078 static int 01079 lcp_rejci(fsm *f, u_char *p, int len) 01080 { 01081 lcp_options *go = &lcp_gotoptions[f->unit]; 01082 u_char cichar; 01083 u_short cishort; 01084 u32_t cilong; 01085 lcp_options try; /* options to request next time */ 01086 01087 try = *go; 01088 01089 /* 01090 * Any Rejected CIs must be in exactly the same order that we sent. 01091 * Check packet length and CI length at each step. 01092 * If we find any deviations, then this packet is bad. 01093 */ 01094 #define REJCIVOID(opt, neg) \ 01095 if (go->neg && \ 01096 len >= CILEN_VOID && \ 01097 p[1] == CILEN_VOID && \ 01098 p[0] == opt) { \ 01099 len -= CILEN_VOID; \ 01100 INCPTR(CILEN_VOID, p); \ 01101 try.neg = 0; \ 01102 LCPDEBUG(LOG_INFO, ("lcp_rejci: void opt %d rejected\n", opt)); \ 01103 } 01104 #define REJCISHORT(opt, neg, val) \ 01105 if (go->neg && \ 01106 len >= CILEN_SHORT && \ 01107 p[1] == CILEN_SHORT && \ 01108 p[0] == opt) { \ 01109 len -= CILEN_SHORT; \ 01110 INCPTR(2, p); \ 01111 GETSHORT(cishort, p); \ 01112 /* Check rejected value. */ \ 01113 if (cishort != val) { \ 01114 goto bad; \ 01115 } \ 01116 try.neg = 0; \ 01117 LCPDEBUG(LOG_INFO, ("lcp_rejci: short opt %d rejected\n", opt)); \ 01118 } 01119 #define REJCICHAP(opt, neg, val, digest) \ 01120 if (go->neg && \ 01121 len >= CILEN_CHAP && \ 01122 p[1] == CILEN_CHAP && \ 01123 p[0] == opt) { \ 01124 len -= CILEN_CHAP; \ 01125 INCPTR(2, p); \ 01126 GETSHORT(cishort, p); \ 01127 GETCHAR(cichar, p); \ 01128 /* Check rejected value. */ \ 01129 if (cishort != val || cichar != digest) { \ 01130 goto bad; \ 01131 } \ 01132 try.neg = 0; \ 01133 try.neg_upap = 0; \ 01134 LCPDEBUG(LOG_INFO, ("lcp_rejci: chap opt %d rejected\n", opt)); \ 01135 } 01136 #define REJCILONG(opt, neg, val) \ 01137 if (go->neg && \ 01138 len >= CILEN_LONG && \ 01139 p[1] == CILEN_LONG && \ 01140 p[0] == opt) { \ 01141 len -= CILEN_LONG; \ 01142 INCPTR(2, p); \ 01143 GETLONG(cilong, p); \ 01144 /* Check rejected value. */ \ 01145 if (cilong != val) { \ 01146 goto bad; \ 01147 } \ 01148 try.neg = 0; \ 01149 LCPDEBUG(LOG_INFO, ("lcp_rejci: long opt %d rejected\n", opt)); \ 01150 } 01151 #define REJCILQR(opt, neg, val) \ 01152 if (go->neg && \ 01153 len >= CILEN_LQR && \ 01154 p[1] == CILEN_LQR && \ 01155 p[0] == opt) { \ 01156 len -= CILEN_LQR; \ 01157 INCPTR(2, p); \ 01158 GETSHORT(cishort, p); \ 01159 GETLONG(cilong, p); \ 01160 /* Check rejected value. */ \ 01161 if (cishort != PPP_LQR || cilong != val) { \ 01162 goto bad; \ 01163 } \ 01164 try.neg = 0; \ 01165 LCPDEBUG(LOG_INFO, ("lcp_rejci: LQR opt %d rejected\n", opt)); \ 01166 } 01167 #define REJCICBCP(opt, neg, val) \ 01168 if (go->neg && \ 01169 len >= CILEN_CBCP && \ 01170 p[1] == CILEN_CBCP && \ 01171 p[0] == opt) { \ 01172 len -= CILEN_CBCP; \ 01173 INCPTR(2, p); \ 01174 GETCHAR(cichar, p); \ 01175 /* Check rejected value. */ \ 01176 if (cichar != val) { \ 01177 goto bad; \ 01178 } \ 01179 try.neg = 0; \ 01180 LCPDEBUG(LOG_INFO, ("lcp_rejci: Callback opt %d rejected\n", opt)); \ 01181 } 01182 01183 REJCISHORT(CI_MRU, neg_mru, go->mru); 01184 REJCILONG(CI_ASYNCMAP, neg_asyncmap, go->asyncmap); 01185 REJCICHAP(CI_AUTHTYPE, neg_chap, PPP_CHAP, go->chap_mdtype); 01186 if (!go->neg_chap) { 01187 REJCISHORT(CI_AUTHTYPE, neg_upap, PPP_PAP); 01188 } 01189 REJCILQR(CI_QUALITY, neg_lqr, go->lqr_period); 01190 REJCICBCP(CI_CALLBACK, neg_cbcp, CBCP_OPT); 01191 REJCILONG(CI_MAGICNUMBER, neg_magicnumber, go->magicnumber); 01192 REJCIVOID(CI_PCOMPRESSION, neg_pcompression); 01193 REJCIVOID(CI_ACCOMPRESSION, neg_accompression); 01194 01195 /* 01196 * If there are any remaining CIs, then this packet is bad. 01197 */ 01198 if (len != 0) { 01199 goto bad; 01200 } 01201 /* 01202 * Now we can update state. 01203 */ 01204 if (f->state != LS_OPENED) { 01205 *go = try; 01206 } 01207 return 1; 01208 01209 bad: 01210 LCPDEBUG(LOG_WARNING, ("lcp_rejci: received bad Reject!\n")); 01211 return 0; 01212 } 01213 01214 01215 /* 01216 * lcp_reqci - Check the peer's requested CIs and send appropriate response. 01217 * 01218 * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified 01219 * appropriately. If reject_if_disagree is non-zero, doesn't return 01220 * CONFNAK; returns CONFREJ if it can't return CONFACK. 01221 */ 01222 static int 01223 lcp_reqci(fsm *f, 01224 u_char *inp, /* Requested CIs */ 01225 int *lenp, /* Length of requested CIs */ 01226 int reject_if_disagree) 01227 { 01228 lcp_options *go = &lcp_gotoptions[f->unit]; 01229 lcp_options *ho = &lcp_hisoptions[f->unit]; 01230 lcp_options *ao = &lcp_allowoptions[f->unit]; 01231 u_char *cip, *next; /* Pointer to current and next CIs */ 01232 int cilen, citype; /* Parsed len, type */ 01233 u_char cichar; /* Parsed char value */ 01234 u_short cishort; /* Parsed short value */ 01235 u32_t cilong; /* Parse long value */ 01236 int rc = CONFACK; /* Final packet return code */ 01237 int orc; /* Individual option return code */ 01238 u_char *p; /* Pointer to next char to parse */ 01239 u_char *rejp; /* Pointer to next char in reject frame */ 01240 u_char *nakp; /* Pointer to next char in Nak frame */ 01241 int l = *lenp; /* Length left */ 01242 #if TRACELCP > 0 01243 char traceBuf[80]; 01244 size_t traceNdx = 0; 01245 #endif 01246 01247 /* 01248 * Reset all his options. 01249 */ 01250 BZERO(ho, sizeof(*ho)); 01251 01252 /* 01253 * Process all his options. 01254 */ 01255 next = inp; 01256 nakp = nak_buffer; 01257 rejp = inp; 01258 while (l) { 01259 orc = CONFACK; /* Assume success */ 01260 cip = p = next; /* Remember begining of CI */ 01261 if (l < 2 || /* Not enough data for CI header or */ 01262 p[1] < 2 || /* CI length too small or */ 01263 p[1] > l) { /* CI length too big? */ 01264 LCPDEBUG(LOG_WARNING, ("lcp_reqci: bad CI length!\n")); 01265 orc = CONFREJ; /* Reject bad CI */ 01266 cilen = l; /* Reject till end of packet */ 01267 l = 0; /* Don't loop again */ 01268 citype = 0; 01269 goto endswitch; 01270 } 01271 GETCHAR(citype, p); /* Parse CI type */ 01272 GETCHAR(cilen, p); /* Parse CI length */ 01273 l -= cilen; /* Adjust remaining length */ 01274 next += cilen; /* Step to next CI */ 01275 01276 switch (citype) { /* Check CI type */ 01277 case CI_MRU: 01278 if (!ao->neg_mru) { /* Allow option? */ 01279 LCPDEBUG(LOG_INFO, ("lcp_reqci: Reject MRU - not allowed\n")); 01280 orc = CONFREJ; /* Reject CI */ 01281 break; 01282 } else if (cilen != CILEN_SHORT) { /* Check CI length */ 01283 LCPDEBUG(LOG_INFO, ("lcp_reqci: Reject MRU - bad length\n")); 01284 orc = CONFREJ; /* Reject CI */ 01285 break; 01286 } 01287 GETSHORT(cishort, p); /* Parse MRU */ 01288 01289 /* 01290 * He must be able to receive at least our minimum. 01291 * No need to check a maximum. If he sends a large number, 01292 * we'll just ignore it. 01293 */ 01294 if (cishort < PPP_MINMRU) { 01295 LCPDEBUG(LOG_INFO, ("lcp_reqci: Nak - MRU too small\n")); 01296 orc = CONFNAK; /* Nak CI */ 01297 PUTCHAR(CI_MRU, nakp); 01298 PUTCHAR(CILEN_SHORT, nakp); 01299 PUTSHORT(PPP_MINMRU, nakp); /* Give him a hint */ 01300 break; 01301 } 01302 ho->neg_mru = 1; /* Remember he sent MRU */ 01303 ho->mru = cishort; /* And remember value */ 01304 #if TRACELCP > 0 01305 snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " MRU %d", cishort); 01306 traceNdx = strlen(traceBuf); 01307 #endif 01308 break; 01309 01310 case CI_ASYNCMAP: 01311 if (!ao->neg_asyncmap) { 01312 LCPDEBUG(LOG_INFO, ("lcp_reqci: Reject ASYNCMAP not allowed\n")); 01313 orc = CONFREJ; 01314 break; 01315 } else if (cilen != CILEN_LONG) { 01316 LCPDEBUG(LOG_INFO, ("lcp_reqci: Reject ASYNCMAP bad length\n")); 01317 orc = CONFREJ; 01318 break; 01319 } 01320 GETLONG(cilong, p); 01321 01322 /* 01323 * Asyncmap must have set at least the bits 01324 * which are set in lcp_allowoptions[unit].asyncmap. 01325 */ 01326 if ((ao->asyncmap & ~cilong) != 0) { 01327 LCPDEBUG(LOG_INFO, ("lcp_reqci: Nak ASYNCMAP %lX missing %lX\n", 01328 cilong, ao->asyncmap)); 01329 orc = CONFNAK; 01330 PUTCHAR(CI_ASYNCMAP, nakp); 01331 PUTCHAR(CILEN_LONG, nakp); 01332 PUTLONG(ao->asyncmap | cilong, nakp); 01333 break; 01334 } 01335 ho->neg_asyncmap = 1; 01336 ho->asyncmap = cilong; 01337 #if TRACELCP > 0 01338 snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " ASYNCMAP=%lX", cilong); 01339 traceNdx = strlen(traceBuf); 01340 #endif 01341 break; 01342 01343 case CI_AUTHTYPE: 01344 if (cilen < CILEN_SHORT) { 01345 LCPDEBUG(LOG_INFO, ("lcp_reqci: Reject AUTHTYPE missing arg\n")); 01346 orc = CONFREJ; 01347 break; 01348 } else if (!(ao->neg_upap || ao->neg_chap)) { 01349 /* 01350 * Reject the option if we're not willing to authenticate. 01351 */ 01352 LCPDEBUG(LOG_INFO, ("lcp_reqci: Reject AUTHTYPE not allowed\n")); 01353 orc = CONFREJ; 01354 break; 01355 } 01356 GETSHORT(cishort, p); 01357 01358 /* 01359 * Authtype must be UPAP or CHAP. 01360 * 01361 * Note: if both ao->neg_upap and ao->neg_chap are set, 01362 * and the peer sends a Configure-Request with two 01363 * authenticate-protocol requests, one for CHAP and one 01364 * for UPAP, then we will reject the second request. 01365 * Whether we end up doing CHAP or UPAP depends then on 01366 * the ordering of the CIs in the peer's Configure-Request. 01367 */ 01368 01369 if (cishort == PPP_PAP) { 01370 if (ho->neg_chap) { /* we've already accepted CHAP */ 01371 LCPDEBUG(LOG_WARNING, ("lcp_reqci: Reject AUTHTYPE PAP already accepted\n")); 01372 orc = CONFREJ; 01373 break; 01374 } else if (cilen != CILEN_SHORT) { 01375 LCPDEBUG(LOG_WARNING, ("lcp_reqci: Reject AUTHTYPE PAP bad len\n")); 01376 orc = CONFREJ; 01377 break; 01378 } 01379 if (!ao->neg_upap) { /* we don't want to do PAP */ 01380 LCPDEBUG(LOG_WARNING, ("lcp_reqci: Nak AUTHTYPE PAP not allowed\n")); 01381 orc = CONFNAK; /* NAK it and suggest CHAP */ 01382 PUTCHAR(CI_AUTHTYPE, nakp); 01383 PUTCHAR(CILEN_CHAP, nakp); 01384 PUTSHORT(PPP_CHAP, nakp); 01385 PUTCHAR(ao->chap_mdtype, nakp); 01386 break; 01387 } 01388 ho->neg_upap = 1; 01389 #if TRACELCP > 0 01390 snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " PAP (%X)", cishort); 01391 traceNdx = strlen(traceBuf); 01392 #endif 01393 break; 01394 } 01395 if (cishort == PPP_CHAP) { 01396 if (ho->neg_upap) { /* we've already accepted PAP */ 01397 LCPDEBUG(LOG_WARNING, ("lcp_reqci: Reject AUTHTYPE CHAP accepted PAP\n")); 01398 orc = CONFREJ; 01399 break; 01400 } else if (cilen != CILEN_CHAP) { 01401 LCPDEBUG(LOG_WARNING, ("lcp_reqci: Reject AUTHTYPE CHAP bad len\n")); 01402 orc = CONFREJ; 01403 break; 01404 } 01405 if (!ao->neg_chap) { /* we don't want to do CHAP */ 01406 LCPDEBUG(LOG_WARNING, ("lcp_reqci: Nak AUTHTYPE CHAP not allowed\n")); 01407 orc = CONFNAK; /* NAK it and suggest PAP */ 01408 PUTCHAR(CI_AUTHTYPE, nakp); 01409 PUTCHAR(CILEN_SHORT, nakp); 01410 PUTSHORT(PPP_PAP, nakp); 01411 break; 01412 } 01413 GETCHAR(cichar, p); /* get digest type*/ 01414 if (cichar != CHAP_DIGEST_MD5 01415 #if MSCHAP_SUPPORT 01416 && cichar != CHAP_MICROSOFT 01417 #endif 01418 ) { 01419 LCPDEBUG(LOG_WARNING, ("lcp_reqci: Nak AUTHTYPE CHAP digest=%d\n", (int)cichar)); 01420 orc = CONFNAK; 01421 PUTCHAR(CI_AUTHTYPE, nakp); 01422 PUTCHAR(CILEN_CHAP, nakp); 01423 PUTSHORT(PPP_CHAP, nakp); 01424 PUTCHAR(ao->chap_mdtype, nakp); 01425 break; 01426 } 01427 #if TRACELCP > 0 01428 snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CHAP %X,%d", cishort, (int)cichar); 01429 traceNdx = strlen(traceBuf); 01430 #endif 01431 ho->chap_mdtype = cichar; /* save md type */ 01432 ho->neg_chap = 1; 01433 break; 01434 } 01435 01436 /* 01437 * We don't recognize the protocol they're asking for. 01438 * Nak it with something we're willing to do. 01439 * (At this point we know ao->neg_upap || ao->neg_chap.) 01440 */ 01441 orc = CONFNAK; 01442 PUTCHAR(CI_AUTHTYPE, nakp); 01443 if (ao->neg_chap) { 01444 LCPDEBUG(LOG_WARNING, ("lcp_reqci: Nak AUTHTYPE %d req CHAP\n", cishort)); 01445 PUTCHAR(CILEN_CHAP, nakp); 01446 PUTSHORT(PPP_CHAP, nakp); 01447 PUTCHAR(ao->chap_mdtype, nakp); 01448 } else { 01449 LCPDEBUG(LOG_WARNING, ("lcp_reqci: Nak AUTHTYPE %d req PAP\n", cishort)); 01450 PUTCHAR(CILEN_SHORT, nakp); 01451 PUTSHORT(PPP_PAP, nakp); 01452 } 01453 break; 01454 01455 case CI_QUALITY: 01456 GETSHORT(cishort, p); 01457 GETLONG(cilong, p); 01458 #if TRACELCP > 0 01459 snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " QUALITY (%x %x)", cishort, (unsigned int) cilong); 01460 traceNdx = strlen(traceBuf); 01461 #endif 01462 01463 if (!ao->neg_lqr || 01464 cilen != CILEN_LQR) { 01465 orc = CONFREJ; 01466 break; 01467 } 01468 01469 /* 01470 * Check the protocol and the reporting period. 01471 * XXX When should we Nak this, and what with? 01472 */ 01473 if (cishort != PPP_LQR) { 01474 orc = CONFNAK; 01475 PUTCHAR(CI_QUALITY, nakp); 01476 PUTCHAR(CILEN_LQR, nakp); 01477 PUTSHORT(PPP_LQR, nakp); 01478 PUTLONG(ao->lqr_period, nakp); 01479 break; 01480 } 01481 break; 01482 01483 case CI_MAGICNUMBER: 01484 if (!(ao->neg_magicnumber || go->neg_magicnumber) || 01485 cilen != CILEN_LONG) { 01486 orc = CONFREJ; 01487 break; 01488 } 01489 GETLONG(cilong, p); 01490 #if TRACELCP > 0 01491 snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " MAGICNUMBER (%lX)", cilong); 01492 traceNdx = strlen(traceBuf); 01493 #endif 01494 01495 /* 01496 * He must have a different magic number. 01497 */ 01498 if (go->neg_magicnumber && 01499 cilong == go->magicnumber) { 01500 cilong = magic(); /* Don't put magic() inside macro! */ 01501 orc = CONFNAK; 01502 PUTCHAR(CI_MAGICNUMBER, nakp); 01503 PUTCHAR(CILEN_LONG, nakp); 01504 PUTLONG(cilong, nakp); 01505 break; 01506 } 01507 ho->neg_magicnumber = 1; 01508 ho->magicnumber = cilong; 01509 break; 01510 01511 01512 case CI_PCOMPRESSION: 01513 #if TRACELCP > 0 01514 snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " PCOMPRESSION"); 01515 traceNdx = strlen(traceBuf); 01516 #endif 01517 if (!ao->neg_pcompression || 01518 cilen != CILEN_VOID) { 01519 orc = CONFREJ; 01520 break; 01521 } 01522 ho->neg_pcompression = 1; 01523 break; 01524 01525 case CI_ACCOMPRESSION: 01526 #if TRACELCP > 0 01527 snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " ACCOMPRESSION"); 01528 traceNdx = strlen(traceBuf); 01529 #endif 01530 if (!ao->neg_accompression || 01531 cilen != CILEN_VOID) { 01532 orc = CONFREJ; 01533 break; 01534 } 01535 ho->neg_accompression = 1; 01536 break; 01537 01538 case CI_MRRU: 01539 #if TRACELCP > 0 01540 snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CI_MRRU"); 01541 traceNdx = strlen(traceBuf); 01542 #endif 01543 orc = CONFREJ; 01544 break; 01545 01546 case CI_SSNHF: 01547 #if TRACELCP > 0 01548 snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CI_SSNHF"); 01549 traceNdx = strlen(traceBuf); 01550 #endif 01551 orc = CONFREJ; 01552 break; 01553 01554 case CI_EPDISC: 01555 #if TRACELCP > 0 01556 snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CI_EPDISC"); 01557 traceNdx = strlen(traceBuf); 01558 #endif 01559 orc = CONFREJ; 01560 break; 01561 01562 default: 01563 #if TRACELCP 01564 snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " unknown %d", citype); 01565 traceNdx = strlen(traceBuf); 01566 #endif 01567 orc = CONFREJ; 01568 break; 01569 } 01570 01571 endswitch: 01572 #if TRACELCP 01573 if (traceNdx >= 80 - 32) { 01574 LCPDEBUG(LOG_INFO, ("lcp_reqci: rcvd%s\n", traceBuf)); 01575 traceNdx = 0; 01576 } 01577 #endif 01578 if (orc == CONFACK && /* Good CI */ 01579 rc != CONFACK) { /* but prior CI wasnt? */ 01580 continue; /* Don't send this one */ 01581 } 01582 01583 if (orc == CONFNAK) { /* Nak this CI? */ 01584 if (reject_if_disagree /* Getting fed up with sending NAKs? */ 01585 && citype != CI_MAGICNUMBER) { 01586 orc = CONFREJ; /* Get tough if so */ 01587 } else { 01588 if (rc == CONFREJ) { /* Rejecting prior CI? */ 01589 continue; /* Don't send this one */ 01590 } 01591 rc = CONFNAK; 01592 } 01593 } 01594 if (orc == CONFREJ) { /* Reject this CI */ 01595 rc = CONFREJ; 01596 if (cip != rejp) { /* Need to move rejected CI? */ 01597 BCOPY(cip, rejp, cilen); /* Move it */ 01598 } 01599 INCPTR(cilen, rejp); /* Update output pointer */ 01600 } 01601 } 01602 01603 /* 01604 * If we wanted to send additional NAKs (for unsent CIs), the 01605 * code would go here. The extra NAKs would go at *nakp. 01606 * At present there are no cases where we want to ask the 01607 * peer to negotiate an option. 01608 */ 01609 01610 switch (rc) { 01611 case CONFACK: 01612 *lenp = (int)(next - inp); 01613 break; 01614 case CONFNAK: 01615 /* 01616 * Copy the Nak'd options from the nak_buffer to the caller's buffer. 01617 */ 01618 *lenp = (int)(nakp - nak_buffer); 01619 BCOPY(nak_buffer, inp, *lenp); 01620 break; 01621 case CONFREJ: 01622 *lenp = (int)(rejp - inp); 01623 break; 01624 } 01625 01626 #if TRACELCP > 0 01627 if (traceNdx > 0) { 01628 LCPDEBUG(LOG_INFO, ("lcp_reqci: %s\n", traceBuf)); 01629 } 01630 #endif 01631 LCPDEBUG(LOG_INFO, ("lcp_reqci: returning CONF%s.\n", CODENAME(rc))); 01632 return (rc); /* Return final code */ 01633 } 01634 01635 01636 /* 01637 * lcp_up - LCP has come UP. 01638 */ 01639 static void 01640 lcp_up(fsm *f) 01641 { 01642 lcp_options *wo = &lcp_wantoptions[f->unit]; 01643 lcp_options *ho = &lcp_hisoptions[f->unit]; 01644 lcp_options *go = &lcp_gotoptions[f->unit]; 01645 lcp_options *ao = &lcp_allowoptions[f->unit]; 01646 01647 if (!go->neg_magicnumber) { 01648 go->magicnumber = 0; 01649 } 01650 if (!ho->neg_magicnumber) { 01651 ho->magicnumber = 0; 01652 } 01653 01654 /* 01655 * Set our MTU to the smaller of the MTU we wanted and 01656 * the MRU our peer wanted. If we negotiated an MRU, 01657 * set our MRU to the larger of value we wanted and 01658 * the value we got in the negotiation. 01659 */ 01660 ppp_send_config(f->unit, LWIP_MIN(ao->mru, (ho->neg_mru? ho->mru: PPP_MRU)), 01661 (ho->neg_asyncmap? ho->asyncmap: 0xffffffffl), 01662 ho->neg_pcompression, ho->neg_accompression); 01663 /* 01664 * If the asyncmap hasn't been negotiated, we really should 01665 * set the receive asyncmap to ffffffff, but we set it to 0 01666 * for backwards contemptibility. 01667 */ 01668 ppp_recv_config(f->unit, (go->neg_mru? LWIP_MAX(wo->mru, go->mru): PPP_MRU), 01669 (go->neg_asyncmap? go->asyncmap: 0x00000000), 01670 go->neg_pcompression, go->neg_accompression); 01671 01672 if (ho->neg_mru) { 01673 peer_mru[f->unit] = ho->mru; 01674 } 01675 01676 lcp_echo_lowerup(f->unit); /* Enable echo messages */ 01677 01678 link_established(f->unit); /* The link is up; authenticate now */ 01679 } 01680 01681 01682 /* 01683 * lcp_down - LCP has gone DOWN. 01684 * 01685 * Alert other protocols. 01686 */ 01687 static void 01688 lcp_down(fsm *f) 01689 { 01690 lcp_options *go = &lcp_gotoptions[f->unit]; 01691 01692 lcp_echo_lowerdown(f->unit); 01693 01694 link_down(f->unit); 01695 01696 ppp_send_config(f->unit, PPP_MRU, 0xffffffffl, 0, 0); 01697 ppp_recv_config(f->unit, PPP_MRU, 01698 (go->neg_asyncmap? go->asyncmap: 0x00000000), 01699 go->neg_pcompression, go->neg_accompression); 01700 peer_mru[f->unit] = PPP_MRU; 01701 } 01702 01703 01704 /* 01705 * lcp_starting - LCP needs the lower layer up. 01706 */ 01707 static void 01708 lcp_starting(fsm *f) 01709 { 01710 link_required(f->unit); /* lwip: currently does nothing */ 01711 } 01712 01713 01714 /* 01715 * lcp_finished - LCP has finished with the lower layer. 01716 */ 01717 static void 01718 lcp_finished(fsm *f) 01719 { 01720 link_terminated(f->unit); /* we are finished with the link */ 01721 } 01722 01723 01724 #if PPP_ADDITIONAL_CALLBACKS 01725 /* 01726 * print_string - print a readable representation of a string using 01727 * printer. 01728 */ 01729 static void 01730 print_string( char *p, int len, void (*printer) (void *, char *, ...), void *arg) 01731 { 01732 int c; 01733 01734 printer(arg, "\""); 01735 for (; len > 0; --len) { 01736 c = *p++; 01737 if (' ' <= c && c <= '~') { 01738 if (c == '\\' || c == '"') { 01739 printer(arg, "\\"); 01740 } 01741 printer(arg, "%c", c); 01742 } else { 01743 switch (c) { 01744 case '\n': 01745 printer(arg, "\\n"); 01746 break; 01747 case '\r': 01748 printer(arg, "\\r"); 01749 break; 01750 case '\t': 01751 printer(arg, "\\t"); 01752 break; 01753 default: 01754 printer(arg, "\\%.3o", c); 01755 } 01756 } 01757 } 01758 printer(arg, "\""); 01759 } 01760 01761 01762 /* 01763 * lcp_printpkt - print the contents of an LCP packet. 01764 */ 01765 static char *lcp_codenames[] = { 01766 "ConfReq", "ConfAck", "ConfNak", "ConfRej", 01767 "TermReq", "TermAck", "CodeRej", "ProtRej", 01768 "EchoReq", "EchoRep", "DiscReq" 01769 }; 01770 01771 static int 01772 lcp_printpkt( u_char *p, int plen, void (*printer) (void *, char *, ...), void *arg) 01773 { 01774 int code, id, len, olen; 01775 u_char *pstart, *optend; 01776 u_short cishort; 01777 u32_t cilong; 01778 01779 if (plen < HEADERLEN) { 01780 return 0; 01781 } 01782 pstart = p; 01783 GETCHAR(code, p); 01784 GETCHAR(id, p); 01785 GETSHORT(len, p); 01786 if (len < HEADERLEN || len > plen) { 01787 return 0; 01788 } 01789 01790 if (code >= 1 && code <= sizeof(lcp_codenames) / sizeof(char *)) { 01791 printer(arg, " %s", lcp_codenames[code-1]); 01792 } else { 01793 printer(arg, " code=0x%x", code); 01794 } 01795 printer(arg, " id=0x%x", id); 01796 len -= HEADERLEN; 01797 switch (code) { 01798 case CONFREQ: 01799 case CONFACK: 01800 case CONFNAK: 01801 case CONFREJ: 01802 /* print option list */ 01803 while (len >= 2) { 01804 GETCHAR(code, p); 01805 GETCHAR(olen, p); 01806 p -= 2; 01807 if (olen < 2 || olen > len) { 01808 break; 01809 } 01810 printer(arg, " <"); 01811 len -= olen; 01812 optend = p + olen; 01813 switch (code) { 01814 case CI_MRU: 01815 if (olen == CILEN_SHORT) { 01816 p += 2; 01817 GETSHORT(cishort, p); 01818 printer(arg, "mru %d", cishort); 01819 } 01820 break; 01821 case CI_ASYNCMAP: 01822 if (olen == CILEN_LONG) { 01823 p += 2; 01824 GETLONG(cilong, p); 01825 printer(arg, "asyncmap 0x%lx", cilong); 01826 } 01827 break; 01828 case CI_AUTHTYPE: 01829 if (olen >= CILEN_SHORT) { 01830 p += 2; 01831 printer(arg, "auth "); 01832 GETSHORT(cishort, p); 01833 switch (cishort) { 01834 case PPP_PAP: 01835 printer(arg, "pap"); 01836 break; 01837 case PPP_CHAP: 01838 printer(arg, "chap"); 01839 break; 01840 default: 01841 printer(arg, "0x%x", cishort); 01842 } 01843 } 01844 break; 01845 case CI_QUALITY: 01846 if (olen >= CILEN_SHORT) { 01847 p += 2; 01848 printer(arg, "quality "); 01849 GETSHORT(cishort, p); 01850 switch (cishort) { 01851 case PPP_LQR: 01852 printer(arg, "lqr"); 01853 break; 01854 default: 01855 printer(arg, "0x%x", cishort); 01856 } 01857 } 01858 break; 01859 case CI_CALLBACK: 01860 if (olen >= CILEN_CHAR) { 01861 p += 2; 01862 printer(arg, "callback "); 01863 GETSHORT(cishort, p); 01864 switch (cishort) { 01865 case CBCP_OPT: 01866 printer(arg, "CBCP"); 01867 break; 01868 default: 01869 printer(arg, "0x%x", cishort); 01870 } 01871 } 01872 break; 01873 case CI_MAGICNUMBER: 01874 if (olen == CILEN_LONG) { 01875 p += 2; 01876 GETLONG(cilong, p); 01877 printer(arg, "magic 0x%x", cilong); 01878 } 01879 break; 01880 case CI_PCOMPRESSION: 01881 if (olen == CILEN_VOID) { 01882 p += 2; 01883 printer(arg, "pcomp"); 01884 } 01885 break; 01886 case CI_ACCOMPRESSION: 01887 if (olen == CILEN_VOID) { 01888 p += 2; 01889 printer(arg, "accomp"); 01890 } 01891 break; 01892 } 01893 while (p < optend) { 01894 GETCHAR(code, p); 01895 printer(arg, " %.2x", code); 01896 } 01897 printer(arg, ">"); 01898 } 01899 break; 01900 01901 case TERMACK: 01902 case TERMREQ: 01903 if (len > 0 && *p >= ' ' && *p < 0x7f) { 01904 printer(arg, " "); 01905 print_string((char*)p, len, printer, arg); 01906 p += len; 01907 len = 0; 01908 } 01909 break; 01910 01911 case ECHOREQ: 01912 case ECHOREP: 01913 case DISCREQ: 01914 if (len >= 4) { 01915 GETLONG(cilong, p); 01916 printer(arg, " magic=0x%x", cilong); 01917 p += 4; 01918 len -= 4; 01919 } 01920 break; 01921 } 01922 01923 /* print the rest of the bytes in the packet */ 01924 for (; len > 0; --len) { 01925 GETCHAR(code, p); 01926 printer(arg, " %.2x", code); 01927 } 01928 01929 return (int)(p - pstart); 01930 } 01931 #endif /* PPP_ADDITIONAL_CALLBACKS */ 01932 01933 /* 01934 * Time to shut down the link because there is nothing out there. 01935 */ 01936 static void 01937 LcpLinkFailure (fsm *f) 01938 { 01939 if (f->state == LS_OPENED) { 01940 LCPDEBUG(LOG_INFO, ("No response to %d echo-requests\n", lcp_echos_pending)); 01941 LCPDEBUG(LOG_NOTICE, ("Serial link appears to be disconnected.\n")); 01942 lcp_close(f->unit, "Peer not responding"); 01943 } 01944 } 01945 01946 /* 01947 * Timer expired for the LCP echo requests from this process. 01948 */ 01949 static void 01950 LcpEchoCheck (fsm *f) 01951 { 01952 LcpSendEchoRequest (f); 01953 01954 /* 01955 * Start the timer for the next interval. 01956 */ 01957 LWIP_ASSERT("lcp_echo_timer_running == 0", lcp_echo_timer_running == 0); 01958 01959 TIMEOUT (LcpEchoTimeout, f, lcp_echo_interval); 01960 lcp_echo_timer_running = 1; 01961 } 01962 01963 /* 01964 * LcpEchoTimeout - Timer expired on the LCP echo 01965 */ 01966 static void 01967 LcpEchoTimeout (void *arg) 01968 { 01969 if (lcp_echo_timer_running != 0) { 01970 lcp_echo_timer_running = 0; 01971 LcpEchoCheck ((fsm *) arg); 01972 } 01973 } 01974 01975 /* 01976 * LcpEchoReply - LCP has received a reply to the echo 01977 */ 01978 static void 01979 lcp_received_echo_reply (fsm *f, int id, u_char *inp, int len) 01980 { 01981 u32_t magic; 01982 01983 LWIP_UNUSED_ARG(id); 01984 01985 /* Check the magic number - don't count replies from ourselves. */ 01986 if (len < 4) { 01987 LCPDEBUG(LOG_WARNING, ("lcp: received short Echo-Reply, length %d\n", len)); 01988 return; 01989 } 01990 GETLONG(magic, inp); 01991 if (lcp_gotoptions[f->unit].neg_magicnumber && magic == lcp_gotoptions[f->unit].magicnumber) { 01992 LCPDEBUG(LOG_WARNING, ("appear to have received our own echo-reply!\n")); 01993 return; 01994 } 01995 01996 /* Reset the number of outstanding echo frames */ 01997 lcp_echos_pending = 0; 01998 } 01999 02000 /* 02001 * LcpSendEchoRequest - Send an echo request frame to the peer 02002 */ 02003 static void 02004 LcpSendEchoRequest (fsm *f) 02005 { 02006 u32_t lcp_magic; 02007 u_char pkt[4], *pktp; 02008 02009 /* 02010 * Detect the failure of the peer at this point. 02011 */ 02012 if (lcp_echo_fails != 0) { 02013 if (lcp_echos_pending >= lcp_echo_fails) { 02014 LcpLinkFailure(f); 02015 lcp_echos_pending = 0; 02016 } 02017 } 02018 02019 /* 02020 * Make and send the echo request frame. 02021 */ 02022 if (f->state == LS_OPENED) { 02023 lcp_magic = lcp_gotoptions[f->unit].magicnumber; 02024 pktp = pkt; 02025 PUTLONG(lcp_magic, pktp); 02026 fsm_sdata(f, ECHOREQ, (u_char)(lcp_echo_number++ & 0xFF), pkt, (int)(pktp - pkt)); 02027 ++lcp_echos_pending; 02028 } 02029 } 02030 02031 /* 02032 * lcp_echo_lowerup - Start the timer for the LCP frame 02033 */ 02034 02035 static void 02036 lcp_echo_lowerup (int unit) 02037 { 02038 fsm *f = &lcp_fsm[unit]; 02039 02040 /* Clear the parameters for generating echo frames */ 02041 lcp_echos_pending = 0; 02042 lcp_echo_number = 0; 02043 lcp_echo_timer_running = 0; 02044 02045 /* If a timeout interval is specified then start the timer */ 02046 if (lcp_echo_interval != 0) { 02047 LcpEchoCheck (f); 02048 } 02049 } 02050 02051 /* 02052 * lcp_echo_lowerdown - Stop the timer for the LCP frame 02053 */ 02054 02055 static void 02056 lcp_echo_lowerdown (int unit) 02057 { 02058 fsm *f = &lcp_fsm[unit]; 02059 02060 if (lcp_echo_timer_running != 0) { 02061 UNTIMEOUT (LcpEchoTimeout, f); 02062 lcp_echo_timer_running = 0; 02063 } 02064 } 02065 02066 #endif /* PPP_SUPPORT */
Generated on Wed Jul 13 2022 09:48:37 by 1.7.2