This chapter is for application programmers. It describes the TELNET library routines.
The TELNET library routines provide a programming interface to the TELNET protocol. Use the TELNET library routines in your own applications to provide TELNET capabilities.
This chapter does not describe the TELNET protocol.
The following routines are included in the library:
TEL_ABORT_CONNECTION |
Aborts a TELNET connection |
TEL_ALLOCATE_CCB |
Allocates a connection control block (CCB) |
TEL_CLOSE_CONNECTION |
Closes a TELNET connection |
TEL_CREATE_TERMINAL |
Opens and allocates a TELNET device |
TEL_DEALLOCATE_CCB |
Deallocates a CCB |
TEL_GET_CCB |
Gets the value of a CCB field |
TEL_OPEN_CONNECTION |
Opens a TELNET connection |
TEL_RECEIVE_DATA |
Receives data |
TEL_SEND_COMMAND |
Sends TELNET commands |
TEL_SEND_DATA |
Sends data |
TEL_SET_CCB |
Sets the value of a CCB field |
These routines allow you to establish and maintain TELNET connections with remote hosts that support the TELNET protocol. You can establish multiple simultaneous TELNET connections; the number is limited only by the resources available to your process.
The TELNET library routines follow the standard OpenVMS conventions for modular library routines. See the OpenVMS documentation on calling modular libraries for more information.
Because TELNET library routines use asynchronous system traps (ASTs), application programs must not run with ASTs disabled for long periods of time.
The TELNET library routines are in the TCPWARE:TELLIB.OLB object library. The symbolic definitions for the various connection control block (CCB) fields are in the TCPWARE_INCLUDE:_CCBFLD.H header file. While this file is written for C, it is easy to convert to other languages.
The TELNET client sample program is provided in TCPWARE_COMMON:[TCPWARE.EXAMPLES]TELNET_SAMPLE.C.
To build using DEC C, enter:
$ CC/DECC/PREFIX=ALL TELNET_SAMPLE.C
$ LINK FTPSAMPLE,
SYS$INPUT/OPTIONS TCPWARE:TELLIB/LIB -
_$ SYS$SHARE:TCPWARE_SOCKLIB_SHR/SHARE
To build using VAX C, enter:
$ CC/VAXC/PREFIX=ALL TELNET_SAMPLE.C
$ LINK FTPSAMPLE,
SYS$INPUT/OPTIONS TCPWARE:TELLIB/LIB -
_$ SYS$SHARE:TCPWARE_SOCKLIB_SHR/SHARE
-
_$ SYS$SHARE:VAXCRTL.EXE/SHARE
This section describes the connection control block (CCB) that contains all the information required to establish and maintain a TELNET connection. Each open connection requires a CCB.
The storage space for the CCB is allocated dynamically. Therefore, the number of simultaneous connections is limited only by your process resources. A CCB can be reused; you can close one connection and then open a new one using the same CCB.
Note: The ccb-ptr argument in the library routines must remain in scope at a fixed address. Also, the ccb-ptr is to be used with a single CCB from the time of TEL_ALLOCATE_CCB to TEL_DEALLOCATE_CCB.
|
You can access the CCB fields with the TEL_GET_CCB and TEL_SET_CCB library routines as described below. The below table lists the CCB fields and their uses:
CCB Fields |
CCB Uses |
CCB_ASTRTN |
Address of the AST routine to be called when data is received (unsigned longword). Cleared once the AST is declared. You must explicitly reset this field each time you want the AST to be used. Use with TEL_GET_CCB or TEL_SET_CCB, or with TEL_OPEN_CONNECTION. |
CCB_CHAN |
Channel number for the TCP0: device (unsigned word), defined only when a connection is open (otherwise 0). (Use the CCB_ISOPEN field described below to determine if a connection is open instead of checking for a non-zero channel number.) Use with TEL_GET_CCB. |
CCB_CMDRTN |
Address of your TELNET command processing routine that you must use with TEL_OPEN_CONNECTION (unsigned longword). Also use with TEL_GET_CCB or TEL_SET_CCB. |
CCB_EF |
Event flag number to set when there is received data (unsigned longword). Can also be used as an argument to TEL_OPEN_CONNECTION. Use event flag 0 to disable the use of an event flag. Use with TEL_GET_CCB. |
CCB_ISOPEN |
Connection status (unsigned byte). Value is 1 if the connection is open, 0 if not. Use with TEL_GET_CCB. |
CCB_LIA |
Connection's local internet address (unsigned longword), in internet byte order (for example, internet address 1.2.3.4 is stored as 04030201 hex). Valid only when a connection is open. Use with TEL_GET_CCB. |
CCB_LPORT |
Local port number for the connection (unsigned word). Valid only when a connection is open. Use with TEL_GET_CCB. |
CCB_RCVBCT |
Total byte count for the connection (unsigned longword). The counter wraps with an overflow. Use with TEL_GET_CCB. |
CCB_RCVBCNT |
Number of unread bytes in the internal receive buffer that reflects the amount of raw data in the internal buffer (unsigned word). May be larger than the actual number of user data bytes you read due to requirements of the TELNET protocol. Use with TEL_GET_CCB. |
CCB_RCVIOC |
Total count of internal network read operations performed for the connection (unsigned longword). The counter wraps with an overflow. Use with TEL_GET_CCB. |
CCB_RIA |
Connection's remote internet address (unsigned longword), in internet byte order (for example, internet address 1.2.3.4 is stored as 04030201 hex). Can be set only when used as an argument to TEL_OPEN_CONNECTION. Use with TEL_GET_CCB. |
CCB_RPORT |
Remote port number for the connection (unsigned word), the default being 23 (for the TELNET server). You can only set this field when specified as an argument to TEL_OPEN_CONNECTION. Valid only when a connection is open. Use with TEL_GET_CCB. |
CCB_SNDBCNT |
Number of untransmitted bytes in the internal send buffer (unsigned word) that reflects the amount of raw data in the internal buffer. May be larger than the actual number of user data bytes you send due to requirements of the TELNET protocol. Use with TEL_GET_CCB. |
CCB_SNDBCT |
Total count of bytes sent for the connection (unsigned longword). The counter wraps with an overflow. Use with TEL_GET_CCB. |
CCB_SNDIOC |
Total count of internal write operations for the connection (unsigned longword). The counter wraps with an overflow. Use with TEL_GET_CCB. |
CCB_TIMO |
Time-out value (in seconds) for the connection (unsigned longword), the default being 120 seconds (2 minutes). Can also be used as an argument to TEL_OPEN_CONNECTION. Use with TEL_GET_CCB. |
CCB_UFLAGS |
Communicates state information between the user's application and the library routines (unsigned longword). The below table lists the only defined bits. All other bits are reserved and must be zero. Your program should set and clear bits 0 and 1 in this field when TELNET negotiates the TRANSMIT-BINARY option. Use with TEL_GET_CCB or TEL_SET_CCB. |
CCB_USER1 |
User-definable (unsigned longword). Use with TEL_GET_CCB or TEL_SET_CCB. |
CCB_USER2 |
User-definable (unsigned longword). Use with TEL_GET_CCB or TEL_SET_CCB. |
If you want to enable SYNCH signal processing mode, set bit 31 before opening a connection. The TELNET library routines enter this mode when they receive urgent data. They remain in this mode until they encounter the TELNET DATA MARK command and no more urgent data exists. In this mode, TEL_RECEIVE_DATA discards all data and the EC and EL commands. All other TELNET commands are passed to your command processing routine.
Bit... |
If set, means... |
0 |
Enables local binary mode |
1 |
Enables remote binary mode |
31 |
Enables SYNCH signal processing |
The TELNET library routines use additional fields internally that are not accessible to application programs.
This section describes each of the TELNET library routines.
All scalar and buffer arguments are passed by reference. Strings are passed by descriptor. You must use all function arguments, although you can omit some optional ones by passing a 0 (by value).
Each TELNET library routine returns an unsigned longword condition value in R0 and use the standard system service return codes defined in the $SSDEF macro.
The function arguments are described using the following "dot" notation:
argument-name.access-data-type.passing-mechanism parameter-form
For example, the following argument specification indicates the CCB address pointer, having modify access and a passing mechanism by reference:
ccb-ptr.ma.r
See the OpenVMS Run-Time Library documentation for a complete description of this procedure argument notation.
These routines are included in the TCPWARE:TELLIB.OLB object library. You must also include the Socket Library when linking.
See the beginning of this chapter for details on linking.
Aborts a connection.
ret-status.wlc.v = TEL_ABORT_CONNECTION(u_long *ccb-ptr);
ccb-ptr
Address of a pointer to the connection control block (CCB) used by all the TELNET library routines to identify a connection.
Aborts the TELNET connection, cancels all outstanding sends and receives, and returns the SS$_VCBROKEN status.
SS$_NORMAL |
Connection aborted (connection closed) |
Allocates a connection control block (CCB).
ret-status.wlc.v = TEL_ALLOCATE_CCB(ccb-ptr,rcv-buf-size,snd-buf-size);
ccb-ptr
Address of an unsigned longword that will receive a pointer to the CCB used by all the TELNET library routines to identify a connection.
rcv-buf-size
Address of an unsigned word containing the number of bytes allocated to the internal receive buffer. There is no minimum buffer size by default. However, use at least 64 bytes as an absolute minimum, with 1024 bytes recommended to enhance performance.
snd-buf-size
Address of an unsigned word containing the number of bytes allocated to the internal send buffer. There is no minimum buffer size by default. However, use at least 64 bytes as an absolute minimum, with 1024 bytes recommended to enhance performance.
Allocates memory for a CCB using the LIB$GET_VM routine. Memory is allocated from the default zone. The CCB and the internal buffers are contiguous in memory. An internal local event flag will also be allocated from the second local event flag cluster.
You should only access the CCB data fields using the TEL_GET_CCB and TEL_SET_CCB routines. You must allocate a CCB before calling any other TELNET library routine.
Any condition value returned by LIB$GET_VM and LIB$GET_EF.
Closes a TELNET connection.
ret-status.wlc.v = TEL_CLOSE_CONNECTION(ccb-ptr);
ccb-ptr
Address of a pointer to the CCB.
Call this routine when you finished sending data to the remote host or when the remote host notifies you that it closed its end of the connection.
This routine initiates a close on the local end of an open connection. For a connection to be fully closed, both ends of the connection (local and remote) must be closed. No more data can be sent or received once a connection is fully closed.
Additional data can be received until the remote end closes its side of the connection. Therefore, you must call the TEL_RECEIVE_DATA routine until the SS$_VCCLOSED status is returned.
Here are the two typical close situations:
Remote end closes first |
TEL_RECEIVE_DATA returns the SS$_VCCLOSED status, then you call TEL_CLOSE_CONNECTION to close your end of the connection. TEL_CLOSE_CONNECTION returns when the connection is fully closed. |
Local end closes first |
You call TEL_CLOSE_CONNECTION to close your end of the connection. TEL_CLOSE_CONNECTION returns, but the remote end of the connection is still open. You must call TEL_RECEIVE_DATA until it returns the SS$_VCCLOSED status. |
In general TEL_RECEIVE_DATA must return SS$_VCCLOSED. This can happen before or after you call TEL_CLOSE_CONNECTION.
SS$_ILLSEQOP |
Connection not open |
SS$_NORMAL |
Success, close initiated or successful |
SS$_THIRDPARTY |
Software was shut down (connection closed) |
SS$_TIMEOUT |
Connection timed out (connection closed) |
SS$_VCBROKEN |
Connection broken (connection closed) |
Opens and allocates a connection to an NTA device so that you can use a terminal device with TELNET.
ret-status.wlc.v = TEL_CREATE_TERMINAL(ccb-ptr, [ia], [host], cmd-rtn, [efn], [ast-addr], [port], [timeout], [flags]);
ccb-ptr
Address of a pointer to the CCB. The CCB must be in a closed state.
ia
Address of an unsigned longword containing the remote host's internet address in internet byte order (for example, internet address 1.2.3.4 is stored as 04030201 hex). If omitted or 0, the host argument determines the remote host.
host
Address of a text string descriptor of the remote host's host name. If the string is a valid a.b.c.d type internet address, that address is used. Otherwise, the Socket Library's gethostbyname routine determines the internet address from the host name. If omitted or a null string, the ia argument determines the remote host.
cmd-rtn
Address of the user's command processing routine called each time a TELNET command is received. Inputs to the command processing routine are the CCB of the connection, a buffer containing one complete command, and a buffer byte count.
efn
Address of an unsigned longword containing the event flag to use. The event flag is set whenever data is available in the receive buffer, and cleared when the last byte of data is removed. It is up to you to allocate the event flag if necessary. You must never set or clear the event flag. If omitted, the previous value of this field is used; if 0, the field is cleared. If no event flag is specified, you will have to use another method, such as an AST routine, to determine when data is received.
ast-adr
Address of an AST routine to be called when data is received. This AST routine is declared when received data is available. You must set the ast-adr each time you want to be notified of received data. Use the TEL_SET_CCB routine to set the ast-adr after a connection is open.
A pointer to the CCB is passed to the AST routine by reference as the AST argument. You can use the CCB_USER1 and CCB_USER2 fields if you want to pass arguments to the AST routine.
port
Address of an unsigned word containing the 16-bit port number for the connection (normally 23). Supplied for use in special applications where the remote server is not a standard TELNET server. If omitted or 0, the default value 23 is used.
timeout
Address of an unsigned longword with the number of seconds to wait on the connection before timeout. If omitted or 0, the default value 120 (2 minutes) is used.
Call this routine when you want to open and allocate a connection to an NTA device so that you can use a terminal device with TELNET.
Deallocates a CCB.
ret-status.wlc.v = TEL_DEALLOCATE_CCB(ccb-ptr);
ccb-ptr
Address of a pointer to the CCB.
Gets rid of a CCB you no longer need. The CCB is deallocated when it is fully closed. An implicit abort is performed on the connection if the CCB is still in use.
The virtual memory and event flag reserved for the CCB by the TEL_ALLOCATE_CCB routine is freed when this routine completes.
SS$_NORMAL |
Success |
Gets information from a CCB field.
ret-status.wlc.v = TEL_GET_CCB(ccb-ptr, field-code, value);
ccb-ptr
Address of a pointer to the CCB. The CCB for the connection does not need to be open unless otherwise specified.
field-code
Address of an unsigned word containing the symbolic value for the CCB field. The symbolic definitions for the CCB fields are in the TCPWARE_INCLUDE:_CCBFLD.H file.
value
Address of a variable that receives the value of the CCB field. The data type of this variable depends on the field requested in field-code.
The value of the CCB field you requested is returned in the argument value. The data type of value should be the same as the field you requested.
SS$_BADPARAM |
Bad field-code specified |
SS$_NORMAL |
Normal, successful completion |
Opens a TELNET connection to a remote host.
ret-status.wlc.v = TEL_OPEN_CONNECTION(ccb-ptr, [ia], [host], cmd-rtn, [efn], [ast-adr], [port], [timeout]);
ccb-ptr
Address of a pointer to the CCB.
ia
Address of an unsigned longword containing the remote host's internet address in internet byte order (for example, internet address 1.2.3.4 is stored as 04030201 hex). If omitted or 0, the host argument determines the remote host name.
host
Address of a text string descriptor of the remote host's host name. If the string is a valid a.b.c.d type internet address, that address is used. Otherwise, the Socket Library's gethostbyname routine determines the internet address from the host name. If omitted or a null string, the ia argument determines the remote host.
cmd-rtn
Address of the user's command processing routine called each time a TELNET command is received. Inputs to the command processing routine are the CCB of the connection, a buffer containing one complete command, and a buffer byte count.
efn
Address of an unsigned longword containing the event flag to use. The event flag is set whenever data is available in the receive buffer, and cleared when the last byte of data is removed. It is up to you to allocate the event flag if necessary. You must never set or clear the event flag. If omitted, the previous value of this field is used; if 0, the field is cleared. If no event flag is specified, you will have to use another method, such as an AST routine, to determine when data is received.
ast-adr
Address of an AST routine to be called when data is received. This AST routine is declared when received data is available. You must set the ast-adr each time you want to be notified of received data. Use the TEL_SET_CCB routine to set the ast-adr after a connection is open.
A pointer to the CCB is passed to the AST routine by reference as the AST argument. You can use the CCB_USER1 and CCB_USER2 fields if you want to pass arguments to the AST routine.
port
Address of an unsigned word containing the 16-bit port number for the connection (normally 23). Supplied for use in special applications where the remote server is not a standard TELNET server. If omitted or 0, the default value 23 is used.
timeout
Address of an unsigned longword with the number of seconds to wait on the connection before timeout. If omitted or 0, the default value 120 (2 minutes) is used.
Opens an active TELNET connection to the remote host specified in ia or host. A network read operation is automatically initiated.
Specify either the internet address or host name. If you specify both, the internet address is used.
See the TCPware Management Guide for details on internet addresses and hostnames.
A connection must be opened before you can send or receive data or commands.
SS$_BADPARAM |
Invalid I/O channel, missing internet address or host name, or no route exists to the specified internet address |
SS$_NORMAL |
Connection is open |
SS$_NOSUCHNODE |
ia was not specified, and host was not found by gethostbyname |
SS$_THIRDPARTY |
Software was shut down (connection closed) |
SS$_TIMEOUT |
Connection timed-out (connection closed) |
SS$_VCBROKEN |
Connection broken (connection closed) |
Any condition value returned by the $ASSIGN and $QIO system services.
Receives data from a remote host.
ret-status.wlc.v = TEL_RECEIVE_DATA(ccb-ptr, buffer-size, buffer, byte-count);
ccb-ptr
Address of a pointer to the CCB.
The ccb-ptr variable must remain in scope at a fixed address. Also, the ccb-ptr is to be used with a single CCB from the time of TEL_ALLOCATE_CCB to TEL_DEALLOCATE_CCB.
buffer-size
Address of an unsigned word containing the number of bytes you are willing to receive.
buffer
Address of the first byte of the buffer. The buffer must be at least buffer-size bytes in length.
byte-count
Address of an unsigned word variable that receives the length of the data in the buffer.
Call this routine whenever data is available. You can use ASTs or event flags to determine when data is available. You must also call this routine after you initiated a close from the local end, as the remote host may still be open and sending data. When the remote host closes, TEL_RECEIVE_DATA returns a status of SS$_VCCLOSED.
If you are using ASTs, you must set the AST address each time you want to be notified by an AST that data is available. This is typically done before returning from your AST routine.
See TEL_SET_CCB()/ TEL_SET_CCB() on how to set the AST address or event flag number.
Do not use this routine to poll for data since that would waste CPU time.
Pairs of IAC characters (ASCII 255) are translated to a single IAC, and a NUL character (ASCII 0) following a carriage return is removed as dictated by the TELNET protocol. When in remote binary mode (bit 1 is set in CCB_UFLAGS) a NULL following a carriage return is not removed.
This routine ensures that TELNET commands and data are processed in the order in which they are received. It does this by copying TELNET data to your buffer until your buffer is full, there is no more data, or a TELNET command is encountered. If a TELNET command is encountered and data was copied to your buffer, it is not processed until the next call to TEL_RECEIVE_DATA(), at which time any additional data following the TELNET command or commands is also returned.
When the byte-count argument is 0, all data (and commands) have been processed. If the remote end closes the connection, a SS$_VCCLOSED status is returned after the last byte is transferred. You must call TEL_CLOSE_CONNECTION() to fully close the connection.
SS$_ILLSEQOP |
Connection not open |
SS$_NORMAL |
Success, data was copied to internal buffer |
SS$_THIRDPARTY |
Software was shut down (connection closed) |
SS$_TIMEOUT |
Connection timed-out (connection closed) |
SS$_VCBROKEN |
Connection broken (connection closed) |
SS$_VCCLOSED |
Connection closed by remote host (local end still open) |
Sends TELNET commands to the remote host. Commands include option commands and control functions (such as BREAK and AYT).
ret-status.wlc.v = TEL_SEND_COMMAND(ccb-ptr, buffer, byte-count);
ccb-ptr
Address of a pointer to the CCB.
buffer
Address of the first byte of your data. The commands must be complete and correct. Command data must include the IAC character(s) where appropriate.
byte-count
Address of an unsigned word containing the number of bytes in the command buffer.
This routine is similar to the TEL_SEND_DATA() routine. The only difference is that no processing is done to the command data. The buffer is transmitted with IAC and CR characters left as is.
SS$_ILLSEQOP |
Connection not open |
SS$_NORMAL |
Success, data was copied to internal buffer |
SS$_THIRDPARTY |
Software was shut down (connection closed) |
SS$_TIMEOUT |
Connection timed-out (connection closed) |
SS$_VCBROKEN |
Connection broken (connection closed) |
Sends data to the remote host.
ret-status.wlc.v = TEL_SEND_DATA(ccb-ptr, buffer, byte-count);
ccb-ptr
Address of a pointer to the CCB.
buffer
Address of the first byte of your data.
byte-count
Address of an unsigned word containing the number of bytes in the data buffer.
Sends the data in your buffer to the remote host. This routine will not return until all of the data is copied to the internal transmit buffer.
Usually data is immediately copied to the internal buffer, and control is returned to your application program. However, if the internal transmit buffer is full, TEL_SEND_DATA ()waits until there is room in the internal buffer before copying the data and returning. Buffer space becomes available as data is delivered to the remote host.
IAC characters (ASCII 255) in your buffer are doubled and carriage returns not followed by line feeds have a NULL character (ASCII 0) inserted following the carriage return as dictated by the TELNET protocol. When in local binary mode (bit 0 is set in CCB_UFLAGS) a NULL character is not inserted after a carriage return.
SS$_ILLSEQOP |
Connection not open |
SS$_NORMAL |
Success, data was copied to internal buffer |
SS$_THIRDPARTY |
Software was shut down (connection closed) |
SS$_TIMEOUT |
Connection timed-out (connection closed) |
SS$_VCBROKEN |
Connection broken (connection closed) |
Sends TELNET commands to the remote host using TCP urgent notification. Commands include option commands and control functions (such as BREAK and AYT).
ret-status.wlc.v = TEL_SEND_URGENT(ccb-ptr, buffer, byte-count);
ccb-ptr
Address of a pointer to the CCB.
buffer
Address of the first byte of your data. The commands must be complete and correct. Command data must include the IAC character(s) where appropriate.
byte-count
Address of an unsigned word containing the number of bytes in the command buffer.
This routine is similar to the TEL_SEND_COMMAND() routine. The only difference is that TEL_SEND_URGENT() sends data using TCP urgent notification.
SS$_ILLSEQOP |
Connection not open |
SS$_NORMAL |
Success, data was copied to internal buffer |
SS$_THIRDPARTY |
Software was shut down (connection closed) |
SS$_TIMEOUT |
Connection timed-out (connection closed) |
SS$_VCBROKEN |
Connection broken (connection closed) |
Sets the value of a CCB field.
ret-status.wlc.v = TEL_SET_CCB(ccb-ptr, field-code, value);
ccb-ptr
Address of a pointer to the CCB. The CCB does not need to be open.
field-code
Address of an unsigned word containing the symbolic value for the CCB field. The symbolic definitions for the CCB fields are in the TCPWARE_INCLUDE:CCBFLD.H file.
value
Address of a variable that receives the value of the CCB field. The data type of this variable depends on the field requested in field-code.
Note: When you set the CCD_ASTRTN or the CCB_CMDRTN field, make sure that value is the address of the address of the routine.
|
The CCB field you requested is set to the value specified in value. The data type of value should be the same as the field you specified.
SS$_BADPARAM |
Bad field-code specified |
SS$_NORMAL |
Normal, successful completion |
The user command processing routine is a routine that you write to process received TELNET commands. TELNET commands include option-negotiating commands (such as WILL, WONT, DO, and DONT) and control functions (such as AYT, EL, and BREAK).
The TEL_RECEIVE_DATA routine calls your processing routine to process TELNET commands. TELNET commands are processed before any data is returned in the TEL_RECEIVE_DATA call. For example, the data stream shown in the below figure is returned to you in three calls to TEL_RECEIVE_DATA.
D represents data bytes and C represents TELNET commands. Your command processing routine is called four times at the beginning of call 2 and twice at the beginning of call 3. This ensures that any change in the way data following a TELNET command is to be interpreted can go into effect before the data is processed. Also, if data needs to be included in the data stream in place of the TELNET command, it can be inserted before the beginning of the data buffer returned by the TEL_RECEIVE_DATA routine.
Your routine should have the following call format:
your-routine (ccb-ptr.ma.r, buffer.rbu.ra, byte-count.rwu.r)
The routine is called with the following inputs:
· CCB pointer, by reference
· Address of the command buffer, as an array of bytes
· Size of the command buffer, by reference to an unsigned word
There are no outputs or return values.
One complete command at a time is passed to your command processing routine. Commands are passed with the leading IAC character removed from them. For example, the command IAC value is passed as value; IAC DO ECHO is passed as DO ECHO, and IAC SB subnegotiation IAC SE is passed as SB. The subnegotiation command data is returned as is. No processing of IAC characters is done.