ppp.c
上传用户:yyhongfa
上传日期:2013-01-18
资源大小:267k
文件大小:48k
开发平台:

C/C++

  1. /*****************************************************************************
  2. * ppp.c - Network Point to Point Protocol program file.
  3. *
  4. * Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
  5. * portions Copyright (c) 1997 by Global Election Systems Inc.
  6. *
  7. * The authors hereby grant permission to use, copy, modify, distribute,
  8. * and license this software and its documentation for any purpose, provided
  9. * that existing copyright notices are retained in all copies and that this
  10. * notice and the following disclaimer are included verbatim in any 
  11. * distributions. No written agreement, license, or royalty fee is required
  12. * for any of the authorized uses.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
  15. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  16. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
  17. * IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  18. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  19. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  20. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  21. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  22. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  23. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24. *
  25. ******************************************************************************
  26. * REVISION HISTORY
  27. *
  28. * 03-01-01 Marc Boucher <marc@mbsi.ca>
  29. *   Ported to lwIP.
  30. * 97-11-05 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
  31. *   Original.
  32. *****************************************************************************/
  33. /*
  34.  * ppp_defs.h - PPP definitions.
  35.  *
  36.  * if_pppvar.h - private structures and declarations for PPP.
  37.  *
  38.  * Copyright (c) 1994 The Australian National University.
  39.  * All rights reserved.
  40.  *
  41.  * Permission to use, copy, modify, and distribute this software and its
  42.  * documentation is hereby granted, provided that the above copyright
  43.  * notice appears in all copies.  This software is provided without any
  44.  * warranty, express or implied. The Australian National University
  45.  * makes no representations about the suitability of this software for
  46.  * any purpose.
  47.  *
  48.  * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
  49.  * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
  50.  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
  51.  * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
  52.  * OF SUCH DAMAGE.
  53.  *
  54.  * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
  55.  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  56.  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  57.  * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
  58.  * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
  59.  * OR MODIFICATIONS.
  60.  */
  61. /*
  62.  * if_ppp.h - Point-to-Point Protocol definitions.
  63.  *
  64.  * Copyright (c) 1989 Carnegie Mellon University.
  65.  * All rights reserved.
  66.  *
  67.  * Redistribution and use in source and binary forms are permitted
  68.  * provided that the above copyright notice and this paragraph are
  69.  * duplicated in all such forms and that any documentation,
  70.  * advertising materials, and other materials related to such
  71.  * distribution and use acknowledge that the software was developed
  72.  * by Carnegie Mellon University.  The name of the
  73.  * University may not be used to endorse or promote products derived
  74.  * from this software without specific prior written permission.
  75.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  76.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  77.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  78.  */
  79.  
  80. #include <string.h>
  81.  
  82. #include "ppp.h"
  83. #if PPP_SUPPORT > 0
  84. #include "randm.h"
  85. #include "fsm.h"
  86. #if PAP_SUPPORT > 0
  87. #include "pap.h"
  88. #endif
  89. #if CHAP_SUPPORT > 0
  90. #include "chap.h"
  91. #endif
  92. #include "ipcp.h"
  93. #include "lcp.h"
  94. #include "magic.h"
  95. #include "auth.h"
  96. #if VJ_SUPPORT > 0
  97. #include "vj.h"
  98. #endif
  99. #include "pppdebug.h"
  100. /*************************/
  101. /*** LOCAL DEFINITIONS ***/
  102. /*************************/
  103. /*
  104.  * The basic PPP frame.
  105.  */
  106. #define PPP_ADDRESS(p)  (((u_char *)(p))[0])
  107. #define PPP_CONTROL(p)  (((u_char *)(p))[1])
  108. #define PPP_PROTOCOL(p) ((((u_char *)(p))[2] << 8) + ((u_char *)(p))[3])
  109. /* PPP packet parser states.  Current state indicates operation yet to be
  110.  * completed. */
  111. typedef enum {
  112.     PDIDLE = 0,                 /* Idle state - waiting. */
  113.     PDSTART,                    /* Process start flag. */
  114.     PDADDRESS,                  /* Process address field. */
  115.     PDCONTROL,                  /* Process control field. */
  116.     PDPROTOCOL1,                /* Process protocol field 1. */
  117.     PDPROTOCOL2,                /* Process protocol field 2. */
  118.     PDDATA                      /* Process data byte. */
  119. } PPPDevStates;
  120. #define ESCAPE_P(accm, c) ((accm)[(c) >> 3] & pppACCMMask[c & 0x07])
  121. /************************/
  122. /*** LOCAL DATA TYPES ***/
  123. /************************/
  124. /*
  125.  * PPP interface control block.
  126.  */
  127. typedef struct PPPControl_s {
  128.     char openFlag;                      /* True when in use. */
  129.     char oldFrame;                      /* Old framing character for fd. */
  130.     sio_fd_t fd;                    /* File device ID of port. */
  131.     int  kill_link;                     /* Shut the link down. */
  132.     int  sig_hup;                       /* Carrier lost. */
  133.     int  if_up;                         /* True when the interface is up. */
  134.     int  errCode;                       /* Code indicating why interface is down. */
  135.     struct pbuf *inHead, *inTail;       /* The input packet. */
  136.     PPPDevStates inState;               /* The input process state. */
  137.     char inEscaped;                     /* Escape next character. */
  138.     u16_t inProtocol;                   /* The input protocol code. */
  139.     u16_t inFCS;                        /* Input Frame Check Sequence value. */
  140.     int  mtu;                           /* Peer's mru */
  141.     int  pcomp;                         /* Does peer accept protocol compression? */
  142.     int  accomp;                        /* Does peer accept addr/ctl compression? */
  143.     u_long lastXMit;                    /* Time of last transmission. */
  144.     ext_accm inACCM;                    /* Async-Ctl-Char-Map for input. */
  145.     ext_accm outACCM;                   /* Async-Ctl-Char-Map for output. */
  146. #if VJ_SUPPORT > 0
  147.     int  vjEnabled;                     /* Flag indicating VJ compression enabled. */
  148.     struct vjcompress vjComp;           /* Van Jabobsen compression header. */
  149. #endif
  150.     struct netif netif;
  151.     struct ppp_addrs addrs;
  152.     void (*linkStatusCB)(void *ctx, int errCode, void *arg);
  153.     void *linkStatusCtx;
  154. } PPPControl;
  155. /*
  156.  * Ioctl definitions.
  157.  */
  158. struct npioctl {
  159.     int     protocol;           /* PPP procotol, e.g. PPP_IP */
  160.     enum NPmode mode;
  161. };
  162. /***********************************/
  163. /*** LOCAL FUNCTION DECLARATIONS ***/
  164. /***********************************/
  165. static void pppMain(void *pd);
  166. static void pppDrop(PPPControl *pc);
  167. void pppInProc(int pd, u_char *s, int l);
  168. extern err_t ip_input(struct pbuf *p, struct netif *inp);
  169. /******************************/
  170. /*** PUBLIC DATA STRUCTURES ***/
  171. /******************************/
  172. u_long subnetMask;
  173. static PPPControl pppControl[NUM_PPP]; /* The PPP interface control blocks. */
  174. /*
  175.  * PPP Data Link Layer "protocol" table.
  176.  * One entry per supported protocol.
  177.  * The last entry must be NULL.
  178.  */
  179. struct protent *ppp_protocols[] = {
  180.     &lcp_protent,
  181. #if PAP_SUPPORT > 0
  182.     &pap_protent,
  183. #endif
  184. #if CHAP_SUPPORT > 0
  185.     &chap_protent,
  186. #endif
  187. #if CBCP_SUPPORT > 0
  188.     &cbcp_protent,
  189. #endif
  190.     &ipcp_protent,
  191. #if CCP_SUPPORT > 0
  192.     &ccp_protent,
  193. #endif
  194.     NULL
  195. };
  196. /*
  197.  * Buffers for outgoing packets.  This must be accessed only from the appropriate
  198.  * PPP task so that it doesn't need to be protected to avoid collisions.
  199.  */
  200. u_char outpacket_buf[NUM_PPP][PPP_MRU+PPP_HDRLEN];  
  201. /*****************************/
  202. /*** LOCAL DATA STRUCTURES ***/
  203. /*****************************/
  204. /*
  205.  * FCS lookup table as calculated by genfcstab.
  206.  */
  207. static const u_short fcstab[256] = {
  208.     0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
  209.     0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
  210.     0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
  211.     0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
  212.     0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
  213.     0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
  214.     0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
  215.     0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
  216.     0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
  217.     0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
  218.     0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
  219.     0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
  220.     0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
  221.     0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
  222.     0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
  223.     0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
  224.     0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
  225.     0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
  226.     0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
  227.     0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
  228.     0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
  229.     0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
  230.     0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
  231.     0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
  232.     0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
  233.     0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
  234.     0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
  235.     0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
  236.     0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
  237.     0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
  238.     0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
  239.     0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
  240. };
  241. /* PPP's Asynchronous-Control-Character-Map.  The mask array is used
  242.  * to select the specific bit for a character. */
  243. static u_char pppACCMMask[] = {
  244.     0x01,
  245.     0x02,
  246.     0x04,
  247.     0x08,
  248.     0x10,
  249.     0x20,
  250.     0x40,
  251.     0x80
  252. };
  253. /***********************************/
  254. /*** PUBLIC FUNCTION DEFINITIONS ***/
  255. /***********************************/
  256. /* Initialize the PPP subsystem. */
  257. struct ppp_settings ppp_settings;
  258. void pppInit(void)
  259. {
  260.     struct protent *protp;
  261.     int i, j;
  262.     
  263. memset(&ppp_settings, 0, sizeof(ppp_settings));
  264. ppp_settings.usepeerdns = 1;
  265. /*
  266. *skier:Parameters should be changed
  267. *modified by skier 2006.01.30
  268. *because we could supprot both  CHAP & PAP
  269. */
  270. //pppSetAuth(PPPAUTHTYPE_NONE, NULL, NULL);
  271. if (CHAP_SUPPORT && PAP_SUPPORT)
  272. {
  273.      pppSetAuth(PPPAUTHTYPE_ANY, USER, PASSWORD);
  274. }
  275. else
  276. {
  277.     pppSetAuth(PPPAUTHTYPE_NONE, NULL, NULL); 
  278. }
  279.      /*skier:end 2006.01.30*/
  280.  
  281. magicInit();
  282.     for (i = 0; i < NUM_PPP; i++) {
  283.         pppControl[i].openFlag = 0;
  284. subnetMask = htonl(0xffffff00);
  285.     
  286.         /*
  287.          * Initialize to the standard option set.
  288.          */
  289.         for (j = 0; (protp = ppp_protocols[j]) != NULL; ++j)
  290.             (*protp->init)(i);
  291.     }
  292. #if LINK_STATS
  293.     /* Clear the statistics. */
  294.     memset(&lwip_stats.link, 0, sizeof(lwip_stats.link));
  295. #endif
  296. }
  297. void pppSetAuth(enum pppAuthType authType, const char *user, const char *passwd)
  298. {
  299.     switch(authType) {
  300. case PPPAUTHTYPE_NONE:
  301. default:
  302. #ifdef LWIP_PPP_STRICT_PAP_REJECT
  303.     ppp_settings.refuse_pap = 1;
  304. #else
  305.     /* some providers request pap and accept an empty login/pw */
  306.     ppp_settings.refuse_pap = 0;
  307. #endif
  308.     ppp_settings.refuse_chap = 1;
  309.     break;
  310. case PPPAUTHTYPE_ANY:
  311. /* Warning: Using PPPAUTHTYPE_ANY might have security consequences.
  312.  * RFC 1994 says:
  313.  *
  314.  * In practice, within or associated with each PPP server, there is a
  315.  * database which associates "user" names with authentication
  316.  * information ("secrets").  It is not anticipated that a particular
  317.  * named user would be authenticated by multiple methods.  This would
  318.  * make the user vulnerable to attacks which negotiate the least secure
  319.  * method from among a set (such as PAP rather than CHAP).  If the same
  320.  * secret was used, PAP would reveal the secret to be used later with
  321.  * CHAP.
  322.  *
  323.  * Instead, for each user name there should be an indication of exactly
  324.  * one method used to authenticate that user name.  If a user needs to
  325.  * make use of different authentication methods under different
  326.  * circumstances, then distinct user names SHOULD be employed, each of
  327.  * which identifies exactly one authentication method.
  328.  *
  329.  */
  330.     ppp_settings.refuse_pap = 0;
  331.     ppp_settings.refuse_chap = 0;
  332.     break;
  333. case PPPAUTHTYPE_PAP:
  334.     ppp_settings.refuse_pap = 0;
  335.     ppp_settings.refuse_chap = 1;
  336.     break;
  337. case PPPAUTHTYPE_CHAP:
  338.     ppp_settings.refuse_pap = 1;
  339.     ppp_settings.refuse_chap = 0;
  340.     break;
  341.     }
  342.     if(user) {
  343. strncpy(ppp_settings.user, user, sizeof(ppp_settings.user)-1);
  344. ppp_settings.user[sizeof(ppp_settings.user)-1] = '';
  345.     } else
  346. ppp_settings.user[0] = '';
  347.     if(passwd) {
  348. strncpy(ppp_settings.passwd, passwd, sizeof(ppp_settings.passwd)-1);
  349. ppp_settings.passwd[sizeof(ppp_settings.passwd)-1] = '';
  350.     } else
  351. ppp_settings.passwd[0] = '';
  352. }
  353. /* Open a new PPP connection using the given I/O device.
  354.  * This initializes the PPP control block but does not
  355.  * attempt to negotiate the LCP session.  If this port
  356.  * connects to a modem, the modem connection must be
  357.  * established before calling this.
  358.  * Return a new PPP connection descriptor on success or
  359.  * an error code (negative) on failure. */
  360. int pppOpen(sio_fd_t fd, void (*linkStatusCB)(void *ctx, int errCode, void *arg), void *linkStatusCtx)
  361. {
  362.     PPPControl *pc;
  363.     int pd;
  364.     /* Find a free PPP session descriptor. Critical region? */
  365.     for (pd = 0; pd < NUM_PPP && pppControl[pd].openFlag != 0; pd++);
  366.     if (pd >= NUM_PPP)
  367.         pd = PPPERR_OPEN;
  368.     else
  369.         pppControl[pd].openFlag = !0;
  370.     /* Launch a deamon thread. */
  371.     if (pd >= 0) {
  372.         pppControl[pd].openFlag = 1;
  373.         lcp_init(pd);
  374.         pc = &pppControl[pd];
  375.         pc->fd = fd;
  376.         pc->kill_link = 0;
  377.         pc->sig_hup = 0;
  378.         pc->if_up = 0;
  379.         pc->errCode = 0;
  380.         pc->inState = PDIDLE;
  381.         pc->inHead = NULL;
  382.         pc->inTail = NULL;
  383.         pc->inEscaped = 0;
  384.         pc->lastXMit = 0;
  385. #if VJ_SUPPORT > 0
  386.         pc->vjEnabled = 0;
  387.         vj_compress_init(&pc->vjComp);
  388. #endif
  389.         /* 
  390.          * Default the in and out accm so that escape and flag characters
  391.          * are always escaped. 
  392.          */
  393.         memset(pc->inACCM, 0, sizeof(ext_accm));
  394.         pc->inACCM[15] = 0x60;
  395.         memset(pc->outACCM, 0, sizeof(ext_accm));
  396.         pc->outACCM[15] = 0x60;
  397. pc->linkStatusCB = linkStatusCB;
  398. pc->linkStatusCtx = linkStatusCtx;
  399.         /*Modified by zhouzhigang 2005.01.16 for single thread, start LCP*/
  400. //sys_thread_new(pppMain, (void*)pd, PPP_THREAD_PRIO);
  401.         pppStartCB((void*)pd);
  402. /*Delete by zhouzhigang 2005.01.16 for not useful*/
  403. /*if(!linkStatusCB) {
  404. while(pd >= 0 && !pc->if_up) {
  405. sys_msleep(500);
  406. if (lcp_phase[pd] == PHASE_DEAD) {
  407. pppClose(pd);
  408. if (pc->errCode)
  409. pd = pc->errCode;
  410. else
  411. pd = PPPERR_CONNECT;
  412. }
  413. }
  414. }*/
  415.     }
  416.     return pd;
  417. }
  418. /* Close a PPP connection and release the descriptor. 
  419.  * Any outstanding packets in the queues are dropped.
  420.  * Return 0 on success, an error code on failure. */
  421. int pppClose(int pd)
  422. {
  423.     PPPControl *pc = &pppControl[pd];
  424.     int st = 0;
  425.     /* Disconnect */
  426.     pc->kill_link = !0;
  427.     pppMainWakeup(pd);
  428.     
  429.     if(!pc->linkStatusCB) {
  430.     while(st >= 0 && lcp_phase[pd] != PHASE_DEAD) {
  431.    // sys_msleep(500);
  432.     break;
  433.     }
  434.     }
  435.     return st;
  436. }
  437. /* This function is called when carrier is lost on the PPP channel. */
  438. void pppSigHUP(int pd)
  439. {
  440.     PPPControl *pc = &pppControl[pd];
  441.     pc->sig_hup = 1;
  442.     pppMainWakeup(pd);
  443. }
  444. static void nPut(PPPControl *pc, struct pbuf *nb)
  445. {
  446. struct pbuf *b;
  447. int c;
  448.  
  449.        DEBUG_EVENT(" Send some data to Modem:");
  450.    
  451. for(b = nb; b != NULL; b = b->next) {
  452.     if((c = sio_write(pc->fd, b->payload, b->len)) != b->len) {
  453. PPPDEBUG((LOG_WARNING,
  454.     "PPP nPut: incomplete sio_write(%d,, %u) = %dn", pc->fd, b->len, c));
  455. #if LINK_STATS
  456. lwip_stats.link.err++;
  457. #endif /* LINK_STATS */
  458. pc->lastXMit = 0; /* prepend PPP_FLAG to next packet */
  459. break;
  460.     }
  461. }
  462. pbuf_free(nb);
  463. #if LINK_STATS
  464. lwip_stats.link.xmit++;
  465. #endif /* LINK_STATS */
  466. }
  467. /* 
  468.  * pppAppend - append given character to end of given pbuf.  If outACCM
  469.  * is not NULL and the character needs to be escaped, do so.
  470.  * If pbuf is full, append another.
  471.  * Return the current pbuf.
  472.  */
  473. static struct pbuf *pppAppend(u_char c, struct pbuf *nb, ext_accm *outACCM)
  474. {
  475.     struct pbuf *tb = nb;
  476.     
  477.     /* Make sure there is room for the character and an escape code.
  478.      * Sure we don't quite fill the buffer if the character doesn't
  479.      * get escaped but is one character worth complicating this? */
  480.     /* Note: We assume no packet header. */
  481.     if (nb && (PBUF_POOL_BUFSIZE - nb->len) < 2) {
  482. tb = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
  483. if (tb) {
  484.     nb->next = tb;
  485.         }
  486. #if LINK_STATS
  487. else {
  488.     lwip_stats.link.memerr++;
  489. }
  490. #endif /* LINK_STATS */
  491. nb = tb;
  492.     }
  493.     if (nb) {
  494. if (outACCM && ESCAPE_P(*outACCM, c)) {
  495.             *((u_char*)nb->payload + nb->len++) = PPP_ESCAPE;
  496.             *((u_char*)nb->payload + nb->len++) = c ^ PPP_TRANS;
  497.         }
  498.         else
  499.             *((u_char*)nb->payload + nb->len++) = c;
  500.     }
  501.         
  502.     return tb;
  503. }
  504. /* Send a packet on the given connection. */
  505. static err_t pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *ipaddr)
  506. {
  507.     int pd = (int)netif->state;
  508.     u_short protocol = PPP_IP;
  509.     PPPControl *pc = &pppControl[pd];
  510.     u_int fcsOut = PPP_INITFCS;
  511.     struct pbuf *headMB = NULL, *tailMB = NULL, *p;
  512.     u_char c;
  513.     (void)ipaddr;
  514.     /* Validate parameters. */
  515.     /* We let any protocol value go through - it can't hurt us
  516.      * and the peer will just drop it if it's not accepting it. */
  517. if (pd < 0 || pd >= NUM_PPP || !pc->openFlag || !pb) {
  518.         PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: bad parms prot=%d pb=%pn",
  519.                     pd, protocol, pb));
  520. #if LINK_STATS
  521. lwip_stats.link.opterr++;
  522. lwip_stats.link.drop++;
  523. #endif
  524. return ERR_ARG;
  525. }
  526.     /* Check that the link is up. */
  527. if (lcp_phase[pd] == PHASE_DEAD) {
  528.         PPPDEBUG((LOG_ERR, "pppifOutput[%d]: link not upn", pd));
  529. #if LINK_STATS
  530. lwip_stats.link.rterr++;
  531. lwip_stats.link.drop++;
  532. #endif
  533. return ERR_RTE;
  534. }
  535.     /* Grab an output buffer. */
  536. headMB = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
  537.     if (headMB == NULL) {
  538.         PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: first alloc failn", pd));
  539. #if LINK_STATS
  540. lwip_stats.link.memerr++;
  541. lwip_stats.link.drop++;
  542. #endif /* LINK_STATS */
  543.         return ERR_MEM;
  544.     }
  545.         
  546. #if VJ_SUPPORT > 0
  547.     /* 
  548.      * Attempt Van Jacobson header compression if VJ is configured and
  549.      * this is an IP packet. 
  550.      */
  551.     if (protocol == PPP_IP && pc->vjEnabled) {
  552.         switch (vj_compress_tcp(&pc->vjComp, pb)) {
  553.         case TYPE_IP:
  554.             /* No change...
  555.             protocol = PPP_IP_PROTOCOL;
  556.              */
  557.             break;
  558.         case TYPE_COMPRESSED_TCP:
  559.             protocol = PPP_VJC_COMP;
  560.             break;
  561.         case TYPE_UNCOMPRESSED_TCP:
  562.             protocol = PPP_VJC_UNCOMP;
  563.             break;
  564.         default:
  565.             PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: bad IP packetn", pd));
  566. #if LINK_STATS
  567. lwip_stats.link.proterr++;
  568. lwip_stats.link.drop++;
  569. #endif
  570.          pbuf_free(headMB);
  571.             return ERR_VAL;
  572.         }
  573.     }
  574. #endif
  575.         
  576.     tailMB = headMB;
  577.         
  578.     /* Build the PPP header. */
  579.     if ((sys_jiffies() - pc->lastXMit) >= PPP_MAXIDLEFLAG)
  580.         tailMB = pppAppend(PPP_FLAG, tailMB, NULL);
  581.     pc->lastXMit = sys_jiffies();
  582.     if (!pc->accomp) {
  583.         fcsOut = PPP_FCS(fcsOut, PPP_ALLSTATIONS);
  584.         tailMB = pppAppend(PPP_ALLSTATIONS, tailMB, &pc->outACCM);
  585.         fcsOut = PPP_FCS(fcsOut, PPP_UI);
  586.         tailMB = pppAppend(PPP_UI, tailMB, &pc->outACCM);
  587.     }
  588.     if (!pc->pcomp || protocol > 0xFF) {
  589.         c = (protocol >> 8) & 0xFF;
  590.         fcsOut = PPP_FCS(fcsOut, c);
  591.         tailMB = pppAppend(c, tailMB, &pc->outACCM);
  592.     }
  593.     c = protocol & 0xFF;
  594.     fcsOut = PPP_FCS(fcsOut, c);
  595.     tailMB = pppAppend(c, tailMB, &pc->outACCM);
  596.     
  597.     /* Load packet. */
  598. for(p = pb; p; p = p->next) {
  599.      int n;
  600.      u_char *sPtr;
  601.         sPtr = (u_char*)p->payload;
  602.         n = p->len;
  603.         while (n-- > 0) {
  604.             c = *sPtr++;
  605.             
  606.             /* Update FCS before checking for special characters. */
  607.             fcsOut = PPP_FCS(fcsOut, c);
  608.             
  609.             /* Copy to output buffer escaping special characters. */
  610.             tailMB = pppAppend(c, tailMB, &pc->outACCM);
  611.         }
  612.     }
  613.     /* Add FCS and trailing flag. */
  614.     c = ~fcsOut & 0xFF;
  615.     tailMB = pppAppend(c, tailMB, &pc->outACCM);
  616.     c = (~fcsOut >> 8) & 0xFF;
  617.     tailMB = pppAppend(c, tailMB, &pc->outACCM);
  618.     tailMB = pppAppend(PPP_FLAG, tailMB, NULL);
  619.         
  620.     /* If we failed to complete the packet, throw it away. */
  621.     if (!tailMB) {
  622.         PPPDEBUG((LOG_WARNING,
  623.                     "pppifOutput[%d]: Alloc err - dropping proto=%dn", 
  624.                     pd, protocol));
  625.         pbuf_free(headMB);
  626. #if LINK_STATS
  627. lwip_stats.link.memerr++;
  628. lwip_stats.link.drop++;
  629. #endif
  630.         return ERR_MEM;
  631.     }
  632. /* Send it. */
  633.     PPPDEBUG((LOG_INFO, "pppifOutput[%d]: proto=0x%04Xn", pd, protocol));
  634.     nPut(pc, headMB);
  635.     return ERR_OK;
  636. }
  637. /* Get and set parameters for the given connection.
  638.  * Return 0 on success, an error code on failure. */
  639. int  pppIOCtl(int pd, int cmd, void *arg)
  640. {
  641.     PPPControl *pc = &pppControl[pd];
  642.     int st = 0;
  643.     if (pd < 0 || pd >= NUM_PPP)
  644.         st = PPPERR_PARAM;
  645.     else {
  646.         switch(cmd) {
  647.         case PPPCTLG_UPSTATUS:      /* Get the PPP up status. */
  648.             if (arg) 
  649.                 *(int *)arg = (int)(pc->if_up);
  650.             else
  651.                 st = PPPERR_PARAM;
  652.             break;
  653.         case PPPCTLS_ERRCODE:       /* Set the PPP error code. */
  654.             if (arg) 
  655.                 pc->errCode = *(int *)arg;
  656.             else
  657.                 st = PPPERR_PARAM;
  658.             break;
  659.         case PPPCTLG_ERRCODE:       /* Get the PPP error code. */
  660.             if (arg) 
  661.                 *(int *)arg = (int)(pc->errCode);
  662.             else
  663.                 st = PPPERR_PARAM;
  664.             break;
  665.         case PPPCTLG_FD:
  666.             if (arg) 
  667.                 *(sio_fd_t *)arg = pc->fd;
  668.             else
  669.                 st = PPPERR_PARAM;
  670.             break;
  671.         default:
  672.             st = PPPERR_PARAM;
  673.             break;
  674.         }
  675.     }
  676.     
  677.     return st;
  678. }
  679. /*
  680.  * Return the Maximum Transmission Unit for the given PPP connection.
  681.  */
  682. u_int pppMTU(int pd)
  683. {
  684.     PPPControl *pc = &pppControl[pd];
  685.     u_int st;
  686.     
  687.     /* Validate parameters. */
  688.     if (pd < 0 || pd >= NUM_PPP || !pc->openFlag)
  689.         st = 0;
  690.     else
  691.         st = pc->mtu;
  692.         
  693.     return st;
  694. }
  695. /*
  696.  * Write n characters to a ppp link.
  697.  *  RETURN: >= 0 Number of characters written
  698.  *           -1 Failed to write to device
  699.  */
  700. int pppWrite(int pd, const u_char *s, int n)
  701. {
  702.     PPPControl *pc = &pppControl[pd];
  703.     u_char c;
  704.     u_int fcsOut = PPP_INITFCS;
  705.     struct pbuf *headMB = NULL, *tailMB;
  706. headMB = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
  707.     if (headMB == NULL) {
  708. #if LINK_STATS
  709. lwip_stats.link.memerr++;
  710. lwip_stats.link.proterr++;
  711. #endif /* LINK_STATS */
  712. return PPPERR_ALLOC;
  713.     }
  714.     tailMB = headMB;
  715.         
  716.     /* If the link has been idle, we'll send a fresh flag character to
  717.      * flush any noise. */
  718.     if ((sys_jiffies() - pc->lastXMit) >= PPP_MAXIDLEFLAG)
  719.         tailMB = pppAppend(PPP_FLAG, tailMB, NULL);
  720.     pc->lastXMit = sys_jiffies();
  721.      
  722.     /* Load output buffer. */
  723.     while (n-- > 0) {
  724.         c = *s++;
  725.         
  726.         /* Update FCS before checking for special characters. */
  727.         fcsOut = PPP_FCS(fcsOut, c);
  728.         
  729.         /* Copy to output buffer escaping special characters. */
  730.         tailMB = pppAppend(c, tailMB, &pc->outACCM);
  731.     }
  732.     
  733.     /* Add FCS and trailing flag. */
  734.     c = ~fcsOut & 0xFF;
  735.     tailMB = pppAppend(c, tailMB, &pc->outACCM);
  736.     c = (~fcsOut >> 8) & 0xFF;
  737.     tailMB = pppAppend(c, tailMB, &pc->outACCM);
  738.     tailMB = pppAppend(PPP_FLAG, tailMB, NULL);
  739.         
  740.     /* If we failed to complete the packet, throw it away.
  741.      * Otherwise send it. */
  742.     if (!tailMB) {
  743. PPPDEBUG((LOG_WARNING,
  744.                 "pppWrite[%d]: Alloc err - dropping pbuf len=%dn", pd, headMB->len));
  745. /*                "pppWrite[%d]: Alloc err - dropping %d:%.*H", pd, headMB->len, LWIP_MIN(headMB->len * 2, 40), headMB->payload)); */
  746. pbuf_free(headMB);
  747. #if LINK_STATS
  748. lwip_stats.link.memerr++;
  749. lwip_stats.link.proterr++;
  750. #endif /* LINK_STATS */
  751. return PPPERR_ALLOC;
  752. }
  753.     PPPDEBUG((LOG_INFO, "pppWrite[%d]: len=%dn", pd, headMB->len));
  754. /*     "pppWrite[%d]: %d:%.*H", pd, headMB->len, LWIP_MIN(headMB->len * 2, 40), headMB->payload)); */
  755.     nPut(pc, headMB);
  756.     return PPPERR_NONE;
  757. }
  758. /*
  759.  * ppp_send_config - configure the transmit characteristics of
  760.  * the ppp interface.
  761.  */
  762. void ppp_send_config(
  763.     int unit, 
  764.     int mtu,
  765.     u32_t asyncmap,
  766.     int pcomp, 
  767.     int accomp
  768. )
  769. {
  770.     PPPControl *pc = &pppControl[unit];
  771.     int i;
  772.     
  773.     pc->mtu = mtu;
  774.     pc->pcomp = pcomp;
  775.     pc->accomp = accomp;
  776.     
  777.     /* Load the ACCM bits for the 32 control codes. */
  778.     for (i = 0; i < 32/8; i++)
  779.         pc->outACCM[i] = (u_char)((asyncmap >> (8 * i)) & 0xFF);
  780.     PPPDEBUG((LOG_INFO, "ppp_send_config[%d]: outACCM=%X %X %X %Xn",
  781.                 unit,
  782.                 pc->outACCM[0], pc->outACCM[1], pc->outACCM[2], pc->outACCM[3]));
  783. }
  784. /*
  785.  * ppp_set_xaccm - set the extended transmit ACCM for the interface.
  786.  */
  787. void ppp_set_xaccm(int unit, ext_accm *accm)
  788. {
  789.     memcpy(pppControl[unit].outACCM, accm, sizeof(ext_accm));
  790.     PPPDEBUG((LOG_INFO, "ppp_set_xaccm[%d]: outACCM=%X %X %X %Xn",
  791.                 unit,
  792.                 pppControl[unit].outACCM[0],
  793.                 pppControl[unit].outACCM[1],
  794.                 pppControl[unit].outACCM[2],
  795.                 pppControl[unit].outACCM[3]));
  796. }
  797. /*
  798.  * ppp_recv_config - configure the receive-side characteristics of
  799.  * the ppp interface.
  800.  */
  801. void ppp_recv_config(
  802.     int unit, 
  803.     int mru,
  804.     u32_t asyncmap,
  805.     int pcomp, 
  806.     int accomp
  807. )
  808. {
  809.     PPPControl *pc = &pppControl[unit];
  810.     int i;
  811.     
  812. (void)accomp;
  813. (void)pcomp;
  814. (void)mru;
  815.     /* Load the ACCM bits for the 32 control codes. */
  816.     for (i = 0; i < 32 / 8; i++)
  817.         pc->inACCM[i] = (u_char)(asyncmap >> (i * 8));
  818.     PPPDEBUG((LOG_INFO, "ppp_recv_config[%d]: inACCM=%X %X %X %Xn",
  819.                 unit,
  820.                 pc->inACCM[0], pc->inACCM[1], pc->inACCM[2], pc->inACCM[3]));
  821. }
  822. #if 0
  823. /*
  824.  * ccp_test - ask kernel whether a given compression method
  825.  * is acceptable for use.  Returns 1 if the method and parameters
  826.  * are OK, 0 if the method is known but the parameters are not OK
  827.  * (e.g. code size should be reduced), or -1 if the method is unknown.
  828.  */
  829. int ccp_test(
  830.     int unit, 
  831.     int opt_len, 
  832.     int for_transmit,
  833.     u_char *opt_ptr
  834. )
  835. {
  836.     return 0;   /* XXX Currently no compression. */
  837. }
  838. /*
  839.  * ccp_flags_set - inform kernel about the current state of CCP.
  840.  */
  841. void ccp_flags_set(int unit, int isopen, int isup)
  842. {
  843.     /* XXX */
  844. }
  845. /*
  846.  * ccp_fatal_error - returns 1 if decompression was disabled as a
  847.  * result of an error detected after decompression of a packet,
  848.  * 0 otherwise.  This is necessary because of patent nonsense.
  849.  */
  850. int ccp_fatal_error(int unit)
  851. {
  852.     /* XXX */
  853.     return 0;
  854. }
  855. #endif
  856. /*
  857.  * get_idle_time - return how long the link has been idle.
  858.  */
  859. int get_idle_time(int u, struct ppp_idle *ip)
  860. {   
  861.     /* XXX */
  862. (void)u;
  863. (void)ip;
  864.     return 0;
  865. }
  866. /*
  867.  * Return user specified netmask, modified by any mask we might determine
  868.  * for address `addr' (in network byte order).
  869.  * Here we scan through the system's list of interfaces, looking for
  870.  * any non-point-to-point interfaces which might appear to be on the same
  871.  * network as `addr'.  If we find any, we OR in their netmask to the
  872.  * user-specified netmask.
  873.  */
  874. u32_t GetMask(u32_t addr)
  875. {
  876.     u32_t mask, nmask;
  877.     
  878.     htonl(addr);
  879.     if (IN_CLASSA(addr))    /* determine network mask for address class */
  880.         nmask = IN_CLASSA_NET;
  881.     else if (IN_CLASSB(addr))
  882.         nmask = IN_CLASSB_NET;
  883.     else
  884.         nmask = IN_CLASSC_NET;
  885.     /* class D nets are disallowed by bad_ip_adrs */
  886.     mask = subnetMask | htonl(nmask);
  887.     
  888.     /* XXX
  889.      * Scan through the system's network interfaces.
  890.      * Get each netmask and OR them into our mask.
  891.      */
  892.     
  893.     return mask;
  894. }
  895. /*
  896.  * sifvjcomp - config tcp header compression
  897.  */
  898. int sifvjcomp(
  899.     int pd, 
  900.     int vjcomp, 
  901.     int cidcomp, 
  902.     int maxcid
  903. )
  904. {
  905. #if VJ_SUPPORT > 0
  906.     PPPControl *pc = &pppControl[pd];
  907.     
  908.     pc->vjEnabled = vjcomp;
  909.     pc->vjComp.compressSlot = cidcomp;
  910.     pc->vjComp.maxSlotIndex = maxcid;
  911.     PPPDEBUG((LOG_INFO, "sifvjcomp: VJ compress enable=%d slot=%d max slot=%dn",
  912.                 vjcomp, cidcomp, maxcid));
  913. #endif
  914.     return 0;
  915. }
  916. /*
  917.  * pppifNetifInit - netif init callback
  918.  */
  919. static err_t pppifNetifInit(struct netif *netif)
  920. {
  921. netif->name[0] = 'p';
  922. netif->name[1] = 'p';
  923. netif->output = pppifOutput;
  924. netif->mtu = pppMTU((int)netif->state);
  925. return ERR_OK;
  926. }
  927. /*
  928.  * sifup - Config the interface up and enable IP packets to pass.
  929.  */
  930. int sifup(int pd)
  931. {
  932.     PPPControl *pc = &pppControl[pd];
  933.     int st = 1;
  934.     
  935.     if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
  936.         st = 0;
  937.         PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parmsn", pd));
  938.     } else {
  939. netif_remove(&pc->netif);
  940. if (netif_add(&pc->netif, &pc->addrs.our_ipaddr, &pc->addrs.netmask, &pc->addrs.his_ipaddr, (void *)pd, pppifNetifInit, ip_input)) {
  941.          pc->if_up = 1;
  942.          pc->errCode = PPPERR_NONE;
  943. /*
  944. *new added by skier 2006.01.30
  945. */
  946. pc->netif.flags = NETIF_FLAG_UP;
  947.                      /*skier:end 2006.01.30*/
  948. PPPDEBUG((LOG_DEBUG, "sifup: unit %d: linkStatusCB=%lx errCode=%dn", pd, pc->linkStatusCB, pc->errCode));
  949. if(pc->linkStatusCB)
  950. pc->linkStatusCB(pc->linkStatusCtx, pc->errCode, &pc->addrs);
  951. } else {
  952.          st = 0;
  953.          PPPDEBUG((LOG_ERR, "sifup[%d]: netif_add failedn", pd));
  954. }
  955.     }
  956.     return st;
  957. }
  958. /*
  959.  * sifnpmode - Set the mode for handling packets for a given NP.
  960.  */
  961. int sifnpmode(int u, int proto, enum NPmode mode)
  962. {
  963. (void)u;
  964. (void)proto;
  965. (void)mode;
  966.     return 0;
  967. }
  968. /*
  969.  * sifdown - Config the interface down and disable IP.
  970.  */
  971. int sifdown(int pd)
  972. {
  973.     PPPControl *pc = &pppControl[pd];
  974.     int st = 1;
  975.     
  976.     if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
  977.         st = 0;
  978.         PPPDEBUG((LOG_WARNING, "sifdown[%d]: bad parmsn", pd));
  979.     } else {
  980.         pc->if_up = 0;
  981. netif_remove(&pc->netif);
  982. PPPDEBUG((LOG_DEBUG, "sifdown: unit %d: linkStatusCB=%lx errCode=%dn", pd, pc->linkStatusCB, pc->errCode));
  983. if(pc->linkStatusCB)
  984. pc->linkStatusCB(pc->linkStatusCtx, PPPERR_CONNECT, NULL);
  985. }
  986.     return st;
  987. }
  988. /*
  989.  * sifaddr - Config the interface IP addresses and netmask.
  990.  */
  991. int sifaddr(
  992.     int pd,             /* Interface unit ??? */
  993.     u32_t o,        /* Our IP address ??? */
  994.     u32_t h,        /* His IP address ??? */
  995.     u32_t m,        /* IP subnet mask ??? */
  996.     u32_t ns1,      /* Primary DNS */
  997.     u32_t ns2       /* Secondary DNS */
  998. )
  999. {
  1000.     PPPControl *pc = &pppControl[pd];
  1001.     int st = 1;
  1002.     
  1003.     if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
  1004.         st = 0;
  1005.         PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parmsn", pd));
  1006.     } else {
  1007. memcpy(&pc->addrs.our_ipaddr, &o, sizeof(o));
  1008. memcpy(&pc->addrs.his_ipaddr, &h, sizeof(h));
  1009. memcpy(&pc->addrs.netmask, &m, sizeof(m));
  1010. memcpy(&pc->addrs.dns1, &ns1, sizeof(ns1));
  1011. memcpy(&pc->addrs.dns2, &ns2, sizeof(ns2));
  1012.     }
  1013.     return st;
  1014. }
  1015. /*
  1016.  * cifaddr - Clear the interface IP addresses, and delete routes
  1017.  * through the interface if possible.
  1018.  */
  1019. int cifaddr(
  1020.     int pd,         /* Interface unit ??? */
  1021.     u32_t o,    /* Our IP address ??? */
  1022.     u32_t h     /* IP broadcast address ??? */
  1023. )
  1024. {
  1025.     PPPControl *pc = &pppControl[pd];
  1026.     int st = 1;
  1027.     
  1028. (void)o;
  1029. (void)h;
  1030.     if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
  1031.         st = 0;
  1032.         PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parmsn", pd));
  1033.     } else {
  1034. IP4_ADDR(&pc->addrs.our_ipaddr, 0,0,0,0);
  1035. IP4_ADDR(&pc->addrs.his_ipaddr, 0,0,0,0);
  1036. IP4_ADDR(&pc->addrs.netmask, 255,255,255,0);
  1037. IP4_ADDR(&pc->addrs.dns1, 0,0,0,0);
  1038. IP4_ADDR(&pc->addrs.dns2, 0,0,0,0);
  1039.     }
  1040.     return st;
  1041. }
  1042. /*
  1043.  * sifdefaultroute - assign a default route through the address given.
  1044.  */
  1045. int sifdefaultroute(int pd, u32_t l, u32_t g)
  1046. {
  1047.     PPPControl *pc = &pppControl[pd];
  1048.     int st = 1;
  1049.     
  1050. (void)l;
  1051. (void)g;
  1052.     if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
  1053.         st = 0;
  1054.         PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parmsn", pd));
  1055.     } else {
  1056. netif_set_default(&pc->netif);
  1057.     }
  1058.     /* TODO: check how PPP handled the netMask, previously not set by ipSetDefault */
  1059.     return st;
  1060. }
  1061. /*
  1062.  * cifdefaultroute - delete a default route through the address given.
  1063.  */
  1064. int cifdefaultroute(int pd, u32_t l, u32_t g)
  1065. {
  1066.     PPPControl *pc = &pppControl[pd];
  1067.     int st = 1;
  1068.     
  1069. (void)l;
  1070. (void)g;
  1071.     if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
  1072.         st = 0;
  1073.         PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parmsn", pd));
  1074.     } else {
  1075. netif_set_default(NULL);
  1076.     }
  1077.     return st;
  1078. }
  1079. void
  1080. pppMainWakeup(int pd)
  1081. {
  1082. PPPDEBUG((LOG_DEBUG, "pppMainWakeup: unit %dn", pd));
  1083. sio_read_abort(pppControl[pd].fd);
  1084. }
  1085. /* these callbacks are necessary because lcp_* functions
  1086.    must be called in the same context as pppInput(),
  1087.    namely the tcpip_thread(), essentially because
  1088.    they manipulate timeouts which are thread-private
  1089. */
  1090. static void
  1091. pppStartCB(void *arg)
  1092. {
  1093.     int pd = (int)arg;
  1094. PPPDEBUG((LOG_DEBUG, "pppStartCB: unit %dn", pd));
  1095.     lcp_lowerup(pd);
  1096.     lcp_open(pd);      /* Start protocol */
  1097. }
  1098. static void
  1099. pppStopCB(void *arg)
  1100. {
  1101.     int pd = (int)arg;
  1102. PPPDEBUG((LOG_DEBUG, "pppStopCB: unit %dn", pd));
  1103.     lcp_close(pd, "User request");
  1104. }
  1105. static void
  1106. pppHupCB(void *arg)
  1107. {
  1108.     int pd = (int)arg;
  1109. PPPDEBUG((LOG_DEBUG, "pppHupCB: unit %dn", pd));
  1110.     lcp_lowerdown(pd);
  1111.     link_terminated(pd);
  1112. }
  1113. /**********************************/
  1114. /*** LOCAL FUNCTION DEFINITIONS ***/
  1115. /**********************************/
  1116. /* The main PPP process function.  This implements the state machine according
  1117.  * to section 4 of RFC 1661: The Point-To-Point Protocol. */
  1118.  #if 0
  1119. static void pppMain(void *arg)
  1120. {
  1121.     int pd = (int)arg;
  1122.     struct pbuf *p;
  1123.     PPPControl* pc;
  1124.     pc = &pppControl[pd];
  1125.     p = pbuf_alloc(PBUF_RAW, PPP_MRU+PPP_HDRLEN, PBUF_RAM);
  1126.     if(!p) {
  1127. LWIP_ASSERT("p != NULL", p);
  1128. pc->errCode = PPPERR_ALLOC;
  1129. goto out;
  1130.     }
  1131.     /*
  1132.      * Start the connection and handle incoming events (packet or timeout).
  1133.      */
  1134. PPPDEBUG((LOG_INFO, "pppMain: unit %d: Connectingn", pd));
  1135.     tcpip_callback(pppStartCB, arg);
  1136.     while (lcp_phase[pd] != PHASE_DEAD) {
  1137.         if (pc->kill_link) {
  1138.      PPPDEBUG((LOG_DEBUG, "pppMainWakeup: unit %d kill_link -> pppStopCBn", pd));
  1139. pc->errCode = PPPERR_USER;
  1140. /* This will leave us at PHASE_DEAD. */
  1141.      tcpip_callback(pppStopCB, arg);
  1142. pc->kill_link = 0;
  1143.         }
  1144.         else if (pc->sig_hup) {
  1145.      PPPDEBUG((LOG_DEBUG, "pppMainWakeup: unit %d sig_hup -> pppHupCBn", pd));
  1146. pc->sig_hup = 0;
  1147.      tcpip_callback(pppHupCB, arg);
  1148.         } else {
  1149.         //delete by zhouzhigang 2006.01.20 for compile
  1150.            #if 0
  1151. int c = sio_read(pc->fd, p->payload, p->len);
  1152. if(c > 0) {
  1153. pppInProc(pd, p->payload, c);
  1154. } else {
  1155.  //   PPPDEBUG((LOG_DEBUG, "pppMainWakeup: unit %d sio_read len=%d returned %dn", pd, p->len, c));
  1156.     sys_msleep(1); /* give other tasks a chance to run */
  1157. }
  1158. #endif
  1159.         }
  1160.     }
  1161. PPPDEBUG((LOG_INFO, "pppMain: unit %d: PHASE_DEADn", pd));
  1162.     pbuf_free(p);
  1163. out:
  1164. PPPDEBUG((LOG_DEBUG, "pppMain: unit %d: linkStatusCB=%lx errCode=%dn", pd, pc->linkStatusCB, pc->errCode));
  1165.     if(pc->linkStatusCB)
  1166.     pc->linkStatusCB(pc->linkStatusCtx, pc->errCode ? pc->errCode : PPPERR_PROTOCOL, NULL);
  1167.     pc->openFlag = 0;
  1168. }
  1169. #endif
  1170. static struct pbuf *pppSingleBuf(struct pbuf *p)
  1171. {
  1172. struct pbuf *q, *b;
  1173. u_char *pl;
  1174. if(p->tot_len == p->len)
  1175. return p;
  1176. q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
  1177. if(!q) {
  1178. PPPDEBUG((LOG_ERR,
  1179.                         "pppSingleBuf: unable to alloc new buf (%d)n", p->tot_len));
  1180. return p; /* live dangerously */
  1181. }
  1182. for(b = p, pl = q->payload; b != NULL; b = b->next) {
  1183. memcpy(pl, b->payload, b->len);
  1184. pl += b->len;
  1185. }
  1186. pbuf_free(p);
  1187. return q;
  1188. }
  1189. struct pppInputHeader {
  1190. int unit;
  1191. u16_t proto;
  1192. };
  1193. /*
  1194.  * Pass the processed input packet to the appropriate handler.
  1195.  * This function and all handlers run in the context of the tcpip_thread
  1196.  */
  1197. static void pppInput(void *arg)
  1198. {
  1199. struct pbuf *nb = (struct pbuf *)arg;
  1200.     u16_t protocol;
  1201.     int pd;
  1202. pd = ((struct pppInputHeader *)nb->payload)->unit;
  1203. protocol = ((struct pppInputHeader *)nb->payload)->proto;
  1204.     pbuf_header(nb, -(int)sizeof(struct pppInputHeader));
  1205. #if LINK_STATS
  1206.     lwip_stats.link.recv++;
  1207. #endif /* LINK_STATS */
  1208.     /*
  1209.      * Toss all non-LCP packets unless LCP is OPEN.
  1210.      * Until we get past the authentication phase, toss all packets
  1211.      * except LCP, LQR and authentication packets.
  1212.      */
  1213.     if((lcp_phase[pd] <= PHASE_AUTHENTICATE) && (protocol != PPP_LCP)) {
  1214.     if(!((protocol == PPP_LQR) || (protocol == PPP_PAP) || (protocol == PPP_CHAP)) ||
  1215. (lcp_phase[pd] != PHASE_AUTHENTICATE)) {
  1216. PPPDEBUG((LOG_INFO, "pppInput: discarding proto 0x%04X in phase %dn", protocol, lcp_phase[pd]));
  1217. goto drop;
  1218.     }
  1219.     }
  1220.     switch(protocol) {
  1221.     case PPP_VJC_COMP:      /* VJ compressed TCP */
  1222. #if VJ_SUPPORT > 0
  1223.         PPPDEBUG((LOG_INFO, "pppInput[%d]: vj_comp in pbuf len=%dn", pd, nb->len));
  1224.         /*
  1225.          * Clip off the VJ header and prepend the rebuilt TCP/IP header and
  1226.          * pass the result to IP.
  1227.          */
  1228.         if (vj_uncompress_tcp(&nb, &pppControl[pd].vjComp) >= 0) {
  1229.             pppControl[pd].netif.input(nb, &pppControl[pd].netif);
  1230. return;
  1231.         }
  1232. /* Something's wrong so drop it. */
  1233. PPPDEBUG((LOG_WARNING, "pppInput[%d]: Dropping VJ compressedn", pd));
  1234. #else
  1235.         /* No handler for this protocol so drop the packet. */
  1236.         PPPDEBUG((LOG_INFO, "pppInput[%d]: drop VJ Comp in %d:%sn", pd, nb->len, nb->payload));
  1237. #endif /* VJ_SUPPORT > 0 */
  1238. break;
  1239.     case PPP_VJC_UNCOMP:    /* VJ uncompressed TCP */
  1240. #if VJ_SUPPORT > 0
  1241.         PPPDEBUG((LOG_INFO, "pppInput[%d]: vj_un in pbuf len=%dn", pd, nb->len));
  1242.         /*
  1243.          * Process the TCP/IP header for VJ header compression and then pass
  1244.          * the packet to IP.
  1245.          */
  1246.         if (vj_uncompress_uncomp(nb, &pppControl[pd].vjComp) >= 0) {
  1247.             pppControl[pd].netif.input(nb, &pppControl[pd].netif);
  1248. return;
  1249.         }
  1250. /* Something's wrong so drop it. */
  1251. PPPDEBUG((LOG_WARNING, "pppInput[%d]: Dropping VJ uncompressedn", pd));
  1252. #else
  1253.         /* No handler for this protocol so drop the packet. */
  1254.         PPPDEBUG((LOG_INFO,
  1255.                     "pppInput[%d]: drop VJ UnComp in %d:.*Hn", 
  1256.                     pd, nb->len, LWIP_MIN(nb->len * 2, 40), nb->payload));
  1257. #endif /* VJ_SUPPORT > 0 */
  1258. break;
  1259.     case PPP_IP:            /* Internet Protocol */
  1260.         PPPDEBUG((LOG_INFO, "pppInput[%d]: ip in pbuf len=%dn", pd, nb->len));
  1261.         pppControl[pd].netif.input(nb, &pppControl[pd].netif);
  1262. return;
  1263.     default:
  1264. {
  1265. struct protent *protp;
  1266. int i;
  1267. /*
  1268.  * Upcall the proper protocol input routine.
  1269.  */
  1270. for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) {
  1271. if (protp->protocol == protocol && protp->enabled_flag) {
  1272. PPPDEBUG((LOG_INFO, "pppInput[%d]: %s len=%dn", pd, protp->name, nb->len));
  1273. nb = pppSingleBuf(nb);
  1274. (*protp->input)(pd, nb->payload, nb->len);
  1275. goto out;
  1276. }
  1277. }
  1278. /* No handler for this protocol so reject the packet. */
  1279. PPPDEBUG((LOG_INFO, "pppInput[%d]: rejecting unsupported proto 0x%04X len=%dn", pd, protocol, nb->len));
  1280. pbuf_header(nb, sizeof(protocol));
  1281. #if BYTE_ORDER == LITTLE_ENDIAN
  1282. protocol = htons(protocol);
  1283. memcpy(nb->payload, &protocol, sizeof(protocol));
  1284. #endif
  1285. lcp_sprotrej(pd, nb->payload, nb->len);
  1286. }
  1287. break;
  1288.     }
  1289. drop:
  1290. #if LINK_STATS
  1291.     lwip_stats.link.drop++;
  1292. #endif
  1293. out:
  1294.     pbuf_free(nb);
  1295.     return;
  1296. }
  1297. /*
  1298.  * Drop the input packet.
  1299.  */
  1300. static void pppDrop(PPPControl *pc)
  1301. {
  1302.     if (pc->inHead != NULL) {
  1303. #if 0     
  1304.         PPPDEBUG((LOG_INFO, "pppDrop: %d:%.*Hn", pc->inHead->len, min(60, pc->inHead->len * 2), pc->inHead->payload));
  1305. #endif
  1306.         PPPDEBUG((LOG_INFO, "pppDrop: pbuf len=%dn", pc->inHead->len));
  1307. if (pc->inTail && (pc->inTail != pc->inHead))
  1308.     pbuf_free(pc->inTail);
  1309.         pbuf_free(pc->inHead);
  1310.         pc->inHead = NULL;
  1311.         pc->inTail = NULL;
  1312.     }
  1313. #if VJ_SUPPORT > 0
  1314.     vj_uncompress_err(&pc->vjComp);
  1315. #endif
  1316. #if LINK_STATS
  1317.     lwip_stats.link.drop++;
  1318. #endif /* LINK_STATS */
  1319. }
  1320. /*
  1321.  * Process a received octet string.
  1322.  */
  1323.  void pppInProc(int pd, u_char *s, int l)
  1324. {
  1325.     PPPControl *pc = &pppControl[pd];
  1326.     struct pbuf *nextNBuf;
  1327.     u_char curChar;
  1328.     PPPDEBUG((LOG_DEBUG, "pppInProc[%d]: got %d bytesn", pd, l));
  1329.     while (l-- > 0) {
  1330.         curChar = *s++;
  1331.         
  1332.         /* Handle special characters. */
  1333.         if (ESCAPE_P(pc->inACCM, curChar)) {
  1334.             /* Check for escape sequences. */
  1335.             /* XXX Note that this does not handle an escaped 0x5d character which
  1336.              * would appear as an escape character.  Since this is an ASCII ']'
  1337.              * and there is no reason that I know of to escape it, I won't complicate
  1338.              * the code to handle this case. GLL */
  1339.             if (curChar == PPP_ESCAPE)
  1340.                 pc->inEscaped = 1;
  1341.             /* Check for the flag character. */
  1342.             else if (curChar == PPP_FLAG) {
  1343.                 /* If this is just an extra flag character, ignore it. */
  1344.                 if (pc->inState <= PDADDRESS)
  1345.                     ;
  1346.                 /* If we haven't received the packet header, drop what has come in. */
  1347.                 else if (pc->inState < PDDATA) {
  1348.                     PPPDEBUG((LOG_WARNING,
  1349.                                 "pppInProc[%d]: Dropping incomplete packet %dn", 
  1350.                                 pd, pc->inState));
  1351. #if LINK_STATS
  1352. lwip_stats.link.lenerr++;
  1353. #endif
  1354.                     pppDrop(pc);
  1355.                 }
  1356.                 /* If the fcs is invalid, drop the packet. */
  1357.                 else if (pc->inFCS != PPP_GOODFCS) {
  1358.                     PPPDEBUG((LOG_INFO,
  1359.                                 "pppInProc[%d]: Dropping bad fcs 0x%04X proto=0x%04Xn", 
  1360.                                 pd, pc->inFCS, pc->inProtocol));
  1361. #if LINK_STATS
  1362. lwip_stats.link.chkerr++;
  1363. #endif
  1364.                     pppDrop(pc);
  1365.                 }
  1366.                 /* Otherwise it's a good packet so pass it on. */
  1367.                 else {
  1368.                     
  1369.                     /* Trim off the checksum. */
  1370.     if(pc->inTail->len >= 2) {
  1371. pc->inTail->len -= 2;
  1372. pc->inTail->tot_len = pc->inTail->len;
  1373. if (pc->inTail != pc->inHead) {
  1374.     pbuf_cat(pc->inHead, pc->inTail);
  1375. }
  1376.     } else {
  1377. pc->inTail->tot_len = pc->inTail->len;
  1378. if (pc->inTail != pc->inHead) {
  1379.     pbuf_cat(pc->inHead, pc->inTail);
  1380. }
  1381. pbuf_realloc(pc->inHead, pc->inHead->tot_len - 2);
  1382.     }
  1383.                     /* Dispatch the packet thereby consuming it. */
  1384. /*Modified by zhouzhigang 2005.01.16 for single thread*/
  1385.     pppInput((void *)(pc->inHead));
  1386.          #if 0
  1387.     if(tcpip_callback(pppInput, pc->inHead) != ERR_OK) {
  1388.                      PPPDEBUG((LOG_ERR,
  1389.     "pppInProc[%d]: tcpip_callback() failed, dropping packetn", pd));
  1390. pbuf_free(pc->inHead);
  1391. #if LINK_STATS
  1392. lwip_stats.link.drop++;
  1393. #endif
  1394.     }
  1395. #endif
  1396.                     pc->inHead = NULL;
  1397.                     pc->inTail = NULL;
  1398.                 }
  1399.                     
  1400.                 /* Prepare for a new packet. */
  1401.                 pc->inFCS = PPP_INITFCS;
  1402.                 pc->inState = PDADDRESS;
  1403.                 pc->inEscaped = 0;
  1404.             }
  1405.             /* Other characters are usually control characters that may have
  1406.              * been inserted by the physical layer so here we just drop them. */
  1407.             else {
  1408.                 PPPDEBUG((LOG_WARNING,
  1409.                             "pppInProc[%d]: Dropping ACCM char <%d>n", pd, curChar));
  1410.             }
  1411.         }
  1412.         /* Process other characters. */
  1413.         else {
  1414.             /* Unencode escaped characters. */
  1415.             if (pc->inEscaped) {
  1416.                 pc->inEscaped = 0;
  1417.                 curChar ^= PPP_TRANS;
  1418.             }
  1419.             
  1420.             /* Process character relative to current state. */
  1421.             switch(pc->inState) {
  1422.             case PDIDLE:                    /* Idle state - waiting. */
  1423.                 /* Drop the character if it's not 0xff
  1424.                  * we would have processed a flag character above. */
  1425.                 if (curChar != PPP_ALLSTATIONS) {
  1426.                  break;
  1427. }
  1428. /* Fall through */
  1429.             case PDSTART:                   /* Process start flag. */
  1430.                 /* Prepare for a new packet. */
  1431.                 pc->inFCS = PPP_INITFCS;
  1432. /* Fall through */
  1433.             case PDADDRESS:                 /* Process address field. */
  1434.                 if (curChar == PPP_ALLSTATIONS) {
  1435.                     pc->inState = PDCONTROL;
  1436.                     break;
  1437.                 }
  1438.                 /* Else assume compressed address and control fields so
  1439.                  * fall through to get the protocol... */
  1440.             case PDCONTROL:                 /* Process control field. */
  1441.                 /* If we don't get a valid control code, restart. */
  1442.                 if (curChar == PPP_UI) {
  1443.                     pc->inState = PDPROTOCOL1;
  1444.                  break;
  1445.                 }
  1446. #if 0
  1447.                 else {
  1448.                     PPPDEBUG((LOG_WARNING,
  1449.                                 "pppInProc[%d]: Invalid control <%d>n", pd, curChar));
  1450.                     pc->inState = PDSTART;
  1451.                 }
  1452. #endif
  1453.             case PDPROTOCOL1:               /* Process protocol field 1. */
  1454.                 /* If the lower bit is set, this is the end of the protocol
  1455.                  * field. */
  1456.                 if (curChar & 1) {
  1457.                     pc->inProtocol = curChar;
  1458.                     pc->inState = PDDATA;
  1459.                 }
  1460.                 else {
  1461.                     pc->inProtocol = (u_int)curChar << 8;
  1462.                     pc->inState = PDPROTOCOL2;
  1463.                 }
  1464.                 break;
  1465.             case PDPROTOCOL2:               /* Process protocol field 2. */
  1466.                 pc->inProtocol |= curChar;
  1467.                 pc->inState = PDDATA;
  1468.                 break;
  1469.             case PDDATA:                    /* Process data byte. */
  1470.                 /* Make space to receive processed data. */
  1471.                 if (pc->inTail == NULL || pc->inTail->len == PBUF_POOL_BUFSIZE) {
  1472.     if(pc->inTail) {
  1473. pc->inTail->tot_len = pc->inTail->len;
  1474. if (pc->inTail != pc->inHead) {
  1475.     pbuf_cat(pc->inHead, pc->inTail);
  1476. }
  1477.     }
  1478.                     /* If we haven't started a packet, we need a packet header. */
  1479.                     nextNBuf = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
  1480.                     if (nextNBuf == NULL) {
  1481.                         /* No free buffers.  Drop the input packet and let the
  1482.                          * higher layers deal with it.  Continue processing
  1483.                          * the received pbuf chain in case a new packet starts. */
  1484.                         PPPDEBUG((LOG_ERR, "pppInProc[%d]: NO FREE MBUFS!n", pd));
  1485. #if LINK_STATS
  1486. lwip_stats.link.memerr++;
  1487. #endif /* LINK_STATS */
  1488.                         pppDrop(pc);
  1489.                         pc->inState = PDSTART;  /* Wait for flag sequence. */
  1490. break;
  1491.                     }
  1492.     if (pc->inHead == NULL) {
  1493. struct pppInputHeader *pih = nextNBuf->payload;
  1494. pih->unit = pd;
  1495. pih->proto = pc->inProtocol;
  1496. nextNBuf->len += sizeof(*pih);
  1497. pc->inHead = nextNBuf;
  1498.     }
  1499.     pc->inTail = nextNBuf;
  1500.                 }
  1501.                 /* Load character into buffer. */
  1502.                 ((u_char*)pc->inTail->payload)[pc->inTail->len++] = curChar;
  1503.                 break;
  1504.             }
  1505.             /* update the frame check sequence number. */
  1506.             pc->inFCS = PPP_FCS(pc->inFCS, curChar);
  1507.         }
  1508.     }
  1509. avRandomize();
  1510. }
  1511. #if( PPP_DEBUG == DBG_ON)
  1512. char debug_buf[1024];
  1513. void ppp_trace(int level, const char *format,...)
  1514. {
  1515.      
  1516.      sprintf(debug_buf, format);
  1517.      DEBUG_EVENT(debug_buf);
  1518. }
  1519. #endif
  1520. #endif /* PPP_SUPPORT */