telnetd.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. /*
  2. * Copyright (c) 2003, Adam Dunkels.
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. The name of the author may not be used to endorse or promote
  14. * products derived from this software without specific prior
  15. * written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
  18. * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  19. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  21. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  23. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  24. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  25. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  26. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  27. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. *
  29. * This file is part of the uIP TCP/IP stack
  30. *
  31. * $Id: telnetd.c,v 1.2 2006/06/07 09:43:54 adam Exp $
  32. *
  33. */
  34. #include "uip.h"
  35. #include "telnetd.h"
  36. #include "memb.h"
  37. #include "shell.h"
  38. #include <string.h>
  39. #define ISO_nl 0x0a
  40. #define ISO_cr 0x0d
  41. struct telnetd_line {
  42. char line[TELNETD_CONF_LINELEN];
  43. };
  44. MEMB(linemem, struct telnetd_line, TELNETD_CONF_NUMLINES);
  45. #define STATE_NORMAL 0
  46. #define STATE_IAC 1
  47. #define STATE_WILL 2
  48. #define STATE_WONT 3
  49. #define STATE_DO 4
  50. #define STATE_DONT 5
  51. #define STATE_CLOSE 6
  52. static struct telnetd_state s;
  53. #define TELNET_IAC 255
  54. #define TELNET_WILL 251
  55. #define TELNET_WONT 252
  56. #define TELNET_DO 253
  57. #define TELNET_DONT 254
  58. /*---------------------------------------------------------------------------*/
  59. static char *
  60. alloc_line(void)
  61. {
  62. return memb_alloc(&linemem);
  63. }
  64. /*---------------------------------------------------------------------------*/
  65. static void
  66. dealloc_line(char *line)
  67. {
  68. memb_free(&linemem, line);
  69. }
  70. /*---------------------------------------------------------------------------*/
  71. void
  72. shell_quit(char *str)
  73. {
  74. s.state = STATE_CLOSE;
  75. }
  76. /*---------------------------------------------------------------------------*/
  77. static void
  78. sendline(char *line)
  79. {
  80. static unsigned int i;
  81. for(i = 0; i < TELNETD_CONF_NUMLINES; ++i) {
  82. if(s.lines[i] == NULL) {
  83. s.lines[i] = line;
  84. break;
  85. }
  86. }
  87. if(i == TELNETD_CONF_NUMLINES) {
  88. dealloc_line(line);
  89. }
  90. }
  91. /*---------------------------------------------------------------------------*/
  92. void
  93. shell_prompt(char *str)
  94. {
  95. char *line;
  96. line = alloc_line();
  97. if(line != NULL) {
  98. strncpy(line, str, TELNETD_CONF_LINELEN);
  99. /* petsciiconv_toascii(line, TELNETD_CONF_LINELEN);*/
  100. sendline(line);
  101. }
  102. }
  103. /*---------------------------------------------------------------------------*/
  104. void
  105. shell_output(char *str1, char *str2)
  106. {
  107. static unsigned len;
  108. char *line;
  109. line = alloc_line();
  110. if(line != NULL) {
  111. len = strlen(str1);
  112. strncpy(line, str1, TELNETD_CONF_LINELEN);
  113. if(len < TELNETD_CONF_LINELEN) {
  114. strncpy(line + len, str2, TELNETD_CONF_LINELEN - len);
  115. }
  116. len = strlen(line);
  117. if(len < TELNETD_CONF_LINELEN - 2) {
  118. line[len] = ISO_cr;
  119. line[len+1] = ISO_nl;
  120. line[len+2] = 0;
  121. }
  122. /* petsciiconv_toascii(line, TELNETD_CONF_LINELEN);*/
  123. sendline(line);
  124. }
  125. }
  126. /*---------------------------------------------------------------------------*/
  127. void
  128. telnetd_init(void)
  129. {
  130. uip_listen(HTONS(23));
  131. memb_init(&linemem);
  132. shell_init();
  133. }
  134. /*---------------------------------------------------------------------------*/
  135. static void
  136. acked(void)
  137. {
  138. static unsigned int i;
  139. while(s.numsent > 0) {
  140. dealloc_line(s.lines[0]);
  141. for(i = 1; i < TELNETD_CONF_NUMLINES; ++i) {
  142. s.lines[i - 1] = s.lines[i];
  143. }
  144. s.lines[TELNETD_CONF_NUMLINES - 1] = NULL;
  145. --s.numsent;
  146. }
  147. }
  148. /*---------------------------------------------------------------------------*/
  149. static void
  150. senddata(void)
  151. {
  152. static char *bufptr, *lineptr;
  153. static int buflen, linelen;
  154. bufptr = uip_appdata;
  155. buflen = 0;
  156. for(s.numsent = 0; s.numsent < TELNETD_CONF_NUMLINES &&
  157. s.lines[s.numsent] != NULL ; ++s.numsent) {
  158. lineptr = s.lines[s.numsent];
  159. linelen = strlen(lineptr);
  160. if(linelen > TELNETD_CONF_LINELEN) {
  161. linelen = TELNETD_CONF_LINELEN;
  162. }
  163. if(buflen + linelen < uip_mss()) {
  164. memcpy(bufptr, lineptr, linelen);
  165. bufptr += linelen;
  166. buflen += linelen;
  167. } else {
  168. break;
  169. }
  170. }
  171. uip_send(uip_appdata, buflen);
  172. }
  173. /*---------------------------------------------------------------------------*/
  174. static void
  175. closed(void)
  176. {
  177. static unsigned int i;
  178. for(i = 0; i < TELNETD_CONF_NUMLINES; ++i) {
  179. if(s.lines[i] != NULL) {
  180. dealloc_line(s.lines[i]);
  181. }
  182. }
  183. }
  184. /*---------------------------------------------------------------------------*/
  185. static void
  186. get_char(u8_t c)
  187. {
  188. if(c == ISO_cr) {
  189. return;
  190. }
  191. s.buf[(int)s.bufptr] = c;
  192. if(s.buf[(int)s.bufptr] == ISO_nl ||
  193. s.bufptr == sizeof(s.buf) - 1) {
  194. if(s.bufptr > 0) {
  195. s.buf[(int)s.bufptr] = 0;
  196. /* petsciiconv_topetscii(s.buf, TELNETD_CONF_LINELEN);*/
  197. }
  198. shell_input(s.buf);
  199. s.bufptr = 0;
  200. } else {
  201. ++s.bufptr;
  202. }
  203. }
  204. /*---------------------------------------------------------------------------*/
  205. static void
  206. sendopt(u8_t option, u8_t value)
  207. {
  208. char *line;
  209. line = alloc_line();
  210. if(line != NULL) {
  211. line[0] = TELNET_IAC;
  212. line[1] = option;
  213. line[2] = value;
  214. line[3] = 0;
  215. sendline(line);
  216. }
  217. }
  218. /*---------------------------------------------------------------------------*/
  219. static void
  220. newdata(void)
  221. {
  222. u16_t len;
  223. u8_t c;
  224. char *dataptr;
  225. len = uip_datalen();
  226. dataptr = (char *)uip_appdata;
  227. while(len > 0 && s.bufptr < sizeof(s.buf)) {
  228. c = *dataptr;
  229. ++dataptr;
  230. --len;
  231. switch(s.state) {
  232. case STATE_IAC:
  233. if(c == TELNET_IAC) {
  234. get_char(c);
  235. s.state = STATE_NORMAL;
  236. } else {
  237. switch(c) {
  238. case TELNET_WILL:
  239. s.state = STATE_WILL;
  240. break;
  241. case TELNET_WONT:
  242. s.state = STATE_WONT;
  243. break;
  244. case TELNET_DO:
  245. s.state = STATE_DO;
  246. break;
  247. case TELNET_DONT:
  248. s.state = STATE_DONT;
  249. break;
  250. default:
  251. s.state = STATE_NORMAL;
  252. break;
  253. }
  254. }
  255. break;
  256. case STATE_WILL:
  257. /* Reply with a DONT */
  258. sendopt(TELNET_DONT, c);
  259. s.state = STATE_NORMAL;
  260. break;
  261. case STATE_WONT:
  262. /* Reply with a DONT */
  263. sendopt(TELNET_DONT, c);
  264. s.state = STATE_NORMAL;
  265. break;
  266. case STATE_DO:
  267. /* Reply with a WONT */
  268. sendopt(TELNET_WONT, c);
  269. s.state = STATE_NORMAL;
  270. break;
  271. case STATE_DONT:
  272. /* Reply with a WONT */
  273. sendopt(TELNET_WONT, c);
  274. s.state = STATE_NORMAL;
  275. break;
  276. case STATE_NORMAL:
  277. if(c == TELNET_IAC) {
  278. s.state = STATE_IAC;
  279. } else {
  280. get_char(c);
  281. }
  282. break;
  283. }
  284. }
  285. }
  286. /*---------------------------------------------------------------------------*/
  287. void
  288. telnetd_appcall(void)
  289. {
  290. static unsigned int i;
  291. if(uip_connected()) {
  292. /* tcp_markconn(uip_conn, &s);*/
  293. for(i = 0; i < TELNETD_CONF_NUMLINES; ++i) {
  294. s.lines[i] = NULL;
  295. }
  296. s.bufptr = 0;
  297. s.state = STATE_NORMAL;
  298. shell_start();
  299. }
  300. if(s.state == STATE_CLOSE) {
  301. s.state = STATE_NORMAL;
  302. uip_close();
  303. return;
  304. }
  305. if(uip_closed() ||
  306. uip_aborted() ||
  307. uip_timedout()) {
  308. closed();
  309. }
  310. if(uip_acked()) {
  311. acked();
  312. }
  313. if(uip_newdata()) {
  314. newdata();
  315. }
  316. if(uip_rexmit() ||
  317. uip_newdata() ||
  318. uip_acked() ||
  319. uip_connected() ||
  320. uip_poll()) {
  321. senddata();
  322. }
  323. }
  324. /*---------------------------------------------------------------------------*/