pppfsm.c
上传用户:hepax88
上传日期:2007-01-03
资源大小:1101k
文件大小:17k
源码类别:

TCP/IP协议栈

开发平台:

Visual C++

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