/************************************************************************ * NAME: fnet_telnet_release * * DESCRIPTION: Telnet server release. ************************************************************************/ void fnet_telnet_release(fnet_telnet_desc_t desc) { struct fnet_telnet_if *telnet_if = (struct fnet_telnet_if *) desc; int i; if(telnet_if && (telnet_if->enabled == FNET_TRUE)) { for(i=0; i<FNET_CFG_TELNET_SESSION_MAX; i++) { struct fnet_telnet_session_if *session = &telnet_if->session[i]; closesocket(session->socket_foreign); session->socket_foreign = SOCKET_INVALID; if(session->shell_descriptor) { fnet_shell_release(session->shell_descriptor); session->shell_descriptor = 0; } session->state = FNET_TELNET_STATE_DISABLED; } closesocket(telnet_if->socket_listen); fnet_poll_service_unregister(telnet_if->service_descriptor); /* Delete service.*/ telnet_if->enabled = FNET_FALSE; } }
static void fapp_release(fnet_shell_desc_t desc) { #if FAPP_CFG_LLMNR_CMD && FNET_CFG_LLMNR /* Release LLMNR server. */ fapp_llmnr_release(); #endif #if FAPP_CFG_DHCP_CMD && FNET_CFG_DHCP && FNET_CFG_IP4 fapp_dhcp_release(); /* Release DHCP client. */ #endif #if FAPP_CFG_TELNET_CMD && FNET_CFG_TELNET /* Release TELNET server. */ fapp_telnet_release(); #endif #if FAPP_CFG_HTTP_CMD && FNET_CFG_HTTP /* Release HTTP server. */ fapp_http_release(); #endif #if FAPP_CFG_TFTPS_CMD /* Release TFTP server. */ fapp_tftps_release(); #endif #if (FAPP_CFG_EXP_CMD && FNET_CFG_FS) || (FAPP_CFG_HTTP_CMD && FNET_CFG_HTTP) fapp_fs_unmount(); /* Unmount and release FS. */ #endif fnet_shell_release(desc); /* Release shell. */ fnet_release(); /* Release the FNET stack.*/ }
/************************************************************************ * NAME: fnet_telnet_state_machine * * DESCRIPTION: Telnet server state machine. ************************************************************************/ static void fnet_telnet_state_machine( void *telnet_if_p ) { struct sockaddr foreign_addr; int res; struct fnet_telnet_if *telnet = (struct fnet_telnet_if *)telnet_if_p; char rx_data[1]; int len; int i; struct fnet_telnet_session_if *session; for(i=0; i<FNET_CFG_TELNET_SESSION_MAX; i++) { session = &telnet->session[i]; telnet->session_active = session; do { switch(session->state) { /*---- LISTENING ------------------------------------------------*/ case FNET_TELNET_STATE_LISTENING: len = sizeof(foreign_addr); session->socket_foreign = accept(telnet->socket_listen, (struct sockaddr *) &foreign_addr, &len); if(session->socket_foreign != SOCKET_INVALID) { #if FNET_CFG_DEBUG_TELNET { char ip_str[FNET_IP_ADDR_STR_SIZE]; fnet_inet_ntop(foreign_addr.sa_family, foreign_addr.sa_data, ip_str, sizeof(ip_str)); FNET_DEBUG_TELNET("\nTELNET: New connection: %s; Port: %d.", ip_str, fnet_ntohs(foreign_addr.sa_port)); } #endif /* Init Shell. */ session->shell_descriptor = fnet_shell_init(&session->shell_params); if(session->shell_descriptor == FNET_ERR) { session->shell_descriptor = 0; FNET_DEBUG_TELNET("TELNET: Shell Service registration error."); session->state = FNET_TELNET_STATE_CLOSING; /*=> CLOSING */ } else { listen(telnet->socket_listen, --telnet->backlog); /* Ignor other connections.*/ /* Reset TX timeout. */ session->state = FNET_TELNET_STATE_RECEIVING; /* => WAITING data */ } } break; /*---- NORMAL -----------------------------------------------*/ case FNET_TELNET_STATE_RECEIVING: if(rx_buffer_free_space(session)>0) { res = recv(session->socket_foreign, rx_data, 1, 0); if(res == 1) { if(rx_data[0] == FNET_TELNET_CMD_IAC ) { session->state = FNET_TELNET_STATE_IAC; /*=> Handle IAC */ } else { rx_buffer_write (session, rx_data[0]); } } else if (res == SOCKET_ERROR) { session->state = FNET_TELNET_STATE_CLOSING; /*=> CLOSING */ } } break; /*---- IAC -----------------------------------------------*/ case FNET_TELNET_STATE_IAC: FNET_DEBUG_TELNET("TELNET: STATE_IAC"); if((res = recv(session->socket_foreign, rx_data, 1, 0) )!= SOCKET_ERROR) { if(res) { switch(rx_data[0]) { case FNET_TELNET_CMD_WILL: session->state = FNET_TELNET_STATE_DONT; break; case FNET_TELNET_CMD_DO: session->state = FNET_TELNET_STATE_WONT; break; case FNET_TELNET_CMD_WONT: case FNET_TELNET_CMD_DONT: session->state = FNET_TELNET_STATE_SKIP ; break; case FNET_TELNET_CMD_IAC: /* the IAC need be doubled to be sent as data, and the other 255 codes may be passed transparently. */ rx_buffer_write (session, rx_data[0]); default: session->state = FNET_TELNET_STATE_RECEIVING; /*=> Ignore commands */ } } } else { session->state = FNET_TELNET_STATE_CLOSING; /*=> CLOSING */ } break; /*---- DONT & WONT -----------------------------------------------*/ case FNET_TELNET_STATE_DONT: case FNET_TELNET_STATE_WONT: { char command; if(session->state == FNET_TELNET_STATE_DONT) { FNET_DEBUG_TELNET("TELNET: STATE_DONT"); command = FNET_TELNET_CMD_DONT; } else { FNET_DEBUG_TELNET("TELNET: STATE_WONT"); command = FNET_TELNET_CMD_WONT; } if(tx_buffer_free_space(session) >= 3) { res = recv(session->socket_foreign, rx_data, 1, 0); if(res == 1) { /* Send command. */ fnet_telnet_send_cmd(session, command, rx_data[0]); session->state = FNET_TELNET_STATE_RECEIVING; } else if (res == SOCKET_ERROR) { session->state = FNET_TELNET_STATE_CLOSING; /*=> CLOSING */ } } } break; /*---- SKIP -----------------------------------------------*/ case FNET_TELNET_STATE_SKIP: FNET_DEBUG_TELNET("TELNET: STATE_SKIP"); res = recv(session->socket_foreign, rx_data, 1, 0); if(res == 1) { session->state = FNET_TELNET_STATE_RECEIVING; } else if (res == SOCKET_ERROR) { session->state = FNET_TELNET_STATE_CLOSING; /*=> CLOSING */ } break; /*---- CLOSING --------------------------------------------*/ case FNET_TELNET_STATE_CLOSING: FNET_DEBUG_TELNET("TELNET: STATE_CLOSING"); if(session->shell_descriptor) { fnet_shell_release(session->shell_descriptor); session->shell_descriptor = 0; } session->rx_buffer_head = session->rx_buffer; session->rx_buffer_tail = session->rx_buffer; closesocket(session->socket_foreign); session->socket_foreign = SOCKET_INVALID; listen(telnet->socket_listen, ++telnet->backlog); /* Allow connection.*/ session->state = FNET_TELNET_STATE_LISTENING; /*=> LISTENING */ break; default: break; } } while(session->state == FNET_TELNET_STATE_CLOSING); } }