blob: e13e3ee0be2834afdfb2b4d2a62204d4ab4ad7a6 [file] [log] [blame]
Sean Middleditch29144852009-03-12 23:14:47 -04001/*
Sean Middleditch9de15982009-03-14 03:35:49 -04002 * Sean Middleditch
3 * sean@sourcemud.org
4 *
Sean Middleditch29144852009-03-12 23:14:47 -04005 * The author or authors of this code dedicate any and all copyright interest
6 * in this code to the public domain. We make this dedication for the benefit
7 * of the public at large and to the detriment of our heirs and successors. We
8 * intend this dedication to be an overt act of relinquishment in perpetuity of
9 * all present and future rights to this code under copyright law.
10 */
11
Sean Middleditch6aef0732009-03-12 23:27:35 -040012#if !defined(LIBTELNET_INCLUDE)
Sean Middleditchaac2c122009-03-14 18:31:26 -040013#define LIBTELNET_INCLUDE 1
Sean Middleditch6aef0732009-03-12 23:27:35 -040014
Sean Middleditch30323022009-03-14 21:45:28 -040015/* forward declarations */
Sean Middleditch812358d2009-03-15 23:24:03 -040016typedef struct libtelnet_t libtelnet_t;
17typedef struct libtelnet_event_t libtelnet_event_t;
Sean Middleditch8b788962009-03-16 01:06:27 -040018typedef struct libtelnet_rfc1143_t libtelnet_rfc1143_t;
Sean Middleditch812358d2009-03-15 23:24:03 -040019typedef enum libtelnet_mode_t libtelnet_mode_t;
20typedef enum libtelnet_state_t libtelnet_state_t;
21typedef enum libtelnet_error_t libtelnet_error_t;
22typedef enum libtelnet_event_type_t libtelnet_event_type_t;
Sean Middleditch30323022009-03-14 21:45:28 -040023
Sean Middleditch29144852009-03-12 23:14:47 -040024/* telnet special values */
25#define LIBTELNET_IAC 255
26#define LIBTELNET_DONT 254
27#define LIBTELNET_DO 253
28#define LIBTELNET_WONT 252
29#define LIBTELNET_WILL 251
30#define LIBTELNET_SB 250
Sean Middleditchc04224b2009-03-14 18:30:57 -040031#define LIBTELNET_SB 250
32#define LIBTELNET_GA 249
33#define LIBTELNET_EL 248
34#define LIBTELNET_EC 247
35#define LIBTELNET_AYT 246
36#define LIBTELNET_AO 245
37#define LIBTELNET_IP 244
38#define LIBTELNET_BREAK 243
39#define LIBTELNET_DM 242
40#define LIBTELNET_NOP 241
Sean Middleditch29144852009-03-12 23:14:47 -040041#define LIBTELNET_SE 240
Sean Middleditchc04224b2009-03-14 18:30:57 -040042#define LIBTELNET_EOR 239
43#define LIBTELNET_ABORT 238
44#define LIBTELNET_SUSP 237
45#define LIBTELNET_EOF 236
Sean Middleditch29144852009-03-12 23:14:47 -040046
47/* telnet options */
Sean Middleditchc04224b2009-03-14 18:30:57 -040048#define LIBTELNET_TELOPT_BINARY 0
49#define LIBTELNET_TELOPT_ECHO 1
50#define LIBTELNET_TELOPT_RCP 2
51#define LIBTELNET_TELOPT_SGA 3
52#define LIBTELNET_TELOPT_NAMS 4
53#define LIBTELNET_TELOPT_STATUS 5
54#define LIBTELNET_TELOPT_TM 6
55#define LIBTELNET_TELOPT_RCTE 7
56#define LIBTELNET_TELOPT_NAOL 8
57#define LIBTELNET_TELOPT_NAOP 9
58#define LIBTELNET_TELOPT_NAOCRD 10
59#define LIBTELNET_TELOPT_NAOHTS 11
60#define LIBTELNET_TELOPT_NAOHTD 12
61#define LIBTELNET_TELOPT_NAOFFD 13
62#define LIBTELNET_TELOPT_NAOVTS 14
63#define LIBTELNET_TELOPT_NAOVTD 15
64#define LIBTELNET_TELOPT_NAOLFD 16
65#define LIBTELNET_TELOPT_XASCII 17
66#define LIBTELNET_TELOPT_LOGOUT 18
67#define LIBTELNET_TELOPT_BM 19
68#define LIBTELNET_TELOPT_DET 20
69#define LIBTELNET_TELOPT_SUPDUP 21
70#define LIBTELNET_TELOPT_SUPDUPOUTPUT 22
71#define LIBTELNET_TELOPT_SNDLOC 23
72#define LIBTELNET_TELOPT_TTYPE 24
73#define LIBTELNET_TELOPT_EOR 25
74#define LIBTELNET_TELOPT_TUID 26
75#define LIBTELNET_TELOPT_OUTMRK 27
76#define LIBTELNET_TELOPT_TTYLOC 28
77#define LIBTELNET_TELOPT_3270REGIME 29
78#define LIBTELNET_TELOPT_X3PAD 30
79#define LIBTELNET_TELOPT_NAWS 31
80#define LIBTELNET_TELOPT_TSPEED 32
81#define LIBTELNET_TELOPT_LFLOW 33
82#define LIBTELNET_TELOPT_LINEMODE 34
83#define LIBTELNET_TELOPT_XDISPLOC 35
84#define LIBTELNET_TELOPT_ENVIRON 36
85#define LIBTELNET_TELOPT_AUTHENTICATION 37
86#define LIBTELNET_TELOPT_ENCRYPT 38
87#define LIBTELNET_TELOPT_NEW_ENVIRON 39
88#define LIBTELNET_TELOPT_COMPRESS 85
89#define LIBTELNET_TELOPT_COMPRESS2 86
90#define LIBTELNET_TELOPT_ZMP 93
91#define LIBTELNET_TELOPT_EXOPL 255
Sean Middleditch29144852009-03-12 23:14:47 -040092
Sean Middleditch08bb05f2009-03-15 23:29:46 -040093/* libtelnet feature flags */
94#define LIBTELNET_FLAG_PROXY (1<<0)
Sean Middleditch61f8eb62009-03-14 04:57:27 -040095
Sean Middleditchfbe93e32009-03-15 23:39:31 -040096#define LIBTELNET_PFLAG_DEFLATE (1<<7)
Sean Middleditch29144852009-03-12 23:14:47 -040097
98/* telnet states */
99enum libtelnet_state_t {
Sean Middleditch9de15982009-03-14 03:35:49 -0400100 LIBTELNET_STATE_DATA = 0,
Sean Middleditch29144852009-03-12 23:14:47 -0400101 LIBTELNET_STATE_IAC,
102 LIBTELNET_STATE_DO,
103 LIBTELNET_STATE_DONT,
104 LIBTELNET_STATE_WILL,
105 LIBTELNET_STATE_WONT,
106 LIBTELNET_STATE_SB,
Sean Middleditchda0e6952009-03-15 13:28:09 -0400107 LIBTELNET_STATE_SB_DATA,
108 LIBTELNET_STATE_SB_DATA_IAC
Sean Middleditch29144852009-03-12 23:14:47 -0400109};
110
111/* error codes */
112enum libtelnet_error_t {
Sean Middleditchf66a7ee2009-03-15 11:54:07 -0400113 LIBTELNET_EOK = 0,
Sean Middleditch16992272009-03-15 19:42:03 -0400114 LIBTELNET_EBADVAL, /* invalid parameter, or API misuse */
Sean Middleditchf66a7ee2009-03-15 11:54:07 -0400115 LIBTELNET_ENOMEM, /* memory allocation failure */
116 LIBTELNET_EOVERFLOW, /* data exceeds buffer size */
117 LIBTELNET_EPROTOCOL, /* invalid sequence of special bytes */
Sean Middleditch16992272009-03-15 19:42:03 -0400118 LIBTELNET_ECOMPRESS /* error handling compressed streams */
Sean Middleditch29144852009-03-12 23:14:47 -0400119};
120
Sean Middleditch637df7f2009-03-15 12:57:32 -0400121/* event codes */
122enum libtelnet_event_type_t {
123 LIBTELNET_EV_DATA = 0,
124 LIBTELNET_EV_SEND,
125 LIBTELNET_EV_IAC,
Sean Middleditch5b5bc922009-03-15 23:02:10 -0400126 LIBTELNET_EV_WILL,
127 LIBTELNET_EV_WONT,
128 LIBTELNET_EV_DO,
129 LIBTELNET_EV_DONT,
Sean Middleditch637df7f2009-03-15 12:57:32 -0400130 LIBTELNET_EV_SUBNEGOTIATION,
131 LIBTELNET_EV_COMPRESS,
Sean Middleditch16992272009-03-15 19:42:03 -0400132 LIBTELNET_EV_WARNING,
Sean Middleditch637df7f2009-03-15 12:57:32 -0400133 LIBTELNET_EV_ERROR
Sean Middleditch30323022009-03-14 21:45:28 -0400134};
135
Sean Middleditch637df7f2009-03-15 12:57:32 -0400136/* event information */
137struct libtelnet_event_t {
Sean Middleditch637df7f2009-03-15 12:57:32 -0400138 /* data buffer: for DATA, SEND, SUBNEGOTIATION, and ERROR events */
Sean Middleditch97a8cb22009-03-16 16:51:41 -0400139 const unsigned char *buffer;
Sean Middleditch637df7f2009-03-15 12:57:32 -0400140 unsigned int size;
Sean Middleditch5b5bc922009-03-15 23:02:10 -0400141 /* type of event */
142 enum libtelnet_event_type_t type;
143 /* IAC command */
144 unsigned char command;
145 /* telopt info: for negotiation events SUBNEGOTIATION */
146 unsigned char telopt;
147 /* accept status: for WILL and DO events */
148 unsigned char accept;
149};
150
151/* option negotiation state (RFC 1143) */
152struct libtelnet_rfc1143_t {
153 unsigned char telopt;
154 char us:4, him:4;
Sean Middleditch637df7f2009-03-15 12:57:32 -0400155};
156
157/* event handler declaration */
Sean Middleditch812358d2009-03-15 23:24:03 -0400158typedef void (*libtelnet_event_handler_t)(libtelnet_t *telnet,
159 libtelnet_event_t *event, void *user_data);
Sean Middleditch637df7f2009-03-15 12:57:32 -0400160
Sean Middleditch4d9444d2009-03-13 22:48:05 -0400161/* state tracker */
162struct libtelnet_t {
Sean Middleditch9f79cc52009-03-15 13:39:24 -0400163 /* user data */
164 void *ud;
Sean Middleditch637df7f2009-03-15 12:57:32 -0400165 /* event handler */
166 libtelnet_event_handler_t eh;
Sean Middleditch9de15982009-03-14 03:35:49 -0400167#ifdef HAVE_ZLIB
Sean Middleditch30323022009-03-14 21:45:28 -0400168 /* zlib (mccp2) compression */
Sean Middleditchfbe93e32009-03-15 23:39:31 -0400169 z_stream *z;
Sean Middleditch9de15982009-03-14 03:35:49 -0400170#endif
Sean Middleditch5b5bc922009-03-15 23:02:10 -0400171 /* RFC1143 option negotiation states */
172 struct libtelnet_rfc1143_t *q;
Sean Middleditch4d9444d2009-03-13 22:48:05 -0400173 /* sub-request buffer */
174 unsigned char *buffer;
175 /* current size of the buffer */
Sean Middleditch5b5bc922009-03-15 23:02:10 -0400176 unsigned int buffer_size;
177 /* current buffer write position (also length of buffer data) */
178 unsigned int buffer_pos;
Sean Middleditch4d9444d2009-03-13 22:48:05 -0400179 /* current state */
180 enum libtelnet_state_t state;
Sean Middleditch08bb05f2009-03-15 23:29:46 -0400181 /* option flags */
182 unsigned char flags;
Sean Middleditchda0e6952009-03-15 13:28:09 -0400183 /* current subnegotiation telopt */
184 unsigned char sb_telopt;
Sean Middleditch5b5bc922009-03-15 23:02:10 -0400185 /* length of RFC1143 queue */
186 unsigned char q_size;
Sean Middleditch4d9444d2009-03-13 22:48:05 -0400187};
188
Sean Middleditch29144852009-03-12 23:14:47 -0400189/* initialize a telnet state tracker */
Sean Middleditch812358d2009-03-15 23:24:03 -0400190extern void libtelnet_init(libtelnet_t *telnet, libtelnet_event_handler_t eh,
Sean Middleditch08bb05f2009-03-15 23:29:46 -0400191 unsigned char flags, void *user_data);
Sean Middleditch29144852009-03-12 23:14:47 -0400192
193/* free up any memory allocated by a state tracker */
Sean Middleditch812358d2009-03-15 23:24:03 -0400194extern void libtelnet_free(libtelnet_t *telnet);
Sean Middleditch29144852009-03-12 23:14:47 -0400195
Sean Middleditch29144852009-03-12 23:14:47 -0400196/* push a byte buffer into the state tracker */
Sean Middleditch97a8cb22009-03-16 16:51:41 -0400197extern void libtelnet_push(libtelnet_t *telnet, const unsigned char *buffer,
Sean Middleditch812358d2009-03-15 23:24:03 -0400198 unsigned int size);
Sean Middleditch29144852009-03-12 23:14:47 -0400199
200/* send an iac command */
Sean Middleditch812358d2009-03-15 23:24:03 -0400201extern void libtelnet_send_command(libtelnet_t *telnet, unsigned char cmd);
Sean Middleditch29144852009-03-12 23:14:47 -0400202
Sean Middleditch2b4bfc42009-03-16 01:25:52 -0400203/* send an iac command with a telopt */
204extern void libtelnet_send_telopt(libtelnet_t *telnet, unsigned char cmd,
205 unsigned char telopt);
206
207/* send negotiation, with RFC1143 checking.
208 * will not actually send unless necessary, but will update internal
209 * negotiation queue.
210 */
Sean Middleditch812358d2009-03-15 23:24:03 -0400211extern void libtelnet_send_negotiate(libtelnet_t *telnet, unsigned char cmd,
212 unsigned char opt);
Sean Middleditch29144852009-03-12 23:14:47 -0400213
214/* send non-command data (escapes IAC bytes) */
Sean Middleditch97a8cb22009-03-16 16:51:41 -0400215extern void libtelnet_send_data(libtelnet_t *telnet,
216 const unsigned char *buffer, unsigned int size);
Sean Middleditch29144852009-03-12 23:14:47 -0400217
Sean Middleditch2b4bfc42009-03-16 01:25:52 -0400218/* send sub-request, equivalent to:
219 * libtelnet_send_telopt(telnet, LIBTELNET_SB, telopt)
220 * libtelnet_send_data(telnet, buffer, size);
221 * libtelnet_send_command(telnet, LIBTELNET_SE);
222 * manually generating sequence may be easier for complex subnegotiations
223 * thare are most easily implemented with a series of send_data calls.
224 */
Sean Middleditch812358d2009-03-15 23:24:03 -0400225extern void libtelnet_send_subnegotiation(libtelnet_t *telnet,
Sean Middleditch97a8cb22009-03-16 16:51:41 -0400226 unsigned char telopt, const unsigned char *buffer, unsigned int size);
Sean Middleditch6aef0732009-03-12 23:27:35 -0400227
Sean Middleditch124a1c22009-03-15 13:20:03 -0400228/* begin sending compressed data (server only) */
Sean Middleditch812358d2009-03-15 23:24:03 -0400229extern void libtelnet_begin_compress2(libtelnet_t *telnet);
Sean Middleditch124a1c22009-03-15 13:20:03 -0400230
Sean Middleditchd58f49f2009-03-16 12:49:35 -0400231/* send formatted data (through libtelnet_send_data) */
232#ifdef __GNUC__
233# define LIBTELNET_GNU_PRINTF(f,a) __attribute__((printf(f, a)))
234#else
235# define LIBTELNET_GNU_PRINTF(f,a)
236#endif
237
Sean Middleditch4a156042009-03-16 17:10:58 -0400238extern int libtelnet_printf(libtelnet_t *telnet, const char *fmt, ...);
239
240/* send formatted data with \r and \n translated */
241extern int libtelnet_printf2(libtelnet_t *telnet, const char *fmt, ...);
Sean Middleditchd58f49f2009-03-16 12:49:35 -0400242
Sean Middleditch6aef0732009-03-12 23:27:35 -0400243#endif /* !defined(LIBTELNET_INCLUDE) */