Feb 23, 2014, 11:38:53 PM2/23/14
> rfc1143: The Q Method of Implementing TELNET Option Negotiation
> D. Bernstein February 1990
> 7. Example of Correct Implementation
> An option is enabled if and only if its state is YES
> Upon receipt of WILL, we choose based upon him and himq:
> NO If we agree that he should enable, him=YES, send
> DO; otherwise, send DONT.
Correct. State changed. We must respond.
> YES Ignore.
Correct. State unchanged. We must be silent.
> WANTNO EMPTY Error: DONT answered by WILL. him=NO.
No. We must NOT unilaterally change state.
Think about how we got to WANTNO in the first place. If the state was
already NO, we would NOT request NO. That would violate rfc854:
> a party may not send out a "request" merely to announce what mode it
> is in.
So the WANTNO state was preceded by either YES or WANTYES. For now,
ignore WANTYES, and consider YES.
YES -> WANTNO is a change of state (noted above). But any unilateral
change is wrong. We must remain in the current state (YES) until the
peer acknowledges our request for change.
Thus YES -> WANTNO is an invalid transition, rendering WANTNO -> NO
invalid as well; the whole third transition for "WILL" is wrong, as is
Why? Consider rfc856, TELNET BINARY TRANSMISSION:
> A connection is being operated in binary transmission mode only
> when one party has requested it and the other has acknowledged it.
The initial state of all options is disabled. rfc856 clearly says that
BINARY is disabled until both parties agree; and it shall not be enabled
until the requester receives positive acknowledgement. All options must
of course work the same way.
But what about changing from enabled to disabled? Although rfc854 does
> a party ... must never refuse a request to disable some option since
> all parties must be prepared to support the NVT
It does NOT follow that we can disable unilaterally. That would be like
walking off a job without telling anyone. A reasonable person would say
"I quit," wait for the employer to understand the words, then leave. The
employer cannot force us to work, just as a telnet peer cannot refuse to
disable an option.
But once an option is enabled, we must not act unilaterally. Our peer
expects to continue in a given mode until we say otherwise. And since we
wait for acknowledgement before enabling an option, disabling an option
should be no different.
As rfc1143 says, there are two sides, we and he. But as "we" suggests
more than one, I say "me" and he, two individuals on opposite ends of a
connection. Clarifying the idea is more important than strict English
"State" is what we have. We either "have" it, or not. The only possible
transitions are 0 -> 1 and 1 -> 0. The "undef" value, a la Perl, means
we don't support the option, and reject all requests to enable it. Once
undef, always undef.
Our next request is what we "want." Have and want are what humans mostly
do, so those two words make natural variable names.
The "want" variable is undef when there is no outstanding request. When
we send a request, we change "want" to 1 or 0, to remember what we asked
for. After receiving a reply, we change it back to undef.
When we already have what we want, no action is needed.
undef undef unsupported, always reject
0 undef don't have it (disabled)
0 1 don't have it, want it
1 undef have it (enabled)
1 0 have it, don't want it
With a third variable, we can implement the Q method of rfc1143.
I leave further exposition and code to the reader. Separating "want"
from "have" was the hard part. Must have been. Nobody noticed it for 24