If you've ever had the opportunity to work with any hardware-based routers,
security appliances, or intelligent switches, you're aware that these devices
typically don't have hard disks for permanent storage of their configurations
and underlying operating systems. Instead, they use a combination of volatile
and non-volatile RAM and an EEPROM
chip.

Since chips have far less storage capacity than hard drives, things get a
bit more interesting when you want to install or upgrade the operating system.
The operating system itself and the utilities that come with it will be
optimized to fit into a small space. Most of the utilities you're used to
finding on a computer's operating system will be missing. You won't find any
browsers or download utilities here! You also won't find any backup utilities,
even though you know the first rule in computing land is "backup, backup,
backup".

The most common utility used to accomplish device backups and upgrades is TFTP, the Trivial File
Transfer Protocol. This utility is similar to FTP, except that it has been
stripped down in functionality in order to fit onto a chip; hence, the
"trivial." Hardware devices, such as a Cisco router or switch, contain a TFTP
client. It is up to you to create a TFTP server somewhere in your network.
The TFTP server will store a backup copy of your configurations and the images
(or operating systems) of the hardware devices within your network.

Enabling a TFTP Server

Your FreeBSD system already contains a TFTP server, meaning you don't have
to install any additional software. You only have to enable the TFTP service
and properly configure a directory. Let's start by enabling the service. As the
superuser, use your favorite editor to open up /etc/inetd.conf.

You'll notice that this file contains several dozen lines of names of
services, and each has been commented out with a #. This is the
configuration file for inetd, the Internet Super Server. This
server listens on behalf of other services. When a request comes in for a
service, inetd will start the appropriate service. This reduces
system load, as one service can listen for requests rather than each service
having to listen separately.

In order to tell inetd to listen for TFTP requests, find the
two lines that start with #tftp and remove the comment from the
first line so it looks like this:

You'll note that FreeBSD supports both IPv4 and IPv6, so its
inetd is capable of listening for both types of requests. Also
note that TFTP uses UDP as its transport. This means it is not as reliable as
FTP (which uses TCP). It also means that TFTP supports broadcasts, meaning you
don't have to configure the TFTP client with the IP address of a particular
TFTP server.

Once you've removed the #, save your changes. You now need to
tell inetd that you've made some changes to its configuration file
by sending what is known as a "signal one." The easiest way to do this is with
the killall command:

# killall -1 inetd

If the command is successful, you will just receive your prompt back. Be
careful to include all three parts of that command. If you forget the
-1, you'll actually terminate the inetd process. But
don't worry, you can start it again by simply typing inetd.

If you instead receive the following error message:

# killall -1 inetd
No matching processes were found

inetd is not running. Again, simply type inetd to
start it. To make sure inetd starts if the TFTP server reboots,
add the following line to /etc/rc.conf:

Serving Files with TFTP

Now that the server is functional, you need to create a directory that will
be used by the TFTP server to store the backups of your hardware devices'
configurations and operating systems. This directory must be called
/tftpboot:

# mkdir /tftpboot

Next, populate this directory with the files you wish to download to your
hardware devices. For example, if you wish to upgrade your Cisco IOS, download
the desired image from the Cisco web site and save it to /tftpboot.
Most software images have rather complicated names, such as
c1600-ny-mz.112-11.P.bin. If you'll be serving many images, you
should document which devices are using which images.

You'll also want to create empty files for the files you'll upload from the
hardware devices themselves. These files can be called anything that is useful
to you. For example, if I wish to save the configurations from a 1602 router, a
PIX 501 firewall, and a 1924 switch, I could create the following files:

# touch 1602_config PIX_config 1924_config

Finally, since TFTP is a stripped-down version of FTP, it does not support
authentication. For this reason, this directory and its contents must be
accessible to your TFTP clients. Typically, this is accomplished by setting the
permissions like so:

# chmod -R 777 /tftpboot

Depending upon the TFTP client built into the hardware device you are
using, you may be able to successfully use stricter permissions. Unfortunately,
with a Cisco device, it will fail unless the permissions are set this way.
When you're finished, verify the permissions in the directory:

Speaking TFTP to the Server

You should now have an operational TFTP server. Since your FreeBSD system
also has a TFTP client, you can test that the server is set up to properly
transfer files. First, tftp to the address of your TFTP server as
a regular user. If the server responds, your prompt will change. Here, I will
use the tftp client from the same computer that is the TFTP
server:

$ tftp 127.0.0.1
tftp>

If you type ?, you'll see that the tftp client
supports few commands. The ones you'll use most often are get to
download a file, put to upload a file, and quit to
exit the utility. If you're used to using the ftp client, you'll
notice the absence of cd, ls, mget,
mput, and several dozen other supported FTP commands.

Now, try to get one of the files; your transfer will be more
exciting if you pick a non-empty file. Here, I'll transfer an image file:

tftp> get c1600-ny-mz.112-11.P.bin
Received 4194172 bytes in 1.6 seconds

I'll then quit the utility:

tftp> quit

There's a couple of important points regarding this file transfer. First, it
won't work if the file you want to transfer is not in /tftpboot.
Notice when I used the get command that I didn't specify the path
to the file, simply the filename. If I had tried this command instead, I would
have received the following error message:

tftp> get /tftpboot/c1600-ny-mz.112-11.P.bin
Error code 1: File not found

Remember, tftp assumes that the file you want to transfer
already exists and that it is located in /tftpboot. Second, make
sure you spell the filename correctly. This is especially important with those
long image filenames. If you're a terrible typist, you'll miss filename
completion, as it's not supported by tftp. This is another reason
why it is a good idea to document the files stored in /tftpboot
and to check your spelling when you use the get command.
Otherwise, you'll end up getting frustrated by "Error code 1" messages.

You may have noticed that I didn't specify where to put the file that was
transferred using get. This is because it is automatically copied
to the current working directory. Typically, this isn't a problem on a hardware
device, but it is something to keep in mind should you ever initiate a
tftp session using your FreeBSD computer.

Finally, you should use ls -l to verify that the number of
bytes received matches the number of bytes in the file stored on the TFTP
server. This is also a handy bit of information to have documented. If you have
a printer attached to your FreeBSD system, you can easily print out the
contents of /tftpboot once you've finished configuring the TFTP
server:

$ ls -l /tftpboot | lpr

Uploading Images via TFTP

Now that I'm satisfied the TFTP server is operational, I'll demonstrate
uploading that image file to a Cisco 1602 router. Once I'm connected to the
router, I'll input the password required to enter privileged mode:

1602> enable
Password:
1602#

Before starting the TFTP client, you should always verify connectivity to
the TFTP server by pinging its IP address:

1602# ping 10.0.0.100
!!!!!

On a Cisco router, ! indicates a successful ping. If you
instead receive a series of .s, the ping is timing out, which
indicates a connectivity problem.

I'll then invoke the router's built-in TFTP client by using the following
command:

1602# copy tftp flash
^^^^NOTICE^^^^
Flash load helper v1.0
This process will accept the copy options and then terminate the
current system image to use the ROM based image for the copy. Routing
functionality will not be available during that time. If you are logged
in via telnet, this connection will terminate. Users with console
access can see the results of the copy operation.
---- ^^^^^^^^ ----
Proceed? [confirm]

After reading the warning message, press Enter to confirm the operation.
You'll then be presented with the name of the current operating system on the
router and the amount of memory available on the EEPROM chip:

If you press Enter here, you'll receive the default value enclosed in square
brackets, or the broadcast address. This means the TFTP client will send a
broadcast onto the network looking for a TFTP server. If there are any
intervening routers between this hardware device and the TFTP server, they will
most likely discard the broadcast. To prevent that from happening, type in the
IP address of your TFTP server.

Next, you'll be prompted for the source filename. That is, the filename of
the image that you would like to download from the TFTP server. Remember, it's
important not to mistype the name of the file in order for the transfer to
succeed. I'll type in the name of my image:

Source file name? c1600-ny-mz.112-11.P.bin

Next, you'll be prompted for the destination filename. That is, what you
would like the file to be called when it is copied to the router's EEPROM chip.
Technically, you could change the filename to anything you want, but usually
you keep the original image name, like I have done here:

Destination file name? c1600-ny-mz.112-11.P.bin

Now comes the moment of truth:

Accessing file 'c1600-ny-mz.112-11.P.bin' on 10.0.0.100...

If you get an "Error code 1," the command will abort and return you to the
command prompt. This means you have a typo in the "source file name," so repeat
the command and try again. If you're sure you spelled the image name correctly,
it's time to go to the TFTP server and ensure the file still exists in
/tftpboot and is indeed spelled the way you are typing it.

If you receive a permissions problem, double-check the permissions of the
image on the TFTP server. Chances are, you forgot to set them to
777.

If all goes well, the TFTP client will continue and give you output similar
to this:

You should double-check that the bytes transferred over match up with the
number of bytes in the image file on the server. In my case, the 4194172
matches up and the checksum indicates that it is OK. If you received many
.s or timeouts during the transfer, you should check your network
connectivity and consider redoing the transfer. Finally, before rebooting the
router into the new operating system, double-check that the correct image is
indeed in the EEPROM chip:

Conclusion

Let's recap the steps necessary to configure your FreeBSD system as a TFTP
server:

Remove comment from /etc/inetd.conf.

Send signal one to inetd.

Create the /tftpboot directory.

Populate the /tftpboot directory.

Set permissions on the /tftpboot directory and its contents to
777.

I demonstrated one use of a TFTP server: upgrading the image file on a Cisco
router. If you have any hardware devices in your network, read their
documentation to see the syntax of the command each uses in order to access the
files you have stored on your TFTP server.

There are additional uses for a TFTP server. You may find some of the
following URLs useful as launching points into your own experiments:

Just keep in mind that TFTP is designed for transferring files to and from
chips on hardware devices. If you want to transfer files from one computer to
another, TFTP is not the answer. There are many other options available that
offer far more functionality and usually, more security.

In the next series of articles, I want to take a look at proxies and
configuring proxy servers and proxy clients.

Dru Lavigne
is a network and systems administrator, IT instructor, author and international speaker. She has over a decade of experience administering and teaching Netware, Microsoft, Cisco, Checkpoint, SCO, Solaris, Linux, and BSD systems. A prolific author, she pens the popular FreeBSD Basics column for O'Reilly and is author of BSD Hacks and The Best of FreeBSD Basics.