Darran Shepherd
/
AutoIpNetStack
Net stack with AutoIP enabled
Embed:
(wiki syntax)
Show/hide line numbers
ppp.c
00001 /***************************************************************************** 00002 * ppp.c - Network Point to Point Protocol program file. 00003 * 00004 * Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. 00005 * portions Copyright (c) 1997 by Global Election Systems Inc. 00006 * 00007 * The authors hereby grant permission to use, copy, modify, distribute, 00008 * and license this software and its documentation for any purpose, provided 00009 * that existing copyright notices are retained in all copies and that this 00010 * notice and the following disclaimer are included verbatim in any 00011 * distributions. No written agreement, license, or royalty fee is required 00012 * for any of the authorized uses. 00013 * 00014 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR 00015 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00016 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 00017 * IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00018 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 00019 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00020 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00021 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00022 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 00023 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00024 * 00025 ****************************************************************************** 00026 * REVISION HISTORY 00027 * 00028 * 03-01-01 Marc Boucher <marc@mbsi.ca> 00029 * Ported to lwIP. 00030 * 97-11-05 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc. 00031 * Original. 00032 *****************************************************************************/ 00033 00034 /* 00035 * ppp_defs.h - PPP definitions. 00036 * 00037 * if_pppvar.h - private structures and declarations for PPP. 00038 * 00039 * Copyright (c) 1994 The Australian National University. 00040 * All rights reserved. 00041 * 00042 * Permission to use, copy, modify, and distribute this software and its 00043 * documentation is hereby granted, provided that the above copyright 00044 * notice appears in all copies. This software is provided without any 00045 * warranty, express or implied. The Australian National University 00046 * makes no representations about the suitability of this software for 00047 * any purpose. 00048 * 00049 * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY 00050 * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 00051 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 00052 * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY 00053 * OF SUCH DAMAGE. 00054 * 00055 * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, 00056 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 00057 * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 00058 * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO 00059 * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, 00060 * OR MODIFICATIONS. 00061 */ 00062 00063 /* 00064 * if_ppp.h - Point-to-Point Protocol definitions. 00065 * 00066 * Copyright (c) 1989 Carnegie Mellon University. 00067 * All rights reserved. 00068 * 00069 * Redistribution and use in source and binary forms are permitted 00070 * provided that the above copyright notice and this paragraph are 00071 * duplicated in all such forms and that any documentation, 00072 * advertising materials, and other materials related to such 00073 * distribution and use acknowledge that the software was developed 00074 * by Carnegie Mellon University. The name of the 00075 * University may not be used to endorse or promote products derived 00076 * from this software without specific prior written permission. 00077 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 00078 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 00079 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00080 */ 00081 00082 #include "lwip/opt.h" 00083 00084 #if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ 00085 00086 #include "lwip/ip.h" /* for ip_input() */ 00087 00088 #include "ppp.h" 00089 #include "pppdebug.h" 00090 00091 #include "randm.h" 00092 #include "fsm.h" 00093 #if PAP_SUPPORT 00094 #include "pap.h" 00095 #endif /* PAP_SUPPORT */ 00096 #if CHAP_SUPPORT 00097 #include "chap.h" 00098 #endif /* CHAP_SUPPORT */ 00099 #include "ipcp.h" 00100 #include "lcp.h" 00101 #include "magic.h" 00102 #include "auth.h" 00103 #if VJ_SUPPORT 00104 #include "vj.h" 00105 #endif /* VJ_SUPPORT */ 00106 #if PPPOE_SUPPORT 00107 #include "netif/ppp_oe.h" 00108 #endif /* PPPOE_SUPPORT */ 00109 00110 #include "lwip/tcpip.h" 00111 #include "lwip/api.h" 00112 #include "lwip/snmp.h" 00113 00114 #include <string.h> 00115 00116 /*************************/ 00117 /*** LOCAL DEFINITIONS ***/ 00118 /*************************/ 00119 00120 /** PPP_INPROC_MULTITHREADED==1 call pppInput using tcpip_callback(). 00121 * Set this to 0 if pppInProc is called inside tcpip_thread or with NO_SYS==1. 00122 * Default is 1 for NO_SYS==0 (multithreaded) and 0 for NO_SYS==1 (single-threaded). 00123 */ 00124 #ifndef PPP_INPROC_MULTITHREADED 00125 #define PPP_INPROC_MULTITHREADED (NO_SYS==0) 00126 #endif 00127 00128 /** PPP_INPROC_OWNTHREAD==1: start a dedicated RX thread per PPP session. 00129 * Default is 0: call pppos_input() for received raw characters, charcater 00130 * reception is up to the port */ 00131 #ifndef PPP_INPROC_OWNTHREAD 00132 #define PPP_INPROC_OWNTHREAD PPP_INPROC_MULTITHREADED 00133 #endif 00134 00135 #if PPP_INPROC_OWNTHREAD && !PPP_INPROC_MULTITHREADED 00136 #error "PPP_INPROC_OWNTHREAD needs PPP_INPROC_MULTITHREADED==1" 00137 #endif 00138 00139 /* 00140 * The basic PPP frame. 00141 */ 00142 #define PPP_ADDRESS(p) (((u_char *)(p))[0]) 00143 #define PPP_CONTROL(p) (((u_char *)(p))[1]) 00144 #define PPP_PROTOCOL(p) ((((u_char *)(p))[2] << 8) + ((u_char *)(p))[3]) 00145 00146 /* PPP packet parser states. Current state indicates operation yet to be 00147 * completed. */ 00148 typedef enum { 00149 PDIDLE = 0, /* Idle state - waiting. */ 00150 PDSTART, /* Process start flag. */ 00151 PDADDRESS, /* Process address field. */ 00152 PDCONTROL, /* Process control field. */ 00153 PDPROTOCOL1, /* Process protocol field 1. */ 00154 PDPROTOCOL2, /* Process protocol field 2. */ 00155 PDDATA /* Process data byte. */ 00156 } PPPDevStates; 00157 00158 #define ESCAPE_P(accm, c) ((accm)[(c) >> 3] & pppACCMMask[c & 0x07]) 00159 00160 /************************/ 00161 /*** LOCAL DATA TYPES ***/ 00162 /************************/ 00163 00164 /** RX buffer size: this may be configured smaller! */ 00165 #ifndef PPPOS_RX_BUFSIZE 00166 #define PPPOS_RX_BUFSIZE (PPP_MRU + PPP_HDRLEN) 00167 #endif 00168 00169 typedef struct PPPControlRx_s { 00170 /** unit number / ppp descriptor */ 00171 int pd; 00172 /** the rx file descriptor */ 00173 sio_fd_t fd; 00174 /** receive buffer - encoded data is stored here */ 00175 u_char rxbuf[PPPOS_RX_BUFSIZE]; 00176 00177 /* The input packet. */ 00178 struct pbuf *inHead, *inTail; 00179 00180 #if PPPOS_SUPPORT 00181 u16_t inProtocol; /* The input protocol code. */ 00182 u16_t inFCS; /* Input Frame Check Sequence value. */ 00183 #endif /* PPPOS_SUPPORT */ 00184 PPPDevStates inState; /* The input process state. */ 00185 char inEscaped; /* Escape next character. */ 00186 ext_accm inACCM; /* Async-Ctl-Char-Map for input. */ 00187 } PPPControlRx; 00188 00189 /* 00190 * PPP interface control block. 00191 */ 00192 typedef struct PPPControl_s { 00193 PPPControlRx rx; 00194 char openFlag; /* True when in use. */ 00195 #if PPPOE_SUPPORT 00196 struct netif *ethif; 00197 struct pppoe_softc *pppoe_sc; 00198 #endif /* PPPOE_SUPPORT */ 00199 int if_up; /* True when the interface is up. */ 00200 int errCode; /* Code indicating why interface is down. */ 00201 #if PPPOS_SUPPORT 00202 sio_fd_t fd; /* File device ID of port. */ 00203 #endif /* PPPOS_SUPPORT */ 00204 u16_t mtu; /* Peer's mru */ 00205 int pcomp; /* Does peer accept protocol compression? */ 00206 int accomp; /* Does peer accept addr/ctl compression? */ 00207 u_long lastXMit; /* Time of last transmission. */ 00208 ext_accm outACCM; /* Async-Ctl-Char-Map for output. */ 00209 #if PPPOS_SUPPORT && VJ_SUPPORT 00210 int vjEnabled; /* Flag indicating VJ compression enabled. */ 00211 struct vjcompress vjComp; /* Van Jacobson compression header. */ 00212 #endif /* PPPOS_SUPPORT && VJ_SUPPORT */ 00213 00214 struct netif netif; 00215 00216 struct ppp_addrs addrs; 00217 00218 void (*linkStatusCB)(void *ctx, int errCode, void *arg); 00219 void *linkStatusCtx; 00220 00221 } PPPControl; 00222 00223 00224 /* 00225 * Ioctl definitions. 00226 */ 00227 00228 struct npioctl { 00229 int protocol; /* PPP procotol, e.g. PPP_IP */ 00230 enum NPmode mode; 00231 }; 00232 00233 00234 00235 /***********************************/ 00236 /*** LOCAL FUNCTION DECLARATIONS ***/ 00237 /***********************************/ 00238 #if PPPOS_SUPPORT 00239 #if PPP_INPROC_OWNTHREAD 00240 static void pppInputThread(void *arg); 00241 #endif /* PPP_INPROC_OWNTHREAD */ 00242 static void pppDrop(PPPControlRx *pcrx); 00243 static void pppInProc(PPPControlRx *pcrx, u_char *s, int l); 00244 #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 = 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 #if PPPOE_SUPPORT 00452 pppoe_init(); 00453 #endif /* PPPOE_SUPPORT */ 00454 } 00455 00456 void 00457 pppSetAuth(enum pppAuthType authType, const char *user, const char *passwd) 00458 { 00459 switch(authType) { 00460 case PPPAUTHTYPE_NONE: 00461 default: 00462 #ifdef LWIP_PPP_STRICT_PAP_REJECT 00463 ppp_settings.refuse_pap = 1; 00464 #else /* LWIP_PPP_STRICT_PAP_REJECT */ 00465 /* some providers request pap and accept an empty login/pw */ 00466 ppp_settings.refuse_pap = 0; 00467 #endif /* LWIP_PPP_STRICT_PAP_REJECT */ 00468 ppp_settings.refuse_chap = 1; 00469 break; 00470 00471 case PPPAUTHTYPE_ANY: 00472 /* Warning: Using PPPAUTHTYPE_ANY might have security consequences. 00473 * RFC 1994 says: 00474 * 00475 * In practice, within or associated with each PPP server, there is a 00476 * database which associates "user" names with authentication 00477 * information ("secrets"). It is not anticipated that a particular 00478 * named user would be authenticated by multiple methods. This would 00479 * make the user vulnerable to attacks which negotiate the least secure 00480 * method from among a set (such as PAP rather than CHAP). If the same 00481 * secret was used, PAP would reveal the secret to be used later with 00482 * CHAP. 00483 * 00484 * Instead, for each user name there should be an indication of exactly 00485 * one method used to authenticate that user name. If a user needs to 00486 * make use of different authentication methods under different 00487 * circumstances, then distinct user names SHOULD be employed, each of 00488 * which identifies exactly one authentication method. 00489 * 00490 */ 00491 ppp_settings.refuse_pap = 0; 00492 ppp_settings.refuse_chap = 0; 00493 break; 00494 00495 case PPPAUTHTYPE_PAP: 00496 ppp_settings.refuse_pap = 0; 00497 ppp_settings.refuse_chap = 1; 00498 break; 00499 00500 case PPPAUTHTYPE_CHAP: 00501 ppp_settings.refuse_pap = 1; 00502 ppp_settings.refuse_chap = 0; 00503 break; 00504 } 00505 00506 if(user) { 00507 strncpy(ppp_settings.user, user, sizeof(ppp_settings.user)-1); 00508 ppp_settings.user[sizeof(ppp_settings.user)-1] = '\0'; 00509 } else { 00510 ppp_settings.user[0] = '\0'; 00511 } 00512 00513 if(passwd) { 00514 strncpy(ppp_settings.passwd, passwd, sizeof(ppp_settings.passwd)-1); 00515 ppp_settings.passwd[sizeof(ppp_settings.passwd)-1] = '\0'; 00516 } else { 00517 ppp_settings.passwd[0] = '\0'; 00518 } 00519 } 00520 00521 #if PPPOS_SUPPORT 00522 /** Open a new PPP connection using the given I/O device. 00523 * This initializes the PPP control block but does not 00524 * attempt to negotiate the LCP session. If this port 00525 * connects to a modem, the modem connection must be 00526 * established before calling this. 00527 * Return a new PPP connection descriptor on success or 00528 * an error code (negative) on failure. 00529 * 00530 * pppOpen() is directly defined to this function. 00531 */ 00532 int 00533 pppOverSerialOpen(sio_fd_t fd, void (*linkStatusCB)(void *ctx, int errCode, void *arg), void *linkStatusCtx) 00534 { 00535 PPPControl *pc; 00536 int pd; 00537 00538 if (linkStatusCB == NULL) { 00539 /* PPP is single-threaded: without a callback, 00540 * there is no way to know when the link is up. */ 00541 return PPPERR_PARAM; 00542 } 00543 00544 /* Find a free PPP session descriptor. */ 00545 for (pd = 0; pd < NUM_PPP && pppControl[pd].openFlag != 0; pd++); 00546 00547 if (pd >= NUM_PPP) { 00548 pd = PPPERR_OPEN; 00549 } else { 00550 pc = &pppControl[pd]; 00551 /* @todo: is this correct or do I overwrite something? */ 00552 memset(pc, 0, sizeof(PPPControl)); 00553 pc->rx.pd = pd; 00554 pc->rx.fd = fd; 00555 00556 pc->openFlag = 1; 00557 pc->fd = fd; 00558 00559 #if VJ_SUPPORT 00560 vj_compress_init(&pc->vjComp); 00561 #endif /* VJ_SUPPORT */ 00562 00563 /* 00564 * Default the in and out accm so that escape and flag characters 00565 * are always escaped. 00566 */ 00567 pc->rx.inACCM[15] = 0x60; /* no need to protect since RX is not running */ 00568 pc->outACCM[15] = 0x60; 00569 00570 pc->linkStatusCB = linkStatusCB; 00571 pc->linkStatusCtx = linkStatusCtx; 00572 00573 /* 00574 * Start the connection and handle incoming events (packet or timeout). 00575 */ 00576 PPPDEBUG(LOG_INFO, ("pppOverSerialOpen: unit %d: Connecting\n", pd)); 00577 pppStart(pd); 00578 #if PPP_INPROC_OWNTHREAD 00579 sys_thread_new(PPP_THREAD_NAME, pppInputThread, (void*)&pc->rx, PPP_THREAD_STACKSIZE, PPP_THREAD_PRIO); 00580 #endif 00581 } 00582 00583 return pd; 00584 } 00585 #endif /* PPPOS_SUPPORT */ 00586 00587 #if PPPOE_SUPPORT 00588 static void pppOverEthernetLinkStatusCB(int pd, int up); 00589 00590 void 00591 pppOverEthernetClose(int pd) 00592 { 00593 PPPControl* pc = &pppControl[pd]; 00594 00595 /* *TJL* There's no lcp_deinit */ 00596 lcp_close(pd, NULL); 00597 00598 pppoe_destroy(&pc->netif); 00599 } 00600 00601 int pppOverEthernetOpen(struct netif *ethif, const char *service_name, const char *concentrator_name, void (*linkStatusCB)(void *ctx, int errCode, void *arg), void *linkStatusCtx) 00602 { 00603 PPPControl *pc; 00604 int pd; 00605 00606 LWIP_UNUSED_ARG(service_name); 00607 LWIP_UNUSED_ARG(concentrator_name); 00608 00609 if (linkStatusCB == NULL) { 00610 /* PPP is single-threaded: without a callback, 00611 * there is no way to know when the link is up. */ 00612 return PPPERR_PARAM; 00613 } 00614 00615 /* Find a free PPP session descriptor. Critical region? */ 00616 for (pd = 0; pd < NUM_PPP && pppControl[pd].openFlag != 0; pd++); 00617 if (pd >= NUM_PPP) { 00618 pd = PPPERR_OPEN; 00619 } else { 00620 pc = &pppControl[pd]; 00621 memset(pc, 0, sizeof(PPPControl)); 00622 pc->openFlag = 1; 00623 pc->ethif = ethif; 00624 00625 pc->linkStatusCB = linkStatusCB; 00626 pc->linkStatusCtx = linkStatusCtx; 00627 00628 lcp_wantoptions[pd].mru = PPPOE_MAXMTU; 00629 lcp_wantoptions[pd].neg_asyncmap = 0; 00630 lcp_wantoptions[pd].neg_pcompression = 0; 00631 lcp_wantoptions[pd].neg_accompression = 0; 00632 00633 lcp_allowoptions[pd].mru = PPPOE_MAXMTU; 00634 lcp_allowoptions[pd].neg_asyncmap = 0; 00635 lcp_allowoptions[pd].neg_pcompression = 0; 00636 lcp_allowoptions[pd].neg_accompression = 0; 00637 00638 if(pppoe_create(ethif, pd, pppOverEthernetLinkStatusCB, &pc->pppoe_sc) != ERR_OK) { 00639 pc->openFlag = 0; 00640 return PPPERR_OPEN; 00641 } 00642 00643 pppoe_connect(pc->pppoe_sc); 00644 } 00645 00646 return pd; 00647 } 00648 #endif /* PPPOE_SUPPORT */ 00649 00650 00651 /* Close a PPP connection and release the descriptor. 00652 * Any outstanding packets in the queues are dropped. 00653 * Return 0 on success, an error code on failure. */ 00654 int 00655 pppClose(int pd) 00656 { 00657 PPPControl *pc = &pppControl[pd]; 00658 int st = 0; 00659 00660 PPPDEBUG(LOG_DEBUG, ("pppClose() called\n")); 00661 00662 /* Disconnect */ 00663 #if PPPOE_SUPPORT 00664 if(pc->ethif) { 00665 PPPDEBUG(LOG_DEBUG, ("pppClose: unit %d kill_link -> pppStop\n", pd)); 00666 pc->errCode = PPPERR_USER; 00667 /* This will leave us at PHASE_DEAD. */ 00668 pppStop(pd); 00669 } else 00670 #endif /* PPPOE_SUPPORT */ 00671 { 00672 #if PPPOS_SUPPORT 00673 PPPDEBUG(LOG_DEBUG, ("pppClose: unit %d kill_link -> pppStop\n", pd)); 00674 pc->errCode = PPPERR_USER; 00675 /* This will leave us at PHASE_DEAD. */ 00676 pppStop(pd); 00677 pppRecvWakeup(pd); 00678 #endif /* PPPOS_SUPPORT */ 00679 } 00680 00681 return st; 00682 } 00683 00684 /* This function is called when carrier is lost on the PPP channel. */ 00685 void 00686 pppSigHUP(int pd) 00687 { 00688 #if PPPOE_SUPPORT 00689 PPPControl *pc = &pppControl[pd]; 00690 if(pc->ethif) { 00691 PPPDEBUG(LOG_DEBUG, ("pppSigHUP: unit %d sig_hup -> pppHupCB\n", pd)); 00692 pppHup(pd); 00693 } else 00694 #endif /* PPPOE_SUPPORT */ 00695 { 00696 #if PPPOS_SUPPORT 00697 PPPDEBUG(LOG_DEBUG, ("pppSigHUP: unit %d sig_hup -> pppHupCB\n", pd)); 00698 pppHup(pd); 00699 pppRecvWakeup(pd); 00700 #endif /* PPPOS_SUPPORT */ 00701 } 00702 } 00703 00704 #if PPPOS_SUPPORT 00705 static void 00706 nPut(PPPControl *pc, struct pbuf *nb) 00707 { 00708 struct pbuf *b; 00709 int c = 0; 00710 00711 for(b = nb; b != NULL; b = b->next) { 00712 if((c = sio_write(pc->fd, (u8_t*)b->payload, b->len)) != b->len) { 00713 PPPDEBUG(LOG_WARNING, 00714 ("PPP nPut: incomplete sio_write(fd:%d, len:%d, c: 0x%"X8_F") c = %d\n", (size_t)pc->fd, b->len, c, c)); 00715 LINK_STATS_INC(link.err); 00716 pc->lastXMit = 0; /* prepend PPP_FLAG to next packet */ 00717 snmp_inc_ifoutdiscards(&pc->netif); 00718 pbuf_free(nb); 00719 return; 00720 } 00721 } 00722 00723 snmp_add_ifoutoctets(&pc->netif, nb->tot_len); 00724 snmp_inc_ifoutucastpkts(&pc->netif); 00725 pbuf_free(nb); 00726 LINK_STATS_INC(link.xmit); 00727 } 00728 00729 /* 00730 * pppAppend - append given character to end of given pbuf. If outACCM 00731 * is not NULL and the character needs to be escaped, do so. 00732 * If pbuf is full, append another. 00733 * Return the current pbuf. 00734 */ 00735 static struct pbuf * 00736 pppAppend(u_char c, struct pbuf *nb, ext_accm *outACCM) 00737 { 00738 struct pbuf *tb = nb; 00739 00740 /* Make sure there is room for the character and an escape code. 00741 * Sure we don't quite fill the buffer if the character doesn't 00742 * get escaped but is one character worth complicating this? */ 00743 /* Note: We assume no packet header. */ 00744 if (nb && (PBUF_POOL_BUFSIZE - nb->len) < 2) { 00745 tb = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); 00746 if (tb) { 00747 nb->next = tb; 00748 } else { 00749 LINK_STATS_INC(link.memerr); 00750 } 00751 nb = tb; 00752 } 00753 00754 if (nb) { 00755 if (outACCM && ESCAPE_P(*outACCM, c)) { 00756 *((u_char*)nb->payload + nb->len++) = PPP_ESCAPE; 00757 *((u_char*)nb->payload + nb->len++) = c ^ PPP_TRANS; 00758 } else { 00759 *((u_char*)nb->payload + nb->len++) = c; 00760 } 00761 } 00762 00763 return tb; 00764 } 00765 #endif /* PPPOS_SUPPORT */ 00766 00767 #if PPPOE_SUPPORT 00768 static err_t 00769 pppnetifOutputOverEthernet(int pd, struct pbuf *p) 00770 { 00771 PPPControl *pc = &pppControl[pd]; 00772 struct pbuf *pb; 00773 u_short protocol = PPP_IP; 00774 int i=0; 00775 u16_t tot_len; 00776 00777 /* @todo: try to use pbuf_header() here! */ 00778 pb = pbuf_alloc(PBUF_LINK, PPPOE_HDRLEN + sizeof(protocol), PBUF_RAM); 00779 if(!pb) { 00780 LINK_STATS_INC(link.memerr); 00781 LINK_STATS_INC(link.proterr); 00782 snmp_inc_ifoutdiscards(&pc->netif); 00783 return ERR_MEM; 00784 } 00785 00786 pbuf_header(pb, -(s16_t)PPPOE_HDRLEN); 00787 00788 pc->lastXMit = sys_jiffies(); 00789 00790 if (!pc->pcomp || protocol > 0xFF) { 00791 *((u_char*)pb->payload + i++) = (protocol >> 8) & 0xFF; 00792 } 00793 *((u_char*)pb->payload + i) = protocol & 0xFF; 00794 00795 pbuf_chain(pb, p); 00796 tot_len = pb->tot_len; 00797 00798 if(pppoe_xmit(pc->pppoe_sc, pb) != ERR_OK) { 00799 LINK_STATS_INC(link.err); 00800 snmp_inc_ifoutdiscards(&pc->netif); 00801 return PPPERR_DEVICE; 00802 } 00803 00804 snmp_add_ifoutoctets(&pc->netif, tot_len); 00805 snmp_inc_ifoutucastpkts(&pc->netif); 00806 LINK_STATS_INC(link.xmit); 00807 return ERR_OK; 00808 } 00809 #endif /* PPPOE_SUPPORT */ 00810 00811 /* Send a packet on the given connection. */ 00812 static err_t 00813 pppnetifOutput(struct netif *netif, struct pbuf *pb, ip_addr_t *ipaddr) 00814 { 00815 int pd = (int)(size_t)netif->state; 00816 PPPControl *pc = &pppControl[pd]; 00817 #if PPPOS_SUPPORT 00818 u_short protocol = PPP_IP; 00819 u_int fcsOut = PPP_INITFCS; 00820 struct pbuf *headMB = NULL, *tailMB = NULL, *p; 00821 u_char c; 00822 #endif /* PPPOS_SUPPORT */ 00823 00824 LWIP_UNUSED_ARG(ipaddr); 00825 00826 /* Validate parameters. */ 00827 /* We let any protocol value go through - it can't hurt us 00828 * and the peer will just drop it if it's not accepting it. */ 00829 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag || !pb) { 00830 PPPDEBUG(LOG_WARNING, ("pppnetifOutput[%d]: bad parms prot=%d pb=%p\n", 00831 pd, PPP_IP, pb)); 00832 LINK_STATS_INC(link.opterr); 00833 LINK_STATS_INC(link.drop); 00834 snmp_inc_ifoutdiscards(netif); 00835 return ERR_ARG; 00836 } 00837 00838 /* Check that the link is up. */ 00839 if (lcp_phase[pd] == PHASE_DEAD) { 00840 PPPDEBUG(LOG_ERR, ("pppnetifOutput[%d]: link not up\n", pd)); 00841 LINK_STATS_INC(link.rterr); 00842 LINK_STATS_INC(link.drop); 00843 snmp_inc_ifoutdiscards(netif); 00844 return ERR_RTE; 00845 } 00846 00847 #if PPPOE_SUPPORT 00848 if(pc->ethif) { 00849 return pppnetifOutputOverEthernet(pd, pb); 00850 } 00851 #endif /* PPPOE_SUPPORT */ 00852 00853 #if PPPOS_SUPPORT 00854 /* Grab an output buffer. */ 00855 headMB = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); 00856 if (headMB == NULL) { 00857 PPPDEBUG(LOG_WARNING, ("pppnetifOutput[%d]: first alloc fail\n", pd)); 00858 LINK_STATS_INC(link.memerr); 00859 LINK_STATS_INC(link.drop); 00860 snmp_inc_ifoutdiscards(netif); 00861 return ERR_MEM; 00862 } 00863 00864 #if VJ_SUPPORT 00865 /* 00866 * Attempt Van Jacobson header compression if VJ is configured and 00867 * this is an IP packet. 00868 */ 00869 if (protocol == PPP_IP && pc->vjEnabled) { 00870 switch (vj_compress_tcp(&pc->vjComp, pb)) { 00871 case TYPE_IP: 00872 /* No change... 00873 protocol = PPP_IP_PROTOCOL; */ 00874 break; 00875 case TYPE_COMPRESSED_TCP: 00876 protocol = PPP_VJC_COMP; 00877 break; 00878 case TYPE_UNCOMPRESSED_TCP: 00879 protocol = PPP_VJC_UNCOMP; 00880 break; 00881 default: 00882 PPPDEBUG(LOG_WARNING, ("pppnetifOutput[%d]: bad IP packet\n", pd)); 00883 LINK_STATS_INC(link.proterr); 00884 LINK_STATS_INC(link.drop); 00885 snmp_inc_ifoutdiscards(netif); 00886 pbuf_free(headMB); 00887 return ERR_VAL; 00888 } 00889 } 00890 #endif /* VJ_SUPPORT */ 00891 00892 tailMB = headMB; 00893 00894 /* Build the PPP header. */ 00895 if ((sys_jiffies() - pc->lastXMit) >= PPP_MAXIDLEFLAG) { 00896 tailMB = pppAppend(PPP_FLAG, tailMB, NULL); 00897 } 00898 00899 pc->lastXMit = sys_jiffies(); 00900 if (!pc->accomp) { 00901 fcsOut = PPP_FCS(fcsOut, PPP_ALLSTATIONS); 00902 tailMB = pppAppend(PPP_ALLSTATIONS, tailMB, &pc->outACCM); 00903 fcsOut = PPP_FCS(fcsOut, PPP_UI); 00904 tailMB = pppAppend(PPP_UI, tailMB, &pc->outACCM); 00905 } 00906 if (!pc->pcomp || protocol > 0xFF) { 00907 c = (protocol >> 8) & 0xFF; 00908 fcsOut = PPP_FCS(fcsOut, c); 00909 tailMB = pppAppend(c, tailMB, &pc->outACCM); 00910 } 00911 c = protocol & 0xFF; 00912 fcsOut = PPP_FCS(fcsOut, c); 00913 tailMB = pppAppend(c, tailMB, &pc->outACCM); 00914 00915 /* Load packet. */ 00916 for(p = pb; p; p = p->next) { 00917 int n; 00918 u_char *sPtr; 00919 00920 sPtr = (u_char*)p->payload; 00921 n = p->len; 00922 while (n-- > 0) { 00923 c = *sPtr++; 00924 00925 /* Update FCS before checking for special characters. */ 00926 fcsOut = PPP_FCS(fcsOut, c); 00927 00928 /* Copy to output buffer escaping special characters. */ 00929 tailMB = pppAppend(c, tailMB, &pc->outACCM); 00930 } 00931 } 00932 00933 /* Add FCS and trailing flag. */ 00934 c = ~fcsOut & 0xFF; 00935 tailMB = pppAppend(c, tailMB, &pc->outACCM); 00936 c = (~fcsOut >> 8) & 0xFF; 00937 tailMB = pppAppend(c, tailMB, &pc->outACCM); 00938 tailMB = pppAppend(PPP_FLAG, tailMB, NULL); 00939 00940 /* If we failed to complete the packet, throw it away. */ 00941 if (!tailMB) { 00942 PPPDEBUG(LOG_WARNING, 00943 ("pppnetifOutput[%d]: Alloc err - dropping proto=%d\n", 00944 pd, protocol)); 00945 pbuf_free(headMB); 00946 LINK_STATS_INC(link.memerr); 00947 LINK_STATS_INC(link.drop); 00948 snmp_inc_ifoutdiscards(netif); 00949 return ERR_MEM; 00950 } 00951 00952 /* Send it. */ 00953 PPPDEBUG(LOG_INFO, ("pppnetifOutput[%d]: proto=0x%"X16_F"\n", pd, protocol)); 00954 00955 nPut(pc, headMB); 00956 #endif /* PPPOS_SUPPORT */ 00957 00958 return ERR_OK; 00959 } 00960 00961 /* Get and set parameters for the given connection. 00962 * Return 0 on success, an error code on failure. */ 00963 int 00964 pppIOCtl(int pd, int cmd, void *arg) 00965 { 00966 PPPControl *pc = &pppControl[pd]; 00967 int st = 0; 00968 00969 if (pd < 0 || pd >= NUM_PPP) { 00970 st = PPPERR_PARAM; 00971 } else { 00972 switch(cmd) { 00973 case PPPCTLG_UPSTATUS: /* Get the PPP up status. */ 00974 if (arg) { 00975 *(int *)arg = (int)(pc->if_up); 00976 } else { 00977 st = PPPERR_PARAM; 00978 } 00979 break; 00980 case PPPCTLS_ERRCODE: /* Set the PPP error code. */ 00981 if (arg) { 00982 pc->errCode = *(int *)arg; 00983 } else { 00984 st = PPPERR_PARAM; 00985 } 00986 break; 00987 case PPPCTLG_ERRCODE: /* Get the PPP error code. */ 00988 if (arg) { 00989 *(int *)arg = (int)(pc->errCode); 00990 } else { 00991 st = PPPERR_PARAM; 00992 } 00993 break; 00994 #if PPPOS_SUPPORT 00995 case PPPCTLG_FD: /* Get the fd associated with the ppp */ 00996 if (arg) { 00997 *(sio_fd_t *)arg = pc->fd; 00998 } else { 00999 st = PPPERR_PARAM; 01000 } 01001 break; 01002 #endif /* PPPOS_SUPPORT */ 01003 default: 01004 st = PPPERR_PARAM; 01005 break; 01006 } 01007 } 01008 01009 return st; 01010 } 01011 01012 /* 01013 * Return the Maximum Transmission Unit for the given PPP connection. 01014 */ 01015 u_short 01016 pppMTU(int pd) 01017 { 01018 PPPControl *pc = &pppControl[pd]; 01019 u_short st; 01020 01021 /* Validate parameters. */ 01022 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { 01023 st = 0; 01024 } else { 01025 st = pc->mtu; 01026 } 01027 01028 return st; 01029 } 01030 01031 #if PPPOE_SUPPORT 01032 int 01033 pppWriteOverEthernet(int pd, const u_char *s, int n) 01034 { 01035 PPPControl *pc = &pppControl[pd]; 01036 struct pbuf *pb; 01037 01038 /* skip address & flags */ 01039 s += 2; 01040 n -= 2; 01041 01042 LWIP_ASSERT("PPPOE_HDRLEN + n <= 0xffff", PPPOE_HDRLEN + n <= 0xffff); 01043 pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HDRLEN + n), PBUF_RAM); 01044 if(!pb) { 01045 LINK_STATS_INC(link.memerr); 01046 LINK_STATS_INC(link.proterr); 01047 snmp_inc_ifoutdiscards(&pc->netif); 01048 return PPPERR_ALLOC; 01049 } 01050 01051 pbuf_header(pb, -(s16_t)PPPOE_HDRLEN); 01052 01053 pc->lastXMit = sys_jiffies(); 01054 01055 MEMCPY(pb->payload, s, n); 01056 01057 if(pppoe_xmit(pc->pppoe_sc, pb) != ERR_OK) { 01058 LINK_STATS_INC(link.err); 01059 snmp_inc_ifoutdiscards(&pc->netif); 01060 return PPPERR_DEVICE; 01061 } 01062 01063 snmp_add_ifoutoctets(&pc->netif, (u16_t)n); 01064 snmp_inc_ifoutucastpkts(&pc->netif); 01065 LINK_STATS_INC(link.xmit); 01066 return PPPERR_NONE; 01067 } 01068 #endif /* PPPOE_SUPPORT */ 01069 01070 /* 01071 * Write n characters to a ppp link. 01072 * RETURN: >= 0 Number of characters written 01073 * -1 Failed to write to device 01074 */ 01075 int 01076 pppWrite(int pd, const u_char *s, int n) 01077 { 01078 PPPControl *pc = &pppControl[pd]; 01079 #if PPPOS_SUPPORT 01080 u_char c; 01081 u_int fcsOut; 01082 struct pbuf *headMB, *tailMB; 01083 #endif /* PPPOS_SUPPORT */ 01084 01085 #if PPPOE_SUPPORT 01086 if(pc->ethif) { 01087 return pppWriteOverEthernet(pd, s, n); 01088 } 01089 #endif /* PPPOE_SUPPORT */ 01090 01091 #if PPPOS_SUPPORT 01092 headMB = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); 01093 if (headMB == NULL) { 01094 LINK_STATS_INC(link.memerr); 01095 LINK_STATS_INC(link.proterr); 01096 snmp_inc_ifoutdiscards(&pc->netif); 01097 return PPPERR_ALLOC; 01098 } 01099 01100 tailMB = headMB; 01101 01102 /* If the link has been idle, we'll send a fresh flag character to 01103 * flush any noise. */ 01104 if ((sys_jiffies() - pc->lastXMit) >= PPP_MAXIDLEFLAG) { 01105 tailMB = pppAppend(PPP_FLAG, tailMB, NULL); 01106 } 01107 pc->lastXMit = sys_jiffies(); 01108 01109 fcsOut = PPP_INITFCS; 01110 /* Load output buffer. */ 01111 while (n-- > 0) { 01112 c = *s++; 01113 01114 /* Update FCS before checking for special characters. */ 01115 fcsOut = PPP_FCS(fcsOut, c); 01116 01117 /* Copy to output buffer escaping special characters. */ 01118 tailMB = pppAppend(c, tailMB, &pc->outACCM); 01119 } 01120 01121 /* Add FCS and trailing flag. */ 01122 c = ~fcsOut & 0xFF; 01123 tailMB = pppAppend(c, tailMB, &pc->outACCM); 01124 c = (~fcsOut >> 8) & 0xFF; 01125 tailMB = pppAppend(c, tailMB, &pc->outACCM); 01126 tailMB = pppAppend(PPP_FLAG, tailMB, NULL); 01127 01128 /* If we failed to complete the packet, throw it away. 01129 * Otherwise send it. */ 01130 if (!tailMB) { 01131 PPPDEBUG(LOG_WARNING, 01132 ("pppWrite[%d]: Alloc err - dropping pbuf len=%d\n", pd, headMB->len)); 01133 /*"pppWrite[%d]: Alloc err - dropping %d:%.*H", pd, headMB->len, LWIP_MIN(headMB->len * 2, 40), headMB->payload)); */ 01134 pbuf_free(headMB); 01135 LINK_STATS_INC(link.memerr); 01136 LINK_STATS_INC(link.proterr); 01137 snmp_inc_ifoutdiscards(&pc->netif); 01138 return PPPERR_ALLOC; 01139 } 01140 01141 PPPDEBUG(LOG_INFO, ("pppWrite[%d]: len=%d\n", pd, headMB->len)); 01142 /* "pppWrite[%d]: %d:%.*H", pd, headMB->len, LWIP_MIN(headMB->len * 2, 40), headMB->payload)); */ 01143 nPut(pc, headMB); 01144 #endif /* PPPOS_SUPPORT */ 01145 01146 return PPPERR_NONE; 01147 } 01148 01149 /* 01150 * ppp_send_config - configure the transmit characteristics of 01151 * the ppp interface. 01152 */ 01153 void 01154 ppp_send_config( int unit, u16_t mtu, u32_t asyncmap, int pcomp, int accomp) 01155 { 01156 PPPControl *pc = &pppControl[unit]; 01157 int i; 01158 01159 pc->mtu = mtu; 01160 pc->pcomp = pcomp; 01161 pc->accomp = accomp; 01162 01163 /* Load the ACCM bits for the 32 control codes. */ 01164 for (i = 0; i < 32/8; i++) { 01165 pc->outACCM[i] = (u_char)((asyncmap >> (8 * i)) & 0xFF); 01166 } 01167 PPPDEBUG(LOG_INFO, ("ppp_send_config[%d]: outACCM=%X %X %X %X\n", 01168 unit, 01169 pc->outACCM[0], pc->outACCM[1], pc->outACCM[2], pc->outACCM[3])); 01170 } 01171 01172 01173 /* 01174 * ppp_set_xaccm - set the extended transmit ACCM for the interface. 01175 */ 01176 void 01177 ppp_set_xaccm(int unit, ext_accm *accm) 01178 { 01179 SMEMCPY(pppControl[unit].outACCM, accm, sizeof(ext_accm)); 01180 PPPDEBUG(LOG_INFO, ("ppp_set_xaccm[%d]: outACCM=%X %X %X %X\n", 01181 unit, 01182 pppControl[unit].outACCM[0], 01183 pppControl[unit].outACCM[1], 01184 pppControl[unit].outACCM[2], 01185 pppControl[unit].outACCM[3])); 01186 } 01187 01188 01189 /* 01190 * ppp_recv_config - configure the receive-side characteristics of 01191 * the ppp interface. 01192 */ 01193 void 01194 ppp_recv_config( int unit, int mru, u32_t asyncmap, int pcomp, int accomp) 01195 { 01196 PPPControl *pc = &pppControl[unit]; 01197 int i; 01198 SYS_ARCH_DECL_PROTECT(lev); 01199 01200 LWIP_UNUSED_ARG(accomp); 01201 LWIP_UNUSED_ARG(pcomp); 01202 LWIP_UNUSED_ARG(mru); 01203 01204 /* Load the ACCM bits for the 32 control codes. */ 01205 SYS_ARCH_PROTECT(lev); 01206 for (i = 0; i < 32 / 8; i++) { 01207 /* @todo: does this work? ext_accm has been modified from pppd! */ 01208 pc->rx.inACCM[i] = (u_char)(asyncmap >> (i * 8)); 01209 } 01210 SYS_ARCH_UNPROTECT(lev); 01211 PPPDEBUG(LOG_INFO, ("ppp_recv_config[%d]: inACCM=%X %X %X %X\n", 01212 unit, 01213 pc->rx.inACCM[0], pc->rx.inACCM[1], pc->rx.inACCM[2], pc->rx.inACCM[3])); 01214 } 01215 01216 #if 0 01217 /* 01218 * ccp_test - ask kernel whether a given compression method 01219 * is acceptable for use. Returns 1 if the method and parameters 01220 * are OK, 0 if the method is known but the parameters are not OK 01221 * (e.g. code size should be reduced), or -1 if the method is unknown. 01222 */ 01223 int 01224 ccp_test( int unit, int opt_len, int for_transmit, u_char *opt_ptr) 01225 { 01226 return 0; /* XXX Currently no compression. */ 01227 } 01228 01229 /* 01230 * ccp_flags_set - inform kernel about the current state of CCP. 01231 */ 01232 void 01233 ccp_flags_set(int unit, int isopen, int isup) 01234 { 01235 /* XXX */ 01236 } 01237 01238 /* 01239 * ccp_fatal_error - returns 1 if decompression was disabled as a 01240 * result of an error detected after decompression of a packet, 01241 * 0 otherwise. This is necessary because of patent nonsense. 01242 */ 01243 int 01244 ccp_fatal_error(int unit) 01245 { 01246 /* XXX */ 01247 return 0; 01248 } 01249 #endif 01250 01251 /* 01252 * get_idle_time - return how long the link has been idle. 01253 */ 01254 int 01255 get_idle_time(int u, struct ppp_idle *ip) 01256 { 01257 /* XXX */ 01258 LWIP_UNUSED_ARG(u); 01259 LWIP_UNUSED_ARG(ip); 01260 01261 return 0; 01262 } 01263 01264 01265 /* 01266 * Return user specified netmask, modified by any mask we might determine 01267 * for address `addr' (in network byte order). 01268 * Here we scan through the system's list of interfaces, looking for 01269 * any non-point-to-point interfaces which might appear to be on the same 01270 * network as `addr'. If we find any, we OR in their netmask to the 01271 * user-specified netmask. 01272 */ 01273 u32_t 01274 GetMask(u32_t addr) 01275 { 01276 u32_t mask, nmask; 01277 01278 htonl(addr); 01279 if (IP_CLASSA(addr)) { /* determine network mask for address class */ 01280 nmask = IP_CLASSA_NET; 01281 } else if (IP_CLASSB(addr)) { 01282 nmask = IP_CLASSB_NET; 01283 } else { 01284 nmask = IP_CLASSC_NET; 01285 } 01286 01287 /* class D nets are disallowed by bad_ip_adrs */ 01288 mask = subnetMask | htonl(nmask); 01289 01290 /* XXX 01291 * Scan through the system's network interfaces. 01292 * Get each netmask and OR them into our mask. 01293 */ 01294 01295 return mask; 01296 } 01297 01298 /* 01299 * sifvjcomp - config tcp header compression 01300 */ 01301 int 01302 sifvjcomp(int pd, int vjcomp, u8_t cidcomp, u8_t maxcid) 01303 { 01304 #if PPPOS_SUPPORT && VJ_SUPPORT 01305 PPPControl *pc = &pppControl[pd]; 01306 01307 pc->vjEnabled = vjcomp; 01308 pc->vjComp.compressSlot = cidcomp; 01309 pc->vjComp.maxSlotIndex = maxcid; 01310 PPPDEBUG(LOG_INFO, ("sifvjcomp: VJ compress enable=%d slot=%d max slot=%d\n", 01311 vjcomp, cidcomp, maxcid)); 01312 #else /* PPPOS_SUPPORT && VJ_SUPPORT */ 01313 LWIP_UNUSED_ARG(pd); 01314 LWIP_UNUSED_ARG(vjcomp); 01315 LWIP_UNUSED_ARG(cidcomp); 01316 LWIP_UNUSED_ARG(maxcid); 01317 #endif /* PPPOS_SUPPORT && VJ_SUPPORT */ 01318 01319 return 0; 01320 } 01321 01322 /* 01323 * pppnetifNetifInit - netif init callback 01324 */ 01325 static err_t 01326 pppnetifNetifInit(struct netif *netif) 01327 { 01328 netif->name[0] = 'p'; 01329 netif->name[1] = 'p'; 01330 netif->output = pppnetifOutput; 01331 netif->mtu = pppMTU((int)(size_t)netif->state); 01332 netif->flags = NETIF_FLAG_POINTTOPOINT | NETIF_FLAG_LINK_UP; 01333 #if LWIP_NETIF_HOSTNAME 01334 /* @todo: Initialize interface hostname */ 01335 /* netif_set_hostname(netif, "lwip"); */ 01336 #endif /* LWIP_NETIF_HOSTNAME */ 01337 return ERR_OK; 01338 } 01339 01340 01341 /* 01342 * sifup - Config the interface up and enable IP packets to pass. 01343 */ 01344 int 01345 sifup(int pd) 01346 { 01347 PPPControl *pc = &pppControl[pd]; 01348 int st = 1; 01349 01350 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { 01351 st = 0; 01352 PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd)); 01353 } else { 01354 netif_remove(&pc->netif); 01355 if (netif_add(&pc->netif, &pc->addrs.our_ipaddr, &pc->addrs.netmask, 01356 &pc->addrs.his_ipaddr, (void *)(size_t)pd, pppnetifNetifInit, ip_input)) { 01357 netif_set_up(&pc->netif); 01358 pc->if_up = 1; 01359 pc->errCode = PPPERR_NONE; 01360 01361 PPPDEBUG(LOG_DEBUG, ("sifup: unit %d: linkStatusCB=%p errCode=%d\n", pd, pc->linkStatusCB, pc->errCode)); 01362 if (pc->linkStatusCB) { 01363 pc->linkStatusCB(pc->linkStatusCtx, pc->errCode, &pc->addrs); 01364 } 01365 } else { 01366 st = 0; 01367 PPPDEBUG(LOG_ERR, ("sifup[%d]: netif_add failed\n", pd)); 01368 } 01369 } 01370 01371 return st; 01372 } 01373 01374 /* 01375 * sifnpmode - Set the mode for handling packets for a given NP. 01376 */ 01377 int 01378 sifnpmode(int u, int proto, enum NPmode mode) 01379 { 01380 LWIP_UNUSED_ARG(u); 01381 LWIP_UNUSED_ARG(proto); 01382 LWIP_UNUSED_ARG(mode); 01383 return 0; 01384 } 01385 01386 /* 01387 * sifdown - Config the interface down and disable IP. 01388 */ 01389 int 01390 sifdown(int pd) 01391 { 01392 PPPControl *pc = &pppControl[pd]; 01393 int st = 1; 01394 01395 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { 01396 st = 0; 01397 PPPDEBUG(LOG_WARNING, ("sifdown[%d]: bad parms\n", pd)); 01398 } else { 01399 pc->if_up = 0; 01400 /* make sure the netif status callback is called */ 01401 netif_set_down(&pc->netif); 01402 netif_remove(&pc->netif); 01403 PPPDEBUG(LOG_DEBUG, ("sifdown: unit %d: linkStatusCB=%p errCode=%d\n", pd, pc->linkStatusCB, pc->errCode)); 01404 if (pc->linkStatusCB) { 01405 pc->linkStatusCB(pc->linkStatusCtx, PPPERR_CONNECT, NULL); 01406 } 01407 } 01408 return st; 01409 } 01410 01411 /** 01412 * sifaddr - Config the interface IP addresses and netmask. 01413 * @param pd Interface unit ??? 01414 * @param o Our IP address ??? 01415 * @param h His IP address ??? 01416 * @param m IP subnet mask ??? 01417 * @param ns1 Primary DNS 01418 * @param ns2 Secondary DNS 01419 */ 01420 int 01421 sifaddr( int pd, u32_t o, u32_t h, u32_t m, u32_t ns1, u32_t ns2) 01422 { 01423 PPPControl *pc = &pppControl[pd]; 01424 int st = 1; 01425 01426 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { 01427 st = 0; 01428 PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd)); 01429 } else { 01430 SMEMCPY(&pc->addrs.our_ipaddr, &o, sizeof(o)); 01431 SMEMCPY(&pc->addrs.his_ipaddr, &h, sizeof(h)); 01432 SMEMCPY(&pc->addrs.netmask, &m, sizeof(m)); 01433 SMEMCPY(&pc->addrs.dns1, &ns1, sizeof(ns1)); 01434 SMEMCPY(&pc->addrs.dns2, &ns2, sizeof(ns2)); 01435 } 01436 return st; 01437 } 01438 01439 /** 01440 * cifaddr - Clear the interface IP addresses, and delete routes 01441 * through the interface if possible. 01442 * @param pd Interface unit ??? 01443 * @param o Our IP address ??? 01444 * @param h IP broadcast address ??? 01445 */ 01446 int 01447 cifaddr( int pd, u32_t o, u32_t h) 01448 { 01449 PPPControl *pc = &pppControl[pd]; 01450 int st = 1; 01451 01452 LWIP_UNUSED_ARG(o); 01453 LWIP_UNUSED_ARG(h); 01454 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { 01455 st = 0; 01456 PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd)); 01457 } else { 01458 IP4_ADDR(&pc->addrs.our_ipaddr, 0,0,0,0); 01459 IP4_ADDR(&pc->addrs.his_ipaddr, 0,0,0,0); 01460 IP4_ADDR(&pc->addrs.netmask, 255,255,255,0); 01461 IP4_ADDR(&pc->addrs.dns1, 0,0,0,0); 01462 IP4_ADDR(&pc->addrs.dns2, 0,0,0,0); 01463 } 01464 return st; 01465 } 01466 01467 /* 01468 * sifdefaultroute - assign a default route through the address given. 01469 */ 01470 int 01471 sifdefaultroute(int pd, u32_t l, u32_t g) 01472 { 01473 PPPControl *pc = &pppControl[pd]; 01474 int st = 1; 01475 01476 LWIP_UNUSED_ARG(l); 01477 LWIP_UNUSED_ARG(g); 01478 01479 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { 01480 st = 0; 01481 PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd)); 01482 } else { 01483 netif_set_default(&pc->netif); 01484 } 01485 01486 /* TODO: check how PPP handled the netMask, previously not set by ipSetDefault */ 01487 01488 return st; 01489 } 01490 01491 /* 01492 * cifdefaultroute - delete a default route through the address given. 01493 */ 01494 int 01495 cifdefaultroute(int pd, u32_t l, u32_t g) 01496 { 01497 PPPControl *pc = &pppControl[pd]; 01498 int st = 1; 01499 01500 LWIP_UNUSED_ARG(l); 01501 LWIP_UNUSED_ARG(g); 01502 01503 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { 01504 st = 0; 01505 PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd)); 01506 } else { 01507 netif_set_default(NULL); 01508 } 01509 01510 return st; 01511 } 01512 01513 /**********************************/ 01514 /*** LOCAL FUNCTION DEFINITIONS ***/ 01515 /**********************************/ 01516 01517 #if PPPOS_SUPPORT && PPP_INPROC_OWNTHREAD 01518 /* The main PPP process function. This implements the state machine according 01519 * to section 4 of RFC 1661: The Point-To-Point Protocol. */ 01520 static void 01521 pppInputThread(void *arg) 01522 { 01523 int count; 01524 PPPControlRx *pcrx = arg; 01525 01526 while (lcp_phase[pcrx->pd] != PHASE_DEAD) { 01527 count = sio_read(pcrx->fd, pcrx->rxbuf, PPPOS_RX_BUFSIZE); 01528 if(count > 0) { 01529 pppInProc(pcrx, pcrx->rxbuf, count); 01530 } else { 01531 /* nothing received, give other tasks a chance to run */ 01532 sys_msleep(1); 01533 } 01534 } 01535 } 01536 #endif /* PPPOS_SUPPORT && PPP_INPROC_OWNTHREAD */ 01537 01538 #if PPPOE_SUPPORT 01539 01540 void 01541 pppOverEthernetInitFailed(int pd) 01542 { 01543 PPPControl* pc; 01544 01545 pppHup(pd); 01546 pppStop(pd); 01547 01548 pc = &pppControl[pd]; 01549 pppoe_destroy(&pc->netif); 01550 pc->openFlag = 0; 01551 01552 if(pc->linkStatusCB) { 01553 pc->linkStatusCB(pc->linkStatusCtx, pc->errCode ? pc->errCode : PPPERR_PROTOCOL, NULL); 01554 } 01555 } 01556 01557 static void 01558 pppOverEthernetLinkStatusCB(int pd, int up) 01559 { 01560 if(up) { 01561 PPPDEBUG(LOG_INFO, ("pppOverEthernetLinkStatusCB: unit %d: Connecting\n", pd)); 01562 pppStart(pd); 01563 } else { 01564 pppOverEthernetInitFailed(pd); 01565 } 01566 } 01567 #endif /* PPPOE_SUPPORT */ 01568 01569 struct pbuf * 01570 pppSingleBuf(struct pbuf *p) 01571 { 01572 struct pbuf *q, *b; 01573 u_char *pl; 01574 01575 if(p->tot_len == p->len) { 01576 return p; 01577 } 01578 01579 q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); 01580 if(!q) { 01581 PPPDEBUG(LOG_ERR, 01582 ("pppSingleBuf: unable to alloc new buf (%d)\n", p->tot_len)); 01583 return p; /* live dangerously */ 01584 } 01585 01586 for(b = p, pl = (u_char*) q->payload; b != NULL; b = b->next) { 01587 MEMCPY(pl, b->payload, b->len); 01588 pl += b->len; 01589 } 01590 01591 pbuf_free(p); 01592 01593 return q; 01594 } 01595 01596 struct pppInputHeader { 01597 int unit; 01598 u16_t proto; 01599 }; 01600 01601 /* 01602 * Pass the processed input packet to the appropriate handler. 01603 * This function and all handlers run in the context of the tcpip_thread 01604 */ 01605 static void 01606 pppInput(void *arg) 01607 { 01608 struct pbuf *nb = (struct pbuf *)arg; 01609 u16_t protocol; 01610 int pd; 01611 01612 pd = ((struct pppInputHeader *)nb->payload)->unit; 01613 protocol = ((struct pppInputHeader *)nb->payload)->proto; 01614 01615 if(pbuf_header(nb, -(int)sizeof(struct pppInputHeader))) { 01616 LWIP_ASSERT("pbuf_header failed\n", 0); 01617 goto drop; 01618 } 01619 01620 LINK_STATS_INC(link.recv); 01621 snmp_inc_ifinucastpkts(&pppControl[pd].netif); 01622 snmp_add_ifinoctets(&pppControl[pd].netif, nb->tot_len); 01623 01624 /* 01625 * Toss all non-LCP packets unless LCP is OPEN. 01626 * Until we get past the authentication phase, toss all packets 01627 * except LCP, LQR and authentication packets. 01628 */ 01629 if((lcp_phase[pd] <= PHASE_AUTHENTICATE) && (protocol != PPP_LCP)) { 01630 if(!((protocol == PPP_LQR) || (protocol == PPP_PAP) || (protocol == PPP_CHAP)) || 01631 (lcp_phase[pd] != PHASE_AUTHENTICATE)) { 01632 PPPDEBUG(LOG_INFO, ("pppInput: discarding proto 0x%"X16_F" in phase %d\n", protocol, lcp_phase[pd])); 01633 goto drop; 01634 } 01635 } 01636 01637 switch(protocol) { 01638 case PPP_VJC_COMP: /* VJ compressed TCP */ 01639 #if PPPOS_SUPPORT && VJ_SUPPORT 01640 PPPDEBUG(LOG_INFO, ("pppInput[%d]: vj_comp in pbuf len=%d\n", pd, nb->len)); 01641 /* 01642 * Clip off the VJ header and prepend the rebuilt TCP/IP header and 01643 * pass the result to IP. 01644 */ 01645 if ((vj_uncompress_tcp(&nb, &pppControl[pd].vjComp) >= 0) && (pppControl[pd].netif.input)) { 01646 pppControl[pd].netif.input(nb, &pppControl[pd].netif); 01647 return; 01648 } 01649 /* Something's wrong so drop it. */ 01650 PPPDEBUG(LOG_WARNING, ("pppInput[%d]: Dropping VJ compressed\n", pd)); 01651 #else /* PPPOS_SUPPORT && VJ_SUPPORT */ 01652 /* No handler for this protocol so drop the packet. */ 01653 PPPDEBUG(LOG_INFO, ("pppInput[%d]: drop VJ Comp in %d:%s\n", pd, nb->len, nb->payload)); 01654 #endif /* PPPOS_SUPPORT && VJ_SUPPORT */ 01655 break; 01656 01657 case PPP_VJC_UNCOMP: /* VJ uncompressed TCP */ 01658 #if PPPOS_SUPPORT && VJ_SUPPORT 01659 PPPDEBUG(LOG_INFO, ("pppInput[%d]: vj_un in pbuf len=%d\n", pd, nb->len)); 01660 /* 01661 * Process the TCP/IP header for VJ header compression and then pass 01662 * the packet to IP. 01663 */ 01664 if ((vj_uncompress_uncomp(nb, &pppControl[pd].vjComp) >= 0) && pppControl[pd].netif.input) { 01665 pppControl[pd].netif.input(nb, &pppControl[pd].netif); 01666 return; 01667 } 01668 /* Something's wrong so drop it. */ 01669 PPPDEBUG(LOG_WARNING, ("pppInput[%d]: Dropping VJ uncompressed\n", pd)); 01670 #else /* PPPOS_SUPPORT && VJ_SUPPORT */ 01671 /* No handler for this protocol so drop the packet. */ 01672 PPPDEBUG((LOG_INFO, 01673 "pppInput[%d]: drop VJ UnComp in %d:.*H\n", 01674 pd, nb->len, LWIP_MIN(nb->len * 2, 40), nb->payload)); 01675 #endif /* PPPOS_SUPPORT && VJ_SUPPORT */ 01676 break; 01677 01678 case PPP_IP: /* Internet Protocol */ 01679 PPPDEBUG(LOG_INFO, ("pppInput[%d]: ip in pbuf len=%d\n", pd, nb->len)); 01680 if (pppControl[pd].netif.input) { 01681 pppControl[pd].netif.input(nb, &pppControl[pd].netif); 01682 return; 01683 } 01684 break; 01685 01686 default: { 01687 struct protent *protp; 01688 int i; 01689 01690 /* 01691 * Upcall the proper protocol input routine. 01692 */ 01693 for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) { 01694 if (protp->protocol == protocol && protp->enabled_flag) { 01695 PPPDEBUG(LOG_INFO, ("pppInput[%d]: %s len=%d\n", pd, protp->name, nb->len)); 01696 nb = pppSingleBuf(nb); 01697 (*protp->input)(pd, (u_char*)nb->payload, nb->len); 01698 PPPDEBUG(LOG_DETAIL, ("pppInput[%d]: packet processed\n", pd)); 01699 goto out; 01700 } 01701 } 01702 01703 /* No handler for this protocol so reject the packet. */ 01704 PPPDEBUG(LOG_INFO, ("pppInput[%d]: rejecting unsupported proto 0x%"X16_F" len=%d\n", pd, protocol, nb->len)); 01705 if (pbuf_header(nb, sizeof(protocol))) { 01706 LWIP_ASSERT("pbuf_header failed\n", 0); 01707 goto drop; 01708 } 01709 #if BYTE_ORDER == LITTLE_ENDIAN 01710 protocol = htons(protocol); 01711 SMEMCPY(nb->payload, &protocol, sizeof(protocol)); 01712 #endif /* BYTE_ORDER == LITTLE_ENDIAN */ 01713 lcp_sprotrej(pd, (u_char*) nb->payload, nb->len); 01714 } 01715 break; 01716 } 01717 01718 drop: 01719 LINK_STATS_INC(link.drop); 01720 snmp_inc_ifindiscards(&pppControl[pd].netif); 01721 01722 out: 01723 pbuf_free(nb); 01724 return; 01725 } 01726 01727 #if PPPOS_SUPPORT 01728 /* 01729 * Drop the input packet. 01730 */ 01731 static void 01732 pppDrop(PPPControlRx *pcrx) 01733 { 01734 if (pcrx->inHead != NULL) { 01735 #if 0 01736 PPPDEBUG(LOG_INFO, ("pppDrop: %d:%.*H\n", pcrx->inHead->len, min(60, pcrx->inHead->len * 2), pcrx->inHead->payload)); 01737 #endif 01738 PPPDEBUG(LOG_INFO, ("pppDrop: pbuf len=%d, addr %p\n", pcrx->inHead->len, (void*)pcrx->inHead)); 01739 if (pcrx->inTail && (pcrx->inTail != pcrx->inHead)) { 01740 pbuf_free(pcrx->inTail); 01741 } 01742 pbuf_free(pcrx->inHead); 01743 pcrx->inHead = NULL; 01744 pcrx->inTail = NULL; 01745 } 01746 #if VJ_SUPPORT 01747 vj_uncompress_err(&pppControl[pcrx->pd].vjComp); 01748 #endif /* VJ_SUPPORT */ 01749 01750 LINK_STATS_INC(link.drop); 01751 snmp_inc_ifindiscards(&pppControl[pcrx->pd].netif); 01752 } 01753 01754 /** Pass received raw characters to PPPoS to be decoded. This function is 01755 * thread-safe and can be called from a dedicated RX-thread or from a main-loop. 01756 * 01757 * @param pd PPP descriptor index, returned by pppOpen() 01758 * @param data received data 01759 * @param len length of received data 01760 */ 01761 void 01762 pppos_input(int pd, u_char* data, int len) 01763 { 01764 pppInProc(&pppControl[pd].rx, data, len); 01765 } 01766 01767 /** 01768 * Process a received octet string. 01769 */ 01770 static void 01771 pppInProc(PPPControlRx *pcrx, u_char *s, int l) 01772 { 01773 struct pbuf *nextNBuf; 01774 u_char curChar; 01775 u_char escaped; 01776 SYS_ARCH_DECL_PROTECT(lev); 01777 01778 PPPDEBUG(LOG_DEBUG, ("pppInProc[%d]: got %d bytes\n", pcrx->pd, l)); 01779 while (l-- > 0) { 01780 curChar = *s++; 01781 01782 SYS_ARCH_PROTECT(lev); 01783 escaped = ESCAPE_P(pcrx->inACCM, curChar); 01784 SYS_ARCH_UNPROTECT(lev); 01785 /* Handle special characters. */ 01786 if (escaped) { 01787 /* Check for escape sequences. */ 01788 /* XXX Note that this does not handle an escaped 0x5d character which 01789 * would appear as an escape character. Since this is an ASCII ']' 01790 * and there is no reason that I know of to escape it, I won't complicate 01791 * the code to handle this case. GLL */ 01792 if (curChar == PPP_ESCAPE) { 01793 pcrx->inEscaped = 1; 01794 /* Check for the flag character. */ 01795 } else if (curChar == PPP_FLAG) { 01796 /* If this is just an extra flag character, ignore it. */ 01797 if (pcrx->inState <= PDADDRESS) { 01798 /* ignore it */; 01799 /* If we haven't received the packet header, drop what has come in. */ 01800 } else if (pcrx->inState < PDDATA) { 01801 PPPDEBUG(LOG_WARNING, 01802 ("pppInProc[%d]: Dropping incomplete packet %d\n", 01803 pcrx->pd, pcrx->inState)); 01804 LINK_STATS_INC(link.lenerr); 01805 pppDrop(pcrx); 01806 /* If the fcs is invalid, drop the packet. */ 01807 } else if (pcrx->inFCS != PPP_GOODFCS) { 01808 PPPDEBUG(LOG_INFO, 01809 ("pppInProc[%d]: Dropping bad fcs 0x%"X16_F" proto=0x%"X16_F"\n", 01810 pcrx->pd, pcrx->inFCS, pcrx->inProtocol)); 01811 /* Note: If you get lots of these, check for UART frame errors or try different baud rate */ 01812 LINK_STATS_INC(link.chkerr); 01813 pppDrop(pcrx); 01814 /* Otherwise it's a good packet so pass it on. */ 01815 } else { 01816 /* Trim off the checksum. */ 01817 if(pcrx->inTail->len >= 2) { 01818 pcrx->inTail->len -= 2; 01819 01820 pcrx->inTail->tot_len = pcrx->inTail->len; 01821 if (pcrx->inTail != pcrx->inHead) { 01822 pbuf_cat(pcrx->inHead, pcrx->inTail); 01823 } 01824 } else { 01825 pcrx->inTail->tot_len = pcrx->inTail->len; 01826 if (pcrx->inTail != pcrx->inHead) { 01827 pbuf_cat(pcrx->inHead, pcrx->inTail); 01828 } 01829 01830 pbuf_realloc(pcrx->inHead, pcrx->inHead->tot_len - 2); 01831 } 01832 01833 /* Dispatch the packet thereby consuming it. */ 01834 #if PPP_INPROC_MULTITHREADED 01835 if(tcpip_callback_with_block(pppInput, pcrx->inHead, 0) != ERR_OK) { 01836 PPPDEBUG(LOG_ERR, ("pppInProc[%d]: tcpip_callback() failed, dropping packet\n", pcrx->pd)); 01837 pbuf_free(pcrx->inHead); 01838 LINK_STATS_INC(link.drop); 01839 snmp_inc_ifindiscards(&pppControl[pcrx->pd].netif); 01840 } 01841 #else /* PPP_INPROC_MULTITHREADED */ 01842 pppInput(pcrx->inHead); 01843 #endif /* PPP_INPROC_MULTITHREADED */ 01844 pcrx->inHead = NULL; 01845 pcrx->inTail = NULL; 01846 } 01847 01848 /* Prepare for a new packet. */ 01849 pcrx->inFCS = PPP_INITFCS; 01850 pcrx->inState = PDADDRESS; 01851 pcrx->inEscaped = 0; 01852 /* Other characters are usually control characters that may have 01853 * been inserted by the physical layer so here we just drop them. */ 01854 } else { 01855 PPPDEBUG(LOG_WARNING, 01856 ("pppInProc[%d]: Dropping ACCM char <%d>\n", pcrx->pd, curChar)); 01857 } 01858 /* Process other characters. */ 01859 } else { 01860 /* Unencode escaped characters. */ 01861 if (pcrx->inEscaped) { 01862 pcrx->inEscaped = 0; 01863 curChar ^= PPP_TRANS; 01864 } 01865 01866 /* Process character relative to current state. */ 01867 switch(pcrx->inState) { 01868 case PDIDLE: /* Idle state - waiting. */ 01869 /* Drop the character if it's not 0xff 01870 * we would have processed a flag character above. */ 01871 if (curChar != PPP_ALLSTATIONS) { 01872 break; 01873 } 01874 01875 /* Fall through */ 01876 case PDSTART: /* Process start flag. */ 01877 /* Prepare for a new packet. */ 01878 pcrx->inFCS = PPP_INITFCS; 01879 01880 /* Fall through */ 01881 case PDADDRESS: /* Process address field. */ 01882 if (curChar == PPP_ALLSTATIONS) { 01883 pcrx->inState = PDCONTROL; 01884 break; 01885 } 01886 /* Else assume compressed address and control fields so 01887 * fall through to get the protocol... */ 01888 case PDCONTROL: /* Process control field. */ 01889 /* If we don't get a valid control code, restart. */ 01890 if (curChar == PPP_UI) { 01891 pcrx->inState = PDPROTOCOL1; 01892 break; 01893 } 01894 #if 0 01895 else { 01896 PPPDEBUG((LOG_WARNING, 01897 "pppInProc[%d]: Invalid control <%d>\n", pcrx->pd, curChar)); 01898 pcrx->inState = PDSTART; 01899 } 01900 #endif 01901 case PDPROTOCOL1: /* Process protocol field 1. */ 01902 /* If the lower bit is set, this is the end of the protocol 01903 * field. */ 01904 if (curChar & 1) { 01905 pcrx->inProtocol = curChar; 01906 pcrx->inState = PDDATA; 01907 } else { 01908 pcrx->inProtocol = (u_int)curChar << 8; 01909 pcrx->inState = PDPROTOCOL2; 01910 } 01911 break; 01912 case PDPROTOCOL2: /* Process protocol field 2. */ 01913 pcrx->inProtocol |= curChar; 01914 pcrx->inState = PDDATA; 01915 break; 01916 case PDDATA: /* Process data byte. */ 01917 /* Make space to receive processed data. */ 01918 if (pcrx->inTail == NULL || pcrx->inTail->len == PBUF_POOL_BUFSIZE) { 01919 if(pcrx->inTail) { 01920 pcrx->inTail->tot_len = pcrx->inTail->len; 01921 if (pcrx->inTail != pcrx->inHead) { 01922 pbuf_cat(pcrx->inHead, pcrx->inTail); 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 = (struct pppInputHeader*) 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:37:05 by 1.7.2