Nut/OS  4.10.3
API Reference
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$
00037  * Revision 1.9  2009/02/06 15:40:29  haraldkipp
00038  * Using newly available strdup() and calloc().
00039  * Replaced NutHeap routines by standard malloc/free.
00040  * Replaced pointer value 0 by NULL.
00041  *
00042  * Revision 1.8  2008/08/11 07:00:32  haraldkipp
00043  * BSD types replaced by stdint types (feature request #1282721).
00044  *
00045  * Revision 1.7  2005/04/30 16:42:42  chaac
00046  * Fixed bug in handling of NUTDEBUG. Added include for cfg/os.h. If NUTDEBUG
00047  * is defined in NutConf, it will make effect where it is used.
00048  *
00049  * Revision 1.6  2005/04/05 17:44:57  haraldkipp
00050  * Made stack space configurable.
00051  *
00052  * Revision 1.5  2004/03/16 16:48:45  haraldkipp
00053  * Added Jan Dubiec's H8/300 port.
00054  *
00055  * Revision 1.4  2004/03/08 11:28:37  haraldkipp
00056  * HDLC functions moved to async HDLC driver.
00057  *
00058  * Revision 1.3  2004/01/30 11:37:58  haraldkipp
00059  * Handle magic number rejects
00060  *
00061  * Revision 1.2  2003/08/14 15:14:19  haraldkipp
00062  * Do not increment ID when resending.
00063  * Added authentication retries.
00064  *
00065  * Revision 1.1.1.1  2003/05/09 14:41:37  haraldkipp
00066  * Initial using 3.2.1
00067  *
00068  * Revision 1.2  2003/05/06 18:18:37  harald
00069  * PPP hack for simple UART support, functions reordered.
00070  *
00071  * Revision 1.1  2003/03/31 14:53:28  harald
00072  * Prepare release 3.1
00073  *
00074  */
00075 
00076 #include <cfg/os.h>
00077 #include <cfg/ppp.h>
00078 
00079 #include <string.h>
00080 #include <io.h>
00081 #include <fcntl.h>
00082 #include <dev/uart.h>
00083 
00084 #include <sys/thread.h>
00085 #include <sys/heap.h>
00086 #include <sys/event.h>
00087 #include <sys/timer.h>
00088 
00089 #include <net/if_var.h>
00090 #include <dev/ppp.h>
00091 
00092 #include <netinet/if_ppp.h>
00093 #include <netinet/ppp_fsm.h>
00094 
00095 #ifdef NUTDEBUG
00096 #include <net/netdebug.h>
00097 #endif
00098 
00099 #ifndef NUT_THREAD_PPPSMSTACK
00100 #define NUT_THREAD_PPPSMSTACK   512
00101 #endif
00102 
00107 
00108 uint32_t new_magic = 0x12345678;
00109 static HANDLE pppThread;
00110 
00111 
00117 THREAD(NutPppSm, arg)
00118 {
00119     NUTDEVICE *dev = arg;
00120     PPPDCB *dcb = dev->dev_dcb;
00121     uint_fast8_t retries;
00122 
00123     for (;;) {
00124         NutSleep(5000);
00125         new_magic++;
00126 
00127         retries = dcb->dcb_retries;
00128 
00129         /*
00130          * LCP timeouts.
00131          */
00132         switch (dcb->dcb_lcp_state) {
00133         case PPPS_CLOSING:
00134         case PPPS_STOPPING:
00135             if (retries < 9) {
00136                 if (retries) {
00137                     NutLcpOutput(dev, XCP_TERMREQ, dcb->dcb_reqid, 0);
00138                 }
00139                 dcb->dcb_retries = retries + 1;
00140             } else
00141                 dcb->dcb_lcp_state = (dcb->dcb_lcp_state == PPPS_CLOSING) ? PPPS_CLOSED : PPPS_STOPPED;
00142             break;
00143 
00144         case PPPS_REQSENT:
00145         case PPPS_ACKSENT:
00146             if (retries < 9) {
00147                 if (retries)
00148                     LcpTxConfReq(dev, dcb->dcb_reqid, 0);
00149                 dcb->dcb_retries = retries + 1;
00150             } else
00151                 dcb->dcb_lcp_state = PPPS_STOPPED;
00152             break;
00153         }
00154 
00155         /*
00156          * Authentication timeouts.
00157          */
00158         if (dcb->dcb_auth_state == PAPCS_AUTHREQ) {
00159             if (retries < 9) {
00160                 if (retries)
00161                     PapTxAuthReq(dev, dcb->dcb_reqid);
00162                 dcb->dcb_retries = retries + 1;
00163             } else
00164                 dcb->dcb_lcp_state = PPPS_STOPPED;
00165         }
00166 
00167         /*
00168          * IPCP timeouts.
00169          */
00170         switch (dcb->dcb_ipcp_state) {
00171         case PPPS_CLOSING:
00172         case PPPS_STOPPING:
00173             if (retries < 9) {
00174                 if (retries)
00175                     NutIpcpOutput(dev, XCP_TERMREQ, dcb->dcb_reqid, 0);
00176                 dcb->dcb_retries = retries + 1;
00177             } else
00178                 dcb->dcb_ipcp_state = (dcb->dcb_ipcp_state == PPPS_CLOSING) ? PPPS_CLOSED : PPPS_STOPPED;
00179             break;
00180 
00181         case PPPS_REQSENT:
00182         case PPPS_ACKSENT:
00183             if (retries < 9) {
00184                 if (retries)
00185                     IpcpTxConfReq(dev, dcb->dcb_reqid);
00186                 dcb->dcb_retries = retries + 1;
00187             } else
00188                 dcb->dcb_ipcp_state = PPPS_STOPPED;
00189             break;
00190         }
00191     }
00192 }
00193 
00203 int NutPppInitStateMachine(NUTDEVICE * dev)
00204 {
00205     if (pppThread == 0 && (pppThread = NutThreadCreate("pppsm", NutPppSm, dev, 
00206         (NUT_THREAD_PPPSMSTACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD)) == 0) {
00207         return -1;
00208     }
00209     return 0;
00210 }
00211 
00221 void LcpOpen(NUTDEVICE * dev)
00222 {
00223     PPPDCB *dcb = dev->dev_dcb;
00224 
00225 #ifdef NUTDEBUG
00226     if (__ppp_trf) {
00227         fputs("\n[LCP-OPEN]", __ppp_trs);
00228     }
00229 #endif
00230 
00231     switch (dcb->dcb_lcp_state) {
00232     case PPPS_INITIAL:
00233         /*
00234          * The LCP layer and the lower layer are down. Enable the LCP
00235          * layer. Link negotiation will start as soon as the lower
00236          * layer comes up.
00237          */
00238         dcb->dcb_lcp_state = PPPS_STARTING;
00239         break;
00240 
00241     case PPPS_CLOSED:
00242         /*
00243          * The LCP layer is down and the lower layer is up. Start 
00244          * link negotiation by sending out a request.
00245          */
00246         LcpTxConfReq(dev, ++dcb->dcb_reqid, 0);
00247         dcb->dcb_lcp_state = PPPS_REQSENT;
00248         break;
00249 
00250     case PPPS_CLOSING:
00251         /*
00252          * The LCP layer is going down.
00253          */
00254         dcb->dcb_lcp_state = PPPS_STOPPING;
00255         break;
00256     }
00257 }
00258 
00266 void LcpClose(NUTDEVICE * dev)
00267 {
00268     PPPDCB *dcb = dev->dev_dcb;
00269 
00270 #ifdef NUTDEBUG
00271     if (__ppp_trf) {
00272         fputs("\n[LCP-CLOSE]", __ppp_trs);
00273     }
00274 #endif
00275 
00276     switch (dcb->dcb_lcp_state) {
00277     case PPPS_STARTING:
00278         /*
00279          * The LCP layer has been enabled, but the lower layer is still 
00280          * down. Disable the link layer.
00281          */
00282         dcb->dcb_lcp_state = PPPS_INITIAL;
00283         break;
00284 
00285     case PPPS_STOPPED:
00286         dcb->dcb_lcp_state = PPPS_CLOSED;
00287         break;
00288 
00289     case PPPS_STOPPING:
00290         dcb->dcb_lcp_state = PPPS_CLOSING;
00291         break;
00292 
00293     case PPPS_REQSENT:
00294     case PPPS_ACKRCVD:
00295     case PPPS_ACKSENT:
00296     case PPPS_OPENED:
00297         /*
00298          * The LCP layer and the lower layer are up. Inform the upper
00299          * layer that we are going down and send out a termination
00300          * request.
00301          */
00302         dcb->dcb_lcp_state = PPPS_CLOSING;
00303         IpcpLowerDown(dev);
00304         NutLcpOutput(dev, XCP_TERMREQ, dcb->dcb_reqid, 0);
00305         break;
00306     }
00307 }
00308 
00315 void LcpLowerUp(NUTDEVICE * dev)
00316 {
00317     PPPDCB *dcb = dev->dev_dcb;
00318 
00319 #ifdef NUTDEBUG
00320     if (__ppp_trf) {
00321         fputs("\n[LCP-LOWERUP]", __ppp_trs);
00322     }
00323 #endif
00324 
00325     switch (dcb->dcb_lcp_state) {
00326     case PPPS_INITIAL:
00327         /*
00328          * The LCP layer is still disabled.
00329          */
00330         dcb->dcb_lcp_state = PPPS_CLOSED;
00331         break;
00332 
00333     case PPPS_STARTING:
00334         /*
00335          * The LCP layer is enabled. Send a configuration request.
00336          */
00337         LcpTxConfReq(dev, ++dcb->dcb_reqid, 0);
00338         dcb->dcb_lcp_state = PPPS_REQSENT;
00339         break;
00340     }
00341 }
00342 
00349 void LcpLowerDown(NUTDEVICE * dev)
00350 {
00351     PPPDCB *dcb = dev->dev_dcb;
00352 
00353 #ifdef NUTDEBUG
00354     if (__ppp_trf) {
00355         fputs("\n[LCP-LOWERDOWN]", __ppp_trs);
00356     }
00357 #endif
00358 
00359     switch (dcb->dcb_lcp_state) {
00360     case PPPS_CLOSED:
00361         dcb->dcb_lcp_state = PPPS_INITIAL;
00362         break;
00363 
00364     case PPPS_STOPPED:
00365         dcb->dcb_lcp_state = PPPS_STARTING;
00366         break;
00367 
00368     case PPPS_CLOSING:
00369         dcb->dcb_lcp_state = PPPS_INITIAL;
00370         break;
00371 
00372     case PPPS_STOPPING:
00373     case PPPS_REQSENT:
00374     case PPPS_ACKRCVD:
00375     case PPPS_ACKSENT:
00376         dcb->dcb_lcp_state = PPPS_STARTING;
00377         break;
00378 
00379     case PPPS_OPENED:
00380         IpcpLowerDown(dev);
00381         dcb->dcb_lcp_state = PPPS_STARTING;
00382         break;
00383     }
00384 }
00385 
00393 void IpcpOpen(NUTDEVICE * dev)
00394 {
00395     PPPDCB *dcb = dev->dev_dcb;
00396 
00397 #ifdef NUTDEBUG
00398     if (__ppp_trf) {
00399         fputs("\n[IPCP-OPEN]", __ppp_trs);
00400     }
00401 #endif
00402 
00403     switch (dcb->dcb_ipcp_state) {
00404     case PPPS_INITIAL:
00405         /*
00406          * The IPCP layer and the lower layer are down. Enable the
00407          * IPCP layer and the lower layer.
00408          */
00409         dcb->dcb_ipcp_state = PPPS_STARTING;
00410         LcpOpen(dev);
00411         break;
00412 
00413     case PPPS_CLOSED:
00414         IpcpTxConfReq(dev, ++dcb->dcb_reqid);
00415         dcb->dcb_ipcp_state = PPPS_REQSENT;
00416         break;
00417 
00418     case PPPS_CLOSING:
00419         dcb->dcb_ipcp_state = PPPS_STOPPING;
00420         break;
00421     }
00422 }
00423 
00434 void IpcpClose(NUTDEVICE * dev)
00435 {
00436     PPPDCB *dcb = dev->dev_dcb;
00437 
00438 #ifdef NUTDEBUG
00439     if (__ppp_trf) {
00440         fputs("\n[IPCP-CLOSE]", __ppp_trs);
00441     }
00442 #endif
00443 
00444     switch (dcb->dcb_ipcp_state) {
00445     case PPPS_STARTING:
00446         /*
00447          * The IPCP layer has been enabled, but the lower layer is still 
00448          * down. Disable the network layer.
00449          */
00450         dcb->dcb_ipcp_state = PPPS_INITIAL;
00451         break;
00452 
00453     case PPPS_STOPPED:
00454         dcb->dcb_ipcp_state = PPPS_CLOSED;
00455         break;
00456 
00457     case PPPS_STOPPING:
00458         dcb->dcb_ipcp_state = PPPS_CLOSING;
00459         break;
00460 
00461     case PPPS_REQSENT:
00462     case PPPS_ACKRCVD:
00463     case PPPS_ACKSENT:
00464     case PPPS_OPENED:
00465         /*
00466          * The IPCP layer and the lower layer are up. Inform the upper
00467          * layer that we are going down and send out a termination
00468          * request.
00469          */
00470         NutIpcpOutput(dev, XCP_TERMREQ, dcb->dcb_reqid, 0);
00471         dcb->dcb_ipcp_state = PPPS_CLOSING;
00472         NutEventPost(&dcb->dcb_state_chg);
00473         break;
00474     }
00475 }
00476 
00477 /*
00478  * The lower layer is up.
00479  * \param dev Pointer to the NUTDEVICE structure of the PPP device.
00480  *
00481  */
00482 void IpcpLowerUp(NUTDEVICE * dev)
00483 {
00484     PPPDCB *dcb = dev->dev_dcb;
00485 
00486 #ifdef NUTDEBUG
00487     if (__ppp_trf) {
00488         fputs("\n[IPCP-LOWERUP]", __ppp_trs);
00489     }
00490 #endif
00491 
00492     switch (dcb->dcb_ipcp_state) {
00493     case PPPS_INITIAL:
00494         dcb->dcb_ipcp_state = PPPS_CLOSED;
00495         break;
00496 
00497     case PPPS_STARTING:
00498         IpcpTxConfReq(dev, ++dcb->dcb_reqid);
00499         dcb->dcb_ipcp_state = PPPS_REQSENT;
00500         break;
00501     }
00502 }
00503 
00504 /*
00505  * The link layer is down.
00506  *
00507  * Cancel all timeouts and inform upper layers.
00508  * \param dev Pointer to the NUTDEVICE structure of the PPP device.
00509  *
00510  */
00511 void IpcpLowerDown(NUTDEVICE * dev)
00512 {
00513     PPPDCB *dcb = dev->dev_dcb;
00514 
00515 #ifdef NUTDEBUG
00516     if (__ppp_trf) {
00517         fputs("\n[IPCP-LOWERDOWN]", __ppp_trs);
00518     }
00519 #endif
00520 
00521     switch (dcb->dcb_ipcp_state) {
00522     case PPPS_CLOSED:
00523         dcb->dcb_ipcp_state = PPPS_INITIAL;
00524         _ioctl(dcb->dcb_fd, HDLC_SETIFNET, 0);
00525         break;
00526 
00527     case PPPS_STOPPED:
00528         dcb->dcb_ipcp_state = PPPS_STARTING;
00529         break;
00530 
00531     case PPPS_CLOSING:
00532         dcb->dcb_ipcp_state = PPPS_INITIAL;
00533         break;
00534 
00535     case PPPS_STOPPING:
00536     case PPPS_REQSENT:
00537     case PPPS_ACKRCVD:
00538     case PPPS_ACKSENT:
00539         dcb->dcb_ipcp_state = PPPS_STARTING;
00540         break;
00541 
00542     case PPPS_OPENED:
00543         dcb->dcb_ipcp_state = PPPS_STARTING;
00544         NutEventPost(&dcb->dcb_state_chg);
00545         break;
00546     }
00547 }
00548