When networking protocols work only with a single kind of physical network, there is no need to identify the network interface to the software. The software knows what the interface must be; no configuration issues are left for the administrator. However, one important strength of TCP/IP is its flexible use of different physical networks. This flexibility adds complexity to the system administrator’s task, because you must tell TCP/IP which interfaces to use, and you must define the characteristics of each interface.
Because TCP/IP is independent of the underlying physical network, IP addresses are implemented in the network software—not in the network hardware. Unlike Ethernet addresses, which are determined by the Ethernet hardware, the system administrator assigns an IP address to each network interface.
In this chapter, we use the ifconfig (interface configure) command to
identify the network interface to TCP/IP and to assign the IP address,
subnet mask, and broadcast address to the interface. We also configure a
network interface to run Point-to-Point Protocol (PPP), which is the
standard Network Access Layer protocol used to run TCP/IP over modem
connections.
During a real installation the system administrator is isolated from
most of the details of the network configuration. The installation program
prompts the administrator for information, places that information in
script files, and then uses the scripts to configure the interface at
every boot. In this chapter we look beyond the superficial to see how
things actually work by examining the details of the ifconfig command and the scripts that invoke the
command. Let’s begin with a discussion of ifconfig.
The ifconfig command sets, or checks, configuration values for network
interfaces. Regardless of the vendor or version of Unix, the ifconfig command sets the IP address, the
subnet mask, and the broadcast address for each interface. Its most
basic function is assigning the IP address.
Here is the ifconfig command
that configures the Ethernet interface on a Solaris system:
# ifconfig dnet0 172.16.12.2 netmask 255.255.255.0 broadcast 172.16.12.255Many other arguments can be used with the ifconfig command; we discuss several of these
later. But a few important arguments provide the basic information
required by TCP/IP for every network interface. These are:
The name of the network interface that you want to configure for TCP/IP. In the example above, this is the Ethernet interface dnet0.
The IP address assigned to this interface. Enter the address as
either an IP address (in dotted decimal form) or as a hostname. If
you use a hostname, place the hostname and its address in the
/etc/hosts file. Your system must be able to find the hostname
in /etc/hosts because ifconfig usually executes before DNS
starts. The example uses the numeric IP address 172.16.12.2 as the
address value.
The address mask for this interface. Ignore this argument only if you’re using the default mask derived from the traditional address class structure. The address mask chosen for our imaginary network is 255.255.255.0, so that is the value assigned to interface dnet0. See Chapter 2 and Chapter 4 for information on address masks.
The broadcast address for the network. Most systems default
to the standard broadcast address, which is an IP address with all
host bits set to 1. In the ifconfig example we explicitly set the
broadcast address to 172.16.12.255 to avoid any confusion, despite
the fact that a Solaris 8 system will set the correct broadcast
address by default. Every system on the subnet must agree on the
broadcast address.
In the example above, we use keyword/value pairs because this makes explaining and understanding the syntax easier. However, Solaris does not require that syntax. The following (much shorter) command does exactly the same thing as the previous one:
# ifconfig dnet0 172.16.12.2/24In this command the network mask is defined with an address prefix and the broadcast address is allowed to default. A prefix length of 24 is the same as 255.255.255.0. The default broadcast address given that prefix length is 172.16.12.255.
The network administrator provides the values for the address,
subnet mask, and broadcast address. The values in our example are taken
directly from the plans we developed in Chapter 4. But the name of the interface,
the first argument on every ifconfig
command line, is determined by the system during startup.
In Chapter 5, we saw that Ethernet network interfaces come in many
varieties and that different Ethernet cards usually have different
interface names. You can usually determine which interface is used on
a system from the messages displayed on the console during a boot. On
many systems these messages can be examined with the dmesg command. The following example shows the output of the
dmesg command on two different
systems:
$ dmesg | grep ether Oct 1 13:07:23 crab gld: [ID 944156 kern.info] dnet0: DNET 21x4x: type "ether" mac address 00:00:c0:dd:d4:da $ dmesg | grep eth eth0: SMC EtherEZ at 0x240, 00 00 C0 9A 72 CA,assigned IRQ 5 programmed-I/O mode.
The first dmesg command in
the example shows the message displayed when an Ethernet interface is
detected during the boot of a Solaris 8 system. The string type "ether" makes it clear that dnet0 is an
Ethernet interface. The Ethernet address (00:00:c0:dd:d4:da) is also
displayed.
The second dmesg example,
which comes from a PC running Linux, provides even more information. On Linux systems,
the Ethernet interface name starts with the string “eth”, so we look
for a message containing that string. The message from the Linux
system displays the Ethernet address (00:00:c0:9a:72:ca) and the make
and model (SMC EtherEZ) of the network adapter card.
It is not always easy to determine all available interfaces on
your system by looking at the output of dmesg. These messages show only the physical
hardware interfaces. In the TCP/IP protocol architecture, the Network
Access Layer encompasses all functions that fall below the Internet
Layer. This can include all three lower layers of the OSI Reference
Model: the Physical Layer, the Data Link Layer, and the Network Layer.
IP needs to know the specific interface in the Network Access Layer
where packets should be passed for delivery to a particular network.
This interface is not limited to a physical hardware driver. It could
be a software interface into the network layer of another protocol
suite. So what other methods can help you determine the network
interfaces available on a system? Use the netstat and the ifconfig
commands. For example, to see all network interfaces that are already
configured, enter:
# netstat -in
Name Mtu Net/Dest Address Ipkts Ierrs Opkts Oerrs Collis Queue
lo0 8232 127.0.0.0 127.0.0.1 4504 0 4504 0 0 0
dnet0 1500 172.16.12.0 172.16.12.1 366 0 130 0 0 0The -i option tells netstat to display the status of all
configured network interfaces, and the -n tells netstat to display its output in numeric
form. In the Solaris 8 example shown above, the netstat -in command displays the following fields:
The Interface Name field shows the actual name assigned to the
interface. This is the name you give to ifconfig to identify the interface. An
asterisk (*) in this field
indicates that the interface is not enabled; i.e., the interface
is not “up.”
The Maximum Transmission Unit shows the longest frame (packet) that can be transmitted by this interface without fragmentation. The MTU is displayed in bytes and is discussed in more detail later in this chapter.
The Network/Destination field shows the network or the
destination host to which the interface provides access. In our
Ethernet examples, this field contains a network address. The
network address is derived from the IP address of the interface
and the subnet mask. This field contains a host address if the
interface is configured for a point-to-point (host-specific)
link. The destination address is the address of the remote host
at the other end of the point-to-point link.[50] A point-to-point link is a direct connection
between two computers. You can create a point-to-point link with
the ifconfig command. How
this is done is covered later in this chapter.
The IP Address field shows the Internet address assigned to this interface.
The Input Packets field shows how many packets this interface has received.
The Input Errors field shows how many damaged packets the interface has received.
The Output Packets field shows how many packets were sent out by this interface.
The Output Errors field shows how many of the packets caused an error condition.
The Collisions field shows how many Ethernet collisions were detected by this interface. Ethernet collisions are a normal condition caused by Ethernet traffic contention. This field is not applicable to non-Ethernet interfaces.
The Packets Queued field shows how many packets are in the queue, awaiting transmission via this interface. Normally this is zero.
The output of a netstat -in command
on a Linux system appears quite different:
$ netstat -in
Kernel Interface table
Iface MTU Met RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX-OVR Flg
eth0 1500 0 2234 280 0 0 1829 0 0 0 BRU
lo 16436 0 10 0 0 0 10 0 0 0 LRUThis output appears different, but as is often the case, appearances can fool you. Again we have the interface name, the MTU, and the packet statistics.[51] Here RX-OK is the total number of input packets, while RX-ERR (errors), RX-DRP (drops), and RX-OVR (overruns) added together give the total number of input errors. The total number of output packets is TX-OK, and the TX-ERR, TX-DRP, and TX-OVR counters provide the total number of output errors. Only two fields, Net/Dest and Address, that are provided in the Solaris output are not provided here. On the other hand, this display has two fields not used in the Solaris output. The Met field contains the routing metric assigned to this interface. The Flg field shows the interface flags:
R means the interface is running.
U means the interface is up.
B means it is a broadcast-capable interface.
L means it is a loopback interface.
This display shows that this workstation has only two network interfaces. In this case it is easy to identify each network interface. The lo0 interface is the loopback interface, which every TCP/IP system has. It is the same loopback device discussed in Chapter 5. eth0 is the Ethernet interface, also discussed previously.
On most systems, the loopback interface is part of the default configuration, so you won’t need to configure it. If you do need to configure lo0 on a Solaris system, use the following command:
# ifconfig lo0 plumb 127.0.0.1 upThis example is specific to Solaris because it contains the plumb option. This option literally creates the “plumbing” required by the network interface the first time it is configured. Subsequent reconfigurations of this interface do not require the plumb option, and other systems, such as Linux, do not use this option.
The configuration of the Ethernet interface requires more attention than the loopback interface. Many systems use an installation script to install Unix. This script requests the host address, which it then uses to configure the interface. Later we’ll look at these scripts and what to do when the user does not successfully set up the interface with the installation script.
The ifconfig command can also be used to find out what network
interfaces are available on a system. The netstat command shows only interfaces that
are configured. On some systems the ifconfig command can be used to show all
interfaces, even those that have not yet been configured. On Solaris 8
systems, ifconfig -a does this; on
a Linux 2.0.0 system, entering ifconfig without any arguments will list all
of the network interfaces.
While most hosts have only one real network interface, some
hosts and all gateways have multiple interfaces. Sometimes all
interfaces are the same type; e.g., a gateway between two Ethernets
may have two Ethernet interfaces. netstat on a gateway like this might display
lo0, eth0, and eth1. Deciphering a netstat display with multiple interfaces of
the same type is still very simple. But deciphering a system with many
different types of network interfaces is more difficult. You must rely
on documentation that comes with optional software to choose the
correct interface. When installing new network software, always read
documentation carefully.
This long discussion about determining the network interface is
not meant to overshadow the important ifconfig functions of assigning the IP
address, subnet mask, and broadcast address. So let’s return to these
important
topics.
As noted previously, the Unix installation script configures the network
interface. However, this configuration may not be exactly what you
want. Check the configuration of an interface with ifconfig. To display the current values
assigned to the interface, enter ifconfig with an interface name and no other
arguments. For example, to check interface dnet0:
% ifconfig dnet0
dnet0: flags=1000843<UP,BROADCAST,NOTRAILERS,RUNNING,MULTICAST,IPv4> mtu 1500 index 2
inet 172.16.12.2 netmask ffff0000 broadcast 172.16.255.255When used to check the status of an interface on a Solaris system, the ifconfig command displays two lines of
output. The first line shows the interface name, the flags that define
the interface’s characteristics, and the Maximum Transmission Unit
(MTU) of this interface.[52] In our example the interface name is dnet0, and the MTU
is 1500 bytes. The flags are displayed as both a numeric value and a
set of keywords.
The interface’s flags have the numeric value 1000843, which corresponds to:
The interface is enabled for use.
The interface supports broadcasts, which means it is connected to a network that supports broadcasts, such as an Ethernet.
This interface does not support trailer encapsulation.
This interface is operational.
This interface supports multicasting.
This interface supports TCP/IP version 4, which is the standard version of TCP/IP used on the Internet and described in this book.
The second line of ifconfig
output displays information that directly relates to TCP/IP. The
keyword inet is followed by the
Internet address assigned to this interface. Next comes the keyword
netmask, followed by the address
mask written in hexadecimal. Finally, the keyword broadcast and the broadcast address are
displayed.
On a Linux system the ifconfig command displays up to seven lines
of information for each interface instead of the two lines displayed
by the Solaris system. The additional information includes the
Ethernet address, the PC IRQ, I/O Base Address and memory address, and
packet statistics. The basic TCP/IP configuration information is the
same on both systems.
> ifconfig eth0
eth0 Link encap:Ethernet HWaddr 00:00:C0:9A:D0:DB
inet addr:172.16.55.106 Bcast:172.16.55.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:844886 errors:0 dropped:0 overruns:0 frame:0
TX packets:7668 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:100
Interrupt:11 Base address:0x7c80 Memory:c0000-c2000Refer to the Solaris ifconfig
dnet0 example at the beginning of
this section, and check the information displayed in that example
against the subnet configuration planned for our imaginary network.
You’ll see that the interface needs to be reconfigured. The
configuration done by the user during the Unix installation did not
provide all of the values we planned. The address (172.16.12.2) is
correct, but the address mask (ffff0000 or 255.255.0.0) and the
broadcast address (172.16.0.0) are incorrect. Let’s look at the
various ways values are assigned, and how to correct them.
The IP address can be assigned directly on the ifconfig command line or indirectly from a
file. The ifconfig examples seen
earlier in this chapter had an IP address written in standard dotted
decimal notation directly on the command line. An alternative is to
use a hostname from the /etc/hosts file on the
ifconfig command line to provide
the address. For example:
# ifconfig dnet0 crab netmask 255.255.255.0Most administrators are very comfortable with using hostnames in
place of addresses. Vendor configurations, however, tend to take
address assignment to another level of indirection. The ifconfig command in the startup script
references a file. The file contains a hostname and the hostname maps
to an address. Solaris systems place the hostname in a file named
/etc/hostname. interface, where
interface is the name of the interface
being configured. On our sample system the file is called
/etc/hostname.dnet0. The
hostname.dnet0 file created by a standard Solaris
installation contains only a simple hostname:
$ cat /etc/hostname.dnet0 crab $ grep crab /etc/hosts 172.16.12.1 crab crab.wrotethebook.com loghost
The example shows that the Solaris configuration created the hostname.dnet0 file and the necessary entry in the /etc/hosts file to map the name from hostname.dnet0 to an IP address. The Solaris boot first gets the hostname from a file and then gets the address associated with that hostname from a second file. Both of these entries are required for the configuration.
Linux also uses indirection for the ifconfig
configuration. Several Linux systems, including Red Hat, Mandrake, and
Caldera, place the values used to configure the network interface in a
file named ifcfg. interface, where
interface is the name of the
interface.[53]
For example, ifcfg.eth0 contains the configuration values for the Ethernet interface eth0.
$ cat /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
ONBOOT=yes
BOOTPROTO=none
BROADCAST=172.16.12.255
NETWORK=172.16.12.0
NETMASK=255.255.255.0
IPADDR=172.16.12.2
USERCTL=noThis file makes the configuration very easy to see.
ONBOOT specifies whether the interface is initialized when the system boots. Normally an Ethernet interface is brought up and running every time the system boots.
BOOTPROTO identifies the configuration service used
to configure the interface. In this case it is none, meaning that the interface is
configured locally. Alternates are bootp if an old-fashioned BootP server
is used, or dhcp if a DHCP
server is used. If either DHCP or BootP is used, the specific
configuration values listed below are not found in this
file.
USERCTL specifies whether users can run usernetctl to bring the interface up or
down. The usernetctl command is
found on only a few versions of Linux. In this case, the value
no prevents the user from
downing the interface.
Most systems take advantage of the fact that the IP address, subnet mask, and broadcast
address can be set indirectly to reduce the extent that startup files
need to be customized. Reducing customization lessens the chance that
a system might hang while booting because a startup file was
improperly edited, and it makes it possible to preconfigure these
files for all of the systems on the network. Solaris systems have the
added advantage that the hosts,
networks, and netmasks
files, which provide input to the ifconfig command, all produce NIS maps that
can be centrally managed at sites using NIS.
A disadvantage of setting the ifconfig values indirectly is that it can make troubleshooting
more cumbersome. If all values are set in the boot file, you only need
to check the values there. When network configuration information is
supplied indirectly, you may need to check several files to find the
problem. An error in any of these files could cause an incorrect
configuration. To make debugging easier, a few operating systems set
the configuration values directly on the ifconfig command line in the boot
file.
My advice is that you follow the standard model used on your system. If you use a Solaris system, set the address in /etc/hostname.dnet0 and /etc/hosts. If you use a Red Hat system, set the address in the /etc/sysconfig/network-scripts/ifcfg.eth0 file. If you use a Slackware system, set the address directly in the rc.inet boot file. Following the standard procedure for your system makes it easier for others to troubleshoot your computer. We’ll see more of these alternatives as we assign the remaining interface configuration values.
In order to function properly, every interface on a specific physical network segment must have the same address mask. For crab and rodent, the netmask value is 255.255.255.0 because both systems are attached to the same subnet. However, although crab’s local network interface and its external network interface are parts of the same computer, they use different netmasks because they are on different networks.
To assign an address mask, write the mask value after the
keyword netmask on
the ifconfig command line or as a
prefix attached to the address. When written as a prefix, the address
mask is a decimal number that defines the number of bits in the
address mask. For example, 172.16.12.2/24 defines a 24-bit address
mask. When the subnet mask follows the keyword netmask, it is usually written in the dotted
decimal form used for IP addresses.[54]
For example, the following command assigns the correct subnet mask to the dnet0 interface on rodent:
# ifconfig le0 172.16.12.2 netmask 255.255.255.0Putting the netmask value directly on the ifconfig command line is the most common,
the simplest, and the best way to assign the mask to an interface
manually. But it is rare for the mask to be assigned manually. Like
addresses, address masks are made part of the configuration during the
initial installation. To simplify configuration, ifconfig is able to take the netmask value
from a file instead of from the command line. Conceptually, this is
similar to using a hostname in place of an IP address. The
administrator can place the mask value in either the
hosts file or the networks
file and then reference it by name. For example, the
books-net administrator might add the following
entry to /etc/networks:
books-mask 255.255.255.0
Once this entry has been added, you can use the name
books-mask on the ifconfig command line instead of the actual
mask. For example:
# ifconfig dnet0 172.16.5.2 netmask books-maskThe name books-mask resolves to 255.255.255.0, which is the correct netmask value for our sample systems.
Personally, I avoid setting the address mask value indirectly from a file that is not primarily intended for this use. The hosts file is a particularly bad choice for storing mask values. The hosts file is heavily used by other programs, and placing a mask value in this file might confuse one of these programs. Setting the address mask directly on the command line or from a file that is dedicated to this purpose is probably the best approach.
On Solaris systems, the /etc/inet/netmasks file is specifically designed to set the subnet mask.[55] The /etc/inet/netmasks file is a table of one-line entries, each containing a network address separated from a mask by whitespace.[56]
If a Solaris system on books-net (172.16.0.0) has an /etc/inet/netmasks file that contains the entry:
172.16.0.0 255.255.255.0
then the following ifconfig
command can be used to set the address mask:
# ifconfig dnet0 172.16.5.1 netmask +The plus sign after the keyword netmask causes ifconfig to take the mask value from
/etc/inet/netmasks. ifconfig searches the file for a network
address that matches the network address of the interface being
configured. It then extracts the mask associated with that address and
applies it to the interface.
Most Linux systems also set the address mask indirectly from a file. The ifcfg-eth0 file shown in the previous section contains the following line:
NETMASK=255.255.255.0
This line clearly defines the netmask value that is used by the
ifconfig command. To modify the
address mask on this Red Hat system, edit this line in the
ifcfg-eth0 file.
RFC 919, Broadcasting Internet Datagrams, clearly defines the format of a broadcast address as an address
with all host bits set to 1. Since the broadcast address is so
precisely defined, ifconfig is able
to compute it automatically, and you should always be able to use the
default. Unfortunately, the user in the example under Section 6.1.2
" used a broadcast address with all host bits set
to 0 and didn’t allow the broadcast address to be set by
default.
Correct this mistake by defining a broadcast address for the
network device with the ifconfig
command. Set the broadcast address in the ifconfig command using the keyword broadcast followed by the correct broadcast
address. For example, the ifconfig
command to set the broadcast address for crab’s
dnet0 interface is:
# ifconfig dnet0 172.16.12.1 netmask 255.255.255.0 broadcast 172.16.12.255
Note that the broadcast address is relative to the local subnet. crab views this interface as connected to network 172.16.12.0; therefore, its broadcast address is 172.16.12.255. Depending on the implementation, a Unix system could interpret the address 172.16.255.255 as host address 255 on subnet 255 of network 172.16.0.0, or as the broadcast address for books-net as a whole. In neither case would it consider 172.16.255.255 the broadcast address for subnet 172.16.12.0.
Solaris systems can indirectly set the broadcast address from
the netmask value defined in /etc/inet/netmasks,
if that file is used. The previous section showed that netmask +
takes the netmask value from a file. Likewise, the broadcast + syntax calculates the correct
broadcast value using the netmask value from the
netmasks file:
# ifconfig dnet0 172.16.12.1 netmask + broadcast +Assume that the netmask defined in netmasks is 255.255.255.0. This tells the Solaris system that the first three bytes are network bytes and that the fourth byte contains the host portion of the address. Since the standard broadcast address consists of the network bits plus host bits of all 1s, Solaris can easily calculate that the broadcast address in this case is 172.16.12.255.
Linux makes it even easier. The ifcfg-eth0 file on our sample Red Hat system clearly defines the broadcast address with the line:
BROADCAST=172.16.12.255
Modify the broadcast address by modifying this line in the ifcfg-eth0 file.
We’ve used ifconfig to set
the interface address, the subnet mask, and the broadcast address.
These are certainly the most important functions of ifconfig, but it has other functions as
well. It can enable or disable the address resolution protocol and the
interface itself. ifconfig can set
the routing metric used by the Routing Information Protocol (RIP) and
the maximum transmission unit (MTU) used by the interface. We’ll look
at examples of each of these functions.
The ifconfig command has two arguments, up and down, for enabling and disabling the
network interface. The up
argument enables the network interface and marks it ready for use.
The down argument disables the
interface so that it cannot be used for network traffic.
Use the down argument when
interactively reconfiguring an interface. Some configuration
parameters—for example, the IP address—cannot be changed unless the
interface is down. First, the interface is brought down. Then, the
reconfiguration is done, and the interface is brought back up. For
example, the following steps change the address for an
interface:
# ifconfig eth0 down # ifconfig eth0 172.16.1.2 up
After these commands execute, the interface operates with the
new configuration values. The up
argument in the second ifconfig
command is not always required because it is the default on some
systems. However, an explicit up
is commonly used after the interface has been disabled, or when an
ifconfig command is used in a
script file to avoid problems because up is not the default on all
systems.
Chapter 2 discusses the
Address Resolution Protocol (ARP), an important
protocol that maps IP addresses to physical Ethernet addresses.
Enable ARP with the ifconfig
keyword arp and disable it with
the keyword -arp. It is possible
(though very unlikely) that a host attached to your network cannot
handle ARP. This would only happen on a network using specialized
equipment or developmental hardware. In these very rare
circumstances, it may be necessary to disable ARP in order to
interoperate with the nonstandard systems. By default, ifconfig enables ARP. Leave ARP enabled on
all your systems.
In Chapter 13, promiscuous mode is used to examine the packets traveling on a local Ethernet. By default, an Ethernet interface passes only frames that are addressed to the local host up to the higher layer protocols. Promiscuous mode passes all frames up without regard to the address in those frames.
On a Linux system, promiscuous mode is enabled using the
promisc option of the ifconfig command. For example:
$ ifconfig eth0 promiscPromiscuous mode is disabled by using -promisc.[57] By default promiscuous mode is disabled. When it is
enabled, the local system is forced to process many packets that are
normally discarded by the Ethernet interface hardware. Promiscuous
mode is enabled only for certain troubleshooting
applications.
On some systems, the ifconfig command creates an entry in the
routing table for every interface that is assigned an IP address.
Each interface is the route to a network. Even if a host isn’t a
gateway, its interface is still its “route” to the local network.
ifconfig determines the route’s
destination network by applying the interface’s address mask to the
interface’s IP address. For example, the dnet0 interface on
crab has an address of 172.16.12.1 and a mask
of 255.255.255.0. Applying this mask to the address provides the
destination network, which is 172.16.12.0. The netstat -in display shows the destination
address:
% netstat -in
Name Mtu Net/Dest Address Ipkts Ierrs Opkts Oerrs Collis Queue
le0 1500 172.16.12.0 172.16.12.1 1125826 16 569786 0 8914 0
lo0 1536 127.0.0.0 127.0.0.1 94280 0 94280 0 0 0The Routing Information Protocol (RIP) is a routing protocol sometimes used by Unix. RIP does
two things: it distributes routing information to other hosts, and
it uses incoming routing information to build routing tables
dynamically. The routes created by ifconfig are one source of the routing
information distributed by RIP, and the ifconfig metric argument can be used to
control how RIP uses this routing information.
RIP makes routing decisions based on the cost of a route. The
route’s cost is determined by a routing metric associated with
the route. A routing metric is just a number. The lower the number,
the lower the cost of the route; the higher the number, the higher
the cost. When building a routing table, RIP favors low-cost routes
over high-cost routes. Directly connected networks are given a very
low cost. Therefore, the default metric is for a route through an
interface to a directly attached network. However, you can use the
metric argument to supply a
different routing metric for an interface.
To increase the cost of an interface to 3, so that RIP prefers
routes with values of 0, 1, or 2, use metric 3 on the ifconfig command line:
# ifconfig std0 10.104.0.19 metric 3Use the metric option only if there is another route to the same destination and you want to use it as the primary route. We did not use this command on crab because it has only one interface connected to the outside world. If it had a second connection, say, through a higher-speed link, then the command shown above could be used to direct traffic through the higher-performance interface.
A related ifconfig
parameter is available on Solaris systems. RIP builds the routing table by
choosing the most economical routes, and it distributes the routing
table information to other hosts. The metric parameter controls which routes RIP
selects as the lowest cost. The private argument, available on Solaris
systems, controls the routes that RIP distributes. If private is specified on the ifconfig command line, the route created
by that ifconfig command is not
distributed by RIP. The default value is -private, which permits the route to be
distributed. The private
parameter is not universally supported.
Additionally, not all systems make use of the metric argument. A Linux system doesn’t create a routing table entry when
it processes the ifconfig
command. When configuring a Linux system, you add an explicit
route command for each interface.
(The route command is covered in
the next chapter.) Linux systems reject the metric argument, as this example
shows:
# ifconfig eth0 192.168.0.4 metric 3
SIOCSIFMETRIC: Operation not supportedSet the routing metric in a routing configuration file instead
of on the ifconfig command line.
This is the preferred method of providing routing information for
newer routing software. We discuss the format of routing
configuration files in the next chapter.
A network has a maximum transmission unit (MTU), which is the largest packet that can be
transported over that physical network. On Ethernet, the maximum size is 1500 bytes, which is
defined as part of the Ethernet standard. There is rarely any need
to change the MTU on the ifconfig
command line. By default, ifconfig chooses the optimum MTU, which is
usually the largest legal MTU for a given type of network hardware.
A large MTU is the default because it normally provides the best
performance. However, a smaller MTU is helpful to achieve the
following goals:
To avoid fragmentation. If the traffic travels from a network with a large MTU (such as an FDDI network with an MTU of 4500 bytes) through a network with a smaller MTU (like an Ethernet), the smaller MTU size may be best in order to avoid packet fragmentation. It is possible that specifying an MTU of 1500 on the interface connected to the FDDI may actually improve performance by avoiding fragmentation in the routers. This would be done only if fragmentation actually appeared to be the cause of a performance problem.
To reduce buffer overruns or similar problems. On serial line connections, it is possible to have equipment of such low performance that it cannot keep up with standard 1006-byte packets. In this case, it is possible to avoid buffer overruns or SILO overflows by using a smaller MTU. However, such solutions are temporary fixes. The real fix is to purchase the correct hardware for the application.
To change the MTU, use the mtu command-line argument:
# ifconfig fddi0 172.16.16.1 netmask 255.255.255.0 mtu 1500This forces the FDDI interface on 172.16.16.1 to use an MTU of 1500 bytes.
There are probably several more ifconfig command-line arguments available
on your system. Linux has parameters to define the PC interrupt of
the Ethernet hardware (irq) and
the Ethernet hardware address (hw), and to enable multicasting (multicast) and promiscuous mode (promisc). Solaris has arguments to set up
or tear down the streams for an interface (plumb/unplumb) and to use Reverse ARP (RARP) to
obtain the IP address for an interface (auto-revarp). But most of these parameters
are not standardized between versions of Unix.
One last feature that is available on most versions of Unix is the ability to define
point-to-point connections with the ifconfig command. Point-to-point
connections are network links that directly connect only two
computers. Of course the computers at either end of the link could
be gateways to the world, but only two computers are directly
connected to the link. Examples of a point-to-point connection are
two computers linked together by a leased telephone line, or two
computers in an office linked together by a null modem cable.
To define a point-to-point link on a Solaris system:
# ifconfig zs0 172.16.62.1 172.16.62.2This ifconfig command has
two addresses immediately following the interface name. The first is
the address of the local host. The second address, called the
destination address, is the address of the remote host at the other
end of the point-to-point link. The second address shows up as the
Net/Dest value in a netstat
-ni display.
On a Linux system, this same configuration looks slightly different:
$ ifconfig sl0 172.16.62.1 point-to-point 172.16.62.2The syntax is different but the effect is the same. This enables the interface to run in point-to-point mode and identifies the hosts at both ends of the link.
Does this set up the Point-to-Point Protocol (PPP) used for
TCP/IP serial line communication? No, it does not. These ifconfig parameters sometimes confuse
people about how to set up PPP. There is much more to configuring
PPP, which we cover later in this chapter.
Before moving on to PPP, you should note that the
configuration entered on an ifconfig command line will not survive a
system boot. For a permanent configuration, put
ifconfig in a startup
file.
The ifconfig command
is normally executed at boot time by a startup file.
The two basic Unix startup models, the BSD model and the System V
model, were explained in Chapter
5. On BSD Unix systems, the ifconfig commands are usually located in
/etc/rc.boot or
/etc/rc.local.
To override a BSD system’s default configuration, place a full
ifconfig command in the
rc.local script. rc.local executes at the
end of the startup process. Any interface configuration values set
in this file override the earlier interface configuration. For
example, the following line placed in that file configures eth0
without regard to any earlier configuration:
ifconfig eth0 172.16.12.1 broadcast 172.16.12.255 netmask 255.255.255.0
The BSD startup model is used on BSD systems and SunOS
systems. Linux and Solaris systems use the System V startup model.
However, Red Hat Linux systems have an rc.local
script in the /etc/rc.d directory. On a Red Hat
system, place the custom ifconfig
command in the rc.local file to override the
default configuration.
Solaris does not have an rc.local script or a central directory of scripts for all runlevels. If you want to use an rc.local script on a Solaris system, you need to create your own and add it to the runlevel 3 directory. You need to name it properly to ensure it executes at the end of the Solaris startup process. For example, the file /etc/rc3.d/S99local would execute at the end of the standard Solaris runlevel 3 startup. Commands placed in this file would override the previous configuration.
If possible, however, configure the network with the standard tools and procedures provided with your system. Directly modifying startup scripts or adding nonstandard scripts can lead to lots of confusion for the people who help you maintain your systems.
TCP/IP runs over a wide variety of physical media. The media can be
Ethernet cables, as in your local Ethernet, or telephone circuits, as in
a wide area network. In the first half of this chapter, we used ifconfig to configure a local Ethernet
interface. In this section, we use other commands to configure a network
interface to use a telephone circuit.
Almost all data communication takes place via serial interfaces. A serial interface is just an interface that sends the data as a series of bits over a single wire, as opposed to a parallel interface that sends the data bits in parallel over several wires simultaneously. This description of a serial interface would fit almost any communications interface (including Ethernet itself), but the term is usually applied to an interface that connects to a telephone circuit via a modem or similar device. Likewise, a telephone circuit is often called a serial line.
In the TCP/IP world, serial lines are used to create wide area networks (WANs). Unfortunately, TCP/IP has not always had a standard physical layer protocol for serial lines. Because of the lack of a standard, network designers were forced to use a single brand of routers within their WANs to ensure successful physical layer communication. The growth of TCP/IP WANs led to a strong interest in standardizing serial line communications to provide vendor independence.
Other forces that increased interest in serial line communications were the advent of small, affordable systems that run TCP/IP, and the advent of high-speed, dial-up modems that provide “reasonable” TCP/IP performance. When the ARPAnet was formed, computers were very expensive and dial-up modems were very slow. At that time, if you could afford a computer, you could afford a leased telephone line. In recent years, however, it has become possible to own a Unix system at home. In this new environment, there is a strong demand for services that allow TCP/IP access over dial-up modems. Currently, approximately 7% of home users have a high-speed Digital Subscriber Line (DSL) connection or a cable modem. Most DSL and cable modems connect to the host via Ethernet, meaning that no special host configuration is required to use those services. But most home users still use dial-up serial lines. Dial-up serial lines require special protocols and special configurations.
These two forces—the need for standardized wide area communications and the need for dial-up TCP/IP access—led to the creation of two serial line protocols: Serial Line IP (SLIP) and Point-to-Point Protocol (PPP).[58]
Serial Line IP was created first. It is a minimal protocol that allows isolated hosts to link via TCP/IP over the telephone network. The SLIP protocol defines a simple mechanism for framing datagrams for transmission across serial lines. SLIP sends the datagram across the serial line as a series of bytes, and it uses special characters to mark when a series of bytes should be grouped together as a datagram. SLIP defines two special characters for this purpose:
The SLIP END character, a single byte with the decimal value 192, is the character that marks the end of a datagram. When the receiving SLIP encounters the END character, it knows that it has a complete datagram that can be sent up to IP.
The SLIP ESC character, a single byte with the decimal value of 219, is used to “escape” the SLIP control characters. If the sending SLIP encounters a byte value equivalent to either a SLIP END character or a SLIP ESC character in the datagram it is sending, it converts that character to a sequence of two characters. The two-character sequences are ESC 220 for the END character, and ESC 221 for the ESC character itself.[59] When the receiving SLIP encounters these two-byte sequences, it converts them back to single-byte values. This procedure prevents the receiving SLIP from incorrectly interpreting a data byte as the end of the datagram.
SLIP is described in RFC 1055, A Nonstandard for Transmission of IP Datagrams Over Serial Lines: SLIP. As the name of the RFC makes clear, SLIP is not an Internet standard. The RFC does not propose a standard; it documents an existing protocol. The RFC identifies the deficiencies in SLIP, which fall into two categories:
The SLIP protocol does not define any link control information that could be used to dynamically control the characteristics of a connection. Therefore, SLIP systems must assume certain link characteristics. Because of this limitation, SLIP can be used only when both hosts know each other’s addresses, and only when IP datagrams are being transmitted.
SLIP does not compensate for noisy, low-speed telephone lines. The protocol does not provide error correction or data compression.
To address SLIP’s weaknesses, Point-to-Point Protocol (PPP) was developed as an Internet standard. There are several RFCs that document Point-to-Point Protocol.[60] Two key documents are RFC 1661, The Point-to-Point Protocol (PPP), and RFC 1172, The Point-to-Point Protocol (PPP) Initial Configuration Options.
PPP addresses the weaknesses of SLIP with a three-layered protocol:
The Data Link Layer Protocol used by PPP is a slightly modified version of High-level Data Link Control (HDLC). PPP modifies HDLC by adding a Protocol field that allows PPP to pass traffic for multiple Network Layer protocols. HDLC is an international standard protocol for reliably sending data over synchronous, serial communications lines. PPP also uses a proposed international standard for transmitting HDLC over asynchronous lines, so PPP can guarantee reliable delivery over any type of serial line.
The Link Control Protocol (LCP) provides control information for the serial link. It is used to establish the connection, negotiate configuration parameters, check link quality, and close the connection. LCP was developed specifically for PPP.
The Network Control protocols are individual protocols that provide configuration and control information for the Network Layer protocols. Remember, PPP is designed to pass data for a wide variety of network protocols. NCP allows PPP to be customized to do just that. Each network protocol (DECNET, IP, OSI, etc.) has its own Network Control protocol. The Network Control protocol defined in RFCs 1661 and 1332 is the Internet Control Protocol (IPCP), which supports Internet Protocol.
Point-to-Point Protocol is the best TCP/IP serial protocol. PPP is preferred because it is an Internet standard, which ensures interoperability between systems from a wide variety of vendors. It has more features than SLIP and is more robust. These benefits make PPP the best choice as an open protocol for connecting routers over serial lines and for connecting remote computers via dial-up lines.
Some Linux systems include both SLIP and PPP. However, on most Unix systems, such as Solaris, PPP is included and SLIP is not. This is fine, as you should avoid using SLIP and use PPP instead.
The procedures for installing and configuring PPP vary from
implementation to implementation.[61] In this section, we use the PPP daemon implementation
(pppd) included with Linux and the
supporting configuration commands that come with it. PPP is an Internet
standard, and most Unix systems include support for it in the kernel as
part of the standard operating system installation. Usually this does
not require any action on your part. Refer to Chapter 5 for examples of how PPP is
configured in the Linux kernel. The Linux system installs the PPP
physical and data link layer software (the HDLC protocol) in the
kernel.
Installing PPP in the kernel is only the beginning. In this
section, we look at how pppd is used
to provide PPP services on a Linux system.
Point-to-Point Protocol is implemented on the Linux system in the PPP daemon
(pppd), which was derived from a
freeware PPP implementation for BSD systems. pppd can be configured to run in all modes:
as a client, as a server, over dial-up connections, and over dedicated
connections. (Clients and servers are familiar concepts from Chapter 3.) A dedicated connection is a direct cable connection or a
leased line, neither of which requires a telephone to establish the
connection. A dial-up connection is a modem link established by
dialing a telephone number.
Configuring pppd for a
dedicated line is the simplest configuration. A dial-up script is not
needed for a leased line or direct connection. There is no point in
dynamically assigning addresses because a dedicated line always
connects the same two systems. Authentication is of limited use because the dedicated line physically runs between
two points. There is no way for an intruder to access the link, short
of “breaking and entering” or a wiretap. A single pppd command placed in a startup file
configures a dedicated PPP link for our Linux system:
pppd /dev/cua3 56000 crtscts defaultroute
The /dev/cua3 argument selects the device to which PPP is attached.
It is, of course, the same port to which the dedicated line is
attached. Next, the line speed is specified in bits per second
(56000). The remainder of the command line is a series of keyword
options. The crtscts option turns on hardware flow control. The final
option, defaultroute , creates a default route using the remote server as the
default gateway.[62]
PPP exchanges IP addresses during the initial link connection process. If no
address is specified on the pppd
command line, the daemon sends the address of the local host, which it
learns from DNS or the host table, to the remote host. Likewise, the
remote system sends its address to the local host. The addresses are
then used as the source and destination addresses of the link. You can
override this by specifying the addresses on the command line in the
form local-address : remote-address.
For example:
pppd /dev/cua3 56000 crtscts defaultroute 172.16.24.1:
Here we define the local address as 172.16.24.1 and leave the
remote address blank. In this case pppd sends the address from the command line
and waits for the remote server to send its address. The local address
is specified on the command line when it is different from the address
associated with the local hostname in the host table or the DNS
server. For example, the system might have an Ethernet interface that
already has an address assigned. If we want to use a different address
for the PPP connection, we must specify it on the pppd command line; otherwise, the PPP link
will be assigned the same address as the Ethernet interface.
The pppd command has many more options than those used in these
examples (see Appendix A for a full
list of options). In fact, there are so many pppd command-line options that it is
sometimes easier to put them in a file than to enter them all on the
command line. pppd reads its
options from the /etc/ppp/options
file, then the ~/.ppprc file, then the /etc/ppp/options.device file (where device
is a device name like cua3), and finally from the command line. The
order in which they are processed creates a hierarchy such that
options on the command line can override those in the ~/.ppprc file, which can in turn override those in the /etc/ppp/options file. This permits the
system administrator to establish certain systemwide defaults in the
/etc/ppp/options file while still
permitting the end user to customize the PPP configuration. The
/etc/ppp/options file is a
convenient and flexible way to pass parameters to pppd.
A single pppd command is all
that is needed to set up and configure the software for a dedicated
PPP link. Dial-up connections are more challenging.
A direct-connect cable can connect just two systems. When a third system is purchased, it cannot be added to the network. For that reason, most people use expandable network technologies, such as Ethernet, for connecting systems in a local area. Additionally, leased lines are expensive. They are primarily used by large organizations to connect networks of systems. For these reasons, using PPP for dedicated network connections is less common than using it for dial-up connections.
Several different utilities provide dial-up support for PPP.
Dial-up IP (dip
) is a popular package for simplifying the process of
dialing the remote server, performing the login, and attaching PPP to
the resulting connection. We discuss dip in this section because it is popular
and freely available for a wide variety of Unix systems, and because
it comes with Red Hat Linux, which is the system we have been using
for our PPP examples.
One of the most important features of dip is a scripting language that lets you
automate all the steps necessary to set up an operational PPP link.
Appendix A covers all the scripting
commands supported by the 3.3.7o-uri version of dip, which is the version included with Red
Hat. You can list the commands supported by your system by running
dip in test mode (-t) and
then entering the help command:
> dip -t DIP: Dialup IP Protocol Driver version 3.3.7o-uri (8 Feb 96) Written by Fred N. van Kempen, MicroWalt Corporation. DIP> help DIP knows about the following commands: beep bootp break chatkey config databits dec default dial echo flush get goto help if inc init mode modem netmask onexit parity password proxyarp print psend port quit reset send shell sleep speed stopbits term timeout wait DIP> quit
These commands can configure the interface, control the execution of the script, and process errors. Only a subset of the commands is required for a minimal script:
# Ask PPP to provide the local IP address get $local 0.0.0.0 # Select the port and set the line speed port cua1 speed 38400 # Reset the modem and flush the terminal reset flush # Dial the PPP server and wait for the CONNECT response dial *70,301-555-1234 wait CONNECT # Give the server 2 seconds to get ready sleep 2 # Send a carriage-return to wake up the server send \r # Wait for the Login> prompt and send the username wait ogin> send kristin\r # Wait for the Password> prompt and send the password wait word> password # Wait for the PPP server's command-line prompt wait > # Send the command required by the PPP server send ppp enabled\r # Set the interface to PPP mode mode PPP # Exit the script exit
The get command at the beginning of the script allows PPP to
provide the local and remote addresses. $local is a script variable. There are
several available script variables, all of which are covered in Appendix A. $local normally stores the local address,
which can be set statically in the script. A PPP server, however, is
capable of assigning an address to the local system dynamically. We
take advantage of this capability by giving a local address of all 0s.
This peculiar syntax tells dip to
let pppd handle the address
assignments. A pppd client can get
addresses in three ways:
The PPP systems can exchange their local addresses as determined from DNS. This was discussed previously for the dedicated line configuration.
The addresses can be specified on the pppd command line, also discussed
previously.
The client can allow the server to assign both addresses. This feature is most commonly used on dial-up lines. It is very popular with servers that must handle a large number of short-lived connections. A dial-up Internet Service Provider (ISP) is a good example.
The next two lines select the physical device to which the modem
is connected, and set the speed at which the device operates. The
port command assumes the path /dev, so
the full device path is not used. On most PC Unix systems, the value
provided to the port command is
cua0, cua1, cua2, or cua3. These values correspond to MS-DOS ports
COM1 to COM4. The speed command sets the maximum speed used to send data to the
modem on this port. The default speed is 38400. Change it if your
modem accepts data at a different speed.
The reset command resets the modem by sending it the Hayes modem
interrupt (+++) followed by the Hayes modem reset command (ATZ). This
version of dip uses the Hayes modem
AT command set and works only with Hayes-compatible modems.[63] Fortunately, that includes most brands of modems. After
being reset, the modem responds with a message indicating that the
modem is ready to accept input. The flush command removes this message, and any others that might
have been displayed by the modem, from the input queue. Use flush to avoid the problems that can be
caused by unexpected data in the queue.
The next command dials the remote server. The dial command sends a standard Hayes ATD dial command to the modem. It passes the
entire string provided on the command line to the modem as part of the
ATD command. The sample dial
command generates ATD*70,301-555-1234. This causes the modem to dial
*70 (which turns off call waiting[64]), and then area code 301, exchange 555, and number
1234.When this modem successfully connects to the remote modem, it
displays the message CONNECT. The wait command waits for that message from the modem.
The sleep 2 command inserts a two-second delay into the script. It
is often useful to delay at the beginning of the connection to allow
the remote server to initialize. Remember that the CONNECT message is
displayed by the modem, not by the remote server. The remote server
may have several steps to execute before it is ready to accept input.
A small delay can sometimes avoid unexplained intermittent
problems.
The send command sends a carriage return (\r) to the remote
system. Once the modems are connected, anything sent from the local
system goes all the way to the remote system. The send command can send any string. In the
sample script, the remote server requires a carriage return before it
issues its first prompt. The carriage return is entered as \r and the
newline is entered as \n.
The remote server then prompts for the username with Login>. The wait ogin> command detects this prompt, and the send kristin command sends the username kristin as a response. The server then
prompts for the password with Password>. The password command causes the script to prompt the local user to
manually enter the password. It is possible to store the password in a
send command inside the script.
However, this is a potential security problem if an unauthorized
person gains access to the script and reads the password. The password command improves security.
If the password is accepted, our remote server prompts for input
with the greater-than symbol (>). Many servers require a command to
set the correct protocol mode. The server in our example supports
several different protocols. We must tell it to use PPP by using
send to pass it the correct
command.
The script finishes with a few commands that set the correct
environment on the local host. The mode command tells the local host to use the PPP protocol on
this link. The protocol selected must match the protocol running on
the remote server. Protocol values that are valid for the dip mode
command are SLIP, CSLIP, PPP, and TERM. SLIP and CSLIP are variations
of the SLIP protocol, which was discussed earlier. TERM is terminal
emulation mode. PPP is the Point-to-Point Protocol. Finally, the
exit command ends the script, while dip keeps running in the background
servicing the link.
This simple script does work and it should give you a good idea
of the wait/send structure of a dip
script. However, your scripts will probably be more complicated. The
sample script is not robust because it does not do any error checking.
If an expected response does not materialize, the sample script hangs.
To address this problem, use a timeout on each wait command. For example, the wait OK 10 command tells the system to wait
10 seconds for the OK response. When the OK response is detected, the
$errlvl script variable is set to
zero and the script falls through to the next command. If the OK
response is not returned before the 10-second timer expires, $errlvl is set to a nonzero value and the
script continues on to the next command. The $errlvl variable is combined with the
if and goto commands to provide error handling in
dip scripts. Refer to Appendix A for more details.
Once the script is created, it is executed with the dip command. Assume that the sample script shown above was
saved to a file named start-ppp.dip. The
following command executes the script, creating a PPP link between the
local system and the remote server:
> dip start-pppTerminate the PPP connection with the command dip -k. This closes the connection and kills
the background dip process.
pppd options are not
configured in the dip script.
dip creates the PPP connection; it
doesn’t customize pppd. pppd options are stored in the
/etc/ppp/options file.
Assuming the dip script shown
above, we might use the following pppd options:
noipdefault ipcp-accept-local ipcp-accept-remote defaultroute
The noipdefault option tells
the client not to look up the local address. ipcp-accept-local tells the client to obtain
its local address from the remote server. The ipcp-accept-remote option tells the system
to accept the remote address from the remote server. Finally, pppd sets the PPP link as the default route.
This is the same defaultroute
option we saw on the pppd command
line in an earlier example. Any pppd option that can be invoked on the
command line can be put in the /etc/ppp/options
file and thus be invoked when pppd
is started by a dip script.
I use dip on my home computer
to set up my dial-up PPP connection.[65] Personally, I find dip simple and straightforward to use, in
part because I am familiar with the dip scripting language. You may prefer to
use the chat command that comes
with
the pppd software package.
A chat script is a simple expect/send script consisting of the
strings the system expects and the strings it sends in response. The
script is organized as a list of expect/send pairs. chat does not really have a scripting
language, but it does have some special characters that can be used to
create more complex scripts. The chat script to perform the same dial-up and
login functions as the sample dip
script would contain:
'' ATZ OK ATDT*70,301-555-1234 CONNECT \d\d\r ogin> kristin word> Wats?Wat? > 'set port ppp enabled'
Each line in the script begins with an expected string and ends
with the string sent as a response. The modem does not send a string
until it receives a command. The first line in the script says, in
effect, “expect nothing and send the modem a reset command.” The pair
of single quotes ('') at the
beginning of the line tells chat to
expect nothing. The script then waits for the modem’s OK prompt and
dials the remote server. When the modem displays the CONNECT message,
the script delays two seconds (\d\d) and then sends a carriage return
(\r). Each \d special character causes a one-second delay. The \r
special character is the carriage return. chat has many special characters that can be
used in the expect strings and the send strings.[66] Finally, the script ends by sending the username,
password, and remote server configuration command in response to the
server’s prompts.
Create the script with your favorite editor and save it in a
file such as dial-server. Test the script
using chat with the
-V option, which logs the script
execution through stderr:
% chat -V -f dial-serverInvoking the chat script is
not sufficient to configure the PPP line. It must be combined with
pppd to do the whole job. The connect command-line option allows you to start pppd and invoke a dial-up script all in one
command:
# pppd /dev/cua1 56700 connect "chat -V -f dial-server" \ nodetach crtscts modem defaultroute
The chat command following the connect option is used to perform the
dial-up and login. Any package capable of doing the job could be
called here; it doesn’t have to be chat.
The pppd command has some
other options that are used when PPP is run as a dial-up client. The
modem option causes pppd
to monitor the carrier-detect (DCD) indicator of the modem. This
indicator tells pppd when the
connection is made and when the connection is broken. pppd monitors DCD to know when the remote
server hangs up the line. The nodetach option prevents pppd
from detaching from the terminal to run as a background process. This
is necessary only when running chat
with the -V option. When you are
done debugging the chat script, you
can remove the -V option from the
chat subcommand and the nodetach option from the pppd command. An alternative is to use
-v on the chat command. -v does not require pppd to remain attached to a terminal
because it sends the chat logging
information to syslogd instead of
to stderr. We have seen all of the other options on this command line
before.
A major benefit of PPP over SLIP is the enhanced security PPP
provides. Put the following pppd
options in the /etc/ppp/options file to enhance
security:
lock auth usehostname domain wrotethebook.com
The first option, lock, makes pppd use UUCP-style lock files. This
prevents other applications, such as UUCP or a terminal emulator, from
interfering with the PPP connection. The auth option requires the remote system to be authenticated
before the PPP link is established. This option causes the local
system to request authentication data from the remote system. It does
not cause the remote system to request similar data from the local
system. If the remote system administrator wants to authenticate your
system before allowing a connection, she must put the auth keyword in the configuration of her
system. The usehostname option requires that the hostname is used in the
authentication process and prevents the user from setting an arbitrary
name for the local system with the name option. (More on authentication in a
minute.) The final option makes sure that the local hostname is fully
qualified with the specified domain before it is used in any
authentication procedure.
Recall that the ~/.ppprc file and the
pppd command-line options can
override options set in the /etc/ppp/options
file, which could be a security problem. For this reason, several
options, once configured in the /etc/ppp/options
file, cannot be overridden. That includes the options just
listed.
pppd supports two authentication protocols: Challenge Handshake Authentication Protocol (CHAP) and
Password Authentication Protocol (PAP). PAP is a simple
password security system that is vulnerable to all of the attacks of
any reusable password system. CHAP, however, is an advanced
authentication system that does not use reusable passwords and that
repeatedly reauthenticates the remote system.
Two files are used in the authentication process, the
/etc/ppp/chap-secrets file and the /etc/ppp/pap-secrets
file. Given the options file shown above, pppd first attempts to authenticate the
remote system with CHAP. To do this, there must be data in the
chap-secrets file, and the remote system must
respond to the CHAP challenge. If either of these conditions is not
true, pppd attempts to authenticate
the remote system with PAP. If there is no applicable entry in the
pap-secrets file or the remote system does not
respond to the PAP challenge, the PPP connection is not established.
This process allows you to authenticate remote systems with CHAP (the
preferred protocol), if they support it, and to fall back to PAP for
systems that support only PAP. For this to work, however, you must
have the correct entries in both files.
Each entry in the chap-secrets file contains up to four fields:
The name of the computer that must answer the challenge, i.e., the computer that must be authenticated before the connection is made. This is not necessarily a client that is seeking access to a PPP server; although client is the term used in most of the documentation, it is really the respondent—the system that responds to the challenge. Both ends of a PPP link can be forced to undergo authentication. In your chap-secrets file you will probably have two entries for each remote system: one entry to authenticate the remote system, and a corresponding entry to authenticate your system when it is challenged by the remote system.
The name of the system that issues the CHAP challenge, i.e., the computer that requires the authentication before the PPP link is established. This is not necessarily a PPP server. The client system can require the server to authenticate itself. Server is the term used in most documentation, but really this is the authenticator—the system that authenticates the response.
The secret key that is used to encrypt the challenge string before it is sent back to the system that issued the challenge.
An address, written as a hostname or an IP address, that is acceptable for the host named in the first field. If the host listed in the first field attempts to use an address other than the address listed here, the connection is terminated even if the remote host properly encrypts the challenge response. This field is optional.
A sample chap-secrets file for the host ring might contain:
limulus ring Peopledon'tknowyou 172.16.15.3 ring limulus andtrustisajoke. 172.16.15.1
The first entry is used to validate limulus, the remote PPP server. limulus is being authenticated and the system performing the authentication is ring. The secret key is “Peopledon’tknowyou”. The allowable address is 172.16.15.3, which is the address assigned to limulus in the host table. The second entry is used to validate ring when limulus issues the challenge. The secret key is “andtrustisajoke.”. The only address ring is allowed to use is 172.16.15.1. A pair of entries, one for each end of the link, is normal. The chap-secret file usually contains two entries for every PPP link: one for validating the remote system and one for answering the challenge of that remote system.
Use PAP only when you must. If you deal with a system that does not support CHAP, make an entry for that system in the pap-secrets file. The format of pap-secrets entries is the same as those used in the chap-secrets file. A system that does not support CHAP might have the following entry in the pap-secrets file:
24seven ring Wherearethestrong? 24seven.wrotethebook.com ring 24seven Whoarethetrusted? ring.wrotethebook.com
Again we have a pair of entries: one for the remote system and one for our system. We support CHAP but the remote system does not. Thus we must be able to respond using the PAP protocol in case the remote system requests authentication.
PPP authentication improves security in a dial-up environment. It is most important when you run the PPP server into which remote systems dial. In the next section, we look at PPP server configuration.
The PPP server can be started in several different ways. One way
is to use pppd as a login
shell for dial-in PPP users. Replace the login shell entry in the
/etc/passwd file with the path of pppd to start the server. A modified
/etc/passwd entry might contain:
craig:wJxX.iPuPzg:101:100:Craig Hunt:/etc/ppp:/usr/sbin/pppd
The fields are exactly the same as in any
/etc/passwd entry: username, password, uid, gid,
gcos information, home directory, and login shell. For a remote PPP
user, the home directory is /etc/ppp and the
login shell is the full path of the pppd program. The encrypted password must be
set using the passwd program, just
as for any user, and the login process is the same as it is for any
user. When getty detects incoming
traffic on the serial port it invokes login to authenticate the user. login verifies the username and the password
entered by the user and starts the login shell. In this case, the
login shell is actually the PPP daemon.
When the server is started in this manner, server options are
generally placed in the /etc/ppp/.ppprc file.
login validates the user, and
pppd authenticates the client.
Therefore the chap-secrets or
pap-secrets file must be set up to handle the
client system from which this user logs in.
A traditional alternative to using pppd as the login script is to create a real script in which
pppd is only one of the commands.
For example, you might create an
/etc/ppp/ppplogin script such as the
following:
#!/bin/sh mesg -n stty -echo exec /sbin/pppd auth passive crtscts modem
You can see that the script can contain more than just the
pppd command. The mesg -n command makes sure that other users
cannot write to this terminal with talk, write, or similar programs. The stty command turns off character echoing. On
some systems, characters typed at the terminal are echoed from the
remote host instead of being locally echoed by the terminal; this
behavior is called full duplex. We don’t want to
echo anything back on a PPP link, so we turn full duplex off.
Controlling the characteristics of the physical line is the main
reason that pppd is often placed
inside a script file.
The key line in the script is, of course, the line that starts
pppd. We start the daemon with
several options, but one thing that is not included on the command
line is the tty device name. In all of the
previous pppd examples, we provided
a device name. When it is not provided, as is this case, pppd uses the controlling terminal as its
device and doesn’t put itself in background mode. This is just what we
want. We want to use the device that login was servicing when it invoked the
ppplogin script.
The auth command-line option tells pppd to authenticate the remote system,
which of course requires us to place an entry for that system in the
chap-secrets or the
pap-secrets file. The crtscts option turns on hardware flow control, and the modem option tells PPP to monitor the modem’s DCD indicator
so that it can detect when the remote system drops the line. We have
seen all of these options before. The one new option is passive. With passive set, the local system waits until it receives a valid
LCP packet from the remote system, even if the remote system fails to
respond to its first packet. Normally, the local system would drop the
connection if the remote system fails to respond in a timely manner.
This option gives the remote system time to initialize its own PPP
daemon.
A final option for running PPP as a server is to allow the user
to start the server from the shell prompt. To do this, pppd must be installed as setuid root, which
is not the default installation. Once pppd is setuid root, a user with a standard
login account can log in and then issue the following command:
$ pppd proxyarpThis command starts the PPP daemon. Assuming that the auth parameter is set in the
/etc/ppp/options file, pppd authenticates the remote client using
CHAP or PAP. Once the client is authenticated, a proxy ARP entry for
the client is placed in the server’s ARP table so that the client
appears to other systems to be located on the local network.
Of these three approaches, I prefer to create a shell script
that is invoked by login as the
user’s login shell. With this approach, I don’t have to install
pppd setuid root. I don’t have to
place the burden of running pppd on
the user. And I get all the power of the pppd command plus all the power of a shell script.
dip and pppd are available for Linux, BSD, AIX, Ultrix, OSF/1, and
SunOS. If you have a different operating system, you probably won’t
use these packages. Solaris is a good example of a system that uses a
different set of commands to configure PPP.
PPP is implemented under Solaris as the Asynchronous PPP Daemon (aspppd). aspppd is configured by the /etc/asppp.cf
file. The asppp.cf file is divided into two
sections: an ifconfig section and a
path section.
ifconfig ipdptp0 plumb ring limulus up path interface ipdptp0 peer_system_name limulus inactivity_timeout 300
The ifconfig command configures the PPP interface (ipdptp0) as a point-to-point link with a
local address of ring and a destination address
of limulus. The ifconfig command does not have to define the
destination address of the link. However, if you always connect to the
same remote server, it will probably be defined here as the
destination address. We saw all of these options in the discussion of
the ifconfig command earlier in
this chapter.
The more interesting part of this file is the path section, which defines the PPP environment. The
interface statement identifies the
interface used for the connection. It must be one of the PPP
interfaces defined in the ifconfig
section. In the example, only one is defined, so it must be ipdptp0. The peer_system_name statement identifies the
system at the remote end of the connection. This may be the same
address as the destination address from the ifconfig statement, but it doesn’t have to
be. It is possible to have no destination address on the ifconfig command and several path sections if you connect to several
different remote hosts. The hostname on the peer_system_name statement is used in the
dialing process, as described later.
The path section ends with an
inactivity_timeout statement. The command in the sample sets the timeout
to 300 seconds. This points out a nice feature of the Solaris system.
Solaris automatically dials the remote system when it detects data
that needs to be delivered through that system. Further, it
automatically disconnects the PPP link when it is inactive for the
specified time. With this feature you can use a PPP link without
manually initiating the dial program and without tying up phone lines
when the link is not in use.
Like pppd, aspppd does not have a built-in dial
facility. It relies on an external program to do the dialing. In the
case of aspppd, it utilizes the
dial-up facility that comes with UUCP. Here’s how.
First, the serial port, the modem attached to it, and the speed at which they operate are defined in the /etc/uucp/Devices file. For example, here we define an Automatic Call Unit (ACU is another name for a modem) attached to serial port B (cua/b) that operates at any speed defined in the Systems file, and that has the modem characteristics defined by the “hayes” entry in the Dialers file:
ACU cua/b - Any hayes
Next, the modem characteristics, such as its initialization
setting and dial command, are defined in the
/etc/uucp/Dialers file. The initialization and
dial commands are defined as a chat
script using the standard expect/send format and the standard set of
chat special characters. For
example:
hayes =,-, "" \dA\pTE1V1X1Q0S2=255S12=255\r\c OK\r \EATDT\T\r\c CONNECT
The system comes with Devices and
Dialers preconfigured. The preconfigured entries
are probably compatible with the modem on your system. The
/etc/uucp/Systems file may be the only
configuration file that you modify. In the
Systems file, you need to enter the name of the
remote system, select the modem you’ll use, enter the telephone
number, and enter a chat script to
handle the login. For example:
limulus Any ACU 56700 5551234 "" \r ogin> kristin word> Wats?Watt? > set ppp on
In this one line, we identify limulus as
the remote system, declare that we allow connections to and from that
host at any time of the day (Any), select the ACU entry in the
Devices file to specify the port and modem, set
the line speed to 56700, send the dialer the telephone number, and
define the login chat
script.
This is not a book about UUCP, so we won’t go into further
details about these files. I’d suggest looking at the Solaris
AnswerBook and the Solaris TCP/IP Network Administration Guide (where did they come up with such a great name?) for
more information about UUCP and aspppd.
There are several layers of complexity that make PPP connections difficult to debug. To set up PPP, we must set up the serial port, configure the modem, configure PPP, and configure TCP/IP. A mistake in any one of these layers can cause a problem in another layer. All of these layers can obscure the true cause of a problem. The best way to approach troubleshooting on a serial line is by debugging each layer, one layer at a time. It is usually best to troubleshoot each layer before you move on to configure the next layer.
The physical serial ports should be configured by the system during the system boot. Check the /dev directory to make sure they are configured. On a Linux system with four serial ports, the inbound serial ports are /dev/ttyS0 through /dev/ttyS3 and the outbound serial ports are /dev/cua0 through /dev/cua3. There are many more tty and cua device names. However, the other devices are associated with real physical devices only if you have a multi-port serial card installed in your Linux system. Most Unix systems use the names tty and cua, even if those names are just symbolic links to the real devices. Solaris is a good example:
% ls -l /dev/tty? lrwxrwxrwx 1 root root 6 Sep 23 2001 /dev/ttya -> term/a lrwxrwxrwx 1 root root 6 Sep 23 2001 /dev/ttyb -> term/b % ls -l /dev/cua/* lrwxrwxrwx 1 root root 35 Sep 23 2001 /dev/cua/a -> /devices/obio/zs@0,100000:a,cu lrwxrwxrwx 1 root root 35 Sep 23 2001 /dev/cua/b -> /devices/obio/zs@0,100000:b,cu
If the serial devices do not show up in the
/dev directory, they can be manually added with a
mknod command. For example, the
following commands create the serial devices for the first serial port
on a Linux system:
# mknod -m 666 /dev/cua0 c 5 64 # mknod -m 666 /dev/ttyS0 c 4 64
However, if you need to add the serial devices manually, there may be a problem with the kernel configuration. The serial devices should be installed in your system by default during the boot when the hardware is detected. The following boot message shows the detection of a single serial interface on a Linux system:
$ dmesg | grep tty
ttyS00 at 0x03f8 (irq = 4) is a 16550You should see similar messages from your system boot for each interface that is detected. If you don’t, you may have a hardware problem with the serial interface board.
The modem used for the connection is attached to one of the
serial ports. Before attempting to build a dial-up script, make sure
the modem works and that you can communicate with it through
the port. Use a simple serial communications package, such as minicom, kermit, or seyon. First, make sure the program is
configured to use your modem. It must be set to the correct port,
speed, parity, number of databits, etc. Check your modem’s
documentation to determine these settings.
We’ll use minicom on a Linux
system for our examples. To configure minicom , su to
root and run it with the -s option, which displays a configuration
menu. Walk through the menu and make sure everything is properly set.
One thing you might notice is that the port is set to
/dev/modem. That device name is sometimes
symbolically linked to the port to which the modem is connected. If
you’re not sure that the link exists on your system, enter the correct
port name in the minicom
configuration, e.g., /dev/cua1. After checking
the configuration, exit the menu and use the minicom terminal emulator to make sure you
can communicate with the modem:
Welcome to minicom 1.83.1 OPTIONS: History Buffer, F-key Macros, Search History Buffer, I18n Compiled on Feb 23 2001, 07:31:40. Press CTRL-A Z for help on special keys AT S7=45 S0=0 L1 V1 X4 &c1 E1 Q0 OK atz OK atdt555-1234 CONNECT 26400/LAPM-V ^M Enter login> kristin Enter user password> Wats?Watt? Welcome to the PPP MODEM POOL PORT-9> set port ppp enabled +++ OK ath OK atz OK ^A CTRL-A Z for help | 57600 8N1 | NOR | Minicom 1.83.1 | VT102 | Offline X
In the sample, minicom
displays a few header lines and then sends a Hayes command (AT) to the modem. We didn’t set this
command; it was part of the default minicom configuration. (If it causes
problems, edit it out of the configuration using the menus discussed
previously.) We then reset the modem (atz) and dial the remote server (atdt). When the modems connect, we log into
the server and configure it. (The login process is different for every
remote server; this is just an example.) Everything appears to be
running fine, so we end the connection by getting the modem’s
attention (+++), hanging up the
line (ath), and resetting the
modem. Exit minicom by pressing
Ctrl-A followed by X. On our sample system the port and modem are
working. If you cannot send simple commands to your modem, ensure
that:
The modem is properly connected to the port
You have the correct cables
The modem is powered up
The modem is properly configured for dial-out and for echoing commands
When the modem responds to simple commands, use it to dial the
remote server as we did in the example above. If the modem fails to
dial the number or displays the message NO DIALTONE, check that the
telephone line is connected to the correct port of the modem and to
the wall jack. You may need to use an analog phone to test the
telephone wall jack and replace the line between the modem and the
wall to make sure that the cable is good. If the modem dials but fails
to successfully connect to the remote modem, check that the local
modem configuration matches the configuration required by the remote
system. You must know the requirements of that remote system to
successfully debug a connection. See the following list of script
debugging tips for some hints on what to check. If you can
successfully connect to the remote system, note everything you entered
to do so, and note everything that the modem and the remote server
display. Then set the remote server to PPP or SLIP mode and note how
you accomplished this. You will need to duplicate all of these steps
in your dip script.
Start with a bare-bones script, like the sample
start-ppp.dip script, so that you can debug the
basic connection before adding the complexity of error processing to
the script. Run the script through dip using the verbose option (-v) option. This displays each line of the
script as it is processed. Look for the following problems:
The modem does not respond to the script. Check that you are
using the correct device on the port command. Make sure that if the
script contains databits,
parity, speed, or stopbits commands, they are set to
values compatible with your modem. Double-check that the modem is
Hayes-compatible, particularly if you attempt to do modem
configuration using dip
keywords instead of using send.
The modem fails to connect to the remote host. Make sure the
modem is configured exactly as it was during the manual login. The
modem’s databits, parity, and other options need to match the
configuration of the remote system. It is possible that you will
need a special configuration, for example, 7-bit/even-parity, to
perform the login before you can switch to the 8-bit/no-parity
configuration required by PPP and SLIP. Don’t forget to check that
the phone number entered in the dial command is correct, particularly if
the modem displays VOICE, RING - NO ANSWER, or BUSY when you
expect to see CONNECT.
The script hangs. It is probably waiting for a response.
Make sure that the string in each wait command is correct. Remember that
the string only needs to be a subset of the response. It is better
to use the string “>” than it is to use “Port9>” if you are
not sure whether the remote system always displays the same port
number. Use a substring from the end of the expected response so
that the script does not send to the server before the server is
ready for input. Also try putting a delay into the script just
before the script sends the first command to the server, e.g.,
sleep 2 to delay two seconds. A
delay is sometimes needed to allow the server to initialize the
port after the modems connect.
The remote server displays an error message. The script
probably sent an incorrect value. Check the string in each
send command. Make sure they
terminate with the correct carriage-return or line-feed
combination expected by the remote server.
If you have trouble with the script, try running dip in test mode (-t), which allows you to enter each command
manually one at a time. Do this repeatedly until you are positive that
you know all the commands needed to log into the remote server. Then
go back to debugging the script. You’ll probably have fresh insight
into the login process that will help you find the flaw in the
script.
Once the script is running and the connection is successfully
made, things should run smoothly. You should be able to ping the remote server without difficulty.
If you have problems, they may be in the IP interface configuration or
in the default route. The script should have created the serial
interface. The netstat -ni command
shows which interfaces have been configured:
# netstat -ni
Name Mtu Net/Dest Address Ipkts Ierrs Opkts Oerrs Collis Queue
dnet0 1500 172.16.15.0 172.16.15.1 1 0 4 0 0 0
lo0 1536 127.0.0.0 127.0.0.1 1712 0 1712 0 0 0
ppp0 1006 172.16.15.26 172.16.15.3 0 0 0 0 0 0The interface, ppp0 in the example, has been installed. The
default command in the script
creates a default route. Use netstat to see the contents of the routing
table:
# netstat -nr
Routing tables
Destination Gateway Flags Refcnt Use Interface
127.0.0.1 127.0.0.1 UH 1 28 lo0
default 172.16.25.3 U 0 0 ppp0
172.16.15.0 172.16.15.1 U 21 1687 le0The contents of routing tables are explained in detail in the next chapter. For now, just notice that the interface used for the default route is ppp0 and that the default route is a route to the remote PPP server (172.16.25.3 in the example).
If the script creates the connection, the interface is installed, and the routing table contains the default route, everything should work fine. If you still have problems they may be related to other parts of the TCP/IP installation. Refer to Chapter 13 for more troubleshooting information.
TCP/IP works with a wide variety of networks. TCP/IP cannot make assumptions about the network it runs on—the network interface and its characteristics must be identified to TCP/IP. In this chapter we looked at several examples of how to configure the physical network interface over which TCP/IP runs.
ifconfig is the most commonly
used interface configuration command. It assigns the interface its IP
address, sets the subnet mask, sets the broadcast address, and performs
several other functions.
TCP/IP can also run over telephone lines using dial-up connections. Two protocols are available to do this: Serial Line IP (SLIP) and Point-to-Point Protocol (PPP). PPP is the preferred choice. It is an Internet standard and offers better reliability, performance, and security.
There are several steps to setting up a PPP connection:
configuring the serial protocol, configuring the port and modem, making
the dial-up connection, and completing the remote login. Some programs,
such as dip, combine all of these
steps into one program. Other programs, such as pppd and chat, separate the functions.
Configuring the network interface allows us to talk to the local
network, while configuring routing allows us to talk to the world. We
touched on routing in Chapter 2 and
again in this chapter in our discussion of routing metrics for ifconfig and default routes for PPP. In the
next chapter we look at routing in much greater detail.
[50] See the description of the H flag in Section 2.4.
[51] The packet statistics displayed by netstat are used in Chapter 13.
[52] index is an interface
characteristic that is specific to Solaris. It is an internal
number used to uniquely identify the interface. The number does
not have meaning to TCP/IP.
[53] Our sample Red Hat system places the file ifcfg.eth0 in the directory /etc/sysconfig/network-scripts.
[54] Hexadecimal notation can also be used for the address mask. To enter a netmask in hexadecimal form, write the value as a single hex number starting with a leading 0x. For example, the hexadecimal form of 255.255.255.0 is 0xffffff00. Choose the form that is easier for you to understand.
[55] /etc/netmasks is symbolically linked to /etc/inet/netmasks.
[56] Use the official network address, not a subnet address.
[57] On Solaris systems, promiscuous mode is enabled by
programs that need it. It is not set by the ifconfig command.
[58] Dial-up modems are usually asynchronous. Both PPP and SLIP support asynchronous dial-up service as well as synchronous leased-line service.
[59] Here ESC refers to the SLIP escape character, not the ASCII escape character.
[60] If you want to make sure you have the very latest version of a standard, obtain the latest list of RFCs as described in Appendix G.
[61] Check your system documentation to find out exactly how to configure PPP on your system.
[62] If a default route already exists in the routing table, the
defaultroute option is
ignored.
[63] If your modem doesn’t use the full Hayes modem command set,
avoid using dip commands, such
as rest and dial, that generate Hayes commands. Use
send instead. This allows you
to send any string you want to the modem.
[64] If you have call waiting, turn it off before you attempt to make a PPP connection. Different local telephone companies may use different codes to disable call waiting.
[65] For me, the PPP dial-up is just a backup; like many other people I use a high-speed connection. However, DSL and cable modem connections do not require a special configuration because the interface to most DSL and cable modems is Ethernet.
[66] See Appendix A for more details.