1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
|
/*
* gensio - A library for abstracting stream I/O
* Copyright (C) 2018 Corey Minyard <minyard@acm.org>
*
* SPDX-License-Identifier: LGPL-2.1-only
*/
#ifndef _SER2NET_TELNET_H
#define _SER2NET_TELNET_H
#include <gensio/gensio_buffer.h>
/* Telnet commands */
#define TN_SE 240
#define TN_DATA_MARK 242
#define TN_BREAK 243
#define TN_SB 250
#define TN_WILL 251
#define TN_WONT 252
#define TN_DO 253
#define TN_DONT 254
#define TN_IAC 255
#define TN_OPT_BINARY_TRANSMISSION 0
#define TN_OPT_ECHO 1
#define TN_OPT_SUPPRESS_GO_AHEAD 3
#define TN_OPT_COM_PORT 44 /* rfc2217 */
#define TN_OPT_NAWS 31 /* rfc1073 - Window size */
typedef struct telnet_data_s telnet_data_t;
#define TELNET_CMD_END_OPTION 255
struct telnet_cmd
{
unsigned char option;
unsigned int i_will : 1;
unsigned int i_do : 1;
unsigned int sent_will : 1;
unsigned int sent_do : 1;
unsigned int rem_will : 1;
unsigned int rem_do : 1;
/* If this is non-null, this will be called on any options
received by the code */
void (*option_handler)(void *cb_data, unsigned char *option, int len);
/* If this is non-null, this will be called if a will/wont/do/dont
command is sent by the remote end. For will and do commands,
if this returns 1, the option will be allowed (a DO/WILL is
returned). If it returns 0, a DONT/WONT is returned. The
return value is ignored for wont and dont commands. */
int (*will_do_handler)(void *cb_data, unsigned char cmd);
};
#define MAX_TELNET_CMD_SIZE 31
#define MAX_TELNET_CMD_XMIT_BUF 256
struct telnet_data_s
{
/* Incoming telnet commands. This is "+1" because the last byte
always holds the previous byte received, even on an overflow, so
that the end of the options can be correctly detected. */
unsigned char telnet_cmd[MAX_TELNET_CMD_SIZE + 1];
int telnet_cmd_pos; /* Current position in the
telnet_cmd buffer. If zero,
no telnet command is in
progress. */
int suboption_iac; /* If true, we are in a
suboption and processing an
IAC. */
/* Outgoing telnet commands. The output routines should look at
this *first* to see if they should transmit some data from
here. */
struct gensio_buffer out_telnet_cmd;
unsigned char out_telnet_cmdbuf[MAX_TELNET_CMD_XMIT_BUF];
/* Marks that an output error occurred. The only error that can
occur is "out of space", meaning that the code needed to do
output wut out_telnet_cmd was full. */
int error;
void *cb_data;
/* Call when data is added to out_telnet_cmd. */
void (*output_ready)(void *cb_data);
/* Called for all one-byte telnet commands. */
void (*cmd_handler)(void *cb_data, unsigned char cmd);
/* An array of commands, the last option must be set to 255 to
mark the end of the array. */
struct telnet_cmd *cmds;
};
/* Send a telnet command. This will set td->error to true if an
output error occurs (out of space). */
void telnet_cmd_send(telnet_data_t *td, const unsigned char *cmd,
unsigned int len);
/* Received some data from the TCP port representing telnet, process
it. The leftover length is returned by this function, and the
telnet data will be removed from data. This will set td->error to
true if an output error occurs (out of space).*/
unsigned int process_telnet_data(unsigned char *outdata, unsigned int outlen,
unsigned char **indata,
unsigned int *inlen,
telnet_data_t *td);
/* Double all the IACs in the transmitted data. If outlen is more
than twice the size of inlen, this will process all the data. The
number of bytes put into outdata is returned. inlen will be
updated to the number of bytes not processed in indata and indata
will be updated to point to the location after the last processed
character. */
unsigned int process_telnet_xmit(unsigned char *outdata, unsigned int outlen,
const unsigned char **indata,
size_t *inlen);
/* Used to send an option. The option should *not* contain the inital
"255 250" nor the tailing "255 240" and should *not* double
internal 255 values. */
void telnet_send_option(telnet_data_t *td, const unsigned char *option,
unsigned int len);
/* Initialize the telnet data. */
void telnet_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,
const unsigned char *init_seq,
int init_seq_len);
void telnet_cleanup(telnet_data_t *td);
#endif /* _SER2NET_TELNET_H */
|