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