home *** CD-ROM | disk | FTP | other *** search
/ Media Share 9 / MEDIASHARE_09.ISO / network / src_1218.zip / PPPFSM.C < prev    next >
C/C++ Source or Header  |  1991-09-18  |  18KB  |  852 lines

  1. /*
  2.  *  PPPFSM.C    -- PPP Finite State Machine
  3.  *
  4.  *    This implementation of PPP is declared to be in the public domain.
  5.  *
  6.  *    Jan 91    Bill_Simpson@um.cc.umich.edu
  7.  *        Computer Systems Consulting Services
  8.  *
  9.  *    Acknowledgements and correction history may be found in PPP.C
  10.  */
  11.  
  12. #include <stdio.h>
  13. #include <ctype.h>
  14. #include "global.h"
  15. #include "mbuf.h"
  16. #include "iface.h"
  17. #include "ppp.h"
  18. #include "pppfsm.h"
  19. #include "ppplcp.h"
  20. #include "trace.h"
  21.  
  22.  
  23. char *fsmStates[] = {
  24.     "Closed",
  25.     "Listen",
  26.     "Req Sent",
  27.     "Ack Rcvd",
  28.     "Ack Sent",
  29.     "Opened",
  30.     "TermSent"
  31. };
  32.  
  33. char *fsmCodes[] = {
  34.     NULLCHAR,
  35.     "Config Req",
  36.     "Config Ack",
  37.     "Config Nak",
  38.     "Config Reject",
  39.     "Termin Req",
  40.     "Termin Ack",
  41.     "Code Reject",
  42.     "Protocol Reject",
  43.     "Echo Request",
  44.     "Echo Reply",
  45.     "Discard Request",
  46. };
  47.  
  48. static int fsm_sendtermreq __ARGS((struct fsm_s *fsm_p));
  49. static int fsm_sendtermack __ARGS((struct fsm_s *fsm_p, byte_t id));
  50.  
  51. static void fsm_timeout __ARGS((void *vp));
  52.  
  53. static void fsm_reset __ARGS((struct fsm_s *fsm_p));
  54. static void fsm_opening __ARGS((struct fsm_s *fsm_p));
  55.  
  56.  
  57. /************************************************************************/
  58. /* Convert header in host form to network form */
  59. struct mbuf *
  60. htoncnf(cnf, data)
  61. struct config_hdr *cnf;
  62. struct mbuf *data;
  63. {
  64.     struct mbuf *bp;
  65.     register char *cp;
  66.  
  67.     /* Prepend bytes for LCP/IPCP header */
  68.     if ((bp = pushdown(data, CONFIG_HDR_LEN)) == NULLBUF) {
  69.         free_p( data );
  70.         return NULLBUF;
  71.     }
  72.  
  73.     /* Load header with proper values */
  74.     cp = bp->data;
  75.     *cp++ = cnf->code;
  76.     *cp++ = cnf->id;
  77.     put16(cp, cnf->len);
  78.  
  79.     return bp;
  80. }
  81.  
  82. /* Extract header from incoming packet */
  83. int
  84. ntohcnf(cnf, bpp)
  85. struct config_hdr *cnf;
  86. struct mbuf **bpp;
  87. {
  88.     char cnfb[CONFIG_HDR_LEN];
  89.  
  90.     if ( cnf == NULL )
  91.         return -1;
  92.  
  93.     if ( pullup( bpp, cnfb, CONFIG_HDR_LEN ) < CONFIG_HDR_LEN )
  94.         return -1;
  95.  
  96.         cnf->code = cnfb[0];
  97.         cnf->id = cnfb[1];
  98.     cnf->len = get16(&cnfb[2]);
  99.     return 0;
  100. }
  101.  
  102. /***************************************/
  103. /* Extract configuration option header */
  104. int
  105. ntohopt(opt,bpp)
  106. struct option_hdr *opt;
  107. struct mbuf **bpp;
  108. {
  109.     char optb[OPTION_HDR_LEN];
  110.  
  111.     if ( opt == NULL )
  112.         return -1;
  113.  
  114.     if ( pullup( bpp, optb, OPTION_HDR_LEN ) < OPTION_HDR_LEN )
  115.         return -1;
  116.  
  117.     opt->type = optb[0];
  118.     opt->len = optb[1];
  119.     return 0;
  120. }
  121.  
  122.  
  123. /************************************************************************/
  124. void
  125. fsm_no_action(fsm_p)
  126. struct fsm_s *fsm_p;
  127. {
  128.     PPP_DEBUG_ROUTINES("fsm_no_action()");
  129. }
  130. int
  131. fsm_no_check(fsm_p, hdr, bp)
  132. struct fsm_s *fsm_p;
  133. struct config_hdr *hdr;
  134. struct mbuf *bp;
  135. {
  136.     PPP_DEBUG_ROUTINES("fsm_no_check()");
  137.     return 0;
  138. }
  139.  
  140.  
  141. /************************************************************************/
  142. /* General log routine */
  143. void
  144. fsm_log(fsm_p, comment)
  145. struct fsm_s *fsm_p;
  146. char *comment;
  147. {
  148.     if (PPPtrace > 1)
  149.         trace_log(PPPiface,"%s PPP/%s %-8s; %s",
  150.             fsm_p->ppp_p->iface->name,
  151.             fsm_p->pdc->name,
  152.             fsmStates[fsm_p->state],
  153.             comment);
  154. }
  155.  
  156.  
  157. /************************************************************************/
  158. /* Set a timer in case an expected event does not occur */
  159. void
  160. fsm_timer(fsm_p)
  161. struct fsm_s *fsm_p;
  162. {
  163.     PPP_DEBUG_ROUTINES("fsm_timer()");
  164.  
  165.     start_timer( &(fsm_p->timer) );
  166. }
  167.  
  168.  
  169. /************************************************************************/
  170. /* Send a packet to the remote host */
  171. int
  172. fsm_send(fsm_p,code,id,data)
  173. struct fsm_s *fsm_p;
  174. byte_t code;
  175. byte_t id;
  176. struct mbuf *data;
  177. {
  178.     struct ppp_s *ppp_p = fsm_p->ppp_p;
  179.     struct iface *iface = ppp_p->iface;
  180.     struct config_hdr hdr;
  181.     struct mbuf *bp;
  182.  
  183.     switch( hdr.code = code ) {
  184.     case CONFIG_REQ:
  185.     case TERM_REQ:
  186.     case ECHO_REQ:
  187.         /* Save ID field for match against replies from remote host */
  188.         fsm_p->lastid = ppp_p->id;
  189.         /* fallthru */
  190.     case PROT_REJ:
  191.     case DISCARD_REQ:
  192.         /* Use a unique ID field value */
  193.         hdr.id = ppp_p->id++;
  194.         break;
  195.  
  196.     case CONFIG_ACK:
  197.     case CONFIG_NAK:
  198.     case CONFIG_REJ:
  199.     case TERM_ACK:
  200.     case CODE_REJ:
  201.     case ECHO_REPLY:
  202.         /* Use ID sent by remote host */
  203.         hdr.id = id;
  204.         break;
  205.  
  206.     default:
  207.         /* we're in trouble */
  208.         trace_log(PPPiface, "%s PPP/%s %-8s;"
  209.             " Send with bogus code: %d",
  210.             iface->name,
  211.             fsm_p->pdc->name,
  212.             fsmStates[fsm_p->state],
  213.             code);
  214.         return -1;
  215.     };
  216.  
  217.     switch( code ) {
  218.     case ECHO_REQ:
  219.     case ECHO_REPLY:
  220.     case DISCARD_REQ:
  221.     {
  222.         struct lcp_s *lcp_p = fsm_p->pdv;
  223.         if ( (bp = pushdown(data, 4)) == NULLBUF ) {
  224.             free_p( data );
  225.             return -1;
  226.         }
  227.         put32(bp->data, lcp_p->local.work.magic_number);
  228.         data = bp;
  229.     }
  230.     };
  231.  
  232.     hdr.len = len_p(data) + CONFIG_HDR_LEN;
  233.  
  234.     /* Prepend header to packet data */
  235.     if ((data = htoncnf(&hdr,data)) == NULLBUF)
  236.         return -1;
  237.  
  238.     if (PPPtrace > 1) {
  239.         trace_log(PPPiface, "%s PPP/%s %-8s;"
  240.             " Sending %s, id: %d, len: %d",
  241.             iface->name,
  242.             fsm_p->pdc->name,
  243.             fsmStates[fsm_p->state],
  244.             fsmCodes[code],
  245.             hdr.id,hdr.len);
  246.     }
  247.  
  248.     ppp_p->OutNCP[fsm_p->pdc->fsmi]++;
  249.  
  250.     return( (*iface->output)
  251.         (iface, NULLCHAR, NULLCHAR, fsm_p->pdc->protocol, data) );
  252. }
  253.  
  254.  
  255. /************************************************************************/
  256. /* Send a configuration request */
  257. int
  258. fsm_sendreq(fsm_p)
  259. struct fsm_s *fsm_p;
  260. {
  261.     struct mbuf *bp;
  262.  
  263.     PPP_DEBUG_ROUTINES("fsm_sendreq()");
  264.  
  265.     if ( fsm_p->retry <= 0 )
  266.         return -1;
  267.  
  268.     fsm_p->retry--;
  269.     fsm_timer(fsm_p);
  270.  
  271.     bp = (*fsm_p->pdc->makereq)(fsm_p);
  272.     return( fsm_send(fsm_p, CONFIG_REQ, 0, bp) );
  273. }
  274.  
  275.  
  276. /************************************************************************/
  277. /* Send a termination request */
  278. static int
  279. fsm_sendtermreq(fsm_p)
  280. struct fsm_s *fsm_p;
  281. {
  282.     PPP_DEBUG_ROUTINES("fsm_sendtermreq()");
  283.  
  284.     if ( fsm_p->retry <= 0 )
  285.         return -1;
  286.  
  287.     fsm_p->retry--;
  288.     fsm_timer(fsm_p);
  289.     return( fsm_send(fsm_p, TERM_REQ, 0, NULLBUF) );
  290. }
  291.  
  292.  
  293. /************************************************************************/
  294. /* Send Terminate Ack */
  295. static int
  296. fsm_sendtermack(fsm_p,id)
  297. struct fsm_s *fsm_p;
  298. byte_t id;
  299. {
  300.     PPP_DEBUG_ROUTINES("fsm_sendtermack()");
  301.  
  302.     return( fsm_send(fsm_p, TERM_ACK, id, NULLBUF) );
  303. }
  304.  
  305.  
  306. /************************************************************************/
  307. /* Reset state machine */
  308. static void
  309. fsm_reset(fsm_p)
  310. struct fsm_s *fsm_p;
  311. {
  312.     PPP_DEBUG_ROUTINES("fsm_reset()");
  313.  
  314.     fsm_p->state = (fsm_p->flags & (FSM_ACTIVE | FSM_PASSIVE))
  315.             ? fsmLISTEN : fsmCLOSED;
  316.     fsm_p->retry = fsm_p->try_req;
  317.     fsm_p->retry_nak = fsm_p->try_nak;
  318.  
  319.     (*fsm_p->pdc->reset)(fsm_p);
  320. }
  321.  
  322.  
  323. /************************************************************************/
  324. /* Configuration negotiation complete */
  325. static void
  326. fsm_opening(fsm_p)
  327. struct fsm_s *fsm_p;
  328. {
  329.     fsm_log(fsm_p, "Opened");
  330.  
  331.     stop_timer(&(fsm_p->timer));
  332.  
  333.     (*fsm_p->pdc->opening)(fsm_p);
  334.     fsm_p->state = fsmOPENED;
  335. }
  336.  
  337.  
  338. /************************************************************************/
  339. /*            E V E N T   P R O C E S S I N G            */
  340. /************************************************************************/
  341.  
  342. /* Process incoming packet */
  343. void
  344. fsm_proc(fsm_p,bp)
  345. struct fsm_s *fsm_p;
  346. struct mbuf *bp;
  347. {
  348.     struct config_hdr hdr;
  349.  
  350.     PPPtrace = fsm_p->ppp_p->trace;
  351.     PPPiface = fsm_p->ppp_p->iface;
  352.  
  353.     if ( ntohcnf(&hdr, &bp) == -1 )
  354.         fsm_log( fsm_p, "short configuration packet" );
  355.  
  356.     if (PPPtrace > 1)
  357.         trace_log(PPPiface, "%s PPP/%s %-8s;"
  358.             " Processing %s, id: %d, len: %d",
  359.             fsm_p->ppp_p->iface->name,
  360.             fsm_p->pdc->name,
  361.             fsmStates[fsm_p->state],
  362.             fsmCodes[hdr.code],
  363.             hdr.id,    hdr.len);
  364.  
  365.     hdr.len -= CONFIG_HDR_LEN;        /* Length includes envelope */
  366.     trim_mbuf(&bp, hdr.len);        /* Trim off padding */
  367.  
  368.     switch(hdr.code) {
  369.     case CONFIG_REQ:
  370.         switch(fsm_p->state) {
  371.         case fsmOPENED:        /* Unexpected event? */
  372.             (*fsm_p->pdc->closing)(fsm_p);
  373.             fsm_reset(fsm_p);
  374.             /* fallthru */
  375.         case fsmLISTEN:
  376.             (*fsm_p->pdc->starting)(fsm_p);
  377.             fsm_sendreq(fsm_p);
  378.             /* fallthru */
  379.         case fsmREQ_Sent:
  380.         case fsmACK_Sent:    /* Unexpected event? */
  381.             fsm_p->state =
  382.             ((*fsm_p->pdc->request)(fsm_p, &hdr, bp) == 0)
  383.                 ? fsmACK_Sent : fsmREQ_Sent;
  384.             break;
  385.  
  386.         case fsmACK_Rcvd:
  387.             if ((*fsm_p->pdc->request)(fsm_p, &hdr, bp) == 0) {
  388.                 fsm_opening(fsm_p);
  389.             } else {
  390.                 /* give peer time to respond */
  391.                 fsm_timer(fsm_p);
  392.             }
  393.             break;
  394.  
  395.         case fsmCLOSED:
  396.             /* Don't accept any connections */
  397.             fsm_sendtermack(fsm_p, hdr.id);
  398.             /* fallthru */
  399.         case fsmTERM_Sent:
  400.             /* We are attempting to close connection; */
  401.             /* wait for timeout to resend a Terminate Request */
  402.             free_p(bp);
  403.             break;
  404.         };
  405.         break;
  406.  
  407.     case CONFIG_ACK:
  408.         switch(fsm_p->state) {
  409.         case fsmREQ_Sent:
  410.             if ((*fsm_p->pdc->ack)(fsm_p, &hdr, bp) == 0) {
  411.                 fsm_p->state = fsmACK_Rcvd;
  412.             }
  413.             break;
  414.  
  415.         case fsmACK_Sent:
  416.             if ((*fsm_p->pdc->ack)(fsm_p, &hdr, bp) == 0) {
  417.                 fsm_opening(fsm_p);
  418.             }
  419.             break;
  420.  
  421.         case fsmOPENED:        /* Unexpected event? */
  422.             (*fsm_p->pdc->closing)(fsm_p);
  423.             (*fsm_p->pdc->starting)(fsm_p);
  424.             fsm_reset(fsm_p);
  425.             /* fallthru */
  426.         case fsmACK_Rcvd:    /* Unexpected event? */
  427.             free_p(bp);
  428.             fsm_sendreq(fsm_p);
  429.             fsm_p->state = fsmREQ_Sent;
  430.             break;
  431.  
  432.         case fsmCLOSED:
  433.         case fsmLISTEN:
  434.             /* Out of Sync; kill the remote */
  435.             fsm_sendtermack(fsm_p, hdr.id);
  436.             /* fallthru */
  437.         case fsmTERM_Sent:
  438.             /* We are attempting to close connection; */
  439.             /* wait for timeout to resend a Terminate Request */
  440.             free_p(bp);
  441.             break;
  442.         };
  443.         break;
  444.  
  445.     case CONFIG_NAK:
  446.         switch(fsm_p->state) {
  447.         case fsmREQ_Sent:
  448.         case fsmACK_Sent:
  449.             /* Update our config request to reflect NAKed options */
  450.             if ((*fsm_p->pdc->nak)(fsm_p, &hdr, bp) == 0) {
  451.                 /* Send updated config request */
  452.                 fsm_sendreq(fsm_p);
  453.             }
  454.             break;
  455.  
  456.         case fsmOPENED:        /* Unexpected event? */
  457.             (*fsm_p->pdc->closing)(fsm_p);
  458.             (*fsm_p->pdc->starting)(fsm_p);
  459.             fsm_reset(fsm_p);
  460.             /* fallthru */
  461.         case fsmACK_Rcvd:    /* Unexpected event? */
  462.             free_p(bp);
  463.             fsm_sendreq(fsm_p);
  464.             fsm_p->state = fsmREQ_Sent;
  465.             break;
  466.  
  467.         case fsmCLOSED:
  468.         case fsmLISTEN:
  469.             /* Out of Sync; kill the remote */
  470.             fsm_sendtermack(fsm_p, hdr.id);
  471.             /* fallthru */
  472.         case fsmTERM_Sent:
  473.             /* We are attempting to close connection; */
  474.             /* wait for timeout to resend a Terminate Request */
  475.             free_p(bp);
  476.             break;
  477.         };
  478.         break;
  479.  
  480.     case CONFIG_REJ:
  481.         switch(fsm_p->state) {
  482.         case fsmREQ_Sent:
  483.         case fsmACK_Sent:
  484.             if((*fsm_p->pdc->reject)(fsm_p, &hdr, bp) == 0) {
  485.                 fsm_sendreq(fsm_p);
  486.             }
  487.             break;
  488.  
  489.         case fsmOPENED:        /* Unexpected event? */
  490.             (*fsm_p->pdc->closing)(fsm_p);
  491.             (*fsm_p->pdc->starting)(fsm_p);
  492.             fsm_reset(fsm_p);
  493.             /* fallthru */
  494.         case fsmACK_Rcvd:    /* Unexpected event? */
  495.             free_p(bp);
  496.             fsm_sendreq(fsm_p);
  497.             fsm_p->state = fsmREQ_Sent;
  498.             break;
  499.  
  500.         case fsmCLOSED:
  501.         case fsmLISTEN:
  502.             /* Out of Sync; kill the remote */
  503.             fsm_sendtermack(fsm_p, hdr.id);
  504.             /* fallthru */
  505.         case fsmTERM_Sent:
  506.             /* We are attempting to close connection; */
  507.             /* wait for timeout to resend a Terminate Request */
  508.             free_p(bp);
  509.             break;
  510.         };
  511.         break;
  512.  
  513.     case TERM_REQ:
  514.         fsm_log(fsm_p, "Peer requested Termination");
  515.  
  516.         switch(fsm_p->state) {
  517.         case fsmOPENED:
  518.             fsm_sendtermack(fsm_p, hdr.id);
  519.             (*fsm_p->pdc->closing)(fsm_p);
  520.             (*fsm_p->pdc->stopping)(fsm_p);
  521.             fsm_reset(fsm_p);
  522.             break;
  523.  
  524.         case fsmACK_Rcvd:
  525.         case fsmACK_Sent:
  526.             fsm_p->state = fsmREQ_Sent;
  527.             /* fallthru */
  528.         case fsmREQ_Sent:
  529.         case fsmTERM_Sent:
  530.             /* waiting for timeout */
  531.             /* fallthru */
  532.         case fsmCLOSED:
  533.         case fsmLISTEN:
  534.             /* Unexpected, but make them happy */
  535.             fsm_sendtermack(fsm_p, hdr.id);
  536.             break;
  537.         };
  538.         break;
  539.  
  540.     case TERM_ACK:
  541.         switch(fsm_p->state) {
  542.         case fsmTERM_Sent:
  543.             stop_timer(&(fsm_p->timer));
  544.  
  545.             fsm_log(fsm_p, "Terminated");
  546.             (*fsm_p->pdc->stopping)(fsm_p);
  547.             fsm_reset(fsm_p);
  548.             break;
  549.  
  550.         case fsmOPENED:
  551.             /* Remote host has abruptly closed connection */
  552.             fsm_log(fsm_p, "Terminated unexpectly");
  553.             (*fsm_p->pdc->closing)(fsm_p);
  554.             fsm_reset(fsm_p);
  555.             if ( fsm_sendreq(fsm_p) == 0 ) {
  556.                 fsm_p->state = fsmREQ_Sent;
  557.             }
  558.             break;
  559.  
  560.         case fsmACK_Sent:
  561.         case fsmACK_Rcvd:
  562.             fsm_p->state = fsmREQ_Sent;
  563.             /* fallthru */
  564.         case fsmREQ_Sent:
  565.             /* waiting for timeout */
  566.             /* fallthru */
  567.         case fsmCLOSED:
  568.         case fsmLISTEN:
  569.             /* Unexpected, but no action needed */
  570.             break;
  571.         };
  572.         break;
  573.  
  574.     case CODE_REJ:
  575.         trace_log(PPPiface,"%s PPP/%s Code Reject;"
  576.             " indicates faulty implementation",
  577.             fsm_p->ppp_p->iface->name,
  578.             fsm_p->pdc->name);
  579.         (*fsm_p->pdc->stopping)(fsm_p);
  580.         fsm_reset(fsm_p);
  581.         free_p(bp);
  582.         break;
  583.  
  584.     case PROT_REJ:
  585.         trace_log(PPPiface,"%s PPP/%s Protocol Reject;"
  586.             " please do not use this protocol",
  587.             fsm_p->ppp_p->iface->name,
  588.             fsm_p->pdc->name);
  589.         free_p(bp);
  590.         break;
  591.  
  592.     case ECHO_REQ:
  593.         switch(fsm_p->state) {
  594.         case fsmOPENED:
  595.             fsm_send( fsm_p, ECHO_REPLY, hdr.id, bp );
  596.             break;
  597.  
  598.         case fsmCLOSED:
  599.         case fsmLISTEN:
  600.             /* Out of Sync; kill the remote */
  601.             fsm_sendtermack(fsm_p, hdr.id);
  602.             /* fallthru */
  603.         case fsmREQ_Sent:
  604.         case fsmACK_Rcvd:
  605.         case fsmACK_Sent:
  606.         case fsmTERM_Sent:
  607.             /* ignore */
  608.             free_p(bp);
  609.             break;
  610.         };
  611.         break;
  612.  
  613.     case ECHO_REPLY:
  614.     case DISCARD_REQ:
  615.     case QUALITY_REPORT:
  616.         free_p(bp);
  617.         break;
  618.  
  619.     default:
  620.         trace_log(PPPiface,"%s PPP/%s Unknown packet type: %d;"
  621.             " Sending Code Reject",
  622.             fsm_p->ppp_p->iface->name,
  623.             fsm_p->pdc->name,
  624.             hdr.code);
  625.  
  626.         hdr.len += CONFIG_HDR_LEN;    /* restore length */
  627.         bp = htoncnf( &hdr, bp );    /* put header back on */
  628.         fsm_send( fsm_p, CODE_REJ, hdr.id, bp );
  629.  
  630.         switch(fsm_p->state) {
  631.         case fsmREQ_Sent:
  632.         case fsmACK_Rcvd:
  633.         case fsmACK_Sent:
  634.         case fsmOPENED:
  635.             fsm_p->state = fsmLISTEN;
  636.             break;
  637.  
  638.         case fsmCLOSED:
  639.         case fsmLISTEN:
  640.         case fsmTERM_Sent:
  641.             /* no change */
  642.             break;
  643.         };
  644.         break;
  645.     }
  646. }
  647.  
  648.  
  649. /************************************************************************/
  650. /* Timeout while waiting for reply from remote host */
  651. static void
  652. fsm_timeout(vp)
  653. void *vp;
  654. {
  655.     struct fsm_s *fsm_p = (struct fsm_s *)vp;
  656.  
  657.     PPPtrace = fsm_p->ppp_p->trace;
  658.     PPPiface = fsm_p->ppp_p->iface;
  659.  
  660.     fsm_log( fsm_p, "Timeout" );
  661.  
  662.     switch(fsm_p->state) {
  663.     case fsmREQ_Sent:
  664.     case fsmACK_Rcvd:
  665.     case fsmACK_Sent:
  666.         if (fsm_p->retry > 0) {
  667.             fsm_sendreq(fsm_p);
  668.             fsm_p->state = fsmREQ_Sent;
  669.         } else {
  670.             fsm_log(fsm_p, "Request retry exceeded");
  671.             fsm_reset(fsm_p);
  672.         }
  673.         break;
  674.  
  675.     case fsmTERM_Sent:
  676.         if (fsm_p->retry > 0) {
  677.             fsm_sendtermreq(fsm_p);
  678.         } else {
  679.             fsm_log(fsm_p, "Terminate retry exceeded");
  680.             (*fsm_p->pdc->stopping)(fsm_p);
  681.             fsm_reset(fsm_p);
  682.         }
  683.         break;
  684.  
  685.     case fsmCLOSED:
  686.     case fsmLISTEN:
  687.     case fsmOPENED:
  688.         /* nothing to do */
  689.         break;
  690.     }
  691. }
  692.  
  693.  
  694. /************************************************************************/
  695. /*            I N I T I A L I Z A T I O N            */
  696. /************************************************************************/
  697.  
  698. /* Start FSM (after open event, and physical line up) */
  699. void
  700. fsm_start(fsm_p)
  701. struct fsm_s *fsm_p;
  702. {
  703.     if ( fsm_p->pdv == NULL )
  704.         return;
  705.  
  706.     PPPtrace = fsm_p->ppp_p->trace;
  707.     PPPiface = fsm_p->ppp_p->iface;
  708.  
  709.     fsm_log(fsm_p, "Start");
  710.  
  711.     if ( !(fsm_p->flags & (FSM_ACTIVE | FSM_PASSIVE)) )
  712.         return;
  713.  
  714.     switch ( fsm_p->state ) {
  715.     case fsmCLOSED:
  716.     case fsmLISTEN:
  717.     case fsmTERM_Sent:
  718.         (*fsm_p->pdc->starting)(fsm_p);
  719.         fsm_reset(fsm_p);
  720.  
  721.         if ( fsm_p->flags & FSM_ACTIVE ){
  722.             fsm_sendreq(fsm_p);
  723.             fsm_p->state = fsmREQ_Sent;
  724.         }
  725.         break;
  726.     default:
  727.         /* already started */
  728.         break;
  729.     };
  730. }
  731.  
  732.  
  733. /************************************************************************/
  734. /* Physical Line Down Event */
  735. void
  736. fsm_down(fsm_p)
  737. struct fsm_s *fsm_p;
  738. {
  739.     if ( fsm_p->pdv == NULL )
  740.         return;
  741.  
  742.     PPPtrace = fsm_p->ppp_p->trace;
  743.     PPPiface = fsm_p->ppp_p->iface;
  744.  
  745.     fsm_log(fsm_p, "Down");
  746.  
  747.     switch ( fsm_p->state ) {
  748.     case fsmREQ_Sent:
  749.     case fsmACK_Rcvd:
  750.     case fsmACK_Sent:
  751.         stop_timer(&(fsm_p->timer));
  752.         fsm_reset(fsm_p);
  753.         break;
  754.  
  755.     case fsmOPENED:
  756.         (*fsm_p->pdc->closing)(fsm_p);
  757.         /* fallthru */
  758.     case fsmTERM_Sent:
  759.         fsm_reset(fsm_p);
  760.         break;
  761.  
  762.     case fsmCLOSED:
  763.     case fsmLISTEN:
  764.         /* nothing to do */
  765.         break;
  766.     };
  767. }
  768.  
  769.  
  770. /************************************************************************/
  771. /* Close the connection */
  772. void
  773. fsm_close(fsm_p)
  774. struct fsm_s *fsm_p;
  775. {
  776.     if ( fsm_p->pdv == NULL )
  777.         return;
  778.  
  779.     PPPtrace = fsm_p->ppp_p->trace;
  780.     PPPiface = fsm_p->ppp_p->iface;
  781.  
  782.     fsm_log(fsm_p, "Close");
  783.  
  784.     switch ( fsm_p->state ) {
  785.     case fsmOPENED:
  786.         (*fsm_p->pdc->closing)(fsm_p);
  787.         /* fallthru */
  788.     case fsmACK_Sent:
  789.         fsm_p->retry = fsm_p->try_terminate;
  790.         fsm_sendtermreq(fsm_p);
  791.         fsm_p->state = fsmTERM_Sent;
  792.         break;
  793.  
  794.     case fsmREQ_Sent:
  795.     case fsmACK_Rcvd:
  796.         /* simply wait for REQ timeout to expire */
  797.         fsm_p->retry = 0;
  798.         fsm_p->state = fsmTERM_Sent;
  799.         break;
  800.  
  801.     case fsmLISTEN:
  802.         fsm_p->state = fsmCLOSED;
  803.         break;
  804.  
  805.     case fsmTERM_Sent:
  806.     case fsmCLOSED:
  807.         /* nothing to do */
  808.         break;
  809.     };
  810. }
  811.  
  812.  
  813. /************************************************************************/
  814. /* Initialize the fsm for this protocol
  815.  * Called from protocol _init
  816.  */
  817. void
  818. fsm_init(fsm_p)
  819. struct fsm_s *fsm_p;
  820. {
  821.     struct timer *t = &(fsm_p->timer);
  822.  
  823.     PPP_DEBUG_ROUTINES("fsm_init()");
  824.  
  825.     fsm_p->try_req = fsm_p->pdc->try_req;
  826.     fsm_p->try_nak = fsm_p->pdc->try_nak;
  827.     fsm_p->try_terminate = fsm_p->pdc->try_terminate;
  828.     fsm_reset(fsm_p);
  829.  
  830.     /* Initialize timer */
  831.     t->func = (void (*)())fsm_timeout;
  832.     t->arg = (void *)fsm_p;
  833.     set_timer(t, fsm_p->pdc->timeout);
  834.     fsm_timer(fsm_p);
  835.     stop_timer(t);
  836. }
  837.  
  838.  
  839. void
  840. fsm_free(fsm_p)
  841. struct fsm_s *fsm_p;
  842. {
  843.     if ( fsm_p->pdv != NULL ) {
  844.         (*fsm_p->pdc->free)(fsm_p);
  845.  
  846.         free( fsm_p->pdv );
  847.         fsm_p->pdv = NULL;
  848.     }
  849. }
  850.  
  851.  
  852.