blob: dc332a3bafea6ecd4456a7c63fe9df049b5c067c [file] [log] [blame]
Sean Middleditchb9e48642009-03-12 23:33:27 -04001=====================================================================
2 libtelnet - TELNET protocol handling library
3=====================================================================
4
Sean Middleditch892c5f12009-03-14 13:39:07 -04005 http://github.com/elanthis/libtelnet
6
7 Sean Middleditch
8 sean@sourcemud.org
Sean Middleditchb9e48642009-03-12 23:33:27 -04009
10---------------------------------------------------------------------
11The author or authors of this code dedicate any and all copyright
12interest in this code to the public domain. We make this dedication
13for the benefit of the public at large and to the detriment of our
14heirs and successors. We intend this dedication to be an overt act of
15relinquishment in perpetuity of all present and future rights to this
16code under copyright law.
17---------------------------------------------------------------------
18
Sean Middleditch9d2f98a2009-03-14 05:24:56 -040019*** TODO ***
20
Sean Middleditch9d2f98a2009-03-14 05:24:56 -040021 - automatic MCCP2 handling (controllable by host app)
Sean Middleditch9d2f98a2009-03-14 05:24:56 -040022 ? ZMP parsing
23 ? MSSP parsing
24 ? ENVIRON/NEW-ENVIRON parsing
25 ? telnet-status testing tool
Sean Middleditch9d2f98a2009-03-14 05:24:56 -040026
Sean Middleditchb9e48642009-03-12 23:33:27 -040027I. INTRODUCTION
28=====================================================================
29
30libtelnet provides safe and correct handling of the core TELNET
Sean Middleditch8b788962009-03-16 01:06:27 -040031protocol. In addition to the base TELNET protocol, libtelnet also
32implements the Q method of TELNET option negotiation. libtelnet
33can be used for writing servers, clients, or proxies.
Sean Middleditchb9e48642009-03-12 23:33:27 -040034
Sean Middleditch892c5f12009-03-14 13:39:07 -040035For more information on the TELNET protocol, see:
36
37 http://www.faqs.org/rfcs/rfc854.html
Sean Middleditch8b788962009-03-16 01:06:27 -040038 http://www.faqs.org/rfcs/rfc1143.html
Sean Middleditch892c5f12009-03-14 13:39:07 -040039
Sean Middleditchb9e48642009-03-12 23:33:27 -040040II. LIBTELNET API
41=====================================================================
42
Sean Middleditch892c5f12009-03-14 13:39:07 -040043The libtelnet API contains several distinct parts. The first part is
44the basic initialization and deinitialization routines. The second
45part is a single function for pushing received data into the
46libtelnet processor. The third part is the libtelnet_send_*()
47functions, which generate TELNET commands and ensure data is properly
Sean Middleditch637df7f2009-03-15 12:57:32 -040048formatted before sending over the wire. The final part is the event
49handler interface.
Sean Middleditch892c5f12009-03-14 13:39:07 -040050
51IIa. Initialization
52
53 struct libtelnet_t;
54 This structure represents the state of the TELNET protocol for a
55 single connection. Each connection utilizing TELNET must have
56 its own libtelnet_t structure, which is passed to all libtelnet
57 API calls.
58
Sean Middleditch812358d2009-03-15 23:24:03 -040059 void libtelnet_init(libtelnet_t *telnet, libtelnet_event_handler_t handler,
Sean Middleditch08bb05f2009-03-15 23:29:46 -040060 unsigned char flags, void *user_data);
Sean Middleditch892c5f12009-03-14 13:39:07 -040061 The libtelnet_init() function is responsible for initializing
62 the data in a libtelnet_t structure. It must be called
63 immediately after establishing a connection and before any other
64 libtelnet API calls are made.
65
Sean Middleditch637df7f2009-03-15 12:57:32 -040066 The handler parameter must be a function matching the
67 libtelnet_event_handler_t definition. More information about
68 events can be found in section IId.
Sean Middleditch30323022009-03-14 21:45:28 -040069
Sean Middleditch9f79cc52009-03-15 13:39:24 -040070 The user_data parameter is passed to the event handler whenver it
71 is invoked. This will usually be a structure container
72 information about the connection, including a socket descriptor
73 for implementing LIBTELNET_EV_SEND event handling.
74
Sean Middleditch08bb05f2009-03-15 23:29:46 -040075 The flags parameter can be any of the following flag constants
76 bit-or'd together, or 0 to leave all options disabled.
77
78 LIBTELNET_FLAG_PROXY - operate in proxy mode
Sean Middleditch892c5f12009-03-14 13:39:07 -040079
Sean Middleditch812358d2009-03-15 23:24:03 -040080 boid libtelnet_free(libtelnet_t *telnet);
Sean Middleditch892c5f12009-03-14 13:39:07 -040081 Releases any internal memory allocated by libtelnet. This must
82 be called whenever a connection is closed, or you will incur
83 memory leaks.
84
85IIb. Receiving Data
86
Sean Middleditch812358d2009-03-15 23:24:03 -040087 void libtelnet_push(libtelnet_t *telnet,
Sean Middleditch892c5f12009-03-14 13:39:07 -040088 unsigned char *buffer, unsigned int size, void *user_data);
89 When your application receives data over the socket from the
90 remote end, it must pass the received bytes into this function.
Sean Middleditch637df7f2009-03-15 12:57:32 -040091
92 As the TELNET stream is parsed, events will be generated and
93 passed to the event handler given to libtelnet_init(). Of
94 particular interest for data receiving is the LIBTELNET_EV_DATA
95 event, which is triggered for any regular data such as user
96 input or server process output.
Sean Middleditch892c5f12009-03-14 13:39:07 -040097
98IIc. Sending Data
99
Sean Middleditch637df7f2009-03-15 12:57:32 -0400100 All of the libtelnet_send_*() functions will invoke the
Sean Middleditch9f79cc52009-03-15 13:39:24 -0400101 LIBTELNET_EV_SEND event.
Sean Middleditch637df7f2009-03-15 12:57:32 -0400102
103 Note: it is very important that ALL data sent to the remote end of
104 the connection be passed through libtelnet. All user input or
105 process output that you wish to send over the wire should be given
106 to libtelnet_send_data(). Do NOT send or buffer unprocessed output
107 data directly!
Sean Middleditch892c5f12009-03-14 13:39:07 -0400108
Sean Middleditch812358d2009-03-15 23:24:03 -0400109 void libtelnet_send_command(libtelnet_t *telnet, unsigned char cmd);
Sean Middleditch892c5f12009-03-14 13:39:07 -0400110 Sends a single "simple" TELNET command, such as the GO-AHEAD
111 commands (255 249).
112
Sean Middleditch2b4bfc42009-03-16 01:25:52 -0400113 void libtelnet_send_command(libtelnet_t *telnet, unsigned char cmd,
114 unsigned char telopt);
115 Sends a TELNET command with an option code following. This is
116 only useful for the WILL, WONT, DO, DONT, and SB commands.
117
Sean Middleditch812358d2009-03-15 23:24:03 -0400118 void libtelnet_send_negotiate(libtelnet_t *telnet,
Sean Middleditch9f79cc52009-03-15 13:39:24 -0400119 unsigned char cmd, unsigned char opt);
Sean Middleditch892c5f12009-03-14 13:39:07 -0400120 Sends a TELNET negotiation command. The cmd parameter must be
121 one of LIBTELNET_WILL, LIBTELNET_DONT, LIBTELNET_DO, or
122 LIBTELNET_DONT. The opt parameter is the option to
123 negotiate.
124
Sean Middleditch812358d2009-03-15 23:24:03 -0400125 void libtelnet_send_data(libtelnet_t *telnet, unsigned char *buffer,
126 unsigned int size);
Sean Middleditch892c5f12009-03-14 13:39:07 -0400127 Sends raw data, which would be either the process output from
128 a server or the user input from a client.
129
Sean Middleditch812358d2009-03-15 23:24:03 -0400130 void libtelnet_send_subnegotiation(libtelnet_t *telnet,
Sean Middleditch2b4bfc42009-03-16 01:25:52 -0400131 unsigned char telopt, unsigned char *buffer, unsigned int size);
132 Sends a TELNET sub-negotiation command. The telopt parameter
Sean Middleditch892c5f12009-03-14 13:39:07 -0400133 is the sub-negotiation option.
134
Sean Middleditch2b4bfc42009-03-16 01:25:52 -0400135 Note that the above function is just a shorthand for:
136 libtelnet_send_telopt(telnet, LIBTELNET_SB, telopt);
137 libtelnet_send_data(telnet, buffer, size);
138 libtelnet_send_command(telnet, LIBTELNET_SE);
139
140 For some subnegotiations that involve a lot of complex formatted
141 data to be sent, it may be easier to manually send the SB telopt
142 header and SE footer around mulitple calls to send_data.
143
144 NOTE: libtelnet_send_subrequest() does have special behavior in
145 PROXY mode, as in that mode this function will automatically
146 detect the COMPRESS2 marker and enable zlib compression.
147
Sean Middleditch637df7f2009-03-15 12:57:32 -0400148IId. Event Handling
Sean Middleditch892c5f12009-03-14 13:39:07 -0400149
Sean Middleditch637df7f2009-03-15 12:57:32 -0400150 libtelnet relies on an event-handling mechanism for processing
151 the parsed TELNET protocol stream as well as for buffering and
152 sending output data.
Sean Middleditch892c5f12009-03-14 13:39:07 -0400153
Sean Middleditch637df7f2009-03-15 12:57:32 -0400154 When you initialize a libtelnet_t structure with libtelnet_init()
155 you had to pass in an event handler function. This function must
156 meet the following prototype:
Sean Middleditch30323022009-03-14 21:45:28 -0400157
Sean Middleditch637df7f2009-03-15 12:57:32 -0400158 void (libtelnet_t *telnet, libtelnet_event_t *event,
Sean Middleditch9f79cc52009-03-15 13:39:24 -0400159 void *user_data);
160
161 The event structure is detailed below. The user_data value is the
162 pointer passed to libtelnet_init().
Sean Middleditch637df7f2009-03-15 12:57:32 -0400163
164 struct libtelnet_event_t {
Sean Middleditch637df7f2009-03-15 12:57:32 -0400165 unsigned char *buffer;
166 unsigned int size;
Sean Middleditch812358d2009-03-15 23:24:03 -0400167 libtelnet_event_type_t type;
168 unsigned char command;
169 unsigned char telopt;
170 unsigned char accept;
Sean Middleditch637df7f2009-03-15 12:57:32 -0400171 };
172
173 The enumeration values of libtelnet_event_type_t are described in
174 detail below. Whenever the the event handler is invoked, the
175 application must look at the event->type value and do any
176 necessary processing.
177
178 The only event that MUST be implemented is LIBTELNET_EV_SEND.
179 Most applications will also always want to implement the event
180 LIBTELNET_EV_DATA.
181
182 Here is an example event handler implementation which includes
183 handlers for several important events.
184
Sean Middleditch812358d2009-03-15 23:24:03 -0400185 void my_event_handler(libtelnet_t *telnet, libtelnet_event_t *ev,
186 void *user_data) {
Sean Middleditch637df7f2009-03-15 12:57:32 -0400187 struct user_info *user = (struct user_info *)user_data;
188
189 switch (ev->type) {
190 case LIBTELNET_EV_DATA:
191 process_user_input(user, event->buffer, event->size);
192 break;
193 case LIBTELNET_EV_SEND:
194 write_to_descriptor(user, event->buffer, event->size);
195 break;
196 case LIBTELNET_EV_ERROR:
197 fatal_error("TELNET error: %s", event->buffer);
198 break;
199 }
Sean Middleditch30323022009-03-14 21:45:28 -0400200 }
201
Sean Middleditch637df7f2009-03-15 12:57:32 -0400202 LIBTELNET_EV_DATA:
203 The DATA event is triggered whenever regular data (not part of
204 any special TELNET command) is received. For a client, this
205 will be process output from the server. For a server, this will
206 be input typed by the user.
Sean Middleditch30323022009-03-14 21:45:28 -0400207
Sean Middleditch637df7f2009-03-15 12:57:32 -0400208 The event->buffer value will contain the bytes received and the
209 event->size value will contain the number of bytes received.
210 Note that event->buffer is not NUL terminated!
Sean Middleditch30323022009-03-14 21:45:28 -0400211
Sean Middleditch637df7f2009-03-15 12:57:32 -0400212 NOTE: there is no guarantee that user input or server output
213 will be received in whole lines. If you wish to process data
214 a line at a time, you are responsible for buffering the data and
215 checking for line terminators yourself!
216
217 LIBTELNET_EV_SEND:
218 This event is sent whenever libtelnet has generated data that
219 must be sent over the wire to the remove end. Generally that
220 means calling send() or adding the data to your application's
221 output buffer.
Sean Middleditch30323022009-03-14 21:45:28 -0400222
Sean Middleditch637df7f2009-03-15 12:57:32 -0400223 The event->buffer value will contain the bytes to send and the
224 event->size value will contain the number of bytes to send.
225 Note that event->buffer is not NUL terminated, and may include
226 NUL characters in its data, so always use event->size!
Sean Middleditch30323022009-03-14 21:45:28 -0400227
Sean Middleditch637df7f2009-03-15 12:57:32 -0400228 NOTE: Your SEND event handler must send or buffer the data in
229 its raw form as provided by libtelnet. If you wish to perform
230 any kind of preprocessing on data you want to send to the other
231
232 LIBTELNET_EV_IAC:
233 The IAC event is triggered whenever a simple IAC command is
234 received, such as the IAC EOR (end of record, also called
235 go ahead or GA) command.
Sean Middleditch892c5f12009-03-14 13:39:07 -0400236
Sean Middleditch637df7f2009-03-15 12:57:32 -0400237 The command received is in the event->command value.
Sean Middleditch892c5f12009-03-14 13:39:07 -0400238
Sean Middleditch637df7f2009-03-15 12:57:32 -0400239 The necessary processing depends on the specific commands; see
240 the TELNET RFC for more information.
241
Sean Middleditch5b5bc922009-03-15 23:02:10 -0400242 LIBTELNET_EV_WILL:
243 LIBTELNET_EV_DO:
244 The WILL and DO events are sent when a TELNET negotiation
245 command of the same name is received.
Sean Middleditch892c5f12009-03-14 13:39:07 -0400246
Sean Middleditch5b5bc922009-03-15 23:02:10 -0400247 WILL events are sent by the remote end when they wish to be
248 allowed to turn an option on on their end, or in confirmation
249 after you have sent a DO command to them.
Sean Middleditch892c5f12009-03-14 13:39:07 -0400250
Sean Middleditch5b5bc922009-03-15 23:02:10 -0400251 DO events are sent by the remote end when they wish for you
252 to turn on an option on your end, or in confirmation after you
253 have sent a WILL command to them.
254
255 In either case, the TELNET option under negotiation will be in
256 event->telopt field.
257
258 If you support the option and wish for it to be enabled you
259 must set the event->accept field to 1, unless this event is
260 a confirmation for a previous WILL/DO command you sent to the
261 remote end. If you do not set event->field to 1 then
262 libtelnet will send a rejection command back to the other end.
263
264 libtelnet manages some of the pecularities of negotiation for
265 you. For information on libtelnet's negotiation method, see:
Sean Middleditch892c5f12009-03-14 13:39:07 -0400266
267 http://www.faqs.org/rfcs/rfc1143.html
268
Sean Middleditch5b5bc922009-03-15 23:02:10 -0400269 Examples:
270
271 You want remote end to use TTYPE, so you send DO TTYPE.
272 Remote accepts and sends WILL TTYPE.
273
274 Remote end wants you to use SGA, so they send DO_SGA.
275 You do not support SGA and set event->accept = 0.
276
277 Remote end wants to use ZMP, so they send WILL ZMP.
278 You support ZMP, so you set event->accept = 1 and enable
279 local ZMP support.
280
281 You want to use MCCP2, so you send WILL COMPRESS2.
282 Remote end accepts and sends DO COMPRESS2.
283
284 Note that in PROXY mode libtelnet will do no processing of its
285 own for you.
286
287 LIBTELNET_EV_WONT:
288 LIBTELNET_EV_DONT:
289 The WONT and DONT events are sent when the remote end of the
290 connection wishes to disable an option, when they are
291 refusing to a support an option that you have asked for, or
292 in confirmation of an option you have asked to be disabled.
293
294 Most commonly WONT and DONT events are sent as rejections of
295 features you requested by sending DO or WILL events. Receiving
296 these events means the TELNET option is not or will not be
297 supported by the remote end, so give up.
298
299 Sometimes WONT or DONT will be sent for TELNET options that are
300 already enabled, but the remote end wishes to stop using. You
301 cannot decline. These events are demands that must be complied
302 with. libtelnet will always send the appropriate response back
303 without consulting your application. These events are sent to
304 allow your application to disable its own use of the features.
305
306 In either case, the TELNET option under negotiation will be in
307 event->telopt field.
308
309 Note that in PROXY mode libtelnet will do no processing of its
310 own for you.
311
Sean Middleditch637df7f2009-03-15 12:57:32 -0400312 LIBTELNET_EV_SUBNEGOTIATION:
313 Triggered whenever a TELNET sub-negotiation has been received.
Sean Middleditch892c5f12009-03-14 13:39:07 -0400314 Sub-negotiations include the NAWS option for communicating
315 terminal size to a server, the NEW-ENVIRON and TTYPE options
316 for negotiating terminal features, and MUD-centric protocols
317 such as ZMP, MSSP, and MCCP2.
318
Sean Middleditch637df7f2009-03-15 12:57:32 -0400319 The event->telopt value is the option under sub-negotiation.
320 The remaining data (if any) is passed in event->buffer and
321 event->size. Note that most subnegotiation commands can
322 include embedded NUL bytes in the subnegotiation data, and
323 the data event->buffer is not NUL terminated, so always use
324 the event->size value!
Sean Middleditch892c5f12009-03-14 13:39:07 -0400325
Sean Middleditch637df7f2009-03-15 12:57:32 -0400326 The meaning and necessary processing for subnegotiations are
327 defined in various TELNET RFCs and other informal
328 specifications. A subnegotiation should never be sent unless
329 the specific option has been enabled through the use of the
330 telnet negotiation feature.
Sean Middleditch892c5f12009-03-14 13:39:07 -0400331
Sean Middleditch637df7f2009-03-15 12:57:32 -0400332 LIBTELNET_EV_COMPRESS
333 The COMPRESS event notifies the app that COMPRESS2/MCCP2
334 compression has begun or ended. Only servers can send compressed
335 data, and hence only clients will receive compressed data.
Sean Middleditchb9e48642009-03-12 23:33:27 -0400336
Sean Middleditch637df7f2009-03-15 12:57:32 -0400337 The event->command value will be 1 if compression has started and
338 will be 0 if compression has ended.
Sean Middleditch16992272009-03-15 19:42:03 -0400339
340 LIBTELNET_EV_WARNING
341 The WARNING event is sent whenever something has gone wrong
342 inside of libtelnet (possibly due to malformed data sent by the
343 other end) but which recovery is (likely) possible. It may be
344 safe to continue using the connection, but some data may have
345 been lost or incorrectly interpreted.
Sean Middleditch637df7f2009-03-15 12:57:32 -0400346
347 The event->buffer value will contain a NUL terminated string
348 explaining the error, and the event->size value containers the
349 length of the string.
350
Sean Middleditch16992272009-03-15 19:42:03 -0400351 LIBTELNET_EV_ERROR
352 Similar to the WARNING event, the ERROR event is sent whenever
353 something has gone wrong. ERROR events are non-recoverable,
354 however, and the application should immediately close the
355 connection. Whatever has happened is likely going only to
356 result in garbage from libtelnet. This is most likely to
357 happen when a COMPRESS2 stream fails, but other problems can
358 occur.
359
360 The event->buffer value will contain a NUL terminated string
361 explaining the error, and the event->size value containers the
362 length of the string.
Sean Middleditch637df7f2009-03-15 12:57:32 -0400363
364III. INTEGRATING LIBTELNET WITH COMMON MUDS
Sean Middleditchb9e48642009-03-12 23:33:27 -0400365=====================================================================
366
Sean Middleditch637df7f2009-03-15 12:57:32 -0400367FIXME: fill in some notes about how to splice in libtelnet with
368common Diku/Merc/Circle/etc. MUD codebases.
Sean Middleditchb9e48642009-03-12 23:33:27 -0400369
Sean Middleditch892c5f12009-03-14 13:39:07 -0400370IV. SAFETY AND CORRECTNESS CONSIDERATIONS
Sean Middleditchb9e48642009-03-12 23:33:27 -0400371=====================================================================
372
Sean Middleditch892c5f12009-03-14 13:39:07 -0400373Your existing application may make heavy use of its own output
374buffering and transmission commands, including hand-made routines
375for sending TELNET commands and sub-negotiation requests. There are
376at times subtle issues that need to be handled when communication
377over the TELNET protocol, not least of which is the need to escape
378any byte value 0xFF with a special TELNET command.
Sean Middleditchb9e48642009-03-12 23:33:27 -0400379
Sean Middleditch892c5f12009-03-14 13:39:07 -0400380For these reasons, it is very important that applications making use
381of libtelnet always make use of the libtelnet_send_*() family of
382functions for all data being sent over the TELNET connection.
383
Sean Middleditch637df7f2009-03-15 12:57:32 -0400384In particular, if you are writing a client, all user input must be
385passed through to libtelnet_send_data(). This also includes any
386input generated automatically by scripts, triggers, or macros.
387
388For a server, any and all output -- including ANSI/VT100 escape
389codes, regular text, newlines, and so on -- must be passed through
390to libtelnet_send_data().
391
392Any TELNET commands that are to be sent must be given to one of the
393following: libtelnet_send_command, libtelnet_send_negotiate, or
394libtelnet_send_subnegotiation().
395
396If you are attempting to enable COMPRESS2/MCCP2, you must use the
397libtelnet_begin_compress2() function.
398
Sean Middleditch892c5f12009-03-14 13:39:07 -0400399V. MCCP2 COMPRESSION
Sean Middleditchb9e48642009-03-12 23:33:27 -0400400=====================================================================
401
Sean Middleditch892c5f12009-03-14 13:39:07 -0400402The MCCP2 (COMPRESS2) TELNET extension allows for the compression of
403all traffic sent from server to client. For more information:
404
405 http://www.mudbytes.net/index.php?a=articles&s=mccp
406
Sean Middleditch637df7f2009-03-15 12:57:32 -0400407In order for libtelnet to support MCCP2, zlib must be installed and
408enabled when compiling libtelnet. Use -DHAVE_ZLIB to enable zlib
409when compiling libtelnet.c and pass -lz to the linker to link in the
410zlib shared library.
411
Sean Middleditch892c5f12009-03-14 13:39:07 -0400412libtelnet transparently supports MCCP2. For a server to support
413MCCP2, the application must begin negotiation of the COMPRESS2
414option using libtelnet_send_negotiate(), for example:
415
416 libtelnet_send_negotiate(&telnet, LIBTELNET_WILL,
417 LIBTELNET_OPTION_COMPRESS2, user_data);
418
Sean Middleditch5b5bc922009-03-15 23:02:10 -0400419If a favorable DO COMPRESS2 is sent back from the client then the
420server application can begin compression at any time by calling
421libtelnet_begin_compress2().
Sean Middleditch892c5f12009-03-14 13:39:07 -0400422
Sean Middleditch637df7f2009-03-15 12:57:32 -0400423If a connection is in PROXY mode and COMPRESS2 support is enabled
424then libtelnet will automatically detect the start of a COMPRESS2
425stream, in either the sending or receiving direction.
Sean Middleditch892c5f12009-03-14 13:39:07 -0400426
427VI. TELNET PROXY UTILITY
428=====================================================================
429
430The telnet-proxy utility is a small application that serves both as
431a testbed for libtelnet and as a powerful debugging tool for TELNET
432servers and clients.
433
434To use telnet-proxy, you must first compile it using:
435
436 $ make
437
438If you do not have zlib installed and wish to disable MCCP2 support
439then you must first edit the Makefile and remove the -DHAVE_ZLIB and
440the -lz from the compile flags.
441
Sean Middleditchd88f1832009-03-15 01:06:17 -0400442To run telnet-proxy, you simply give it the server's host name or
443IP address, the server's port number, and the port number that
444telnet-proxy should listen on. For example, to connect to the server
445on mud.example.com port 7800 and to listen on port 5000, run:
Sean Middleditch892c5f12009-03-14 13:39:07 -0400446
Sean Middleditchd88f1832009-03-15 01:06:17 -0400447 $ ./telnet-proxy mud.example.com 7800 5000
Sean Middleditch892c5f12009-03-14 13:39:07 -0400448
449You can then connect to the host telnet-proxy is running on (e.g.
Sean Middleditchd88f1832009-03-15 01:06:17 -0400450127.0.0.1) on port 500 and you will automatically be proxied into
451mud.example.com.
Sean Middleditch892c5f12009-03-14 13:39:07 -0400452
453telnet-proxy will display status information about the data
Sean Middleditchaefcd0c2009-03-15 13:16:44 -0400454passing through both ends of the tunnel. telnet-proxy can only
455support a single tunnel at a time. It will continue running until
456an error occurs or a terminating signal is sent to the proxy
457process.