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