折腾这个东西有一段时间了,现在总算有头绪了。
起因:st的机顶盒,os21操作系统上那个osplus的网络协议栈,支持dhcp功能。但是,有个严重的问题,如果ip地址为0.0.0.0时,从某些dhcp服务器申请ip时会崩溃;解决办法是,启动dhcp client前,将ip地址随意设置一个地址。
接下来事情就复杂了。
我发现我的linux虚拟机,原来架设好的dhcp服务器,怎么也无法给机顶盒分配ip地址了。比较过两个版本的linux,包括ubuntu 7和fedora10,还有tftpd32都不管用。
找来抓包分析工具ethereal,抓下dhcp数据包来看,发现有一个能够给机顶盒成功分配ip地址的,一直采用广播方式与机顶盒进行通讯。而我测试不行的几个服务器,收到discover消息后,都是采用单播方式来offer的。单播也就算了,问题是,单播时,接收方的ip地址一般是机顶盒启动dhcp前的那个ip地址,和服务器都不在一个网段。根本无法到达机顶盒了。
也有采用了即将分配给机顶盒使用的客户ip来作为单播目标地址的。但是这里又有问题了,因为机顶盒还没有获得这个ip地址,协议栈里面还是那个旧的ip地址,它还是无法收到offer数据包。也就无法进一步来应答了。
这样的解决办法就是,修改tftpd32源码,去掉unicast,改成广播方式。这样一来,机顶盒就可以正常获取到ip地址了。
还有个速度问题。因为局域网里好几个dhcp服务器,我就奇怪,怎么我的服务器总是比对门那个慢?后来仔细一看,才发现,对门的服务器省略了ping 待分配地址的步骤,直接就offer一个ip给客户端,难怪快了。
再看看为啥我们的tftpd32要用unicast来发offer。原来,在rfc2131中有说明,若客户端discover时,广播标志为0,relay ip地址为0,且client ip也为0,此时服务器应该使用unicast来发offer和ack给客户端。我的虚拟机中dhcp服务器一直是对的,tftpd32也是对的,是对门那台服务器有问题,该unicast的时候用广播。
原本,没这么多事,起因都是这个破协议栈,逼着我们不规范的使用dhcp client。哪有dhcp分配ip地址前,还要先给个有效ip地址的?