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