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