进行DHCP IPV6连接的时候,经常遇到设备获取过一次地址后,在短时间内再次重新主动进行一次DHCP IPV6连接,会连接失败,从抓包来分析就是上行服务器不响应。

通过与服务器方的沟通,了解到一点,服务器会记录请求设备的mac和DUID(是唯一标识一台DHCPv6设备(包括客户端、中继和服务器)的标识符,用于DHCPv6设备之间的相互验证),发现的设备DUID会一直变动,导致校验失败,所以服务器就不响应了。
找到原因,接下来就到了分析源码的时候了:
/*
* 2 bytes for the 'duid type' field.
* 2 bytes for the 'htype' field.
* (not stateless) 4 bytes for the 'current time'.
* enough bytes for the hardware address (note that hw_address has
* the 'htype' on byte zero).
*/
len = 4 + (ip->hw_address.hlen - 1);
if (duid_type == DUID_LLT)
len += 4;
if (!buffer_allocate(&duid->buffer, len, MDL))
log_fatal("no memory for default DUID!");
duid->data = duid->buffer->data;
duid->len = len;
/* Basic Link Local Address type of DUID. */
if (duid_type == DUID_LLT) {
putUShort(duid->buffer->data, DUID_LLT);
putUShort(duid->buffer->data + 2, ip->hw_address.hbuf[0]);
putULong(duid->buffer->data + 4, cur_time - DUID_TIME_EPOCH);
memcpy(duid->buffer->data + 8, ip->hw_address.hbuf + 1,
ip->hw_address.hlen - 1);
} else {
putUShort(duid->buffer->data, DUID_LL);
putUShort(duid->buffer->data + 2, ip->hw_address.hbuf[0]);
memcpy(duid->buffer->data + 4, ip->hw_address.hbuf + 1,
ip->hw_address.hlen - 1);
}
这里就是填充DUID字段的地方,发现DUID有两种类型,一种是LL类型,也就是Link-Layer Address,DUID填充内容为设备mac地址;另外一种就是LLT类型,也就是Link-Layer Address Plus Time,DUID填充内容为设备地址加上时间。前面报文中的设备使用的就是LLT类型DUID,加上了4字节的当前时间,所以肯定每次DHCP IPV6请求的DUID字段内容就会不同。
所以针对会校验 DUID的服务器,我们就需要将DUID类型改变为LL,即字段内容为设备mac地址,这样就保证了每次的请求DUID都相同了。
一般的开源DHCPv6代码,DUID类型都是可以通过参数可配置的,所以启动时加上使用LL类型的DUID参数即可,修改后的DUID如下图报文所示:

版权声明:本文为cc0410原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。