Example program with HTTPServer and sensor data streaming over TCPSockets, using Donatien Garnier's Net APIs and services code on top of LWIP. Files StreamServer.h and .cpp encapsulate streaming over TCPSockets. Broadcast is done by sendToAll(), and all incoming data is echoed back to the client. Echo code can be replaced with some remote control of the streaming interface. See main() that shows how to periodically send some data to all subscribed clients. To subscribe, a client should open a socket at <mbed_ip> port 123. I used few lines in TCL code to set up a quick sink for the data. HTTP files are served on port 80 concurrently to the streaming.
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.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] MEM_POSITION; /* 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 } 02028 } 02029 02030 /* 02031 * lcp_echo_lowerup - Start the timer for the LCP frame 02032 */ 02033 02034 static void 02035 lcp_echo_lowerup (int unit) 02036 { 02037 fsm *f = &lcp_fsm[unit]; 02038 02039 /* Clear the parameters for generating echo frames */ 02040 lcp_echos_pending = 0; 02041 lcp_echo_number = 0; 02042 lcp_echo_timer_running = 0; 02043 02044 /* If a timeout interval is specified then start the timer */ 02045 if (lcp_echo_interval != 0) { 02046 LcpEchoCheck (f); 02047 } 02048 } 02049 02050 /* 02051 * lcp_echo_lowerdown - Stop the timer for the LCP frame 02052 */ 02053 02054 static void 02055 lcp_echo_lowerdown (int unit) 02056 { 02057 fsm *f = &lcp_fsm[unit]; 02058 02059 if (lcp_echo_timer_running != 0) { 02060 UNTIMEOUT (LcpEchoTimeout, f); 02061 lcp_echo_timer_running = 0; 02062 } 02063 } 02064 02065 #endif /* PPP_SUPPORT */
Generated on Tue Jul 12 2022 21:10:25 by 1.7.2