C++构造DHCP Discovery报文并使用socket发送

本文介绍了如何使用C++构造DHCP Discovery报文,并通过socket接口发送。DHCP基于UDP和IP协议,因此可以通过socket实现。内容包括DHCP报文的结构、选项设置以及使用raw socket发送的注意事项。示例代码展示了如何设置DHCP请求的各种参数,如消息类型、客户端ID等,并使用广播地址进行发送。
摘要由CSDN通过智能技术生成
DHCP由BOOTP协议发展而来,而后者基于UDP、IP协议,这使得使用socket发送DHCP报文成为可能。本文示例构造了DHCP Discovery报文并调用socket接口发送,值得注意的是,由于DHCP要求发送者ip是0.0.0.0,所以必须使用raw socket进行发送(本文没有示例),更进一步的,用户层代码Linux、macOS系统可以使用libpcap,Windows系统可以使用Windivert、Winpcap/Npcap进行发送。
	builder<dhcp_hdr, char[64]> packet;
	auto dhcp    = packet.get<dhcp_hdr>();
	dopt opts[]  = { 
		packet.get<dhcp_opt>(3),
		packet.get<dhcp_opt>(9),
		packet.get<dhcp_opt>(6),
		packet.get<dhcp_opt>(8), // host name
		packet.get<dhcp_opt>(10),
		packet.get<dhcp_opt>(15)
	};
	auto optend  = packet.get(1);
	auto padcalc = calculator<>();
 	auto padding = packet.get( BOOTP_MIN_LEN - packet.length());

	dhcp->opcode     = DHCP_REQUEST;
	dhcp->htype      = ARPHRD_ETHER;
	dhcp->hlen       = ETHER_ADDR_LEN;
	dhcp->hops       = 0;
	dhcp->xid        = 0; // TODO
发送DHCP报文获取DHCP信息的方法如下: 1. 创建原始套接字: ```c++ int sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); if (sock < 0) { perror("socket"); exit(1); } ``` 2. 设置套接字选项: ```c++ int on = 1; if (setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) < 0) { perror("setsockopt"); exit(1); } ``` 3. 构造DHCP报文: ```c++ struct dhcp_packet { uint8_t op; /* op: Message opcode/type */ uint8_t htype; /* htype: Hardware addr type */ uint8_t hlen; /* hlen: Hardware addr length */ uint8_t hops; /* hops: Number of relay agent hops from client */ uint32_t xid; /* xid: Transaction ID */ uint16_t secs; /* secs: Seconds since client started trying to boot */ uint16_t flags; /* flags: Flag bits */ struct in_addr ciaddr; /* ciaddr: Client IP address (if already in use) */ struct in_addr yiaddr; /* yiaddr: Your (client) IP address */ struct in_addr siaddr; /* siaddr: Next server to use in bootstrap */ struct in_addr giaddr; /* giaddr: Relay agent IP address */ uint8_t chaddr[16]; /* chaddr: Client hardware address */ uint8_t sname[64]; /* sname: Server host name */ uint8_t file[128]; /* file: Boot file name */ uint8_t options[312]; /* options: Optional parameters (actual length dependent on MTU). */ } dhcp_packet; memset(&dhcp_packet, 0, sizeof(dhcp_packet)); dhcp_packet.op = BOOTREQUEST; dhcp_packet.htype = ARPHRD_ETHER; dhcp_packet.hlen = ETH_ALEN; dhcp_packet.xid = htonl(random()); memcpy(dhcp_packet.chaddr, mac_address, ETH_ALEN); ``` 在构造DHCP报文时,需要填写一些固定的字段,如op、htype、hlen、xid、chaddr等,还需要填写一些可选参数,如sname、file、options等。其中,mac_address是客户端的MAC地址。 4. 发送DHCP报文: ```c++ struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(67); addr.sin_addr.s_addr = INADDR_BROADCAST; if (sendto(sock, &dhcp_packet, sizeof(dhcp_packet), 0, (struct sockaddr*)&addr, sizeof(addr)) < 0) { perror("sendto"); exit(1); } ``` 在发送DHCP报文时,需要指定目的地地址为广播地址,即INADDR_BROADCAST。 5. 接收DHCP响应报文: ```c++ struct sockaddr_in from; socklen_t fromlen = sizeof(from); char buf[1024]; ssize_t n = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr*)&from, &fromlen); if (n < 0) { perror("recvfrom"); exit(1); } ``` 在接收DHCP响应报文时,需要设置接收缓冲区大小,一般建议设置为1024字节。收到响应报文后,可以解析报文中的各个字段,如yiaddr、siaddr、giaddr等,从而获取DHCP服务器分配的IP地址等信息。 以上就是发送DHCP报文获取DHCP信息的基本步骤。注意,发送DHCP报文需要root权限才能执行。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值