第一部分 DHCP工作过程
DHCP的工作过程主要分为以下六个阶段:
发现阶段,即DHCP客户端寻找DHCP服务器的阶段。DHCP客户端首先以广播方式发送DHCP DISCOVER发现信息来寻找DHCP服务器(因为DHCP服务器的IP地址对于客户端来说是未知的),即客户端向地址255.255.255.255发送特定的广播信息。请求信息主要包含客户端的网卡MAC地址还有客户端的计算机名称。网络上每一台安装了TCP/IP协议的主机都会接收到这种广播信息,但只有DHCP服务器才会做出响应。
提供阶段,即DHCP服务器提供IP地址的阶段。在网络中接收到DHCP DISCOVER发现信息的DHCP服务器都会做出响应,它从尚未出租的IP地址中挑选一个分配给DHCP客户端,向DHCP客户端发送一个包含出租的IP地址和其他设置的DHCP OFFER提供信息。
选择阶段,即DHCP客户端选择某台DHCP服务器提供的IP地址的阶段。如果网络中有多台DHCP服务器向DHCP客户端发来的DHCP OFFER提供信息,则DHCP客户端只接受第一个收到的DHCP OFFER提供信息。在客户端收到DHCP OFFER提供信息后,会以广播方式回答一个DHCP REQUEST请求信息,所有的DHCP服务器都会收到这个信息,该信息中包含它所选定的DHCP服务器和服务器提供的IP地址。之所以要以广播方式回答,是为了通知所有的DHCP服务器,他将选择某台DHCP服务器所提供的IP地址,其他没有被选择的DHCP服务器则会收回发出的IP地址。
确认阶段,即DHCP服务器确认所提供的IP地址的阶段。当DHCP服务器收到DHCP客户端回答的DHCP REQUEST请求信息之后,它便向DHCP客户端发送一个包含它所提供的IP地址和其他设置的DHCP ACK确认信息,告诉DHCP客户端可以使用它所提供的IP地址。至此DHCP客户端可以使用DHCP服务器所提供的IP地址与网卡绑定。
重新登录阶段。以后DHCP客户端每次重新登录网络时,就不需要再发送DHCP DISCOVER发现信息了,而是直接发送包含前一次所分配的IP地址的DHCP REQUEST请求信息。当DHCP服务器收到这一信息后,它会尝试让DHCP客户端继续使用原来的IP地址,并回答一个DHCP ACK确认信息。如果此IP地址已无法再分配给原来的DHCP客户端使用时(比如此IP地址已分配给其它DHCP客户端使用),则DHCP服务器给DHCP客户端回答一个DHCP NACK否认信息。当原来的DHCP客户端收到此DHCP NACK否认信息后,它就必须重新发送DHCP DISCOVER发现信息来请求新的IP地址。 更新租约阶段。DHCP服务器所提供的IP地址一般都是有期限的,我们把这个期限称为租期,租期的长短通过DHCP服务器来设置。设置这个期限是为了让那些过了租期又不活动的IP能空出来,由DHCP服务器重新分配给DHCP客户端,这样就会有效减少IP地址的浪费现象。期满后DHCP服务器便会收回出租的IP地址。如果DHCP客户端要延长其IP租约,则必须更新其IP租约。DHCP客户端启动时和IP租约期限过一半时,DHCP客户端都会自动向DHCP服务器发送更新其IP租约的信息。
如果DHCP客户端一直开启,客户端会在租约过去50%的时候向原DHCP服务器提出DHCP REQUEST请求信息,信息中包含一个客户端正使用的IP地址,并请求服务机延长对此地址的租用。如果原服务器同意会发出DHCP ACK确认信息。这样,续租成功,客户端获得新的租约。如果这个请求信息没有得到回复,因为租约尚未结束,DHCP客户端会继续使用原来的IP,并且每隔大约2分钟向原DHCP服务器再次发送DHCP REQUEST请求信息申请续租。如果到了租约期限的87.5%,DHCP客户端依然没有收到原DHCP服务器的DHCP ACK确认信息,则客户端转为重新绑定状态。在重新绑定状态下,DHCP客户端会以广播的方式向网络中的所有服务器发送DHCP REQUEST请求信息,如果有DHCP服务器响应,并发回DHCP ACK确认信息则DHCP客户端从新的DHCP服务器获得新的IP地址还有新的租约。如果直到租约结束也没有收到任何DHCP服务器的DHCP ACK确认信息,则DHCP客户端会停用租来的IP地址,然后返回初始化状态。
第二部分 DHCP 报文
DHCP报文是承载于UDP上的高层协议报文,采用67(DHCP服务器)和68(DHCP客户端)两个端口号。DHCP报文的格式如下图所示。
图1 DHCP报文格式
< 所有DHCP提供的配置信息都在options字段中,这才是精华部分 >
报文中各字段的描述如下:
op,报文类型,1表示请求报文,2表示回应报文。
htype,硬件地址类型,1表示10Mb/s的以太网的硬件地址。
hlen,硬件地址长度,以太网中该值为6。
hops,跳数。客户端设置为0,也能被一个代理服务器设置。
xid,事务ID,由客户端选择的一个随机数,被服务器和客户端用来在它们之间交流请求和响应,客户端用它对请求和应答进行匹配。该ID由客户端设置并由服务器返回,为32位整数。
secs,由客户端填充,表示从客户端开始获得IP地址或IP地址续借后所使用了的秒数。
flags,标志字段。这个16比特的字段,目前只有最左边的一个比特有用,该位为0,表示单播,为1表示广播。
ciaddr,客户端的IP地址。只有客户端是Bound、Renew、Rebinding状态,并且能响应ARP请求时,才能被填充。
yiaddr,"你自己的"或客户端的IP地址。
siaddr,表明DHCP协议流程的下一个阶段要使用的服务器的IP地址。
giaddr,DHCP中继器的IP地址。//注意:不是地址池中定义的网关
chaddr,客户端硬件地址。客户端必须设置它的"chaddr"字段。UDP数据包中的以太网帧首部也有该字段,但通常通过查看UDP数据包来确定以太网帧首部中的该字段获取该值比较困难或者说不可能,而在UDP协议承载的DHCP报文中设置该字段,用户进程就可以很容易地获取该值。
sname,可选的服务器主机名,该字段是空结尾的字符串,由服务器填写。
file,启动文件名,是一个空结尾的字符串。DHCP Discover报文中是"generic"名字或空字符,DHCP Offer报文中提供有效的目录路径全名。
options,可选参数域,格式为"代码+长度+数据"。
DHCP Options
Option id | Length(字节) | 描述 |
1 | 4 | Subnet Mask |
3 | n*4 | Router(网关) |
6 | n*4 | DNS Server |
7 | n*4 | Log Server |
26 | 2 | Interface MTU |
33 | n*8 | Static route |
35 | 4 | ARP cache timeout |
42 | n*4 | NTP servers |
51 | 4 | IP address lease time |
53 | 1 | Message type 1-DHCPDISCOVER 2-DHCPOFFER 3-DHCPREQUEST 4-DHCPDECLINE 5-DHCPACK 6-DHCPNAK 7-DHCPRELEASE 8-DHCPINFORM |
54 | 4 | DHCP Server Identifier |
60 | n | 华为自定义:可配置该终端设备在发起DHCP请求时,通过Option 60携带域信息。ME60收到DHCP报文时,可根据Option 60中携带的域信息来分配IP地址。 |
82 | n | 华为自定义:ME60作为DHCP Relay,在中继用户DHCP报文时,可在Option 82中填写用户的物理位置信息,通知DHCP服务器按物理位置信息对为用户分配IP地址。 |
DHCP报文类型
DHCP共有八种报文,分别为DHCP Discover、DHCP Offer、DHCP Request、DHCP ACK、DHCP NAK、DHCP Release、DHCP Decline、DHCP Inform。各报文类型功能如表1所述。
DHCP报文类型 | 描述 |
DHCP Discover | DHCP客户端请求地址时,并不知道DHCP服务器的位置,因此DHCP客户端会在本地网络内以广播方式发送请求报文,这个报文成为Discover报文,目的是发现网络中的DHCP服务器,所有收到Discover报文的DHCP服务器都会发送回应报文,DHCP客户端据此可以知道网络中存在的DHCP服务器的位置。 |
DHCP Offer | DHCP服务器收到Discover报文后,就会在所配置的地址池中查找一个合适的IP地址,加上相应的租约期限和其他配置信息(如网关、DNS服务器等),构造一个Offer报文,发送给用户,告知用户本服务器可以为其提供IP地址。< 只是告诉client可以提供,是预分配,还需要client通过ARP检测该IP是否重复> |
DHCP Request | DHCP客户端可能会收到很多Offer,所以必须在这些回应中选择一个。Client通常选择第一个回应Offer报文的服务器作为自己的目标服务器,并回应一个广播Request报文,通告选择的服务器。DHCP客户端成功获取IP地址后,在地址使用租期过去1/2时,会向DHCP服务器发送单播Request报文续延租期,如果没有收到DHCP ACK报文,在租期过去3/4时,发送广播Request报文续延租期。 |
DHCP ACK | DHCP服务器收到Request报文后,根据Request报文中携带的用户MAC来查找有没有相应的租约记录,如果有则发送ACK报文作为回应,通知用户可以使用分配的IP地址。 |
DHCP NAK | 如果DHCP服务器收到Request报文后,没有发现有相应的租约记录或者由于某些原因无法正常分配IP地址,则发送NAK报文作为回应,通知用户无法分配合适的IP地址。 |
DHCP Release | 当用户不再需要使用分配IP地址时,就会主动向DHCP服务器发送Release报文,告知服务器用户不再需要分配IP地址,DHCP服务器会释放被绑定的租约。 |
DHCP Decline | DHCP客户端收到DHCP服务器回应的ACK报文后,通过地址冲突检测发现服务器分配的地址冲突或者由于其他原因导致不能使用,则发送Decline报文,通知服务器所分配的IP地址不可用。 |
DHCP Inform | DHCP客户端如果需要从DHCP服务器端获取更为详细的配置信息,则发送Inform报文向服务器进行请求,服务器收到该报文后,将根据租约进行查找,找到相应的配置信息后,发送ACK报文回应DHCP客户端。< 极少用到> |
第三部分 dhcpcd分析
dhcpcd一共有7种状态:
REBOOTING , INIT , SELECTING , REQUESTING , BOUND , REBINDING , RENEWING
重新启动DHCPCD时的动作,这时直接发生request申请上次获取到的IP。
重新启动DHCPCD时的动作,这时直接发生request申请上次获取到的IP。
用户初始化动作,发送discover,转换到SELECTING状态。
接收服务器的ACK报文,对下发的IP 进行验证,然后转换到BOUND状态。
将获取到的IP设置成网卡的地址,进入绑定状态,等待超时。
当租约定时器超时的时候,发送request,进行续约。
当80%租期的时候,服务器还没有回应ACK,则进行广播request,若在原租期到期时
收到了ACK 则进入BOUND状态,否则转换到INIT状态。
第四部分 Android dhcpcd守护进程
最近在调android ethernet功能,android本身不带 ethernet 功能,需要打patch。这个patch可以在setting里出来 ethernet configuration 选项。即添加了用户配置IP的功能。
我打上patch之后,点击选上DHCP功能,结果路由器一直不能自动分配IP。
经检测,命令行里运行 netcfg eth0 up dhcp 时,ethernet能被正常启动,DHCP能分配到IP。
但是Setting里选上时,dhcp却不能正常分配IP。 这很费解,我先后查看了,
/system/core/libnetutils/*
/externel/dhcpcd/*
发现都没什么问题。
在Setting中点击turn on ethernet选项时,从log看到能调到
1. E/EthernetStateTracker( 185): DhcpHandler: DHCP request failed: Timed out waiting for dhcpcd to start
2. D/EthernetStateTracker( 185): DhcpHandler: DHCP request started
说明patch是好的能正常工作,能正常掉用dhcp,只是DHCP运行不成功。
然后我查了 getprop: 显示 init.svc.dhcpcd_eth0 = stop
正常应该是running的,这样DHCP 才能运行成功。
最后调试了两天,才搞明白,原来是 init.rc 中 dhcpcd_eth0 守护进程的问题:
改成:
1. on property:init.svc.dhcpcd_eth0=stopped
2. start dhcpcd_eth0
3.
4. service dhcpcd_eth0 /system/bin/dhcpcd -ABKL -f /system/etc/dhcpcd/dhcpcd.conf -d eth0
5. class main
6. disabled
7. oneshot
这样就可以了。