Telnet Negotiation

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.

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License