diff --git a/README b/README index bcb55c8..dc332a3 100644 --- a/README +++ b/README @@ -110,6 +110,11 @@ IIc. Sending Data Sends a single "simple" TELNET command, such as the GO-AHEAD commands (255 249). + void libtelnet_send_command(libtelnet_t *telnet, unsigned char cmd, + unsigned char telopt); + Sends a TELNET command with an option code following. This is + only useful for the WILL, WONT, DO, DONT, and SB commands. + void libtelnet_send_negotiate(libtelnet_t *telnet, unsigned char cmd, unsigned char opt); Sends a TELNET negotiation command. The cmd parameter must be @@ -123,10 +128,23 @@ IIc. Sending Data a server or the user input from a client. void libtelnet_send_subnegotiation(libtelnet_t *telnet, - unsigned char opt, unsigned char *buffer, unsigned int size); - Sends a TELNET sub-negotiation command. The opt parameter + unsigned char telopt, unsigned char *buffer, unsigned int size); + Sends a TELNET sub-negotiation command. The telopt parameter is the sub-negotiation option. + Note that the above function is just a shorthand for: + libtelnet_send_telopt(telnet, LIBTELNET_SB, telopt); + libtelnet_send_data(telnet, buffer, size); + libtelnet_send_command(telnet, LIBTELNET_SE); + + For some subnegotiations that involve a lot of complex formatted + data to be sent, it may be easier to manually send the SB telopt + header and SE footer around mulitple calls to send_data. + + NOTE: libtelnet_send_subrequest() does have special behavior in + PROXY mode, as in that mode this function will automatically + detect the COMPRESS2 marker and enable zlib compression. + IId. Event Handling libtelnet relies on an event-handling mechanism for processing diff --git a/libtelnet.c b/libtelnet.c index 5bf5295..cf786a9 100644 --- a/libtelnet.c +++ b/libtelnet.c @@ -206,13 +206,6 @@ void _set_rfc1143(libtelnet_t *telnet, libtelnet_rfc1143_t q) { telnet->q[telnet->q_size++] = q; } -/* send a negotiation without going through the RFC1143 checks */ -static void _send_negotiate(libtelnet_t *telnet, unsigned char cmd, - unsigned char opt) { - unsigned char bytes[3] = { LIBTELNET_IAC, cmd, opt }; - _send(telnet, bytes, 3); -} - /* negotiation handling magic for RFC1143 */ static void _negotiate(libtelnet_t *telnet, unsigned char cmd, unsigned char telopt) { @@ -249,9 +242,9 @@ static void _negotiate(libtelnet_t *telnet, unsigned char cmd, if (_event(telnet, LIBTELNET_EV_WILL, cmd, telopt, 0, 0) == 1) { q.him = RFC1143_YES; _set_rfc1143(telnet, q); - _send_negotiate(telnet, LIBTELNET_DO, telopt); + libtelnet_send_telopt(telnet, LIBTELNET_DO, telopt); } else - _send_negotiate(telnet, LIBTELNET_DONT, telopt); + libtelnet_send_telopt(telnet, LIBTELNET_DONT, telopt); break; case RFC1143_YES: break; @@ -274,7 +267,7 @@ static void _negotiate(libtelnet_t *telnet, unsigned char cmd, case RFC1143_WANTYES_OP: q.him = RFC1143_WANTNO; _set_rfc1143(telnet, q); - _send_negotiate(telnet, LIBTELNET_DONT, telopt); + libtelnet_send_telopt(telnet, LIBTELNET_DONT, telopt); break; } break; @@ -287,7 +280,7 @@ static void _negotiate(libtelnet_t *telnet, unsigned char cmd, case RFC1143_YES: q.him = RFC1143_NO; _set_rfc1143(telnet, q); - _send_negotiate(telnet, LIBTELNET_DONT, telopt); + libtelnet_send_telopt(telnet, LIBTELNET_DONT, telopt); _event(telnet, LIBTELNET_EV_WONT, 0, telopt, 0, 0); break; @@ -318,9 +311,9 @@ static void _negotiate(libtelnet_t *telnet, unsigned char cmd, if (_event(telnet, LIBTELNET_EV_DO, cmd, telopt, 0, 0) == 1) { q.us = RFC1143_YES; _set_rfc1143(telnet, q); - _send_negotiate(telnet, LIBTELNET_WILL, telopt); + libtelnet_send_telopt(telnet, LIBTELNET_WILL, telopt); } else - _send_negotiate(telnet, LIBTELNET_WONT, telopt); + libtelnet_send_telopt(telnet, LIBTELNET_WONT, telopt); break; case RFC1143_YES: break; @@ -343,7 +336,7 @@ static void _negotiate(libtelnet_t *telnet, unsigned char cmd, case RFC1143_WANTYES_OP: q.us = RFC1143_WANTNO; _set_rfc1143(telnet, q); - _send_negotiate(telnet, LIBTELNET_WONT, telopt); + libtelnet_send_telopt(telnet, LIBTELNET_WONT, telopt); break; } break; @@ -356,7 +349,7 @@ static void _negotiate(libtelnet_t *telnet, unsigned char cmd, case RFC1143_YES: q.us = RFC1143_NO; _set_rfc1143(telnet, q); - _send_negotiate(telnet, LIBTELNET_WONT, telopt); + libtelnet_send_telopt(telnet, LIBTELNET_WONT, telopt); _event(telnet, LIBTELNET_EV_DONT, 0, telopt, 0, 0); break; case RFC1143_WANTNO: @@ -673,6 +666,13 @@ void libtelnet_send_command(libtelnet_t *telnet, unsigned char cmd) { _send(telnet, bytes, 2); } +/* send an iac command with telopt */ +void libtelnet_send_telopt(libtelnet_t *telnet, unsigned char cmd, + unsigned char telopt) { + unsigned char bytes[3] = { LIBTELNET_IAC, cmd, telopt }; + _send(telnet, bytes, 3); +} + /* send negotiation */ void libtelnet_send_negotiate(libtelnet_t *telnet, unsigned char cmd, unsigned char telopt) { @@ -814,10 +814,9 @@ void libtelnet_send_data(libtelnet_t *telnet, unsigned char *buffer, } /* send sub-request */ -void libtelnet_send_subnegotiation(libtelnet_t *telnet, unsigned char opt, +void libtelnet_send_subnegotiation(libtelnet_t *telnet, unsigned char telopt, unsigned char *buffer, unsigned int size) { - libtelnet_send_command(telnet, LIBTELNET_SB); - libtelnet_send_data(telnet, &opt, 1); + libtelnet_send_telopt(telnet, LIBTELNET_SB, telopt); libtelnet_send_data(telnet, buffer, size); libtelnet_send_command(telnet, LIBTELNET_SE); @@ -826,8 +825,7 @@ void libtelnet_send_subnegotiation(libtelnet_t *telnet, unsigned char opt, * make sure all further data is compressed if not already. */ if (telnet->flags & LIBTELNET_FLAG_PROXY && - telnet->z == 0 && - opt == LIBTELNET_TELOPT_COMPRESS2) { + telopt == LIBTELNET_TELOPT_COMPRESS2) { if (_init_zlib(telnet, 1, 1) != LIBTELNET_EOK) return; @@ -852,5 +850,8 @@ void libtelnet_begin_compress2(libtelnet_t *telnet) { * the compress marker itself being compressed. */ _event(telnet, LIBTELNET_EV_SEND, 0, 0, compress2, sizeof(compress2)); + + /* notify app that compression was successfully enabled */ + _event(telnet, LIBTELNET_EV_COMPRESS, 1, 0, 0, 0); #endif /* HAVE_ZLIB */ } diff --git a/libtelnet.h b/libtelnet.h index 8db4d6c..e27dc3e 100644 --- a/libtelnet.h +++ b/libtelnet.h @@ -200,7 +200,14 @@ extern void libtelnet_push(libtelnet_t *telnet, unsigned char *buffer, /* send an iac command */ extern void libtelnet_send_command(libtelnet_t *telnet, unsigned char cmd); -/* send negotiation */ +/* send an iac command with a telopt */ +extern void libtelnet_send_telopt(libtelnet_t *telnet, unsigned char cmd, + unsigned char telopt); + +/* send negotiation, with RFC1143 checking. + * will not actually send unless necessary, but will update internal + * negotiation queue. + */ extern void libtelnet_send_negotiate(libtelnet_t *telnet, unsigned char cmd, unsigned char opt); @@ -208,9 +215,15 @@ extern void libtelnet_send_negotiate(libtelnet_t *telnet, unsigned char cmd, extern void libtelnet_send_data(libtelnet_t *telnet, unsigned char *buffer, unsigned int size); -/* send sub-request */ +/* send sub-request, equivalent to: + * libtelnet_send_telopt(telnet, LIBTELNET_SB, telopt) + * libtelnet_send_data(telnet, buffer, size); + * libtelnet_send_command(telnet, LIBTELNET_SE); + * manually generating sequence may be easier for complex subnegotiations + * thare are most easily implemented with a series of send_data calls. + */ extern void libtelnet_send_subnegotiation(libtelnet_t *telnet, - unsigned char opt, unsigned char *buffer, unsigned int size); + unsigned char telopt, unsigned char *buffer, unsigned int size); /* begin sending compressed data (server only) */ extern void libtelnet_begin_compress2(libtelnet_t *telnet);