| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519 |
- /*
- * Copyright (C) 2001-2004 by egnite Software GmbH
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holders nor the names of
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
- * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * For additional information see http://www.ethernut.de/
- *
- * -
- */
- /*!
- * \file net/pppsm.c
- * \brief PPP state machine.
- *
- * \verbatim
- * $Id: pppsm.c 3686 2011-12-04 14:20:38Z haraldkipp $
- * \endverbatim
- */
- #include <cfg/os.h>
- #include <cfg/ppp.h>
- #include <string.h>
- #include <io.h>
- #include <fcntl.h>
- #include <dev/uart.h>
- #include <sys/thread.h>
- #include <sys/heap.h>
- #include <sys/event.h>
- #include <sys/timer.h>
- #include <net/if_var.h>
- #include <dev/ppp.h>
- #include <netinet/if_ppp.h>
- #include <netinet/ppp_fsm.h>
- #ifdef NUTDEBUG
- #include <net/netdebug.h>
- #endif
- #ifndef NUT_THREAD_PPPSMSTACK
- #define NUT_THREAD_PPPSMSTACK 512
- #endif
- /*!
- * \addtogroup xgPPP
- */
- /*@{*/
- uint32_t new_magic = 0x12345678;
- static HANDLE pppThread;
- /*! \fn NutPppSm(void *arg)
- * \brief PPP state machine timeout thread.
- *
- * Handles timeouts for LCP and IPCP.
- */
- THREAD(NutPppSm, arg)
- {
- NUTDEVICE *dev = arg;
- PPPDCB *dcb = dev->dev_dcb;
- uint_fast8_t retries;
- for (;;) {
- NutSleep(5000);
- new_magic++;
- retries = dcb->dcb_retries;
- /*
- * LCP timeouts.
- */
- switch (dcb->dcb_lcp_state) {
- case PPPS_CLOSING:
- case PPPS_STOPPING:
- if (retries < 9) {
- if (retries) {
- NutLcpOutput(dev, XCP_TERMREQ, dcb->dcb_reqid, 0);
- }
- dcb->dcb_retries = retries + 1;
- } else
- dcb->dcb_lcp_state = (dcb->dcb_lcp_state == PPPS_CLOSING) ? PPPS_CLOSED : PPPS_STOPPED;
- break;
- case PPPS_REQSENT:
- case PPPS_ACKSENT:
- if (retries < 9) {
- if (retries)
- LcpTxConfReq(dev, dcb->dcb_reqid, 0);
- dcb->dcb_retries = retries + 1;
- } else
- dcb->dcb_lcp_state = PPPS_STOPPED;
- break;
- }
- /*
- * Authentication timeouts.
- */
- if (dcb->dcb_auth_state == PAPCS_AUTHREQ) {
- if (retries < 9) {
- if (retries)
- PapTxAuthReq(dev, dcb->dcb_reqid);
- dcb->dcb_retries = retries + 1;
- } else
- dcb->dcb_lcp_state = PPPS_STOPPED;
- }
- /*
- * IPCP timeouts.
- */
- switch (dcb->dcb_ipcp_state) {
- case PPPS_CLOSING:
- case PPPS_STOPPING:
- if (retries < 9) {
- if (retries)
- NutIpcpOutput(dev, XCP_TERMREQ, dcb->dcb_reqid, 0);
- dcb->dcb_retries = retries + 1;
- } else
- dcb->dcb_ipcp_state = (dcb->dcb_ipcp_state == PPPS_CLOSING) ? PPPS_CLOSED : PPPS_STOPPED;
- break;
- case PPPS_REQSENT:
- case PPPS_ACKSENT:
- if (retries < 9) {
- if (retries)
- IpcpTxConfReq(dev, dcb->dcb_reqid);
- dcb->dcb_retries = retries + 1;
- } else
- dcb->dcb_ipcp_state = PPPS_STOPPED;
- break;
- }
- }
- }
- /*!
- * \brief Initialize the PPP state machine.
- *
- * Start the PPP timer thread, if not already running.
- *
- * \param dev Pointer to the NUTDEVICE structure of the PPP device.
- *
- * \return 0 on success, -1 otherwise.
- */
- int NutPppInitStateMachine(NUTDEVICE * dev)
- {
- if (pppThread == 0 && (pppThread = NutThreadCreate("pppsm", NutPppSm, dev,
- (NUT_THREAD_PPPSMSTACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD)) == 0) {
- return -1;
- }
- return 0;
- }
- /*!
- * \brief Trigger LCP open event.
- *
- * Enable the link to come up. Typically triggered by the upper layer,
- * when it is enabled.
- *
- * \param dev Pointer to the NUTDEVICE structure of the PPP device.
- *
- */
- void LcpOpen(NUTDEVICE * dev)
- {
- PPPDCB *dcb = dev->dev_dcb;
- #ifdef NUTDEBUG
- if (__ppp_trf) {
- fputs("\n[LCP-OPEN]", __ppp_trs);
- }
- #endif
- switch (dcb->dcb_lcp_state) {
- case PPPS_INITIAL:
- /*
- * The LCP layer and the lower layer are down. Enable the LCP
- * layer. Link negotiation will start as soon as the lower
- * layer comes up.
- */
- dcb->dcb_lcp_state = PPPS_STARTING;
- break;
- case PPPS_CLOSED:
- /*
- * The LCP layer is down and the lower layer is up. Start
- * link negotiation by sending out a request.
- */
- LcpTxConfReq(dev, ++dcb->dcb_reqid, 0);
- dcb->dcb_lcp_state = PPPS_REQSENT;
- break;
- case PPPS_CLOSING:
- /*
- * The LCP layer is going down.
- */
- dcb->dcb_lcp_state = PPPS_STOPPING;
- break;
- }
- }
- /*!
- * \brief Trigger LCP close event.
- *
- * Disable the link.
- *
- * \param dev Pointer to the NUTDEVICE structure of the PPP device.
- */
- void LcpClose(NUTDEVICE * dev)
- {
- PPPDCB *dcb = dev->dev_dcb;
- #ifdef NUTDEBUG
- if (__ppp_trf) {
- fputs("\n[LCP-CLOSE]", __ppp_trs);
- }
- #endif
- switch (dcb->dcb_lcp_state) {
- case PPPS_STARTING:
- /*
- * The LCP layer has been enabled, but the lower layer is still
- * down. Disable the link layer.
- */
- dcb->dcb_lcp_state = PPPS_INITIAL;
- break;
- case PPPS_STOPPED:
- dcb->dcb_lcp_state = PPPS_CLOSED;
- break;
- case PPPS_STOPPING:
- dcb->dcb_lcp_state = PPPS_CLOSING;
- break;
- case PPPS_REQSENT:
- case PPPS_ACKRCVD:
- case PPPS_ACKSENT:
- case PPPS_OPENED:
- /*
- * The LCP layer and the lower layer are up. Inform the upper
- * layer that we are going down and send out a termination
- * request.
- */
- dcb->dcb_lcp_state = PPPS_CLOSING;
- IpcpLowerDown(dev);
- NutLcpOutput(dev, XCP_TERMREQ, dcb->dcb_reqid, 0);
- break;
- }
- }
- /*!
- * \brief Trigger LCP lower up event.
- *
- * \param dev Pointer to the NUTDEVICE structure of the PPP device.
- *
- */
- void LcpLowerUp(NUTDEVICE * dev)
- {
- PPPDCB *dcb = dev->dev_dcb;
- #ifdef NUTDEBUG
- if (__ppp_trf) {
- fputs("\n[LCP-LOWERUP]", __ppp_trs);
- }
- #endif
- switch (dcb->dcb_lcp_state) {
- case PPPS_INITIAL:
- /*
- * The LCP layer is still disabled.
- */
- dcb->dcb_lcp_state = PPPS_CLOSED;
- break;
- case PPPS_STARTING:
- /*
- * The LCP layer is enabled. Send a configuration request.
- */
- LcpTxConfReq(dev, ++dcb->dcb_reqid, 0);
- dcb->dcb_lcp_state = PPPS_REQSENT;
- break;
- }
- }
- /*!
- * \brief Trigger LCP lower down event.
- *
- * \param dev Pointer to the NUTDEVICE structure of the PPP device.
- *
- */
- void LcpLowerDown(NUTDEVICE * dev)
- {
- PPPDCB *dcb = dev->dev_dcb;
- #ifdef NUTDEBUG
- if (__ppp_trf) {
- fputs("\n[LCP-LOWERDOWN]", __ppp_trs);
- }
- #endif
- switch (dcb->dcb_lcp_state) {
- case PPPS_CLOSED:
- dcb->dcb_lcp_state = PPPS_INITIAL;
- break;
- case PPPS_STOPPED:
- dcb->dcb_lcp_state = PPPS_STARTING;
- break;
- case PPPS_CLOSING:
- dcb->dcb_lcp_state = PPPS_INITIAL;
- break;
- case PPPS_STOPPING:
- case PPPS_REQSENT:
- case PPPS_ACKRCVD:
- case PPPS_ACKSENT:
- dcb->dcb_lcp_state = PPPS_STARTING;
- break;
- case PPPS_OPENED:
- IpcpLowerDown(dev);
- dcb->dcb_lcp_state = PPPS_STARTING;
- break;
- }
- }
- /*!
- * \brief Trigger IPCP open event.
- *
- * Link is allowed to come up.
- * \param dev Pointer to the NUTDEVICE structure of the PPP device.
- *
- */
- void IpcpOpen(NUTDEVICE * dev)
- {
- PPPDCB *dcb = dev->dev_dcb;
- #ifdef NUTDEBUG
- if (__ppp_trf) {
- fputs("\n[IPCP-OPEN]", __ppp_trs);
- }
- #endif
- switch (dcb->dcb_ipcp_state) {
- case PPPS_INITIAL:
- /*
- * The IPCP layer and the lower layer are down. Enable the
- * IPCP layer and the lower layer.
- */
- dcb->dcb_ipcp_state = PPPS_STARTING;
- LcpOpen(dev);
- break;
- case PPPS_CLOSED:
- IpcpTxConfReq(dev, ++dcb->dcb_reqid);
- dcb->dcb_ipcp_state = PPPS_REQSENT;
- break;
- case PPPS_CLOSING:
- dcb->dcb_ipcp_state = PPPS_STOPPING;
- break;
- }
- }
- /*!
- * \brief Trigger IPCP close event.
- *
- * Disable the link.
- *
- * Cancel timeouts and either initiate close or possibly go directly to
- * the PPPS_CLOSED state.
- *
- * \param dev Pointer to the NUTDEVICE structure of the PPP device.
- */
- void IpcpClose(NUTDEVICE * dev)
- {
- PPPDCB *dcb = dev->dev_dcb;
- #ifdef NUTDEBUG
- if (__ppp_trf) {
- fputs("\n[IPCP-CLOSE]", __ppp_trs);
- }
- #endif
- switch (dcb->dcb_ipcp_state) {
- case PPPS_STARTING:
- /*
- * The IPCP layer has been enabled, but the lower layer is still
- * down. Disable the network layer.
- */
- dcb->dcb_ipcp_state = PPPS_INITIAL;
- break;
- case PPPS_STOPPED:
- dcb->dcb_ipcp_state = PPPS_CLOSED;
- break;
- case PPPS_STOPPING:
- dcb->dcb_ipcp_state = PPPS_CLOSING;
- break;
- case PPPS_REQSENT:
- case PPPS_ACKRCVD:
- case PPPS_ACKSENT:
- case PPPS_OPENED:
- /*
- * The IPCP layer and the lower layer are up. Inform the upper
- * layer that we are going down and send out a termination
- * request.
- */
- NutIpcpOutput(dev, XCP_TERMREQ, dcb->dcb_reqid, 0);
- dcb->dcb_ipcp_state = PPPS_CLOSING;
- NutEventPost(&dcb->dcb_state_chg);
- break;
- }
- }
- /*
- * The lower layer is up.
- * \param dev Pointer to the NUTDEVICE structure of the PPP device.
- *
- */
- void IpcpLowerUp(NUTDEVICE * dev)
- {
- PPPDCB *dcb = dev->dev_dcb;
- #ifdef NUTDEBUG
- if (__ppp_trf) {
- fputs("\n[IPCP-LOWERUP]", __ppp_trs);
- }
- #endif
- switch (dcb->dcb_ipcp_state) {
- case PPPS_INITIAL:
- dcb->dcb_ipcp_state = PPPS_CLOSED;
- break;
- case PPPS_STARTING:
- IpcpTxConfReq(dev, ++dcb->dcb_reqid);
- dcb->dcb_ipcp_state = PPPS_REQSENT;
- break;
- }
- }
- /*
- * The link layer is down.
- *
- * Cancel all timeouts and inform upper layers.
- * \param dev Pointer to the NUTDEVICE structure of the PPP device.
- *
- */
- void IpcpLowerDown(NUTDEVICE * dev)
- {
- PPPDCB *dcb = dev->dev_dcb;
- #ifdef NUTDEBUG
- if (__ppp_trf) {
- fputs("\n[IPCP-LOWERDOWN]", __ppp_trs);
- }
- #endif
- switch (dcb->dcb_ipcp_state) {
- case PPPS_CLOSED:
- dcb->dcb_ipcp_state = PPPS_INITIAL;
- _ioctl(dcb->dcb_fd, HDLC_SETIFNET, 0);
- break;
- case PPPS_STOPPED:
- dcb->dcb_ipcp_state = PPPS_STARTING;
- break;
- case PPPS_CLOSING:
- dcb->dcb_ipcp_state = PPPS_INITIAL;
- break;
- case PPPS_STOPPING:
- case PPPS_REQSENT:
- case PPPS_ACKRCVD:
- case PPPS_ACKSENT:
- dcb->dcb_ipcp_state = PPPS_STARTING;
- break;
- case PPPS_OPENED:
- dcb->dcb_ipcp_state = PPPS_STARTING;
- NutEventPost(&dcb->dcb_state_chg);
- break;
- }
- }
- /*@}*/
|