[comp.unix.sysv386] uucp using TLI

bill@ssbn.WLK.COM (Bill Kennedy) (11/16/90)

Before I start this, many many thanks to Doug Mc Callum and Dick Dunn
at ISC for getting me straightened out on the address that nlsadmin
wants to make this work, to Bill Bunton at Tools & Techniques, Austin
for persevering as I stumble blundered through it, and to Bob Tracy
at CDC San Antonio for getting me started.

If you have no interest in a TLI based uucp over TCP/IP, hit `n' now,
but if you ever might, save this article, it will save your hair.

Here's the configuration and the problem.  I have two machines that are
networked together using ISC TCP/IP.  One of them has both printers that
used to be on a third machine connected by a direct 19.2Kbps uucp link.
My old lp scripts sort of went by the board when I no longer had a uucp
link to the system that had the printers.  It became obvious to me that I
had to figure out how to get uucp to work using TLI across the network.
TFM has some information on getting RFS to work, but it's silent with
respect to uucp using TLI.  A generous and TLI savvy neighbor, Bob Tracy,
was able to get things to almost work, but we kept failing in t_bind, it
couldn't allocate the address.  ISC lept to the rescue by explaining how
the address had to look for the listener to fundtion but we still (by now,
Bill Bunton had agreed to help but was falling into similar potholes)
couldn't get the originator's uucico to connect with its destination.  What
follows is a step-by-step recipe for something that works.  If there is a
more elegant way to do it, please feel free to mark it up and re-post.  If
there is any generally available documentation (cookbook please, not theory),
please tell us too.

Begin by editing /etc/services and create a port for nls.  We used
nls	256/tcp		# TLI port
if that doesn't suit you, keep track of the port number because you
need it to develop the nls address.  Now choose a name for the nls
"net_spec" (see NLSADMIN(1M)), we chose tcp.

Initialize the nls net_spec with nlsadmin -i tcp, it will create a
directory, /usr/net/nls/tcp and will create some files in it that it
uses to actually start the listener.  Now set up the nls service_code
nlsadmin -a 101 -c"/usr/lib/uucp/uucico -r0 -iTLI -u loginid" -y "comment" tcp
Here loginid is the name of the system who's going to be logging in, on
ssbn it's udunsel and on dunsel it's ussbn, both are no password logins
since they are local uucp over the ethernet.  I used "dunsel/ssbn uucico"
for the comment, all of this ends up in /usr/net/nls/tcp/dbf, you can make
a similar entry for cu, choose another service_code, avoid 105 because
that's rfs.

Now you have to work up your network address.  We'd have _never_ figured this
out without ISC's help!  This is a hex string that is composed of address
family (AF_INET), port number, IP address, and padding zeroes.  Here is the
format and an example:
\x02000100c0fafa010000000000000000    mapped as
  aaaappppiiiiiiiizzzzzzzzzzzzzzzz
  |   |   |       +------------------ sixteen padding zeroes
  |   |   +-------------------------- IP address 192.250.250.1 co.fa.fa.01
  |   +------------------------------ port address fm /etc/services (256)
  +---------------------------------- address family, socket address
Obviously your mileage is going to vary, but it shouldn't be hard to figure
out from this example.  Hang on to it, you're going to use it more than one
place...  You have to tell the listener what address he's going to use
nlsadmin -l "\x02000100c0fafa010000000000000000" tcp
and that number will appear in /usr/net/nls/tcp/addr to be used when you
start nls with nlsadmin -s tcp.  Look at /usr/net/nls/tcp/log to be sure
that you've gotten started, "Couldn't allocate address" means he can't
get to the address you specified, "Invalid argument" means you don't have
the right length.

Now you need to make some entries in /usr/lib/uucp/Systems, Devices, and
Dialers.  Remember that ssbn and dunsel don't have passwords on each
other, we can drop directly into uucico which is what we specified when
we added the 101 service code.

Systems:
# ssbn's Systems line for contacting dunsel, 192.250.250.2
dunsel Any wlknet Any \x02000100c0fafa020000000000000000
# dunsel's Systems line for contacting ssbn, 192.250.250.1
ssbn   Any wlknet Any \x02000100c0fafa010000000000000000

Devices:
wlknet,eg tcp - - TLI \D nls

Dialers:
nls "" "" NLPS:000:001:101\N\c

If you used a service_code other than 101 in the nlsadmin -a, replace the
101 in the Dialers entry with the code you used.  Also note that the Systems
lines need the address of the system that they are "calling", choose any
convenient Devices name, I used wlknet because that's the network name in my
/etc/networks.  Now you're ready to test the connection with Uutry.  It
goes by too fast to watch, but it's all recorded in /tmp/systemname.  You
might have to go through the usual /usr/lib/uucp/Permissions exercise to
make them actually talk to each other, but that's unrelated to nls or TCP/IP
(I _think_ :-)

Back to the original problem I had set out to solve, my ssbn resident lp
scripts just uux the stuff over to dunsel who is physically connected to
the printers.  Here's what I use to get to the dot matrix printer:

user=$2
options=$5
copies=$4
shift; shift; shift; shift; shift
files="$*"
for file in $files
do
	uux -  -a$user "dunsel!lp -o$options -n$copies 2>/dev/null" < $file
done

The lp setup on dunsel contains all the stuff that worries about lines
per inch, pitch, etc.  That's all passed in options, I don't try to use
more than one, so beware of quotes/apostrophes.

You'll get some astonishing transfer rates!  My lamebrained lp approach is
what I cobbled together because I don't have lpr/lpd and (you can probably
tell :-) probably wouldn't understand them if I did.  Don't forget, I didn't
claim that this was elegant, just that it works...
-- 
Bill Kennedy  usenet      {att,cs.utexas.edu,pyramid!daver}!ssbn.wlk.com!bill
              internet    bill@ssbn.WLK.COM   or attmail!ssbn!bill

marc@dumbcat.sf.ca.us (Marco S Hyman) (11/18/90)

In article <1861@ssbn.WLK.COM> bill@ssbn.WLK.COM (Bill Kennedy) writes:
    Now you have to work up your network address.  We'd have _never_ figured
    this out without ISC's help!  This is a hex string that is composed of
    address family (AF_INET), port number, IP address, and padding zeroes.
    Here is the format and an example:

    \x02000100c0fafa010000000000000000    mapped as
      aaaappppiiiiiiiizzzzzzzzzzzzzzzz
      |   |   |       +------------------ sixteen padding zeroes
      |   |   +-------------------------- IP address 192.250.250.1 co.fa.fa.01
      |   +------------------------------ port address fm /etc/services (256)
      +---------------------------------- address family, socket address

Not too suprising. One of the disadvantages of TLI (IMHO) is that the
format of the addr field in the t_{bind,call,unitdata,uderr} structures is
implementation dependent, e.g. "The responsibility of the transport
provider."  Since a socket interface library usually (always?) comes with
TCP-IP, even when a TLI is used, the address format used is that of a
struct sockaddr.  Saves having to support multiple address formats, I guess.
Anyroad, the format is

    struct sockaddr {
	u_short	sa_family;		/* address family */
	char	sa_data[14];		/* up to 14 bytes of direct address */
    };

in its most generic form.  The internet style definition (when sa_family ==
AF_INET) is:

    struct sockaddr_in {
	short	sin_family;
	u_short	sin_port;
	struct	in_addr sin_addr;
	char	sin_zero[8];
    };

This should look familiar -- it's what you entered above.  Isn't it nice to
know that when writing code using TLI you have to know who implemented the
transport providor protocols to know the address formats to use.


// marc
-- 
// marc@dumbcat.sf.ca.us
// {ames,decwrl,sun}!pacbell!dumbcat!marc

ssb@quest.UUCP (Scott S. Bertilson) (12/05/90)

  Bill Kennedy's article answered some questions I've wanted to know
answers to for a very long time.  I've often thought that there must
be a way to make an Altos 386/2000 (which runs AT&T UNIX SVR3 with
Lachmann TCP/IP) use streams to make a UUCP connections to and from
it.  Bill's notes got me most of the way there.  I had a slight
problem with "nlsadmin" in that the "-l"/"-s" options don't work
quite the same.  To be specific, Bill's directions said to use
	nlsadmin -l "\x02000100c0fafa010000000000000000" tcp
which gets stored in "/usr/net/nls/tcp/addr".  The problem comes
because the Altos (?) version of "nlsadmin" doesn't strip the "\x"
when you say "nlsadmin -s tcp" whereas (for example) SCO ODT
does.  I was able to work around this problem by specifying the
address by:
	nlsadmin -l 02000100c0f700030000000000000000 tcp
  I found that I could contact this server even from a non-streams
machine if I gave a bogus "nls" string as the first thing in a
"telnet" connection:
	telnet system 256
	NLPS:000:001:101^@
The ^@ is a null byte which seems to be the way that the "nls"
string is terminated.
  I also did a little hacking and found that I could call a
non-streams TCP/IP machine from our Altos using either "cu" or
"uucico" if I played a few games:

Systems:
	rem-sock Any qinet - \x02000201c0f700010000000000000000 "" \0\0\0\0\c in: log-in rd: pass-word
	rem-str Any qinetnls - \x02000100c0f700020000000000000000

Devconfig:
	service=cu	device=qinet	push=tirdwr
	service=uucico	device=qinetnls	push=tirdwr

Devices:
	qinet,eg inet/tcp - - TLIS \D
	qinetnls,eg inet/tcp - - TLIS \D nls

Dialers:
	nls	""	""	NLPS:000:001:101\N\c

  If you look closely at the address, you'll see that I specify that it
should connect to port 0x201 or 513 which is "rlogind".  Since I'm talk-
ing to "rlogind", I have to begin the conversation by sending 0 bytes
in place of local-username, remote-username, and terminal/speed.  On
the Altos, the TCP/IP devices are all in "/dev/inet", so we specify
"inet/tcp" instead of "tcp" as Bill was able to do.
  I've also included the hooks for "nls" connections.  I was pretty
excited about this until I discovered that Altos or SCO has stripped
out the generic streams code from the version of UUCP that we get
with our SCO ODT on the Altos 486/5000.  Another nit is that I
tried "push=ntty:tirdwr:ld0" and even though I've configured "ntty"
and "ld0" into my kernel, I get an error when either "uucico" or "cu"
try to push them.  Happily it doesn't seem to prevent things from
working, but I would like to know what they do and why they don't
work.  I sure would appreciate it if someone could tell me where
I can get documentation on streams addressing with Lachmann TCP/IP -
I really don't understand what the first 2 bytes mean - address
family would make sense except that it should be 2 bytes all by
itself and it should be 0x0002 instead of 0x0200.
  Hope this is helpful to other people using Altos machines.
-- 

Scott S. Bertilson   ...ssb@quest.UUCP
			scott@poincare.geom.umn.edu