blob: 74a52ef3bc46fc706f651408b48d79b86c22ab7f [file] [log] [blame]
Sean Middleditch29144852009-03-12 23:14:47 -04001/*
Sean Middleditch55655962009-10-24 15:38:46 -07002 * libtelnet - TELNET protocol handling library
Sean Middleditchae39cee2009-03-22 22:47:30 -04003 *
Sean Middleditch9de15982009-03-14 03:35:49 -04004 * Sean Middleditch
5 * sean@sourcemud.org
6 *
Sean Middleditch29144852009-03-12 23:14:47 -04007 * The author or authors of this code dedicate any and all copyright interest
8 * in this code to the public domain. We make this dedication for the benefit
9 * of the public at large and to the detriment of our heirs and successors. We
10 * intend this dedication to be an overt act of relinquishment in perpetuity of
11 * all present and future rights to this code under copyright law.
12 */
13
Sean Middleditch6aef0732009-03-12 23:27:35 -040014#if !defined(LIBTELNET_INCLUDE)
Sean Middleditchaac2c122009-03-14 18:31:26 -040015#define LIBTELNET_INCLUDE 1
Sean Middleditch6aef0732009-03-12 23:27:35 -040016
Sean Middleditche22b4772009-03-22 16:44:40 -040017/* printf type checking feature in GCC and some other compilers */
18#if __GNUC__
19# define TELNET_GNU_PRINTF(f,a) __attribute__((format(printf, f, a)))
20# define TELNET_GNU_SENTINEL __attribute__((sentinel))
21#else
22# define TELNET_GNU_PRINTF(f,a)
23# define TELNET_GNU_SENTINEL
24#endif
25
Sean Middleditch30323022009-03-14 21:45:28 -040026/* forward declarations */
Sean Middleditchf65f27d2009-03-19 02:32:04 -040027typedef struct telnet_t telnet_t;
28typedef struct telnet_event_t telnet_event_t;
Sean Middleditch34bb0992009-03-21 00:20:44 -040029typedef struct telnet_telopt_t telnet_telopt_t;
Sean Middleditch30323022009-03-14 21:45:28 -040030
Sean Middleditch29144852009-03-12 23:14:47 -040031/* telnet special values */
Sean Middleditchf65f27d2009-03-19 02:32:04 -040032#define TELNET_IAC 255
33#define TELNET_DONT 254
34#define TELNET_DO 253
35#define TELNET_WONT 252
36#define TELNET_WILL 251
37#define TELNET_SB 250
Sean Middleditchf65f27d2009-03-19 02:32:04 -040038#define TELNET_GA 249
39#define TELNET_EL 248
40#define TELNET_EC 247
41#define TELNET_AYT 246
42#define TELNET_AO 245
43#define TELNET_IP 244
44#define TELNET_BREAK 243
45#define TELNET_DM 242
46#define TELNET_NOP 241
47#define TELNET_SE 240
48#define TELNET_EOR 239
49#define TELNET_ABORT 238
50#define TELNET_SUSP 237
51#define TELNET_EOF 236
Sean Middleditch29144852009-03-12 23:14:47 -040052
53/* telnet options */
Sean Middleditchf65f27d2009-03-19 02:32:04 -040054#define TELNET_TELOPT_BINARY 0
55#define TELNET_TELOPT_ECHO 1
56#define TELNET_TELOPT_RCP 2
57#define TELNET_TELOPT_SGA 3
58#define TELNET_TELOPT_NAMS 4
59#define TELNET_TELOPT_STATUS 5
60#define TELNET_TELOPT_TM 6
61#define TELNET_TELOPT_RCTE 7
62#define TELNET_TELOPT_NAOL 8
63#define TELNET_TELOPT_NAOP 9
64#define TELNET_TELOPT_NAOCRD 10
65#define TELNET_TELOPT_NAOHTS 11
66#define TELNET_TELOPT_NAOHTD 12
67#define TELNET_TELOPT_NAOFFD 13
68#define TELNET_TELOPT_NAOVTS 14
69#define TELNET_TELOPT_NAOVTD 15
70#define TELNET_TELOPT_NAOLFD 16
71#define TELNET_TELOPT_XASCII 17
72#define TELNET_TELOPT_LOGOUT 18
73#define TELNET_TELOPT_BM 19
74#define TELNET_TELOPT_DET 20
75#define TELNET_TELOPT_SUPDUP 21
76#define TELNET_TELOPT_SUPDUPOUTPUT 22
77#define TELNET_TELOPT_SNDLOC 23
78#define TELNET_TELOPT_TTYPE 24
79#define TELNET_TELOPT_EOR 25
80#define TELNET_TELOPT_TUID 26
81#define TELNET_TELOPT_OUTMRK 27
82#define TELNET_TELOPT_TTYLOC 28
83#define TELNET_TELOPT_3270REGIME 29
84#define TELNET_TELOPT_X3PAD 30
85#define TELNET_TELOPT_NAWS 31
86#define TELNET_TELOPT_TSPEED 32
87#define TELNET_TELOPT_LFLOW 33
88#define TELNET_TELOPT_LINEMODE 34
89#define TELNET_TELOPT_XDISPLOC 35
90#define TELNET_TELOPT_ENVIRON 36
91#define TELNET_TELOPT_AUTHENTICATION 37
92#define TELNET_TELOPT_ENCRYPT 38
93#define TELNET_TELOPT_NEW_ENVIRON 39
Sean Middleditche2122b22009-03-20 23:55:09 -040094#define TELNET_TELOPT_MSSP 70
Sean Middleditchf65f27d2009-03-19 02:32:04 -040095#define TELNET_TELOPT_COMPRESS2 86
96#define TELNET_TELOPT_ZMP 93
97#define TELNET_TELOPT_EXOPL 255
Sean Middleditch29144852009-03-12 23:14:47 -040098
Sean Middleditche2122b22009-03-20 23:55:09 -040099#define TELNET_TELOPT_MCCP2 86
100
Sean Middleditch2d5c4992009-03-22 22:21:42 -0400101/* special codes for the subnegotiation commands for certain telopts */
102#define TELNET_TTYPE_IS 0
103#define TELNET_TTYPE_SEND 1
104
105#define TELNET_ENVIRON_IS 0
106#define TELNET_ENVIRON_SEND 1
107#define TELNET_ENVIRON_INFO 2
108#define TELNET_ENVIRON_VAR 0
109#define TELNET_ENVIRON_VALUE 1
110#define TELNET_ENVIRON_ESC 2
111#define TELNET_ENVIRON_USERVAR 3
112
113#define TELNET_MSSP_VAR 1
114#define TELNET_MSSP_VAL 2
115
Sean Middleditch08bb05f2009-03-15 23:29:46 -0400116/* libtelnet feature flags */
Sean Middleditchf65f27d2009-03-19 02:32:04 -0400117#define TELNET_FLAG_PROXY (1<<0)
Sean Middleditch61f8eb62009-03-14 04:57:27 -0400118
Sean Middleditchf65f27d2009-03-19 02:32:04 -0400119#define TELNET_PFLAG_DEFLATE (1<<7)
Sean Middleditch29144852009-03-12 23:14:47 -0400120
121/* telnet states */
Sean Middleditchf65f27d2009-03-19 02:32:04 -0400122enum telnet_state_t {
123 TELNET_STATE_DATA = 0,
124 TELNET_STATE_IAC,
Sean Middleditchf65f27d2009-03-19 02:32:04 -0400125 TELNET_STATE_WILL,
126 TELNET_STATE_WONT,
Sean Middleditch447d3ad2009-03-20 23:22:37 -0400127 TELNET_STATE_DO,
128 TELNET_STATE_DONT,
Sean Middleditchf65f27d2009-03-19 02:32:04 -0400129 TELNET_STATE_SB,
130 TELNET_STATE_SB_DATA,
131 TELNET_STATE_SB_DATA_IAC
Sean Middleditch29144852009-03-12 23:14:47 -0400132};
Sean Middleditchf65f27d2009-03-19 02:32:04 -0400133typedef enum telnet_state_t telnet_state_t;
Sean Middleditch29144852009-03-12 23:14:47 -0400134
135/* error codes */
Sean Middleditchf65f27d2009-03-19 02:32:04 -0400136enum telnet_error_t {
137 TELNET_EOK = 0,
138 TELNET_EBADVAL, /* invalid parameter, or API misuse */
139 TELNET_ENOMEM, /* memory allocation failure */
140 TELNET_EOVERFLOW, /* data exceeds buffer size */
141 TELNET_EPROTOCOL, /* invalid sequence of special bytes */
142 TELNET_ECOMPRESS /* error handling compressed streams */
Sean Middleditch29144852009-03-12 23:14:47 -0400143};
Sean Middleditchf65f27d2009-03-19 02:32:04 -0400144typedef enum telnet_error_t telnet_error_t;
Sean Middleditch29144852009-03-12 23:14:47 -0400145
Sean Middleditch637df7f2009-03-15 12:57:32 -0400146/* event codes */
Sean Middleditchf65f27d2009-03-19 02:32:04 -0400147enum telnet_event_type_t {
148 TELNET_EV_DATA = 0,
149 TELNET_EV_SEND,
150 TELNET_EV_IAC,
151 TELNET_EV_WILL,
152 TELNET_EV_WONT,
153 TELNET_EV_DO,
154 TELNET_EV_DONT,
155 TELNET_EV_SUBNEGOTIATION,
156 TELNET_EV_COMPRESS,
157 TELNET_EV_WARNING,
158 TELNET_EV_ERROR
Sean Middleditch30323022009-03-14 21:45:28 -0400159};
Sean Middleditchf65f27d2009-03-19 02:32:04 -0400160typedef enum telnet_event_type_t telnet_event_type_t;
Sean Middleditch30323022009-03-14 21:45:28 -0400161
Sean Middleditch637df7f2009-03-15 12:57:32 -0400162/* event information */
Sean Middleditchf65f27d2009-03-19 02:32:04 -0400163struct telnet_event_t {
Sean Middleditche5327da2009-03-21 00:54:50 -0400164 /* ZMP argument list */
165 const char **argv;
166 size_t argc;
Sean Middleditch637df7f2009-03-15 12:57:32 -0400167 /* data buffer: for DATA, SEND, SUBNEGOTIATION, and ERROR events */
Sean Middleditch8daf7742009-03-19 02:05:24 -0400168 const char *buffer;
Sean Middleditch340a51b2009-03-19 02:08:46 -0400169 size_t size;
Sean Middleditch5b5bc922009-03-15 23:02:10 -0400170 /* type of event */
Sean Middleditchf65f27d2009-03-19 02:32:04 -0400171 enum telnet_event_type_t type;
Sean Middleditch5b5bc922009-03-15 23:02:10 -0400172 /* IAC command */
173 unsigned char command;
174 /* telopt info: for negotiation events SUBNEGOTIATION */
175 unsigned char telopt;
Sean Middleditch5b5bc922009-03-15 23:02:10 -0400176};
177
Sean Middleditch637df7f2009-03-15 12:57:32 -0400178/* event handler declaration */
Sean Middleditchf65f27d2009-03-19 02:32:04 -0400179typedef void (*telnet_event_handler_t)(telnet_t *telnet,
180 telnet_event_t *event, void *user_data);
Sean Middleditch637df7f2009-03-15 12:57:32 -0400181
Sean Middleditch34bb0992009-03-21 00:20:44 -0400182/* telopt support table element; use telopt of -1 for end marker */
183struct telnet_telopt_t {
Sean Middleditchbfc641e2009-03-22 16:26:06 -0400184 short telopt; /* one of the TELOPT codes or -1 */
185 unsigned char us; /* TELNET_WILL or TELNET_WONT */
186 unsigned char him; /* TELNET_DO or TELNET_DONT */
Sean Middleditch34bb0992009-03-21 00:20:44 -0400187};
188
Sean Middleditchd2466a02009-09-19 14:35:48 -0700189/* state tracker -- private data structure */
190struct telnet_t;
Sean Middleditch4d9444d2009-03-13 22:48:05 -0400191
Sean Middleditch29144852009-03-12 23:14:47 -0400192/* initialize a telnet state tracker */
Sean Middleditchd2466a02009-09-19 14:35:48 -0700193extern telnet_t* telnet_init(const telnet_telopt_t *telopts,
Sean Middleditch34bb0992009-03-21 00:20:44 -0400194 telnet_event_handler_t eh, unsigned char flags, void *user_data);
Sean Middleditch29144852009-03-12 23:14:47 -0400195
196/* free up any memory allocated by a state tracker */
Sean Middleditchf65f27d2009-03-19 02:32:04 -0400197extern void telnet_free(telnet_t *telnet);
Sean Middleditch29144852009-03-12 23:14:47 -0400198
Sean Middleditch29144852009-03-12 23:14:47 -0400199/* push a byte buffer into the state tracker */
Sean Middleditch4f0c37f2009-03-20 23:08:55 -0400200extern void telnet_recv(telnet_t *telnet, const char *buffer,
Sean Middleditch340a51b2009-03-19 02:08:46 -0400201 size_t size);
Sean Middleditch29144852009-03-12 23:14:47 -0400202
203/* send an iac command */
Sean Middleditch4f0c37f2009-03-20 23:08:55 -0400204extern void telnet_iac(telnet_t *telnet, unsigned char cmd);
Sean Middleditch29144852009-03-12 23:14:47 -0400205
Sean Middleditch2b4bfc42009-03-16 01:25:52 -0400206/* send negotiation, with RFC1143 checking.
207 * will not actually send unless necessary, but will update internal
208 * negotiation queue.
209 */
Sean Middleditch4f0c37f2009-03-20 23:08:55 -0400210extern void telnet_negotiate(telnet_t *telnet, unsigned char cmd,
Sean Middleditch812358d2009-03-15 23:24:03 -0400211 unsigned char opt);
Sean Middleditch29144852009-03-12 23:14:47 -0400212
213/* send non-command data (escapes IAC bytes) */
Sean Middleditch4f0c37f2009-03-20 23:08:55 -0400214extern void telnet_send(telnet_t *telnet,
Sean Middleditch340a51b2009-03-19 02:08:46 -0400215 const char *buffer, size_t size);
Sean Middleditch29144852009-03-12 23:14:47 -0400216
Sean Middleditch90e79da2009-03-19 15:17:13 -0400217/* send IAC SB followed by the telopt code */
Sean Middleditch4f0c37f2009-03-20 23:08:55 -0400218extern void telnet_begin_sb(telnet_t *telnet,
Sean Middleditch90e79da2009-03-19 15:17:13 -0400219 unsigned char telopt);
220
221/* send IAC SE */
Sean Middleditch4f0c37f2009-03-20 23:08:55 -0400222#define telnet_finish_sb(telnet) telnet_iac((telnet), TELNET_SE)
Sean Middleditch90e79da2009-03-19 15:17:13 -0400223
224/* shortcut for sending a complete subnegotiation buffer.
225 * equivalent to:
Sean Middleditch4f0c37f2009-03-20 23:08:55 -0400226 * telnet_begin_sb(telnet, telopt);
227 * telnet_send(telnet, buffer, size);
228 * telnet_finish_sb(telnet);
Sean Middleditch2b4bfc42009-03-16 01:25:52 -0400229 */
Sean Middleditch4f0c37f2009-03-20 23:08:55 -0400230extern void telnet_subnegotiation(telnet_t *telnet, unsigned char telopt,
Sean Middleditch90e79da2009-03-19 15:17:13 -0400231 const char *buffer, size_t size);
Sean Middleditch6aef0732009-03-12 23:27:35 -0400232
Sean Middleditch124a1c22009-03-15 13:20:03 -0400233/* begin sending compressed data (server only) */
Sean Middleditchf65f27d2009-03-19 02:32:04 -0400234extern void telnet_begin_compress2(telnet_t *telnet);
Sean Middleditch124a1c22009-03-15 13:20:03 -0400235
Sean Middleditchf65f27d2009-03-19 02:32:04 -0400236/* send formatted data with \r and \n translated, and IAC escaped */
Sean Middleditche22b4772009-03-22 16:44:40 -0400237extern int telnet_printf(telnet_t *telnet, const char *fmt, ...)
238 TELNET_GNU_PRINTF(2, 3);
Sean Middleditch4a156042009-03-16 17:10:58 -0400239
Sean Middleditchf65f27d2009-03-19 02:32:04 -0400240/* send formatted data with just IAC escaped */
Sean Middleditch9dcfd4b2009-10-14 16:17:46 -0700241extern int telnet_raw_printf(telnet_t *telnet, const char *fmt, ...)
Sean Middleditche22b4772009-03-22 16:44:40 -0400242 TELNET_GNU_PRINTF(2, 3);
243
Sean Middleditcheb950a82009-03-22 23:04:28 -0400244/* send TTYPE/ENVIRON/NEW-ENVIRON/MSSP data */
245extern void telnet_format_sb(telnet_t *telnet, unsigned char telopt,
246 size_t count, ...);
247
Sean Middleditche22b4772009-03-22 16:44:40 -0400248/* send ZMP commands */
249extern void telnet_send_zmp(telnet_t *telnet, size_t argc, const char **argv);
250extern void telnet_send_zmpv(telnet_t *telnet, ...) TELNET_GNU_SENTINEL;
Sean Middleditchd58f49f2009-03-16 12:49:35 -0400251
Sean Middleditch6aef0732009-03-12 23:27:35 -0400252#endif /* !defined(LIBTELNET_INCLUDE) */