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.7  2005/04/30 16:42:42  chaac
00038  * Fixed bug in handling of NUTDEBUG. Added include for cfg/os.h. If NUTDEBUG
00039  * is defined in NutConf, it will make effect where it is used.
00040  *
00041  * Revision 1.6  2005/04/05 17:44:57  haraldkipp
00042  * Made stack space configurable.
00043  *
00044  * Revision 1.5  2004/03/16 16:48:45  haraldkipp
00045  * Added Jan Dubiec's H8/300 port.
00046  *
00047  * Revision 1.4  2004/03/08 11:28:37  haraldkipp
00048  * HDLC functions moved to async HDLC driver.
00049  *
00050  * Revision 1.3  2004/01/30 11:37:58  haraldkipp
00051  * Handle magic number rejects
00052  *
00053  * Revision 1.2  2003/08/14 15:14:19  haraldkipp
00054  * Do not increment ID when resending.
00055  * Added authentication retries.
00056  *
00057  * Revision 1.1.1.1  2003/05/09 14:41:37  haraldkipp
00058  * Initial using 3.2.1
00059  *
00060  * Revision 1.2  2003/05/06 18:18:37  harald
00061  * PPP hack for simple UART support, functions reordered.
00062  *
00063  * Revision 1.1  2003/03/31 14:53:28  harald
00064  * Prepare release 3.1
00065  *
00066  */
00067 
00068 #include <cfg/os.h>
00069 #include <cfg/ppp.h>
00070 
00071 #include <string.h>
00072 #include <io.h>
00073 #include <fcntl.h>
00074 #include <dev/uart.h>
00075 
00076 #include <sys/thread.h>
00077 #include <sys/heap.h>
00078 #include <sys/event.h>
00079 #include <sys/timer.h>
00080 
00081 #include <net/if_var.h>
00082 #include <dev/ppp.h>
00083 
00084 #include <netinet/if_ppp.h>
00085 #include <netinet/ppp_fsm.h>
00086 
00087 #ifdef NUTDEBUG
00088 #include <net/netdebug.h>
00089 #endif
00090 
00091 #ifndef NUT_THREAD_PPPSMSTACK
00092 #define NUT_THREAD_PPPSMSTACK   512
00093 #endif
00094 
00099 
00100 u_long new_magic = 0x12345678;
00101 static HANDLE pppThread;
00102 
00103 
00109 THREAD(NutPppSm, arg)
00110 {
00111     NUTDEVICE *dev = arg;
00112     PPPDCB *dcb = dev->dev_dcb;
00113     u_char retries;
00114 
00115     for (;;) {
00116         NutSleep(5000);
00117         new_magic++;
00118 
00119         retries = dcb->dcb_retries;
00120 
00121         /*
00122          * LCP timeouts.
00123          */
00124         switch (dcb->dcb_lcp_state) {
00125         case PPPS_CLOSING:
00126         case PPPS_STOPPING:
00127             if (retries < 9) {
00128                 if (retries) {
00129                     NutLcpOutput(dev, XCP_TERMREQ, dcb->dcb_reqid, 0);
00130                 }
00131                 dcb->dcb_retries = retries + 1;
00132             } else
00133                 dcb->dcb_lcp_state = (dcb->dcb_lcp_state == PPPS_CLOSING) ? PPPS_CLOSED : PPPS_STOPPED;
00134             break;
00135 
00136         case PPPS_REQSENT:
00137         case PPPS_ACKSENT:
00138             if (retries < 9) {
00139                 if (retries)
00140                     LcpTxConfReq(dev, dcb->dcb_reqid, 0);
00141                 dcb->dcb_retries = retries + 1;
00142             } else
00143                 dcb->dcb_lcp_state = PPPS_STOPPED;
00144             break;
00145         }
00146 
00147         /*
00148          * Authentication timeouts.
00149          */
00150         if (dcb->dcb_auth_state == PAPCS_AUTHREQ) {
00151             if (retries < 9) {
00152                 if (retries)
00153                     PapTxAuthReq(dev, dcb->dcb_reqid);
00154                 dcb->dcb_retries = retries + 1;
00155             } else
00156                 dcb->dcb_lcp_state = PPPS_STOPPED;
00157         }
00158 
00159         /*
00160          * IPCP timeouts.
00161          */
00162         switch (dcb->dcb_ipcp_state) {
00163         case PPPS_CLOSING:
00164         case PPPS_STOPPING:
00165             if (retries < 9) {
00166                 if (retries)
00167                     NutIpcpOutput(dev, XCP_TERMREQ, dcb->dcb_reqid, 0);
00168                 dcb->dcb_retries = retries + 1;
00169             } else
00170                 dcb->dcb_ipcp_state = (dcb->dcb_ipcp_state == PPPS_CLOSING) ? PPPS_CLOSED : PPPS_STOPPED;
00171             break;
00172 
00173         case PPPS_REQSENT:
00174         case PPPS_ACKSENT:
00175             if (retries < 9) {
00176                 if (retries)
00177                     IpcpTxConfReq(dev, dcb->dcb_reqid);
00178                 dcb->dcb_retries = retries + 1;
00179             } else
00180                 dcb->dcb_ipcp_state = PPPS_STOPPED;
00181             break;
00182         }
00183     }
00184 }
00185 
00195 int NutPppInitStateMachine(NUTDEVICE * dev)
00196 {
00197     if (pppThread == 0 && (pppThread = NutThreadCreate("pppsm", NutPppSm, dev, NUT_THREAD_PPPSMSTACK)) == 0) {
00198         return -1;
00199     }
00200     return 0;
00201 }
00202 
00212 void LcpOpen(NUTDEVICE * dev)
00213 {
00214     PPPDCB *dcb = dev->dev_dcb;
00215 
00216 #ifdef NUTDEBUG
00217     if (__ppp_trf) {
00218         fputs("\n[LCP-OPEN]", __ppp_trs);
00219     }
00220 #endif
00221 
00222     switch (dcb->dcb_lcp_state) {
00223     case PPPS_INITIAL:
00224         /*
00225          * The LCP layer and the lower layer are down. Enable the LCP
00226          * layer. Link negotiation will start as soon as the lower
00227          * layer comes up.
00228          */
00229         dcb->dcb_lcp_state = PPPS_STARTING;
00230         break;
00231 
00232     case PPPS_CLOSED:
00233         /*
00234          * The LCP layer is down and the lower layer is up. Start 
00235          * link negotiation by sending out a request.
00236          */
00237         LcpTxConfReq(dev, ++dcb->dcb_reqid, 0);
00238         dcb->dcb_lcp_state = PPPS_REQSENT;
00239         break;
00240 
00241     case PPPS_CLOSING:
00242         /*
00243          * The LCP layer is going down.
00244          */
00245         dcb->dcb_lcp_state = PPPS_STOPPING;
00246         break;
00247     }
00248 }
00249 
00257 void LcpClose(NUTDEVICE * dev)
00258 {
00259     PPPDCB *dcb = dev->dev_dcb;
00260 
00261 #ifdef NUTDEBUG
00262     if (__ppp_trf) {
00263         fputs("\n[LCP-CLOSE]", __ppp_trs);
00264     }
00265 #endif
00266 
00267     switch (dcb->dcb_lcp_state) {
00268     case PPPS_STARTING:
00269         /*
00270          * The LCP layer has been enabled, but the lower layer is still 
00271          * down. Disable the link layer.
00272          */
00273         dcb->dcb_lcp_state = PPPS_INITIAL;
00274         break;
00275 
00276     case PPPS_STOPPED:
00277         dcb->dcb_lcp_state = PPPS_CLOSED;
00278         break;
00279 
00280     case PPPS_STOPPING:
00281         dcb->dcb_lcp_state = PPPS_CLOSING;
00282         break;
00283 
00284     case PPPS_REQSENT:
00285     case PPPS_ACKRCVD:
00286     case PPPS_ACKSENT:
00287     case PPPS_OPENED:
00288         /*
00289          * The LCP layer and the lower layer are up. Inform the upper
00290          * layer that we are going down and send out a termination
00291          * request.
00292          */
00293         dcb->dcb_lcp_state = PPPS_CLOSING;
00294         IpcpLowerDown(dev);
00295         NutLcpOutput(dev, XCP_TERMREQ, dcb->dcb_reqid, 0);
00296         break;
00297     }
00298 }
00299 
00306 void LcpLowerUp(NUTDEVICE * dev)
00307 {
00308     PPPDCB *dcb = dev->dev_dcb;
00309 
00310 #ifdef NUTDEBUG
00311     if (__ppp_trf) {
00312         fputs("\n[LCP-LOWERUP]", __ppp_trs);
00313     }
00314 #endif
00315 
00316     switch (dcb->dcb_lcp_state) {
00317     case PPPS_INITIAL:
00318         /*
00319          * The LCP layer is still disabled.
00320          */
00321         dcb->dcb_lcp_state = PPPS_CLOSED;
00322         break;
00323 
00324     case PPPS_STARTING:
00325         /*
00326          * The LCP layer is enabled. Send a configuration request.
00327          */
00328         LcpTxConfReq(dev, ++dcb->dcb_reqid, 0);
00329         dcb->dcb_lcp_state = PPPS_REQSENT;
00330         break;
00331     }
00332 }
00333 
00340 void LcpLowerDown(NUTDEVICE * dev)
00341 {
00342     PPPDCB *dcb = dev->dev_dcb;
00343 
00344 #ifdef NUTDEBUG
00345     if (__ppp_trf) {
00346         fputs("\n[LCP-LOWERDOWN]", __ppp_trs);
00347     }
00348 #endif
00349 
00350     switch (dcb->dcb_lcp_state) {
00351     case PPPS_CLOSED:
00352         dcb->dcb_lcp_state = PPPS_INITIAL;
00353         break;
00354 
00355     case PPPS_STOPPED:
00356         dcb->dcb_lcp_state = PPPS_STARTING;
00357         break;
00358 
00359     case PPPS_CLOSING:
00360         dcb->dcb_lcp_state = PPPS_INITIAL;
00361         break;
00362 
00363     case PPPS_STOPPING:
00364     case PPPS_REQSENT:
00365     case PPPS_ACKRCVD:
00366     case PPPS_ACKSENT:
00367         dcb->dcb_lcp_state = PPPS_STARTING;
00368         break;
00369 
00370     case PPPS_OPENED:
00371         IpcpLowerDown(dev);
00372         dcb->dcb_lcp_state = PPPS_STARTING;
00373         break;
00374     }
00375 }
00376 
00384 void IpcpOpen(NUTDEVICE * dev)
00385 {
00386     PPPDCB *dcb = dev->dev_dcb;
00387 
00388 #ifdef NUTDEBUG
00389     if (__ppp_trf) {
00390         fputs("\n[IPCP-OPEN]", __ppp_trs);
00391     }
00392 #endif
00393 
00394     switch (dcb->dcb_ipcp_state) {
00395     case PPPS_INITIAL:
00396         /*
00397          * The IPCP layer and the lower layer are down. Enable the
00398          * IPCP layer and the lower layer.
00399          */
00400         dcb->dcb_ipcp_state = PPPS_STARTING;
00401         LcpOpen(dev);
00402         break;
00403 
00404     case PPPS_CLOSED:
00405         IpcpTxConfReq(dev, ++dcb->dcb_reqid);
00406         dcb->dcb_ipcp_state = PPPS_REQSENT;
00407         break;
00408 
00409     case PPPS_CLOSING:
00410         dcb->dcb_ipcp_state = PPPS_STOPPING;
00411         break;
00412     }
00413 }
00414 
00425 void IpcpClose(NUTDEVICE * dev)
00426 {
00427     PPPDCB *dcb = dev->dev_dcb;
00428 
00429 #ifdef NUTDEBUG
00430     if (__ppp_trf) {
00431         fputs("\n[IPCP-CLOSE]", __ppp_trs);
00432     }
00433 #endif
00434 
00435     switch (dcb->dcb_ipcp_state) {
00436     case PPPS_STARTING:
00437         /*
00438          * The IPCP layer has been enabled, but the lower layer is still 
00439          * down. Disable the network layer.
00440          */
00441         dcb->dcb_ipcp_state = PPPS_INITIAL;
00442         break;
00443 
00444     case PPPS_STOPPED:
00445         dcb->dcb_ipcp_state = PPPS_CLOSED;
00446         break;
00447 
00448     case PPPS_STOPPING:
00449         dcb->dcb_ipcp_state = PPPS_CLOSING;
00450         break;
00451 
00452     case PPPS_REQSENT:
00453     case PPPS_ACKRCVD:
00454     case PPPS_ACKSENT:
00455     case PPPS_OPENED:
00456         /*
00457          * The IPCP layer and the lower layer are up. Inform the upper
00458          * layer that we are going down and send out a termination
00459          * request.
00460          */
00461         NutIpcpOutput(dev, XCP_TERMREQ, dcb->dcb_reqid, 0);
00462         dcb->dcb_ipcp_state = PPPS_CLOSING;
00463         NutEventPost(&dcb->dcb_state_chg);
00464         break;
00465     }
00466 }
00467 
00468 /*
00469  * The lower layer is up.
00470  * \param dev Pointer to the NUTDEVICE structure of the PPP device.
00471  *
00472  */
00473 void IpcpLowerUp(NUTDEVICE * dev)
00474 {
00475     PPPDCB *dcb = dev->dev_dcb;
00476 
00477 #ifdef NUTDEBUG
00478     if (__ppp_trf) {
00479         fputs("\n[IPCP-LOWERUP]", __ppp_trs);
00480     }
00481 #endif
00482 
00483     switch (dcb->dcb_ipcp_state) {
00484     case PPPS_INITIAL:
00485         dcb->dcb_ipcp_state = PPPS_CLOSED;
00486         break;
00487 
00488     case PPPS_STARTING:
00489         IpcpTxConfReq(dev, ++dcb->dcb_reqid);
00490         dcb->dcb_ipcp_state = PPPS_REQSENT;
00491         break;
00492     }
00493 }
00494 
00495 /*
00496  * The link layer is down.
00497  *
00498  * Cancel all timeouts and inform upper layers.
00499  * \param dev Pointer to the NUTDEVICE structure of the PPP device.
00500  *
00501  */
00502 void IpcpLowerDown(NUTDEVICE * dev)
00503 {
00504     PPPDCB *dcb = dev->dev_dcb;
00505 
00506 #ifdef NUTDEBUG
00507     if (__ppp_trf) {
00508         fputs("\n[IPCP-LOWERDOWN]", __ppp_trs);
00509     }
00510 #endif
00511 
00512     switch (dcb->dcb_ipcp_state) {
00513     case PPPS_CLOSED:
00514         dcb->dcb_ipcp_state = PPPS_INITIAL;
00515         _ioctl(dcb->dcb_fd, HDLC_SETIFNET, 0);
00516         break;
00517 
00518     case PPPS_STOPPED:
00519         dcb->dcb_ipcp_state = PPPS_STARTING;
00520         break;
00521 
00522     case PPPS_CLOSING:
00523         dcb->dcb_ipcp_state = PPPS_INITIAL;
00524         break;
00525 
00526     case PPPS_STOPPING:
00527     case PPPS_REQSENT:
00528     case PPPS_ACKRCVD:
00529     case PPPS_ACKSENT:
00530         dcb->dcb_ipcp_state = PPPS_STARTING;
00531         break;
00532 
00533     case PPPS_OPENED:
00534         dcb->dcb_ipcp_state = PPPS_STARTING;
00535         NutEventPost(&dcb->dcb_state_chg);
00536         break;
00537     }
00538 }
00539 

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