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