[fa.tcp-ip] tftp for bootstrap

tcp-ip@ucbvax.ARPA (07/03/85)

From: sun!l5!gnu@BERKELEY (John Gilmore)

Sun would like to use "standard" protocols for diskless bootstrap in
new products.  We're looking at tftp/rarp/arp as described in RFC 906
and have run into some trouble which I hope the Internet community can
shed some light on.

How do you put useful information in a name that contains only
alphanumeric characters?  We'd like to put either the machine's
internet address e.g. 192.9.1.23, or its machine type e.g. Sun-2/120,
in the name, but these both use punctuation and don't work very well if
run-together.

It's not clear how many systems will do a tftp file transfer of an
unqualified name (without any directory specified) or whether you want
to put a set of boot files in the directory it would pick for that
case.

It's not clear whether upper and/or lower case letters are possible or
preferred.

[My personal preference would be a SunRPC based boot protocol, but
SunRPC has not seen much use in the Internet yet, is not as "standard"
as tftp, and would require people to port RPC if they wanted to boot
from non-Unix machines.  How big a problem are these?]

[Note that the protocol and administrative setup required would also
be used for booting from Sun servers, thus it must be easy to set up and
explain and administer.]

tcp-ip@ucbvax.ARPA (07/03/85)

From: "J. Noel Chiappa" <JNC@MIT-XX.ARPA>

	MIT has used TFTP to boot diskless gateways for about 5 years
now. It works quite well. We really like TFTP since it is a standard
IP protocol and machines usually come with server TFTP implementations.
	We handle the 'punctuation characters' problem by using a file
name that consists of the IP address with all the fields three characters
long; thus, a gateway at 18.10.0.11 would boot from a file named
'018010000011'. (Actually, we use octal because we are wierd, but you
get the idea).
	In general, we use built in configuration information, kept in
some non-volatile storage. While you can avoid this on an Ethernet
with broadcast, this method does not work on non-broadcast nets. In
general, the spirit of IP is that the 'base solution' to any problem
should work on a non-broadcast net with no gateways. We thus feel that
having some small non-volatile store for information such as which
directories to look in on which hosts is reasonable.

	Noel
-------

tcp-ip@ucbvax.ARPA (07/04/85)

From: jas@proteon.arpa

I'd agree with Noel about the need to some small EAROM or such
for the configuration data.

You might consider using the domain nameserver protocols to get
additional information beyond that in the EAROM. (I don't love
these protocols, but I guess there here for good now...) The HINFO
record has the CPU type and O/S. You might invent a new
record type for booting information. (Sometimes is it better
to tweak an existing protocl a little than develop a new one.)
Of course, this requires keeping the address of a domain nameserver
in EAROM.

My TFTP does have a default directory, but I suspect that this is
very rare. Most need fully qualified names. I suspect that servers
are case sensitive if the O/S behind them is, otherwise not.

I suspect the hard facts of life would point at some amount of data
being kept in EAROM (or EPROM). Once you surrender this point,
the rest gets rather easy.
-------

tcp-ip@ucbvax.ARPA (07/04/85)

From: Jeff Mogul <mogul@Navajo>

One thing you might want to consider is a multi-stage bootstrap, where
TFTP is used to load a small program that then determines (via NFS
or whatever you prefer) what the host's configuration should be.

For example, we have Suns here that run the V-system (instead of
Sun Unix.)  They load a short program called Vload, using whatever
protocol Suns bootload with.  Vload then reads a configuration
file (located using the hardware ethernet address as an identifier)
which says what programs should really be loaded.  Vload uses
the V protocols (which is unfortunate but that's another story)
to read the config file and load the real program; all that is
needed from the original bootstrap protocol is the ability to
load the second-phase bootstrap program.

The point here is that the non-volatile storage need not reside
on the workstation or whatever; as long as the first-phase boot
program can find a database on some server, either by broadcast
or by wiring the server address into the code, the rest is
just a matter of chasing pointers.

I think TFTP is preferable to ND or NFS or FTP or whatever because
it's extremely simple, which is important when it has to be squeezed
into a ROM, and because it's widely available, unlike certain
manufacturers' proprietary protocols.  If you only care about
loading Suns as Suns, then using NFS might make sense because
of efficiency or convenience; if you care about loading a variety
of hosts with a variety of operating systems, then TFTP makes
more sense because it's simpler and more available.

As to the problem of default directories:  perhaps what we
need is to separate the TFTP protocol from the intended use.
TFTP is currently expected to listen on port 69, but there
is no reason why a TFTP-based boot server couldn't listen on
some other port; the port-69 server would not need a default
directory, while the behaviour of the port-XX server would be
defined so that alphanumeri-only file names would refer to a
default directory.  Alternatively (this is what our pseudo-ND
server does), the TFTP-boot server might be allowed to look
at the requesting host address to look up in a database which
file to download.

tcp-ip@ucbvax.ARPA (07/05/85)

From: lewis <lewis@sri-tsc>

We have been using a loader server for several years to load TIUs, BBN
and Jeff Mogul also use versions of it to load GWYs. In our user testbeds,
the same physical hardware is a multifunction box, depending on which
module is loaded. We have found that the users often complained that
the server was down, when in fact they specified improper file name
syntax. This caused us to come up with two changes.

There is a data base on the server hosts, which maps requestor's
internet IDs to load file names (TOPS20 or Unix pathnames, depending on
server).  Wildcards in the database for Internet IDs exist to shorten
the list.  A default load then retrieves the file found in the
database.  In addition, Internet IDs with or without wildcards can be
paired with another database file name, allowing separation of database
administration for different hosts and ranges of hosts. Alternatively,
the user can specify a file name to be loaded from the server.

The first change involves finding the file to boot. If the user specifies
any file, the database is not queried. To make it easier for the user
to remember how to specify file names, we now allow suffixes to be left
off and uppercase is converted to lower, and preceding blanks
( MYLOAD is myload.ext). In this case the default directory is searched.
If the file name requested begins with a system directory delimiter,
"<" on TOPS20 or "/" on Unix, the server takes the request literally,
for people who supposedly know what they want.

The second change, not implemented yet, is to return a text string to
indicate the status. Currently, if the file is not found, the only
perception the user has is the three minute timeout. The string packet
should probably be allowed asynchronously with loading progress.
It could report (file not found / illegal file name / file broken / etc.).

The servee code resides in about 6K bytes nonvolatile memory, and the
internet address is used as the database key for default booting.
Probably some mechanism for privacy/accounting should be considered.

-Mark Lewis

tcp-ip@ucbvax.ARPA (07/05/85)

From: "J. Noel Chiappa" <JNC@MIT-XX.ARPA>

	You mentioned the lack of error messages; TFTP already provides
them, and the bootstrap we run prints them.
-------

tcp-ip@ucbvax.ARPA (07/08/85)

From: sun!l5!gnu@BERKELEY (John Gilmore)

I personally don't see much point in using tftp as a boot protocol
UNLESS it will talk to existing servers.  We might as well use our
existing "nd" protocol if the only thing it will ever talk to is
other Suns.

The responses I've gotten tend strongly toward the "we did it kinda
that way and it has worked for N years" type of stories, which are OK
but not much help.  I guess what I'm looking for is a good reason to
boot with TFTP (nobody has yet said "we did it another way and are
really sorry"), and some help in designing the protocol above TFTP (the
file name, how we find the server), to let it interoperate with other
Internet machines with minimal or no effort.  It seems like the war
stories all describe schemes where a custom boot server exists (maybe
running TFTP but not the way it's spec'd for everybody, eg odd port #,
odd file types).

Can I focus this discussion to answer a specific question?  What does
YOUR system's TFTP server do with a file name in a RRQ which does not have
any pathname delimiters?  Reply to me (sun!gnu@Berkeley.arpa) and I'll
summarize to the list.

tcp-ip@ucbvax.ARPA (07/08/85)

From: imagen!geof@su-shasta.arpa


I must confess that my comments should really be in conjunction with
Noel Chiappa's, since we are referring to the same set of TFTP
implementations.  I worked on some of the TFTP implementations while I
was at MIT.

My last message should only be read in context -- I agree that TFTP is
no better a protocol than most others for bootloading, except insofar as
it is possible to use other server implementations of TFTP.

It is not necessary to modify a TFTP server from its "vanilla" state to
make it useable for bootloading.  The modifications that were done at
MIT mostly were because some machines had TFTP has their only file
transfer protocol (specifically, the UPDATE mode).

The MIT implementations of TFTP all met spec (I presume they all still
do), and few had hidden features.  All ran on port 69.  Some efforts
were occasionally made to make sure that the implementations at MIT and
ISI were able to interconnect.  File names which were received were
handed by the server to the operating system, and interpreted in the
security and naming contexts of the server.  As additional security
measures:
	- all servers refused to overwrite existing files
	- the servers on Tops-20 and Multics were sufficiently isolated
	  from a security point of view that the server had (by default)
	  very little access to most user's files and directories.  On
	  multics, the server had to be explicitly permitted to access
	  a portion of the directory tree.
	- on berkeley Unix, the server explicitly tested protections to
	  verify that global read (or write) access existed where it 
	  was needed. This was necessary because the server had to run
	  as root to be able to access socket 69, so our initial
	  attempts to just have the server attempt to open the file and
	  let the OS apply some default set of protections wouldn't work
	  (interesting how in this case a security feature turned out
	  to be a security bug).
On most of the machines, the server would also reject any file transfer
for which no directory was specified (the exception was the alto
implementation, because there were no directories to speak of).  On
Tops-20, a device or directory spec had to be specified, but it was not
necessary to specify both.

For purposes of bootloading, a special directory was set up on each
machine.  The name of the directory was configured into the
gateways, as was each machine's internet address.  For reasons of code
size, the bootloader was typically only able to use one interface. 
However, the gateways were able to boot through each other, so
bootloading was possible from a wide variety of machines.

Since gateway code was different for each gateway, the boot files for
each gateway were named by concatenating the address of the gateway
together.  As Noel pointed out, this is easy to keep track of if you
assign three letters to each byte for decimal or octal number
(alternately, use hex).  When booting, the gateway sent a read request
to each host for a file whose name was the concatenation of the prefix
for that host and the internet address of the gateway, unparsed as an
octal string with three digits for each byte.  The transfer mode was
mode "image." The intent of mode "image" is that a file which is
transferred to a host using it and then transferred back ends up with
the same bits in it (perhaps a few more tacked onto the end); it is
perfect for bootloading.  We simply distributed the boot-code using
TFTP mode image (with a little telnet fudging to delete the original
first, see below) from the source, and were confident that it would be
read back correctly.  This worked on Alto's, Unices, Tops-20, and
Multics (the latter two used different ways of storing the Image files
- Tops-20 used 8-bit bytes with 4 bits of each 36 bit word wasted, and
multics stored the bits sequentially in 36-bit words, ignoring word
boundaries).

The obvious way to use TFTP for bootloading is to have the gateway send
a read request to every host in the list at once, and to accept the
first response (and eventually reject any other responses).  This is
analogous to a broadcast request for booting.  I'm not sure if the
gateway did this in practise, or just tried the hosts in sequence.

So, in summary, TFTP is a good bootloading protocol, without
modification:
	- It supports a pseudo-broadcast mode of booting request.
	- It has a transfer mode that works.
	- It is fast enough.
	- It is simple (the original TFTP bootloader fit into 2Kb of
	  ROM).
	- It is an internet protocol (you can boot through gateways -
	  for a while at MIT we had two gateways booting off a network
	  which had no other hosts on it.  Each booted through the
	  other.  Worked for weeks until the power flickered one day...
	  then we had to get out the old serial-line downloader).
Problems:
	- You have to derive an Internet address for the host to be
	  able to use an internet protocol to boot it.  On an ethernet
	  this is more of a problem.

	- You have to store both the names of the boot directories on
	  each boot-host and the internet addresses of the boot hosts
	  (in practise, there was only one boot rom that
	  had all the hosts and directories in it; each gateway could
	  not access some of the hosts in its table).
	  This problem is minimized in a homogeneous environment, since
	  the name of the directory can be the same everywhere.

	- It is an Internet protocol, so that broadcast is not a
	  "native" mode of using it.  If your nodes implement internet
	  broadcast (I guess sun's still use host number 0 for
	  broadcast, like the vaxen do...) you could theoretically use
	  it, although as Noel points out, there are advantages to being
	  able to boot through a gateway when necessary.

One compromise position might be to use a broadcast scheme to get the
booting information into the host, then use TFTP to boot the host. 
This would have the effect of compartmentalizing the nonstandard code 
in the system, and would add a more minor restriction to booting a
host.  Or use a "breath of life" scheme.  Have a host periodically
broadcast the booting information on the network in question, and have
the bootloader just wait for the promiscuous packet to arrive.  The
advantage of this scheme is that you don't have to have any broadcasting
booters on the local net -- they can use directed broadcast to send
the breath of life packets.

- Geof

tcp-ip@ucbvax.ARPA (07/09/85)

From: Bill Croft <croft@safe>

John,

I guess what I would like to see in your new SUN Microsystems boot
proms (and adopted as an internet standard) is a TWO PHASE boot:

	(1) The 'server location / address assignment' phase could use a
	simple UDP broadcast packet exchange.  This exchange allows the
	booting client to locate boot servers by name.  The same protocol
	can also be used to assign an IP address to the client, given
	his ethernet address.  A sample packet exchange of such a protocol is
	shown below.

	(2) The second phase corresponds to the TFTP file transfer of
	the load image, given that the client knows his IP address,
	the servers IP address, and the file name.   Optionally the
	client may also load through gateways if he knows a default
	gateway address.

The boot is split into these two phases because the first is more volitile
and likely to change than the second.  Given that there are many TFTP
'boot/load servers' already running in the internet, it would be 
great to be able to utilize this resource.  I could imagine that your
boot code would have several entry points.  The default 'power up' boot
might go through both phases.  However a manual entry point would allow
the user to begin just the second phase, by supplying the IP addresses
and pathname string mentioned above.  Further, if the hardware had an
EAPROM capability, a 'default' second phase boot could be completed
automatically, if the person wished to make that setup option.

Note that both phases of this booting use ONLY INTERNET protocols.  This
is in contrast to the proposed RFC903 "A Reverse Address Resolution
Protocol".  RFC903 proposes that we use a new ethernet link type (not ARP,
but RARP) to allow a client to find his own IP address, given his ethernet
address.  But RFC903 can only be implemented with kernel modifications;  e.g.
by using the 'CMU packet filter' kernel code, or some new (as yet
unwritten and unstandardized) IOCTL interface to the kernel to load this
RARP information from the boot servers.

Instead what you can do is have the first phase server BROADCAST his
reply to the requesting client.  This is only one more broadcast than
the RFC903 case, but it now allows all the boot server processes to
be simple UDP servers at user level with no kernel changes.  Even if
you did find a way to modify the kernel for RFC903, how are you going
to get these mods out to all the different UNIX box companies?  What
about booting from TOPS20?  Etc.  I think the advantages are overwhelming
for restricting the boot protocol to use only IP/UDP.


EXAMPLE PACKET EXCHANGE OF FIRST PHASE BOOT

BOOTREQUEST packet from diskless client to server:

	IP DST: 255.255.255.255
	IP SRC: 0.0.0.0			[i.e. I don't know it yet]
	PROTO: UDP
	PORT: bootport
	----- packet data is:
	OPCODE: BOOTREQUEST
	MY ETHERADDR: xx xx xx xx xx xx
	FILENAME: xxxxxx
	SERVERNAME: yyyyyy		[optional]

Then the boot server answers back, with a broadcast [only to this first
exchange] so that we neatly bypass all the ARP bootstraping problems.
After the client has his real IP address (and that of the server),
a normal TFTP file read occurs.  The client only accepts a BOOTACK with
a CLIENT'S ETHERADDR that matches his own.

BOOTACK packet from server to client:

	IP DST: 255.255.255.255
	IP SRC: server IP address
	PROTO: UDP
	PORT: bootport
	----- packet data is:
	OPCODE: BOOTACK
	CLIENT'S ETHERADDR: xx xx xx xx xx xx
	CLIENT'S IP ADDR: xx xx xx xx
	DEFAULT GATE ADDR: xx xx xx xx
	FILEVERSION: xx
	FILEDATE: xx

tcp-ip@ucbvax.ARPA (07/09/85)

From: Christopher A Kent <cak@Purdue.EDU>

Bill,

Your protocol sounds really nice, except that IP broadcasting doesn't
exist. 

Maybe this will provide the grease to get the wheels in motion again.

chris
----------

tcp-ip@ucbvax.ARPA (07/10/85)

From: David C. Plummer in disguise <DCP@SCRC-QUABBIN.ARPA>

    Date:  8 Jul 1985 1633-PDT (Monday)
    From: Bill Croft <croft@safe>

    John,

    I guess what I would like to see in your new SUN Microsystems boot
    proms (and adopted as an internet standard) is a TWO PHASE boot:

	    (1) The 'server location / address assignment' phase could use a
	    simple UDP broadcast packet exchange.  This exchange allows the
	    booting client to locate boot servers by name.  The same protocol
	    can also be used to assign an IP address to the client, given
	    his ethernet address.  A sample packet exchange of such a protocol is
	    shown below.

A more general scheme for this (actually, getting the IP address), which
unfortunately requires implementing a slightly new protocol set is to
implement inverse ARP (most servers can use existing forward ARP tables;
with a full backup in the file system).  That is, instead of saying
"What's your Ethernet address" it says "What's my protocol address."  We
almost did this at MIT, but the need didn't come up.  If anybody is
really interested I can try to find the full description (it's pretty
trivial; just take ARP and rearrange a few fields).

    EXAMPLE PACKET EXCHANGE OF FIRST PHASE BOOT

    BOOTREQUEST packet from diskless client to server:

	    IP DST: 255.255.255.255
	    IP SRC: 0.0.0.0			[i.e. I don't know it yet]
	    PROTO: UDP
	    PORT: bootport
	    ----- packet data is:
	    OPCODE: BOOTREQUEST
	    MY ETHERADDR: xx xx xx xx xx xx
	    FILENAME: xxxxxx
	    SERVERNAME: yyyyyy		[optional]

    Then the boot server answers back, with a broadcast [only to this first
    exchange] so that we neatly bypass all the ARP bootstraping problems.
    After the client has his real IP address (and that of the server),
    a normal TFTP file read occurs.  The client only accepts a BOOTACK with
    a CLIENT'S ETHERADDR that matches his own.

    BOOTACK packet from server to client:

	    IP DST: 255.255.255.255
Why 255.255.255.255.  Shouldn't this be "CLIENT'S IP ADDR"?
	    IP SRC: server IP address
	    PROTO: UDP
	    PORT: bootport
	    ----- packet data is:
	    OPCODE: BOOTACK
	    CLIENT'S ETHERADDR: xx xx xx xx xx xx
	    CLIENT'S IP ADDR: xx xx xx xx
	    DEFAULT GATE ADDR: xx xx xx xx
	    FILEVERSION: xx
	    FILEDATE: xx

tcp-ip@ucbvax.ARPA (07/12/85)

From: Bill Croft <croft@safe>

Dave,

That is a good point, if the server sending the 'bootreply' packet
has the kernel hooks to allow him to fill in an ARP table entry
'by hand', then the server CAN send the packet to the client's
new IP address.  I will mention this point in the RFC I am preparing.
However if such kernel hooks are missing from a particular operating
system, broadcasting the bootreply (as I mentioned earlier) is the
only way to get the packet out the door.

tcp-ip@ucbvax.ARPA (07/12/85)

From: Bill Croft <croft@safe>

----
>Date: 09 Jul 85 13:30:31 EST (Tue)
>From: Christopher A Kent <cak@Purdue.EDU>
>
>Your protocol sounds really nice, except that IP broadcasting doesn't exist. 
>
Well it is implemented (perhaps non-standardly) in many Berkeley UNIXes.  
I hope that 4.3BSD implements the recommendations made by 
Jeff Mogul in RFC919/922.
Those RFCs use various forms of an IP address consisting of 'all ones'
or mostly ones to represent the broadcast address.

----
>Date: Wed, 10 Jul 85 08:45 EDT
>From: David C. Plummer in disguise <DCP@SCRC-QUABBIN.ARPA>
>
>A more general scheme for this (actually, getting the IP address), which
>unfortunately requires implementing a slightly new protocol set is to
>implement inverse ARP (most servers can use existing forward ARP tables;
>
Dave, my argument was that it would be best to implement the first
phase protocol as ONLY an IP/UDP protocol.  This way the server can be
a user-level process (on UNIX, Multics, TOPS20, etc.) without requiring
kernel/operating system mods necessary for the "reverse ARP solution".
The authors of RFC903 DID implement 'reverse ARP' here at Stanford,
but it required using the 'CMU packet filter' kernel code to allow
a user-level server process to access arbitrary ethernet link level
packet types.  Any 'reverse ARP' scheme is going to require kernel
mods;  given that there are many different kernels out there now,
with each source maintained by different organizations, a boot
protocol that does not require kernel modifications I think is
an overwhelming advantage.

In addition, the protocol I illustrated provided several other pieces
of information that "reverse ARP" lacks:  (1) it allows server specification
by name, instead of just address;  (2) it returns IP addresses of
both the client and of gateways on the cable, to allow cross-net booting;
(3) it returns 'qualified' filename / version / date information.
Item #3 allows the client to specify a generic name in the bootrequest
(e.g. 'unix') and then the bootreply from the server could contain
a qualified name based upon database lookups at the server, indexed by
the client's hardware address.  For example, the person performing the
boot may ask to 'boot unix';  the bootreply returned from the server
may contain the qualified pathname '/usr/boot/vmunix123';  the second
phase boot (TFTP) then does a transfer of this new name.

>Why 255.255.255.255.  Shouldn't this be "CLIENT'S IP ADDR"?
>
In the first phase, since the client DOESNT KNOW his IP address yet,
if the server sent the reply to the client's (new) IP address, the
server's ARP module would be unable to discover the client's hardware
address.  That is why the server must broadcast this bootreply
packet.  I claim the slight extra overhead of this extra broadcast
is well worth it, since it allows our first phase server to use
only existing IP/UDP transmission (instead of implementing new
ethernet link types in the kernel).

tcp-ip@ucbvax.ARPA (07/13/85)

From: David C. Plummer in disguise <DCP@SCRC-QUABBIN.ARPA>

    Date: 10 Jul 1985 1008-PDT (Wednesday)
    From: Bill Croft <croft@safe>

    >Why 255.255.255.255.  Shouldn't this be "CLIENT'S IP ADDR"?
    >
    In the first phase, since the client DOESNT KNOW his IP address yet,
    if the server sent the reply to the client's (new) IP address, the
    server's ARP module would be unable to discover the client's hardware
    address.  That is why the server must broadcast this bootreply
    packet. 
Nope.  Recall that the user end already told the server end what the
Ethernet address is (otherwise how could the server backtranslate that
into an IP address?).  Therefore, it /should/ be a trivial matter to add
this into the ARP tables so it goes direct to the user end.

Anyway, a better argument against my proposal is that it requires the
user and server to be on the same cable.