void arp_request(uint8_t sn, uint16_t port, uint8_t *dest_ip)
{
uint16_t i;
uint8_t broadcast_addr[4] = {0xff, 0xff, 0xff, 0xff};
for (i = 0; i < 6; i++)
{
pARPMSG.dst_mac[i] = 0xff; // Broadcast address in an Ethernet frame
pARPMSG.tgt_mac[i] = 0x00;
if (i < 4)
{
pARPMSG.tgt_ip[i] = dest_ip[i];
}
}
getSHAR(pARPMSG.src_mac); // Fill in the source MAC address of the link layer
getSHAR(pARPMSG.sender_mac); // Fill in the MAC address of the sender in ARP
getSIPR(pARPMSG.sender_ip); // Enter the IP address of the sender in ARP
pARPMSG.msg_type = htons(ARP_TYPE); // ARP type
pARPMSG.hw_type = htons(ETHER_TYPE); // Ethernet type
pARPMSG.pro_type = htons(PRO_TYPE); // IP
pARPMSG.hw_size = HW_SIZE; // 6
pARPMSG.pro_size = PRO_SIZE; // 4
pARPMSG.opcode = htons(ARP_REQUEST); // request: 0x0001; reply: 0x0002
if (sendto(sn, (uint8_t *)&pARPMSG, sizeof(pARPMSG), broadcast_addr, port) != sizeof(pARPMSG))
{
printf("Fail to send arp request packet.\r\n");
}
else
{
if (pARPMSG.opcode == htons(ARP_REQUEST))
{
printf("Who has %d.%d.%d.%d ? Tell %d.%d.%d.%d\r\n",
pARPMSG.tgt_ip[0], pARPMSG.tgt_ip[1], pARPMSG.tgt_ip[2], pARPMSG.tgt_ip[3],
pARPMSG.sender_ip[0], pARPMSG.sender_ip[1], pARPMSG.sender_ip[2], pARPMSG.sender_ip[3]);
}
else
{
printf("Opcode has wrong value. check opcode!\r\n");
}
}
}
报文组包关键:目的 MAC 设为广播地址 FF:FF:FF:FF:FF:FF,目标 MAC 设为 0x00(待解析),Opcode 设为 ARP_REQUEST(0x0001)。htons() 用于字节序转换。通过 sendto() 以广播方式发送。
步骤4:arp_reply() 解析 ARP 响应
文件:USER/arp/arp.c。接收 ARP 报文并进行校验:如果报文为回复报文(Opcode=2)且回复的 IP 地址与请求的 IP 匹配,则将 arp_succ_flag 置 1,表示 ARP 请求成功。
void arp_reply(uint8_t sn, uint8_t *buff, uint16_t rlen)
{
uint8_t destip[4];
uint16_t destport;
uint8_t ret_arp_reply[128];
uint8_t i;
recvfrom(sn, (uint8_t *)buff, rlen, destip, &destport);
if (buff[12] == ARP_TYPE_HI && buff[13] == ARP_TYPE_LO)
{
aAPRMSG = (ARPMSG *)buff;
if ((aAPRMSG->opcode) == htons(ARP_REPLY))
{
for (i = 0; i < 4; i++)
{
if (aAPRMSG->tgt_ip[i] != pARPMSG.tgt_ip[i])
{
break;
}
arp_succ_flag = 1;
}
memset(ret_arp_reply, 0x00, 128);
sprintf((char *)ret_arp_reply, "%d.%d.%d.%d is at %.2x.%.2x.%.2x.%.2x.%.2x.%.2x\r\n",
aAPRMSG->sender_ip[0], aAPRMSG->sender_ip[1], aAPRMSG->sender_ip[2], aAPRMSG->sender_ip[3],
aAPRMSG->sender_mac[0], aAPRMSG->sender_mac[1], aAPRMSG->sender_mac[2], aAPRMSG->sender_mac[3],
aAPRMSG->sender_mac[4], aAPRMSG->sender_mac[5]);
printf("%d.%d.%d.%d is at %.2x.%.2x.%.2x.%.2x.%.2x.%.2x\r\n",
aAPRMSG->sender_ip[0], aAPRMSG->sender_ip[1], aAPRMSG->sender_ip[2], aAPRMSG->sender_ip[3],
aAPRMSG->sender_mac[0], aAPRMSG->sender_mac[1], aAPRMSG->sender_mac[2], aAPRMSG->sender_mac[3],
aAPRMSG->sender_mac[4], aAPRMSG->sender_mac[5]);
}
else if ((aAPRMSG->opcode) == htons(ARP_REQUEST))
{
printf("Who has %d.%d.%d.%d ? Tell %.2x.%.2x.%.2x.%.2x.%.2x.%.2x\r\n",
aAPRMSG->tgt_ip[0], aAPRMSG->tgt_ip[1], aAPRMSG->tgt_ip[2], aAPRMSG->tgt_ip[3],
aAPRMSG->sender_mac[0], aAPRMSG->sender_mac[1], aAPRMSG->sender_mac[2], aAPRMSG->sender_mac[3],
aAPRMSG->sender_mac[4], aAPRMSG->sender_mac[5]);
}
}
else
{
// printf("This message is not ARP reply: opcode is not 0x02!\r\n");
}
}