DHCP源码&报文分析
一. DHCP源码&报文分析
1. 服务器
1.1 DHCPDISCOVER
1.1.1 find_lease
- client ip地址为空则分配ip,否则查找报文中的requested address
- 不知道在干啥
- 查找client identifier是否已经绑定其他的主机.
Option: (61) Client identifier
Length: 7
Hardware type: Ethernet (0x01)
Client MAC address: HewlettP_62:02:4e (ec:b1:d7:62:02:4e)
通过uid —> 通过mac地址 —-> 通过host-identifier option
如果收到的是DHCPREQUEST请求并且在租约中的ip地址和requested address不同,就返回错误
/* If fixed_lease is present but does not match the requested
IP address, and this is a DHCPREQUEST, then we can't return
any other lease, so we might as well return now. */
if (packet -> packet_type == DHCPREQUEST && fixed_lease &&
(fixed_lease -> ip_addr.len != cip.len ||
memcmp (fixed_lease -> ip_addr.iabuf,
cip.iabuf, cip.len))) {
if (ours)
*ours = 1;
strcpy (dhcp_message, "requested address is incorrect");
goto out;
}
- 找到匹配的lease之后验证lease的合法性
1.1.2 没有找到已有的lease,分配新的 allocate_lease
遍历地址池,首先寻找没有使用过的地址—-> 找能用的地址 —-> 重启一个已经废弃的地址 —-> 不分配地址,当有两个状态相同的候选地址的时候选择先过期的.
将租期设置为至少两分钟
when = cur_time + 120;
if (when < lease -> ends)
when = lease -> ends;
1.1.3 ack_lease
1.2 DHCPREQUEST
1.2.1 查找REQUESTED_ADDRESS
//#define DHO_DHCP_REQUESTED_ADDRESS 50
oc = lookup_option (&dhcp_universe, packet -> options,
DHO_DHCP_REQUESTED_ADDRESS);
Option: (50) Requested IP Address
Length: 4
Requested IP Address: 192.168.2.198
如果REQUESTED_ADDRESS不可用就分配0.0.0.0
if (oc &&
evaluate_option_cache (&data, packet, (struct lease *)0,
(struct client_state *)0,
packet -> options, (struct option_state *)0,
&global_scope, oc, MDL)) {
cip.len = 4;
memcpy (cip.iabuf, data.data, 4);
data_string_forget (&data, MDL);
have_requested_addr = 1;
} else {
oc = (struct option_cache *)0;
cip.len = 4;
memcpy (cip.iabuf, &packet -> raw -> ciaddr.s_addr, 4);
}
1.2.2 查找REQUESTED_ADDRESS对应的lease
subnet = (struct subnet *)0;
lease = (struct lease *)0;
if (find_subnet (&subnet, cip, MDL))
find_lease (&lease, packet,
subnet -> shared_network, &ours, 0, ip_lease, MDL);
if (lease && lease -> client_hostname) {
if ((strlen (lease -> client_hostname) <= 64) &&
db_printable((unsigned char *)lease->client_hostname))
s = lease -> client_hostname;
else
s = "Hostname Unsuitable for Printing";
} else
s = (char *)0;
1.2.3 检查服务器标志
oc = lookup_option (&dhcp_universe, packet -> options,
DHO_DHCP_SERVER_IDENTIFIER);
memset (&data, 0, sizeof data);
if (oc &&
evaluate_option_cache (&data, packet, (struct lease *)0,
(struct client_state *)0,
packet -> options, (struct option_state *)0,
&global_scope, oc, MDL)) {
sip.len = 4;
memcpy (sip.iabuf, data.data, 4);
data_string_forget (&data, MDL);
/* piaddr() should not return more than a 15 byte string.
* safe.
*/
sprintf (smbuf, " (%s)", piaddr (sip));
have_server_identifier = 1;
} else
smbuf [0] = 0;
Option: (54) DHCP Server Identifier
Length: 4
DHCP Server Identifier: 192.168.2.1
1.3 DHCPRELEASE
释放已经获取的ip地址
1.3.1 通过CLIENT_IDENTIFIER标签查找lease
Option: (61) Client identifier
Length: 7
Hardware type: Etherne