telnet.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2012-04-01 Bernard first version
  9. * 2018-01-25 armink Fix it on RT-Thread 3.0+
  10. */
  11. #include <rtdevice.h>
  12. #ifdef PKG_NETUTILS_TELNET
  13. #if defined(RT_USING_DFS_NET) || defined(SAL_USING_POSIX)
  14. #include <sys/socket.h>
  15. #else
  16. #include <lwip/sockets.h>
  17. #endif /* defined(RT_USING_DFS_NET) || defined(SAL_USING_POSIX) */
  18. #if defined(RT_USING_POSIX_STDIO) /* RT_VER_NUM >= 0x40100 */
  19. #include <fcntl.h>
  20. #include <sys/ioctl.h>
  21. #include <poll.h>
  22. #elif defined(RT_USING_POSIX) /* RT_VER_NUM < 0x40100 */
  23. #include <dfs_posix.h>
  24. #include <dfs_poll.h>
  25. #endif /* defined(RT_USING_POSIX_STDIO) */
  26. #if defined(RT_USING_POSIX_STDIO) || defined(RT_USING_POSIX)
  27. #if RT_VER_NUM >= 0x50100
  28. #include <unistd.h>
  29. #include <posix/stdio.h>
  30. #else
  31. #include <libc.h>
  32. #endif /* RT_VER_NUM >= 0x50100 */
  33. static int dev_old_flag;
  34. #endif /* defined(RT_USING_POSIX_STDIO) || defined(RT_USING_POSIX) */
  35. #include <finsh.h>
  36. #include <msh.h>
  37. #include <shell.h>
  38. #define TELNET_PORT 23
  39. #define TELNET_BACKLOG 5
  40. #define RX_BUFFER_SIZE 256
  41. #define TX_BUFFER_SIZE 4096
  42. #define ISO_nl 0x0a
  43. #define ISO_cr 0x0d
  44. #define STATE_NORMAL 0
  45. #define STATE_IAC 1
  46. #define STATE_WILL 2
  47. #define STATE_WONT 3
  48. #define STATE_DO 4
  49. #define STATE_DONT 5
  50. #define STATE_CLOSE 6
  51. #define TELNET_IAC 255
  52. #define TELNET_WILL 251
  53. #define TELNET_WONT 252
  54. #define TELNET_DO 253
  55. #define TELNET_DONT 254
  56. #define TELNET_OPT_ECHO 1
  57. #define TELNET_OPT_SGA 3
  58. struct telnet_session
  59. {
  60. struct rt_ringbuffer rx_ringbuffer;
  61. struct rt_ringbuffer tx_ringbuffer;
  62. rt_mutex_t rx_ringbuffer_lock;
  63. rt_mutex_t tx_ringbuffer_lock;
  64. struct rt_device device;
  65. rt_int32_t server_fd;
  66. rt_int32_t client_fd;
  67. /* telnet protocol */
  68. rt_uint8_t state;
  69. rt_uint8_t finsh_saved_echo_mode;
  70. rt_sem_t read_notice;
  71. };
  72. static struct telnet_session* telnet;
  73. /* process tx data */
  74. static void send_to_client(struct telnet_session* telnet)
  75. {
  76. rt_size_t length;
  77. rt_uint8_t tx_buffer[32];
  78. while (1)
  79. {
  80. rt_memset(tx_buffer, 0, sizeof(tx_buffer));
  81. rt_mutex_take(telnet->tx_ringbuffer_lock, RT_WAITING_FOREVER);
  82. /* get buffer from ringbuffer */
  83. length = rt_ringbuffer_get(&(telnet->tx_ringbuffer), tx_buffer, sizeof(tx_buffer));
  84. rt_mutex_release(telnet->tx_ringbuffer_lock);
  85. /* do a tx procedure */
  86. if (length > 0)
  87. {
  88. send(telnet->client_fd, tx_buffer, length, 0);
  89. }
  90. else break;
  91. }
  92. }
  93. /* send telnet option to remote */
  94. static void send_option_to_client(struct telnet_session* telnet, rt_uint8_t option, rt_uint8_t value)
  95. {
  96. rt_uint8_t optbuf[4];
  97. optbuf[0] = TELNET_IAC;
  98. optbuf[1] = option;
  99. optbuf[2] = value;
  100. optbuf[3] = 0;
  101. rt_mutex_take(telnet->tx_ringbuffer_lock, RT_WAITING_FOREVER);
  102. rt_ringbuffer_put(&telnet->tx_ringbuffer, optbuf, 3);
  103. rt_mutex_release(telnet->tx_ringbuffer_lock);
  104. send_to_client(telnet);
  105. }
  106. /* process rx data */
  107. static void process_rx(struct telnet_session* telnet, rt_uint8_t *data, rt_size_t length)
  108. {
  109. rt_size_t index;
  110. for (index = 0; index < length; index++)
  111. {
  112. switch (telnet->state)
  113. {
  114. case STATE_IAC:
  115. if (*data == TELNET_IAC)
  116. {
  117. rt_mutex_take(telnet->rx_ringbuffer_lock, RT_WAITING_FOREVER);
  118. /* put buffer to ringbuffer */
  119. rt_ringbuffer_putchar(&(telnet->rx_ringbuffer), *data);
  120. rt_mutex_release(telnet->rx_ringbuffer_lock);
  121. telnet->state = STATE_NORMAL;
  122. }
  123. else
  124. {
  125. /* set telnet state according to received package */
  126. switch (*data)
  127. {
  128. case TELNET_WILL:
  129. telnet->state = STATE_WILL;
  130. break;
  131. case TELNET_WONT:
  132. telnet->state = STATE_WONT;
  133. break;
  134. case TELNET_DO:
  135. telnet->state = STATE_DO;
  136. break;
  137. case TELNET_DONT:
  138. telnet->state = STATE_DONT;
  139. break;
  140. default:
  141. telnet->state = STATE_NORMAL;
  142. break;
  143. }
  144. }
  145. break;
  146. case STATE_WILL:
  147. if (*data == TELNET_OPT_ECHO || *data == TELNET_OPT_SGA)
  148. {
  149. send_option_to_client(telnet, TELNET_DO, *data);
  150. }
  151. else
  152. {
  153. send_option_to_client(telnet, TELNET_DONT, *data);
  154. }
  155. telnet->state = STATE_NORMAL;
  156. break;
  157. case STATE_WONT:
  158. if (*data == TELNET_OPT_ECHO)
  159. {
  160. finsh_set_echo(0);
  161. }
  162. telnet->state = STATE_NORMAL;
  163. break;
  164. case STATE_DO:
  165. if (*data == TELNET_OPT_ECHO || *data == TELNET_OPT_SGA)
  166. {
  167. if (*data == TELNET_OPT_ECHO)
  168. {
  169. finsh_set_echo(1);
  170. }
  171. send_option_to_client(telnet, TELNET_WILL, *data);
  172. }
  173. else
  174. {
  175. send_option_to_client(telnet, TELNET_WONT, *data);
  176. }
  177. telnet->state = STATE_NORMAL;
  178. break;
  179. case STATE_DONT:
  180. if (*data == TELNET_OPT_ECHO)
  181. {
  182. finsh_set_echo(0);
  183. }
  184. telnet->state = STATE_NORMAL;
  185. break;
  186. case STATE_NORMAL:
  187. if (*data == TELNET_IAC)
  188. {
  189. telnet->state = STATE_IAC;
  190. }
  191. else if (*data == '\r')
  192. {
  193. /*
  194. * telnet client(not busybox's telnet) will send 0d00 if not toggle crlf by default,
  195. * change them to 0d0a, so we don't have to toggle
  196. */
  197. if ((index + 1) <= length)
  198. {
  199. if (data[1] == 0)
  200. {
  201. data[1] = '\n';
  202. }
  203. }
  204. }
  205. else if (*data != '\r') /* ignore '\r' */
  206. {
  207. rt_mutex_take(telnet->rx_ringbuffer_lock, RT_WAITING_FOREVER);
  208. /* put buffer to ringbuffer */
  209. rt_ringbuffer_putchar(&(telnet->rx_ringbuffer), *data);
  210. rt_mutex_release(telnet->rx_ringbuffer_lock);
  211. rt_sem_release(telnet->read_notice);
  212. }
  213. break;
  214. }
  215. data++;
  216. }
  217. #if !(defined(RT_USING_POSIX_STDIO) || defined(RT_USING_POSIX))
  218. rt_size_t rx_length;
  219. rt_mutex_take(telnet->rx_ringbuffer_lock, RT_WAITING_FOREVER);
  220. /* get total size */
  221. rx_length = rt_ringbuffer_data_len(&telnet->rx_ringbuffer);
  222. rt_mutex_release(telnet->rx_ringbuffer_lock);
  223. /* indicate there are reception data */
  224. if ((rx_length > 0) && (telnet->device.rx_indicate != RT_NULL))
  225. {
  226. telnet->device.rx_indicate(&telnet->device, rx_length);
  227. }
  228. #endif /* !(defined(RT_USING_POSIX_STDIO) || defined(RT_USING_POSIX)) */
  229. return;
  230. }
  231. /* client close */
  232. static void client_close(struct telnet_session* telnet)
  233. {
  234. /* set console */
  235. rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
  236. /* set finsh device */
  237. #if defined(RT_USING_POSIX_STDIO) || defined(RT_USING_POSIX)
  238. #if RT_VER_NUM >= 0x50100
  239. ioctl(rt_posix_stdio_get_console(), F_SETFL, (void *) dev_old_flag);
  240. rt_posix_stdio_set_console(RT_CONSOLE_DEVICE_NAME, O_RDWR);
  241. #else
  242. ioctl(libc_stdio_get_console(), F_SETFL, (void *) dev_old_flag);
  243. libc_stdio_set_console(RT_CONSOLE_DEVICE_NAME, O_RDWR);
  244. #endif /* RT_VER_NUM >= 0x50100 */
  245. #else
  246. finsh_set_device(RT_CONSOLE_DEVICE_NAME);
  247. #endif /* defined(RT_USING_POSIX_STDIO) || defined(RT_USING_POSIX) */
  248. rt_sem_release(telnet->read_notice);
  249. /* close connection */
  250. closesocket(telnet->client_fd);
  251. /* restore shell option */
  252. finsh_set_echo(telnet->finsh_saved_echo_mode);
  253. rt_kprintf("telnet: resume console to %s\n", RT_CONSOLE_DEVICE_NAME);
  254. }
  255. /* RT-Thread Device Driver Interface */
  256. static rt_err_t telnet_init(rt_device_t dev)
  257. {
  258. return RT_EOK;
  259. }
  260. static rt_err_t telnet_open(rt_device_t dev, rt_uint16_t oflag)
  261. {
  262. return RT_EOK;
  263. }
  264. static rt_err_t telnet_close(rt_device_t dev)
  265. {
  266. return RT_EOK;
  267. }
  268. static rt_ssize_t telnet_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
  269. {
  270. rt_size_t result = 0;
  271. rt_sem_take(telnet->read_notice, RT_WAITING_FOREVER);
  272. /* read from rx ring buffer */
  273. rt_mutex_take(telnet->rx_ringbuffer_lock, RT_WAITING_FOREVER);
  274. result = rt_ringbuffer_get(&(telnet->rx_ringbuffer), buffer, size);
  275. if (result == 0)
  276. {
  277. /**
  278. * MUST return unless **1** byte for support sync read data.
  279. * It will return empty string when read no data
  280. */
  281. *(char *) buffer = '\0';
  282. result = 1;
  283. }
  284. rt_mutex_release(telnet->rx_ringbuffer_lock);
  285. return result;
  286. }
  287. static rt_ssize_t telnet_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
  288. {
  289. const rt_uint8_t *ptr;
  290. ptr = (rt_uint8_t*) buffer;
  291. rt_mutex_take(telnet->tx_ringbuffer_lock, RT_WAITING_FOREVER);
  292. while (size)
  293. {
  294. if (*ptr == '\n')
  295. rt_ringbuffer_putchar(&telnet->tx_ringbuffer, '\r');
  296. if (rt_ringbuffer_putchar(&telnet->tx_ringbuffer, *ptr) == 0) /* overflow */
  297. break;
  298. ptr++;
  299. size--;
  300. }
  301. rt_mutex_release(telnet->tx_ringbuffer_lock);
  302. /* send data to telnet client */
  303. send_to_client(telnet);
  304. return (rt_uint32_t) ptr - (rt_uint32_t) buffer;
  305. }
  306. static rt_err_t telnet_control(rt_device_t dev, int cmd, void *args)
  307. {
  308. return RT_EOK;
  309. }
  310. #ifdef RT_USING_DEVICE_OPS
  311. static struct rt_device_ops _ops = {
  312. telnet_init,
  313. telnet_open,
  314. telnet_close,
  315. telnet_read,
  316. telnet_write,
  317. telnet_control
  318. };
  319. #endif /* RT_USING_DEVICE_OPS */
  320. #ifdef RT_USING_POSIX_STDIO
  321. #include <dfs_file.h>
  322. #include <fcntl.h>
  323. #include <unistd.h>
  324. #include <poll.h>
  325. #include <sys/ioctl.h>
  326. #ifdef RT_USING_POSIX_TERMIOS
  327. #include <termios.h>
  328. #endif
  329. /* it's possible the 'getc/putc' is defined by stdio.h in gcc/newlib. */
  330. #ifdef getc
  331. #undef getc
  332. #endif
  333. #ifdef putc
  334. #undef putc
  335. #endif
  336. #ifdef RT_USING_DFS_V2
  337. static ssize_t telnet_fops_read(struct dfs_file *fd, void *buf, size_t count, off_t *pos)
  338. #else
  339. static ssize_t telnet_fops_read(struct dfs_file *fd, void *buf, size_t count)
  340. #endif
  341. {
  342. int size = 0;
  343. rt_device_t device;
  344. int wait_ret;
  345. device = &telnet->device;
  346. do
  347. {
  348. size = rt_device_read(device, -1, buf, count);
  349. if (size <= 0)
  350. {
  351. if (fd->flags & O_NONBLOCK)
  352. {
  353. size = -EAGAIN;
  354. break;
  355. }
  356. wait_ret = rt_wqueue_wait_interruptible(&(device->wait_queue), 0, RT_WAITING_FOREVER);
  357. if (wait_ret != RT_EOK)
  358. {
  359. break;
  360. }
  361. }
  362. }while (size <= 0);
  363. if (size < 0)
  364. {
  365. size = 0;
  366. }
  367. return size;
  368. }
  369. static const struct dfs_file_ops telnet_fops =
  370. {
  371. .open = NULL,
  372. .close = NULL,
  373. .ioctl = NULL,
  374. .read = telnet_fops_read,
  375. .write = NULL,
  376. .poll = NULL,
  377. };
  378. #endif /* RT_USING_POSIX_STDIO */
  379. /* telnet server thread entry */
  380. static void telnet_thread(void* parameter)
  381. {
  382. #define RECV_BUF_LEN 64
  383. struct sockaddr_in addr;
  384. socklen_t addr_size;
  385. rt_uint8_t recv_buf[RECV_BUF_LEN];
  386. rt_int32_t recv_len = 0;
  387. rt_int32_t keepalive = 1;
  388. if ((telnet->server_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
  389. {
  390. rt_kprintf("telnet: create socket failed\n");
  391. return;
  392. }
  393. if(setsockopt(telnet->server_fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepalive, sizeof(keepalive)) < 0)
  394. {
  395. rt_kprintf("telnet:set socket keepalive failed\n");
  396. return;
  397. }
  398. addr.sin_family = AF_INET;
  399. addr.sin_port = htons(TELNET_PORT);
  400. addr.sin_addr.s_addr = INADDR_ANY;
  401. rt_memset(&(addr.sin_zero), 0, sizeof(addr.sin_zero));
  402. if (bind(telnet->server_fd, (struct sockaddr *) &addr, sizeof(struct sockaddr)) == -1)
  403. {
  404. rt_kprintf("telnet: bind socket failed\n");
  405. return;
  406. }
  407. if (listen(telnet->server_fd, TELNET_BACKLOG) == -1)
  408. {
  409. rt_kprintf("telnet: listen socket failed\n");
  410. return;
  411. }
  412. /* register telnet device */
  413. telnet->device.type = RT_Device_Class_Char;
  414. #ifdef RT_USING_DEVICE_OPS
  415. telnet->device.ops = &_ops;
  416. #else
  417. telnet->device.init = telnet_init;
  418. telnet->device.open = telnet_open;
  419. telnet->device.close = telnet_close;
  420. telnet->device.read = telnet_read;
  421. telnet->device.write = telnet_write;
  422. telnet->device.control = telnet_control;
  423. #endif /* RT_USING_DEVICE_OPS */
  424. #ifdef RT_USING_POSIX_STDIO
  425. telnet->device.fops = &telnet_fops;
  426. #endif
  427. /* no private */
  428. telnet->device.user_data = RT_NULL;
  429. /* register telnet device */
  430. rt_device_register(&telnet->device, "telnet", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STREAM);
  431. while (1)
  432. {
  433. rt_kprintf("telnet: waiting for connection\n");
  434. /* grab new connection */
  435. if ((telnet->client_fd = accept(telnet->server_fd, (struct sockaddr *) &addr, &addr_size)) == -1)
  436. {
  437. continue;
  438. }
  439. rt_kprintf("telnet: new telnet client(%s:%d) connection, switch console to telnet...\n", inet_ntoa(addr.sin_addr), addr.sin_port);
  440. /* process the new connection */
  441. /* set console */
  442. rt_console_set_device("telnet");
  443. /* set finsh device */
  444. #if defined(RT_USING_POSIX_STDIO) || defined(RT_USING_POSIX)
  445. /* backup flag */
  446. #if RT_VER_NUM >= 0x50100
  447. dev_old_flag = ioctl(rt_posix_stdio_get_console(), F_GETFL, (void *) RT_NULL);
  448. /* add non-block flag */
  449. ioctl(rt_posix_stdio_get_console(), F_SETFL, (void *) (dev_old_flag | O_NONBLOCK));
  450. /* set tcp shell device for console */
  451. rt_posix_stdio_set_console("telnet", O_RDWR);
  452. #else
  453. dev_old_flag = ioctl(libc_stdio_get_console(), F_GETFL, (void *) RT_NULL);
  454. /* add non-block flag */
  455. ioctl(libc_stdio_get_console(), F_SETFL, (void *) (dev_old_flag | O_NONBLOCK));
  456. /* set tcp shell device for console */
  457. libc_stdio_set_console("telnet", O_RDWR);
  458. #endif /* RT_VER_NUM >= 0x50100 */
  459. /* resume finsh thread, make sure it will unblock from last device receive */
  460. rt_thread_t tid = rt_thread_find(FINSH_THREAD_NAME);
  461. if (tid)
  462. {
  463. rt_thread_resume(tid);
  464. rt_schedule();
  465. }
  466. #else
  467. /* set finsh device */
  468. finsh_set_device("telnet");
  469. #endif /* defined(RT_USING_POSIX_STDIO) || defined(RT_USING_POSIX) */
  470. /* set init state */
  471. telnet->state = STATE_NORMAL;
  472. telnet->finsh_saved_echo_mode = finsh_get_echo();
  473. send_option_to_client(telnet, TELNET_WILL, TELNET_OPT_ECHO);
  474. /* output RT-Thread version and shell prompt */
  475. #ifdef FINSH_USING_MSH
  476. msh_exec("version", rt_strlen("version"));
  477. #endif /* FINSH_USING_MSH */
  478. rt_kprintf(FINSH_PROMPT);
  479. while (1)
  480. {
  481. /* try to send all data in tx ringbuffer */
  482. send_to_client(telnet);
  483. /* do a rx procedure */
  484. if ((recv_len = recv(telnet->client_fd, recv_buf, RECV_BUF_LEN, 0)) > 0)
  485. {
  486. process_rx(telnet, recv_buf, recv_len);
  487. }
  488. else
  489. {
  490. /* close connection */
  491. client_close(telnet);
  492. break;
  493. }
  494. }
  495. }
  496. }
  497. /* telnet server */
  498. void telnet_server(void)
  499. {
  500. rt_thread_t tid;
  501. if (telnet == RT_NULL)
  502. {
  503. rt_uint8_t *ptr;
  504. telnet = rt_malloc(sizeof(struct telnet_session));
  505. if (telnet == RT_NULL)
  506. {
  507. rt_kprintf("telnet: no memory\n");
  508. return;
  509. }
  510. /* init ringbuffer */
  511. ptr = rt_malloc(RX_BUFFER_SIZE);
  512. if (ptr)
  513. {
  514. rt_ringbuffer_init(&telnet->rx_ringbuffer, ptr, RX_BUFFER_SIZE);
  515. }
  516. else
  517. {
  518. rt_kprintf("telnet: no memory\n");
  519. return;
  520. }
  521. ptr = rt_malloc(TX_BUFFER_SIZE);
  522. if (ptr)
  523. {
  524. rt_ringbuffer_init(&telnet->tx_ringbuffer, ptr, TX_BUFFER_SIZE);
  525. }
  526. else
  527. {
  528. rt_kprintf("telnet: no memory\n");
  529. return;
  530. }
  531. /* create tx ringbuffer lock */
  532. telnet->tx_ringbuffer_lock = rt_mutex_create("telnet_tx", RT_IPC_FLAG_FIFO);
  533. /* create rx ringbuffer lock */
  534. telnet->rx_ringbuffer_lock = rt_mutex_create("telnet_rx", RT_IPC_FLAG_FIFO);
  535. telnet->read_notice = rt_sem_create("telnet_rx", 0, RT_IPC_FLAG_FIFO);
  536. tid = rt_thread_create("telnet", telnet_thread, RT_NULL, 2048, 25, 5);
  537. if (tid != RT_NULL)
  538. {
  539. rt_thread_startup(tid);
  540. rt_kprintf("Telnet server start successfully\n");
  541. }
  542. }
  543. else
  544. {
  545. rt_kprintf("telnet: server already running\n");
  546. }
  547. }
  548. #ifdef RT_USING_FINSH
  549. #include <finsh.h>
  550. FINSH_FUNCTION_EXPORT(telnet_server, startup telnet server);
  551. #ifdef FINSH_USING_MSH
  552. MSH_CMD_EXPORT(telnet_server, startup telnet server)
  553. #endif /* FINSH_USING_MSH */
  554. #endif /* RT_USING_FINSH */
  555. #endif /* PKG_NETUTILS_TELNET */