pppsm.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2001-2004 by egnite Software GmbH. All rights reserved.
00003  *
00004  * Redistribution and use in source and binary forms, with or without
00005  * modification, are permitted provided that the following conditions
00006  * are met:
00007  *
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the copyright holders nor the names of
00014  *    contributors may be used to endorse or promote products derived
00015  *    from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS
00018  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00019  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00020  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE
00021  * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00022  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00023  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00024  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00025  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00026  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00027  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00028  * SUCH DAMAGE.
00029  *
00030  * For additional information see http://www.ethernut.de/
00031  *
00032  * -
00033  */
00034 
00035 /*
00036  * $Log: pppsm.c,v $
00037  * Revision 1.8  2008/08/11 07:00:32  haraldkipp
00038  * BSD types replaced by stdint types (feature request #1282721).
00039  *
00040  * Revision 1.7  2005/04/30 16:42:42  chaac
00041  * Fixed bug in handling of NUTDEBUG. Added include for cfg/os.h. If NUTDEBUG
00042  * is defined in NutConf, it will make effect where it is used.
00043  *
00044  * Revision 1.6  2005/04/05 17:44:57  haraldkipp
00045  * Made stack space configurable.
00046  *
00047  * Revision 1.5  2004/03/16 16:48:45  haraldkipp
00048  * Added Jan Dubiec's H8/300 port.
00049  *
00050  * Revision 1.4  2004/03/08 11:28:37  haraldkipp
00051  * HDLC functions moved to async HDLC driver.
00052  *
00053  * Revision 1.3  2004/01/30 11:37:58  haraldkipp
00054  * Handle magic number rejects
00055  *
00056  * Revision 1.2  2003/08/14 15:14:19  haraldkipp
00057  * Do not increment ID when resending.
00058  * Added authentication retries.
00059  *
00060  * Revision 1.1.1.1  2003/05/09 14:41:37  haraldkipp
00061  * Initial using 3.2.1
00062  *
00063  * Revision 1.2  2003/05/06 18:18:37  harald
00064  * PPP hack for simple UART support, functions reordered.
00065  *
00066  * Revision 1.1  2003/03/31 14:53:28  harald
00067  * Prepare release 3.1
00068  *
00069  */
00070 
00071 #include <cfg/os.h>
00072 #include <cfg/ppp.h>
00073 
00074 #include <string.h>
00075 #include <io.h>
00076 #include <fcntl.h>
00077 #include <dev/uart.h>
00078 
00079 #include <sys/thread.h>
00080 #include <sys/heap.h>
00081 #include <sys/event.h>
00082 #include <sys/timer.h>
00083 
00084 #include <net/if_var.h>
00085 #include <dev/ppp.h>
00086 
00087 #include <netinet/if_ppp.h>
00088 #include <netinet/ppp_fsm.h>
00089 
00090 #ifdef NUTDEBUG
00091 #include <net/netdebug.h>
00092 #endif
00093 
00094 #ifndef NUT_THREAD_PPPSMSTACK
00095 #define NUT_THREAD_PPPSMSTACK   512
00096 #endif
00097 
00102 
00103 uint32_t new_magic = 0x12345678;
00104 static HANDLE pppThread;
00105 
00106 
00112 THREAD(NutPppSm, arg)
00113 {
00114     NUTDEVICE *dev = arg;
00115     PPPDCB *dcb = dev->dev_dcb;
00116     uint_fast8_t retries;
00117 
00118     for (;;) {
00119         NutSleep(5000);
00120         new_magic++;
00121 
00122         retries = dcb->dcb_retries;
00123 
00124         /*
00125          * LCP timeouts.
00126          */
00127         switch (dcb->dcb_lcp_state) {
00128         case PPPS_CLOSING:
00129         case PPPS_STOPPING:
00130             if (retries < 9) {
00131                 if (retries) {
00132                     NutLcpOutput(dev, XCP_TERMREQ, dcb->dcb_reqid, 0);
00133                 }
00134                 dcb->dcb_retries = retries + 1;
00135             } else
00136                 dcb->dcb_lcp_state = (dcb->dcb_lcp_state == PPPS_CLOSING) ? PPPS_CLOSED : PPPS_STOPPED;
00137             break;
00138 
00139         case PPPS_REQSENT:
00140         case PPPS_ACKSENT:
00141             if (retries < 9) {
00142                 if (retries)
00143                     LcpTxConfReq(dev, dcb->dcb_reqid, 0);
00144                 dcb->dcb_retries = retries + 1;
00145             } else
00146                 dcb->dcb_lcp_state = PPPS_STOPPED;
00147             break;
00148         }
00149 
00150         /*
00151          * Authentication timeouts.
00152          */
00153         if (dcb->dcb_auth_state == PAPCS_AUTHREQ) {
00154             if (retries < 9) {
00155                 if (retries)
00156                     PapTxAuthReq(dev, dcb->dcb_reqid);
00157                 dcb->dcb_retries = retries + 1;
00158             } else
00159                 dcb->dcb_lcp_state = PPPS_STOPPED;
00160         }
00161 
00162         /*
00163          * IPCP timeouts.
00164          */
00165         switch (dcb->dcb_ipcp_state) {
00166         case PPPS_CLOSING:
00167         case PPPS_STOPPING:
00168             if (retries < 9) {
00169                 if (retries)
00170                     NutIpcpOutput(dev, XCP_TERMREQ, dcb->dcb_reqid, 0);
00171                 dcb->dcb_retries = retries + 1;
00172             } else
00173                 dcb->dcb_ipcp_state = (dcb->dcb_ipcp_state == PPPS_CLOSING) ? PPPS_CLOSED : PPPS_STOPPED;
00174             break;
00175 
00176         case PPPS_REQSENT:
00177         case PPPS_ACKSENT:
00178             if (retries < 9) {
00179                 if (retries)
00180                     IpcpTxConfReq(dev, dcb->dcb_reqid);
00181                 dcb->dcb_retries = retries + 1;
00182             } else
00183                 dcb->dcb_ipcp_state = PPPS_STOPPED;
00184             break;
00185         }
00186     }
00187 }
00188 
00198 int NutPppInitStateMachine(NUTDEVICE * dev)
00199 {
00200     if (pppThread == 0 && (pppThread = NutThreadCreate("pppsm", NutPppSm, dev, NUT_THREAD_PPPSMSTACK)) == 0) {
00201         return -1;
00202     }
00203     return 0;
00204 }
00205 
00215 void LcpOpen(NUTDEVICE * dev)
00216 {
00217     PPPDCB *dcb = dev->dev_dcb;
00218 
00219 #ifdef NUTDEBUG
00220     if (__ppp_trf) {
00221         fputs("\n[LCP-OPEN]", __ppp_trs);
00222     }
00223 #endif
00224 
00225     switch (dcb->dcb_lcp_state) {
00226     case PPPS_INITIAL:
00227         /*
00228          * The LCP layer and the lower layer are down. Enable the LCP
00229          * layer. Link negotiation will start as soon as the lower
00230          * layer comes up.
00231          */
00232         dcb->dcb_lcp_state = PPPS_STARTING;
00233         break;
00234 
00235     case PPPS_CLOSED:
00236         /*
00237          * The LCP layer is down and the lower layer is up. Start 
00238          * link negotiation by sending out a request.
00239          */
00240         LcpTxConfReq(dev, ++dcb->dcb_reqid, 0);
00241         dcb->dcb_lcp_state = PPPS_REQSENT;
00242         break;
00243 
00244     case PPPS_CLOSING:
00245         /*
00246          * The LCP layer is going down.
00247          */
00248         dcb->dcb_lcp_state = PPPS_STOPPING;
00249         break;
00250     }
00251 }
00252 
00260 void LcpClose(NUTDEVICE * dev)
00261 {
00262     PPPDCB *dcb = dev->dev_dcb;
00263 
00264 #ifdef NUTDEBUG
00265     if (__ppp_trf) {
00266         fputs("\n[LCP-CLOSE]", __ppp_trs);
00267     }
00268 #endif
00269 
00270     switch (dcb->dcb_lcp_state) {
00271     case PPPS_STARTING:
00272         /*
00273          * The LCP layer has been enabled, but the lower layer is still 
00274          * down. Disable the link layer.
00275          */
00276         dcb->dcb_lcp_state = PPPS_INITIAL;
00277         break;
00278 
00279     case PPPS_STOPPED:
00280         dcb->dcb_lcp_state = PPPS_CLOSED;
00281         break;
00282 
00283     case PPPS_STOPPING:
00284         dcb->dcb_lcp_state = PPPS_CLOSING;
00285         break;
00286 
00287     case PPPS_REQSENT:
00288     case PPPS_ACKRCVD:
00289     case PPPS_ACKSENT:
00290     case PPPS_OPENED:
00291         /*
00292          * The LCP layer and the lower layer are up. Inform the upper
00293          * layer that we are going down and send out a termination
00294          * request.
00295          */
00296         dcb->dcb_lcp_state = PPPS_CLOSING;
00297         IpcpLowerDown(dev);
00298         NutLcpOutput(dev, XCP_TERMREQ, dcb->dcb_reqid, 0);
00299         break;
00300     }
00301 }
00302 
00309 void LcpLowerUp(NUTDEVICE * dev)
00310 {
00311     PPPDCB *dcb = dev->dev_dcb;
00312 
00313 #ifdef NUTDEBUG
00314     if (__ppp_trf) {
00315         fputs("\n[LCP-LOWERUP]", __ppp_trs);
00316     }
00317 #endif
00318 
00319     switch (dcb->dcb_lcp_state) {
00320     case PPPS_INITIAL:
00321         /*
00322          * The LCP layer is still disabled.
00323          */
00324         dcb->dcb_lcp_state = PPPS_CLOSED;
00325         break;
00326 
00327     case PPPS_STARTING:
00328         /*
00329          * The LCP layer is enabled. Send a configuration request.
00330          */
00331         LcpTxConfReq(dev, ++dcb->dcb_reqid, 0);
00332         dcb->dcb_lcp_state = PPPS_REQSENT;
00333         break;
00334     }
00335 }
00336 
00343 void LcpLowerDown(NUTDEVICE * dev)
00344 {
00345     PPPDCB *dcb = dev->dev_dcb;
00346 
00347 #ifdef NUTDEBUG
00348     if (__ppp_trf) {
00349         fputs("\n[LCP-LOWERDOWN]", __ppp_trs);
00350     }
00351 #endif
00352 
00353     switch (dcb->dcb_lcp_state) {
00354     case PPPS_CLOSED:
00355         dcb->dcb_lcp_state = PPPS_INITIAL;
00356         break;
00357 
00358     case PPPS_STOPPED:
00359         dcb->dcb_lcp_state = PPPS_STARTING;
00360         break;
00361 
00362     case PPPS_CLOSING:
00363         dcb->dcb_lcp_state = PPPS_INITIAL;
00364         break;
00365 
00366     case PPPS_STOPPING:
00367     case PPPS_REQSENT:
00368     case PPPS_ACKRCVD:
00369     case PPPS_ACKSENT:
00370         dcb->dcb_lcp_state = PPPS_STARTING;
00371         break;
00372 
00373     case PPPS_OPENED:
00374         IpcpLowerDown(dev);
00375         dcb->dcb_lcp_state = PPPS_STARTING;
00376         break;
00377     }
00378 }
00379 
00387 void IpcpOpen(NUTDEVICE * dev)
00388 {
00389     PPPDCB *dcb = dev->dev_dcb;
00390 
00391 #ifdef NUTDEBUG
00392     if (__ppp_trf) {
00393         fputs("\n[IPCP-OPEN]", __ppp_trs);
00394     }
00395 #endif
00396 
00397     switch (dcb->dcb_ipcp_state) {
00398     case PPPS_INITIAL:
00399         /*
00400          * The IPCP layer and the lower layer are down. Enable the
00401          * IPCP layer and the lower layer.
00402          */
00403         dcb->dcb_ipcp_state = PPPS_STARTING;
00404         LcpOpen(dev);
00405         break;
00406 
00407     case PPPS_CLOSED:
00408         IpcpTxConfReq(dev, ++dcb->dcb_reqid);
00409         dcb->dcb_ipcp_state = PPPS_REQSENT;
00410         break;
00411 
00412     case PPPS_CLOSING:
00413         dcb->dcb_ipcp_state = PPPS_STOPPING;
00414         break;
00415     }
00416 }
00417 
00428 void IpcpClose(NUTDEVICE * dev)
00429 {
00430     PPPDCB *dcb = dev->dev_dcb;
00431 
00432 #ifdef NUTDEBUG
00433     if (__ppp_trf) {
00434         fputs("\n[IPCP-CLOSE]", __ppp_trs);
00435     }
00436 #endif
00437 
00438     switch (dcb->dcb_ipcp_state) {
00439     case PPPS_STARTING:
00440         /*
00441          * The IPCP layer has been enabled, but the lower layer is still 
00442          * down. Disable the network layer.
00443          */
00444         dcb->dcb_ipcp_state = PPPS_INITIAL;
00445         break;
00446 
00447     case PPPS_STOPPED:
00448         dcb->dcb_ipcp_state = PPPS_CLOSED;
00449         break;
00450 
00451     case PPPS_STOPPING:
00452         dcb->dcb_ipcp_state = PPPS_CLOSING;
00453         break;
00454 
00455     case PPPS_REQSENT:
00456     case PPPS_ACKRCVD:
00457     case PPPS_ACKSENT:
00458     case PPPS_OPENED:
00459         /*
00460          * The IPCP layer and the lower layer are up. Inform the upper
00461          * layer that we are going down and send out a termination
00462          * request.
00463          */
00464         NutIpcpOutput(dev, XCP_TERMREQ, dcb->dcb_reqid, 0);
00465         dcb->dcb_ipcp_state = PPPS_CLOSING;
00466         NutEventPost(&dcb->dcb_state_chg);
00467         break;
00468     }
00469 }
00470 
00471 /*
00472  * The lower layer is up.
00473  * \param dev Pointer to the NUTDEVICE structure of the PPP device.
00474  *
00475  */
00476 void IpcpLowerUp(NUTDEVICE * dev)
00477 {
00478     PPPDCB *dcb = dev->dev_dcb;
00479 
00480 #ifdef NUTDEBUG
00481     if (__ppp_trf) {
00482         fputs("\n[IPCP-LOWERUP]", __ppp_trs);
00483     }
00484 #endif
00485 
00486     switch (dcb->dcb_ipcp_state) {
00487     case PPPS_INITIAL:
00488         dcb->dcb_ipcp_state = PPPS_CLOSED;
00489         break;
00490 
00491     case PPPS_STARTING:
00492         IpcpTxConfReq(dev, ++dcb->dcb_reqid);
00493         dcb->dcb_ipcp_state = PPPS_REQSENT;
00494         break;
00495     }
00496 }
00497 
00498 /*
00499  * The link layer is down.
00500  *
00501  * Cancel all timeouts and inform upper layers.
00502  * \param dev Pointer to the NUTDEVICE structure of the PPP device.
00503  *
00504  */
00505 void IpcpLowerDown(NUTDEVICE * dev)
00506 {
00507     PPPDCB *dcb = dev->dev_dcb;
00508 
00509 #ifdef NUTDEBUG
00510     if (__ppp_trf) {
00511         fputs("\n[IPCP-LOWERDOWN]", __ppp_trs);
00512     }
00513 #endif
00514 
00515     switch (dcb->dcb_ipcp_state) {
00516     case PPPS_CLOSED:
00517         dcb->dcb_ipcp_state = PPPS_INITIAL;
00518         _ioctl(dcb->dcb_fd, HDLC_SETIFNET, 0);
00519         break;
00520 
00521     case PPPS_STOPPED:
00522         dcb->dcb_ipcp_state = PPPS_STARTING;
00523         break;
00524 
00525     case PPPS_CLOSING:
00526         dcb->dcb_ipcp_state = PPPS_INITIAL;
00527         break;
00528 
00529     case PPPS_STOPPING:
00530     case PPPS_REQSENT:
00531     case PPPS_ACKRCVD:
00532     case PPPS_ACKSENT:
00533         dcb->dcb_ipcp_state = PPPS_STARTING;
00534         break;
00535 
00536     case PPPS_OPENED:
00537         dcb->dcb_ipcp_state = PPPS_STARTING;
00538         NutEventPost(&dcb->dcb_state_chg);
00539         break;
00540     }
00541 }
00542 

© 2000-2007 by egnite Software GmbH - visit http://www.ethernut.de/