Adapted to Lora Semtech + Nucleo
Dependents: LoRaWAN-lmic-app LoRaWAN-lmic-app LoRaWAN-test-10secs LoRaPersonalizedDeviceForEverynet ... more
Fork of lwip_ppp_ethernet by
ppp.c
00001 /***************************************************************************** 00002 * ppp.c - Network Point to Point Protocol program file. 00003 * 00004 * Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. 00005 * portions Copyright (c) 1997 by Global Election Systems Inc. 00006 * 00007 * The authors hereby grant permission to use, copy, modify, distribute, 00008 * and license this software and its documentation for any purpose, provided 00009 * that existing copyright notices are retained in all copies and that this 00010 * notice and the following disclaimer are included verbatim in any 00011 * distributions. No written agreement, license, or royalty fee is required 00012 * for any of the authorized uses. 00013 * 00014 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR 00015 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00016 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 00017 * IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00018 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 00019 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00020 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00021 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00022 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 00023 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00024 * 00025 ****************************************************************************** 00026 * REVISION HISTORY 00027 * 00028 * 03-01-01 Marc Boucher <marc@mbsi.ca> 00029 * Ported to lwIP. 00030 * 97-11-05 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc. 00031 * Original. 00032 *****************************************************************************/ 00033 00034 /* 00035 * ppp_defs.h - PPP definitions. 00036 * 00037 * if_pppvar.h - private structures and declarations for PPP. 00038 * 00039 * Copyright (c) 1994 The Australian National University. 00040 * All rights reserved. 00041 * 00042 * Permission to use, copy, modify, and distribute this software and its 00043 * documentation is hereby granted, provided that the above copyright 00044 * notice appears in all copies. This software is provided without any 00045 * warranty, express or implied. The Australian National University 00046 * makes no representations about the suitability of this software for 00047 * any purpose. 00048 * 00049 * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY 00050 * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 00051 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 00052 * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY 00053 * OF SUCH DAMAGE. 00054 * 00055 * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, 00056 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 00057 * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 00058 * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO 00059 * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, 00060 * OR MODIFICATIONS. 00061 */ 00062 00063 /* 00064 * if_ppp.h - Point-to-Point Protocol definitions. 00065 * 00066 * Copyright (c) 1989 Carnegie Mellon University. 00067 * All rights reserved. 00068 * 00069 * Redistribution and use in source and binary forms are permitted 00070 * provided that the above copyright notice and this paragraph are 00071 * duplicated in all such forms and that any documentation, 00072 * advertising materials, and other materials related to such 00073 * distribution and use acknowledge that the software was developed 00074 * by Carnegie Mellon University. The name of the 00075 * University may not be used to endorse or promote products derived 00076 * from this software without specific prior written permission. 00077 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 00078 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 00079 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00080 */ 00081 00082 #define __LWIP_ORIG 0 00083 00084 #include "lwip/opt.h" 00085 00086 #if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ 00087 00088 #include "lwip/ip.h" /* for ip_input() */ 00089 00090 #include "ppp.h" 00091 #include "pppdebug.h" 00092 00093 #include "randm.h" 00094 #include "fsm.h" 00095 #if PAP_SUPPORT 00096 #include "pap.h" 00097 #endif /* PAP_SUPPORT */ 00098 #if CHAP_SUPPORT 00099 #include "chap.h" 00100 #endif /* CHAP_SUPPORT */ 00101 #include "ipcp.h" 00102 #include "lcp.h" 00103 #include "magic.h" 00104 #include "auth.h" 00105 #if VJ_SUPPORT 00106 #include "vj.h" 00107 #endif /* VJ_SUPPORT */ 00108 #if PPPOE_SUPPORT 00109 #include "netif/ppp_oe.h" 00110 #endif /* PPPOE_SUPPORT */ 00111 00112 #include "lwip/tcpip.h" 00113 #include "lwip/api.h" 00114 #include "lwip/snmp.h" 00115 00116 #include <string.h> 00117 00118 /*************************/ 00119 /*** LOCAL DEFINITIONS ***/ 00120 /*************************/ 00121 00122 /** PPP_INPROC_MULTITHREADED==1 call pppInput using tcpip_callback(). 00123 * Set this to 0 if pppInProc is called inside tcpip_thread or with NO_SYS==1. 00124 * Default is 1 for NO_SYS==0 (multithreaded) and 0 for NO_SYS==1 (single-threaded). 00125 */ 00126 #ifndef PPP_INPROC_MULTITHREADED 00127 #define PPP_INPROC_MULTITHREADED (NO_SYS==0) 00128 #endif 00129 00130 /** PPP_INPROC_OWNTHREAD==1: start a dedicated RX thread per PPP session. 00131 * Default is 0: call pppos_input() for received raw characters, charcater 00132 * reception is up to the port */ 00133 #ifndef PPP_INPROC_OWNTHREAD 00134 #define PPP_INPROC_OWNTHREAD PPP_INPROC_MULTITHREADED 00135 #endif 00136 00137 #if PPP_INPROC_OWNTHREAD && !PPP_INPROC_MULTITHREADED 00138 #error "PPP_INPROC_OWNTHREAD needs PPP_INPROC_MULTITHREADED==1" 00139 #endif 00140 00141 /* 00142 * The basic PPP frame. 00143 */ 00144 #define PPP_ADDRESS(p) (((u_char *)(p))[0]) 00145 #define PPP_CONTROL(p) (((u_char *)(p))[1]) 00146 #define PPP_PROTOCOL(p) ((((u_char *)(p))[2] << 8) + ((u_char *)(p))[3]) 00147 00148 /* PPP packet parser states. Current state indicates operation yet to be 00149 * completed. */ 00150 typedef enum { 00151 PDIDLE = 0, /* Idle state - waiting. */ 00152 PDSTART, /* Process start flag. */ 00153 PDADDRESS, /* Process address field. */ 00154 PDCONTROL, /* Process control field. */ 00155 PDPROTOCOL1, /* Process protocol field 1. */ 00156 PDPROTOCOL2, /* Process protocol field 2. */ 00157 PDDATA /* Process data byte. */ 00158 } PPPDevStates; 00159 00160 #define ESCAPE_P(accm, c) ((accm)[(c) >> 3] & pppACCMMask[c & 0x07]) 00161 00162 /************************/ 00163 /*** LOCAL DATA TYPES ***/ 00164 /************************/ 00165 00166 /** RX buffer size: this may be configured smaller! */ 00167 #ifndef PPPOS_RX_BUFSIZE 00168 #define PPPOS_RX_BUFSIZE (PPP_MRU + PPP_HDRLEN) 00169 #endif 00170 00171 typedef struct PPPControlRx_s { 00172 /** unit number / ppp descriptor */ 00173 int pd; 00174 /** the rx file descriptor */ 00175 sio_fd_t fd; 00176 /** receive buffer - encoded data is stored here */ 00177 u_char rxbuf[PPPOS_RX_BUFSIZE]; 00178 00179 /* The input packet. */ 00180 struct pbuf *inHead, *inTail; 00181 00182 #if PPPOS_SUPPORT 00183 u16_t inProtocol; /* The input protocol code. */ 00184 u16_t inFCS; /* Input Frame Check Sequence value. */ 00185 #endif /* PPPOS_SUPPORT */ 00186 PPPDevStates inState; /* The input process state. */ 00187 char inEscaped; /* Escape next character. */ 00188 ext_accm inACCM; /* Async-Ctl-Char-Map for input. */ 00189 } PPPControlRx; 00190 00191 /* 00192 * PPP interface control block. 00193 */ 00194 typedef struct PPPControl_s { 00195 PPPControlRx rx; 00196 char openFlag; /* True when in use. */ 00197 #if PPPOE_SUPPORT 00198 struct netif *ethif; 00199 struct pppoe_softc *pppoe_sc; 00200 #endif /* PPPOE_SUPPORT */ 00201 int if_up; /* True when the interface is up. */ 00202 int errCode; /* Code indicating why interface is down. */ 00203 #if PPPOS_SUPPORT 00204 sio_fd_t fd; /* File device ID of port. */ 00205 #endif /* PPPOS_SUPPORT */ 00206 u16_t mtu; /* Peer's mru */ 00207 int pcomp; /* Does peer accept protocol compression? */ 00208 int accomp; /* Does peer accept addr/ctl compression? */ 00209 u_long lastXMit; /* Time of last transmission. */ 00210 ext_accm outACCM; /* Async-Ctl-Char-Map for output. */ 00211 #if PPPOS_SUPPORT && VJ_SUPPORT 00212 int vjEnabled; /* Flag indicating VJ compression enabled. */ 00213 struct vjcompress vjComp; /* Van Jacobson compression header. */ 00214 #endif /* PPPOS_SUPPORT && VJ_SUPPORT */ 00215 00216 struct netif netif; 00217 00218 struct ppp_addrs addrs; 00219 00220 void (*linkStatusCB)(void *ctx, int errCode, void *arg); 00221 void *linkStatusCtx; 00222 00223 } PPPControl; 00224 00225 00226 /* 00227 * Ioctl definitions. 00228 */ 00229 00230 struct npioctl { 00231 int protocol; /* PPP procotol, e.g. PPP_IP */ 00232 enum NPmode mode; 00233 }; 00234 00235 00236 00237 /***********************************/ 00238 /*** LOCAL FUNCTION DECLARATIONS ***/ 00239 /***********************************/ 00240 #if PPPOS_SUPPORT 00241 #if PPP_INPROC_OWNTHREAD 00242 static void pppInputThread(void *arg); 00243 #endif /* PPP_INPROC_OWNTHREAD */ 00244 static void pppDrop(PPPControlRx *pcrx); 00245 static void pppInProc(PPPControlRx *pcrx, u_char *s, int l); 00246 #endif /* PPPOS_SUPPORT */ 00247 00248 00249 /******************************/ 00250 /*** PUBLIC DATA STRUCTURES ***/ 00251 /******************************/ 00252 u_long subnetMask; 00253 00254 static PPPControl pppControl[NUM_PPP] __attribute((section("AHBSRAM1"))); //Add DG; /* The PPP interface control blocks. */ 00255 00256 #if !__LWIP_ORIG 00257 sys_mbox_t pppMbox; //Used to signal PPP thread that a PPP session begins 00258 #endif 00259 00260 /* 00261 * PPP Data Link Layer "protocol" table. 00262 * One entry per supported protocol. 00263 * The last entry must be NULL. 00264 */ 00265 struct protent *ppp_protocols[] = { 00266 &lcp_protent, 00267 #if PAP_SUPPORT 00268 &pap_protent, 00269 #endif /* PAP_SUPPORT */ 00270 #if CHAP_SUPPORT 00271 &chap_protent, 00272 #endif /* CHAP_SUPPORT */ 00273 #if CBCP_SUPPORT 00274 &cbcp_protent, 00275 #endif /* CBCP_SUPPORT */ 00276 &ipcp_protent, 00277 #if CCP_SUPPORT 00278 &ccp_protent, 00279 #endif /* CCP_SUPPORT */ 00280 NULL 00281 }; 00282 00283 00284 /* 00285 * Buffers for outgoing packets. This must be accessed only from the appropriate 00286 * PPP task so that it doesn't need to be protected to avoid collisions. 00287 */ 00288 u_char outpacket_buf[NUM_PPP][PPP_MRU+PPP_HDRLEN] __attribute((section("AHBSRAM1"))); 00289 00290 00291 /*****************************/ 00292 /*** LOCAL DATA STRUCTURES ***/ 00293 /*****************************/ 00294 00295 #if PPPOS_SUPPORT 00296 /* 00297 * FCS lookup table as calculated by genfcstab. 00298 * @todo: smaller, slower implementation for lower memory footprint? 00299 */ 00300 static const u_short fcstab[256] = { 00301 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 00302 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, 00303 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, 00304 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, 00305 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, 00306 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, 00307 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, 00308 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, 00309 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, 00310 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, 00311 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, 00312 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, 00313 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, 00314 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, 00315 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, 00316 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, 00317 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, 00318 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, 00319 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, 00320 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, 00321 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, 00322 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, 00323 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, 00324 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, 00325 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, 00326 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, 00327 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, 00328 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, 00329 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, 00330 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, 00331 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 00332 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 00333 }; 00334 00335 /* PPP's Asynchronous-Control-Character-Map. The mask array is used 00336 * to select the specific bit for a character. */ 00337 static u_char pppACCMMask[] = { 00338 0x01, 00339 0x02, 00340 0x04, 00341 0x08, 00342 0x10, 00343 0x20, 00344 0x40, 00345 0x80 00346 }; 00347 00348 /** Wake up the task blocked in reading from serial line (if any) */ 00349 static void 00350 pppRecvWakeup(int pd) 00351 { 00352 PPPDEBUG(LOG_DEBUG, ("pppRecvWakeup: unit %d\n", pd)); 00353 if (pppControl[pd].openFlag != 0) { 00354 sio_read_abort(pppControl[pd].fd); 00355 } 00356 } 00357 #endif /* PPPOS_SUPPORT */ 00358 00359 void 00360 pppLinkTerminated(int pd) 00361 { 00362 PPPDEBUG(LOG_DEBUG, ("pppLinkTerminated: unit %d\n", pd)); 00363 00364 #if PPPOE_SUPPORT 00365 if (pppControl[pd].ethif) { 00366 pppoe_disconnect(pppControl[pd].pppoe_sc); 00367 } else 00368 #endif /* PPPOE_SUPPORT */ 00369 { 00370 #if PPPOS_SUPPORT 00371 PPPControl* pc; 00372 pppRecvWakeup(pd); 00373 pc = &pppControl[pd]; 00374 00375 PPPDEBUG(LOG_DEBUG, ("pppLinkTerminated: unit %d: linkStatusCB=%p errCode=%d\n", pd, pc->linkStatusCB, pc->errCode)); 00376 if (pc->linkStatusCB) { 00377 pc->linkStatusCB(pc->linkStatusCtx, pc->errCode ? pc->errCode : PPPERR_PROTOCOL, NULL); 00378 } 00379 00380 pc->openFlag = 0;/**/ 00381 #endif /* PPPOS_SUPPORT */ 00382 } 00383 PPPDEBUG(LOG_DEBUG, ("pppLinkTerminated: finished.\n")); 00384 } 00385 00386 void 00387 pppLinkDown(int pd) 00388 { 00389 PPPDEBUG(LOG_DEBUG, ("pppLinkDown: unit %d\n", pd)); 00390 00391 #if PPPOE_SUPPORT 00392 if (pppControl[pd].ethif) { 00393 pppoe_disconnect(pppControl[pd].pppoe_sc); 00394 } else 00395 #endif /* PPPOE_SUPPORT */ 00396 { 00397 #if PPPOS_SUPPORT 00398 pppRecvWakeup(pd); 00399 #endif /* PPPOS_SUPPORT */ 00400 } 00401 } 00402 00403 /** Initiate LCP open request */ 00404 static void 00405 pppStart(int pd) 00406 { 00407 PPPDEBUG(LOG_DEBUG, ("pppStart: unit %d\n", pd)); 00408 lcp_lowerup(pd); 00409 lcp_open(pd); /* Start protocol */ 00410 PPPDEBUG(LOG_DEBUG, ("pppStart: finished\n")); 00411 } 00412 00413 /** LCP close request */ 00414 static void 00415 pppStop(int pd) 00416 { 00417 PPPDEBUG(LOG_DEBUG, ("pppStop: unit %d\n", pd)); 00418 lcp_close(pd, "User request"); 00419 } 00420 00421 /** Called when carrier/link is lost */ 00422 static void 00423 pppHup(int pd) 00424 { 00425 PPPDEBUG(LOG_DEBUG, ("pppHupCB: unit %d\n", pd)); 00426 lcp_lowerdown(pd); 00427 link_terminated(pd); 00428 } 00429 00430 /***********************************/ 00431 /*** PUBLIC FUNCTION DEFINITIONS ***/ 00432 /***********************************/ 00433 /* Initialize the PPP subsystem. */ 00434 00435 struct ppp_settings ppp_settings; 00436 00437 void 00438 pppInit(void) 00439 { 00440 struct protent *protp; 00441 int i, j; 00442 00443 memset(&ppp_settings, 0, sizeof(ppp_settings)); 00444 ppp_settings.usepeerdns = 1; 00445 pppSetAuth(PPPAUTHTYPE_NONE, NULL, NULL); 00446 00447 magicInit(); 00448 00449 subnetMask = PP_HTONL(0xffffff00UL); 00450 00451 for (i = 0; i < NUM_PPP; i++) { 00452 /* Initialize each protocol to the standard option set. */ 00453 for (j = 0; (protp = ppp_protocols[j]) != NULL; ++j) { 00454 (*protp->init)(i); 00455 } 00456 } 00457 00458 #if !__LWIP_ORIG 00459 sys_mbox_new(&pppMbox, 1); 00460 sys_thread_new(PPP_THREAD_NAME, pppInputThread, (void*)NULL, PPP_THREAD_STACKSIZE, PPP_THREAD_PRIO); //Create PPP thread here 00461 #endif 00462 } 00463 00464 void 00465 pppSetAuth(enum pppAuthType authType, const char *user, const char *passwd) 00466 { 00467 switch(authType) { 00468 case PPPAUTHTYPE_NONE: 00469 default: 00470 #ifdef LWIP_PPP_STRICT_PAP_REJECT 00471 ppp_settings.refuse_pap = 1; 00472 #else /* LWIP_PPP_STRICT_PAP_REJECT */ 00473 /* some providers request pap and accept an empty login/pw */ 00474 ppp_settings.refuse_pap = 0; 00475 #endif /* LWIP_PPP_STRICT_PAP_REJECT */ 00476 ppp_settings.refuse_chap = 1; 00477 break; 00478 00479 case PPPAUTHTYPE_ANY: 00480 /* Warning: Using PPPAUTHTYPE_ANY might have security consequences. 00481 * RFC 1994 says: 00482 * 00483 * In practice, within or associated with each PPP server, there is a 00484 * database which associates "user" names with authentication 00485 * information ("secrets"). It is not anticipated that a particular 00486 * named user would be authenticated by multiple methods. This would 00487 * make the user vulnerable to attacks which negotiate the least secure 00488 * method from among a set (such as PAP rather than CHAP). If the same 00489 * secret was used, PAP would reveal the secret to be used later with 00490 * CHAP. 00491 * 00492 * Instead, for each user name there should be an indication of exactly 00493 * one method used to authenticate that user name. If a user needs to 00494 * make use of different authentication methods under different 00495 * circumstances, then distinct user names SHOULD be employed, each of 00496 * which identifies exactly one authentication method. 00497 * 00498 */ 00499 ppp_settings.refuse_pap = 0; 00500 ppp_settings.refuse_chap = 0; 00501 break; 00502 00503 case PPPAUTHTYPE_PAP: 00504 ppp_settings.refuse_pap = 0; 00505 ppp_settings.refuse_chap = 1; 00506 break; 00507 00508 case PPPAUTHTYPE_CHAP: 00509 ppp_settings.refuse_pap = 1; 00510 ppp_settings.refuse_chap = 0; 00511 break; 00512 } 00513 00514 if(user) { 00515 strncpy(ppp_settings.user, user, sizeof(ppp_settings.user)-1); 00516 ppp_settings.user[sizeof(ppp_settings.user)-1] = '\0'; 00517 } else { 00518 ppp_settings.user[0] = '\0'; 00519 } 00520 00521 if(passwd) { 00522 strncpy(ppp_settings.passwd, passwd, sizeof(ppp_settings.passwd)-1); 00523 ppp_settings.passwd[sizeof(ppp_settings.passwd)-1] = '\0'; 00524 } else { 00525 ppp_settings.passwd[0] = '\0'; 00526 } 00527 } 00528 00529 #if PPPOS_SUPPORT 00530 /** Open a new PPP connection using the given I/O device. 00531 * This initializes the PPP control block but does not 00532 * attempt to negotiate the LCP session. If this port 00533 * connects to a modem, the modem connection must be 00534 * established before calling this. 00535 * Return a new PPP connection descriptor on success or 00536 * an error code (negative) on failure. 00537 * 00538 * pppOpen() is directly defined to this function. 00539 */ 00540 int 00541 pppOverSerialOpen(sio_fd_t fd, void (*linkStatusCB)(void *ctx, int errCode, void *arg), void *linkStatusCtx) 00542 { 00543 PPPControl *pc; 00544 int pd; 00545 00546 if (linkStatusCB == NULL) { 00547 /* PPP is single-threaded: without a callback, 00548 * there is no way to know when the link is up. */ 00549 return PPPERR_PARAM; 00550 } 00551 00552 /* Find a free PPP session descriptor. */ 00553 for (pd = 0; pd < NUM_PPP && pppControl[pd].openFlag != 0; pd++); 00554 00555 if (pd >= NUM_PPP) { 00556 pd = PPPERR_OPEN; 00557 } else { 00558 pc = &pppControl[pd]; 00559 /* @todo: is this correct or do I overwrite something? */ 00560 memset(pc, 0, sizeof(PPPControl)); 00561 pc->rx.pd = pd; 00562 pc->rx.fd = fd; 00563 00564 pc->openFlag = 1; 00565 pc->fd = fd; 00566 00567 #if VJ_SUPPORT 00568 vj_compress_init(&pc->vjComp); 00569 #endif /* VJ_SUPPORT */ 00570 00571 /* 00572 * Default the in and out accm so that escape and flag characters 00573 * are always escaped. 00574 */ 00575 pc->rx.inACCM[15] = 0x60; /* no need to protect since RX is not running */ 00576 pc->outACCM[15] = 0x60; 00577 00578 pc->linkStatusCB = linkStatusCB; 00579 pc->linkStatusCtx = linkStatusCtx; 00580 00581 /* 00582 * Start the connection and handle incoming events (packet or timeout). 00583 */ 00584 PPPDEBUG(LOG_INFO, ("pppOverSerialOpen: unit %d: Connecting\n", pd)); 00585 pppStart(pd); 00586 #if PPP_INPROC_OWNTHREAD 00587 #if __LWIP_ORIG 00588 sys_thread_new(PPP_THREAD_NAME, pppInputThread, (void*)&pc->rx, PPP_THREAD_STACKSIZE, PPP_THREAD_PRIO); 00589 #else 00590 sys_mbox_post(&pppMbox, (void*)&pc->rx); 00591 #endif 00592 #endif 00593 } 00594 00595 return pd; 00596 } 00597 #endif /* PPPOS_SUPPORT */ 00598 00599 #if PPPOE_SUPPORT 00600 static void pppOverEthernetLinkStatusCB(int pd, int up); 00601 00602 void 00603 pppOverEthernetClose(int pd) 00604 { 00605 PPPControl* pc = &pppControl[pd]; 00606 00607 /* *TJL* There's no lcp_deinit */ 00608 lcp_close(pd, NULL); 00609 00610 pppoe_destroy(&pc->netif); 00611 } 00612 00613 int pppOverEthernetOpen(struct netif *ethif, const char *service_name, const char *concentrator_name, void (*linkStatusCB)(void *ctx, int errCode, void *arg), void *linkStatusCtx) 00614 { 00615 PPPControl *pc; 00616 int pd; 00617 00618 LWIP_UNUSED_ARG(service_name); 00619 LWIP_UNUSED_ARG(concentrator_name); 00620 00621 if (linkStatusCB == NULL) { 00622 /* PPP is single-threaded: without a callback, 00623 * there is no way to know when the link is up. */ 00624 return PPPERR_PARAM; 00625 } 00626 00627 /* Find a free PPP session descriptor. Critical region? */ 00628 for (pd = 0; pd < NUM_PPP && pppControl[pd].openFlag != 0; pd++); 00629 if (pd >= NUM_PPP) { 00630 pd = PPPERR_OPEN; 00631 } else { 00632 pc = &pppControl[pd]; 00633 memset(pc, 0, sizeof(PPPControl)); 00634 pc->openFlag = 1; 00635 pc->ethif = ethif; 00636 00637 pc->linkStatusCB = linkStatusCB; 00638 pc->linkStatusCtx = linkStatusCtx; 00639 00640 lcp_wantoptions[pd].mru = PPPOE_MAXMTU; 00641 lcp_wantoptions[pd].neg_asyncmap = 0; 00642 lcp_wantoptions[pd].neg_pcompression = 0; 00643 lcp_wantoptions[pd].neg_accompression = 0; 00644 00645 lcp_allowoptions[pd].mru = PPPOE_MAXMTU; 00646 lcp_allowoptions[pd].neg_asyncmap = 0; 00647 lcp_allowoptions[pd].neg_pcompression = 0; 00648 lcp_allowoptions[pd].neg_accompression = 0; 00649 00650 if(pppoe_create(ethif, pd, pppOverEthernetLinkStatusCB, &pc->pppoe_sc) != ERR_OK) { 00651 pc->openFlag = 0; 00652 return PPPERR_OPEN; 00653 } 00654 00655 pppoe_connect(pc->pppoe_sc); 00656 } 00657 00658 return pd; 00659 } 00660 #endif /* PPPOE_SUPPORT */ 00661 00662 00663 /* Close a PPP connection and release the descriptor. 00664 * Any outstanding packets in the queues are dropped. 00665 * Return 0 on success, an error code on failure. */ 00666 int 00667 pppClose(int pd) 00668 { 00669 PPPControl *pc = &pppControl[pd]; 00670 int st = 0; 00671 00672 PPPDEBUG(LOG_DEBUG, ("pppClose() called\n")); 00673 00674 /* Disconnect */ 00675 #if PPPOE_SUPPORT 00676 if(pc->ethif) { 00677 PPPDEBUG(LOG_DEBUG, ("pppClose: unit %d kill_link -> pppStop\n", pd)); 00678 pc->errCode = PPPERR_USER; 00679 /* This will leave us at PHASE_DEAD. */ 00680 pppStop(pd); 00681 } else 00682 #endif /* PPPOE_SUPPORT */ 00683 { 00684 #if PPPOS_SUPPORT 00685 PPPDEBUG(LOG_DEBUG, ("pppClose: unit %d kill_link -> pppStop\n", pd)); 00686 pc->errCode = PPPERR_USER; 00687 /* This will leave us at PHASE_DEAD. */ 00688 pppStop(pd); 00689 pppRecvWakeup(pd); 00690 #endif /* PPPOS_SUPPORT */ 00691 } 00692 00693 return st; 00694 } 00695 00696 /* This function is called when carrier is lost on the PPP channel. */ 00697 void 00698 pppSigHUP(int pd) 00699 { 00700 PPPDEBUG(LOG_DEBUG, ("pppSigHUP: unit %d sig_hup -> pppHupCB\n", pd)); 00701 pppHup(pd); 00702 } 00703 00704 #if PPPOS_SUPPORT 00705 static void 00706 nPut(PPPControl *pc, struct pbuf *nb) 00707 { 00708 struct pbuf *b; 00709 int c; 00710 00711 for(b = nb; b != NULL; b = b->next) { 00712 if((c = sio_write(pc->fd, b->payload, b->len)) != b->len) { 00713 PPPDEBUG(LOG_WARNING, 00714 ("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)); 00715 LINK_STATS_INC(link.err); 00716 pc->lastXMit = 0; /* prepend PPP_FLAG to next packet */ 00717 snmp_inc_ifoutdiscards(&pc->netif); 00718 pbuf_free(nb); 00719 return; 00720 } 00721 } 00722 00723 snmp_add_ifoutoctets(&pc->netif, nb->tot_len); 00724 snmp_inc_ifoutucastpkts(&pc->netif); 00725 pbuf_free(nb); 00726 LINK_STATS_INC(link.xmit); 00727 } 00728 00729 /* 00730 * pppAppend - append given character to end of given pbuf. If outACCM 00731 * is not NULL and the character needs to be escaped, do so. 00732 * If pbuf is full, append another. 00733 * Return the current pbuf. 00734 */ 00735 static struct pbuf * 00736 pppAppend(u_char c, struct pbuf *nb, ext_accm *outACCM) 00737 { 00738 struct pbuf *tb = nb; 00739 00740 /* Make sure there is room for the character and an escape code. 00741 * Sure we don't quite fill the buffer if the character doesn't 00742 * get escaped but is one character worth complicating this? */ 00743 /* Note: We assume no packet header. */ 00744 if (nb && (PBUF_POOL_BUFSIZE - nb->len) < 2) { 00745 tb = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); 00746 if (tb) { 00747 nb->next = tb; 00748 } else { 00749 LINK_STATS_INC(link.memerr); 00750 } 00751 nb = tb; 00752 } 00753 00754 if (nb) { 00755 if (outACCM && ESCAPE_P(*outACCM, c)) { 00756 *((u_char*)nb->payload + nb->len++) = PPP_ESCAPE; 00757 *((u_char*)nb->payload + nb->len++) = c ^ PPP_TRANS; 00758 } else { 00759 *((u_char*)nb->payload + nb->len++) = c; 00760 } 00761 } 00762 00763 return tb; 00764 } 00765 #endif /* PPPOS_SUPPORT */ 00766 00767 #if PPPOE_SUPPORT 00768 static err_t 00769 pppifOutputOverEthernet(int pd, struct pbuf *p) 00770 { 00771 PPPControl *pc = &pppControl[pd]; 00772 struct pbuf *pb; 00773 u_short protocol = PPP_IP; 00774 int i=0; 00775 u16_t tot_len; 00776 00777 /* @todo: try to use pbuf_header() here! */ 00778 pb = pbuf_alloc(PBUF_LINK, PPPOE_HDRLEN + sizeof(protocol), PBUF_RAM); 00779 if(!pb) { 00780 LINK_STATS_INC(link.memerr); 00781 LINK_STATS_INC(link.proterr); 00782 snmp_inc_ifoutdiscards(&pc->netif); 00783 return ERR_MEM; 00784 } 00785 00786 pbuf_header(pb, -(s16_t)PPPOE_HDRLEN); 00787 00788 pc->lastXMit = sys_jiffies(); 00789 00790 if (!pc->pcomp || protocol > 0xFF) { 00791 *((u_char*)pb->payload + i++) = (protocol >> 8) & 0xFF; 00792 } 00793 *((u_char*)pb->payload + i) = protocol & 0xFF; 00794 00795 pbuf_chain(pb, p); 00796 tot_len = pb->tot_len; 00797 00798 if(pppoe_xmit(pc->pppoe_sc, pb) != ERR_OK) { 00799 LINK_STATS_INC(link.err); 00800 snmp_inc_ifoutdiscards(&pc->netif); 00801 return PPPERR_DEVICE; 00802 } 00803 00804 snmp_add_ifoutoctets(&pc->netif, tot_len); 00805 snmp_inc_ifoutucastpkts(&pc->netif); 00806 LINK_STATS_INC(link.xmit); 00807 return ERR_OK; 00808 } 00809 #endif /* PPPOE_SUPPORT */ 00810 00811 /* Send a packet on the given connection. */ 00812 static err_t 00813 pppifOutput(struct netif *netif, struct pbuf *pb, ip_addr_t *ipaddr) 00814 { 00815 int pd = (int)(size_t)netif->state; 00816 PPPControl *pc = &pppControl[pd]; 00817 #if PPPOS_SUPPORT 00818 u_short protocol = PPP_IP; 00819 u_int fcsOut = PPP_INITFCS; 00820 struct pbuf *headMB = NULL, *tailMB = NULL, *p; 00821 u_char c; 00822 #endif /* PPPOS_SUPPORT */ 00823 00824 LWIP_UNUSED_ARG(ipaddr); 00825 00826 /* Validate parameters. */ 00827 /* We let any protocol value go through - it can't hurt us 00828 * and the peer will just drop it if it's not accepting it. */ 00829 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag || !pb) { 00830 PPPDEBUG(LOG_WARNING, ("pppifOutput[%d]: bad parms prot=%d pb=%p\n", 00831 pd, PPP_IP, pb)); 00832 LINK_STATS_INC(link.opterr); 00833 LINK_STATS_INC(link.drop); 00834 snmp_inc_ifoutdiscards(netif); 00835 return ERR_ARG; 00836 } 00837 00838 /* Check that the link is up. */ 00839 if (lcp_phase[pd] == PHASE_DEAD) { 00840 PPPDEBUG(LOG_ERR, ("pppifOutput[%d]: link not up\n", pd)); 00841 LINK_STATS_INC(link.rterr); 00842 LINK_STATS_INC(link.drop); 00843 snmp_inc_ifoutdiscards(netif); 00844 return ERR_RTE; 00845 } 00846 00847 #if PPPOE_SUPPORT 00848 if(pc->ethif) { 00849 return pppifOutputOverEthernet(pd, pb); 00850 } 00851 #endif /* PPPOE_SUPPORT */ 00852 00853 #if PPPOS_SUPPORT 00854 /* Grab an output buffer. */ 00855 headMB = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); 00856 if (headMB == NULL) { 00857 PPPDEBUG(LOG_WARNING, ("pppifOutput[%d]: first alloc fail\n", pd)); 00858 LINK_STATS_INC(link.memerr); 00859 LINK_STATS_INC(link.drop); 00860 snmp_inc_ifoutdiscards(netif); 00861 return ERR_MEM; 00862 } 00863 00864 #if VJ_SUPPORT 00865 /* 00866 * Attempt Van Jacobson header compression if VJ is configured and 00867 * this is an IP packet. 00868 */ 00869 if (protocol == PPP_IP && pc->vjEnabled) { 00870 switch (vj_compress_tcp(&pc->vjComp, pb)) { 00871 case TYPE_IP: 00872 /* No change... 00873 protocol = PPP_IP_PROTOCOL; */ 00874 break; 00875 case TYPE_COMPRESSED_TCP: 00876 protocol = PPP_VJC_COMP; 00877 break; 00878 case TYPE_UNCOMPRESSED_TCP: 00879 protocol = PPP_VJC_UNCOMP; 00880 break; 00881 default: 00882 PPPDEBUG(LOG_WARNING, ("pppifOutput[%d]: bad IP packet\n", pd)); 00883 LINK_STATS_INC(link.proterr); 00884 LINK_STATS_INC(link.drop); 00885 snmp_inc_ifoutdiscards(netif); 00886 pbuf_free(headMB); 00887 return ERR_VAL; 00888 } 00889 } 00890 #endif /* VJ_SUPPORT */ 00891 00892 tailMB = headMB; 00893 00894 /* Build the PPP header. */ 00895 if ((sys_jiffies() - pc->lastXMit) >= PPP_MAXIDLEFLAG) { 00896 tailMB = pppAppend(PPP_FLAG, tailMB, NULL); 00897 } 00898 00899 pc->lastXMit = sys_jiffies(); 00900 if (!pc->accomp) { 00901 fcsOut = PPP_FCS(fcsOut, PPP_ALLSTATIONS); 00902 tailMB = pppAppend(PPP_ALLSTATIONS, tailMB, &pc->outACCM); 00903 fcsOut = PPP_FCS(fcsOut, PPP_UI); 00904 tailMB = pppAppend(PPP_UI, tailMB, &pc->outACCM); 00905 } 00906 if (!pc->pcomp || protocol > 0xFF) { 00907 c = (protocol >> 8) & 0xFF; 00908 fcsOut = PPP_FCS(fcsOut, c); 00909 tailMB = pppAppend(c, tailMB, &pc->outACCM); 00910 } 00911 c = protocol & 0xFF; 00912 fcsOut = PPP_FCS(fcsOut, c); 00913 tailMB = pppAppend(c, tailMB, &pc->outACCM); 00914 00915 /* Load packet. */ 00916 for(p = pb; p; p = p->next) { 00917 int n; 00918 u_char *sPtr; 00919 00920 sPtr = (u_char*)p->payload; 00921 n = p->len; 00922 while (n-- > 0) { 00923 c = *sPtr++; 00924 00925 /* Update FCS before checking for special characters. */ 00926 fcsOut = PPP_FCS(fcsOut, c); 00927 00928 /* Copy to output buffer escaping special characters. */ 00929 tailMB = pppAppend(c, tailMB, &pc->outACCM); 00930 } 00931 } 00932 00933 /* Add FCS and trailing flag. */ 00934 c = ~fcsOut & 0xFF; 00935 tailMB = pppAppend(c, tailMB, &pc->outACCM); 00936 c = (~fcsOut >> 8) & 0xFF; 00937 tailMB = pppAppend(c, tailMB, &pc->outACCM); 00938 tailMB = pppAppend(PPP_FLAG, tailMB, NULL); 00939 00940 /* If we failed to complete the packet, throw it away. */ 00941 if (!tailMB) { 00942 PPPDEBUG(LOG_WARNING, 00943 ("pppifOutput[%d]: Alloc err - dropping proto=%d\n", 00944 pd, protocol)); 00945 pbuf_free(headMB); 00946 LINK_STATS_INC(link.memerr); 00947 LINK_STATS_INC(link.drop); 00948 snmp_inc_ifoutdiscards(netif); 00949 return ERR_MEM; 00950 } 00951 00952 /* Send it. */ 00953 PPPDEBUG(LOG_INFO, ("pppifOutput[%d]: proto=0x%"X16_F"\n", pd, protocol)); 00954 00955 nPut(pc, headMB); 00956 #endif /* PPPOS_SUPPORT */ 00957 00958 return ERR_OK; 00959 } 00960 00961 /* Get and set parameters for the given connection. 00962 * Return 0 on success, an error code on failure. */ 00963 int 00964 pppIOCtl(int pd, int cmd, void *arg) 00965 { 00966 PPPControl *pc = &pppControl[pd]; 00967 int st = 0; 00968 00969 if (pd < 0 || pd >= NUM_PPP) { 00970 st = PPPERR_PARAM; 00971 } else { 00972 switch(cmd) { 00973 case PPPCTLG_UPSTATUS: /* Get the PPP up status. */ 00974 if (arg) { 00975 *(int *)arg = (int)(pc->if_up); 00976 } else { 00977 st = PPPERR_PARAM; 00978 } 00979 break; 00980 case PPPCTLS_ERRCODE: /* Set the PPP error code. */ 00981 if (arg) { 00982 pc->errCode = *(int *)arg; 00983 } else { 00984 st = PPPERR_PARAM; 00985 } 00986 break; 00987 case PPPCTLG_ERRCODE: /* Get the PPP error code. */ 00988 if (arg) { 00989 *(int *)arg = (int)(pc->errCode); 00990 } else { 00991 st = PPPERR_PARAM; 00992 } 00993 break; 00994 #if PPPOS_SUPPORT 00995 case PPPCTLG_FD: /* Get the fd associated with the ppp */ 00996 if (arg) { 00997 *(sio_fd_t *)arg = pc->fd; 00998 } else { 00999 st = PPPERR_PARAM; 01000 } 01001 break; 01002 #endif /* PPPOS_SUPPORT */ 01003 default: 01004 st = PPPERR_PARAM; 01005 break; 01006 } 01007 } 01008 01009 return st; 01010 } 01011 01012 /* 01013 * Return the Maximum Transmission Unit for the given PPP connection. 01014 */ 01015 u_short 01016 pppMTU(int pd) 01017 { 01018 PPPControl *pc = &pppControl[pd]; 01019 u_short st; 01020 01021 /* Validate parameters. */ 01022 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { 01023 st = 0; 01024 } else { 01025 st = pc->mtu; 01026 } 01027 01028 return st; 01029 } 01030 01031 #if PPPOE_SUPPORT 01032 int 01033 pppWriteOverEthernet(int pd, const u_char *s, int n) 01034 { 01035 PPPControl *pc = &pppControl[pd]; 01036 struct pbuf *pb; 01037 01038 /* skip address & flags */ 01039 s += 2; 01040 n -= 2; 01041 01042 LWIP_ASSERT("PPPOE_HDRLEN + n <= 0xffff", PPPOE_HDRLEN + n <= 0xffff); 01043 pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HDRLEN + n), PBUF_RAM); 01044 if(!pb) { 01045 LINK_STATS_INC(link.memerr); 01046 LINK_STATS_INC(link.proterr); 01047 snmp_inc_ifoutdiscards(&pc->netif); 01048 return PPPERR_ALLOC; 01049 } 01050 01051 pbuf_header(pb, -(s16_t)PPPOE_HDRLEN); 01052 01053 pc->lastXMit = sys_jiffies(); 01054 01055 MEMCPY(pb->payload, s, n); 01056 01057 if(pppoe_xmit(pc->pppoe_sc, pb) != ERR_OK) { 01058 LINK_STATS_INC(link.err); 01059 snmp_inc_ifoutdiscards(&pc->netif); 01060 return PPPERR_DEVICE; 01061 } 01062 01063 snmp_add_ifoutoctets(&pc->netif, (u16_t)n); 01064 snmp_inc_ifoutucastpkts(&pc->netif); 01065 LINK_STATS_INC(link.xmit); 01066 return PPPERR_NONE; 01067 } 01068 #endif /* PPPOE_SUPPORT */ 01069 01070 /* 01071 * Write n characters to a ppp link. 01072 * RETURN: >= 0 Number of characters written 01073 * -1 Failed to write to device 01074 */ 01075 int 01076 pppWrite(int pd, const u_char *s, int n) 01077 { 01078 PPPControl *pc = &pppControl[pd]; 01079 #if PPPOS_SUPPORT 01080 u_char c; 01081 u_int fcsOut; 01082 struct pbuf *headMB, *tailMB; 01083 #endif /* PPPOS_SUPPORT */ 01084 01085 #if PPPOE_SUPPORT 01086 if(pc->ethif) { 01087 return pppWriteOverEthernet(pd, s, n); 01088 } 01089 #endif /* PPPOE_SUPPORT */ 01090 01091 #if PPPOS_SUPPORT 01092 headMB = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); 01093 if (headMB == NULL) { 01094 LINK_STATS_INC(link.memerr); 01095 LINK_STATS_INC(link.proterr); 01096 snmp_inc_ifoutdiscards(&pc->netif); 01097 return PPPERR_ALLOC; 01098 } 01099 01100 tailMB = headMB; 01101 01102 /* If the link has been idle, we'll send a fresh flag character to 01103 * flush any noise. */ 01104 if ((sys_jiffies() - pc->lastXMit) >= PPP_MAXIDLEFLAG) { 01105 tailMB = pppAppend(PPP_FLAG, tailMB, NULL); 01106 } 01107 pc->lastXMit = sys_jiffies(); 01108 01109 fcsOut = PPP_INITFCS; 01110 /* Load output buffer. */ 01111 while (n-- > 0) { 01112 c = *s++; 01113 01114 /* Update FCS before checking for special characters. */ 01115 fcsOut = PPP_FCS(fcsOut, c); 01116 01117 /* Copy to output buffer escaping special characters. */ 01118 tailMB = pppAppend(c, tailMB, &pc->outACCM); 01119 } 01120 01121 /* Add FCS and trailing flag. */ 01122 c = ~fcsOut & 0xFF; 01123 tailMB = pppAppend(c, tailMB, &pc->outACCM); 01124 c = (~fcsOut >> 8) & 0xFF; 01125 tailMB = pppAppend(c, tailMB, &pc->outACCM); 01126 tailMB = pppAppend(PPP_FLAG, tailMB, NULL); 01127 01128 /* If we failed to complete the packet, throw it away. 01129 * Otherwise send it. */ 01130 if (!tailMB) { 01131 PPPDEBUG(LOG_WARNING, 01132 ("pppWrite[%d]: Alloc err - dropping pbuf len=%d\n", pd, headMB->len)); 01133 /*"pppWrite[%d]: Alloc err - dropping %d:%.*H", pd, headMB->len, LWIP_MIN(headMB->len * 2, 40), headMB->payload)); */ 01134 pbuf_free(headMB); 01135 LINK_STATS_INC(link.memerr); 01136 LINK_STATS_INC(link.proterr); 01137 snmp_inc_ifoutdiscards(&pc->netif); 01138 return PPPERR_ALLOC; 01139 } 01140 01141 PPPDEBUG(LOG_INFO, ("pppWrite[%d]: len=%d\n", pd, headMB->len)); 01142 /* "pppWrite[%d]: %d:%.*H", pd, headMB->len, LWIP_MIN(headMB->len * 2, 40), headMB->payload)); */ 01143 nPut(pc, headMB); 01144 #endif /* PPPOS_SUPPORT */ 01145 01146 return PPPERR_NONE; 01147 } 01148 01149 /* 01150 * ppp_send_config - configure the transmit characteristics of 01151 * the ppp interface. 01152 */ 01153 void 01154 ppp_send_config( int unit, u16_t mtu, u32_t asyncmap, int pcomp, int accomp) 01155 { 01156 PPPControl *pc = &pppControl[unit]; 01157 int i; 01158 01159 pc->mtu = mtu; 01160 pc->pcomp = pcomp; 01161 pc->accomp = accomp; 01162 01163 /* Load the ACCM bits for the 32 control codes. */ 01164 for (i = 0; i < 32/8; i++) { 01165 pc->outACCM[i] = (u_char)((asyncmap >> (8 * i)) & 0xFF); 01166 } 01167 PPPDEBUG(LOG_INFO, ("ppp_send_config[%d]: outACCM=%X %X %X %X\n", 01168 unit, 01169 pc->outACCM[0], pc->outACCM[1], pc->outACCM[2], pc->outACCM[3])); 01170 } 01171 01172 01173 /* 01174 * ppp_set_xaccm - set the extended transmit ACCM for the interface. 01175 */ 01176 void 01177 ppp_set_xaccm(int unit, ext_accm *accm) 01178 { 01179 SMEMCPY(pppControl[unit].outACCM, accm, sizeof(ext_accm)); 01180 PPPDEBUG(LOG_INFO, ("ppp_set_xaccm[%d]: outACCM=%X %X %X %X\n", 01181 unit, 01182 pppControl[unit].outACCM[0], 01183 pppControl[unit].outACCM[1], 01184 pppControl[unit].outACCM[2], 01185 pppControl[unit].outACCM[3])); 01186 } 01187 01188 01189 /* 01190 * ppp_recv_config - configure the receive-side characteristics of 01191 * the ppp interface. 01192 */ 01193 void 01194 ppp_recv_config( int unit, int mru, u32_t asyncmap, int pcomp, int accomp) 01195 { 01196 PPPControl *pc = &pppControl[unit]; 01197 int i; 01198 SYS_ARCH_DECL_PROTECT(lev); 01199 01200 LWIP_UNUSED_ARG(accomp); 01201 LWIP_UNUSED_ARG(pcomp); 01202 LWIP_UNUSED_ARG(mru); 01203 01204 /* Load the ACCM bits for the 32 control codes. */ 01205 SYS_ARCH_PROTECT(lev); 01206 for (i = 0; i < 32 / 8; i++) { 01207 /* @todo: does this work? ext_accm has been modified from pppd! */ 01208 pc->rx.inACCM[i] = (u_char)(asyncmap >> (i * 8)); 01209 } 01210 SYS_ARCH_UNPROTECT(lev); 01211 PPPDEBUG(LOG_INFO, ("ppp_recv_config[%d]: inACCM=%X %X %X %X\n", 01212 unit, 01213 pc->rx.inACCM[0], pc->rx.inACCM[1], pc->rx.inACCM[2], pc->rx.inACCM[3])); 01214 } 01215 01216 #if 0 01217 /* 01218 * ccp_test - ask kernel whether a given compression method 01219 * is acceptable for use. Returns 1 if the method and parameters 01220 * are OK, 0 if the method is known but the parameters are not OK 01221 * (e.g. code size should be reduced), or -1 if the method is unknown. 01222 */ 01223 int 01224 ccp_test( int unit, int opt_len, int for_transmit, u_char *opt_ptr) 01225 { 01226 return 0; /* XXX Currently no compression. */ 01227 } 01228 01229 /* 01230 * ccp_flags_set - inform kernel about the current state of CCP. 01231 */ 01232 void 01233 ccp_flags_set(int unit, int isopen, int isup) 01234 { 01235 /* XXX */ 01236 } 01237 01238 /* 01239 * ccp_fatal_error - returns 1 if decompression was disabled as a 01240 * result of an error detected after decompression of a packet, 01241 * 0 otherwise. This is necessary because of patent nonsense. 01242 */ 01243 int 01244 ccp_fatal_error(int unit) 01245 { 01246 /* XXX */ 01247 return 0; 01248 } 01249 #endif 01250 01251 /* 01252 * get_idle_time - return how long the link has been idle. 01253 */ 01254 int 01255 get_idle_time(int u, struct ppp_idle *ip) 01256 { 01257 /* XXX */ 01258 LWIP_UNUSED_ARG(u); 01259 LWIP_UNUSED_ARG(ip); 01260 01261 return 0; 01262 } 01263 01264 01265 /* 01266 * Return user specified netmask, modified by any mask we might determine 01267 * for address `addr' (in network byte order). 01268 * Here we scan through the system's list of interfaces, looking for 01269 * any non-point-to-point interfaces which might appear to be on the same 01270 * network as `addr'. If we find any, we OR in their netmask to the 01271 * user-specified netmask. 01272 */ 01273 u32_t 01274 GetMask(u32_t addr) 01275 { 01276 u32_t mask, nmask; 01277 01278 htonl(addr); 01279 if (IP_CLASSA(addr)) { /* determine network mask for address class */ 01280 nmask = IP_CLASSA_NET; 01281 } else if (IP_CLASSB(addr)) { 01282 nmask = IP_CLASSB_NET; 01283 } else { 01284 nmask = IP_CLASSC_NET; 01285 } 01286 01287 /* class D nets are disallowed by bad_ip_adrs */ 01288 mask = subnetMask | htonl(nmask); 01289 01290 /* XXX 01291 * Scan through the system's network interfaces. 01292 * Get each netmask and OR them into our mask. 01293 */ 01294 01295 return mask; 01296 } 01297 01298 /* 01299 * sifvjcomp - config tcp header compression 01300 */ 01301 int 01302 sifvjcomp(int pd, int vjcomp, u8_t cidcomp, u8_t maxcid) 01303 { 01304 #if PPPOS_SUPPORT && VJ_SUPPORT 01305 PPPControl *pc = &pppControl[pd]; 01306 01307 pc->vjEnabled = vjcomp; 01308 pc->vjComp.compressSlot = cidcomp; 01309 pc->vjComp.maxSlotIndex = maxcid; 01310 PPPDEBUG(LOG_INFO, ("sifvjcomp: VJ compress enable=%d slot=%d max slot=%d\n", 01311 vjcomp, cidcomp, maxcid)); 01312 #else /* PPPOS_SUPPORT && VJ_SUPPORT */ 01313 LWIP_UNUSED_ARG(pd); 01314 LWIP_UNUSED_ARG(vjcomp); 01315 LWIP_UNUSED_ARG(cidcomp); 01316 LWIP_UNUSED_ARG(maxcid); 01317 #endif /* PPPOS_SUPPORT && VJ_SUPPORT */ 01318 01319 return 0; 01320 } 01321 01322 /* 01323 * pppifNetifInit - netif init callback 01324 */ 01325 static err_t 01326 pppifNetifInit(struct netif *netif) 01327 { 01328 netif->name[0] = 'p'; 01329 netif->name[1] = 'p'; 01330 netif->output = pppifOutput; 01331 netif->mtu = pppMTU((int)(size_t)netif->state); 01332 netif->flags = NETIF_FLAG_POINTTOPOINT | NETIF_FLAG_LINK_UP; 01333 #if LWIP_NETIF_HOSTNAME 01334 /* @todo: Initialize interface hostname */ 01335 /* netif_set_hostname(netif, "lwip"); */ 01336 #endif /* LWIP_NETIF_HOSTNAME */ 01337 return ERR_OK; 01338 } 01339 01340 01341 /* 01342 * sifup - Config the interface up and enable IP packets to pass. 01343 */ 01344 int 01345 sifup(int pd) 01346 { 01347 PPPControl *pc = &pppControl[pd]; 01348 int st = 1; 01349 01350 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { 01351 st = 0; 01352 PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd)); 01353 } else { 01354 netif_remove(&pc->netif); 01355 if (netif_add(&pc->netif, &pc->addrs.our_ipaddr, &pc->addrs.netmask, 01356 &pc->addrs.his_ipaddr, (void *)(size_t)pd, pppifNetifInit, ip_input)) { 01357 netif_set_up(&pc->netif); 01358 pc->if_up = 1; 01359 pc->errCode = PPPERR_NONE; 01360 01361 PPPDEBUG(LOG_DEBUG, ("sifup: unit %d: linkStatusCB=%p errCode=%d\n", pd, pc->linkStatusCB, pc->errCode)); 01362 if (pc->linkStatusCB) { 01363 pc->linkStatusCB(pc->linkStatusCtx, pc->errCode, &pc->addrs); 01364 } 01365 } else { 01366 st = 0; 01367 PPPDEBUG(LOG_ERR, ("sifup[%d]: netif_add failed\n", pd)); 01368 } 01369 } 01370 01371 return st; 01372 } 01373 01374 /* 01375 * sifnpmode - Set the mode for handling packets for a given NP. 01376 */ 01377 int 01378 sifnpmode(int u, int proto, enum NPmode mode) 01379 { 01380 LWIP_UNUSED_ARG(u); 01381 LWIP_UNUSED_ARG(proto); 01382 LWIP_UNUSED_ARG(mode); 01383 return 0; 01384 } 01385 01386 /* 01387 * sifdown - Config the interface down and disable IP. 01388 */ 01389 int 01390 sifdown(int pd) 01391 { 01392 PPPControl *pc = &pppControl[pd]; 01393 int st = 1; 01394 01395 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { 01396 st = 0; 01397 PPPDEBUG(LOG_WARNING, ("sifdown[%d]: bad parms\n", pd)); 01398 } else { 01399 pc->if_up = 0; 01400 /* make sure the netif status callback is called */ 01401 netif_set_down(&pc->netif); 01402 netif_remove(&pc->netif); 01403 PPPDEBUG(LOG_DEBUG, ("sifdown: unit %d: linkStatusCB=%p errCode=%d\n", pd, pc->linkStatusCB, pc->errCode)); 01404 if (pc->linkStatusCB) { 01405 pc->linkStatusCB(pc->linkStatusCtx, PPPERR_CONNECT, NULL); 01406 } 01407 } 01408 return st; 01409 } 01410 01411 /** 01412 * sifaddr - Config the interface IP addresses and netmask. 01413 * @param pd Interface unit ??? 01414 * @param o Our IP address ??? 01415 * @param h His IP address ??? 01416 * @param m IP subnet mask ??? 01417 * @param ns1 Primary DNS 01418 * @param ns2 Secondary DNS 01419 */ 01420 int 01421 sifaddr( int pd, u32_t o, u32_t h, u32_t m, u32_t ns1, u32_t ns2) 01422 { 01423 PPPControl *pc = &pppControl[pd]; 01424 int st = 1; 01425 01426 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { 01427 st = 0; 01428 PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd)); 01429 } else { 01430 SMEMCPY(&pc->addrs.our_ipaddr, &o, sizeof(o)); 01431 SMEMCPY(&pc->addrs.his_ipaddr, &h, sizeof(h)); 01432 SMEMCPY(&pc->addrs.netmask, &m, sizeof(m)); 01433 SMEMCPY(&pc->addrs.dns1, &ns1, sizeof(ns1)); 01434 SMEMCPY(&pc->addrs.dns2, &ns2, sizeof(ns2)); 01435 } 01436 return st; 01437 } 01438 01439 /** 01440 * cifaddr - Clear the interface IP addresses, and delete routes 01441 * through the interface if possible. 01442 * @param pd Interface unit ??? 01443 * @param o Our IP address ??? 01444 * @param h IP broadcast address ??? 01445 */ 01446 int 01447 cifaddr( int pd, u32_t o, u32_t h) 01448 { 01449 PPPControl *pc = &pppControl[pd]; 01450 int st = 1; 01451 01452 LWIP_UNUSED_ARG(o); 01453 LWIP_UNUSED_ARG(h); 01454 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { 01455 st = 0; 01456 PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd)); 01457 } else { 01458 IP4_ADDR(&pc->addrs.our_ipaddr, 0,0,0,0); 01459 IP4_ADDR(&pc->addrs.his_ipaddr, 0,0,0,0); 01460 IP4_ADDR(&pc->addrs.netmask, 255,255,255,0); 01461 IP4_ADDR(&pc->addrs.dns1, 0,0,0,0); 01462 IP4_ADDR(&pc->addrs.dns2, 0,0,0,0); 01463 } 01464 return st; 01465 } 01466 01467 /* 01468 * sifdefaultroute - assign a default route through the address given. 01469 */ 01470 int 01471 sifdefaultroute(int pd, u32_t l, u32_t g) 01472 { 01473 PPPControl *pc = &pppControl[pd]; 01474 int st = 1; 01475 01476 LWIP_UNUSED_ARG(l); 01477 LWIP_UNUSED_ARG(g); 01478 01479 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { 01480 st = 0; 01481 PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd)); 01482 } else { 01483 netif_set_default(&pc->netif); 01484 } 01485 01486 /* TODO: check how PPP handled the netMask, previously not set by ipSetDefault */ 01487 01488 return st; 01489 } 01490 01491 /* 01492 * cifdefaultroute - delete a default route through the address given. 01493 */ 01494 int 01495 cifdefaultroute(int pd, u32_t l, u32_t g) 01496 { 01497 PPPControl *pc = &pppControl[pd]; 01498 int st = 1; 01499 01500 LWIP_UNUSED_ARG(l); 01501 LWIP_UNUSED_ARG(g); 01502 01503 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { 01504 st = 0; 01505 PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd)); 01506 } else { 01507 netif_set_default(NULL); 01508 } 01509 01510 return st; 01511 } 01512 01513 /**********************************/ 01514 /*** LOCAL FUNCTION DEFINITIONS ***/ 01515 /**********************************/ 01516 01517 #if PPPOS_SUPPORT && PPP_INPROC_OWNTHREAD 01518 /* The main PPP process function. This implements the state machine according 01519 * to section 4 of RFC 1661: The Point-To-Point Protocol. */ 01520 static void 01521 pppInputThread(void *arg) 01522 { 01523 int count; 01524 PPPControlRx *pcrx = arg; 01525 01526 #if !__LWIP_ORIG 01527 do 01528 { 01529 sys_arch_mbox_fetch(&pppMbox, (void**)&pcrx, 0); //Wait indefinitely 01530 #endif 01531 01532 while (lcp_phase[pcrx->pd] != PHASE_DEAD) { 01533 count = sio_read(pcrx->fd, pcrx->rxbuf, PPPOS_RX_BUFSIZE); 01534 if(count > 0) { 01535 pppInProc(pcrx, pcrx->rxbuf, count); 01536 } else { 01537 /* nothing received, give other tasks a chance to run */ 01538 sys_msleep(1); 01539 } 01540 } 01541 #if !__LWIP_ORIG 01542 } while(1); //Never terminates 01543 #endif 01544 } 01545 #endif /* PPPOS_SUPPORT && PPP_INPROC_OWNTHREAD */ 01546 01547 #if PPPOE_SUPPORT 01548 01549 void 01550 pppOverEthernetInitFailed(int pd) 01551 { 01552 PPPControl* pc; 01553 01554 pppHup(pd); 01555 pppStop(pd); 01556 01557 pc = &pppControl[pd]; 01558 pppoe_destroy(&pc->netif); 01559 pc->openFlag = 0; 01560 01561 if(pc->linkStatusCB) { 01562 pc->linkStatusCB(pc->linkStatusCtx, pc->errCode ? pc->errCode : PPPERR_PROTOCOL, NULL); 01563 } 01564 } 01565 01566 static void 01567 pppOverEthernetLinkStatusCB(int pd, int up) 01568 { 01569 if(up) { 01570 PPPDEBUG(LOG_INFO, ("pppOverEthernetLinkStatusCB: unit %d: Connecting\n", pd)); 01571 pppStart(pd); 01572 } else { 01573 pppOverEthernetInitFailed(pd); 01574 } 01575 } 01576 #endif /* PPPOE_SUPPORT */ 01577 01578 struct pbuf * 01579 pppSingleBuf(struct pbuf *p) 01580 { 01581 struct pbuf *q, *b; 01582 u_char *pl; 01583 01584 if(p->tot_len == p->len) { 01585 return p; 01586 } 01587 01588 q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); 01589 if(!q) { 01590 PPPDEBUG(LOG_ERR, 01591 ("pppSingleBuf: unable to alloc new buf (%d)\n", p->tot_len)); 01592 return p; /* live dangerously */ 01593 } 01594 01595 for(b = p, pl = q->payload; b != NULL; b = b->next) { 01596 MEMCPY(pl, b->payload, b->len); 01597 pl += b->len; 01598 } 01599 01600 pbuf_free(p); 01601 01602 return q; 01603 } 01604 01605 struct pppInputHeader { 01606 int unit; 01607 u16_t proto; 01608 }; 01609 01610 /* 01611 * Pass the processed input packet to the appropriate handler. 01612 * This function and all handlers run in the context of the tcpip_thread 01613 */ 01614 static void 01615 pppInput(void *arg) 01616 { 01617 struct pbuf *nb = (struct pbuf *)arg; 01618 u16_t protocol; 01619 int pd; 01620 01621 pd = ((struct pppInputHeader *)nb->payload)->unit; 01622 protocol = ((struct pppInputHeader *)nb->payload)->proto; 01623 01624 if(pbuf_header(nb, -(int)sizeof(struct pppInputHeader))) { 01625 LWIP_ASSERT("pbuf_header failed\n", 0); 01626 goto drop; 01627 } 01628 01629 LINK_STATS_INC(link.recv); 01630 snmp_inc_ifinucastpkts(&pppControl[pd].netif); 01631 snmp_add_ifinoctets(&pppControl[pd].netif, nb->tot_len); 01632 01633 /* 01634 * Toss all non-LCP packets unless LCP is OPEN. 01635 * Until we get past the authentication phase, toss all packets 01636 * except LCP, LQR and authentication packets. 01637 */ 01638 if((lcp_phase[pd] <= PHASE_AUTHENTICATE) && (protocol != PPP_LCP)) { 01639 if(!((protocol == PPP_LQR) || (protocol == PPP_PAP) || (protocol == PPP_CHAP)) || 01640 (lcp_phase[pd] != PHASE_AUTHENTICATE)) { 01641 PPPDEBUG(LOG_INFO, ("pppInput: discarding proto 0x%"X16_F" in phase %d\n", protocol, lcp_phase[pd])); 01642 goto drop; 01643 } 01644 } 01645 01646 switch(protocol) { 01647 case PPP_VJC_COMP: /* VJ compressed TCP */ 01648 #if PPPOS_SUPPORT && VJ_SUPPORT 01649 PPPDEBUG(LOG_INFO, ("pppInput[%d]: vj_comp in pbuf len=%d\n", pd, nb->len)); 01650 /* 01651 * Clip off the VJ header and prepend the rebuilt TCP/IP header and 01652 * pass the result to IP. 01653 */ 01654 if ((vj_uncompress_tcp(&nb, &pppControl[pd].vjComp) >= 0) && (pppControl[pd].netif.input)) { 01655 pppControl[pd].netif.input(nb, &pppControl[pd].netif); 01656 return; 01657 } 01658 /* Something's wrong so drop it. */ 01659 PPPDEBUG(LOG_WARNING, ("pppInput[%d]: Dropping VJ compressed\n", pd)); 01660 #else /* PPPOS_SUPPORT && VJ_SUPPORT */ 01661 /* No handler for this protocol so drop the packet. */ 01662 PPPDEBUG(LOG_INFO, ("pppInput[%d]: drop VJ Comp in %d:%s\n", pd, nb->len, nb->payload)); 01663 #endif /* PPPOS_SUPPORT && VJ_SUPPORT */ 01664 break; 01665 01666 case PPP_VJC_UNCOMP: /* VJ uncompressed TCP */ 01667 #if PPPOS_SUPPORT && VJ_SUPPORT 01668 PPPDEBUG(LOG_INFO, ("pppInput[%d]: vj_un in pbuf len=%d\n", pd, nb->len)); 01669 /* 01670 * Process the TCP/IP header for VJ header compression and then pass 01671 * the packet to IP. 01672 */ 01673 if ((vj_uncompress_uncomp(nb, &pppControl[pd].vjComp) >= 0) && pppControl[pd].netif.input) { 01674 pppControl[pd].netif.input(nb, &pppControl[pd].netif); 01675 return; 01676 } 01677 /* Something's wrong so drop it. */ 01678 PPPDEBUG(LOG_WARNING, ("pppInput[%d]: Dropping VJ uncompressed\n", pd)); 01679 #else /* PPPOS_SUPPORT && VJ_SUPPORT */ 01680 /* No handler for this protocol so drop the packet. */ 01681 PPPDEBUG(LOG_INFO, 01682 ("pppInput[%d]: drop VJ UnComp in %d:.*H\n", 01683 pd, nb->len, LWIP_MIN(nb->len * 2, 40), nb->payload)); 01684 #endif /* PPPOS_SUPPORT && VJ_SUPPORT */ 01685 break; 01686 01687 case PPP_IP: /* Internet Protocol */ 01688 PPPDEBUG(LOG_INFO, ("pppInput[%d]: ip in pbuf len=%d\n", pd, nb->len)); 01689 if (pppControl[pd].netif.input) { 01690 pppControl[pd].netif.input(nb, &pppControl[pd].netif); 01691 return; 01692 } 01693 break; 01694 01695 default: { 01696 struct protent *protp; 01697 int i; 01698 01699 /* 01700 * Upcall the proper protocol input routine. 01701 */ 01702 for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) { 01703 if (protp->protocol == protocol && protp->enabled_flag) { 01704 PPPDEBUG(LOG_INFO, ("pppInput[%d]: %s len=%d\n", pd, protp->name, nb->len)); 01705 nb = pppSingleBuf(nb); 01706 (*protp->input)(pd, nb->payload, nb->len); 01707 PPPDEBUG(LOG_DETAIL, ("pppInput[%d]: packet processed\n", pd)); 01708 goto out; 01709 } 01710 } 01711 01712 /* No handler for this protocol so reject the packet. */ 01713 PPPDEBUG(LOG_INFO, ("pppInput[%d]: rejecting unsupported proto 0x%"X16_F" len=%d\n", pd, protocol, nb->len)); 01714 if (pbuf_header(nb, sizeof(protocol))) { 01715 LWIP_ASSERT("pbuf_header failed\n", 0); 01716 goto drop; 01717 } 01718 #if BYTE_ORDER == LITTLE_ENDIAN 01719 protocol = htons(protocol); 01720 #endif /* BYTE_ORDER == LITTLE_ENDIAN */ 01721 SMEMCPY(nb->payload, &protocol, sizeof(protocol)); 01722 lcp_sprotrej(pd, nb->payload, nb->len); 01723 } 01724 break; 01725 } 01726 01727 drop: 01728 LINK_STATS_INC(link.drop); 01729 snmp_inc_ifindiscards(&pppControl[pd].netif); 01730 01731 out: 01732 pbuf_free(nb); 01733 return; 01734 } 01735 01736 #if PPPOS_SUPPORT 01737 /* 01738 * Drop the input packet. 01739 */ 01740 static void 01741 pppDrop(PPPControlRx *pcrx) 01742 { 01743 if (pcrx->inHead != NULL) { 01744 #if 0 01745 PPPDEBUG(LOG_INFO, ("pppDrop: %d:%.*H\n", pcrx->inHead->len, min(60, pcrx->inHead->len * 2), pcrx->inHead->payload)); 01746 #endif 01747 PPPDEBUG(LOG_INFO, ("pppDrop: pbuf len=%d, addr %p\n", pcrx->inHead->len, (void*)pcrx->inHead)); 01748 if (pcrx->inTail && (pcrx->inTail != pcrx->inHead)) { 01749 pbuf_free(pcrx->inTail); 01750 } 01751 pbuf_free(pcrx->inHead); 01752 pcrx->inHead = NULL; 01753 pcrx->inTail = NULL; 01754 } 01755 #if VJ_SUPPORT 01756 vj_uncompress_err(&pppControl[pcrx->pd].vjComp); 01757 #endif /* VJ_SUPPORT */ 01758 01759 LINK_STATS_INC(link.drop); 01760 snmp_inc_ifindiscards(&pppControl[pcrx->pd].netif); 01761 } 01762 01763 /** Pass received raw characters to PPPoS to be decoded. This function is 01764 * thread-safe and can be called from a dedicated RX-thread or from a main-loop. 01765 * 01766 * @param pd PPP descriptor index, returned by pppOpen() 01767 * @param data received data 01768 * @param len length of received data 01769 */ 01770 void 01771 pppos_input(int pd, u_char* data, int len) 01772 { 01773 pppInProc(&pppControl[pd].rx, data, len); 01774 } 01775 01776 /** 01777 * Process a received octet string. 01778 */ 01779 static void 01780 pppInProc(PPPControlRx *pcrx, u_char *s, int l) 01781 { 01782 struct pbuf *nextNBuf; 01783 u_char curChar; 01784 u_char escaped; 01785 SYS_ARCH_DECL_PROTECT(lev); 01786 01787 PPPDEBUG(LOG_DEBUG, ("pppInProc[%d]: got %d bytes\n", pcrx->pd, l)); 01788 while (l-- > 0) { 01789 curChar = *s++; 01790 01791 SYS_ARCH_PROTECT(lev); 01792 escaped = ESCAPE_P(pcrx->inACCM, curChar); 01793 SYS_ARCH_UNPROTECT(lev); 01794 /* Handle special characters. */ 01795 if (escaped) { 01796 /* Check for escape sequences. */ 01797 /* XXX Note that this does not handle an escaped 0x5d character which 01798 * would appear as an escape character. Since this is an ASCII ']' 01799 * and there is no reason that I know of to escape it, I won't complicate 01800 * the code to handle this case. GLL */ 01801 if (curChar == PPP_ESCAPE) { 01802 pcrx->inEscaped = 1; 01803 /* Check for the flag character. */ 01804 } else if (curChar == PPP_FLAG) { 01805 /* If this is just an extra flag character, ignore it. */ 01806 if (pcrx->inState <= PDADDRESS) { 01807 /* ignore it */; 01808 /* If we haven't received the packet header, drop what has come in. */ 01809 } else if (pcrx->inState < PDDATA) { 01810 PPPDEBUG(LOG_WARNING, 01811 ("pppInProc[%d]: Dropping incomplete packet %d\n", 01812 pcrx->pd, pcrx->inState)); 01813 LINK_STATS_INC(link.lenerr); 01814 pppDrop(pcrx); 01815 /* If the fcs is invalid, drop the packet. */ 01816 } else if (pcrx->inFCS != PPP_GOODFCS) { 01817 PPPDEBUG(LOG_INFO, 01818 ("pppInProc[%d]: Dropping bad fcs 0x%"X16_F" proto=0x%"X16_F"\n", 01819 pcrx->pd, pcrx->inFCS, pcrx->inProtocol)); 01820 /* Note: If you get lots of these, check for UART frame errors or try different baud rate */ 01821 LINK_STATS_INC(link.chkerr); 01822 pppDrop(pcrx); 01823 /* Otherwise it's a good packet so pass it on. */ 01824 } else { 01825 struct pbuf *inp; 01826 /* Trim off the checksum. */ 01827 if(pcrx->inTail->len >= 2) { 01828 pcrx->inTail->len -= 2; 01829 01830 pcrx->inTail->tot_len = pcrx->inTail->len; 01831 if (pcrx->inTail != pcrx->inHead) { 01832 pbuf_cat(pcrx->inHead, pcrx->inTail); 01833 } 01834 } else { 01835 pcrx->inTail->tot_len = pcrx->inTail->len; 01836 if (pcrx->inTail != pcrx->inHead) { 01837 pbuf_cat(pcrx->inHead, pcrx->inTail); 01838 } 01839 01840 pbuf_realloc(pcrx->inHead, pcrx->inHead->tot_len - 2); 01841 } 01842 01843 /* Dispatch the packet thereby consuming it. */ 01844 inp = pcrx->inHead; 01845 /* Packet consumed, release our references. */ 01846 pcrx->inHead = NULL; 01847 pcrx->inTail = NULL; 01848 #if PPP_INPROC_MULTITHREADED 01849 if(tcpip_callback_with_block(pppInput, inp, 0) != ERR_OK) { 01850 PPPDEBUG(LOG_ERR, ("pppInProc[%d]: tcpip_callback() failed, dropping packet\n", pcrx->pd)); 01851 pbuf_free(inp); 01852 LINK_STATS_INC(link.drop); 01853 snmp_inc_ifindiscards(&pppControl[pcrx->pd].netif); 01854 } 01855 #else /* PPP_INPROC_MULTITHREADED */ 01856 pppInput(inp); 01857 #endif /* PPP_INPROC_MULTITHREADED */ 01858 } 01859 01860 /* Prepare for a new packet. */ 01861 pcrx->inFCS = PPP_INITFCS; 01862 pcrx->inState = PDADDRESS; 01863 pcrx->inEscaped = 0; 01864 /* Other characters are usually control characters that may have 01865 * been inserted by the physical layer so here we just drop them. */ 01866 } else { 01867 PPPDEBUG(LOG_WARNING, 01868 ("pppInProc[%d]: Dropping ACCM char <%d>\n", pcrx->pd, curChar)); 01869 } 01870 /* Process other characters. */ 01871 } else { 01872 /* Unencode escaped characters. */ 01873 if (pcrx->inEscaped) { 01874 pcrx->inEscaped = 0; 01875 curChar ^= PPP_TRANS; 01876 } 01877 01878 /* Process character relative to current state. */ 01879 switch(pcrx->inState) { 01880 case PDIDLE: /* Idle state - waiting. */ 01881 /* Drop the character if it's not 0xff 01882 * we would have processed a flag character above. */ 01883 if (curChar != PPP_ALLSTATIONS) { 01884 break; 01885 } 01886 01887 /* Fall through */ 01888 case PDSTART: /* Process start flag. */ 01889 /* Prepare for a new packet. */ 01890 pcrx->inFCS = PPP_INITFCS; 01891 01892 /* Fall through */ 01893 case PDADDRESS: /* Process address field. */ 01894 if (curChar == PPP_ALLSTATIONS) { 01895 pcrx->inState = PDCONTROL; 01896 break; 01897 } 01898 /* Else assume compressed address and control fields so 01899 * fall through to get the protocol... */ 01900 case PDCONTROL: /* Process control field. */ 01901 /* If we don't get a valid control code, restart. */ 01902 if (curChar == PPP_UI) { 01903 pcrx->inState = PDPROTOCOL1; 01904 break; 01905 } 01906 #if 0 01907 else { 01908 PPPDEBUG(LOG_WARNING, 01909 ("pppInProc[%d]: Invalid control <%d>\n", pcrx->pd, curChar)); 01910 pcrx->inState = PDSTART; 01911 } 01912 #endif 01913 case PDPROTOCOL1: /* Process protocol field 1. */ 01914 /* If the lower bit is set, this is the end of the protocol 01915 * field. */ 01916 if (curChar & 1) { 01917 pcrx->inProtocol = curChar; 01918 pcrx->inState = PDDATA; 01919 } else { 01920 pcrx->inProtocol = (u_int)curChar << 8; 01921 pcrx->inState = PDPROTOCOL2; 01922 } 01923 break; 01924 case PDPROTOCOL2: /* Process protocol field 2. */ 01925 pcrx->inProtocol |= curChar; 01926 pcrx->inState = PDDATA; 01927 break; 01928 case PDDATA: /* Process data byte. */ 01929 /* Make space to receive processed data. */ 01930 if (pcrx->inTail == NULL || pcrx->inTail->len == PBUF_POOL_BUFSIZE) { 01931 if (pcrx->inTail != NULL) { 01932 pcrx->inTail->tot_len = pcrx->inTail->len; 01933 if (pcrx->inTail != pcrx->inHead) { 01934 pbuf_cat(pcrx->inHead, pcrx->inTail); 01935 /* give up the inTail reference now */ 01936 pcrx->inTail = NULL; 01937 } 01938 } 01939 /* If we haven't started a packet, we need a packet header. */ 01940 nextNBuf = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); 01941 if (nextNBuf == NULL) { 01942 /* No free buffers. Drop the input packet and let the 01943 * higher layers deal with it. Continue processing 01944 * the received pbuf chain in case a new packet starts. */ 01945 PPPDEBUG(LOG_ERR, ("pppInProc[%d]: NO FREE MBUFS!\n", pcrx->pd)); 01946 LINK_STATS_INC(link.memerr); 01947 pppDrop(pcrx); 01948 pcrx->inState = PDSTART; /* Wait for flag sequence. */ 01949 break; 01950 } 01951 if (pcrx->inHead == NULL) { 01952 struct pppInputHeader *pih = nextNBuf->payload; 01953 01954 pih->unit = pcrx->pd; 01955 pih->proto = pcrx->inProtocol; 01956 01957 nextNBuf->len += sizeof(*pih); 01958 01959 pcrx->inHead = nextNBuf; 01960 } 01961 pcrx->inTail = nextNBuf; 01962 } 01963 /* Load character into buffer. */ 01964 ((u_char*)pcrx->inTail->payload)[pcrx->inTail->len++] = curChar; 01965 break; 01966 } 01967 01968 /* update the frame check sequence number. */ 01969 pcrx->inFCS = PPP_FCS(pcrx->inFCS, curChar); 01970 } 01971 } /* while (l-- > 0), all bytes processed */ 01972 01973 avRandomize(); 01974 } 01975 #endif /* PPPOS_SUPPORT */ 01976 01977 #if PPPOE_SUPPORT 01978 void 01979 pppInProcOverEthernet(int pd, struct pbuf *pb) 01980 { 01981 struct pppInputHeader *pih; 01982 u16_t inProtocol; 01983 01984 if(pb->len < sizeof(inProtocol)) { 01985 PPPDEBUG(LOG_ERR, ("pppInProcOverEthernet: too small for protocol field\n")); 01986 goto drop; 01987 } 01988 01989 inProtocol = (((u8_t *)pb->payload)[0] << 8) | ((u8_t*)pb->payload)[1]; 01990 01991 /* make room for pppInputHeader - should not fail */ 01992 if (pbuf_header(pb, sizeof(*pih) - sizeof(inProtocol)) != 0) { 01993 PPPDEBUG(LOG_ERR, ("pppInProcOverEthernet: could not allocate room for header\n")); 01994 goto drop; 01995 } 01996 01997 pih = pb->payload; 01998 01999 pih->unit = pd; 02000 pih->proto = inProtocol; 02001 02002 /* Dispatch the packet thereby consuming it. */ 02003 pppInput(pb); 02004 return; 02005 02006 drop: 02007 LINK_STATS_INC(link.drop); 02008 snmp_inc_ifindiscards(&pppControl[pd].netif); 02009 pbuf_free(pb); 02010 return; 02011 } 02012 #endif /* PPPOE_SUPPORT */ 02013 02014 #if LWIP_NETIF_STATUS_CALLBACK 02015 /** Set the status callback of a PPP's netif 02016 * 02017 * @param pd The PPP descriptor returned by pppOpen() 02018 * @param status_callback pointer to the status callback function 02019 * 02020 * @see netif_set_status_callback 02021 */ 02022 void 02023 ppp_set_netif_statuscallback(int pd, netif_status_callback_fn status_callback) 02024 { 02025 netif_set_status_callback(&pppControl[pd].netif, status_callback); 02026 } 02027 #endif /* LWIP_NETIF_STATUS_CALLBACK */ 02028 02029 #if LWIP_NETIF_LINK_CALLBACK 02030 /** Set the link callback of a PPP's netif 02031 * 02032 * @param pd The PPP descriptor returned by pppOpen() 02033 * @param link_callback pointer to the link callback function 02034 * 02035 * @see netif_set_link_callback 02036 */ 02037 void 02038 ppp_set_netif_linkcallback(int pd, netif_status_callback_fn link_callback) 02039 { 02040 netif_set_link_callback(&pppControl[pd].netif, link_callback); 02041 } 02042 #endif /* LWIP_NETIF_LINK_CALLBACK */ 02043 02044 #endif /* PPP_SUPPORT */
Generated on Tue Jul 12 2022 15:12:16 by 1.7.2