dest-unreach / socat / contrib / rfc2217

RFC2217 feature

Introduction

RFC 2217 describes an extension to the telnet protocol that specifies transfer of serial line parameters like baud rate and parity over the network.

Kenneth Kassing contributed a patch to socat that adds support for RFC 2217 controls on a tty/pty and that allows to synchronize the attributes of two tty/pty devices locally or on different hosts.

Requisites

Apply this patch to socat 1.6.0.0 source.

Download

socat-1.6.0.0-rfc2217.patch.gz

Alternatively, this patch is available as branch socat-rfc2217 in git://repo.or.cz/socat.git and http://repo.or.cz/r/socat.git.

Status

While this contribution adds an extremely useful feature, it does not fit well socat's modulare concept. Therefore there are currently no plans to directly integrate it into socat mainstream; parts of it might, however, be reused for a better conforming solution.

Notes

In the file download, documentation of the new features is described in the man page socat.1 only.

Message of the contributor

Hi Gerhard,
Thanks for your response and suggestions.  I have made some updates to
reflect your suggestions.


Attached is an initial patch to socat 1.6.0.0 to support the features I
mentioned in my previous email.  Additionally, I have included a change
log below.  I have done some extensive testing to the code I added, but
I expect I may find some bugs in the next few weeks and I will send
further updates if I do.

I would like very much to see these updates make it into upcoming
releases, and I am willing to assist you with supporting them.

Thanks
Ken Kassing


CHANGELOG
----------------
* Update doc/socat.1, EXAMPLES
  * Add documentation and examples for the TELNET/RF2217 features
 * Update Makefile.in, configure.in, configure, config.h.in
  * Modify build logic to support the TELNET/RF2217 features
 * Update socat.c
  * Add '-p- command line option to support continually polling the
sockets for updates to the TERMIOS structure
  * Add call to 'termios_updatePorts' in the transfer loop.  This will
check for changes to the TERMIOS structure for both sockets and update
them as needed.
 * Update xio-openssl.h and xio-openssl.c
  * Make 'xioopen_openssl_connect' and 'xioopen_openssl_listen'
functions externally linkable
 * Update xio-termios.h, xio-termios.c, xioopts.h, and xioopts.c
  * Add 'control', 'read' and 'nomodem' options
 * Update xio.h
  * Add XIOREAD_TELNET, XIOWRITE_TELNET, and XIODATA_TELNET
  * Add termios control structure
  * Add telnet control structure
 * Update xioread.c and xiowrite.c
  * Add support for XIOREAD_TELNET and XIOWRITE_TELNET
 * Update xioopen.c
  * Add TELNET, TELNET-LISTEN, TELNET-SSL, and TELNET-SSL-LISTEN address
variants
 * Add termioscls.h and termioscls.c
  * Utility calls that handle the TERMIOS structure operations
 * Add xio-telnet.h and xio-telnet.h
  * Defines the XIO functions that supports the telnet address types
  * Handle the telnet options (including the RFC2217 extension)


Gerhard Rieger wrote:

> Kenneth Kassing wrote:

>> Hello,
>> I am working on making some updates to socat that primarily involve
>> adding a new address type, but also include adding a couple options to
>> the TERMIOS option group.
>>
>> The address type I am adding is an implementation of RFC2217 Telnet Com
>> Port Control Option.  This is basically an extension to telnet that
>> allows baud rate, parity, etc to transmitted to the remote server.
>>
>> The most common application for this will be to redirect a com port on
>> one device to another device.  This will involve a socat instance
>> running on each device.
>>
>> The server device will bind to the physical tty, and listen on a TCP
>> port.  The second device will connect to the remote TCP port, and create
>> a pseudo tty.  The end goal of this setup will allow programs running
>> locally (ie.. minicom, kermit, or stty) to change the baud rate of the
>> pseudo tty and have the change propagate to the real tty on the remote
>> device.
>>
>> To actually accomplish this propagation, I added two options to the
>> TERMIOS option group ("control" and "read").  In addition I added a
>> function call to the data loop that will check for updates to the
>> termios structure and propagate them.  These options allow a user to
>> seperately enable the system to read termios changes or write them back
>> to the address type.  (NOTE: Control assumes read.)
>>
>> Usage/Testing examples:
>>
>> Here is an example that tests the termios prorogation code for a simple
>> case.  This is probably not a real usage case for socat.
>>
>> # socat -T 5 -R PTY,link=/dev/ttyR0,raw,group=dialout,mode=660,control
>> PTY,link=/dev/ttyR1,raw,group=dialout,mode=660,control
>> # stty -F /dev/ttyR0 speed; stty -F /dev/ttyR1 speed
>> 38400
>> 38400
>> # stty -F /dev/ttyR0 19200
>> # stty -F /dev/ttyR0 speed; stty -F /dev/ttyR1 speed
>> 19200
>> 19200
>>
>> NOTE: I added the "-R" option to prevent socat from exiting after the
>> idle timeout, so the option string "-T 5 -R" will cause socat to repeat
>> the data loop every 5 seconds.   I do this mainly for testing purposes
>> so it will read and propagate the termios changes without any data being
>> transmitted.
>>
>>
>> Here is an example of starting the RCF2217 server
>>
>> # socat -T 5 -R telnet-listen:30000,fork /dev/ttyS0,raw,echo=0,control
>>
>>
>> Here is an example of starting the RCF2217 client
>>
>> # socat -T 5 -R PTY,link=/dev/ttyR0,raw,group=dialout,mode=660,read
>> telnet:localhost:30000
>>
>>
>>
>>
>>
>>
>> I have a couple questions I would like your opinion on.
>>
>> 1. The only way I have found so far to collect the termios information
>> is to poll it from the data loop.  (Ie... With the Tcgetattr function.)
>>  Currently I am using the global timer option to cause the data loop to
>> escape and read the termios info.  This may not be required in the
>> normal case where data is passed regularly.  (I added a command line
>> option that prevents the -T option from exiting.)  Are you aware of a
>> better method for this?

> I recommend that you check how the ignoreeof option performs polls in
> the transfer loop; this would keep the -T for its original purpose.

>> 2. The RFC2217 is basically a RAW TCP connection that internally escapes
>> some data.  Because of this, I am calling 'xioopen_ipapp_connect' and
>> 'xioopen_ipapp_listen' from my respective connect and listen functions.
>>  I did this to avoid recoding all the TCP stuff in the hopes that it
>> would help keep the code more maintainable in the future.  Do you have
>> any issues with this approach?

> Using these functions is the best way to implement TCP or UDP based
> addresses in socat - but see below.

>> 3. I intend use the OpenSSL functions in the same way I used TCP above.
>>   Do you have any issues with this approach?

> See answer below.

>> 4. Have you considered devising an API that would allow address types to
>> wrap some other object like item #2 and #3?  I see potential for
>> wrapping other higher layer protocols in a similar manner.

> Yes, I am currently extending socat to support invocations like these:
> 
> socat stdio 'ssl|proxy:...|tcp:host:port'
> 
> or:
> 
> socat tcp-l:port,fork 'ssl-l,cert=...|exec:script'
> 
> which means that bidirectional pipes will be possible in socat.
> For your work I recommend that you strictly separate the telnet protocol
> from TCP. I think the best aproach would be to derive the TELNET address
> from the PTY address or the OPEN address with TERMIOS support; this will
> give it direct access to the pty/tty, while the networking part can be
> fulfilled by already existing addresses.