ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

ppp.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.