系统管理指南:IP 服务

第 18 章 DHCP 命令和文件(参考)

本章介绍了 DHCP 命令和 DHCP 文件之间的关系,但并未介绍如何使用这些命令。

本章包含以下信息:

DHCP 命令

下表列出了可用于在网络中管理 DHCP 的命令。

表 18–1 用于 DHCP 的命令

命令 

说明 

手册页 

dhtadm

用于对 dhcptab 中的选项和宏进行更改。此命令最适用于在创建的脚本中自动更改 DHCP 信息。使用带有 -P 选项的 dhtadm,并通过 grep 命令传输输出,可以在 dhcptab 表中快速搜索特定的选项值。

dhtadm(1M)

pntadm

用于更改将客户机 ID 映射到 IP 地址的 DHCP 网络表,还可选择将配置信息与 IP 地址进行关联。

pntadm(1M)

dhcpconfig

用于配置和取消配置 DHCP 服务器及 BOOTP 中继代理。另外,还可用于转换为另一种数据存储格式,以及导入和导出 DHCP 配置数据。

dhcpconfig(1M)

in.dhcpd

DHCP 服务器守护进程。该守护进程在启动系统时启动。请勿直接启动服务器守护进程。使用 DHCP 管理程序、svcadm 命令或 dhcpconfig 可启动和停止该守护进程。仅当以调试模式运行服务器来解决问题时,才可以直接调用该守护进程。

in.dhcpd(1M)

dhcpmgr

DHCP 管理程序,一种用于配置和管理 DHCP 服务的图形用户界面 (graphical user interface, GUI) 工具。推荐将 DHCP 管理程序作为 Oracle Solaris : DHCP 管理工具。

dhcpmgr(1M)

ifconfig

在系统引导时用于为网络接口指定 IP 地址或配置网络接口参数,或者同时执行这两种操作。在 Oracle Solaris : DHCP 客户机上,ifconfig 可启动 DHCP 以获取配置网络接口所需的参数(包括 IP 地址)。

ifconfig(1M)

dhcpinfo

由 Oracle Solaris : 客户机系统的系统启动脚本用于从 DHCP 客户机守护进程 dhcpagent 中获取信息(如主机名)。您也可以在脚本或命令行中使用 dhcpinfo 来获取指定的参数值。

dhcpinfo(1)

snoop

用于捕获和显示在网络中传送的包的内容。snoop 在解决 DHCP 服务问题时非常有用。

snoop(1M)

dhcpagent

DHCP 客户机守护进程,用于实现 DHCP 协议的客户端。 

dhcpagent(1M)

在脚本中运行 DHCP 命令

dhcpconfigdhtadmpntadm 命令为便于在脚本中使用进行了优化。特别是,pntadm 命令对于在 DHCP 网络表中创建大量 IP 地址项非常有用。以下样例脚本在批处理模式下使用 pntadm 来创建 IP 地址。


示例 18–1 使用 pntadm 命令的 addclient.ksh 脚本

#! /usr/bin/ksh
#
# This script utilizes the pntadm batch facility to add client entries
# to a DHCP network table. It assumes that the user has the rights to
# run pntadm to add entries to DHCP network tables.

#
# Based on the nsswitch setting, query the netmasks table for a netmask.
# Accepts one argument, a dotted IP address.
#
get_netmask()
{
	MTMP=`getent netmasks ${1} | awk '{ print $2 }'`
	if [ ! -z "${MTMP}" ]
	then
		print - ${MTMP}
	fi
}

#
# Based on the network specification, determine whether or not network is 
# subnetted or supernetted.
# Given a dotted IP network number, convert it to the default class
# network.(used to detect subnetting). Requires one argument, the
# network number. (e.g. 10.0.0.0) Echos the default network and default
# mask for success, null if error.
#
get_default_class()
{
	NN01=${1%%.*}
	tmp=${1#*.}
	NN02=${tmp%%.*}
	tmp=${tmp#*.}
	NN03=${tmp%%.*}
	tmp=${tmp#*.}
	NN04=${tmp%%.*}
	RETNET=""
	RETMASK=""

	typeset -i16 ONE=10#${1%%.*}
	typeset -i10 X=$((${ONE}&16#f0))
	if [ ${X} -eq 224 ]
	then
		# Multicast
		typeset -i10 TMP=$((${ONE}&16#f0))
		RETNET="${TMP}.0.0.0"
		RETMASK="240.0.0.0"
	fi
	typeset -i10 X=$((${ONE}&16#80))
	if [ -z "${RETNET}" -a ${X} -eq 0 ]
	then
		# Class A
		RETNET="${NN01}.0.0.0"
		RETMASK="255.0.0.0"
	fi
	typeset -i10 X=$((${ONE}&16#c0))
	if [ -z "${RETNET}" -a ${X} -eq 128 ]
	then
		# Class B
		RETNET="${NN01}.${NN02}.0.0"
		RETMASK="255.255.0.0"
	fi
	typeset -i10 X=$((${ONE}&16#e0))
	if [ -z "${RETNET}" -a ${X} -eq 192 ]
	then
		# Class C
		RETNET="${NN01}.${NN02}.${NN03}.0"
		RETMASK="255.255.255.0"
	fi
	print - ${RETNET} ${RETMASK}
	unset NNO1 NNO2 NNO3 NNO4 RETNET RETMASK X ONE
}

#
# Given a dotted form of an IP address, convert it to its hex equivalent.
#
convert_dotted_to_hex()
{
	typeset -i10 one=${1%%.*}
	typeset -i16 one=${one}
	typeset -Z2 one=${one}
	tmp=${1#*.}

	typeset -i10 two=${tmp%%.*}
	typeset -i16 two=${two}
	typeset -Z2 two=${two}
	tmp=${tmp#*.}

	typeset -i10 three=${tmp%%.*}
	typeset -i16 three=${three}
	typeset -Z2 three=${three}
	tmp=${tmp#*.}

	typeset -i10 four=${tmp%%.*}
	typeset -i16 four=${four}
	typeset -Z2 four=${four}

	 hex=`print - ${one}${two}${three}${four} | sed -e 's/#/0/g'`
	 print - 16#${hex}
	 unset one two three four tmp
}

#
# Generate an IP address given the network address, mask, increment.
# 
get_addr()
{
	typeset -i16 net=`convert_dotted_to_hex ${1}`
	typeset -i16 mask=`convert_dotted_to_hex ${2}`
	typeset -i16 incr=10#${3}

	# Maximum legal value - invert the mask, add to net.
	typeset -i16 mhosts=~${mask}
	typeset -i16 maxnet=${net}+${mhosts}

	# Add the incr value.
	let net=${net}+${incr}

	if [ $((${net} < ${maxnet})) -eq 1 ]
	then
		typeset -i16 a=${net}\&16#ff000000
		typeset -i10 a="${a}>>24"

		typeset -i16 b=${net}\&16#ff0000
		typeset -i10 b="${b}>>16"

		typeset -i16 c=${net}\&16#ff00
		typeset -i10 c="${c}>>8"

		typeset -i10 d=${net}\&16#ff
		print - "${a}.${b}.${c}.${d}"
	fi
	unset net mask incr mhosts maxnet a b c d
}

# Given a network address and client address, return the index.
client_index()
{
	typeset -i NNO1=${1%%.*}
	tmp=${1#*.}
	typeset -i NNO2=${tmp%%.*}
	tmp=${tmp#*.}
	typeset -i NNO3=${tmp%%.*}
	tmp=${tmp#*.}
	typeset -i NNO4=${tmp%%.*}

	typeset -i16 NNF1
	let NNF1=${NNO1}
	typeset -i16 NNF2
	let NNF2=${NNO2}
	typeset -i16 NNF3
	let NNF3=${NNO3}
	typeset -i16 NNF4
	let NNF4=${NNO4}
	typeset +i16 NNF1
	typeset +i16 NNF2
	typeset +i16 NNF3
	typeset +i16 NNF4
	NNF1=${NNF1#16\#}
	NNF2=${NNF2#16\#}
	NNF3=${NNF3#16\#}
	NNF4=${NNF4#16\#}
	if [ ${#NNF1} -eq 1 ]
	then
		NNF1="0${NNF1}"
	fi
	if [ ${#NNF2} -eq 1 ]
	then
		NNF2="0${NNF2}"
	fi
	if [ ${#NNF3} -eq 1 ]
	then
		NNF3="0${NNF3}"
	fi
	if [ ${#NNF4} -eq 1 ]
	then
		NNF4="0${NNF4}"
	fi
	typeset -i16 NN
	let NN=16#${NNF1}${NNF2}${NNF3}${NNF4}
	unset NNF1 NNF2 NNF3 NNF4

	typeset -i NNO1=${2%%.*}
	tmp=${2#*.}
	typeset -i NNO2=${tmp%%.*}
	tmp=${tmp#*.}
	typeset -i NNO3=${tmp%%.*}
	tmp=${tmp#*.}
	typeset -i NNO4=${tmp%%.*}
	typeset -i16 NNF1
	let NNF1=${NNO1}
	typeset -i16 NNF2
	let NNF2=${NNO2}
	typeset -i16 NNF3
	let NNF3=${NNO3}
	typeset -i16 NNF4
	let NNF4=${NNO4}
	typeset +i16 NNF1
	typeset +i16 NNF2
	typeset +i16 NNF3
	typeset +i16 NNF4
	NNF1=${NNF1#16\#}
	NNF2=${NNF2#16\#}
	NNF3=${NNF3#16\#}
	NNF4=${NNF4#16\#}
	if [ ${#NNF1} -eq 1 ]
	then
		NNF1="0${NNF1}"
	fi
	if [ ${#NNF2} -eq 1 ]
	then
		NNF2="0${NNF2}"
	fi
	if [ ${#NNF3} -eq 1 ]
	then
		NNF3="0${NNF3}"
	fi
	if [ ${#NNF4} -eq 1 ]
	then
		NNF4="0${NNF4}"
	fi
	typeset -i16 NC
	let NC=16#${NNF1}${NNF2}${NNF3}${NNF4}
	typeset -i10 ANS
	let ANS=${NC}-${NN}
	print - $ANS
}

#
# Check usage.
#
if [ "$#" != 3 ]
then
	print "This script is used to add client entries to a DHCP network"
	print "table by utilizing the pntadm batch facilty.\n"
	print "usage: $0 network start_ip entries\n"
	print "where: network is the IP address of the network"
        print "       start_ip is the starting IP address \n"
        print "       entries is the number of the entries to add\n"
	print "example: $0 10.148.174.0 10.148.174.1 254\n"
	return
fi

#
# Use input arguments to set script variables.
#
NETWORK=$1
START_IP=$2
typeset -i STRTNUM=`client_index ${NETWORK} ${START_IP}`
let ENDNUM=${STRTNUM}+$3
let ENTRYNUM=${STRTNUM}
BATCHFILE=/tmp/batchfile.$$
MACRO=`uname -n`

#
# Check if mask in netmasks table. First try
# for network address as given, in case VLSM
# is in use.
#
NETMASK=`get_netmask ${NETWORK}`
if [ -z "${NETMASK}" ]
then
	get_default_class ${NETWORK} | read DEFNET DEFMASK
	# use the default.
	if [ "${DEFNET}" != "${NETWORK}" ]
	then
		# likely subnetted/supernetted.
		print - "\n\n###\tWarning\t###\n"
		print - "Network ${NETWORK} is netmasked, but no entry was found  \n
              in the 'netmasks' table; please update the 'netmasks'  \n
              table in the appropriate nameservice before continuing. \n 
              (See /etc/nsswitch.conf.) \n" >&2
		return 1
	else
		# use the default.
		NETMASK="${DEFMASK}"
	fi
fi

#
# Create a batch file.
#
print -n "Creating batch file "
while [ ${ENTRYNUM} -lt ${ENDNUM} ]
do
	if [ $((${ENTRYNUM}-${STRTNUM}))%50 -eq 0 ]
	then
		print -n "."
	fi

	CLIENTIP=`get_addr ${NETWORK} ${NETMASK} ${ENTRYNUM}`
	print "pntadm -A ${CLIENTIP} -m ${MACRO} ${NETWORK}" >> ${BATCHFILE}
	let ENTRYNUM=${ENTRYNUM}+1
done
print " done.\n"

#
# Run pntadm in batch mode and redirect output to a temporary file.
# Progress can be monitored by using the output file.
#
print "Batch processing output redirected to ${BATCHFILE}"
print "Batch processing started."

pntadm -B ${BATCHFILE} -v > /tmp/batch.out 2 >&1

print "Batch processing completed."

DHCP 服务使用的文件

下表列出了与 Oracle Solaris : DHCP 关联的文件。

表 18–2 DHCP 守护进程和命令使用的文件和表

文件名或表名 

说明 

手册页 

dhcptab

DHCP 配置信息表的通称,这些配置信息以选项及指定值的形式进行记录,而这些选项及指定值随后会组合为宏。dhcptab 表的名称及其地址由用于 DHCP 信息的数据存储确定。

dhcptab(4)

DHCP 网络表 

将 IP 地址映射为客户机 ID 和配置选项。DHCP 网络表根据网络的 IP 地址(如 10.21.32.0)来命名。不存在名为 dhcp_network 的文件。DHCP 网络表的名称和地址由用于 DHCP 信息的数据存储确定。

dhcp_network(4)

dhcpsvc.conf

存储 DHCP 守护进程的启动选项以及数据存储信息。此文件决不能手动编辑。使用 dhcpconfig 命令可更改启动选项。

dhcpsvc.conf(4)

nsswitch.conf

指定名称服务数据库的地址以及搜索名称服务以查找各种信息的顺序。配置 DHCP 服务器时,会读取 nsswitch.conf 文件以获取准确的配置信息。此文件位于 /etc 目录中。

nsswitch.conf(4)

resolv.conf

包含用于解析 DNS 查询的信息。在 DHCP 服务器配置过程中,会查看此文件以获取有关 DNS 域和 DNS 服务器的信息。此文件位于 /etc 目录中。

resolv.conf(4)

dhcp.interface

表示将在 dhcp.interface 文件名中指定的客户机网络接口上使用 DHCP。例如,存在名为 dhcp.qe0 的文件表示将在 qe0 接口上使用 DHCP。dhcp.interface 文件可能包含一些命令,这些命令将作为选项传递给用于在客户机上启动 DHCP 的 ifconfig 命令。此文件位于 Oracle Solaris : DHCP 客户机系统上的 /etc 目录中。

没有特定的手册页,请参见 dhcp(5)

interface.dhc

包含从 DHCP 中为给定网络接口获取的配置参数。当删除此接口的 IP 地址租用时,客户机会将当前配置信息高速缓存至 /etc/dhcp/interface.dhc 中。例如,如果在 qe0 接口上使用 DHCP,则 dhcpagent 会将配置信息高速缓存至 /etc/dhcp/qe0.dhc 中。下次在此接口上启动 DHCP 时,如果租用未过期,客户机会请求使用高速缓存的配置。如果 DHCP 服务器拒绝此请求,则客户机会启动标准的 DHCP 租用协商进程。

没有特定的手册页,请参见 dhcpagent(1M)

dhcpagent

设置 dhcpagent 客户机守护进程的参数值。此文件的路径为 /etc/default/dhcpagent。有关参数的信息,请参见 /etc/default/dhcpagent 文件或 dhcpagent(1M) 手册页。

dhcpagent(1M)

DHCP inittab

定义 DHCP 选项代码的各个方面(如数据类型),并指定助记标签。有关此文件语法的更多信息,请参见 dhcp_inittab(4) 手册页。

在客户机上,dhcpinfo 会使用 /etc/dhcp/inittab 文件中的信息来为此信息的读者提供更多有意义的信息。在 DHCP 服务器系统上,DHCP 守护进程和管理工具会使用此文件来获取 DHCP 选项信息。

/etc/dhcp/inittab 文件将替换在先前的发行版中使用的 /etc/dhcp/dhcptags 文件。DHCP 选项信息提供了有关这种替换的更多信息。

dhcp_inittab(4)

DHCP 选项信息

过去,DHCP 选项信息存储在多个位置,包括服务器的 dhcptab 表、客户机的 dhcptags 文件和各种程序的内部表。在 Solaris 8 发行版以及更高发行版中,选项信息合并在 /etc/dhcp/inittab 文件中。有关此文件的详细信息,请参见 dhcp_inittab(4) 手册页。

Oracle Solaris : DHCP 客户机使用 DHCP inittab 文件代替 dhcptags 文件。客户机使用此文件可获取有关在 DHCP 包中收到的选项代码的信息。DHCP 服务器上的 in.dhcpdsnoopdhcpmgr 程序也将使用 inittab 文件。

确定站点是否受到影响

大多数使用 Oracle Solaris : DHCP 的站点不会受到转换为 /etc/dhcp/inittab 文件这一操作的影响。如果满足以下所有条件,则站点将会受到影响:

升级时,升级日志会通知您 dhcptags 文件已经修改,因此应对 DHCP inittab 文件进行更改。

dhcptags inittab 文件之间的差异

inittab 文件比 dhcptags 文件包含更多的信息。inittab 文件使用的语法也不同。

以下是 dhcptags 项的一个样例:

33 StaticRt - IPList Static_Routes

33 为在 DHCP 包中传送的数字代码。StaticRt 为选项名。IPList 表示 StaticRt 的数据类型必须为 IP 地址列表。Static_Routes 是一个描述性更强的名称。

inittab 文件由说明每个选项的单行记录组成。其格式类似于在 dhcptab 中定义符号的格式。下表说明了 inittab 文件的语法。

选项

说明

option-name

选项名。选项名在其选项类别中必须是唯一的,不可与标准选项、站点选项和供应商选项等类别中的其他选项重名。例如,不能有两个同名的站点选项,不能创建与标准选项名称相同的站点选项。

category

标识选项所属的名称空间。必须为以下名称空间之一: 标准、站点、供应商、字段或内部。

code

当选项在网络中发送时标识此选项。大多数情况下,代码唯一标识选项,与类别无关。但是,在涉及内部类别(如字段选项或内部选项)的情况下,代码可能会用于其他目的。代码可能不是全局唯一的。代码在选项类别中应是唯一的,并且不会与标准字段和站点字段中的代码重名。

type

说明与此选项关联的数据。有效类型为 IP、ASCII、Octet、Boolean、Unumber8、Unumber16、Unumber32、Unumber64、Snumber8、Snumber16、Snumber32 和 Snumber64 等。对数字来说,首字母 U 或 S 表示该数字为无符号或带符号的数字。末尾数字指明数字中的二进制位数。例如,Unumber8 即为无符号的 8 位二进制数字。类型不区分大小写。

granularity

说明组成此选项的完整值的数据单元的数量。

maximum

说明此选项允许使用的完整值的数量。0 表示一个无穷大的数字。

consumers

说明可使用此信息的程序。使用者应设置为 sdmi,其中:

s

snoop

d

in.dhcpd

m

dhcpmgr

i

dhcpinfo

以下是 inittab 项的一个样例:

StaticRt - Standard, 33, IP, 2, 0, sdmi

该项介绍了名为 StaticRt 的选项。此选项属于标准类别,选项代码为 33。由于类型为 IP、粒度为 2、最大值为无穷大 (0),因此预期的数据是一个可能为无穷大的 IP 地址对数量。此选项的使用者为 sdmisnoopin.dhcpddhcpmgrdhcpinfo

dhcptags 项转换为 inittab

如果之前向 dhcptags 文件中添加了项,则必须向新的 inittab 文件中添加对应的项,这样才能继续使用添加到站点中的选项。以下示例说明如何以 inittab 格式表示 dhcptags 项的一个样例。

假定已经为连接到网络的传真机添加了以下 dhcptags 项:

128 FaxMchn - IP Fax_Machine

代码 128 意味着此选项一定属于站点类别。选项名为 FaxMchn,数据类型为 IP

对应的 inittab 项可能是:

FaxMchn SITE, 128, IP, 1, 1, sdmi

粒度 1 和最大值 1 表示此选项应有一个 IP 地址。