Since the days of BSD, the Transmission Control Protocol/Internet Protocol (TCP/IP) has been thoroughly integrated into the heart of most versions of UNIX. Linux is no exception. The Linux TCP/IP “stack” has been redesigned several times. The version currently available boasts speeds and reliability that rival any other implementation.

It is impossible to have a serious network based upon TCP/IP that is devoid of the influence of UNIX. If the network is connected in some way to the Internet, it will rely upon the root name servers (which run UNIX). If the network uses the global SMTP mail system, chances are that UNIX is involved. If the network has access to the World Wide Web, one out of every two web servers accessed will run Apache on UNIX. While it may be possible to implement these protocols over other operating systems, UNIX was the origin, and UNIX remains the preferred implementation.

The physical networking media (usually ethernet) will be addressed only tangentially. This hardware should be detected automatically during installation if it is configured correctly. Information on the cabling is available from many sources, and will be mentioned here only in passing.

Basic IP Configuration

This section will attempt to explain the three major components of a basic TCP/IP configuration: the IP address, the default gateway, and the DNS server.

If a host computer is being connected to a Class C IP network and no connections are being made to external networks and/or the Internet, only a single configuration parameter is required (the IP address):

IP Address
Standard IP addresses are unsigned 32-bit integers, but they are normally represented as 4 unsigned bytes in decimal notation, separated by dots. For example, the IP address C0A80101 would normally be represented as Every computer on a TCP/IP network (or internetwork) must have a unique IP address. In entering the IP address, a netmask and broadcast address will also be required, which is explained below.

If the computer is being connected to a TCP/IP network where routing is required, a default gateway address will most likely be necessary:

Default Gateway
This is the IP address of a router that is on the local network. On a Class C IP address, only the last digit (byte) of the router's IP address should be different from the IP addresses of any other hosts on the local networks. Be careful: routers always have more than one IP address. Choose only the one on the local network.

If the computer is being connected to the Internet (or to another TCP/IP network where DNS is performed), one last parameter is required:

DNS Server
The Domain Name Server is a computer that can translate Internet hostnames into IP addresses. For example, at the time that this text was composed, the one of the IP addresses of “” was The DNS server provides this translation; it does so by sending queries to the distributed, fault-tolerant domain name system.

In Class C IP networks, the Netmask parameter is always The network number is obtained by changing the last digit to a 0 in any IP address on the network (i.e., a bitwise AND of an IP address and the netmask). The broadcast address, if required, is the network number with a 255 as the last byte (the broadcast address allows data to be sent to all hosts on the local network - pinging the broadcast address will generate replies from up to 254 other hosts).

For example, let us pretend that a small home network is being constructed, and this network will not (at least most of the time) be connected to the Internet. A good choice for the IP address, network mask, and broadcast would be:

IP Address:

If a second computer were to be added to this network, it could be given an IP address of, and so on until All hosts on an IP network must share the same network number; if the Class C hosts and are connected directly without an intervening gateway, they will not be able to communicate because they do not share the same network number.

It might be a good idea to create an /etc/hosts file with pairs of IP addresses and hostnames. This would allow network connections to be made without the bother of remembering the exact address. This function is subsumed by a DNS server in larger networks.

Please note that the Class C network number is an excellent choice for a home network. See Chapter 4 for more details.

Now, let us imagine that the neighbor also constructed a home network, and he used the network number If a network cable was run between the two homes, a router device could be installed that would carry traffic between the two networks. The router would require two IP addresses. Two common choices would be and (host number 254 is commonly assigned as a gateway, and host 1 is commonly the DNS server - these are values that Red Hat will assume during installation). Linux can be a router if it is explicitly instructed to do so - this behavior is controlled by the /etc/sysconfig/network file. This file also contains the IP address of the default gateway. Settings from this file are normally activated at boot time. Hosts on the first network could define their default gateway as, and any data not bound for hosts on the local network would automatically be sent to the remote. If more than two local networks are connected, the default route might no longer be used to direct traffic, and a more explicit routing table would be required.

Bearing all of this in mind, attached in Figures 2-1 and 2-2 are screenshots of the netcfg utility, which can be used to edit network interface configurations once they are installed:

The linuxconf utility can also be used to add network devices. In the following example, a 3Com 509 ethernet card is configured:

            ************ This host basic configuration *************
            * You are allowed to control the parameters            *
            * which are specific to this host and related          *
            * to its main connection to the local network          *
            *                                                      *
            *                      *********************************
            *                      ***********Adaptor 2*************
            *                      *[X] Enabled                   **
            *Config mode           *(o) Manual ( ) Dhcp ( ) Bootp **
            *Primary name + domain *                              **
            *Aliases (opt)         *                              **
            *IP address            *                   **
            *Netmask (opt)         *                ***
            *Net device            *eth1                         ***
            *Kernel module         *3c509                        ***
            *I/O port (opt)        *                              **
            *Irq (opt)             *                             ***
            *                      ***********Adaptor 3*************
            *                      *[ ] Enabled                   **
            *                      *********************************
            *       ********        ********        ******         *
            *       *Accept*        *Cancel*        *Help*         *
            *       ********        ********        ******         *

To accomplish the same operation from the command line, one could enter:

# modprobe 3c509.o
eth1: 3c509 at 0x300 tag 1, 10baseT port, address  00 60 97 a6 b0 e5, IRQ 10.
3c509.c:1.16 (2.2) 2/3/98
# ifconfig eth1 netmask broadcast
eth1: Setting Rx mode to 1 addresses.

However, adding the device with the command line will not make entries for it in the system initialization scripts. When Linux is rebooted, the card definition will be lost. Cards defined for boot-time initialization leave entries in /etc/conf.modules and the /etc/sysconfig/network-scripts directory.

When adding a network device such as the above, a route to the network will automatically be added to the routing table, enabling access to the network which is directly attached to the adapter. Access to additional networks (including the default route) must be added explicitly.

The only piece of information that is not immediately clear above is the modprobe 3c509.o section. This command loads a kernel module. This module is a driver for a 3Com 509 network card. An experienced Linux administrator might be able to pick up a network card, find upon it a Digital 21040 network chip (for example), and realize that a call to modprobe tulip.o would properly initialize the card. However, such knowledge normally escapes the novice. For more information about kernel module drivers for network cards, install the Linux kernel source and examine the /usr/src/linux/Documentation/networking directory. Some of these network driver modules (especially modules for ISA network adapters, such as the NE2000) require extensive information about the card before they will load and initialize properly. Generally, if possible, it is much more convenient to have these cards detected at installation time, rather than adding to the system later.

To reiterate, basic network configuration requires the three parameters of IP address, netmask, and broadcast address.

The more expansive configuration options of gateway address and DNS server are addressed by the /etc/sysconfig/network script and /etc/resolv.conf files. These files are configured at install time, and with luck they should not require modification.

The final point of this section is a trick with 10BaseT ethernet cabling used between two computers, allowing a home network to be constructed very inexpensively. Normally, if 10BaseT twisted-pair ethernet is being used, a hub is required to allow two or more computers to communicate. However, two 10BaseT devices can communicate without a hub if a special cable is constructed (or obtained from a manufacturer). This cable reverses the transmit and receive wire pairs from end to end. The RJ-45 wiring diagram follows (note that pins 4, 5, 7, and 8 are unused):

PairHost LeadRemote Lead

Such a “crossover” cable dramatically reduces the expense of connecting two 10BaseT devices, which is useful in cost-conscious installations.


This section discusses techniques for subnetting Class C IP addresses. Subnetting an IP network is a method that can be used to transform a single network into many. It is usually employed when multiple networks must be maintained, but multiple Class C (or Class B or A) networks are not available.

Unless you have specific reasons for using subnets of a Class C, it is probably a very bad idea. IP Masquerading techniques, as discussed in Chapter 4, might be a much more convenient method for attaching multiple hosts to the Internet with limited IP address space.

Also note that two IP addresses will be sacrificed for each subnet formed (one for the network number, and one for the broadcast address), plus another IP required for a router.

Despite these difficulties, let us pretend that a system administrator at a branch office of some company has been allocated the Class C IP network of 192.168.1. Let us further suppose that this single office opens up two additional satellite offices close by. The administrator is expected to network the additional offices using the Class C already in possession (another Class C will not be granted).

A quick reminder of the powers of 2 might be in order:


The regular Class C netmask used before the split is shown below, both in decimal and binary form:

The administrator decides to expand the netmask two bits beyond the Class C, like so:

In the modified netmask, the final byte now has the two leftmost (or most significant) bits set. A sequence of two bits can be arranged in four different ways (00, 01, 10, or 11), so expanding the netmask in this way will create four new networks. Only three are needed, but the fourth must follow as networks can only be allocated in powers of two.

In expanding the subnet mask in this way, the following four networks have been created:

NetworkNetmaskBroadCastStarting IPConcluding IP

A router will be required to route traffic on each network, and the router will consume an IP address on each network. In total, twelve IP addresses will be consumed between the new network numbers, broadcast addresses, and the new gateways.

Use this technique only when necessary.


The Domain Name System is the engine that translates host names into IP addresses. It is a cornerstone of Internet design. No domain with connectivity to the Internet can afford to ignore it.

If a system with Red Hat Linux will ever be connected to the Internet in any way except through proxies, it should probably have at least a caching-only DNS server installed. Such a caching server will be loaded at installation time if “named” is selected from the package list. This is especially true for modem users, or users of transient or limited bandwidth connections.

The DNS server and caching-only settings can be loaded at any time after installation by issuing the following commands from the RedHat/RPMS directory of the installation tree:

rpm -Uvh bind-8.2-6.i386.rpm
rpm -Uvh caching-nameserver-6.0-2.noarch.rpm

Installing the Bind package will automatically configure it to be launched at boot time through the /etc/rc.d/init.d/named startup script. If this is not the desired behavior, use the ntsysv utility to alter the boot status.

Please note that if Red Hat Linux was installed over a network (with either FTP or NFS) and a name server was specified, that server will be used in preference to any name server running on the local host if the network settings were retained at the end of the installation. To specify the local host as the primary name server, make sure that the first nameserver directive in /etc/resolv.conf reads as follows:


The /etc/resolv.conf file can also be removed to force the local name server to be used, however, if the local server fails, connectivity to the Internet will essentially be lost. It is preferable to list up to three nameserver entries; the local will fail over to the backup(s) should the primary server(s) cease responding.

Be cautious with the permissions on the /etc/resolv.conf file, as well. If a user does not have read permissions on this file, their DNS resolution will fail.

A name server is normally used in two ways. One is where it is asked to provide information about hosts which it owns (over which it is authoritative). Another way they are used is where they are asked about hosts over which they are not authoritative, and they must query other (authoritative) name servers to gain the information, which they then cache.

The caching-only settings for the name server above create a name server that is authoritative about nothing, and it must ask other name servers about every host. Even if it is the administrator's intention to create an authoritative name server, the installation of the caching-only name server is recommended as a caching-only server is the skeleton of an authoritative server.

Files for Forward Lookups

Before DNS authority records can be created, a domain must be obtained from InterNIC. This can be accomplished through their website at In order to register a domain, two authoritative name servers for the requested domain must be available at the time of the registration.

The popular “whois” utility is now included in Red Hat Linux and can be used to query the InterNIC databases (the utility was sorely lacking in past releases):


Red Hat Software (REDHAT-DOM)
   4201 Research Commons, Suite 100
   79 T.W. Alexander Dr.
   P.O. Box 13588
   Research Triangle Park, NC 27709

   Domain Name: REDHAT.COM

   Administrative Contact, Technical Contact, Zone Contact:
      Network Operations Center  (NOC144-ORG)  noc@REDHAT.COM
      919-572-6500 x235Fax- 919-361-2711
Fax- - 919-361-2711
   Billing Contact:
      Accounts Payable  (AP1279-ORG)  accounts@REDHAT.COM
      (919) 572-6500
Fax- (919) 361-2711

   Record last updated on 23-Jul-97.
   Record created on 26-May-94.
   Database last updated on 16-Dec-98 03:49:10 EST.

   Domain servers in listed order:


The InterNIC Registration Services database contains ONLY
non-military and non-US Government Domains and contacts.
Other associated whois servers:
   American Registry for Internet Numbers -
   European IP Address Allocations        -
   Asia Pacific IP Address Allocations    -
   US Military                            -
   US Government                          -

Let us say that we have obtained the domain, and it has been registered with the InterNIC. To configure the primary name server, we might save the following text in /var/named/db.acme:

@               IN SOA (
                        199901010       ; Serial
                        10800           ; Refresh
                        1800            ; Retry
                        3600000         ; Expire
                        86400 )         ; Minimum
                        IN      NS    
                        IN      NS    
                        IN      MX      10

localhost               IN      A                    IN      A     
www                     IN      A     

mail                    IN      CNAME 
ftp                     IN      CNAME 

This file is probably the simplest format for a small domain registration. The IP address of and are both listed as Additional hosts for the domain could be listed with more “IN A” records.

This file will essentially allow anyone on the Internet to connect to the hostname, which will be quietly resolved to To see such a resolution in action, the UNIX “nslookup” command can be used:

Server:  localhost


Files for Reverse Lookups

In order to configure a file for reverse lookups, an Internet network number must be obtained. These network numbers are usually received through network service providers, who obtain them from the Internet Assigned Numbers Authority (IANA) at

Assuming that the Internet Class C network 1.2.3 has been obtained, the following file would be placed in /var/named/db.1.2.3:

@		IN SOA (
			199901010	; Serial
			10800	; Refresh
			1800	; Retry
			3600000 ; Expire
			86400 )	; Minimum
                        IN      NS    
                        IN      NS    


The term “reverse lookup” means that the IP address can be looked up to obtain the hostname:

Server:  localhost


If a domain does not define a reverse lookup for some IP address (which is bad practice if the address is in use), the registered owner of the IP can be determined with whois:

NETCOM On-Line Communication Services, Inc. (NETBLK-NETCOMCBLK-3) NETBLK-NETCOMCBLK-3 -
Red Hat Software (NET-REDHAT)	REDHAT

To single out one record, look it up with "!xxx", where xxx is the
handle, shown in parenthesis following the name, which comes first.

The ARIN Registration Services Host contains ONLY Internet
Network Information: Networks, ASN's, and related POC's.
Please use the whois server at for DOMAIN related
Information and for NIPRNET Information.

Configuring /etc/named.conf

Once the master files have been created, the primary name server must be instructed to use them. This is done by modifying /etc/named.conf. The modified file for this case follows:

options {
        directory "/var/named";

// no longer a caching only nameserver config

zone "." {
        type hint;
        file "";

zone "" {
        type master;
        file "named.local";

zone "" {
        type master;
        file "db.acme";

zone "" {
        type master;
        file "db.1.2.3";

After the file has been placed, restart the primary name server with the following command:

/etc/rc.d/init.d/named restart

The secondary server can be configured by instructing it to replicate the new domains from the primary. This means that the data files can be maintained in only one place, easing administration. However, when the files are changed on the primary, the serial number near the top must be increased. This is normally done by using the current date for the serial number.

The secondary must be told the IP address of the primary in the named.conf file. Assuming that the IP address of the primary is, the proper form of the named.conf file on the secondary would be:

options {
        directory "/var/named";

zone "." {
        type hint;
        file "";

zone "" {
        type master;
        file "named.local";

zone "" {
        type slave;
        file "db.acme";
        masters {

zone "" {
        type slave;
        file "db.1.2.3";
        masters {

When the secondary name server is restarted, it will automatically transfer the domain information from the primary and build the db.acme and db.1.2.3 file in /var/named (however, they will look nothing like the original files on the primary).

The file /var/named/ (which exists on both the primary and the secondary) must be reloaded from time to time. Instructions for doing so are in the file itself. This must even be done for caching-only name servers. The file should be checked for new changes once every six months. If the computer is regularly upgraded with new versions of Red Hat, the upgrade will be performed automatically.

Round-Robin DNS and “Clustering”

The version of named distributed with Red Hat Linux supports a simple method of server load balancing. Several hosts can be given the same name. When this is done, named will automatically cycle through the entire list of IP addresses when asked to resolve the name, answering each query with a different IP.

Obviously, this method of load distribution will not be even across all servers. If a firewall's DNS resolves to a certain host, it may direct thousands of clients there for the period that it is allowed to cache the results of the lookup.

This rotation is configured in the forward lookup files. If records such as the following were entered into /var/named/db.acme:

www                     IN      A     
                        IN      A     
                        IN      A     
                        IN      A     
                        IN      A     

The first lookup on would be, the second would be, the third would be, and so on.

IP Alias and Virtual Hosting

IP Alias is a mechanism where a single ethernet interface can respond to multiple IP addresses. This has many applications, including the virtual hosting of websites and fault-tolerant network services design.

Let us imagine that the eth0 device has been configured with the standard Class C network address of The interface could be configured to also respond to with the following sequence of commands (issued by root):

/sbin/ifconfig eth0:0
/sbin/route add -host dev eth0:0

Any normal network services which ran on the first interface (i.e., Telnet, FTP, etc.) will run on the second. Some services pay particular attention to IP Alias settings, and will modify their behavior for each interface if configured to do so (i.e., Apache).

Additional interfaces can be created by following a sequence:

/sbin/ifconfig eth0:1
/sbin/route add -host dev eth0:1

A computer could provide backup network services for another host by issuing ping packets at regular intervals. If the remote host does not respond, the backup computer could automatically execute an IP Alias for the inoperative host's network address, providing a rudimentary form of fault tolerance.


The Dynamic Host Configuration Protocol is a method to allocate IP addresses and other relevant parameters for TCP/IP from a centralized repository, rather than recording the information statically on each host. A DHCP server should be a computer that is operational and attached to its network continuously, available whenever clients might request its services.

If a network has more than a few hosts, and it has a Linux system that is in continual operation, it should have a DHCP server to ease network administration.

The server portion of the protocol is implemented by the dhcpd daemon. This server protocol is compatible with the DHCP implementations used by other operating systems (i.e., the variants of Microsoft Windows).

The Linux client portion is controlled by dhcpcd or pump. It is automatically configured if DHCP is selected for the TCP/IP configuration at installation time. It can be implemented after installation via netcfg.

The DHCP server is not automatically installed when a Red Hat Linux system is prepared. It can be installed by running the following commands as root from the RedHat/RPMS directory of the CD included with this text:

rpm -Uvh dhcp-2.0b1pl6-6.i386.rpm
touch /etc/dhcpd.leases

Installing the package will automatically configure it to be launched at boot time through the /etc/rc.d/init.d/dhcpd startup script. If this is not the desired behavior, use the ntsysv utility to alter the boot status.

There is a Linux-specific issue in the configuration of the DHCP server. A routing command must be run to allow traffic to be sent to the IP address. This issue is documented in the file /usr/doc/dhcp-2.0b1pl6/README. The exact command is:

/sbin/route add -host dev eth0

This command must be run every time the system is restarted, so it should be placed in one of the boot scripts. A good location for it is in the /etc/rc.d/init.d/dhcpd file, in the startup section. Following is a fragment of a startup script from a running system, which introduces another important DHCP issue and some related points:

# See how we were called.
case "$1" in
        # Start daemons.
        echo -n "Starting dhcpd: "
        /sbin/route add -host dev eth1
        daemon /usr/sbin/dhcpd eth1
        /sbin/ipfwadm-wrapper -F -p deny
        /sbin/ipfwadm-wrapper -F -a m -S -D
        /sbin/modprobe ip_masq_ftp
        touch /var/lock/subsys/dhcpd

Notice that the above route command routes not to eth0, but to the eth1 network device. Note further that eth1 has been passed as an argument to the dhcpd command line. In a system with multiple network devices, dhcpd must be instructed in this way which device it is to use.

The calls to ipfwadm-wrapper and modprobe are not directly related to DHCP. They configure the local system as a masquerading router. A “synthetic” network with a 192.168.1 network number will have all outgoing packets rewritten with the local IP address that forwards to the default gateway. This technique is extremely useful in the conservation of valuable Internet IP addresses, and is discussed at some length in Chapter 4.

There is also a warning if an advanced development kernel is utilized. It might be necessary to issue the following command (although it is not necessary with the kernel distributed with Red Hat Linux 6.0):

echo 1 >/proc/sys/net/ipv4/ip_bootp_agent

The last step in bringing a Linux DHCP server online is writing an /etc/dhcpd.conf file. An example of such a file follows:

subnet netmask {
        default-lease-time 600; max-lease-time 7200;
        option subnet-mask;
        option broadcast-address;
        option routers;
        option domain-name-servers;
        option domain-name "";

This configuration is designed for a 192.168.1 network. Each of the directives is discussed below:

This command sets the range of IP addresses which the server may hand out to clients. The addresses that will be dispensed here are from 128 to 254.

default-lease-time 600; max-lease-time 7200;
This directive controls how long clients may keep the IP addresses that the DHCP server allocates to them. The time is specified in seconds.

option subnet-mask;
The actual subnet mask that is passed to the clients is stated here.

option broadcast-address;
The broadcast address that is passed to the clients is stated here.

option routers;
The address of the router that is passed to the clients is stated here. Notice that this is the address of the DHCP server, which is also serving as a router.

option domain-name-servers;
The address of the DNS server that is passed to the clients is stated here. Notice that this is the address of the DHCP server, which is also serving as a Domain Name Server - it must either be configured as a DNS server that is authoritative for some domain, or as a caching-only name server.

option domain-name "";
The actual text of the domain name that is passed to the clients is stated here.

To start the DHCP server, either reboot the system, or run the following command as root:

/etc/rc.d/init.d/dhcpd start

Many additional configuration parameters are available. Specifically, individual computers can be granted specific settings by the DHCP server based upon the MAC address of the network card within them (the Media Access Controller address, or MAC address, is a truly unique identifier that vendors of ethernet devices embed into their products).

For additional information on the operation of DHCP services, check the online manual pages for dhcpd, dhcpd.conf, and dhcpcd. Also, when debugging the behavior of dhcpd, it can be useful to examine /var/log/messages as all DHCP activity is logged there.


The Network File System (NFS) is a protocol designed by Sun Microsystems that allows directories to be easily shared with remote computers.

If you have purchased any books on basic NFS operation for Linux, throw them away. NFS is almost trivially easy to configure and use.

The NFS server is configured through the /etc/exports file. The simplest (and least secure) configuration simply lists directories that may be shared with other servers:


The Red Hat Linux NFS server is started by calling the portmap and nfs scripts in /etc/rc.d/init.d. These can be configured to run at boot time, or they can be launched with the following commands:

/etc/rc.d/init.d/portmap start
/etc/rc.d/init.d/nfs start

If the server is already active and the /etc/exports file has been changed, the server can be instructed to reread the file with the command:

exportfs -rv

Once the server has been initialized, a client can use the exported directories (called “volumes” when used over NFS) with a simple mount command:

mount /mnt

An IP address can be used instead of a hostname. Several other options can be passed that influence performance (particularly rsize=8192,wsize=8192). Check the man page for mount for more information.

If a hostname is used, rather than an IP address, the system must be able to somehow resolve the name of a remote NFS server into an IP address. Since DNS failures can prevent this resolution from taking place, it is always advisable to place entries in /etc/hosts for NFS servers mounted at boot time. It might also be profitable to examine /etc/nsswitch.conf and /etc/fstab for additional flexibility in boot time mounts.

When the mount command is executed, the local host will then see the remote file system within the local directory tree, and can manipulate the files natively. File locking can be a problem; if there is great contention over a file, it is best not to place it within an NFS volume.

Please also note that mounting an NFS file system over the Internet is not a very good thing to do. NFS normally uses UDP packets which are suited to local networks; UDP packets over the Internet can be discarded easily and force retransmissions; FTP is much more appropriate for Internet usage. scp with compression is even better (scp is discussed in Chapter 4).

Also note that the root user is normally restricted in accessing remote file systems through a mechanism called “root squash.” The root will usually work as user “nobody” on the volume. Every other user is completely vulnerable to whatever the remote administrator may do, so do not export an NFS volume to a system that you do not trust (or at least export it as read-only, which is discussed shortly).

As previously mentioned, /etc/exports can be made much more secure. Examine the following:


This file allows only to access /home via NFS, and root squash is in effect. The /usr/local/bin directory is set for read-only access from, and the /var directory has been completely shared with; root may work natively on the remote host with full access to the exported volume.

NIS presents a different issue entirely. The Network Information System is a framework that allows several important files to be shared between UNIX hosts (namely /etc/passwd, /etc/group, and /etc/hosts among others). Unfortunately, NIS has a reputation of being rather insecure. It also can be cumbersome to use, as the local /etc/passwd file is no longer the authoritative source of local account information.

Several alternatives to NIS exist, including NIS+, the DCE registry, and Hesiod Bind. They are all extremely difficult to configure and use.

A much simpler and better solution would be to use scp to copy these files from an arbitrarily-allocated master server to the “slave” servers whenever the files change. The programs which change these files (such as chfn, chsh, passwd, and chgrp) should be disabled on the slave servers.