telnet_server.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789
  1. /*
  2. * telnet_server.c
  3. *
  4. * Created on: 24.11.2017
  5. * Author: balbekova
  6. */
  7. #pragma GCC diagnostic error "-Wall"
  8. /* Standard includes. */
  9. #include <string.h>
  10. /* lwIP core includes */
  11. #include "lwip/opt.h"
  12. #include "lwip/sockets.h"
  13. /* FreeRTOS includes. */
  14. #include "FreeRTOS.h"
  15. #include "task.h"
  16. #include "fr_timers.h"
  17. /* Utils includes. */
  18. #include "FreeRTOS_CLI.h"
  19. #include "CLI_Commands.h"
  20. #include "cli.h"
  21. #include "telnet_server.h"
  22. #include "settings_api.h"
  23. #include "parameters.h"
  24. #include "control_symbol.h"
  25. #include "log.h"
  26. #include "web_params_api.h"
  27. #define ISO_nl 0x0a
  28. #define ISO_cr 0x0d
  29. //
  30. // States
  31. //
  32. typedef enum {
  33. TELNET_STATE_NORMAL = 0,
  34. TELNET_STATE_IAC,
  35. TELNET_STATE_OPT,
  36. TELNET_STATE_SB,
  37. TELNET_STATE_OPTDAT,
  38. //TELNET_STATE_SE,
  39. TELNET_STATE_CLOSE,
  40. } telnet_state_t;
  41. //
  42. // Special telnet characters
  43. //
  44. #define TELNET_SE 240 // End of subnegotiation parameters
  45. #define TELNET_NOP 241 // No operation
  46. #define TELNET_MARK 242 // Data mark
  47. #define TELNET_BRK 243 // Break
  48. #define TELNET_IP 244 // Interrupt process
  49. #define TELNET_AO 245 // Abort output
  50. #define TELNET_AYT 246 // Are you there
  51. #define TELNET_EC 247 // Erase character
  52. #define TELNET_EL 248 // Erase line
  53. #define TELNET_GA 249 // Go ahead
  54. #define TELNET_SB 250 // Start of subnegotiation parameters
  55. #define TELNET_WILL 251 // Will option code
  56. #define TELNET_WONT 252 // Won't option code
  57. #define TELNET_DO 253 // Do option code
  58. #define TELNET_DONT 254 // Don't option code
  59. #define TELNET_IAC 255 // Interpret as command
  60. //
  61. // Telnet options
  62. //
  63. #define TELOPT_TRANSMIT_BINARY 0 // Binary Transmission (RFC856)
  64. #define TELOPT_ECHO 1 // Echo (RFC857)
  65. #define TELOPT_SUPPRESS_GO_AHEAD 3 // Suppress Go Ahead (RFC858)
  66. #define TELOPT_STATUS 5 // Status (RFC859)
  67. #define TELOPT_TIMING_MARK 6 // Timing Mark (RFC860)
  68. #define TELOPT_NAOCRD 10 // Output Carriage-Return Disposition (RFC652)
  69. #define TELOPT_NAOHTS 11 // Output Horizontal Tab Stops (RFC653)
  70. #define TELOPT_NAOHTD 12 // Output Horizontal Tab Stop Disposition (RFC654)
  71. #define TELOPT_NAOFFD 13 // Output Formfeed Disposition (RFC655)
  72. #define TELOPT_NAOVTS 14 // Output Vertical Tabstops (RFC656)
  73. #define TELOPT_NAOVTD 15 // Output Vertical Tab Disposition (RFC657)
  74. #define TELOPT_NAOLFD 16 // Output Linefeed Disposition (RFC658)
  75. #define TELOPT_EXTEND_ASCII 17 // Extended ASCII (RFC698)
  76. #define TELOPT_TERMINAL_TYPE 24 // Terminal Type (RFC1091)
  77. #define TELOPT_NAWS 31 // Negotiate About Window Size (RFC1073)
  78. #define TELOPT_TERMINAL_SPEED 32 // Terminal Speed (RFC1079)
  79. #define TELOPT_TOGGLE_FLOW_CONTROL 33 // Remote Flow Control (RFC1372)
  80. #define TELOPT_LINEMODE 34 // Linemode (RFC1184)
  81. #define TELOPT_DISPLAY_POS 35 // Linemode (RFC1184)
  82. #define TELOPT_AUTHENTICATION 37 // Authentication (RFC1416)
  83. #define TELOPT_NEW_ENV_OPTION 39 // Authentication (RFC1416)
  84. //Sub option for LINEMODE
  85. #define LINEMODE_MODE 1
  86. #define LINEMODE_EDIT 1
  87. #define LINEMODE_TRAPSIG 2
  88. #define LINEMODE_MODE_ACK 4
  89. #define LINEMODE_SOFT_TAB 8
  90. #define LINEMODE_LIT_ECHO 16
  91. #define LINEMODE_FORWARDMASK 2
  92. #define LINEMODE_SLC 3
  93. #define LINEMODE_SLC_SYNCH 1
  94. #define LINEMODE_SLC_BRK 2
  95. #define LINEMODE_SLC_IP 3
  96. #define LINEMODE_SLC_AO 4
  97. #define LINEMODE_SLC_AYT 5
  98. #define LINEMODE_SLC_EOR 6
  99. #define LINEMODE_SLC_ABORT 7
  100. #define LINEMODE_SLC_EOF 8
  101. #define LINEMODE_SLC_SUSP 9
  102. #define LINEMODE_SLC_EC 10
  103. #define LINEMODE_SLC_EL 11
  104. #define LINEMODE_SLC_EW 12
  105. #define LINEMODE_SLC_RP 13
  106. #define LINEMODE_SLC_LNEXT 14
  107. #define LINEMODE_SLC_XON 15
  108. #define LINEMODE_SLC_XOFF 16
  109. #define LINEMODE_SLC_FORW1 17
  110. #define LINEMODE_SLC_FORW2 18
  111. #define LINEMODE_SLC_MCL 19
  112. #define LINEMODE_SLC_MCR 20
  113. #define LINEMODE_SLC_MCWL 21
  114. #define LINEMODE_SLC_MCWR 22
  115. #define LINEMODE_SLC_MCBOL 23
  116. #define LINEMODE_SLC_MCEOL 24
  117. #define LINEMODE_SLC_INSRT 25
  118. #define LINEMODE_SLC_OVER 26
  119. #define LINEMODE_SLC_ECR 27
  120. #define LINEMODE_SLC_EWR 28
  121. #define LINEMODE_SLC_EBOL 29
  122. #define LINEMODE_SLC_EEOL 30
  123. #define LINEMODE_SLC_DEFAULT 3
  124. #define LINEMODE_SLC_VALUE 2
  125. #define LINEMODE_SLC_CANTCHANGE 1
  126. #define LINEMODE_SLC_NOSUPPORT 0
  127. #define LINEMODE_SLC_LEVELBITS 3
  128. #define LINEMODE_SLC_ACK 128
  129. #define LINEMODE_SLC_FLUSHIN 64
  130. #define LINEMODE_SLC_FLUSHOUT 32
  131. #define LINEMODE_EOF 236
  132. #define LINEMODE_SUSP 237
  133. #define LINEMODE_ABORT 238
  134. /* Repeat Login timeout, 1 seconds */
  135. #define REPEAT_SENSOR_INFO_TIME configTICK_RATE_HZ*5*1
  136. /* Set option to drop old connection if the new one is accepted */
  137. #define TCP_DROP_PREV_CONNECTION 0
  138. /**
  139. * A telnet connection structure.
  140. */
  141. typedef struct{
  142. telnet_state_t state;
  143. uint8_t code;
  144. unsigned char optdata[cmdMAX_INPUT_SIZE];
  145. uint8_t optlen;
  146. uint8_t login_err; // the number of failed password entry attempts
  147. uint8_t num_connect;
  148. bool active_conn;
  149. cli_state_t *cli_state;
  150. } telnetd_state_t;
  151. telnetd_state_t auth_tlnt_srvr_param[NUMBER_TELNET_CONNECT];
  152. uint8_t type_term = 0;
  153. static int32_t lSocket;
  154. static int8_t *pcOutputString;
  155. static struct fd_set master_set, read_set;
  156. static int max_sd;
  157. static struct sockaddr_in sa;
  158. static const int8_t * const pcEndOfCommandOutputString = ( int8_t * ) "\r\n[Нажмите клавишу ENTER для повторного выполнения предыдущей команды]\r\n>";
  159. /**
  160. * @brief Общая структура настроек
  161. */
  162. extern SETTINGS_t sSettings;
  163. static void deconfigure_telnet_state(telnetd_state_t *state)
  164. {
  165. if (state->cli_state) {
  166. free_state(state->cli_state);
  167. state->cli_state = NULL;
  168. }
  169. memset(state->optdata, 0, cmdMAX_INPUT_SIZE);
  170. state->optlen = 0;
  171. state->state = TELNET_STATE_NORMAL;
  172. state->num_connect = 0;
  173. state->active_conn = false;
  174. }
  175. static void sendopt(telnetd_state_t *s, u8_t code, u8_t option)
  176. {
  177. unsigned char buf[3];
  178. buf[0] = TELNET_IAC;
  179. buf[1] = code;
  180. buf[2] = option;
  181. send( s->num_connect, buf, 3, 0 );
  182. }
  183. static void sendopt_cli(cli_state_t *s, u8_t code, u8_t option)
  184. {
  185. unsigned char buf[3];
  186. buf[0] = TELNET_IAC;
  187. buf[1] = code;
  188. buf[2] = option;
  189. send( s->num_connect, buf, 3, 0 );
  190. }
  191. static void sendsubopt(telnetd_state_t *s, u8_t code, u8_t *option, u8_t len)
  192. {
  193. unsigned char buf[cmdMAX_INPUT_SIZE+3];
  194. buf[0] = TELNET_IAC;
  195. buf[1] = TELNET_SB;
  196. buf[2] = code;
  197. memcpy(&buf[3], option, len);
  198. buf[len + 3] = TELNET_IAC;
  199. buf[len + 4] = TELNET_SE;
  200. send( s->num_connect, buf, (len + 5), 0 );
  201. }
  202. void parseopt(telnetd_state_t *ts, uint8_t code, uint8_t option)
  203. {
  204. switch (option) {
  205. case TELOPT_ECHO:
  206. if (code == TELNET_WONT) {
  207. type_term = 0;
  208. }
  209. else if (code == TELNET_WILL ){
  210. type_term = 1;
  211. }
  212. break;
  213. case TELOPT_SUPPRESS_GO_AHEAD:
  214. case TELOPT_LINEMODE:
  215. case TELOPT_NAWS:
  216. case TELOPT_DISPLAY_POS:
  217. case TELOPT_NEW_ENV_OPTION:
  218. case TELOPT_TERMINAL_SPEED:
  219. case TELOPT_TERMINAL_TYPE:
  220. case TELOPT_STATUS:
  221. case TELOPT_TOGGLE_FLOW_CONTROL:
  222. break;
  223. case TELOPT_TIMING_MARK:
  224. xTimerStop(ts->cli_state->RepeatSensorInfoTimer, 0);
  225. ts->cli_state->flag_telnet_ip_option = true;
  226. sendopt(ts, TELNET_WILL, TELOPT_TIMING_MARK);
  227. sendopt(ts, TELNET_MARK, 0);
  228. if(ts->cli_state->input_state != CLI_CHANGE_PWD && ts->cli_state->input_state != CLI_CHANGE_PWD_ACK)
  229. send( ts->num_connect, pcEndOfCommandOutputString, strlen( ( const char * ) pcEndOfCommandOutputString ), 0 );
  230. break;
  231. default:
  232. if (code == TELNET_WILL || code == TELNET_WONT) {
  233. sendopt(ts, TELNET_DONT, option);
  234. } else {
  235. sendopt(ts, TELNET_WONT, option);
  236. }
  237. break;
  238. }
  239. }
  240. static void parseoptdat(telnetd_state_t *ts, int option, unsigned char *data, uint8_t len) {
  241. uint8_t subopt = 0;
  242. uint8_t subopt_val = 0;
  243. uint8_t sub_opt_data[2] = {LINEMODE_MODE, LINEMODE_EDIT};
  244. switch (option) {
  245. case TELOPT_NAWS:
  246. break;
  247. case TELOPT_TERMINAL_SPEED:
  248. break;
  249. case TELOPT_TERMINAL_TYPE:
  250. break;
  251. case TELOPT_LINEMODE:
  252. subopt = data[0];
  253. switch (subopt) {
  254. case LINEMODE_SLC:
  255. if(data[2] & LINEMODE_SLC_ACK){
  256. return;
  257. }
  258. sendsubopt(ts, option, sub_opt_data, 2);
  259. for(uint8_t i = 1; i < len; i += 3){
  260. subopt_val = data[i];
  261. switch (subopt_val) {
  262. case LINEMODE_SLC_IP:
  263. data[i+1] = LINEMODE_SLC_VALUE | LINEMODE_SLC_FLUSHIN | LINEMODE_SLC_FLUSHOUT | LINEMODE_SLC_ACK;
  264. break;
  265. case LINEMODE_SLC_XON:
  266. case LINEMODE_SLC_XOFF:
  267. case LINEMODE_SLC_EC:
  268. data[i+1] = LINEMODE_SLC_VALUE | LINEMODE_SLC_ACK;
  269. break;
  270. default:
  271. data[i+1] = LINEMODE_SLC_NOSUPPORT;
  272. data[i+2] = 0;
  273. break;
  274. }
  275. }
  276. sendsubopt(ts, option, data, len);
  277. break;
  278. }
  279. break;
  280. }
  281. }
  282. extern int8_t cOutputBuffer[ configCOMMAND_INT_MAX_OUTPUT_SIZE ];
  283. portBASE_TYPE FreeRTOS_CLIAuthProcess( int8_t * pcWriteBuffer, cli_state_t *s)
  284. {
  285. portBASE_TYPE xReturn = pdTRUE;
  286. uint32_t len;
  287. user_level_t user_id = MAX_USER_LEVELS;
  288. char password[cmdMAX_INPUT_SIZE] = { 0 };
  289. const int8_t * const pcPSWHeader = ( int8_t * ) "\r\npassword:";
  290. const int8_t * const pcLoginHeader = ( int8_t * ) "\r\nlogin:";
  291. printf("CAP buf: %s\r\n", s->buf);
  292. memset(pcWriteBuffer, 0, configCOMMAND_INT_MAX_OUTPUT_SIZE);
  293. switch(s->input_state){
  294. case CLI_AUTH:
  295. memset(s->login, 0, MAX_WEB_LOGIN_LEN);
  296. len = strlen(s->buf);
  297. if (len < MAX_WEB_LOGIN_LEN){
  298. strncpy(s->login, s->buf, len);
  299. sendopt_cli(s, TELNET_WILL, TELOPT_ECHO);
  300. strncpy( ( char * ) pcWriteBuffer, ( const char * ) pcPSWHeader, strlen( ( char * ) pcPSWHeader ) );
  301. s->input_state = CLI_AUTH_PASSW;
  302. xReturn = pdTRUE;
  303. } else {
  304. xReturn = pdFALSE;
  305. }
  306. break;
  307. case CLI_AUTH_PASSW:
  308. sendopt_cli(s, TELNET_WONT, TELOPT_ECHO);
  309. memset(password, 0, MAX_WEB_PASSWD_LEN);
  310. len = strlen(s->buf);
  311. strncpy(password, s->buf, len);
  312. user_id = cli_auth_user((const char *)s->login, password, LOG_LOGIN_TELNET);
  313. if (user_id != MAX_USER_LEVELS) {
  314. s->user_id = user_id;
  315. s->login_err = 0;
  316. strcpy( ( char * ) pcWriteBuffer, "\r\nАвторизация успешно пройдена\r\n>" );
  317. s->input_state = CLI_CMD;
  318. xReturn = pdTRUE;
  319. } else {
  320. xReturn = pdFALSE;
  321. }
  322. break;
  323. default:
  324. // called auth when already authorized
  325. xReturn = pdFALSE;
  326. s->input_state = CLI_AUTH;
  327. return xReturn;
  328. break;
  329. }
  330. if (xReturn == pdFALSE){
  331. s->input_state = CLI_AUTH;
  332. if (s->login_err < 4){
  333. s->login_err ++;
  334. strcpy( ( char * ) pcWriteBuffer, "\r\nОшибка авторизации\r\n" );
  335. strncat( ( char * ) pcWriteBuffer, ( const char * ) pcLoginHeader, strlen( ( char * ) pcLoginHeader ) );
  336. xReturn = pdTRUE;
  337. } else {
  338. // password entry tries exceeded
  339. s->login_err = 0;
  340. xReturn = pdFALSE;
  341. }
  342. printf("login error, errors so far: %d\r\n", s->login_err);
  343. }
  344. return xReturn;
  345. }
  346. /*-----------------------------------------------------------------------------------*/
  347. static void newdata(telnetd_state_t *s, char c)
  348. {
  349. switch(s->state) {
  350. case TELNET_STATE_IAC:
  351. switch (c) {
  352. case TELNET_IAC:
  353. s->state = TELNET_STATE_NORMAL;
  354. break;
  355. case TELNET_WILL:
  356. case TELNET_WONT:
  357. case TELNET_DO:
  358. case TELNET_DONT:
  359. s->code = c;
  360. s->state = TELNET_STATE_OPT;
  361. break;
  362. case TELNET_SB:
  363. s->state = TELNET_STATE_SB;
  364. break;
  365. default:
  366. s->state = TELNET_STATE_NORMAL;
  367. break;
  368. }
  369. break;
  370. case TELNET_STATE_OPT:
  371. parseopt(s, s->code, c);
  372. s->state = TELNET_STATE_NORMAL;
  373. break;
  374. case TELNET_STATE_SB:
  375. s->code = c;
  376. s->optlen = 0;
  377. s->state = TELNET_STATE_OPTDAT;
  378. break;
  379. case TELNET_STATE_OPTDAT:
  380. if (c == TELNET_SE && s->optdata[s->optlen-1] == TELNET_IAC) {
  381. parseoptdat(s, s->code, s->optdata, (s->optlen-1));
  382. s->state = TELNET_STATE_NORMAL;
  383. //s->state = TELNET_STATE_SE;
  384. } else if (s->optlen < sizeof(s->optdata)) {
  385. s->optdata[s->optlen++] = c;
  386. }
  387. break;
  388. /*case TELNET_STATE_SE:
  389. if (c == TELNET_SE) parseoptdat(s, s->code, s->optdata, s->optlen);
  390. s->state = TELNET_STATE_NORMAL;
  391. break;*/
  392. case TELNET_STATE_NORMAL:
  393. if(c == TELNET_IAC) {
  394. s->state = TELNET_STATE_IAC;
  395. } else {
  396. // incoming user input
  397. cli_getchar(s->cli_state, c, type_term == 1);
  398. }
  399. break;
  400. default:
  401. printf("unexpected telnet state\r\n");
  402. }
  403. }
  404. /*-----------------------------------------------------------*/
  405. /* Stop server */
  406. static void stop_server(void) {
  407. /* Clean up all of the sockets that are open */
  408. for (int i = 0; i <= max_sd; ++i)
  409. {
  410. if (FD_ISSET(i, &master_set)) {
  411. DBG printf("Close sock %d\n", i);
  412. closesocket(i);
  413. FD_CLR(i, &master_set);
  414. }
  415. }
  416. DBG printf("Portgw stopped\n");
  417. for (int i = 0; i < array_len(auth_tlnt_srvr_param); ++i) {
  418. deconfigure_telnet_state(auth_tlnt_srvr_param + i);
  419. }
  420. }
  421. /* Start server */
  422. static bool start_server(uint16_t port)
  423. {
  424. int res;
  425. lSocket = socket(PF_INET, SOCK_STREAM, 0);
  426. if (lSocket < 0) {
  427. DBG printf("Socket create failed\r\n");
  428. return false;
  429. }
  430. res = fcntl(lSocket, F_SETFL, O_NONBLOCK);
  431. if (res < 0) {
  432. DBG printf("fcntl() failed");
  433. closesocket(lSocket);
  434. return false;
  435. }
  436. memset(&sa, 0, sizeof(struct sockaddr_in));
  437. sa.sin_family = AF_INET;
  438. sa.sin_addr.s_addr = IPADDR_ANY;
  439. sa.sin_port = htons(port);
  440. if (bind(lSocket, (struct sockaddr *)&sa, sizeof(sa)) == -1)
  441. {
  442. DBG printf("Bind to port %d failed\n", port);
  443. closesocket(lSocket);
  444. return false;
  445. }
  446. res = listen(lSocket, 20);
  447. if (res < 0) {
  448. DBG printf("Listen failed failed\r\n");
  449. closesocket(lSocket);
  450. return false;
  451. }
  452. FD_ZERO(&master_set);
  453. max_sd = lSocket;
  454. FD_SET(lSocket, &master_set);
  455. DBG printf("Port %d opened\n", port);
  456. return true;
  457. }
  458. static void cli_send(intptr_t fd, const char *str, unsigned len)
  459. {
  460. send(fd, str, len, 0);
  461. }
  462. void vBasicSocketsCommandInterpreterTask( void *pvParameters )
  463. {
  464. int32_t lBytes;
  465. int new_sd;
  466. int desc_ready, rc;
  467. struct timeval timeout;
  468. uint16_t port;
  469. bool enabled;
  470. bool firstrun = true;
  471. #if HARDWARE_BT6709 || HARDWARE_BT6709_MTS || HARDWARE_BT6710
  472. struct sockaddr_in sa_temp;
  473. socklen_t len;
  474. #endif
  475. #if TCP_DROP_PREV_CONNECTION
  476. static int active_sd = -1;
  477. #endif
  478. static uint8_t cnt_conn = 0;
  479. uint8_t cur_cnt = 0;
  480. FD_ZERO(&master_set);
  481. timeout.tv_sec = 5;
  482. timeout.tv_usec = 0;
  483. ( void ) pvParameters;
  484. pcOutputString = FreeRTOS_CLIGetOutputBuffer();
  485. enabled = sSettings.sTelnet.TelnetEnable;
  486. port = ( uint16_t ) sSettings.sTelnet.port;
  487. while (1) {
  488. /* Check if network settings was changed */
  489. if ((sSettings.sTelnet.port != port) ||
  490. (sSettings.sTelnet.TelnetEnable != enabled) ||
  491. (firstrun))
  492. {
  493. if (!firstrun || sSettings.sTelnet.port != port) {
  494. /* Stop server */
  495. stop_server();
  496. cnt_conn = 0;
  497. }
  498. if (sSettings.sTelnet.TelnetEnable) {
  499. /* (Re)start server */
  500. if (!start_server(sSettings.sTelnet.port)) {
  501. DBG printf("Server start error\n");
  502. firstrun = true;
  503. vTaskDelay(5000);
  504. continue;
  505. }
  506. }
  507. else {
  508. /* Obtain the address of the output buffer. Note there is no mutual
  509. exclusion on this buffer as it is assumed only one command console
  510. interface will be used at any one time. */
  511. firstrun = true;
  512. vTaskDelay(5000);
  513. continue;
  514. }
  515. firstrun = false;
  516. port = sSettings.sTelnet.port;
  517. enabled = sSettings.sTelnet.TelnetEnable;
  518. }
  519. if (!enabled) {
  520. firstrun = true;
  521. vTaskDelay(5000);
  522. continue;
  523. }
  524. memcpy(&read_set, &master_set, sizeof(master_set));
  525. DBG printf("Waiting on select()...\n");
  526. rc = select(max_sd + 1, &read_set, NULL, NULL, &timeout);
  527. DBG printf(" select() returned %d\n", rc);
  528. if (rc < 0) {
  529. DBG printf(" select() failed\n");
  530. }
  531. if (rc == 0) {
  532. DBG printf(" select() timed out.\n");
  533. }
  534. /* One or more descriptors are readable. Need to \
  535. * determine which ones they are. */
  536. desc_ready = rc;
  537. for (int sock = 0; sock <= max_sd && desc_ready > 0; ++sock) {
  538. /*******************************************************/
  539. /* Check to see if this descriptor is ready */
  540. /*******************************************************/
  541. if (FD_ISSET(sock, &read_set)) {
  542. /* A descriptor was found that was readable - one \
  543. * less has to be looked for. This is being done \
  544. * so that we can stop looking at the working set \
  545. * once we have found all of the descriptors that \
  546. * were ready. */
  547. desc_ready -= 1;
  548. /* Check to see if this is the listening socket */
  549. if (sock == lSocket) {
  550. DBG printf(" Listening socket is readable\n");
  551. /* Accept all incoming connections that are */
  552. /* queued up on the listening socket before we */
  553. /* loop back and call select again. */
  554. do {
  555. /* Accept each incoming connection. If */
  556. /* accept fails with EWOULDBLOCK, then we */
  557. /* have accepted all of them. Any other */
  558. /* failure on accept will cause us to end the */
  559. /* server. */
  560. new_sd = accept(lSocket, NULL, NULL);
  561. if (new_sd < 0) {
  562. if (errno != EWOULDBLOCK) {
  563. DBG printf(" accept() failed\n");
  564. }
  565. break;
  566. }
  567. /* Add the new incoming connection to the */
  568. /* master read set */
  569. printf(" New incoming connection - %d\n", new_sd);
  570. FD_SET(new_sd, &master_set);
  571. if (new_sd > max_sd) {
  572. max_sd = new_sd;
  573. }
  574. #if HARDWARE_BT6709 || HARDWARE_BT6709_MTS || HARDWARE_BT6710
  575. lwip_getpeername(new_sd, &sa_temp, &len);
  576. #endif
  577. // recv( new_sd, &auth_tlnt_srvr_param[cur_cnt].buf, 27, 0 );
  578. // Send initial options
  579. bool not_enough_memory = false;
  580. if(cnt_conn < NUMBER_TELNET_CONNECT){
  581. cli_state_t *cli_state = 0;
  582. for(uint8_t k = 0; k < NUMBER_TELNET_CONNECT; k ++){
  583. if(auth_tlnt_srvr_param[k].active_conn == false && (cli_state = alloc_state())){
  584. auth_tlnt_srvr_param[k].active_conn = true;
  585. auth_tlnt_srvr_param[k].num_connect = new_sd;
  586. auth_tlnt_srvr_param[k].state = TELNET_STATE_NORMAL;
  587. cli_state->num_connect = new_sd;
  588. cli_state->send = cli_send;
  589. cli_state->state = STATE_NORMAL;
  590. auth_tlnt_srvr_param[k].cli_state = cli_state;
  591. char c;
  592. while (recv(new_sd, &c, 1, MSG_DONTWAIT) > 0) {
  593. newdata(&auth_tlnt_srvr_param[k], c);
  594. vTaskDelay(10);
  595. }
  596. sendopt(&auth_tlnt_srvr_param[k], TELNET_DO, TELOPT_SUPPRESS_GO_AHEAD);
  597. sendopt(&auth_tlnt_srvr_param[k], TELNET_DO, TELOPT_LINEMODE);
  598. sendopt(&auth_tlnt_srvr_param[k], TELNET_DONT, TELOPT_ECHO);
  599. vTaskDelay(50);
  600. while (recv(new_sd, &c, 1, MSG_DONTWAIT) > 0) {
  601. newdata(&auth_tlnt_srvr_param[k], c);
  602. vTaskDelay(5);
  603. }
  604. send( new_sd, TELNET_CLI_WELCOME_MESSAGE, strlen( TELNET_CLI_WELCOME_MESSAGE ), 0 );
  605. break;
  606. }
  607. }
  608. if (!cli_state) {
  609. not_enough_memory = true;
  610. } else {
  611. cnt_conn++;
  612. }
  613. } else {
  614. not_enough_memory = true;
  615. }
  616. if (not_enough_memory) {
  617. send(new_sd, pcWarningMessage, pcWarningMessageLen, 0);
  618. closesocket(new_sd);
  619. FD_CLR(new_sd, &master_set);
  620. while (FD_ISSET(max_sd, &master_set) == false) {
  621. max_sd -= 1;
  622. }
  623. }
  624. #if TCP_DROP_PREV_CONNECTION
  625. /* Close previous active connection */
  626. if (active_sd != -1 && active_sd != new_sd) {
  627. DBG printf(" Close prev active connection %d\n", active_sd);
  628. close(active_sd);
  629. FD_CLR(active_sd, &master_set);
  630. if (active_sd == max_sd) {
  631. while (FD_ISSET(max_sd, &master_set) == false) {
  632. max_sd -= 1;
  633. }
  634. }
  635. }
  636. /* Mark new connection as active */
  637. active_sd = new_sd;
  638. DBG printf(" New active connection %d\n", active_sd);
  639. #endif
  640. /* Loop back up and accept another incoming */
  641. /* connection */
  642. } while (new_sd != -1);
  643. }
  644. /* This is not the listening socket, therefore an */
  645. /* existing connection must be readable */
  646. else {
  647. DBG printf(" Descriptor %d is readable\n", sock);
  648. for(cur_cnt = 0; cur_cnt < NUMBER_TELNET_CONNECT; cur_cnt ++){
  649. if(auth_tlnt_srvr_param[cur_cnt].num_connect == sock){
  650. break;
  651. }
  652. }
  653. /* Receive data on this connection until the */
  654. /* recv fails with EWOULDBLOCK. If any other */
  655. /* failure occurs, we will close the */
  656. /* connection. */
  657. char c;
  658. if ((lBytes = recv(sock, &c, 1, 0)) > 0) {
  659. newdata(&auth_tlnt_srvr_param[cur_cnt], c);
  660. }
  661. if (lBytes < 0) {
  662. if (errno != EWOULDBLOCK){
  663. DBG printf(" recv() failed\n");
  664. auth_tlnt_srvr_param[cur_cnt].state = TELNET_STATE_CLOSE;
  665. }
  666. }
  667. /* Check to see if the connection has been */
  668. /* closed by the client */
  669. if (lBytes == 0) {
  670. DBG printf(" Connection closed\n");
  671. auth_tlnt_srvr_param[cur_cnt].state = TELNET_STATE_CLOSE;
  672. }
  673. /* If the close_conn flag was turned on, we need */
  674. /* to clean up this active connection. This */
  675. /* clean up process includes removing the */
  676. /* descriptor from the master set and */
  677. /* determining the new maximum descriptor value */
  678. /* based on the bits that are still turned on in */
  679. /* the master set. */
  680. if (auth_tlnt_srvr_param[cur_cnt].state == TELNET_STATE_CLOSE || auth_tlnt_srvr_param[cur_cnt].cli_state->state == STATE_CLOSE) {
  681. deconfigure_telnet_state(auth_tlnt_srvr_param + cur_cnt);
  682. cnt_conn -= 1;
  683. closesocket(sock);
  684. FD_CLR(sock, &master_set);
  685. if (sock == max_sd) {
  686. while (FD_ISSET(max_sd, &master_set) == false) {
  687. max_sd -= 1;
  688. }
  689. }
  690. }
  691. }
  692. }
  693. }
  694. }
  695. }
  696. void telnet_server_init(void) {
  697. xTaskCreate(vBasicSocketsCommandInterpreterTask, ( char * ) "vBasicSocketsCommandInterpreterTask", 8*configMINIMAL_STACK_SIZE , NULL, tskIDLE_PRIORITY + 1, NULL);
  698. }