📄 telnet.c
字号:
#include <stdlib.h>#include <string.h>#include "telnet.h"static struct telnet_cmd *find_cmd(struct telnet_cmd *array, unsigned char option){ int i; for (i=0; array[i].option != 255; i++) { if (array[i].option == option) return &array[i]; } return NULL;}voidtelnet_cmd_send(telnet_data_t *td, unsigned char *cmd, int len){ int pos = td->out_telnet_cmd_size; int left = MAX_TELNET_CMD_XMIT_BUF - pos; if (len > left) { /* Out of data, abort the connection. This really shouldn't happen.*/ td->error = 1; return; } memcpy(td->out_telnet_cmd+pos, cmd, len); td->out_telnet_cmd_size += len; td->output_ready(td->cb_data);}static voidsend_i(telnet_data_t *td, unsigned char type, unsigned char option){ unsigned char i[3]; i[0] = TN_IAC; i[1] = type; i[2] = option; telnet_cmd_send(td, i, 3);}static voidhandle_telnet_cmd(telnet_data_t *td){ int size = td->telnet_cmd_pos; unsigned char *cmd_str = td->telnet_cmd; struct telnet_cmd *cmd; int rv; if (size < 2) return; if (cmd_str[1] < 250) { /* A one-byte command. */ td->cmd_handler(td->cb_data, cmd_str[1]); } else if (cmd_str[1] == 250) { /* Option */ cmd = find_cmd(td->cmds, cmd_str[2]); if (!cmd) return; cmd->option_handler(td->cb_data, cmd_str+2, size-2); } else if (cmd_str[1] == 251) { /* WILL */ unsigned char option = cmd_str[2]; cmd = find_cmd(td->cmds, option); if (!cmd || !cmd->sent_do) { if ((!cmd) || (!cmd->i_will)) send_i(td, TN_DONT, option); else { rv = 1; if (cmd->will_handler) rv = cmd->will_handler(td->cb_data); if (rv) send_i(td, TN_DO, option); else send_i(td, TN_DONT, option); } } else if (cmd) cmd->sent_do = 0; if (cmd) { cmd->rem_will = 1; } } else if (cmd_str[1] == 252) { /* WONT */ unsigned char option = cmd_str[2]; cmd = find_cmd(td->cmds, option); if (!cmd || !cmd->sent_do) send_i(td, TN_DONT, option); else if (cmd) cmd->sent_do = 0; if (cmd) cmd->rem_will = 0; } else if (cmd_str[1] == 253) { /* DO */ unsigned char option = cmd_str[2]; cmd = find_cmd(td->cmds, option); if (!cmd || !cmd->sent_will) { if ((!cmd) || (! cmd->i_do)) send_i(td, TN_WONT, option); else send_i(td, TN_WILL, option); } else if (cmd) cmd->sent_will = 0; if (cmd) cmd->rem_do = 1; } else if (cmd_str[1] == 254) { /* DONT */ unsigned char option = cmd_str[2]; cmd = find_cmd(td->cmds, option); if (!cmd || !cmd->sent_will) send_i(td, TN_WONT, option); else if (cmd) cmd->sent_will = 0; if (cmd) cmd->rem_do = 0; }}voidtelnet_send_option(telnet_data_t *td, unsigned char *option, int len){ int pos = td->out_telnet_cmd_size; int left = MAX_TELNET_CMD_XMIT_BUF - pos; int real_len; int i; /* Make sure to account for any duplicate 255s. */ for (real_len=0, i=0; i<len; i++, real_len++) { if (option[i] == 255) real_len++; } real_len += 4; /* Add the initial and end markers. */ if (real_len > left) { /* Out of data, abort the connection. This really shouldn't happen.*/ td->error = 1; return; } i = 0; td->out_telnet_cmd[pos++] = 255; td->out_telnet_cmd[pos++] = 250; for (i=0; i<len; i++, pos++) { td->out_telnet_cmd[pos] = option[i]; if (option[i] == 255) td->out_telnet_cmd[++pos] = option[i]; } td->out_telnet_cmd[pos++] = 255; td->out_telnet_cmd[pos++] = 240; td->out_telnet_cmd_size = pos; td->output_ready(td->cb_data);}static intdelete_char(char *data, int pos, int len){ int i; for (i=pos; i<len-1; i++) { data[i] = data[i+1]; } return len-1;}intprocess_telnet_data(unsigned char *data, int len, telnet_data_t *td){ int i; /* If it's a telnet port, get the commands out of the stream. */ for (i=0; i<len;) { if (td->telnet_cmd_pos != 0) { unsigned char tn_byte; tn_byte = data[i]; if ((td->telnet_cmd_pos == 1) && (tn_byte == 255)) { /* Two IACs in a row causes one IAC to be sent, so just let this one go through. */ i++; continue; } len = delete_char(data, i, len); if (td->telnet_cmd_pos == 1) { /* These are two byte commands, so we have everything we need to handle the command. */ td->telnet_cmd[td->telnet_cmd_pos] = tn_byte; td->telnet_cmd_pos++; if (tn_byte < 250) { handle_telnet_cmd(td); td->telnet_cmd_pos = 0; } } else if (td->telnet_cmd_pos == 2) { td->telnet_cmd[td->telnet_cmd_pos] = tn_byte; td->telnet_cmd_pos++; if (td->telnet_cmd[1] != 250) { /* It's a will/won't/do/don't */ handle_telnet_cmd(td); td->telnet_cmd_pos = 0; } } else { /* It's in a suboption, look for the end and IACs. */ if (td->telnet_cmd[td->telnet_cmd_pos-1] == 255) { if (tn_byte == 240) { /* Remove the IAC 240 from the end. */ td->telnet_cmd_pos--; handle_telnet_cmd(td); td->telnet_cmd_pos = 0; } else if (tn_byte == 255) { /* Don't do anything, a double 255 means we leave on 255 in. */ } else { /* If we have an IAC and an invalid character, delete them both */ td->telnet_cmd_pos--; } } else { if (td->telnet_cmd_pos > MAX_TELNET_CMD_SIZE) /* Always store the last character received in the final postition (the array is one bigger than the max size) so we can detect the end of the suboption. */ td->telnet_cmd_pos = MAX_TELNET_CMD_SIZE; td->telnet_cmd[td->telnet_cmd_pos] = tn_byte; td->telnet_cmd_pos++; } } } else if (data[i] == 255) { td->telnet_cmd[td->telnet_cmd_pos] = 255; len = delete_char(data, i, len); td->telnet_cmd_pos++; } else { i++; } } return len;}voidtelnet_init(telnet_data_t *td, void *cb_data, void (*output_ready)(void *cb_data), void (*cmd_handler)(void *cb_data, unsigned char cmd), struct telnet_cmd *cmds, unsigned char *init_seq, int init_seq_len){ td->telnet_cmd_pos = 0; td->out_telnet_cmd_size = 0; td->error = 0; td->cb_data = cb_data; td->output_ready = output_ready; td->cmd_handler = cmd_handler; td->cmds = cmds; memcpy(td->out_telnet_cmd, init_seq, init_seq_len); td->out_telnet_cmd_size = init_seq_len; td->output_ready(cb_data);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -