[ih] X.25

John Gilmore gnu at toad.com
Fri Oct 3 09:11:47 PDT 2025


The earliest posting that I saved of the "f" protocol for UUCP over X.25
was on 1984-07-31; it's below.  Piet Beertema of mcvax in Amsterdam was
the author.  He later posted a bug-fixed version on 1984-09-26 in
message-ID <6006 at mcvax.UUCP>.  The protocol was incorporated by Rick
Adams, who maintained uucp for the BSD 4.3 release.  Later, Chris Lewis
<mnetor!spectrix!clewis> created a matching X.25 PAD dialer, which he
wrote about on 1986-10-24 (also below) and later posted to mod.sources
v08i050 on 1987-02-09.  He noted that "Protocol 'f' and the dialer work
quite well - mnetor (my previous home) has taken over almost all of
utzoo's long haul incoming news feed - getting it from seismo."

	John

>From decwrl!decvax!mcvax!piet Tue Jul 31 09:58:22 1984
Relay-Version: version B 2.10.1 6/24/83 SMI; site sun.uucp
Posting-Version: version B 2.10.1 6/24/83 (MC840302); site mcvax.UUCP
Path: sun!decwrl!decvax!mcvax!piet
From: piet at mcvax.UUCP (Piet Beertema)
Newsgroups: net.sources
Subject: new uucp protocol
Message-ID: <5919 at mcvax.UUCP>
Date: Tue, 31-Jul-84 09:58:22 PDT
Article-I.D.: mcvax.5919
Posted: Tue Jul 31 09:58:22 1984
Date-Received: Sun, 5-Aug-84 07:19:17 PDT
Organization: CWI, Amsterdam
Lines: 430

<...>

Here is a new uucp protocol for use over X.25+PAD connections. It can
be used too on direct lines and 7-bit links, provided the receiving
machine is fast enough to handle high-speed flow control (e.g. no
11/45's etc.).

The reason for introducing this protocol:
In Europe there is an increasing tendency to switch uucp links (especially
the international links) from phone to X.25, because that would be both
faster and cheaper.
Initial tests however proved that this was *not* the case, due to (often
long) delays in the X.25 network. It turned out that with 4800 Baud lines
no effective speed higher than ~1200 Baud could be attained! Besides it
proved to be even more expensive than phone links.
The cause of this was the standard g-protocol which, when used over X.25,
exchanges more than 3 times as many packets as would be needed for the data.
Now the problem is that when you're using a PAD to link to the X.25 network,
you effectively have an async line, which *could* introduce errors, so you
can't use an X.25-dedicated protocol that doesn't control the data flow and
makes no security checks on the data. Besides special care should be taken
with control characters, that may be meaningful for a PAD.
The f-protocol given here overcomes these difficulties. It has been tested
now for about two months. On 4800 Baud links it can attain an effective
speed of ~4000 Baud. Pity is that I still haven't found a site in the USA
to test it with, so I can't say as yet what speeds can be reached on a
transatlantic link.

Adding this proto to uucico requires only two minor changes to the existing
sources:
- in cico.c the signals SIGINT and SIGQUIT must be ignored not only in
  MASTER mode, but also in SLAVE mode. Move the corresponding lines to
  before the "if (Role == MASTER) {" line.
- in cntrl.c a line "sleep(2);" must be added before "WMESG(HUP, "");" to
  prevent timing problems during f-proto turnon.

WARNING: if you've installed this proto and have a phone link to a site
	 that has installed it too, you must hack the sources to prevent
	 selection of it on a phone link or use a separate uucico for
	 that link.


Here's the source of the f-proto, fio.c:

/*
 * fio.c; flow-control protocol.
 *
 * This protocol relies basically on flow control of the
 * data stream. It is meant for working over links that
 * can (almost) be guaranteed to be errorfree, like direct
 * or X.25 links.
 * It carries out a sumcheck over a whole file only. If a
 * file transport fails the receiving side can request
 * retransmission(s).
 * This protocol uses a 7-bit datapath only, so it can be
 * used on links that are not 8-bit transparent.
 *
 * Author: Piet Beertema, CWI, June 1984.
 */

#include "uucp.h"
#include <signal.h>
#ifdef SIII
#include <termio.h>
#else
#include <sgtty.h>
#endif SIII
#include <setjmp.h>


#define MAXRETRIES	1	/* max. attempts to retransmit a file */
#define FBUFSIZ		256

static int chksum;
static jmp_buf Ffailbuf;

static falarm()
{
	longjmp(Ffailbuf, 1);
}

static int (*fsig)();

#ifndef SIII
#define TCGETA	TIOCGETP
#define TCSETA	TIOCSETP
#define termio	sgttyb
#endif SIII

fturnon()
{
	int ret;
	struct termio ttbuf;

	ioctl(Ifn, TCGETA, &ttbuf);
#ifdef SIII
	ttbuf.iflag = IXOFF|IXON|ISTRIP;
	ttbuf.c_cc[4] = FBUFSIZ > 64 ? 64 : FBUFSIZ;
	ttbuf.c_cc[5] = 5;
#else
	ttbuf.sg_flags = ANYP|CBREAK|TANDEM;
#endif SIII
	ret = ioctl(Ifn, TCSETA, &ttbuf);
	ASSERT(ret >= 0, "STTY FAILED", "", ret);
	fsig = signal(SIGALRM, falarm);
	return 0;
}

fturnoff()
{
	(void) signal(SIGALRM, fsig);
	return 0;
}

fwrmsg(type, str, fn)
register char *str;
int fn;
char type;
{
	register char *s;
	char bufr[MAXMSGLEN];

	s = bufr;
	*s++ = type;
	while (*str)
		*s++ = *str++;
	if (*(s-1) == '\n')
		s--;
	*s++ = '\r';
	(void) write(fn, bufr, s - bufr);
	return 0;
}

frdmsg(str, fn)
register char *str;
register int fn;
{
	register char *smax;

	if (setjmp(Ffailbuf))
		return FAIL;
	smax = str + MAXMSGLEN - 1;
	for (;;) {
		(void) alarm(MAXMSGTIME);
		if (read(fn, str, 1) <= 0)
			return FAIL;
		if (*str == '\r')
			break;
		if (str++ >= smax)
			return FAIL;
	}
	*str = '\0';
	(void) alarm(0);
	return 0;
}

fwrdata(fp1, fn)
FILE *fp1;
int fn;
{
	register int flen, alen, ret;
	register char *obp;
	char ibuf[FBUFSIZ];
	char ack;
	long abytes, fbytes;
	time_t t1, t2;
	struct sgttyb sgtty;

	ret = FAIL;
retry:
	chksum = 0xffff;
	abytes = fbytes = 0L;
	time(&t1);
	while ((flen = fread(ibuf, sizeof (char), FBUFSIZ, fp1)) > 0) {
		if ((alen = fwrblk(fn, ibuf, flen)) < 0)
			goto acct;
		fbytes += flen;
		abytes += alen;
	}
	sprintf(ibuf, "\176\176%4x", chksum);
	alen = strlen(ibuf);
	if (write(fn, ibuf, alen) == alen) {
		abytes += alen;
		DEBUG(8, "%d\n", 6);
		DEBUG(8, "checksum: %4x\n", chksum);
	}
	if (frdmsg(ibuf, fn) < 0) {
		ack = 0;
		goto acct;
	}
	ack = ibuf[0];
	DEBUG(8, "got ack: '%c'\n", ack);
	if (ack == 'G')
		ret = 0;
acct:
	time(&t2);
	sprintf(ibuf, ret == 0 ?
		"sent data %ld bytes %ld secs" :
		"send failed after %ld bytes %ld secs",
		fbytes, t2 - t1);
	DEBUG(1, "%s\n", ibuf);
	syslog(ibuf);
	sysacct(abytes, t2 - t1);
	if (ack == 'R') {
		DEBUG(4, "RETRY:\n", 0);
		fseek(fp1, 0L, 0);
		goto retry;
	}
	return ret;
}

frddata(fn, fp2)
register int fn;
register FILE *fp2;
{
	register int flen;
	register char eof;
	char ibuf[FBUFSIZ];
	int ret, alen, retries = 0;
	long abytes, fbytes;
	time_t t1, t2;

	ret = FAIL;
retry:
	chksum = 0xffff;
	abytes = fbytes = 0L;
	time(&t1);
	do {
		if ((flen = frdblk(ibuf, fn, &alen)) < 0)
			goto acct;
		if (eof = flen > FBUFSIZ)
			flen -= FBUFSIZ + 1;
		fbytes += flen;
		abytes += alen;
		if (fwrite(ibuf, sizeof (char), flen, fp2) != flen)
			goto acct;
	} while (!eof);
	ret = 0;
acct:
	time(&t2);
	sprintf(ibuf, ret == 0 ? 
		"received data %ld bytes %ld secs" :
		"receive failed after %ld bytes %ld secs",
		fbytes, t2 - t1);
	DEBUG(1, "%s\n", ibuf);
	syslog(ibuf);
	sysacct(abytes, t2 - t1);
	if (ret) {
		if (retries++ < MAXRETRIES) {
			DEBUG(8, "send ack: 'R'\n", 0);
			fwrmsg('R', "", fn);
			fseek(fp2, 0L, 0);
			DEBUG(4, "RETRY:\n", 0);
			goto retry;
		}
		DEBUG(8, "send ack: 'Q'\n", 0);
		fwrmsg('Q', "", fn);
	} else {
		DEBUG(8, "send ack: 'G'\n", 0);
		fwrmsg('G', "", fn);
	}
	return ret;
}

frdbuf(blk, len, fn)
register char *blk;
register int len;
register int fn;
{
	register int ret;

	if (setjmp(Ffailbuf))
		return FAIL;
	(void) alarm(MAXCHARTIME);
	ret = read(fn, blk, len);
	alarm(0);
	return ret <= 0 ? FAIL : ret;
}

/* Byte conversion:
 *
 *   from        pre       to
 * 000-037       172     100-137
 * 040-171               040-171
 * 172-177       173     072-077
 * 200-237       174     100-137
 * 240-371       175     040-171
 * 372-377       176     072-077
 */

fwrblk(fn, ip, len)
int fn;
register char *ip;
register int len;
{
	register char *op;
	register int sum, nl;
	char obuf[FBUFSIZ * 2];

	DEBUG(8, "%d/", len);
	op = obuf;
	nl = 0;
	sum = chksum;
	do {
		if ((sum <<= 1) & 0x10000)
			sum++;
		sum = ((sum & 0xffff) + (*ip & 0377)) & 0xffff;
		if (*ip & 0200) {
			*ip &= 0177;
			if (*ip < 040) {
				*op++ = '\174';
				*op++ = *ip++ + 0100;
			} else
			if (*ip <= 0171) {
				*op++ = '\175';
				*op++ = *ip++;
			}
			else {
				*op++ = '\176';
				*op++ = *ip++ - 0100;
			}
			nl += 2;
		} else {
			if (*ip < 040) {
				*op++ = '\172';
				*op++ = *ip++ + 0100;
				nl += 2;
			} else
			if (*ip <= 0171) {
				*op++ = *ip++;
				nl++;
			} else {
				*op++ = '\173';
				*op++ = *ip++ - 0100;
				nl += 2;
			}
		}
	} while (--len);
	chksum = sum;
	DEBUG(8, "%d,", nl);
	return write(fn, obuf, nl) == nl ? nl : FAIL;
}

frdblk(ip, fn, rlen)
register char *ip;
int fn, *rlen;
{
	register char *op, c;
	register int sum;
	register int len, nl;
	char buf[5];
	int i;
	static char special = 0;

	if ((*rlen = len = frdbuf(ip, FBUFSIZ, fn)) < 0)
		return FAIL;
	DEBUG(8, "%d/", len);
	op = ip;
	nl = 0;
	sum = chksum;
	do {
		if (*ip >= '\172') {
			if (special) {
				DEBUG(8, "%d", nl);
				special = 0;
				ip++;
				op = buf;
				i = --len;
				while (i--)
					*op++ = *ip++;
				while (len < 4) {
					i = frdbuf(&buf[len], 4 - len, fn);
					if (i < 0)
						return FAIL;
					DEBUG(8, ",%d", i);
					len += i;
					*rlen += i;
				}
				sscanf(buf, "%4x", &chksum);
				DEBUG(8, "\nchecksum: %4x\n", sum);
				if (chksum == sum)
					return FBUFSIZ + 1 + nl;
				else {
					DEBUG(4, "Bad checksum\n", 0);
					return FAIL;
				}
			}
			special = *ip++;
		} else {
			if (*ip < '\040') {
				/* error: shouldn't get control chars */
				special = 0;
				sum = chksum ? 0 : 0xffff;
				break;
			}
			switch (special) {
			case 0:
				c = *ip++;
				break;
			case '\172':
				c = *ip++ - 0100;
				break;
			case '\173':
				c = *ip++ + 0100;
				break;
			case '\174':
				c = *ip++ + 0100;
				break;
			case '\175':
				c = *ip++ + 0200;
				break;
			case '\176':
				c = *ip++ + 0300;
				break;
			}
			*op++ = c;
			if ((sum <<= 1) & 0x10000)
				sum++;
			sum = ((sum & 0xffff) + (c & 0377)) & 0xffff;
			special = 0;
			nl++;
		}
	} while (--len);
	chksum = sum;
	DEBUG(8, "%d,", nl);
	return nl;
}
-- 
	Piet Beertema, CWI, Amsterdam
	...{decvax,philabs}!mcvax!piet


>From ptsfa!lll-lcc!lll-crg!nike!sri-spam!rutgers!seismo!mnetor!spectrix!clewis Fri Oct 24 08:19:42 1986
Relay-Version: version B 2.10.3 4.3bsd-beta 6/6/85; site hoptoad.uucp
Path: hoptoad!ptsfa!lll-lcc!lll-crg!nike!sri-spam!rutgers!seismo!mnetor!spectrix!clewis
From: clewis at spectrix.UUCP (Chris Lewis)
Newsgroups: net.sources.bugs
Subject: Re: Need help with UUCP over X.25
Message-ID: <176 at spectrix.UUCP>
Date: 24 Oct 86 15:19:42 GMT
Date-Received: 
References: <44700004 at cdp> <532 at argus.UUCP>
Reply-To: clewis at spectrix.UUCP (Chris Lewis)
Organization: Spectrix Microsystems Inc., Toronto, Ontario, Canada
Lines: 80

In article <532 at argus.UUCP> ken at argus.UUCP (Kenneth Ng) writes:
>In article <44700004 at cdp>, scott at cdp.UUCP writes:
>> 
>> I would like to talk to someone who has an X.25 connection to
>> Telenet, runs SysVr2 vanilla UUCP or something close, and has
>> people call them via Telenet to run UUCP.  Any pointers on
>> running UUCP over Telenet would be appreciated.
>> 
>> -scott
>> 415-322-9060
>> {ihnp4,...}!hplabs!cdp!scott
>
>If you get this to work I'd be interested.  About a year ago this
>site tried to get uucp to work over a couple Dynapac X.25 pads.
>It never worked.  Apparently the problem is that uucp does not
>have an option to use only 7 bit data transfer.  It seems that
>all the options uucp has are variations of the same single option.
>By the way, I never found documentation that says that uucp needs
>8 bit transfer, the local Unix guru swears that uucp works 7 bit
>however.  Can anyone confirm or deny this?

Back in my cX days, we did get SVR2 and BSD4.2 UUCP standard protocol
"g" talking over Motorola/MICOM PADS.  Basically, you have to dedicate 
an "outgoing" PAD line/tty and/or "incoming" PAD line/ttys.  Then,
you have to set quite a few parameters on these lines in the PAD.
I can't remember all of the details, but these are a few that I remember:

	1) 8-bit data path
	2) packet timeout (we used the minimum - 50 ms. I think)
	3) Turn off *ALL* special characters - especially ^P.
	4) packet size shouldn't matter much.

You should be able to put the parameter settings plus the "conn" sequences
into the L.sys file.  Once this is done, normal "g" protocol will work, but
VERY slowly.  Eg: on 9600 baud lines all of the way through the network, we
were acheiving effective baud rates of about 600 to 1200.  Eg: takes
64 Ms. to place the packet in the PAD, 50 Ms. later it times out and sends
the packet, then the other side writes the acknowledge into the remote PAD, 
and the remote PAD waits another 50 ms. before sending it back.  Approx
3:1 time expansion.  Further, you might have problems trying to hang up 
the connection.  Further, since you are always sending short packets (most
of them only a few bytes), it'll cost a lot if your network is charging
"per-packet" (ala DATAPAC).

YECH!

Yes, "g" protocol *DOES* use 8 bit data transmission.

After we got this to work, I started thinking about writing a new protocol,
when, miracle of miracles, we managed to get a copy of alpha 4.3 UUCP.  It has
protocol "f" which is designed for X.25 PADS.  We acheived thruput in excess
of 5600 baud.  Protocol "f" is rather simple minded:

    1) Most non-printing characters (ASCII and 8th bit on chars) are converted
       into two characters.
    2) The whole file is blasted out on the line without any packetization.
    3) The only acknowledge is a checksum exchange after the file has been
       transmitted.
    4) X-ON/X-OFF better work well between your computer and the PAD - if
       you drop characters, UUCP only notices it at the end of the transmission
       and simply retransmits the whole file again.  Can be very expensive with
       big files.

I've written a "proper" "PAD" dialer (as opposed to ACU or DIR) for protocol 
"f" and sent it off to Rick Adams - however, it was probably too late for 
inclusion in the "official" 4.3 release.  This dialer does all of the 
PAD parameter settings itself, so that it is no longer necessary to 
dedicate PAD lines.  If you already have 4.3 UUCP, you'll already have 
the "f" protocol itself.  If you have 4.3 UUCP and you're interested 
in the dialer, contact me for a copy of it.  However, because of rather 
extensive internal differences between 4.3 UUCP and it's predecessors, 
I am unable to help people add proto "f" into non-4.3 UUCP's.

Protocol "f" and the dialer work quite well - mnetor (my previous home)
has taken over almost all of utzoo's long haul incoming news feed - getting
it from seismo.
-- 
Chris Lewis
UUCP: {utzoo|utcs|yetti|genat|seismo}!mnetor!spectrix!clewis
Phone: (416)-474-1955




More information about the Internet-history mailing list