【问题标题】:DHCP Multiple IP address requestDHCP 多 IP 地址请求
【发布时间】:2012-06-13 15:17:38
【问题描述】:

我正在尝试使用 C++ 代码从我的一端模仿 DHCP 客户端。我的目标是从 DHCP 服务器获取一些免费/未使用的 IP 以将其分配给不同的设备 - 类似于 DHCP 中继,但在技术上并不相同。我的CLIENT 在嵌入式 linux 平台上运行,并通过我们的内部网络与 DHCP 服务器通信。

根据 DHCP 协议,有一个正式的过程(DISCOVEROFFERREQUESTACK/NAKRELEASE)与 DHCP 服务器通信。根据 RFC(2131),当我做了一个DISCOVER,我收到了OFFER,在 YIAddr 字段中有一个未使用的 IP 地址。我使用 RFC 2132 中提到的选项 50 在我的 REQUEST 消息中进一步使用此 IP 地址。

我的主路由器 make-Edgewater(它也是 DHCP 服务器)在发送 DISCOVER 消息时,会在 YIAddr 字段中发回带有未使用 IP 地址的 OFFER 消息(我在我的随后REQUEST消息),这是我的要求。我对其他几个路由器(NetGear、Dlink、Broadcom)做了同样的实验,发现OFFER 消息向我发送了与请求未使用 IP 的CLIENT 相同的 IP 地址。我很想知道为什么会这样。据我了解,我正在按照 RFC2131/RFC2131/RFC4361 中提到的步骤来创建我的 DHCP 数据包格式。

是否有其他 DHCP 服务器/路由器期望提供未使用的 IP 的特定格式或特定选项?如 RFC4361 中所述,我在选项字段中使用了唯一的客户端标识符。

这是我创建 dhcp 数据包部分的快照。

    request_packet.m_OperationCode  =   0x01;
request_packet.m_HwareType  =   0x01;
request_packet.m_HwareLen   =   0x06;
request_packet.m_Hops       =   0x01;
request_packet.m_XID        =   htonl(XID[m_numberOfIPs]);
request_packet.m_Secs       =   htons(0x10);
request_packet.m_flags      =   htons(0x8000);
request_packet.m_CIAddr     =   0x000000; //Client IP
request_packet.m_YIAddr     =   0x000000; //Your IP
request_packet.m_SIAddr     =   0x000000; //Server IP
request_packet.m_GIAddr         =   0x000000;
request_packet.m_CHAddr[0]  =   MACADDRESS[m_numberOfIPs][0];
request_packet.m_CHAddr[1]  =   MACADDRESS[m_numberOfIPs][1];//[1];
request_packet.m_CHAddr[2]  =   MACADDRESS[m_numberOfIPs][2];//[2];
request_packet.m_CHAddr[3]  =   MACADDRESS[m_numberOfIPs][3];//[3];
request_packet.m_CHAddr[4]  =   MACADDRESS[m_numberOfIPs][4];//[4];
request_packet.m_CHAddr[5]  =   MACADDRESS[m_numberOfIPs][5];//[5];
memset(request_packet.m_CHAddr+6, 0, 10);
memset(request_packet.m_SName, 0, 64);      
memset(request_packet.m_File, 0, 128);  
request_packet.m_pOptions[0]    =   99; //Start of magic cookie
request_packet.m_pOptions[1]    =   130;            
request_packet.m_pOptions[2]    =   83;
request_packet.m_pOptions[3]    =   99; //end of magic cookie

选项字段

发现消息

CID 和 DUID 是用于创建唯一客户端标识符的随机唯一数字

 request_packet.m_pOptions[4]   =   53; //DHCP MESSAGE TYPE OPTION CODE
 request_packet.m_pOptions[5]   =   1;  //OPTION DATA LEN
 request_packet.m_pOptions[6]   =   1;  //DHCP DISCOVER

 request_packet.m_pOptions[7]   =   55; //Parameter Request List
 request_packet.m_pOptions[8]   =   7; //Length
 request_packet.m_pOptions[9]   =   1; //Subnet Mask
 request_packet.m_pOptions[10]  =   3; //Router
 request_packet.m_pOptions[11]  =   6; //Domain Name Server
 request_packet.m_pOptions[12]  =   12; // Host Name
 request_packet.m_pOptions[13]  =   15; //Domain Name
 request_packet.m_pOptions[14]  =   28; //Broadcast Address
 request_packet.m_pOptions[15]  =   42; //NTP servers

 request_packet.m_pOptions[16]  =   51; //IP Address Lease Time
 request_packet.m_pOptions[17]  =   4;  
 request_packet.m_pOptions[18]  =   0x00;
 request_packet.m_pOptions[19]  =   0x00;
 request_packet.m_pOptions[20]  =   0xFF;
 request_packet.m_pOptions[21]  =   0xFF;

 request_packet.m_pOptions[22]  =   61;//Client Identifier code
 request_packet.m_pOptions[23]  =   15;//Length
 request_packet.m_pOptions[24]  =   255;//IAID Type
 printf("The CID generated inside REQUEST is %x\n", CID[m_numberOfIPs]);
 request_packet.m_pOptions[25]  =   CID[m_numberOfIPs][0];
 request_packet.m_pOptions[26]  =   CID[m_numberOfIPs][1];
 request_packet.m_pOptions[27]  =   CID[m_numberOfIPs][2];
 request_packet.m_pOptions[28]  =   CID[m_numberOfIPs][3];
 request_packet.m_pOptions[29]  =   0x00;//DUID Type
 request_packet.m_pOptions[30]  =   0x03;//DUID Type
 request_packet.m_pOptions[31]  =   0x00;//HW Type code - Ethernet
 request_packet.m_pOptions[32]  =   0x01;//HW Type code - Ethernet
 request_packet.m_pOptions[33]  =   DUID[m_numberOfIPs][0];
 request_packet.m_pOptions[34]  =   DUID[m_numberOfIPs][1];
 request_packet.m_pOptions[35]  =   DUID[m_numberOfIPs][2];
 request_packet.m_pOptions[36]  =   DUID[m_numberOfIPs][3];
 request_packet.m_pOptions[37]  =   DUID[m_numberOfIPs][4];
 request_packet.m_pOptions[38]  =   DUID[m_numberOfIPs][5];


 request_packet.m_pOptions[39]  =   (0xff);  // End option

请求消息

request_packet.m_pOptions[4]    =   53; //DHCP MESSAGE TYPE OPTION CODE
request_packet.m_pOptions[5]    =   1;  //OPTION DATA LEN
request_packet.m_pOptions[6]    =   3;  //DHCP REQUEST

request_packet.m_pOptions[7]    =   50; //DHCP REQUESTION OPTION
request_packet.m_pOptions[8]    =   4;  //OPTION DATA LEN
request_packet.m_pOptions[9]    =   (m_YourIP & 0xff000000)>>24;  //first byte
request_packet.m_pOptions[10]   =   (m_YourIP & 0xff0000)>>16;  //second byte
request_packet.m_pOptions[11]   =   (m_YourIP & 0xff00)>>8;  //third byte
request_packet.m_pOptions[12]   =   (m_YourIP & 0xff);  //fourth byte
/*- Added by JA. Refer 3.1.3 Section of RFC2131.txt - Server identifier option*/
 request_packet.m_pOptions[13]  =   54;
 request_packet.m_pOptions[14]   =  4;
 request_packet.m_pOptions[15]  =   (m_ServerIP & 0xff000000) >> 24; //first byte
 request_packet.m_pOptions[16]  =   (m_ServerIP & 0xff0000)>>16;  //second byte
 request_packet.m_pOptions[17]  =   (m_ServerIP & 0xff00)>>8;  //third byte
 request_packet.m_pOptions[18]  =   (m_ServerIP & 0xff);  //fourth byte

 request_packet.m_pOptions[19]  =   55; //Parameter Request List
 request_packet.m_pOptions[20]  =   7; //Length
 request_packet.m_pOptions[21]  =   1; //Subnet Mask
 request_packet.m_pOptions[22]  =   3; //Router
 request_packet.m_pOptions[23]  =   6; //Domain Name Server
 request_packet.m_pOptions[24]  =   12; // Host Name
 request_packet.m_pOptions[25]  =   15; //Domain Name
 request_packet.m_pOptions[26]  =   28; //Broadcast Address
 request_packet.m_pOptions[27]  =   42; //NTP servers

     request_packet.m_pOptions[28]  =   51; //IP Address Lease Time
     request_packet.m_pOptions[29]  =   4;  
     request_packet.m_pOptions[30]  =   0x00;
     request_packet.m_pOptions[31]  =   0x00;
     request_packet.m_pOptions[32]  =   0xFF;
     request_packet.m_pOptions[33]  =   0xFF;

     /*- Added by JA. Refer 6.1 Section of RFC4361.txt - Client identifier option*/
     request_packet.m_pOptions[34]  =   61;//Client Identifier code
     request_packet.m_pOptions[35]  =   15;//Length
     request_packet.m_pOptions[36]  =   255;//IAID Type
     printf("The CID generated inside REQUEST is %x\n", CID[m_numberOfIPs]);
     request_packet.m_pOptions[37]  =   CID[m_numberOfIPs][0];
     request_packet.m_pOptions[38]  =   CID[m_numberOfIPs][1];
     request_packet.m_pOptions[39]  =   CID[m_numberOfIPs][2];
     request_packet.m_pOptions[40]  =   CID[m_numberOfIPs][3];
     request_packet.m_pOptions[41]  =   0x00;//DUID Type
     request_packet.m_pOptions[42]  =   0x03;//DUID Type
     request_packet.m_pOptions[43]  =   0x00;//HW Type code - Ethernet
     request_packet.m_pOptions[44]  =   0x01;//HW Type code - Ethernet
     request_packet.m_pOptions[45]  =   DUID[m_numberOfIPs][0];
     request_packet.m_pOptions[46]  =   DUID[m_numberOfIPs][1];
     request_packet.m_pOptions[47]  =   DUID[m_numberOfIPs][2];
     request_packet.m_pOptions[48]  =   DUID[m_numberOfIPs][3];
     request_packet.m_pOptions[49]  =   DUID[m_numberOfIPs][4];
     request_packet.m_pOptions[50]  =   DUID[m_numberOfIPs][5];
     request_packet.m_pOptions[51]  =   (0xff);  // End option

【问题讨论】:

  • 我调用这个函数(它创建数据包)'x'次,具体取决于我需要的空闲 IP 的数量。现在,在 m_ChAddr 字段中为每个 DORA(Discover-Offer-Request-ACK) 提供一个唯一的 MAC 地址字段时,我在 m_YIAddr 字段中获得了一个未使用的 IP 地址,这正是我需要的。通过阅读 rfc,我认为通过保持 MAC 地址相同并为每个 DORA 提供唯一的客户端标识符,它应该可以工作(并且它正在与我们的主路由器 - Edgewater 一起工作)。某些路由器是否希望在每个 DORA 中提供唯一的 MAC 地址来释放未使用的 IP?

标签: networking udp router dhcp


【解决方案1】:

使用路由器作为 DHCP 中继和服务器,它将为您分配基于其配置的唯一 IP 的 DHCP 子网,例如 10.1.2.0/24 是路由器上为 DHCP 请求定义的池,它将根据您的 MAC 为您分配第一个未分配的 IP仅此分配是随机的,您不能在路由器上保留 mac。在 DORA 之后,它会触发该 MAC-IP 的租用计时器。

如果您使用 DHCP 服务器 Microsoft/Unix,它们具有扩展功能,可以为特定的 mac 永久保留 IP。

【讨论】:

  • 感谢您的回复。我了解 IP 是根据 MA​​C 地址分配的。我正在尝试确定协议/RFC 是否支持 DHCP 客户端以使用相同的 MAC 地址(DHCP 客户端的 MAC 地址)获得不同的唯一未分配 IP。
  • 路由器不会为特定的mac永久保留ip;每次 dhcp 客户端查询时,都可以通过 dhcp 中继获得唯一的 ip。
  • 我的 dhcp 客户端和 dhcp 服务器在同一个子网中。我不想为 mac 永久保留 IP。我希望 dhcp 客户端根据它的 MAC 地址获取一些 IP 地址(有点像中继代理,但不完全),并将这些 IP 地址传递给各种设备(这些设备没有 MAC 地址)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-31
  • 2013-07-01
  • 1970-01-01
  • 2015-06-21
  • 2018-07-04
  • 1970-01-01
相关资源
最近更新 更多