1 /***************************************************************************** 2 * ppp.c - Network Point to Point Protocol program file. 3 * 4 * Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. 5 * portions Copyright (c) 1997 by Global Election Systems Inc. 6 * 7 * The authors hereby grant permission to use, copy, modify, distribute, 8 * and license this software and its documentation for any purpose, provided 9 * that existing copyright notices are retained in all copies and that this 10 * notice and the following disclaimer are included verbatim in any 11 * distributions. No written agreement, license, or royalty fee is required 12 * for any of the authorized uses. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 * 25 ****************************************************************************** 26 * REVISION HISTORY 27 * 28 * 03-01-01 Marc Boucher <marc (at) mbsi.ca> 29 * Ported to lwIP. 30 * 97-11-05 Guy Lancaster <lancasterg (at) acm.org>, Global Election Systems Inc. 31 * Original. 32 *****************************************************************************/ 33 34 /* 35 * ppp_defs.h - PPP definitions. 36 * 37 * if_pppvar.h - private structures and declarations for PPP. 38 * 39 * Copyright (c) 1994 The Australian National University. 40 * All rights reserved. 41 * 42 * Permission to use, copy, modify, and distribute this software and its 43 * documentation is hereby granted, provided that the above copyright 44 * notice appears in all copies. This software is provided without any 45 * warranty, express or implied. The Australian National University 46 * makes no representations about the suitability of this software for 47 * any purpose. 48 * 49 * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY 50 * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 51 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 52 * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY 53 * OF SUCH DAMAGE. 54 * 55 * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, 56 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 57 * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 58 * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO 59 * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, 60 * OR MODIFICATIONS. 61 */ 62 63 /* 64 * if_ppp.h - Point-to-Point Protocol definitions. 65 * 66 * Copyright (c) 1989 Carnegie Mellon University. 67 * All rights reserved. 68 * 69 * Redistribution and use in source and binary forms are permitted 70 * provided that the above copyright notice and this paragraph are 71 * duplicated in all such forms and that any documentation, 72 * advertising materials, and other materials related to such 73 * distribution and use acknowledge that the software was developed 74 * by Carnegie Mellon University. The name of the 75 * University may not be used to endorse or promote products derived 76 * from this software without specific prior written permission. 77 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 78 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 79 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 80 */ 81 82 #include "lwip/opt.h" 83 84 #if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ 85 86 #include "lwip/ip.h" /* for ip_input() */ 87 88 #include "ppp.h" 89 #include "pppdebug.h" 90 91 #include "randm.h" 92 #include "fsm.h" 93 #if PAP_SUPPORT 94 #include "pap.h" 95 #endif /* PAP_SUPPORT */ 96 #if CHAP_SUPPORT 97 #include "chap.h" 98 #endif /* CHAP_SUPPORT */ 99 #include "ipcp.h" 100 #include "lcp.h" 101 #include "magic.h" 102 #include "auth.h" 103 #if VJ_SUPPORT 104 #include "vj.h" 105 #endif /* VJ_SUPPORT */ 106 #if PPPOE_SUPPORT 107 #include "netif/ppp_oe.h" 108 #endif /* PPPOE_SUPPORT */ 109 110 #include "lwip/tcpip.h" 111 #include "lwip/api.h" 112 #include "lwip/snmp.h" 113 114 #include <string.h> 115 116 /*************************/ 117 /*** LOCAL DEFINITIONS ***/ 118 /*************************/ 119 120 /** PPP_INPROC_MULTITHREADED==1 call pppInput using tcpip_callback(). 121 * Set this to 0 if pppInProc is called inside tcpip_thread or with NO_SYS==1. 122 * Default is 1 for NO_SYS==0 (multithreaded) and 0 for NO_SYS==1 (single-threaded). 123 */ 124 #ifndef PPP_INPROC_MULTITHREADED 125 #define PPP_INPROC_MULTITHREADED (NO_SYS==0) 126 #endif 127 128 /** PPP_INPROC_OWNTHREAD==1: start a dedicated RX thread per PPP session. 129 * Default is 0: call pppos_input() for received raw characters, charcater 130 * reception is up to the port */ 131 #ifndef PPP_INPROC_OWNTHREAD 132 #define PPP_INPROC_OWNTHREAD PPP_INPROC_MULTITHREADED 133 #endif 134 135 #if PPP_INPROC_OWNTHREAD && !PPP_INPROC_MULTITHREADED 136 #error "PPP_INPROC_OWNTHREAD needs PPP_INPROC_MULTITHREADED==1" 137 #endif 138 139 /* 140 * The basic PPP frame. 141 */ 142 #define PPP_ADDRESS(p) (((u_char *)(p))[0]) 143 #define PPP_CONTROL(p) (((u_char *)(p))[1]) 144 #define PPP_PROTOCOL(p) ((((u_char *)(p))[2] << 8) + ((u_char *)(p))[3]) 145 146 /* PPP packet parser states. Current state indicates operation yet to be 147 * completed. */ 148 typedef enum { 149 PDIDLE = 0, /* Idle state - waiting. */ 150 PDSTART, /* Process start flag. */ 151 PDADDRESS, /* Process address field. */ 152 PDCONTROL, /* Process control field. */ 153 PDPROTOCOL1, /* Process protocol field 1. */ 154 PDPROTOCOL2, /* Process protocol field 2. */ 155 PDDATA /* Process data byte. */ 156 } PPPDevStates; 157 158 #define ESCAPE_P(accm, c) ((accm)[(c) >> 3] & pppACCMMask[c & 0x07]) 159 160 /************************/ 161 /*** LOCAL DATA TYPES ***/ 162 /************************/ 163 164 /** RX buffer size: this may be configured smaller! */ 165 #ifndef PPPOS_RX_BUFSIZE 166 #define PPPOS_RX_BUFSIZE (PPP_MRU + PPP_HDRLEN) 167 #endif 168 169 typedef struct PPPControlRx_s { 170 /** unit number / ppp descriptor */ 171 int pd; 172 /** the rx file descriptor */ 173 sio_fd_t fd; 174 /** receive buffer - encoded data is stored here */ 175 u_char rxbuf[PPPOS_RX_BUFSIZE]; 176 177 /* The input packet. */ 178 struct pbuf *inHead, *inTail; 179 180 #if PPPOS_SUPPORT 181 u16_t inProtocol; /* The input protocol code. */ 182 u16_t inFCS; /* Input Frame Check Sequence value. */ 183 #endif /* PPPOS_SUPPORT */ 184 PPPDevStates inState; /* The input process state. */ 185 char inEscaped; /* Escape next character. */ 186 ext_accm inACCM; /* Async-Ctl-Char-Map for input. */ 187 } PPPControlRx; 188 189 /* 190 * PPP interface control block. 191 */ 192 typedef struct PPPControl_s { 193 PPPControlRx rx; 194 char openFlag; /* True when in use. */ 195 #if PPPOE_SUPPORT 196 struct netif *ethif; 197 struct pppoe_softc *pppoe_sc; 198 #endif /* PPPOE_SUPPORT */ 199 int if_up; /* True when the interface is up. */ 200 int errCode; /* Code indicating why interface is down. */ 201 #if PPPOS_SUPPORT 202 sio_fd_t fd; /* File device ID of port. */ 203 #endif /* PPPOS_SUPPORT */ 204 u16_t mtu; /* Peer's mru */ 205 int pcomp; /* Does peer accept protocol compression? */ 206 int accomp; /* Does peer accept addr/ctl compression? */ 207 u_long lastXMit; /* Time of last transmission. */ 208 ext_accm outACCM; /* Async-Ctl-Char-Map for output. */ 209 #if PPPOS_SUPPORT && VJ_SUPPORT 210 int vjEnabled; /* Flag indicating VJ compression enabled. */ 211 struct vjcompress vjComp; /* Van Jacobson compression header. */ 212 #endif /* PPPOS_SUPPORT && VJ_SUPPORT */ 213 214 struct netif netif; 215 216 struct ppp_addrs addrs; 217 218 void (*linkStatusCB)(void *ctx, int errCode, void *arg); 219 void *linkStatusCtx; 220 221 } PPPControl; 222 223 224 /* 225 * Ioctl definitions. 226 */ 227 228 struct npioctl { 229 int protocol; /* PPP procotol, e.g. PPP_IP */ 230 enum NPmode mode; 231 }; 232 233 234 235 /***********************************/ 236 /*** LOCAL FUNCTION DECLARATIONS ***/ 237 /***********************************/ 238 #if PPPOS_SUPPORT 239 #if PPP_INPROC_OWNTHREAD 240 static void pppInputThread(void *arg); 241 #endif /* PPP_INPROC_OWNTHREAD */ 242 static void pppDrop(PPPControlRx *pcrx); 243 static void pppInProc(PPPControlRx *pcrx, u_char *s, int l); 244 #endif /* PPPOS_SUPPORT */ 245 246 247 /******************************/ 248 /*** PUBLIC DATA STRUCTURES ***/ 249 /******************************/ 250 u_long subnetMask; 251 252 static PPPControl pppControl[NUM_PPP]; /* The PPP interface control blocks. */ 253 254 /* 255 * PPP Data Link Layer "protocol" table. 256 * One entry per supported protocol. 257 * The last entry must be NULL. 258 */ 259 struct protent *ppp_protocols[] = { 260 &lcp_protent, 261 #if PAP_SUPPORT 262 &pap_protent, 263 #endif /* PAP_SUPPORT */ 264 #if CHAP_SUPPORT 265 &chap_protent, 266 #endif /* CHAP_SUPPORT */ 267 #if CBCP_SUPPORT 268 &cbcp_protent, 269 #endif /* CBCP_SUPPORT */ 270 &ipcp_protent, 271 #if CCP_SUPPORT 272 &ccp_protent, 273 #endif /* CCP_SUPPORT */ 274 NULL 275 }; 276 277 278 /* 279 * Buffers for outgoing packets. This must be accessed only from the appropriate 280 * PPP task so that it doesn't need to be protected to avoid collisions. 281 */ 282 u_char outpacket_buf[NUM_PPP][PPP_MRU+PPP_HDRLEN]; 283 284 285 /*****************************/ 286 /*** LOCAL DATA STRUCTURES ***/ 287 /*****************************/ 288 289 #if PPPOS_SUPPORT 290 /* 291 * FCS lookup table as calculated by genfcstab. 292 * @todo: smaller, slower implementation for lower memory footprint? 293 */ 294 static const u_short fcstab[256] = { 295 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 296 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, 297 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, 298 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, 299 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, 300 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, 301 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, 302 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, 303 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, 304 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, 305 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, 306 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, 307 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, 308 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, 309 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, 310 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, 311 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, 312 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, 313 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, 314 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, 315 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, 316 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, 317 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, 318 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, 319 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, 320 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, 321 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, 322 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, 323 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, 324 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, 325 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 326 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 327 }; 328 329 /* PPP's Asynchronous-Control-Character-Map. The mask array is used 330 * to select the specific bit for a character. */ 331 static u_char pppACCMMask[] = { 332 0x01, 333 0x02, 334 0x04, 335 0x08, 336 0x10, 337 0x20, 338 0x40, 339 0x80 340 }; 341 342 /** Wake up the task blocked in reading from serial line (if any) */ 343 static void 344 pppRecvWakeup(int pd) 345 { 346 PPPDEBUG(LOG_DEBUG, ("pppRecvWakeup: unit %d\n", pd)); 347 if (pppControl[pd].openFlag != 0) { 348 sio_read_abort(pppControl[pd].fd); 349 } 350 } 351 #endif /* PPPOS_SUPPORT */ 352 353 void 354 pppLinkTerminated(int pd) 355 { 356 PPPDEBUG(LOG_DEBUG, ("pppLinkTerminated: unit %d\n", pd)); 357 358 #if PPPOE_SUPPORT 359 if (pppControl[pd].ethif) { 360 pppoe_disconnect(pppControl[pd].pppoe_sc); 361 } else 362 #endif /* PPPOE_SUPPORT */ 363 { 364 #if PPPOS_SUPPORT 365 PPPControl* pc; 366 pppRecvWakeup(pd); 367 pc = &pppControl[pd]; 368 369 PPPDEBUG(LOG_DEBUG, ("pppLinkTerminated: unit %d: linkStatusCB=%p errCode=%d\n", pd, pc->linkStatusCB, pc->errCode)); 370 if (pc->linkStatusCB) { 371 pc->linkStatusCB(pc->linkStatusCtx, pc->errCode ? pc->errCode : PPPERR_PROTOCOL, NULL); 372 } 373 374 pc->openFlag = 0;/**/ 375 #endif /* PPPOS_SUPPORT */ 376 } 377 PPPDEBUG(LOG_DEBUG, ("pppLinkTerminated: finished.\n")); 378 } 379 380 void 381 pppLinkDown(int pd) 382 { 383 PPPDEBUG(LOG_DEBUG, ("pppLinkDown: unit %d\n", pd)); 384 385 #if PPPOE_SUPPORT 386 if (pppControl[pd].ethif) { 387 pppoe_disconnect(pppControl[pd].pppoe_sc); 388 } else 389 #endif /* PPPOE_SUPPORT */ 390 { 391 #if PPPOS_SUPPORT 392 pppRecvWakeup(pd); 393 #endif /* PPPOS_SUPPORT */ 394 } 395 } 396 397 /** Initiate LCP open request */ 398 static void 399 pppStart(int pd) 400 { 401 PPPDEBUG(LOG_DEBUG, ("pppStart: unit %d\n", pd)); 402 lcp_lowerup(pd); 403 lcp_open(pd); /* Start protocol */ 404 PPPDEBUG(LOG_DEBUG, ("pppStart: finished\n")); 405 } 406 407 /** LCP close request */ 408 static void 409 pppStop(int pd) 410 { 411 PPPDEBUG(LOG_DEBUG, ("pppStop: unit %d\n", pd)); 412 lcp_close(pd, "User request"); 413 } 414 415 /** Called when carrier/link is lost */ 416 static void 417 pppHup(int pd) 418 { 419 PPPDEBUG(LOG_DEBUG, ("pppHupCB: unit %d\n", pd)); 420 lcp_lowerdown(pd); 421 link_terminated(pd); 422 } 423 424 /***********************************/ 425 /*** PUBLIC FUNCTION DEFINITIONS ***/ 426 /***********************************/ 427 /* Initialize the PPP subsystem. */ 428 429 struct ppp_settings ppp_settings; 430 431 void 432 pppInit(void) 433 { 434 struct protent *protp; 435 int i, j; 436 437 memset(&ppp_settings, 0, sizeof(ppp_settings)); 438 ppp_settings.usepeerdns = 1; 439 pppSetAuth(PPPAUTHTYPE_NONE, NULL, NULL); 440 441 magicInit(); 442 443 subnetMask = PP_HTONL(0xffffff00UL); 444 445 for (i = 0; i < NUM_PPP; i++) { 446 /* Initialize each protocol to the standard option set. */ 447 for (j = 0; (protp = ppp_protocols[j]) != NULL; ++j) { 448 (*protp->init)(i); 449 } 450 } 451 } 452 453 void 454 pppSetAuth(enum pppAuthType authType, const char *user, const char *passwd) 455 { 456 switch(authType) { 457 case PPPAUTHTYPE_NONE: 458 default: 459 #ifdef LWIP_PPP_STRICT_PAP_REJECT 460 ppp_settings.refuse_pap = 1; 461 #else /* LWIP_PPP_STRICT_PAP_REJECT */ 462 /* some providers request pap and accept an empty login/pw */ 463 ppp_settings.refuse_pap = 0; 464 #endif /* LWIP_PPP_STRICT_PAP_REJECT */ 465 ppp_settings.refuse_chap = 1; 466 break; 467 468 case PPPAUTHTYPE_ANY: 469 /* Warning: Using PPPAUTHTYPE_ANY might have security consequences. 470 * RFC 1994 says: 471 * 472 * In practice, within or associated with each PPP server, there is a 473 * database which associates "user" names with authentication 474 * information ("secrets"). It is not anticipated that a particular 475 * named user would be authenticated by multiple methods. This would 476 * make the user vulnerable to attacks which negotiate the least secure 477 * method from among a set (such as PAP rather than CHAP). If the same 478 * secret was used, PAP would reveal the secret to be used later with 479 * CHAP. 480 * 481 * Instead, for each user name there should be an indication of exactly 482 * one method used to authenticate that user name. If a user needs to 483 * make use of different authentication methods under different 484 * circumstances, then distinct user names SHOULD be employed, each of 485 * which identifies exactly one authentication method. 486 * 487 */ 488 ppp_settings.refuse_pap = 0; 489 ppp_settings.refuse_chap = 0; 490 break; 491 492 case PPPAUTHTYPE_PAP: 493 ppp_settings.refuse_pap = 0; 494 ppp_settings.refuse_chap = 1; 495 break; 496 497 case PPPAUTHTYPE_CHAP: 498 ppp_settings.refuse_pap = 1; 499 ppp_settings.refuse_chap = 0; 500 break; 501 } 502 503 if(user) { 504 strncpy(ppp_settings.user, user, sizeof(ppp_settings.user)-1); 505 ppp_settings.user[sizeof(ppp_settings.user)-1] = '\0'; 506 } else { 507 ppp_settings.user[0] = '\0'; 508 } 509 510 if(passwd) { 511 strncpy(ppp_settings.passwd, passwd, sizeof(ppp_settings.passwd)-1); 512 ppp_settings.passwd[sizeof(ppp_settings.passwd)-1] = '\0'; 513 } else { 514 ppp_settings.passwd[0] = '\0'; 515 } 516 } 517 518 #if PPPOS_SUPPORT 519 /** Open a new PPP connection using the given I/O device. 520 * This initializes the PPP control block but does not 521 * attempt to negotiate the LCP session. If this port 522 * connects to a modem, the modem connection must be 523 * established before calling this. 524 * Return a new PPP connection descriptor on success or 525 * an error code (negative) on failure. 526 * 527 * pppOpen() is directly defined to this function. 528 */ 529 int 530 pppOverSerialOpen(sio_fd_t fd, void (*linkStatusCB)(void *ctx, int errCode, void *arg), void *linkStatusCtx) 531 { 532 PPPControl *pc; 533 int pd; 534 535 if (linkStatusCB == NULL) { 536 /* PPP is single-threaded: without a callback, 537 * there is no way to know when the link is up. */ 538 return PPPERR_PARAM; 539 } 540 541 /* Find a free PPP session descriptor. */ 542 for (pd = 0; pd < NUM_PPP && pppControl[pd].openFlag != 0; pd++); 543 544 if (pd >= NUM_PPP) { 545 pd = PPPERR_OPEN; 546 } else { 547 pc = &pppControl[pd]; 548 /* @todo: is this correct or do I overwrite something? */ 549 memset(pc, 0, sizeof(PPPControl)); 550 pc->rx.pd = pd; 551 pc->rx.fd = fd; 552 553 pc->openFlag = 1; 554 pc->fd = fd; 555 556 #if VJ_SUPPORT 557 vj_compress_init(&pc->vjComp); 558 #endif /* VJ_SUPPORT */ 559 560 /* 561 * Default the in and out accm so that escape and flag characters 562 * are always escaped. 563 */ 564 pc->rx.inACCM[15] = 0x60; /* no need to protect since RX is not running */ 565 pc->outACCM[15] = 0x60; 566 567 pc->linkStatusCB = linkStatusCB; 568 pc->linkStatusCtx = linkStatusCtx; 569 570 /* 571 * Start the connection and handle incoming events (packet or timeout). 572 */ 573 PPPDEBUG(LOG_INFO, ("pppOverSerialOpen: unit %d: Connecting\n", pd)); 574 pppStart(pd); 575 #if PPP_INPROC_OWNTHREAD 576 sys_thread_new(PPP_THREAD_NAME, pppInputThread, (void*)&pc->rx, PPP_THREAD_STACKSIZE, PPP_THREAD_PRIO); 577 #endif 578 } 579 580 return pd; 581 } 582 #endif /* PPPOS_SUPPORT */ 583 584 #if PPPOE_SUPPORT 585 static void pppOverEthernetLinkStatusCB(int pd, int up); 586 587 void 588 pppOverEthernetClose(int pd) 589 { 590 PPPControl* pc = &pppControl[pd]; 591 592 /* *TJL* There's no lcp_deinit */ 593 lcp_close(pd, NULL); 594 595 pppoe_destroy(&pc->netif); 596 } 597 598 int pppOverEthernetOpen(struct netif *ethif, const char *service_name, const char *concentrator_name, void (*linkStatusCB)(void *ctx, int errCode, void *arg), void *linkStatusCtx) 599 { 600 PPPControl *pc; 601 int pd; 602 603 LWIP_UNUSED_ARG(service_name); 604 LWIP_UNUSED_ARG(concentrator_name); 605 606 if (linkStatusCB == NULL) { 607 /* PPP is single-threaded: without a callback, 608 * there is no way to know when the link is up. */ 609 return PPPERR_PARAM; 610 } 611 612 /* Find a free PPP session descriptor. Critical region? */ 613 for (pd = 0; pd < NUM_PPP && pppControl[pd].openFlag != 0; pd++); 614 if (pd >= NUM_PPP) { 615 pd = PPPERR_OPEN; 616 } else { 617 pc = &pppControl[pd]; 618 memset(pc, 0, sizeof(PPPControl)); 619 pc->openFlag = 1; 620 pc->ethif = ethif; 621 622 pc->linkStatusCB = linkStatusCB; 623 pc->linkStatusCtx = linkStatusCtx; 624 625 lcp_wantoptions[pd].mru = PPPOE_MAXMTU; 626 lcp_wantoptions[pd].neg_asyncmap = 0; 627 lcp_wantoptions[pd].neg_pcompression = 0; 628 lcp_wantoptions[pd].neg_accompression = 0; 629 630 lcp_allowoptions[pd].mru = PPPOE_MAXMTU; 631 lcp_allowoptions[pd].neg_asyncmap = 0; 632 lcp_allowoptions[pd].neg_pcompression = 0; 633 lcp_allowoptions[pd].neg_accompression = 0; 634 635 if(pppoe_create(ethif, pd, pppOverEthernetLinkStatusCB, &pc->pppoe_sc) != ERR_OK) { 636 pc->openFlag = 0; 637 return PPPERR_OPEN; 638 } 639 640 pppoe_connect(pc->pppoe_sc); 641 } 642 643 return pd; 644 } 645 #endif /* PPPOE_SUPPORT */ 646 647 648 /* Close a PPP connection and release the descriptor. 649 * Any outstanding packets in the queues are dropped. 650 * Return 0 on success, an error code on failure. */ 651 int 652 pppClose(int pd) 653 { 654 PPPControl *pc = &pppControl[pd]; 655 int st = 0; 656 657 PPPDEBUG(LOG_DEBUG, ("pppClose() called\n")); 658 659 /* Disconnect */ 660 #if PPPOE_SUPPORT 661 if(pc->ethif) { 662 PPPDEBUG(LOG_DEBUG, ("pppClose: unit %d kill_link -> pppStop\n", pd)); 663 pc->errCode = PPPERR_USER; 664 /* This will leave us at PHASE_DEAD. */ 665 pppStop(pd); 666 } else 667 #endif /* PPPOE_SUPPORT */ 668 { 669 #if PPPOS_SUPPORT 670 PPPDEBUG(LOG_DEBUG, ("pppClose: unit %d kill_link -> pppStop\n", pd)); 671 pc->errCode = PPPERR_USER; 672 /* This will leave us at PHASE_DEAD. */ 673 pppStop(pd); 674 pppRecvWakeup(pd); 675 #endif /* PPPOS_SUPPORT */ 676 } 677 678 return st; 679 } 680 681 /* This function is called when carrier is lost on the PPP channel. */ 682 void 683 pppSigHUP(int pd) 684 { 685 PPPDEBUG(LOG_DEBUG, ("pppSigHUP: unit %d sig_hup -> pppHupCB\n", pd)); 686 pppHup(pd); 687 } 688 689 #if PPPOS_SUPPORT 690 static void 691 nPut(PPPControl *pc, struct pbuf *nb) 692 { 693 struct pbuf *b; 694 int c; 695 696 for(b = nb; b != NULL; b = b->next) { 697 if((c = sio_write(pc->fd, b->payload, b->len)) != b->len) { 698 PPPDEBUG(LOG_WARNING, 699 ("PPP nPut: incomplete sio_write(fd:%"SZT_F", len:%d, c: 0x%"X8_F") c = %d\n", (size_t)pc->fd, b->len, c, c)); 700 LINK_STATS_INC(link.err); 701 pc->lastXMit = 0; /* prepend PPP_FLAG to next packet */ 702 snmp_inc_ifoutdiscards(&pc->netif); 703 pbuf_free(nb); 704 return; 705 } 706 } 707 708 snmp_add_ifoutoctets(&pc->netif, nb->tot_len); 709 snmp_inc_ifoutucastpkts(&pc->netif); 710 pbuf_free(nb); 711 LINK_STATS_INC(link.xmit); 712 } 713 714 /* 715 * pppAppend - append given character to end of given pbuf. If outACCM 716 * is not NULL and the character needs to be escaped, do so. 717 * If pbuf is full, append another. 718 * Return the current pbuf. 719 */ 720 static struct pbuf * 721 pppAppend(u_char c, struct pbuf *nb, ext_accm *outACCM) 722 { 723 struct pbuf *tb = nb; 724 725 /* Make sure there is room for the character and an escape code. 726 * Sure we don't quite fill the buffer if the character doesn't 727 * get escaped but is one character worth complicating this? */ 728 /* Note: We assume no packet header. */ 729 if (nb && (PBUF_POOL_BUFSIZE - nb->len) < 2) { 730 tb = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); 731 if (tb) { 732 nb->next = tb; 733 } else { 734 LINK_STATS_INC(link.memerr); 735 } 736 nb = tb; 737 } 738 739 if (nb) { 740 if (outACCM && ESCAPE_P(*outACCM, c)) { 741 *((u_char*)nb->payload + nb->len++) = PPP_ESCAPE; 742 *((u_char*)nb->payload + nb->len++) = c ^ PPP_TRANS; 743 } else { 744 *((u_char*)nb->payload + nb->len++) = c; 745 } 746 } 747 748 return tb; 749 } 750 #endif /* PPPOS_SUPPORT */ 751 752 #if PPPOE_SUPPORT 753 static err_t 754 pppifOutputOverEthernet(int pd, struct pbuf *p) 755 { 756 PPPControl *pc = &pppControl[pd]; 757 struct pbuf *pb; 758 u_short protocol = PPP_IP; 759 int i=0; 760 u16_t tot_len; 761 762 /* @todo: try to use pbuf_header() here! */ 763 pb = pbuf_alloc(PBUF_LINK, PPPOE_HDRLEN + sizeof(protocol), PBUF_RAM); 764 if(!pb) { 765 LINK_STATS_INC(link.memerr); 766 LINK_STATS_INC(link.proterr); 767 snmp_inc_ifoutdiscards(&pc->netif); 768 return ERR_MEM; 769 } 770 771 pbuf_header(pb, -(s16_t)PPPOE_HDRLEN); 772 773 pc->lastXMit = sys_jiffies(); 774 775 if (!pc->pcomp || protocol > 0xFF) { 776 *((u_char*)pb->payload + i++) = (protocol >> 8) & 0xFF; 777 } 778 *((u_char*)pb->payload + i) = protocol & 0xFF; 779 780 pbuf_chain(pb, p); 781 tot_len = pb->tot_len; 782 783 if(pppoe_xmit(pc->pppoe_sc, pb) != ERR_OK) { 784 LINK_STATS_INC(link.err); 785 snmp_inc_ifoutdiscards(&pc->netif); 786 return PPPERR_DEVICE; 787 } 788 789 snmp_add_ifoutoctets(&pc->netif, tot_len); 790 snmp_inc_ifoutucastpkts(&pc->netif); 791 LINK_STATS_INC(link.xmit); 792 return ERR_OK; 793 } 794 #endif /* PPPOE_SUPPORT */ 795 796 /* Send a packet on the given connection. */ 797 static err_t 798 pppifOutput(struct netif *netif, struct pbuf *pb, ip_addr_t *ipaddr) 799 { 800 int pd = (int)(size_t)netif->state; 801 PPPControl *pc = &pppControl[pd]; 802 #if PPPOS_SUPPORT 803 u_short protocol = PPP_IP; 804 u_int fcsOut = PPP_INITFCS; 805 struct pbuf *headMB = NULL, *tailMB = NULL, *p; 806 u_char c; 807 #endif /* PPPOS_SUPPORT */ 808 809 LWIP_UNUSED_ARG(ipaddr); 810 811 /* Validate parameters. */ 812 /* We let any protocol value go through - it can't hurt us 813 * and the peer will just drop it if it's not accepting it. */ 814 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag || !pb) { 815 PPPDEBUG(LOG_WARNING, ("pppifOutput[%d]: bad parms prot=%d pb=%p\n", 816 pd, PPP_IP, pb)); 817 LINK_STATS_INC(link.opterr); 818 LINK_STATS_INC(link.drop); 819 snmp_inc_ifoutdiscards(netif); 820 return ERR_ARG; 821 } 822 823 /* Check that the link is up. */ 824 if (lcp_phase[pd] == PHASE_DEAD) { 825 PPPDEBUG(LOG_ERR, ("pppifOutput[%d]: link not up\n", pd)); 826 LINK_STATS_INC(link.rterr); 827 LINK_STATS_INC(link.drop); 828 snmp_inc_ifoutdiscards(netif); 829 return ERR_RTE; 830 } 831 832 #if PPPOE_SUPPORT 833 if(pc->ethif) { 834 return pppifOutputOverEthernet(pd, pb); 835 } 836 #endif /* PPPOE_SUPPORT */ 837 838 #if PPPOS_SUPPORT 839 /* Grab an output buffer. */ 840 headMB = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); 841 if (headMB == NULL) { 842 PPPDEBUG(LOG_WARNING, ("pppifOutput[%d]: first alloc fail\n", pd)); 843 LINK_STATS_INC(link.memerr); 844 LINK_STATS_INC(link.drop); 845 snmp_inc_ifoutdiscards(netif); 846 return ERR_MEM; 847 } 848 849 #if VJ_SUPPORT 850 /* 851 * Attempt Van Jacobson header compression if VJ is configured and 852 * this is an IP packet. 853 */ 854 if (protocol == PPP_IP && pc->vjEnabled) { 855 switch (vj_compress_tcp(&pc->vjComp, pb)) { 856 case TYPE_IP: 857 /* No change... 858 protocol = PPP_IP_PROTOCOL; */ 859 break; 860 case TYPE_COMPRESSED_TCP: 861 protocol = PPP_VJC_COMP; 862 break; 863 case TYPE_UNCOMPRESSED_TCP: 864 protocol = PPP_VJC_UNCOMP; 865 break; 866 default: 867 PPPDEBUG(LOG_WARNING, ("pppifOutput[%d]: bad IP packet\n", pd)); 868 LINK_STATS_INC(link.proterr); 869 LINK_STATS_INC(link.drop); 870 snmp_inc_ifoutdiscards(netif); 871 pbuf_free(headMB); 872 return ERR_VAL; 873 } 874 } 875 #endif /* VJ_SUPPORT */ 876 877 tailMB = headMB; 878 879 /* Build the PPP header. */ 880 if ((sys_jiffies() - pc->lastXMit) >= PPP_MAXIDLEFLAG) { 881 tailMB = pppAppend(PPP_FLAG, tailMB, NULL); 882 } 883 884 pc->lastXMit = sys_jiffies(); 885 if (!pc->accomp) { 886 fcsOut = PPP_FCS(fcsOut, PPP_ALLSTATIONS); 887 tailMB = pppAppend(PPP_ALLSTATIONS, tailMB, &pc->outACCM); 888 fcsOut = PPP_FCS(fcsOut, PPP_UI); 889 tailMB = pppAppend(PPP_UI, tailMB, &pc->outACCM); 890 } 891 if (!pc->pcomp || protocol > 0xFF) { 892 c = (protocol >> 8) & 0xFF; 893 fcsOut = PPP_FCS(fcsOut, c); 894 tailMB = pppAppend(c, tailMB, &pc->outACCM); 895 } 896 c = protocol & 0xFF; 897 fcsOut = PPP_FCS(fcsOut, c); 898 tailMB = pppAppend(c, tailMB, &pc->outACCM); 899 900 /* Load packet. */ 901 for(p = pb; p; p = p->next) { 902 int n; 903 u_char *sPtr; 904 905 sPtr = (u_char*)p->payload; 906 n = p->len; 907 while (n-- > 0) { 908 c = *sPtr++; 909 910 /* Update FCS before checking for special characters. */ 911 fcsOut = PPP_FCS(fcsOut, c); 912 913 /* Copy to output buffer escaping special characters. */ 914 tailMB = pppAppend(c, tailMB, &pc->outACCM); 915 } 916 } 917 918 /* Add FCS and trailing flag. */ 919 c = ~fcsOut & 0xFF; 920 tailMB = pppAppend(c, tailMB, &pc->outACCM); 921 c = (~fcsOut >> 8) & 0xFF; 922 tailMB = pppAppend(c, tailMB, &pc->outACCM); 923 tailMB = pppAppend(PPP_FLAG, tailMB, NULL); 924 925 /* If we failed to complete the packet, throw it away. */ 926 if (!tailMB) { 927 PPPDEBUG(LOG_WARNING, 928 ("pppifOutput[%d]: Alloc err - dropping proto=%d\n", 929 pd, protocol)); 930 pbuf_free(headMB); 931 LINK_STATS_INC(link.memerr); 932 LINK_STATS_INC(link.drop); 933 snmp_inc_ifoutdiscards(netif); 934 return ERR_MEM; 935 } 936 937 /* Send it. */ 938 PPPDEBUG(LOG_INFO, ("pppifOutput[%d]: proto=0x%"X16_F"\n", pd, protocol)); 939 940 nPut(pc, headMB); 941 #endif /* PPPOS_SUPPORT */ 942 943 return ERR_OK; 944 } 945 946 /* Get and set parameters for the given connection. 947 * Return 0 on success, an error code on failure. */ 948 int 949 pppIOCtl(int pd, int cmd, void *arg) 950 { 951 PPPControl *pc = &pppControl[pd]; 952 int st = 0; 953 954 if (pd < 0 || pd >= NUM_PPP) { 955 st = PPPERR_PARAM; 956 } else { 957 switch(cmd) { 958 case PPPCTLG_UPSTATUS: /* Get the PPP up status. */ 959 if (arg) { 960 *(int *)arg = (int)(pc->if_up); 961 } else { 962 st = PPPERR_PARAM; 963 } 964 break; 965 case PPPCTLS_ERRCODE: /* Set the PPP error code. */ 966 if (arg) { 967 pc->errCode = *(int *)arg; 968 } else { 969 st = PPPERR_PARAM; 970 } 971 break; 972 case PPPCTLG_ERRCODE: /* Get the PPP error code. */ 973 if (arg) { 974 *(int *)arg = (int)(pc->errCode); 975 } else { 976 st = PPPERR_PARAM; 977 } 978 break; 979 #if PPPOS_SUPPORT 980 case PPPCTLG_FD: /* Get the fd associated with the ppp */ 981 if (arg) { 982 *(sio_fd_t *)arg = pc->fd; 983 } else { 984 st = PPPERR_PARAM; 985 } 986 break; 987 #endif /* PPPOS_SUPPORT */ 988 default: 989 st = PPPERR_PARAM; 990 break; 991 } 992 } 993 994 return st; 995 } 996 997 /* 998 * Return the Maximum Transmission Unit for the given PPP connection. 999 */ 1000 u_short 1001 pppMTU(int pd) 1002 { 1003 PPPControl *pc = &pppControl[pd]; 1004 u_short st; 1005 1006 /* Validate parameters. */ 1007 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { 1008 st = 0; 1009 } else { 1010 st = pc->mtu; 1011 } 1012 1013 return st; 1014 } 1015 1016 #if PPPOE_SUPPORT 1017 int 1018 pppWriteOverEthernet(int pd, const u_char *s, int n) 1019 { 1020 PPPControl *pc = &pppControl[pd]; 1021 struct pbuf *pb; 1022 1023 /* skip address & flags */ 1024 s += 2; 1025 n -= 2; 1026 1027 LWIP_ASSERT("PPPOE_HDRLEN + n <= 0xffff", PPPOE_HDRLEN + n <= 0xffff); 1028 pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HDRLEN + n), PBUF_RAM); 1029 if(!pb) { 1030 LINK_STATS_INC(link.memerr); 1031 LINK_STATS_INC(link.proterr); 1032 snmp_inc_ifoutdiscards(&pc->netif); 1033 return PPPERR_ALLOC; 1034 } 1035 1036 pbuf_header(pb, -(s16_t)PPPOE_HDRLEN); 1037 1038 pc->lastXMit = sys_jiffies(); 1039 1040 MEMCPY(pb->payload, s, n); 1041 1042 if(pppoe_xmit(pc->pppoe_sc, pb) != ERR_OK) { 1043 LINK_STATS_INC(link.err); 1044 snmp_inc_ifoutdiscards(&pc->netif); 1045 return PPPERR_DEVICE; 1046 } 1047 1048 snmp_add_ifoutoctets(&pc->netif, (u16_t)n); 1049 snmp_inc_ifoutucastpkts(&pc->netif); 1050 LINK_STATS_INC(link.xmit); 1051 return PPPERR_NONE; 1052 } 1053 #endif /* PPPOE_SUPPORT */ 1054 1055 /* 1056 * Write n characters to a ppp link. 1057 * RETURN: >= 0 Number of characters written 1058 * -1 Failed to write to device 1059 */ 1060 int 1061 pppWrite(int pd, const u_char *s, int n) 1062 { 1063 PPPControl *pc = &pppControl[pd]; 1064 #if PPPOS_SUPPORT 1065 u_char c; 1066 u_int fcsOut; 1067 struct pbuf *headMB, *tailMB; 1068 #endif /* PPPOS_SUPPORT */ 1069 1070 #if PPPOE_SUPPORT 1071 if(pc->ethif) { 1072 return pppWriteOverEthernet(pd, s, n); 1073 } 1074 #endif /* PPPOE_SUPPORT */ 1075 1076 #if PPPOS_SUPPORT 1077 headMB = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); 1078 if (headMB == NULL) { 1079 LINK_STATS_INC(link.memerr); 1080 LINK_STATS_INC(link.proterr); 1081 snmp_inc_ifoutdiscards(&pc->netif); 1082 return PPPERR_ALLOC; 1083 } 1084 1085 tailMB = headMB; 1086 1087 /* If the link has been idle, we'll send a fresh flag character to 1088 * flush any noise. */ 1089 if ((sys_jiffies() - pc->lastXMit) >= PPP_MAXIDLEFLAG) { 1090 tailMB = pppAppend(PPP_FLAG, tailMB, NULL); 1091 } 1092 pc->lastXMit = sys_jiffies(); 1093 1094 fcsOut = PPP_INITFCS; 1095 /* Load output buffer. */ 1096 while (n-- > 0) { 1097 c = *s++; 1098 1099 /* Update FCS before checking for special characters. */ 1100 fcsOut = PPP_FCS(fcsOut, c); 1101 1102 /* Copy to output buffer escaping special characters. */ 1103 tailMB = pppAppend(c, tailMB, &pc->outACCM); 1104 } 1105 1106 /* Add FCS and trailing flag. */ 1107 c = ~fcsOut & 0xFF; 1108 tailMB = pppAppend(c, tailMB, &pc->outACCM); 1109 c = (~fcsOut >> 8) & 0xFF; 1110 tailMB = pppAppend(c, tailMB, &pc->outACCM); 1111 tailMB = pppAppend(PPP_FLAG, tailMB, NULL); 1112 1113 /* If we failed to complete the packet, throw it away. 1114 * Otherwise send it. */ 1115 if (!tailMB) { 1116 PPPDEBUG(LOG_WARNING, 1117 ("pppWrite[%d]: Alloc err - dropping pbuf len=%d\n", pd, headMB->len)); 1118 /*"pppWrite[%d]: Alloc err - dropping %d:%.*H", pd, headMB->len, LWIP_MIN(headMB->len * 2, 40), headMB->payload)); */ 1119 pbuf_free(headMB); 1120 LINK_STATS_INC(link.memerr); 1121 LINK_STATS_INC(link.proterr); 1122 snmp_inc_ifoutdiscards(&pc->netif); 1123 return PPPERR_ALLOC; 1124 } 1125 1126 PPPDEBUG(LOG_INFO, ("pppWrite[%d]: len=%d\n", pd, headMB->len)); 1127 /* "pppWrite[%d]: %d:%.*H", pd, headMB->len, LWIP_MIN(headMB->len * 2, 40), headMB->payload)); */ 1128 nPut(pc, headMB); 1129 #endif /* PPPOS_SUPPORT */ 1130 1131 return PPPERR_NONE; 1132 } 1133 1134 /* 1135 * ppp_send_config - configure the transmit characteristics of 1136 * the ppp interface. 1137 */ 1138 void 1139 ppp_send_config( int unit, u16_t mtu, u32_t asyncmap, int pcomp, int accomp) 1140 { 1141 PPPControl *pc = &pppControl[unit]; 1142 int i; 1143 1144 pc->mtu = mtu; 1145 pc->pcomp = pcomp; 1146 pc->accomp = accomp; 1147 1148 /* Load the ACCM bits for the 32 control codes. */ 1149 for (i = 0; i < 32/8; i++) { 1150 pc->outACCM[i] = (u_char)((asyncmap >> (8 * i)) & 0xFF); 1151 } 1152 PPPDEBUG(LOG_INFO, ("ppp_send_config[%d]: outACCM=%X %X %X %X\n", 1153 unit, 1154 pc->outACCM[0], pc->outACCM[1], pc->outACCM[2], pc->outACCM[3])); 1155 } 1156 1157 1158 /* 1159 * ppp_set_xaccm - set the extended transmit ACCM for the interface. 1160 */ 1161 void 1162 ppp_set_xaccm(int unit, ext_accm *accm) 1163 { 1164 SMEMCPY(pppControl[unit].outACCM, accm, sizeof(ext_accm)); 1165 PPPDEBUG(LOG_INFO, ("ppp_set_xaccm[%d]: outACCM=%X %X %X %X\n", 1166 unit, 1167 pppControl[unit].outACCM[0], 1168 pppControl[unit].outACCM[1], 1169 pppControl[unit].outACCM[2], 1170 pppControl[unit].outACCM[3])); 1171 } 1172 1173 1174 /* 1175 * ppp_recv_config - configure the receive-side characteristics of 1176 * the ppp interface. 1177 */ 1178 void 1179 ppp_recv_config( int unit, int mru, u32_t asyncmap, int pcomp, int accomp) 1180 { 1181 PPPControl *pc = &pppControl[unit]; 1182 int i; 1183 SYS_ARCH_DECL_PROTECT(lev); 1184 1185 LWIP_UNUSED_ARG(accomp); 1186 LWIP_UNUSED_ARG(pcomp); 1187 LWIP_UNUSED_ARG(mru); 1188 1189 /* Load the ACCM bits for the 32 control codes. */ 1190 SYS_ARCH_PROTECT(lev); 1191 for (i = 0; i < 32 / 8; i++) { 1192 /* @todo: does this work? ext_accm has been modified from pppd! */ 1193 pc->rx.inACCM[i] = (u_char)(asyncmap >> (i * 8)); 1194 } 1195 SYS_ARCH_UNPROTECT(lev); 1196 PPPDEBUG(LOG_INFO, ("ppp_recv_config[%d]: inACCM=%X %X %X %X\n", 1197 unit, 1198 pc->rx.inACCM[0], pc->rx.inACCM[1], pc->rx.inACCM[2], pc->rx.inACCM[3])); 1199 } 1200 1201 #if 0 1202 /* 1203 * ccp_test - ask kernel whether a given compression method 1204 * is acceptable for use. Returns 1 if the method and parameters 1205 * are OK, 0 if the method is known but the parameters are not OK 1206 * (e.g. code size should be reduced), or -1 if the method is unknown. 1207 */ 1208 int 1209 ccp_test( int unit, int opt_len, int for_transmit, u_char *opt_ptr) 1210 { 1211 return 0; /* XXX Currently no compression. */ 1212 } 1213 1214 /* 1215 * ccp_flags_set - inform kernel about the current state of CCP. 1216 */ 1217 void 1218 ccp_flags_set(int unit, int isopen, int isup) 1219 { 1220 /* XXX */ 1221 } 1222 1223 /* 1224 * ccp_fatal_error - returns 1 if decompression was disabled as a 1225 * result of an error detected after decompression of a packet, 1226 * 0 otherwise. This is necessary because of patent nonsense. 1227 */ 1228 int 1229 ccp_fatal_error(int unit) 1230 { 1231 /* XXX */ 1232 return 0; 1233 } 1234 #endif 1235 1236 /* 1237 * get_idle_time - return how long the link has been idle. 1238 */ 1239 int 1240 get_idle_time(int u, struct ppp_idle *ip) 1241 { 1242 /* XXX */ 1243 LWIP_UNUSED_ARG(u); 1244 LWIP_UNUSED_ARG(ip); 1245 1246 return 0; 1247 } 1248 1249 1250 /* 1251 * Return user specified netmask, modified by any mask we might determine 1252 * for address `addr' (in network byte order). 1253 * Here we scan through the system's list of interfaces, looking for 1254 * any non-point-to-point interfaces which might appear to be on the same 1255 * network as `addr'. If we find any, we OR in their netmask to the 1256 * user-specified netmask. 1257 */ 1258 u32_t 1259 GetMask(u32_t addr) 1260 { 1261 u32_t mask, nmask; 1262 1263 htonl(addr); 1264 if (IP_CLASSA(addr)) { /* determine network mask for address class */ 1265 nmask = IP_CLASSA_NET; 1266 } else if (IP_CLASSB(addr)) { 1267 nmask = IP_CLASSB_NET; 1268 } else { 1269 nmask = IP_CLASSC_NET; 1270 } 1271 1272 /* class D nets are disallowed by bad_ip_adrs */ 1273 mask = subnetMask | htonl(nmask); 1274 1275 /* XXX 1276 * Scan through the system's network interfaces. 1277 * Get each netmask and OR them into our mask. 1278 */ 1279 1280 return mask; 1281 } 1282 1283 /* 1284 * sifvjcomp - config tcp header compression 1285 */ 1286 int 1287 sifvjcomp(int pd, int vjcomp, u8_t cidcomp, u8_t maxcid) 1288 { 1289 #if PPPOS_SUPPORT && VJ_SUPPORT 1290 PPPControl *pc = &pppControl[pd]; 1291 1292 pc->vjEnabled = vjcomp; 1293 pc->vjComp.compressSlot = cidcomp; 1294 pc->vjComp.maxSlotIndex = maxcid; 1295 PPPDEBUG(LOG_INFO, ("sifvjcomp: VJ compress enable=%d slot=%d max slot=%d\n", 1296 vjcomp, cidcomp, maxcid)); 1297 #else /* PPPOS_SUPPORT && VJ_SUPPORT */ 1298 LWIP_UNUSED_ARG(pd); 1299 LWIP_UNUSED_ARG(vjcomp); 1300 LWIP_UNUSED_ARG(cidcomp); 1301 LWIP_UNUSED_ARG(maxcid); 1302 #endif /* PPPOS_SUPPORT && VJ_SUPPORT */ 1303 1304 return 0; 1305 } 1306 1307 /* 1308 * pppifNetifInit - netif init callback 1309 */ 1310 static err_t 1311 pppifNetifInit(struct netif *netif) 1312 { 1313 netif->name[0] = 'p'; 1314 netif->name[1] = 'p'; 1315 netif->output = pppifOutput; 1316 netif->mtu = pppMTU((int)(size_t)netif->state); 1317 netif->flags = NETIF_FLAG_POINTTOPOINT | NETIF_FLAG_LINK_UP; 1318 #if LWIP_NETIF_HOSTNAME 1319 /* @todo: Initialize interface hostname */ 1320 /* netif_set_hostname(netif, "lwip"); */ 1321 #endif /* LWIP_NETIF_HOSTNAME */ 1322 return ERR_OK; 1323 } 1324 1325 1326 /* 1327 * sifup - Config the interface up and enable IP packets to pass. 1328 */ 1329 int 1330 sifup(int pd) 1331 { 1332 PPPControl *pc = &pppControl[pd]; 1333 int st = 1; 1334 1335 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { 1336 st = 0; 1337 PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd)); 1338 } else { 1339 netif_remove(&pc->netif); 1340 if (netif_add(&pc->netif, &pc->addrs.our_ipaddr, &pc->addrs.netmask, 1341 &pc->addrs.his_ipaddr, (void *)(size_t)pd, pppifNetifInit, ip_input)) { 1342 netif_set_up(&pc->netif); 1343 pc->if_up = 1; 1344 pc->errCode = PPPERR_NONE; 1345 1346 PPPDEBUG(LOG_DEBUG, ("sifup: unit %d: linkStatusCB=%p errCode=%d\n", pd, pc->linkStatusCB, pc->errCode)); 1347 if (pc->linkStatusCB) { 1348 pc->linkStatusCB(pc->linkStatusCtx, pc->errCode, &pc->addrs); 1349 } 1350 } else { 1351 st = 0; 1352 PPPDEBUG(LOG_ERR, ("sifup[%d]: netif_add failed\n", pd)); 1353 } 1354 } 1355 1356 return st; 1357 } 1358 1359 /* 1360 * sifnpmode - Set the mode for handling packets for a given NP. 1361 */ 1362 int 1363 sifnpmode(int u, int proto, enum NPmode mode) 1364 { 1365 LWIP_UNUSED_ARG(u); 1366 LWIP_UNUSED_ARG(proto); 1367 LWIP_UNUSED_ARG(mode); 1368 return 0; 1369 } 1370 1371 /* 1372 * sifdown - Config the interface down and disable IP. 1373 */ 1374 int 1375 sifdown(int pd) 1376 { 1377 PPPControl *pc = &pppControl[pd]; 1378 int st = 1; 1379 1380 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { 1381 st = 0; 1382 PPPDEBUG(LOG_WARNING, ("sifdown[%d]: bad parms\n", pd)); 1383 } else { 1384 pc->if_up = 0; 1385 /* make sure the netif status callback is called */ 1386 netif_set_down(&pc->netif); 1387 netif_remove(&pc->netif); 1388 PPPDEBUG(LOG_DEBUG, ("sifdown: unit %d: linkStatusCB=%p errCode=%d\n", pd, pc->linkStatusCB, pc->errCode)); 1389 if (pc->linkStatusCB) { 1390 pc->linkStatusCB(pc->linkStatusCtx, PPPERR_CONNECT, NULL); 1391 } 1392 } 1393 return st; 1394 } 1395 1396 /** 1397 * sifaddr - Config the interface IP addresses and netmask. 1398 * @param pd Interface unit ??? 1399 * @param o Our IP address ??? 1400 * @param h His IP address ??? 1401 * @param m IP subnet mask ??? 1402 * @param ns1 Primary DNS 1403 * @param ns2 Secondary DNS 1404 */ 1405 int 1406 sifaddr( int pd, u32_t o, u32_t h, u32_t m, u32_t ns1, u32_t ns2) 1407 { 1408 PPPControl *pc = &pppControl[pd]; 1409 int st = 1; 1410 1411 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { 1412 st = 0; 1413 PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd)); 1414 } else { 1415 SMEMCPY(&pc->addrs.our_ipaddr, &o, sizeof(o)); 1416 SMEMCPY(&pc->addrs.his_ipaddr, &h, sizeof(h)); 1417 SMEMCPY(&pc->addrs.netmask, &m, sizeof(m)); 1418 SMEMCPY(&pc->addrs.dns1, &ns1, sizeof(ns1)); 1419 SMEMCPY(&pc->addrs.dns2, &ns2, sizeof(ns2)); 1420 } 1421 return st; 1422 } 1423 1424 /** 1425 * cifaddr - Clear the interface IP addresses, and delete routes 1426 * through the interface if possible. 1427 * @param pd Interface unit ??? 1428 * @param o Our IP address ??? 1429 * @param h IP broadcast address ??? 1430 */ 1431 int 1432 cifaddr( int pd, u32_t o, u32_t h) 1433 { 1434 PPPControl *pc = &pppControl[pd]; 1435 int st = 1; 1436 1437 LWIP_UNUSED_ARG(o); 1438 LWIP_UNUSED_ARG(h); 1439 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { 1440 st = 0; 1441 PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd)); 1442 } else { 1443 IP4_ADDR(&pc->addrs.our_ipaddr, 0,0,0,0); 1444 IP4_ADDR(&pc->addrs.his_ipaddr, 0,0,0,0); 1445 IP4_ADDR(&pc->addrs.netmask, 255,255,255,0); 1446 IP4_ADDR(&pc->addrs.dns1, 0,0,0,0); 1447 IP4_ADDR(&pc->addrs.dns2, 0,0,0,0); 1448 } 1449 return st; 1450 } 1451 1452 /* 1453 * sifdefaultroute - assign a default route through the address given. 1454 */ 1455 int 1456 sifdefaultroute(int pd, u32_t l, u32_t g) 1457 { 1458 PPPControl *pc = &pppControl[pd]; 1459 int st = 1; 1460 1461 LWIP_UNUSED_ARG(l); 1462 LWIP_UNUSED_ARG(g); 1463 1464 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { 1465 st = 0; 1466 PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd)); 1467 } else { 1468 netif_set_default(&pc->netif); 1469 } 1470 1471 /* TODO: check how PPP handled the netMask, previously not set by ipSetDefault */ 1472 1473 return st; 1474 } 1475 1476 /* 1477 * cifdefaultroute - delete a default route through the address given. 1478 */ 1479 int 1480 cifdefaultroute(int pd, u32_t l, u32_t g) 1481 { 1482 PPPControl *pc = &pppControl[pd]; 1483 int st = 1; 1484 1485 LWIP_UNUSED_ARG(l); 1486 LWIP_UNUSED_ARG(g); 1487 1488 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { 1489 st = 0; 1490 PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd)); 1491 } else { 1492 netif_set_default(NULL); 1493 } 1494 1495 return st; 1496 } 1497 1498 /**********************************/ 1499 /*** LOCAL FUNCTION DEFINITIONS ***/ 1500 /**********************************/ 1501 1502 #if PPPOS_SUPPORT && PPP_INPROC_OWNTHREAD 1503 /* The main PPP process function. This implements the state machine according 1504 * to section 4 of RFC 1661: The Point-To-Point Protocol. */ 1505 static void 1506 pppInputThread(void *arg) 1507 { 1508 int count; 1509 PPPControlRx *pcrx = arg; 1510 1511 while (lcp_phase[pcrx->pd] != PHASE_DEAD) { 1512 count = sio_read(pcrx->fd, pcrx->rxbuf, PPPOS_RX_BUFSIZE); 1513 if(count > 0) { 1514 pppInProc(pcrx, pcrx->rxbuf, count); 1515 } else { 1516 /* nothing received, give other tasks a chance to run */ 1517 sys_msleep(1); 1518 } 1519 } 1520 } 1521 #endif /* PPPOS_SUPPORT && PPP_INPROC_OWNTHREAD */ 1522 1523 #if PPPOE_SUPPORT 1524 1525 void 1526 pppOverEthernetInitFailed(int pd) 1527 { 1528 PPPControl* pc; 1529 1530 pppHup(pd); 1531 pppStop(pd); 1532 1533 pc = &pppControl[pd]; 1534 pppoe_destroy(&pc->netif); 1535 pc->openFlag = 0; 1536 1537 if(pc->linkStatusCB) { 1538 pc->linkStatusCB(pc->linkStatusCtx, pc->errCode ? pc->errCode : PPPERR_PROTOCOL, NULL); 1539 } 1540 } 1541 1542 static void 1543 pppOverEthernetLinkStatusCB(int pd, int up) 1544 { 1545 if(up) { 1546 PPPDEBUG(LOG_INFO, ("pppOverEthernetLinkStatusCB: unit %d: Connecting\n", pd)); 1547 pppStart(pd); 1548 } else { 1549 pppOverEthernetInitFailed(pd); 1550 } 1551 } 1552 #endif /* PPPOE_SUPPORT */ 1553 1554 struct pbuf * 1555 pppSingleBuf(struct pbuf *p) 1556 { 1557 struct pbuf *q, *b; 1558 u_char *pl; 1559 1560 if(p->tot_len == p->len) { 1561 return p; 1562 } 1563 1564 q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); 1565 if(!q) { 1566 PPPDEBUG(LOG_ERR, 1567 ("pppSingleBuf: unable to alloc new buf (%d)\n", p->tot_len)); 1568 return p; /* live dangerously */ 1569 } 1570 1571 for(b = p, pl = q->payload; b != NULL; b = b->next) { 1572 MEMCPY(pl, b->payload, b->len); 1573 pl += b->len; 1574 } 1575 1576 pbuf_free(p); 1577 1578 return q; 1579 } 1580 1581 struct pppInputHeader { 1582 int unit; 1583 u16_t proto; 1584 }; 1585 1586 /* 1587 * Pass the processed input packet to the appropriate handler. 1588 * This function and all handlers run in the context of the tcpip_thread 1589 */ 1590 static void 1591 pppInput(void *arg) 1592 { 1593 struct pbuf *nb = (struct pbuf *)arg; 1594 u16_t protocol; 1595 int pd; 1596 1597 pd = ((struct pppInputHeader *)nb->payload)->unit; 1598 protocol = ((struct pppInputHeader *)nb->payload)->proto; 1599 1600 if(pbuf_header(nb, -(int)sizeof(struct pppInputHeader))) { 1601 LWIP_ASSERT("pbuf_header failed\n", 0); 1602 goto drop; 1603 } 1604 1605 LINK_STATS_INC(link.recv); 1606 snmp_inc_ifinucastpkts(&pppControl[pd].netif); 1607 snmp_add_ifinoctets(&pppControl[pd].netif, nb->tot_len); 1608 1609 /* 1610 * Toss all non-LCP packets unless LCP is OPEN. 1611 * Until we get past the authentication phase, toss all packets 1612 * except LCP, LQR and authentication packets. 1613 */ 1614 if((lcp_phase[pd] <= PHASE_AUTHENTICATE) && (protocol != PPP_LCP)) { 1615 if(!((protocol == PPP_LQR) || (protocol == PPP_PAP) || (protocol == PPP_CHAP)) || 1616 (lcp_phase[pd] != PHASE_AUTHENTICATE)) { 1617 PPPDEBUG(LOG_INFO, ("pppInput: discarding proto 0x%"X16_F" in phase %d\n", protocol, lcp_phase[pd])); 1618 goto drop; 1619 } 1620 } 1621 1622 switch(protocol) { 1623 case PPP_VJC_COMP: /* VJ compressed TCP */ 1624 #if PPPOS_SUPPORT && VJ_SUPPORT 1625 PPPDEBUG(LOG_INFO, ("pppInput[%d]: vj_comp in pbuf len=%d\n", pd, nb->len)); 1626 /* 1627 * Clip off the VJ header and prepend the rebuilt TCP/IP header and 1628 * pass the result to IP. 1629 */ 1630 if ((vj_uncompress_tcp(&nb, &pppControl[pd].vjComp) >= 0) && (pppControl[pd].netif.input)) { 1631 pppControl[pd].netif.input(nb, &pppControl[pd].netif); 1632 return; 1633 } 1634 /* Something's wrong so drop it. */ 1635 PPPDEBUG(LOG_WARNING, ("pppInput[%d]: Dropping VJ compressed\n", pd)); 1636 #else /* PPPOS_SUPPORT && VJ_SUPPORT */ 1637 /* No handler for this protocol so drop the packet. */ 1638 PPPDEBUG(LOG_INFO, ("pppInput[%d]: drop VJ Comp in %d:%s\n", pd, nb->len, nb->payload)); 1639 #endif /* PPPOS_SUPPORT && VJ_SUPPORT */ 1640 break; 1641 1642 case PPP_VJC_UNCOMP: /* VJ uncompressed TCP */ 1643 #if PPPOS_SUPPORT && VJ_SUPPORT 1644 PPPDEBUG(LOG_INFO, ("pppInput[%d]: vj_un in pbuf len=%d\n", pd, nb->len)); 1645 /* 1646 * Process the TCP/IP header for VJ header compression and then pass 1647 * the packet to IP. 1648 */ 1649 if ((vj_uncompress_uncomp(nb, &pppControl[pd].vjComp) >= 0) && pppControl[pd].netif.input) { 1650 pppControl[pd].netif.input(nb, &pppControl[pd].netif); 1651 return; 1652 } 1653 /* Something's wrong so drop it. */ 1654 PPPDEBUG(LOG_WARNING, ("pppInput[%d]: Dropping VJ uncompressed\n", pd)); 1655 #else /* PPPOS_SUPPORT && VJ_SUPPORT */ 1656 /* No handler for this protocol so drop the packet. */ 1657 PPPDEBUG(LOG_INFO, 1658 ("pppInput[%d]: drop VJ UnComp in %d:.*H\n", 1659 pd, nb->len, LWIP_MIN(nb->len * 2, 40), nb->payload)); 1660 #endif /* PPPOS_SUPPORT && VJ_SUPPORT */ 1661 break; 1662 1663 case PPP_IP: /* Internet Protocol */ 1664 PPPDEBUG(LOG_INFO, ("pppInput[%d]: ip in pbuf len=%d\n", pd, nb->len)); 1665 if (pppControl[pd].netif.input) { 1666 pppControl[pd].netif.input(nb, &pppControl[pd].netif); 1667 return; 1668 } 1669 break; 1670 1671 default: { 1672 struct protent *protp; 1673 int i; 1674 1675 /* 1676 * Upcall the proper protocol input routine. 1677 */ 1678 for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) { 1679 if (protp->protocol == protocol && protp->enabled_flag) { 1680 PPPDEBUG(LOG_INFO, ("pppInput[%d]: %s len=%d\n", pd, protp->name, nb->len)); 1681 nb = pppSingleBuf(nb); 1682 (*protp->input)(pd, nb->payload, nb->len); 1683 PPPDEBUG(LOG_DETAIL, ("pppInput[%d]: packet processed\n", pd)); 1684 goto out; 1685 } 1686 } 1687 1688 /* No handler for this protocol so reject the packet. */ 1689 PPPDEBUG(LOG_INFO, ("pppInput[%d]: rejecting unsupported proto 0x%"X16_F" len=%d\n", pd, protocol, nb->len)); 1690 if (pbuf_header(nb, sizeof(protocol))) { 1691 LWIP_ASSERT("pbuf_header failed\n", 0); 1692 goto drop; 1693 } 1694 #if BYTE_ORDER == LITTLE_ENDIAN 1695 protocol = htons(protocol); 1696 #endif /* BYTE_ORDER == LITTLE_ENDIAN */ 1697 SMEMCPY(nb->payload, &protocol, sizeof(protocol)); 1698 lcp_sprotrej(pd, nb->payload, nb->len); 1699 } 1700 break; 1701 } 1702 1703 drop: 1704 LINK_STATS_INC(link.drop); 1705 snmp_inc_ifindiscards(&pppControl[pd].netif); 1706 1707 out: 1708 pbuf_free(nb); 1709 return; 1710 } 1711 1712 #if PPPOS_SUPPORT 1713 /* 1714 * Drop the input packet. 1715 */ 1716 static void 1717 pppDrop(PPPControlRx *pcrx) 1718 { 1719 if (pcrx->inHead != NULL) { 1720 #if 0 1721 PPPDEBUG(LOG_INFO, ("pppDrop: %d:%.*H\n", pcrx->inHead->len, min(60, pcrx->inHead->len * 2), pcrx->inHead->payload)); 1722 #endif 1723 PPPDEBUG(LOG_INFO, ("pppDrop: pbuf len=%d, addr %p\n", pcrx->inHead->len, (void*)pcrx->inHead)); 1724 if (pcrx->inTail && (pcrx->inTail != pcrx->inHead)) { 1725 pbuf_free(pcrx->inTail); 1726 } 1727 pbuf_free(pcrx->inHead); 1728 pcrx->inHead = NULL; 1729 pcrx->inTail = NULL; 1730 } 1731 #if VJ_SUPPORT 1732 vj_uncompress_err(&pppControl[pcrx->pd].vjComp); 1733 #endif /* VJ_SUPPORT */ 1734 1735 LINK_STATS_INC(link.drop); 1736 snmp_inc_ifindiscards(&pppControl[pcrx->pd].netif); 1737 } 1738 1739 /** Pass received raw characters to PPPoS to be decoded. This function is 1740 * thread-safe and can be called from a dedicated RX-thread or from a main-loop. 1741 * 1742 * @param pd PPP descriptor index, returned by pppOpen() 1743 * @param data received data 1744 * @param len length of received data 1745 */ 1746 void 1747 pppos_input(int pd, u_char* data, int len) 1748 { 1749 pppInProc(&pppControl[pd].rx, data, len); 1750 } 1751 1752 /** 1753 * Process a received octet string. 1754 */ 1755 static void 1756 pppInProc(PPPControlRx *pcrx, u_char *s, int l) 1757 { 1758 struct pbuf *nextNBuf; 1759 u_char curChar; 1760 u_char escaped; 1761 SYS_ARCH_DECL_PROTECT(lev); 1762 1763 PPPDEBUG(LOG_DEBUG, ("pppInProc[%d]: got %d bytes\n", pcrx->pd, l)); 1764 while (l-- > 0) { 1765 curChar = *s++; 1766 1767 SYS_ARCH_PROTECT(lev); 1768 escaped = ESCAPE_P(pcrx->inACCM, curChar); 1769 SYS_ARCH_UNPROTECT(lev); 1770 /* Handle special characters. */ 1771 if (escaped) { 1772 /* Check for escape sequences. */ 1773 /* XXX Note that this does not handle an escaped 0x5d character which 1774 * would appear as an escape character. Since this is an ASCII ']' 1775 * and there is no reason that I know of to escape it, I won't complicate 1776 * the code to handle this case. GLL */ 1777 if (curChar == PPP_ESCAPE) { 1778 pcrx->inEscaped = 1; 1779 /* Check for the flag character. */ 1780 } else if (curChar == PPP_FLAG) { 1781 /* If this is just an extra flag character, ignore it. */ 1782 if (pcrx->inState <= PDADDRESS) { 1783 /* ignore it */; 1784 /* If we haven't received the packet header, drop what has come in. */ 1785 } else if (pcrx->inState < PDDATA) { 1786 PPPDEBUG(LOG_WARNING, 1787 ("pppInProc[%d]: Dropping incomplete packet %d\n", 1788 pcrx->pd, pcrx->inState)); 1789 LINK_STATS_INC(link.lenerr); 1790 pppDrop(pcrx); 1791 /* If the fcs is invalid, drop the packet. */ 1792 } else if (pcrx->inFCS != PPP_GOODFCS) { 1793 PPPDEBUG(LOG_INFO, 1794 ("pppInProc[%d]: Dropping bad fcs 0x%"X16_F" proto=0x%"X16_F"\n", 1795 pcrx->pd, pcrx->inFCS, pcrx->inProtocol)); 1796 /* Note: If you get lots of these, check for UART frame errors or try different baud rate */ 1797 LINK_STATS_INC(link.chkerr); 1798 pppDrop(pcrx); 1799 /* Otherwise it's a good packet so pass it on. */ 1800 } else { 1801 struct pbuf *inp; 1802 /* Trim off the checksum. */ 1803 if(pcrx->inTail->len >= 2) { 1804 pcrx->inTail->len -= 2; 1805 1806 pcrx->inTail->tot_len = pcrx->inTail->len; 1807 if (pcrx->inTail != pcrx->inHead) { 1808 pbuf_cat(pcrx->inHead, pcrx->inTail); 1809 } 1810 } else { 1811 pcrx->inTail->tot_len = pcrx->inTail->len; 1812 if (pcrx->inTail != pcrx->inHead) { 1813 pbuf_cat(pcrx->inHead, pcrx->inTail); 1814 } 1815 1816 pbuf_realloc(pcrx->inHead, pcrx->inHead->tot_len - 2); 1817 } 1818 1819 /* Dispatch the packet thereby consuming it. */ 1820 inp = pcrx->inHead; 1821 /* Packet consumed, release our references. */ 1822 pcrx->inHead = NULL; 1823 pcrx->inTail = NULL; 1824 #if PPP_INPROC_MULTITHREADED 1825 if(tcpip_callback_with_block(pppInput, inp, 0) != ERR_OK) { 1826 PPPDEBUG(LOG_ERR, ("pppInProc[%d]: tcpip_callback() failed, dropping packet\n", pcrx->pd)); 1827 pbuf_free(inp); 1828 LINK_STATS_INC(link.drop); 1829 snmp_inc_ifindiscards(&pppControl[pcrx->pd].netif); 1830 } 1831 #else /* PPP_INPROC_MULTITHREADED */ 1832 pppInput(inp); 1833 #endif /* PPP_INPROC_MULTITHREADED */ 1834 } 1835 1836 /* Prepare for a new packet. */ 1837 pcrx->inFCS = PPP_INITFCS; 1838 pcrx->inState = PDADDRESS; 1839 pcrx->inEscaped = 0; 1840 /* Other characters are usually control characters that may have 1841 * been inserted by the physical layer so here we just drop them. */ 1842 } else { 1843 PPPDEBUG(LOG_WARNING, 1844 ("pppInProc[%d]: Dropping ACCM char <%d>\n", pcrx->pd, curChar)); 1845 } 1846 /* Process other characters. */ 1847 } else { 1848 /* Unencode escaped characters. */ 1849 if (pcrx->inEscaped) { 1850 pcrx->inEscaped = 0; 1851 curChar ^= PPP_TRANS; 1852 } 1853 1854 /* Process character relative to current state. */ 1855 switch(pcrx->inState) { 1856 case PDIDLE: /* Idle state - waiting. */ 1857 /* Drop the character if it's not 0xff 1858 * we would have processed a flag character above. */ 1859 if (curChar != PPP_ALLSTATIONS) { 1860 break; 1861 } 1862 1863 /* Fall through */ 1864 case PDSTART: /* Process start flag. */ 1865 /* Prepare for a new packet. */ 1866 pcrx->inFCS = PPP_INITFCS; 1867 1868 /* Fall through */ 1869 case PDADDRESS: /* Process address field. */ 1870 if (curChar == PPP_ALLSTATIONS) { 1871 pcrx->inState = PDCONTROL; 1872 break; 1873 } 1874 /* Else assume compressed address and control fields so 1875 * fall through to get the protocol... */ 1876 case PDCONTROL: /* Process control field. */ 1877 /* If we don't get a valid control code, restart. */ 1878 if (curChar == PPP_UI) { 1879 pcrx->inState = PDPROTOCOL1; 1880 break; 1881 } 1882 #if 0 1883 else { 1884 PPPDEBUG(LOG_WARNING, 1885 ("pppInProc[%d]: Invalid control <%d>\n", pcrx->pd, curChar)); 1886 pcrx->inState = PDSTART; 1887 } 1888 #endif 1889 case PDPROTOCOL1: /* Process protocol field 1. */ 1890 /* If the lower bit is set, this is the end of the protocol 1891 * field. */ 1892 if (curChar & 1) { 1893 pcrx->inProtocol = curChar; 1894 pcrx->inState = PDDATA; 1895 } else { 1896 pcrx->inProtocol = (u_int)curChar << 8; 1897 pcrx->inState = PDPROTOCOL2; 1898 } 1899 break; 1900 case PDPROTOCOL2: /* Process protocol field 2. */ 1901 pcrx->inProtocol |= curChar; 1902 pcrx->inState = PDDATA; 1903 break; 1904 case PDDATA: /* Process data byte. */ 1905 /* Make space to receive processed data. */ 1906 if (pcrx->inTail == NULL || pcrx->inTail->len == PBUF_POOL_BUFSIZE) { 1907 if (pcrx->inTail != NULL) { 1908 pcrx->inTail->tot_len = pcrx->inTail->len; 1909 if (pcrx->inTail != pcrx->inHead) { 1910 pbuf_cat(pcrx->inHead, pcrx->inTail); 1911 /* give up the inTail reference now */ 1912 pcrx->inTail = NULL; 1913 } 1914 } 1915 /* If we haven't started a packet, we need a packet header. */ 1916 nextNBuf = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); 1917 if (nextNBuf == NULL) { 1918 /* No free buffers. Drop the input packet and let the 1919 * higher layers deal with it. Continue processing 1920 * the received pbuf chain in case a new packet starts. */ 1921 PPPDEBUG(LOG_ERR, ("pppInProc[%d]: NO FREE MBUFS!\n", pcrx->pd)); 1922 LINK_STATS_INC(link.memerr); 1923 pppDrop(pcrx); 1924 pcrx->inState = PDSTART; /* Wait for flag sequence. */ 1925 break; 1926 } 1927 if (pcrx->inHead == NULL) { 1928 struct pppInputHeader *pih = nextNBuf->payload; 1929 1930 pih->unit = pcrx->pd; 1931 pih->proto = pcrx->inProtocol; 1932 1933 nextNBuf->len += sizeof(*pih); 1934 1935 pcrx->inHead = nextNBuf; 1936 } 1937 pcrx->inTail = nextNBuf; 1938 } 1939 /* Load character into buffer. */ 1940 ((u_char*)pcrx->inTail->payload)[pcrx->inTail->len++] = curChar; 1941 break; 1942 } 1943 1944 /* update the frame check sequence number. */ 1945 pcrx->inFCS = PPP_FCS(pcrx->inFCS, curChar); 1946 } 1947 } /* while (l-- > 0), all bytes processed */ 1948 1949 avRandomize(); 1950 } 1951 #endif /* PPPOS_SUPPORT */ 1952 1953 #if PPPOE_SUPPORT 1954 void 1955 pppInProcOverEthernet(int pd, struct pbuf *pb) 1956 { 1957 struct pppInputHeader *pih; 1958 u16_t inProtocol; 1959 1960 if(pb->len < sizeof(inProtocol)) { 1961 PPPDEBUG(LOG_ERR, ("pppInProcOverEthernet: too small for protocol field\n")); 1962 goto drop; 1963 } 1964 1965 inProtocol = (((u8_t *)pb->payload)[0] << 8) | ((u8_t*)pb->payload)[1]; 1966 1967 /* make room for pppInputHeader - should not fail */ 1968 if (pbuf_header(pb, sizeof(*pih) - sizeof(inProtocol)) != 0) { 1969 PPPDEBUG(LOG_ERR, ("pppInProcOverEthernet: could not allocate room for header\n")); 1970 goto drop; 1971 } 1972 1973 pih = pb->payload; 1974 1975 pih->unit = pd; 1976 pih->proto = inProtocol; 1977 1978 /* Dispatch the packet thereby consuming it. */ 1979 pppInput(pb); 1980 return; 1981 1982 drop: 1983 LINK_STATS_INC(link.drop); 1984 snmp_inc_ifindiscards(&pppControl[pd].netif); 1985 pbuf_free(pb); 1986 return; 1987 } 1988 #endif /* PPPOE_SUPPORT */ 1989 1990 #if LWIP_NETIF_STATUS_CALLBACK 1991 /** Set the status callback of a PPP's netif 1992 * 1993 * @param pd The PPP descriptor returned by pppOpen() 1994 * @param status_callback pointer to the status callback function 1995 * 1996 * @see netif_set_status_callback 1997 */ 1998 void 1999 ppp_set_netif_statuscallback(int pd, netif_status_callback_fn status_callback) 2000 { 2001 netif_set_status_callback(&pppControl[pd].netif, status_callback); 2002 } 2003 #endif /* LWIP_NETIF_STATUS_CALLBACK */ 2004 2005 #if LWIP_NETIF_LINK_CALLBACK 2006 /** Set the link callback of a PPP's netif 2007 * 2008 * @param pd The PPP descriptor returned by pppOpen() 2009 * @param link_callback pointer to the link callback function 2010 * 2011 * @see netif_set_link_callback 2012 */ 2013 void 2014 ppp_set_netif_linkcallback(int pd, netif_status_callback_fn link_callback) 2015 { 2016 netif_set_link_callback(&pppControl[pd].netif, link_callback); 2017 } 2018 #endif /* LWIP_NETIF_LINK_CALLBACK */ 2019 2020 #endif /* PPP_SUPPORT */ 2021