shell: Add TELNET backend
Add TELNET backed for shell module. The TELNET implementation is based on the telnet_console driver. Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
This commit is contained in:
parent
766edd449d
commit
658a08a4cb
5 changed files with 791 additions and 0 deletions
|
@ -23,6 +23,11 @@ zephyr_sources_ifdef(
|
|||
shell_rtt.c
|
||||
)
|
||||
|
||||
zephyr_sources_ifdef(
|
||||
CONFIG_SHELL_BACKEND_TELNET
|
||||
shell_telnet.c
|
||||
)
|
||||
|
||||
zephyr_sources_ifdef(
|
||||
CONFIG_SHELL_HELP
|
||||
shell_help.c
|
||||
|
|
|
@ -167,6 +167,94 @@ source "subsys/logging/Kconfig.template.log_config"
|
|||
|
||||
endif #SHELL_BACKEND_RTT
|
||||
|
||||
config SHELL_BACKEND_TELNET
|
||||
bool "Enable TELNET backend."
|
||||
depends on NET_TCP
|
||||
depends on NET_IPV4 || NET_IPV6
|
||||
help
|
||||
Enable TELNET backend.
|
||||
|
||||
if SHELL_BACKEND_TELNET
|
||||
|
||||
config SHELL_TELNET_PORT
|
||||
int "Telnet port number"
|
||||
default 23
|
||||
help
|
||||
This option is used to configure on which port telnet is going
|
||||
to be bound.
|
||||
|
||||
config SHELL_TELNET_LINE_BUF_SIZE
|
||||
int "Telnet line buffer size"
|
||||
default 80
|
||||
help
|
||||
This option can be used to modify the size of the buffer storing
|
||||
shell output line, prior to sending it through the network.
|
||||
Of course an output line can be longer than such size, it just
|
||||
means sending it will start as soon as it reaches this size.
|
||||
It really depends on what type of output is expected.
|
||||
A lot of short lines: better reduce this value. On the contrary,
|
||||
raise it.
|
||||
|
||||
config SHELL_TELNET_SEND_TIMEOUT
|
||||
int "Telnet line send timeout"
|
||||
default 100
|
||||
help
|
||||
This option can be used to modify the duration of the timer that kick
|
||||
in when a line buffer is not empty but did not yet meet the line feed.
|
||||
|
||||
config SHELL_TELNET_SUPPORT_COMMAND
|
||||
bool "Add support for telnet commands (IAC) [Experimental]"
|
||||
help
|
||||
Current support is so limited it's not interesting to enable it.
|
||||
However, if proven to be needed at some point, it will be possible
|
||||
to extend such support.
|
||||
|
||||
module = SHELL_TELNET
|
||||
default-timeout = 100
|
||||
source "subsys/shell/Kconfig.template.shell_log_queue_timeout"
|
||||
|
||||
default-size = 10
|
||||
source "subsys/shell/Kconfig.template.shell_log_queue_size"
|
||||
|
||||
choice
|
||||
prompt "Initial log level limit"
|
||||
default SHELL_TELNET_INIT_LOG_LEVEL_DEFAULT
|
||||
|
||||
config SHELL_TELNET_INIT_LOG_LEVEL_DEFAULT
|
||||
bool "System limit (LOG_MAX_LEVEL)"
|
||||
|
||||
config SHELL_TELNET_INIT_LOG_LEVEL_DBG
|
||||
bool "Debug"
|
||||
|
||||
config SHELL_TELNET_INIT_LOG_LEVEL_INF
|
||||
bool "Info"
|
||||
|
||||
config SHELL_TELNET_INIT_LOG_LEVEL_WRN
|
||||
bool "Warning"
|
||||
|
||||
config SHELL_TELNET_INIT_LOG_LEVEL_ERR
|
||||
bool "Error"
|
||||
|
||||
config SHELL_TELNET_INIT_LOG_LEVEL_NONE
|
||||
bool "None"
|
||||
|
||||
endchoice
|
||||
|
||||
config SHELL_TELNET_INIT_LOG_LEVEL
|
||||
int
|
||||
default 0 if SHELL_TELNET_INIT_LOG_LEVEL_NONE
|
||||
default 1 if SHELL_TELNET_INIT_LOG_LEVEL_ERR
|
||||
default 2 if SHELL_TELNET_INIT_LOG_LEVEL_WRN
|
||||
default 3 if SHELL_TELNET_INIT_LOG_LEVEL_INF
|
||||
default 4 if SHELL_TELNET_INIT_LOG_LEVEL_DBG
|
||||
default 5 if SHELL_TELNET_INIT_LOG_LEVEL_DEFAULT
|
||||
|
||||
module = SHELL_TELNET
|
||||
module-str = TELNET shell backend
|
||||
source "subsys/logging/Kconfig.template.log_config"
|
||||
|
||||
endif # SHELL_TELNET_BACKEND
|
||||
|
||||
config SHELL_BACKEND_DUMMY
|
||||
bool "Enable dummy backend."
|
||||
help
|
||||
|
|
498
subsys/shell/shell_telnet.c
Normal file
498
subsys/shell/shell_telnet.c
Normal file
|
@ -0,0 +1,498 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
* Copyright (c) 2019 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <init.h>
|
||||
|
||||
#include <logging/log.h>
|
||||
#include <net/net_context.h>
|
||||
#include <net/net_ip.h>
|
||||
#include <net/net_pkt.h>
|
||||
#include <shell/shell_telnet.h>
|
||||
|
||||
#include "shell_telnet_protocol.h"
|
||||
|
||||
SHELL_TELNET_DEFINE(shell_transport_telnet);
|
||||
SHELL_DEFINE(shell_telnet, "~$ ", &shell_transport_telnet,
|
||||
CONFIG_SHELL_TELNET_LOG_MESSAGE_QUEUE_SIZE,
|
||||
CONFIG_SHELL_TELNET_LOG_MESSAGE_QUEUE_TIMEOUT,
|
||||
SHELL_FLAG_OLF_CRLF);
|
||||
|
||||
LOG_MODULE_REGISTER(shell_telnet, CONFIG_SHELL_TELNET_LOG_LEVEL);
|
||||
|
||||
struct shell_telnet *sh_telnet;
|
||||
|
||||
/* Various definitions mapping the TELNET service configuration options */
|
||||
#define TELNET_PORT CONFIG_SHELL_TELNET_PORT
|
||||
#define TELNET_LINE_SIZE CONFIG_SHELL_TELNET_LINE_BUF_SIZE
|
||||
#define TELNET_TIMEOUT K_MSEC(CONFIG_SHELL_TELNET_SEND_TIMEOUT)
|
||||
|
||||
#define TELNET_MIN_MSG 2
|
||||
|
||||
/* Basic TELNET implmentation. */
|
||||
|
||||
static void telnet_end_client_connection(void)
|
||||
{
|
||||
struct net_pkt *pkt;
|
||||
|
||||
net_context_put(sh_telnet->client_ctx);
|
||||
sh_telnet->client_ctx = NULL;
|
||||
sh_telnet->output_lock = false;
|
||||
|
||||
k_timer_stop(&sh_telnet->send_timer);
|
||||
|
||||
/* Flush the RX FIFO */
|
||||
while ((pkt = k_fifo_get(&sh_telnet->rx_fifo, K_NO_WAIT)) != NULL) {
|
||||
net_pkt_unref(pkt);
|
||||
}
|
||||
}
|
||||
|
||||
static void telnet_sent_cb(struct net_context *client,
|
||||
int status, void *user_data)
|
||||
{
|
||||
if (status < 0) {
|
||||
telnet_end_client_connection();
|
||||
LOG_ERR("Could not send packet %d", status);
|
||||
}
|
||||
}
|
||||
|
||||
static void telnet_command_send_reply(u8_t *msg, u16_t len)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (sh_telnet->client_ctx == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
err = net_context_send(sh_telnet->client_ctx, msg, len, telnet_sent_cb,
|
||||
K_FOREVER, NULL);
|
||||
if (err < 0) {
|
||||
LOG_ERR("Failed to send command %d, shutting down", err);
|
||||
telnet_end_client_connection();
|
||||
}
|
||||
}
|
||||
|
||||
static void telnet_reply_ay_command(void)
|
||||
{
|
||||
static const char alive[] = "Zephyr at your service\r\n";
|
||||
|
||||
telnet_command_send_reply((u8_t *)alive, strlen(alive));
|
||||
}
|
||||
|
||||
static void telnet_reply_do_command(struct telnet_simple_command *cmd)
|
||||
{
|
||||
switch (cmd->opt) {
|
||||
case NVT_OPT_SUPR_GA:
|
||||
cmd->op = NVT_CMD_WILL;
|
||||
break;
|
||||
default:
|
||||
cmd->op = NVT_CMD_WONT;
|
||||
break;
|
||||
}
|
||||
|
||||
telnet_command_send_reply((u8_t *)cmd,
|
||||
sizeof(struct telnet_simple_command));
|
||||
}
|
||||
|
||||
static void telnet_reply_command(struct telnet_simple_command *cmd)
|
||||
{
|
||||
if (!cmd->iac) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (cmd->op) {
|
||||
case NVT_CMD_AO:
|
||||
/* OK, no output then */
|
||||
sh_telnet->output_lock = true;
|
||||
sh_telnet->line_out.len = 0;
|
||||
k_timer_stop(&sh_telnet->send_timer);
|
||||
break;
|
||||
case NVT_CMD_AYT:
|
||||
telnet_reply_ay_command();
|
||||
break;
|
||||
case NVT_CMD_DO:
|
||||
telnet_reply_do_command(cmd);
|
||||
break;
|
||||
default:
|
||||
LOG_DBG("Operation %u not handled", cmd->op);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int telnet_send(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (sh_telnet->line_out.len == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sh_telnet->client_ctx == NULL) {
|
||||
return -ENOTCONN;
|
||||
}
|
||||
|
||||
err = net_context_send(sh_telnet->client_ctx, sh_telnet->line_out.buf,
|
||||
sh_telnet->line_out.len, telnet_sent_cb,
|
||||
K_FOREVER, NULL);
|
||||
if (err < 0) {
|
||||
LOG_ERR("Failed to send %d, shutting down", err);
|
||||
telnet_end_client_connection();
|
||||
return err;
|
||||
}
|
||||
|
||||
/* We reinitialize the line buffer */
|
||||
sh_telnet->line_out.len = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void telnet_send_prematurely(struct k_timer *timer)
|
||||
{
|
||||
(void)telnet_send();
|
||||
}
|
||||
|
||||
static inline bool telnet_handle_command(struct net_pkt *pkt)
|
||||
{
|
||||
/* Commands are two or three bytes. */
|
||||
NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(cmd_access, u16_t);
|
||||
struct telnet_simple_command *cmd;
|
||||
|
||||
cmd = (struct telnet_simple_command *)net_pkt_get_data(pkt,
|
||||
&cmd_access);
|
||||
if (!cmd || cmd->iac != NVT_CMD_IAC) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_SHELL_TELNET_SUPPORT_COMMAND)) {
|
||||
LOG_DBG("Got a command %u/%u/%u", cmd->iac, cmd->op, cmd->opt);
|
||||
telnet_reply_command(cmd);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void telnet_recv(struct net_context *client,
|
||||
struct net_pkt *pkt,
|
||||
union net_ip_header *ip_hdr,
|
||||
union net_proto_header *proto_hdr,
|
||||
int status,
|
||||
void *user_data)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
if (!pkt || status) {
|
||||
telnet_end_client_connection();
|
||||
|
||||
LOG_DBG("Telnet client dropped (AF_INET%s) status %d",
|
||||
net_context_get_family(client) == AF_INET ?
|
||||
"" : "6", status);
|
||||
return;
|
||||
}
|
||||
|
||||
len = net_pkt_remaining_data(pkt);
|
||||
if (len < TELNET_MIN_MSG) {
|
||||
LOG_DBG("Packet smaller than minimum length");
|
||||
goto unref;
|
||||
}
|
||||
|
||||
if (telnet_handle_command(pkt)) {
|
||||
LOG_DBG("Handled command");
|
||||
goto unref;
|
||||
}
|
||||
|
||||
/* Fifo add */
|
||||
k_fifo_put(&sh_telnet->rx_fifo, pkt);
|
||||
|
||||
sh_telnet->shell_handler(SHELL_TRANSPORT_EVT_RX_RDY,
|
||||
sh_telnet->shell_context);
|
||||
|
||||
return;
|
||||
|
||||
unref:
|
||||
net_pkt_unref(pkt);
|
||||
}
|
||||
|
||||
static void telnet_accept(struct net_context *client,
|
||||
struct sockaddr *addr,
|
||||
socklen_t addrlen,
|
||||
int error,
|
||||
void *user_data)
|
||||
{
|
||||
if (error) {
|
||||
LOG_ERR("Error %d", error);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (sh_telnet->client_ctx) {
|
||||
LOG_INF("A telnet client is already in.");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (net_context_recv(client, telnet_recv, 0, NULL)) {
|
||||
LOG_ERR("Unable to setup reception (family %u)",
|
||||
net_context_get_family(client));
|
||||
goto error;
|
||||
}
|
||||
|
||||
LOG_DBG("Telnet client connected (family AF_INET%s)",
|
||||
net_context_get_family(client) == AF_INET ? "" : "6");
|
||||
|
||||
sh_telnet->client_ctx = client;
|
||||
|
||||
return;
|
||||
error:
|
||||
net_context_put(client);
|
||||
}
|
||||
|
||||
static void telnet_setup_server(struct net_context **ctx, sa_family_t family,
|
||||
struct sockaddr *addr, socklen_t addrlen)
|
||||
{
|
||||
if (net_context_get(family, SOCK_STREAM, IPPROTO_TCP, ctx)) {
|
||||
LOG_ERR("No context available");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (net_context_bind(*ctx, addr, addrlen)) {
|
||||
LOG_ERR("Cannot bind on family AF_INET%s",
|
||||
family == AF_INET ? "" : "6");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (net_context_listen(*ctx, 0)) {
|
||||
LOG_ERR("Cannot listen on");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (net_context_accept(*ctx, telnet_accept, K_NO_WAIT, NULL)) {
|
||||
LOG_ERR("Cannot accept");
|
||||
goto error;
|
||||
}
|
||||
|
||||
LOG_DBG("Telnet console enabled on AF_INET%s",
|
||||
family == AF_INET ? "" : "6");
|
||||
|
||||
return;
|
||||
error:
|
||||
LOG_ERR("Unable to start telnet on AF_INET%s",
|
||||
family == AF_INET ? "" : "6");
|
||||
|
||||
if (*ctx) {
|
||||
net_context_put(*ctx);
|
||||
*ctx = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int telnet_init(void)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_NET_IPV4)) {
|
||||
struct sockaddr_in any_addr4 = {
|
||||
.sin_family = AF_INET,
|
||||
.sin_port = htons(TELNET_PORT),
|
||||
.sin_addr = INADDR_ANY_INIT
|
||||
};
|
||||
static struct net_context *ctx4;
|
||||
|
||||
telnet_setup_server(&ctx4, AF_INET,
|
||||
(struct sockaddr *)&any_addr4,
|
||||
sizeof(any_addr4));
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_IPV6)) {
|
||||
struct sockaddr_in6 any_addr6 = {
|
||||
.sin6_family = AF_INET6,
|
||||
.sin6_port = htons(TELNET_PORT),
|
||||
.sin6_addr = IN6ADDR_ANY_INIT
|
||||
};
|
||||
static struct net_context *ctx6;
|
||||
|
||||
telnet_setup_server(&ctx6, AF_INET6,
|
||||
(struct sockaddr *)&any_addr6,
|
||||
sizeof(any_addr6));
|
||||
}
|
||||
|
||||
LOG_INF("Telnet shell backend initialized");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Shell API */
|
||||
|
||||
static int init(const struct shell_transport *transport,
|
||||
const void *config,
|
||||
shell_transport_handler_t evt_handler,
|
||||
void *context)
|
||||
{
|
||||
int err;
|
||||
|
||||
sh_telnet = (struct shell_telnet *)transport->ctx;
|
||||
|
||||
err = telnet_init();
|
||||
if (err != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
memset(sh_telnet, 0, sizeof(struct shell_telnet));
|
||||
|
||||
sh_telnet->shell_handler = evt_handler;
|
||||
sh_telnet->shell_context = context;
|
||||
|
||||
k_fifo_init(&sh_telnet->rx_fifo);
|
||||
k_timer_init(&sh_telnet->send_timer, telnet_send_prematurely, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uninit(const struct shell_transport *transport)
|
||||
{
|
||||
if (sh_telnet == NULL) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int enable(const struct shell_transport *transport, bool blocking)
|
||||
{
|
||||
if (sh_telnet == NULL) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int write(const struct shell_transport *transport,
|
||||
const void *data, size_t length, size_t *cnt)
|
||||
{
|
||||
struct shell_telnet_line_buf *lb;
|
||||
size_t copy_len;
|
||||
int err;
|
||||
u32_t timeout;
|
||||
|
||||
if (sh_telnet == NULL) {
|
||||
*cnt = 0;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (sh_telnet->client_ctx == NULL || sh_telnet->output_lock) {
|
||||
*cnt = length;
|
||||
return 0;
|
||||
}
|
||||
|
||||
*cnt = 0;
|
||||
lb = &sh_telnet->line_out;
|
||||
|
||||
/* Stop the transmission timer, so it does not interrupt the operation.
|
||||
*/
|
||||
timeout = k_timer_remaining_get(&sh_telnet->send_timer);
|
||||
k_timer_stop(&sh_telnet->send_timer);
|
||||
|
||||
do {
|
||||
if (lb->len + length - *cnt > TELNET_LINE_SIZE) {
|
||||
copy_len = TELNET_LINE_SIZE - lb->len;
|
||||
} else {
|
||||
copy_len = length - *cnt;
|
||||
}
|
||||
|
||||
memcpy(lb->buf + lb->len, (u8_t *)data + *cnt, copy_len);
|
||||
lb->len += copy_len;
|
||||
|
||||
/* Send the data immediately if the buffer is full or line feed
|
||||
* is recognized.
|
||||
*/
|
||||
if (lb->buf[lb->len - 1] == '\n' ||
|
||||
lb->len == TELNET_LINE_SIZE) {
|
||||
err = telnet_send();
|
||||
if (err != 0) {
|
||||
*cnt = length;
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
*cnt += copy_len;
|
||||
} while (*cnt < length);
|
||||
|
||||
if (lb->len > 0) {
|
||||
/* Check if the timer was already running, initialize otherwise.
|
||||
*/
|
||||
timeout = (timeout == 0) ? TELNET_TIMEOUT : timeout;
|
||||
|
||||
k_timer_start(&sh_telnet->send_timer, timeout, 0);
|
||||
}
|
||||
|
||||
sh_telnet->shell_handler(SHELL_TRANSPORT_EVT_TX_RDY,
|
||||
sh_telnet->shell_context);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read(const struct shell_transport *transport,
|
||||
void *data, size_t length, size_t *cnt)
|
||||
{
|
||||
struct net_pkt *pkt;
|
||||
size_t read_len;
|
||||
bool flush = true;
|
||||
|
||||
if (sh_telnet == NULL) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (sh_telnet->client_ctx == NULL) {
|
||||
goto no_data;
|
||||
}
|
||||
|
||||
pkt = k_fifo_peek_head(&sh_telnet->rx_fifo);
|
||||
if (pkt == NULL) {
|
||||
goto no_data;
|
||||
}
|
||||
|
||||
read_len = net_pkt_remaining_data(pkt);
|
||||
if (read_len > length) {
|
||||
read_len = length;
|
||||
flush = false;
|
||||
}
|
||||
|
||||
*cnt = read_len;
|
||||
net_pkt_read(pkt, data, read_len);
|
||||
|
||||
if (flush) {
|
||||
(void)k_fifo_get(&sh_telnet->rx_fifo, K_NO_WAIT);
|
||||
net_pkt_unref(pkt);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
no_data:
|
||||
*cnt = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct shell_transport_api shell_telnet_transport_api = {
|
||||
.init = init,
|
||||
.uninit = uninit,
|
||||
.enable = enable,
|
||||
.write = write,
|
||||
.read = read
|
||||
};
|
||||
|
||||
static int enable_shell_telnet(struct device *arg)
|
||||
{
|
||||
ARG_UNUSED(arg);
|
||||
|
||||
bool log_backend = CONFIG_SHELL_TELNET_INIT_LOG_LEVEL > 0;
|
||||
u32_t level = (CONFIG_SHELL_TELNET_INIT_LOG_LEVEL > LOG_LEVEL_DBG) ?
|
||||
CONFIG_LOG_MAX_LEVEL : CONFIG_SHELL_TELNET_INIT_LOG_LEVEL;
|
||||
|
||||
shell_init(&shell_telnet, NULL, true, log_backend, level);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SYS_INIT(enable_shell_telnet, APPLICATION, 0);
|
||||
|
||||
const struct shell *shell_backend_telnet_get_ptr(void)
|
||||
{
|
||||
return &shell_telnet;
|
||||
}
|
125
subsys/shell/shell_telnet_protocol.h
Normal file
125
subsys/shell/shell_telnet_protocol.h
Normal file
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Telnet console protocol specific defines
|
||||
*
|
||||
*
|
||||
* This defines the Telnet codes, all prefixed as NVT_
|
||||
* (NVT: Network Virtual Terminal, see rfc854)
|
||||
*/
|
||||
|
||||
#ifndef SHELL_TELNET_PROTOCOL_H__
|
||||
#define SHELL_TELNET_PROTOCOL_H__
|
||||
|
||||
/** Printer/Keyboard codes */
|
||||
|
||||
/* Mandatory ones */
|
||||
#define NVT_NUL 0
|
||||
#define NVT_LF 10
|
||||
#define NVT_CR 13
|
||||
|
||||
/* Optional ones */
|
||||
#define NVT_BEL 7
|
||||
#define NVT_BS 8
|
||||
#define NVT_HT 9
|
||||
#define NVT_VT 11
|
||||
#define NVT_FF 12
|
||||
|
||||
/* Telnet commands */
|
||||
#define NVT_CMD_SE 240
|
||||
#define NVT_CMD_NOP 241
|
||||
#define NVT_CMD_DM 242
|
||||
#define NVT_CMD_BRK 243
|
||||
#define NVT_CMD_IP 244
|
||||
#define NVT_CMD_AO 245
|
||||
#define NVT_CMD_AYT 246
|
||||
#define NVT_CMD_EC 247
|
||||
#define NVT_CMD_EL 248
|
||||
#define NVT_CMD_GA 249
|
||||
#define NVT_CMD_SB 250
|
||||
#define NVT_CMD_WILL 251
|
||||
#define NVT_CMD_WONT 252
|
||||
#define NVT_CMD_DO 253
|
||||
#define NVT_CMD_DONT 254
|
||||
#define NVT_CMD_IAC 255
|
||||
|
||||
/* Telnet options */
|
||||
#define NVT_OPT_TX_BIN 0
|
||||
#define NVT_OPT_ECHO 1
|
||||
#define NVT_OPT_RECONNECT 2
|
||||
#define NVT_OPT_SUPR_GA 3
|
||||
#define NVT_OPT_MSG_SZ_NEG 4
|
||||
#define NVT_OPT_STATUS 5
|
||||
#define NVT_OPT_TIMING_MARK 6
|
||||
#define NVT_OPT_REMOTE_CTRL_TRANS_ECHO 7
|
||||
#define NVT_OPT_OUT_LINE_WIDTH 8
|
||||
#define NVT_OPT_OUT_PAGE_SZ 9
|
||||
#define NVT_OPT_NEG_CR 10
|
||||
#define NVT_OPT_NEG_HT 11
|
||||
#define NVT_OPT_NAOHTD 12
|
||||
#define NVT_OPT_NEG_OUT_FF 13
|
||||
#define NVT_OPT_NEG_VT 14
|
||||
#define NVT_OPT_NEG_OUT_VT 15
|
||||
#define NVT_OPT_NET_OUT_LF 16
|
||||
#define NVT_OPT_EXT_ASCII 17
|
||||
#define NVT_OPT_LOGOUT 18
|
||||
#define NVT_OPT_BYTE_MACRO 19
|
||||
#define NVT_OPT_DATA_ENTRY 20
|
||||
#define NVT_OPT_SUPDUP 21
|
||||
#define NVT_OPT_SUPDUP_OUT 22
|
||||
#define NVT_OPT_SEND_LOC 23
|
||||
#define NVT_OPT_TERM_TYPE 24
|
||||
#define NVT_OPT_EOR 25
|
||||
#define NVT_OPT_TACACS_UID 26
|
||||
#define NVT_OPT_OUT_MARK 27
|
||||
#define NVT_OPT_TTYLOC 28
|
||||
#define NVT_OPT_3270 29
|
||||
#define NVT_OPT_X_3_PAD 30
|
||||
#define NVT_OPT_NAWS 31
|
||||
#define NVT_OPT_TERM_SPEED 32
|
||||
#define NVT_OPT_REMOTE_FC 33
|
||||
#define NVT_OPT_LINEMODE 34
|
||||
#define NVT_OPT_X_LOC 35
|
||||
#define NVT_OPT_ENV 36
|
||||
#define NVT_OPT_AUTH 37
|
||||
#define NVT_OPT_ENCRYPT_OPT 38
|
||||
#define NVT_OPT_NEW_ENV 39
|
||||
#define NVT_OPT_TN3270E 40
|
||||
#define NVT_OPT_XAUTH 41
|
||||
#define NVT_OPT_CHARSET 42
|
||||
#define NVT_OPT_RSP 43
|
||||
#define NVT_OPT_COM_PORT_CTRL 44
|
||||
#define NVT_OPT_SUPR_LOCAL_ECHO 45
|
||||
#define NVT_OPT_START_TLS 46
|
||||
#define NVT_OPT_KERMIT 47
|
||||
#define NVT_OPT_SEND_URL 48
|
||||
#define NVT_OPT_FORWARD_X 49
|
||||
#define NVT_OPT_PRAGMA_LOGON 138
|
||||
#define NVT_OPT_SSPI_LOGON 139
|
||||
#define NVT_OPT_PRAGMA_HB 140
|
||||
#define NVT_OPT_EXT_OPT_LIST 255
|
||||
|
||||
/** Describes a telnet command */
|
||||
struct telnet_simple_command {
|
||||
/** Mandatory IAC code */
|
||||
u8_t iac;
|
||||
/** Type of operation (see Telnet commands above) */
|
||||
u8_t op;
|
||||
/** Option code */
|
||||
u8_t opt;
|
||||
};
|
||||
|
||||
static inline void telnet_command_cpy(struct telnet_simple_command *dst,
|
||||
struct telnet_simple_command *src)
|
||||
{
|
||||
dst->iac = src->iac;
|
||||
dst->op = src->op;
|
||||
dst->opt = src->opt;
|
||||
}
|
||||
|
||||
#endif /* SHELL_TELNET_PROTOCOL_H__ */
|
Loading…
Add table
Add a link
Reference in a new issue