pppsm.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  1. /*
  2. * Copyright (C) 2001-2004 by egnite Software GmbH
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. Neither the name of the copyright holders nor the names of
  16. * contributors may be used to endorse or promote products derived
  17. * from this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  22. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  23. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  24. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  25. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  26. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  27. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  28. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  29. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30. * SUCH DAMAGE.
  31. *
  32. * For additional information see http://www.ethernut.de/
  33. *
  34. * -
  35. */
  36. /*!
  37. * \file net/pppsm.c
  38. * \brief PPP state machine.
  39. *
  40. * \verbatim
  41. * $Id: pppsm.c 3686 2011-12-04 14:20:38Z haraldkipp $
  42. * \endverbatim
  43. */
  44. #include <cfg/os.h>
  45. #include <cfg/ppp.h>
  46. #include <string.h>
  47. #include <io.h>
  48. #include <fcntl.h>
  49. #include <dev/uart.h>
  50. #include <sys/thread.h>
  51. #include <sys/heap.h>
  52. #include <sys/event.h>
  53. #include <sys/timer.h>
  54. #include <net/if_var.h>
  55. #include <dev/ppp.h>
  56. #include <netinet/if_ppp.h>
  57. #include <netinet/ppp_fsm.h>
  58. #ifdef NUTDEBUG
  59. #include <net/netdebug.h>
  60. #endif
  61. #ifndef NUT_THREAD_PPPSMSTACK
  62. #define NUT_THREAD_PPPSMSTACK 512
  63. #endif
  64. /*!
  65. * \addtogroup xgPPP
  66. */
  67. /*@{*/
  68. uint32_t new_magic = 0x12345678;
  69. static HANDLE pppThread;
  70. /*! \fn NutPppSm(void *arg)
  71. * \brief PPP state machine timeout thread.
  72. *
  73. * Handles timeouts for LCP and IPCP.
  74. */
  75. THREAD(NutPppSm, arg)
  76. {
  77. NUTDEVICE *dev = arg;
  78. PPPDCB *dcb = dev->dev_dcb;
  79. uint_fast8_t retries;
  80. for (;;) {
  81. NutSleep(5000);
  82. new_magic++;
  83. retries = dcb->dcb_retries;
  84. /*
  85. * LCP timeouts.
  86. */
  87. switch (dcb->dcb_lcp_state) {
  88. case PPPS_CLOSING:
  89. case PPPS_STOPPING:
  90. if (retries < 9) {
  91. if (retries) {
  92. NutLcpOutput(dev, XCP_TERMREQ, dcb->dcb_reqid, 0);
  93. }
  94. dcb->dcb_retries = retries + 1;
  95. } else
  96. dcb->dcb_lcp_state = (dcb->dcb_lcp_state == PPPS_CLOSING) ? PPPS_CLOSED : PPPS_STOPPED;
  97. break;
  98. case PPPS_REQSENT:
  99. case PPPS_ACKSENT:
  100. if (retries < 9) {
  101. if (retries)
  102. LcpTxConfReq(dev, dcb->dcb_reqid, 0);
  103. dcb->dcb_retries = retries + 1;
  104. } else
  105. dcb->dcb_lcp_state = PPPS_STOPPED;
  106. break;
  107. }
  108. /*
  109. * Authentication timeouts.
  110. */
  111. if (dcb->dcb_auth_state == PAPCS_AUTHREQ) {
  112. if (retries < 9) {
  113. if (retries)
  114. PapTxAuthReq(dev, dcb->dcb_reqid);
  115. dcb->dcb_retries = retries + 1;
  116. } else
  117. dcb->dcb_lcp_state = PPPS_STOPPED;
  118. }
  119. /*
  120. * IPCP timeouts.
  121. */
  122. switch (dcb->dcb_ipcp_state) {
  123. case PPPS_CLOSING:
  124. case PPPS_STOPPING:
  125. if (retries < 9) {
  126. if (retries)
  127. NutIpcpOutput(dev, XCP_TERMREQ, dcb->dcb_reqid, 0);
  128. dcb->dcb_retries = retries + 1;
  129. } else
  130. dcb->dcb_ipcp_state = (dcb->dcb_ipcp_state == PPPS_CLOSING) ? PPPS_CLOSED : PPPS_STOPPED;
  131. break;
  132. case PPPS_REQSENT:
  133. case PPPS_ACKSENT:
  134. if (retries < 9) {
  135. if (retries)
  136. IpcpTxConfReq(dev, dcb->dcb_reqid);
  137. dcb->dcb_retries = retries + 1;
  138. } else
  139. dcb->dcb_ipcp_state = PPPS_STOPPED;
  140. break;
  141. }
  142. }
  143. }
  144. /*!
  145. * \brief Initialize the PPP state machine.
  146. *
  147. * Start the PPP timer thread, if not already running.
  148. *
  149. * \param dev Pointer to the NUTDEVICE structure of the PPP device.
  150. *
  151. * \return 0 on success, -1 otherwise.
  152. */
  153. int NutPppInitStateMachine(NUTDEVICE * dev)
  154. {
  155. if (pppThread == 0 && (pppThread = NutThreadCreate("pppsm", NutPppSm, dev,
  156. (NUT_THREAD_PPPSMSTACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD)) == 0) {
  157. return -1;
  158. }
  159. return 0;
  160. }
  161. /*!
  162. * \brief Trigger LCP open event.
  163. *
  164. * Enable the link to come up. Typically triggered by the upper layer,
  165. * when it is enabled.
  166. *
  167. * \param dev Pointer to the NUTDEVICE structure of the PPP device.
  168. *
  169. */
  170. void LcpOpen(NUTDEVICE * dev)
  171. {
  172. PPPDCB *dcb = dev->dev_dcb;
  173. #ifdef NUTDEBUG
  174. if (__ppp_trf) {
  175. fputs("\n[LCP-OPEN]", __ppp_trs);
  176. }
  177. #endif
  178. switch (dcb->dcb_lcp_state) {
  179. case PPPS_INITIAL:
  180. /*
  181. * The LCP layer and the lower layer are down. Enable the LCP
  182. * layer. Link negotiation will start as soon as the lower
  183. * layer comes up.
  184. */
  185. dcb->dcb_lcp_state = PPPS_STARTING;
  186. break;
  187. case PPPS_CLOSED:
  188. /*
  189. * The LCP layer is down and the lower layer is up. Start
  190. * link negotiation by sending out a request.
  191. */
  192. LcpTxConfReq(dev, ++dcb->dcb_reqid, 0);
  193. dcb->dcb_lcp_state = PPPS_REQSENT;
  194. break;
  195. case PPPS_CLOSING:
  196. /*
  197. * The LCP layer is going down.
  198. */
  199. dcb->dcb_lcp_state = PPPS_STOPPING;
  200. break;
  201. }
  202. }
  203. /*!
  204. * \brief Trigger LCP close event.
  205. *
  206. * Disable the link.
  207. *
  208. * \param dev Pointer to the NUTDEVICE structure of the PPP device.
  209. */
  210. void LcpClose(NUTDEVICE * dev)
  211. {
  212. PPPDCB *dcb = dev->dev_dcb;
  213. #ifdef NUTDEBUG
  214. if (__ppp_trf) {
  215. fputs("\n[LCP-CLOSE]", __ppp_trs);
  216. }
  217. #endif
  218. switch (dcb->dcb_lcp_state) {
  219. case PPPS_STARTING:
  220. /*
  221. * The LCP layer has been enabled, but the lower layer is still
  222. * down. Disable the link layer.
  223. */
  224. dcb->dcb_lcp_state = PPPS_INITIAL;
  225. break;
  226. case PPPS_STOPPED:
  227. dcb->dcb_lcp_state = PPPS_CLOSED;
  228. break;
  229. case PPPS_STOPPING:
  230. dcb->dcb_lcp_state = PPPS_CLOSING;
  231. break;
  232. case PPPS_REQSENT:
  233. case PPPS_ACKRCVD:
  234. case PPPS_ACKSENT:
  235. case PPPS_OPENED:
  236. /*
  237. * The LCP layer and the lower layer are up. Inform the upper
  238. * layer that we are going down and send out a termination
  239. * request.
  240. */
  241. dcb->dcb_lcp_state = PPPS_CLOSING;
  242. IpcpLowerDown(dev);
  243. NutLcpOutput(dev, XCP_TERMREQ, dcb->dcb_reqid, 0);
  244. break;
  245. }
  246. }
  247. /*!
  248. * \brief Trigger LCP lower up event.
  249. *
  250. * \param dev Pointer to the NUTDEVICE structure of the PPP device.
  251. *
  252. */
  253. void LcpLowerUp(NUTDEVICE * dev)
  254. {
  255. PPPDCB *dcb = dev->dev_dcb;
  256. #ifdef NUTDEBUG
  257. if (__ppp_trf) {
  258. fputs("\n[LCP-LOWERUP]", __ppp_trs);
  259. }
  260. #endif
  261. switch (dcb->dcb_lcp_state) {
  262. case PPPS_INITIAL:
  263. /*
  264. * The LCP layer is still disabled.
  265. */
  266. dcb->dcb_lcp_state = PPPS_CLOSED;
  267. break;
  268. case PPPS_STARTING:
  269. /*
  270. * The LCP layer is enabled. Send a configuration request.
  271. */
  272. LcpTxConfReq(dev, ++dcb->dcb_reqid, 0);
  273. dcb->dcb_lcp_state = PPPS_REQSENT;
  274. break;
  275. }
  276. }
  277. /*!
  278. * \brief Trigger LCP lower down event.
  279. *
  280. * \param dev Pointer to the NUTDEVICE structure of the PPP device.
  281. *
  282. */
  283. void LcpLowerDown(NUTDEVICE * dev)
  284. {
  285. PPPDCB *dcb = dev->dev_dcb;
  286. #ifdef NUTDEBUG
  287. if (__ppp_trf) {
  288. fputs("\n[LCP-LOWERDOWN]", __ppp_trs);
  289. }
  290. #endif
  291. switch (dcb->dcb_lcp_state) {
  292. case PPPS_CLOSED:
  293. dcb->dcb_lcp_state = PPPS_INITIAL;
  294. break;
  295. case PPPS_STOPPED:
  296. dcb->dcb_lcp_state = PPPS_STARTING;
  297. break;
  298. case PPPS_CLOSING:
  299. dcb->dcb_lcp_state = PPPS_INITIAL;
  300. break;
  301. case PPPS_STOPPING:
  302. case PPPS_REQSENT:
  303. case PPPS_ACKRCVD:
  304. case PPPS_ACKSENT:
  305. dcb->dcb_lcp_state = PPPS_STARTING;
  306. break;
  307. case PPPS_OPENED:
  308. IpcpLowerDown(dev);
  309. dcb->dcb_lcp_state = PPPS_STARTING;
  310. break;
  311. }
  312. }
  313. /*!
  314. * \brief Trigger IPCP open event.
  315. *
  316. * Link is allowed to come up.
  317. * \param dev Pointer to the NUTDEVICE structure of the PPP device.
  318. *
  319. */
  320. void IpcpOpen(NUTDEVICE * dev)
  321. {
  322. PPPDCB *dcb = dev->dev_dcb;
  323. #ifdef NUTDEBUG
  324. if (__ppp_trf) {
  325. fputs("\n[IPCP-OPEN]", __ppp_trs);
  326. }
  327. #endif
  328. switch (dcb->dcb_ipcp_state) {
  329. case PPPS_INITIAL:
  330. /*
  331. * The IPCP layer and the lower layer are down. Enable the
  332. * IPCP layer and the lower layer.
  333. */
  334. dcb->dcb_ipcp_state = PPPS_STARTING;
  335. LcpOpen(dev);
  336. break;
  337. case PPPS_CLOSED:
  338. IpcpTxConfReq(dev, ++dcb->dcb_reqid);
  339. dcb->dcb_ipcp_state = PPPS_REQSENT;
  340. break;
  341. case PPPS_CLOSING:
  342. dcb->dcb_ipcp_state = PPPS_STOPPING;
  343. break;
  344. }
  345. }
  346. /*!
  347. * \brief Trigger IPCP close event.
  348. *
  349. * Disable the link.
  350. *
  351. * Cancel timeouts and either initiate close or possibly go directly to
  352. * the PPPS_CLOSED state.
  353. *
  354. * \param dev Pointer to the NUTDEVICE structure of the PPP device.
  355. */
  356. void IpcpClose(NUTDEVICE * dev)
  357. {
  358. PPPDCB *dcb = dev->dev_dcb;
  359. #ifdef NUTDEBUG
  360. if (__ppp_trf) {
  361. fputs("\n[IPCP-CLOSE]", __ppp_trs);
  362. }
  363. #endif
  364. switch (dcb->dcb_ipcp_state) {
  365. case PPPS_STARTING:
  366. /*
  367. * The IPCP layer has been enabled, but the lower layer is still
  368. * down. Disable the network layer.
  369. */
  370. dcb->dcb_ipcp_state = PPPS_INITIAL;
  371. break;
  372. case PPPS_STOPPED:
  373. dcb->dcb_ipcp_state = PPPS_CLOSED;
  374. break;
  375. case PPPS_STOPPING:
  376. dcb->dcb_ipcp_state = PPPS_CLOSING;
  377. break;
  378. case PPPS_REQSENT:
  379. case PPPS_ACKRCVD:
  380. case PPPS_ACKSENT:
  381. case PPPS_OPENED:
  382. /*
  383. * The IPCP layer and the lower layer are up. Inform the upper
  384. * layer that we are going down and send out a termination
  385. * request.
  386. */
  387. NutIpcpOutput(dev, XCP_TERMREQ, dcb->dcb_reqid, 0);
  388. dcb->dcb_ipcp_state = PPPS_CLOSING;
  389. NutEventPost(&dcb->dcb_state_chg);
  390. break;
  391. }
  392. }
  393. /*
  394. * The lower layer is up.
  395. * \param dev Pointer to the NUTDEVICE structure of the PPP device.
  396. *
  397. */
  398. void IpcpLowerUp(NUTDEVICE * dev)
  399. {
  400. PPPDCB *dcb = dev->dev_dcb;
  401. #ifdef NUTDEBUG
  402. if (__ppp_trf) {
  403. fputs("\n[IPCP-LOWERUP]", __ppp_trs);
  404. }
  405. #endif
  406. switch (dcb->dcb_ipcp_state) {
  407. case PPPS_INITIAL:
  408. dcb->dcb_ipcp_state = PPPS_CLOSED;
  409. break;
  410. case PPPS_STARTING:
  411. IpcpTxConfReq(dev, ++dcb->dcb_reqid);
  412. dcb->dcb_ipcp_state = PPPS_REQSENT;
  413. break;
  414. }
  415. }
  416. /*
  417. * The link layer is down.
  418. *
  419. * Cancel all timeouts and inform upper layers.
  420. * \param dev Pointer to the NUTDEVICE structure of the PPP device.
  421. *
  422. */
  423. void IpcpLowerDown(NUTDEVICE * dev)
  424. {
  425. PPPDCB *dcb = dev->dev_dcb;
  426. #ifdef NUTDEBUG
  427. if (__ppp_trf) {
  428. fputs("\n[IPCP-LOWERDOWN]", __ppp_trs);
  429. }
  430. #endif
  431. switch (dcb->dcb_ipcp_state) {
  432. case PPPS_CLOSED:
  433. dcb->dcb_ipcp_state = PPPS_INITIAL;
  434. _ioctl(dcb->dcb_fd, HDLC_SETIFNET, 0);
  435. break;
  436. case PPPS_STOPPED:
  437. dcb->dcb_ipcp_state = PPPS_STARTING;
  438. break;
  439. case PPPS_CLOSING:
  440. dcb->dcb_ipcp_state = PPPS_INITIAL;
  441. break;
  442. case PPPS_STOPPING:
  443. case PPPS_REQSENT:
  444. case PPPS_ACKRCVD:
  445. case PPPS_ACKSENT:
  446. dcb->dcb_ipcp_state = PPPS_STARTING;
  447. break;
  448. case PPPS_OPENED:
  449. dcb->dcb_ipcp_state = PPPS_STARTING;
  450. NutEventPost(&dcb->dcb_state_chg);
  451. break;
  452. }
  453. }
  454. /*@}*/