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