Description
Implementation of telnet negotiation allows a client or a server to help provide the user with an enhanced experience. Ever resized a window and seen the contents within the window change to suit the new window size? With the support of a decent client implementation of the NAWS option, a server can provide this response. Ever used a curses based user interface, whether an email program like Pine or a text editor like Nano? With the support of a decent client implementation of the TTYPE option, a server can provide user interfaces like these.
Not Implementing Negotiation
It is not required that you implementing telnet negotiation in any clients and servers you may create, but you need to be aware of it in order to avoid problems that its presence on the other end of your connection may otherwise cause. As a byte-based protocol, a value of 255 (named IAC) is reserved to indicate that a negotiation sequence follows. In order to actually send a value of 255, you need to be escape it. You can do this by sending it twice in a row.
Client Sensitivity
Attempting to negotiate may have side-effects on the users of buggy or even basic clients. If a client does not support negotiation, barraging it with a range of attempts may result in junk characters appearing in the output displayed to the client's user. One MUD client that does not support negotiation is GMud, and attempts to send it negotiation for MXP and MSP will result in a junk character being displayed. If a client does support negotiation, its support may be broken in a way that is difficult to work around. On receiving negotiation from a server, Windows Telnet for instance, will stop doing local echo and it is not possible for the server to get it to start again.
Negotiation
Protocol
The negotiation process is engaged in through sending and receiving special sequences of characters. Every one of these sequences is started with the IAC token, but there are a variety of forms that the sequence might follow from there.
Token | Binary Value | Description | RFC Standard |
---|---|---|---|
IAC | 255 | Marks the start of a negotiation sequence. | 855 |
WILL | 251 | Confirm willingness to negotiate. | 855 |
WONT | 252 | Confirm unwillingness to negotiate. | 855 |
DO | 253 | Indicate willingness to negotiate. | 855 |
DONT | 254 | Indicate unwillingness to negotiate. | 855 |
NOP | 241 | No operation. | 855 |
SB | 250 | The start of sub-negotiation options. | 855 |
SE | 240 | The end of sub-negotiation options. | 855 |
IS | 0 | Sub-negotiation IS command. | 855 |
SEND | 1 | Sub-negotiation SEND command. | 855 |
Passive or Active Negotiation
Some telnet clients, like Putty for instance, default to active negotiation. Rather than waiting for the server to ask them if they are willing to communicate about a given option through a DO command, the client will proactively indicate its willingness by proactively sending their WILL command without being prompted.
Negotiation Options
CHARSET
Token | Binary Value | Description | RFC Standard |
---|---|---|---|
CHARSET | 42 | Charset option. | 2066 |
Wouldn't it be nice if this were in common use? Then the server could ensure that any client which connected to it, displayed its output using the correct characters. Unfortunately, implementation of this option is rare, assuming it has ever been implemented at all. It is not worth implementing support for it at this time, or given the age of telnet, any time in the future.
NAWS
Token | Binary Value | Description | RFC Standard |
---|---|---|---|
NAWS | 31 | Window size option. | 1073 |
If the server you are connected to makes use of the client window in ways that are linked to its width and height, then is useful for it to be able to find out how big it is, and also to get notified when it is resized.
Role | Command | Binary Representation |
---|---|---|
Server | IAC DO NAWS | 255, 253, 31 |
Client | IAC WILL NAWS | 255, 251, 31 |
Client | IAC SB NAWS SEND IAC SE | 255, 250, 31, 0, 80, 0, 24, 255, 240 |
That's pretty much it. Once the server has asked the client to do NAWS, and the client has confirmed it will, subnegotiation events come in with the window sizes. It is worth noting that while clients like Putty will send these events immediately, Windows Telnet will only send it as it sends the next input from the user. This does not allow for the best user experience in terms of updated window contents, but it is better than nothing of course.
NEW-ENVIRON
Token | Binary Value | Description | RFC Standard |
---|---|---|---|
NEW-ENVIRON | 39 | Environment variables. | 1572 |
IS | 0 | Sub-negotiation IS command. | 1572 |
SEND | 1 | Sub-negotiation SEND command. | 1572 |
INFO | 2 | Sub-negotiation INFO command. | 1572 |
VAR | 0 | NEW-ENVIRON command. | 1572 |
VALUE | 1 | NEW-ENVIRON command. | 1572 |
ESC | 2 | NEW-ENVIRON command. | 1572 |
USERVAR | 3 | NEW-ENVIRON command. | 1572 |
The idea of knowing the value of environment variables on a connected client is appealing in the sense of what useful information it might reveal about the user. But in practice, very few clients supply information of interest.
For the information that is of interest, you really have to know the names of the variables that provide it in order to request their values. In theory the spec allows for the server to request what variables the client is willing to provide, but in practice no client I have ever encountered lists any. The following is what you can expect if you try.
Role | Command | Binary Representation |
---|---|---|
Server | IAC DO NEW-ENVIRON | 255, 253, 39 |
Client | IAC WILL NEW-ENVIRON | 255, 251, 39 |
Server | IAC SB NEW-ENVIRON SEND IAC SE | 255, 250, 39, 1, 255, 240 |
Client | IAC SB NEW-ENVIRON IS IAC SE | 255, 250, 39, 0, 255, 240 |
The specification lists a set of well known variables, although they are now dated. They include the following:
- ACCT
- DISPLAY
- JOB
- PRINTER
- SYSTEMTYPE
- USER
Requesting these variables for a user connected through Windows Telnet gave me the following sequence of commands. Let us ignore that it also crashed Windows Telnet, as it seems to choke on the "USER" variable. Want to discourage your users from using Windows Telnet? I guess you could crash it on them.
Role | Command | Binary Representation |
---|---|---|
Server | IAC DO NEW-ENVIRON | 255, 253, 39 |
Client | IAC WILL NEW-ENVIRON | 255, 251, 39 |
Server | IAC SB NEW-ENVIRON SEND VAR "ACCT" VAR "DISPLAY" VAR "JOB" VAR "PRINTER" VAR "SYSTEMTYPE" VAR "USER" IAC SE | 255, 250, 39, 1, 0, 65, 67, 67, 84, 0, 68, 73, 83, 80, 76, 65, 89, 0, 74, 79, 66, 0, 80, 82, 73, 78, 84, 69, 82, 0, 83, 89, 83, 84, 69, 77, 84, 89, 80, 69, 0, 85, 83, 69, 82, 255, 240 |
Client | IAC SB NEW-ENVIRON IS VAR "SYSTEMTYPE" VALUE "WIN32" VAR "ACCT" VAR "JOB" VAR "PRINTER" VAR "DISPLAY" IAC SE | 255, 250, 39, 0, 0, 83, 89, 83, 84, 69, 77, 84, 89, 80, 69, 1, 87, 73, 78, 51, 50, 0, 65, 67, 67, 84, 0, 74, 79, 66, 0, 80, 82, 73, 78, 84, 69, 82, 0, 68, 73, 83, 80, 76, 65, 89, 255, 240 |
TTYPE
Token | Binary Value | Description | RFC Standard |
---|---|---|---|
TTYPE | 24 | Terminal type option. | 1091 |
The way a server engages in negotiation about terminal types with a client, is an arcane process. After the client has indicated it is willing to send terminal type in a sub-negotiation, the server can proceed with that sub-negotiation.
Role | Command | Binary Representation |
---|---|---|
Client | IAC WILL TERMINAL-TYPE | 255, 251, 24 |
Server | IAC SB TERMINAL-TYPE SEND IAC SE | 255, 250, 24, 1, 255, 240 |
Client | IAC SB TERMINAL-TYPE IS "ANSI" IAC SE | 255, 250, 24, 0, 65, 78, 83, 73, 255, 240 |
Now at this point, what the server has actually done is asked the client to select a terminal type. In order to determine all the terminal types the client supports, the server needs to select them one by one until it encounters one it has already seen. Exactly what this means may differ between clients, some may continue repeating the last terminal type in their list, and others may wrap round and start selecting terminal types from the beginning again.
Enumerating terminal types with Windows Vista telnet:
Role | Command | Binary Representation |
---|---|---|
Client | IAC WILL TERMINAL-TYPE | 255, 251, 24 |
Server | IAC SB TERMINAL-TYPE SEND IAC SE | 255, 250, 24, 1, 255, 240 |
Client | IAC SB TERMINAL-TYPE IS "ANSI" IAC SE | 255, 250, 24, 0, 65, 78, 83, 73, 255, 240 |
Server | IAC SB TERMINAL-TYPE SEND IAC SE | 255, 250, 24, 1, 255, 240 |
Client | IAC SB TERMINAL-TYPE IS "VT100" IAC SE | 255, 250, 24, 0, 86, 84, 49, 48, 48, 255, 240 |
Server | IAC SB TERMINAL-TYPE SEND IAC SE | 255, 250, 24, 1, 255, 240 |
Client | IAC SB TERMINAL-TYPE IS "VT52" IAC SE | 255, 250, 24, 0, 86, 84, 53, 50, 255, 240 |
Server | IAC SB TERMINAL-TYPE SEND IAC SE | 255, 250, 24, 1, 255, 240 |
Client | IAC SB TERMINAL-TYPE IS "VTNT" IAC SE | 255, 250, 24, 0, 86, 84, 78, 84, 255, 240 |
Server | IAC SB TERMINAL-TYPE SEND IAC SE | 255, 250, 24, 1, 255, 240 |
Client | IAC SB TERMINAL-TYPE IS "VTNT" IAC SE | 255, 250, 24, 0, 86, 84, 78, 84, 255, 240 |
At this point, the server needs to decide which terminal type it wants the client to use, and restart the negotiation process selecting terminal types until it reaches it. Generally, the best terminal type for general use is the first one the client selects anyway.
Selecting the ANSI terminal type:
Role | Command | Binary Representation |
---|---|---|
Server | IAC DO TERMINAL-TYPE | 255, 253, 24 |
Client | IAC WILL TERMINAL-TYPE | 255, 251, 24 |
Server | IAC SB TERMINAL-TYPE SEND IAC SE | 255, 250, 24, 1, 255, 240 |
Client | IAC SB TERMINAL-TYPE IS "ANSI" IAC SE | 255, 250, 24, 0, 65, 78, 83, 73, 255, 240 |
External Links
CGMud Telnet Support - A document about the telnet negotiation support in CGMud.
TPPMud Telnet Negotiation - A document about the telnet negotiation support in LDMud.