UUCP `g' Protocol
=================
The `g' protocol is a packet based flow controlled error correcting
protocol that requires an eight bit clear connection. It is the
original UUCP protocol, and is supported by all UUCP implementations.
Many implementations of it are only able to support small window and
packet sizes, specifically a window size of 3 and a packet size of 64
bytes, but the protocol itself can support up to a window size of 7 and
a packet size of 4096 bytes. Complaints about the inefficiency of the
`g' protocol generally refer to specific implementations, rather than
to the correctly implemented protocol.
The `g' protocol was originally designed for general packet drivers,
and thus contains some features that are not used by UUCP, including an
alternate data channel and the ability to renegotiate packet and window
sizes during the communication session.
The `g' protocol is spoofed by many Telebit modems. When spoofing
is in effect, each Telebit modem uses the `g' protocol to communicate
with the attached computer, but the data between the modems is sent
using a Telebit proprietary error correcting protocol. This allows for
very high throughput over the Telebit connection, which, because it is
half-duplex, would not normally be able to handle the `g' protocol very
well at all. When a Telebit is spoofing the `g' protocol, it forces
the packet size to be 64 bytes and the window size to be 3.
This discussion of the `g' protocol explains how it works, but does
not discuss useful error handling techniques. Some discussion of this
can be found in Jamie E. Hanrahan's paper, cited above (*note UUCP
Protocol Sources::.).
All `g' protocol communication is done with packets. Each packet
begins with a six byte header. Control packets consist only of the
header. Data packets contain additional data.
The header is as follows:
`\020'
Every packet begins with a `^P'.
K (1 <= K <= 9)
The K value is always 9 for a control packet. For a data packet,
the K value indicates how much data follows the six byte header.
The amount of data is 2 ** (K + 4), where ** indicates
exponentiation. Thus a K value of 1 means 32 data bytes and a K
value of 8 means 4096 data bytes. The K value for a data packet
must be between 1 and 8 inclusive.
checksum low byte
checksum high byte
The checksum value is described below.
control byte
The control byte indicates the type of packet, and is described
below.
xor byte
This byte is the xor of K, the checksum low byte, the checksum
high byte and the control byte (i.e., the second, third, fourth and
fifth header bytes). It is used to ensure that the header data is
valid.
The control byte in the header is composed of three bit fields,
referred to here as TT (two bits), XXX (three bits) and YYY (three
bits). The control is TTXXXYYY, or `(TT << 6) + (XXX << 3) + YYY'.
The TT field takes on the following values:
`0'
This is a control packet. In this case the K byte in the header
must be 9. The XXX field indicates the type of control packet;
these types are described below.
`1'
This is an alternate data channel packet. This is not used by
UUCP.
`2'
This is a data packet, and the entire contents of the attached data
field (whose length is given by the K byte in the header) are
valid. The XXX and YYY fields are described below.
`3'
This is a short data packet. Let the length of the data field (as
given by the K byte in the header) be L. Let the first byte in
the data field be B1. If B1 is less than 128 (if the most
significant bit of B1 is 0), then there are `L - B1' valid bytes
of data in the data field, beginning with the second byte. If `B1
>= 128', let B2 be the second byte in the data field. Then there
are `L - ((B1 & 0x7f) + (B2 << 7))' valid bytes of data in the
data field, beginning with the third byte. In all cases L bytes
of data are sent (and all data bytes participate in the checksum
calculation) but some of the trailing bytes may be dropped by the
receiver. The XXX and YYY fields are described below.
In a data packet (short or not) the XXX field gives the sequence
number of the packet. Thus sequence numbers can range from 0 to 7,
inclusive. The YYY field gives the sequence number of the last
correctly received packet.
Each communication direction uses a window which indicates how many
unacknowledged packets may be transmitted before waiting for an
acknowledgement. The window may range from 1 to 7, and may be different
in each direction. For example, if the window is 3 and the last packet
acknowledged was packet number 6, packet numbers 7, 0 and 1 may be sent
but the sender must wait for an acknowledgement before sending packet
number 2. This acknowledgement could come as the YYY field of a data
packet, or as the YYY field of a `RJ' or `RR' control packet (described
below).
Each packet must be transmitted in order (the sender may not skip
sequence numbers). Each packet must be acknowledged, and each packet
must be acknowledged in order.
In a control packet, the XXX field takes on the following values:
1 `CLOSE'
The connection should be closed immediately. This is typically
sent when one side has seen too many errors and wants to give up.
It is also sent when shutting down the protocol. If an unexpected
`CLOSE' packet is received, a `CLOSE' packet should be sent in
reply and the `g' protocol should halt, causing UUCP to enter the
final handshake.
2 `RJ' or `NAK'
The last packet was not received correctly. The YYY field
contains the sequence number of the last correctly received packet.
3 `SRJ'
Selective reject. The YYY field contains the sequence number of a
packet that was not received correctly, and should be
retransmitted. This is not used by UUCP, and most implementations
will not recognize it.
4 `RR' or `ACK'
Packet acknowledgement. The YYY field contains the sequence
number of the last correctly received packet.
5 `INITC'
Third initialization packet. The YYY field contains the maximum
window size to use.
6 `INITB'
Second initialization packet. The YYY field contains the packet
size to use. It requests a size of 2 ** (YYY + 5). Note that
this is not the same coding used for the K byte in the packet
header (it is 1 less). Most UUCP implementations that request a
packet size larger than 64 bytes can handle any packet size up to
that specified.
7 `INITA'
First initialization packet. The YYY field contains the maximum
window size to use.
To compute the checksum, call the control byte (the fifth byte in the
header) C.
The checksum of a control packet is simply `0xaaaa - C'.
The checksum of a data packet is `0xaaaa - (CHECK ^ C)', where `^'
denotes exclusive or, and CHECK is the result of the following routine
as run on the contents of the data field (every byte in the data field
participates in the checksum, even for a short data packet). Below is
the routine used by an early version of Taylor UUCP; it is a slightly
modified version of a routine which John Gilmore patched from G.L.
Chesson's original paper. The `z' argument points to the data and the
`c' argument indicates how much data there is.
int
igchecksum (z, c)
register const char *z;
register int c;
{
register unsigned int ichk1, ichk2;
ichk1 = 0xffff;
ichk2 = 0;
do
{
register unsigned int b;
/* Rotate ichk1 left. */
if ((ichk1 & 0x8000) == 0)
ichk1 <<= 1;
else
{
ichk1 <<= 1;
++ichk1;
}
/* Add the next character to ichk1. */
b = *z++ & 0xff;
ichk1 += b;
/* Add ichk1 xor the character position in the buffer counting from
the back to ichk2. */
ichk2 += ichk1 ^ c;
/* If the character was zero, or adding it to ichk1 caused an
overflow, xor ichk2 to ichk1. */
if (b == 0 || (ichk1 & 0xffff) < b)
ichk1 ^= ichk2;
}
while (--c > 0);
return ichk1 & 0xffff;
}
When the `g' protocol is started, the calling UUCP sends an `INITA'
control packet with the window size it wishes the called UUCP to use.
The called UUCP responds with an `INITA' packet with the window size it
wishes the calling UUCP to use. Pairs of `INITB' and `INITC' packets
are then similarly exchanged. When these exchanges are completed, the
protocol is considered to have been started.
Note that the window and packet sizes are not a negotiation. Each
system announces the window and packet size which the other system
should use. It is possible that different window and packet sizes will
be used in each direction. The protocol works this way on the theory
that each system knows how much data it can accept without getting
overrun. Therefore, each system tells the other how much data to send
before waiting for an acknowledgement.
When a UUCP package transmits a command, it sends one or more data
packets. All the data packets will normally be complete, although some
UUCP packages may send the last one as a short packet. The command
string is sent with a trailing null byte, to let the receiving package
know when the command is finished. Some UUCP packages require the last
byte of the last packet sent to be null, even if the command ends
earlier in the packet. Some packages may require all the trailing bytes
in the last packet to be null, but I have not confirmed this.
When a UUCP package sends a file, it will send a sequence of data
packets. The end of the file is signalled by a short data packet
containing zero valid bytes (it will normally be preceeded by a short
data packet containing the last few bytes in the file).
Note that the sequence numbers cover the entire communication
session, including both command and file data.
When the protocol is shut down, each UUCP package sends a `CLOSE'
control packet.