4.2 生成ARP首部 生成ARP首部还是紧紧围绕两个地址展开,即目标MAC地址和目标IP地址,在ARP响应过程中,源MAC地址和IP地址现在转变为了目标MAC地址和IP地址。
[cpp] view plaincopy
- void arp_generate_packet ( BYTE *rxtx_buffer, BYTE *dest_mac, BYTE *dest_ip )
- {
- unsigned char i;
- // 硬件类型 0001 10M以太网
- rxtx_buffer[ ARP_HARDWARE_TYPE_H_P ] = ARP_HARDWARE_TYPE_H_V;
- rxtx_buffer[ ARP_HARDWARE_TYPE_L_P ] = ARP_HARDWARE_TYPE_L_V;
- // 协议类型
- rxtx_buffer[ ARP_PROTOCOL_H_P ] = ARP_PROTOCOL_H_V;
- rxtx_buffer[ ARP_PROTOCOL_L_P ] = ARP_PROTOCOL_L_V;
- // 硬件地址长度
- rxtx_buffer[ ARP_HARDWARE_SIZE_P ] = ARP_HARDWARE_SIZE_V;
- // 协议地址长度
- rxtx_buffer[ ARP_PROTOCOL_SIZE_P ] = ARP_PROTOCOL_SIZE_V;
- // 目标硬件地址和源硬件地址
- for ( i=0; i<sizeof(MAC_ADDR); i++)
- {
- rxtx_buffer[ ARP_DST_MAC_P + i ] = dest_mac;
- rxtx_buffer[ ARP_SRC_MAC_P + i ] = stm32_mac.byte;
- }
- // 目标IP地址和源IP地址
- for ( i=0; i<sizeof(IP_ADDR); i++)
- {
- rxtx_buffer[ ARP_DST_IP_P + i ] = dest_ip;
- rxtx_buffer[ ARP_SRC_IP_P + i ] = stm32_ip.byte;
- }
- }
4.3 响应ARP请求 ARP响应可以体现出TCP IP报文产生的基本过程,即层层包装。先包装以太网首部,在包装ARP首部,最后通过ENC28J60发送即可。
[cpp] view plaincopy
- void arp_send_request ( BYTE *rxtx_buffer, BYTE *dest_ip )
- {
- unsigned char i;
- MAC_ADDR dest_mac;
- // generate ethernet header
- for ( i=0; i<sizeof(MAC_ADDR); i++)
- dest_mac.byte = 0xff;
- eth_generate_header ( rxtx_buffer, (WORD_BYTES){ETH_TYPE_ARP_V}, (BYTE*)&dest_mac );
- // generate arp packet
- for ( i = 0 ; i < sizeof(MAC_ADDR) ; i++)
- dest_mac.byte = 0x00;
- // set arp opcode is request
- rxtx_buffer[ ARP_OPCODE_H_P ] = ARP_OPCODE_REQUEST_H_V;
- rxtx_buffer[ ARP_OPCODE_L_P ] = ARP_OPCODE_REQUEST_L_V;
- arp_generate_packet ( rxtx_buffer, (BYTE*)&dest_mac, dest_ip );
- // send arp packet to network
- enc28j60_packet_send ( rxtx_buffer, sizeof(ETH_HEADER) + sizeof(ARP_PACKET) );
- }
5.测试 PC机通过ping命令发送一个ICMP报文,ping命令是确认网络是否连接的命令,例如发送ping 192.168.1.115,由于PC机不明确该IP地址的MAC地址,所以会先发送一个ARP请求。STM32设备可捕获该ARP请求,并通过串口输出发送ARP请求的设备的IP地址和MAC地址。此时先不用理会是否可以ping通,因为会在以后的文章中实现。
在开始之前可以通过ipconfig /all指令查询本机的IP地址和MAC地址,通过arp -a指令查询PC机中ARP缓冲表。如果有必要可使用arp –d清除缓冲表的所有内容。
图1 串口打印结果 |