[国嵌攻略][066][ARP协议实现]

以太网通讯

在计算机网络中,数据发送的过程就是把数据按照各层协议层层封装的过程。在这个过程中,最终要使用的协议通常是以太网协议(数据链路层协议)。

以太网包格式

目的MAC地址:接收者的物理地址(6字节)

源MAC地址:发送者的物理地址(6字节)

类型:高层数据使用的协议类型(2字节)

数据:高层的数据(46~1500字节)

CRC:校验码(4字节)

ARP功能

在以太网络中,每一台计算机的唯一身份表示是MAC地址(物理层的地址),两台计算机要进行通讯,必须要知道对方的MAC地址,但是用户通常只知道对方的IP地址 ,这时就可以利用ARP(地址解析协议)来向局域网中的所有计算机发送ARP请求包,收到请求包并且满足条件的计算机会恢复ARP应答包,告知其MAC地址。所以ARP协议是一种利用IP地址和MAC地址的协议。

ARP包格式

ARP包属于网络层,分为请求包和应答包,通过OP字段来区分。

以太网目的地址(6字节)

以太网源地址(6字节)

帧类型(2字节)

硬件类型(2字节)

协议类型(2字节)

硬件地址长度(1字节)

协议地址长度(1字节)

OP(2字节)

发送端以太网地址(6字节)

发送端到IP地址(4字节)

目的以太网地址(6字节)

目的IP地址(4字节)

网络字节序

在网络通讯中认为主机都是大端模式。对与多个字节的需要转换,一个字节的不用转换。

小端模式:低地址放低字节,高地址放高字节

大端模式:低地址方高字节,高地址放低字节

 

/********************************************************************
*名称:arp.c
*作者:D
*时间:2015.11.26
*功能:ARP协议
*********************************************************************/

/********************************************************************
*宏定义
*********************************************************************/
#define ETH_ARP 0x0806   //ARP
#define ETH_RARP 0x0805  //RARP
#define ARP_ETH 0x0001   //ETHERNET
#define ARP_IP 0x0800    //IP
#define ARP_REQ 0x0001   //Request
#define ARP_REP 0x0002   //Reply

#define HTONS(n) ( (((n)&0xFF00)>>8) | (((n)&0x00FF)<<8) )   //把unsigned short类型从主机序转换到网络序

#define MAC_LENGTH 6       //MAC地址长度
#define IP_LENGTH 4        //IP地址长度
#define PACKET_LENGTH 42   //ARP报文包长度,以太网帧最小长度为64字节,发送时会自动填充为64字节

/********************************************************************
*类型定义
*********************************************************************/
//以太网帧首部
typedef struct ehhdr
{
	unsigned char eh_dst[6];   //destination ethernet addrress
	unsigned char eh_src[6];   //source ethernet addresss
	unsigned short eh_type;    //ethernet packet type
}EHHDR, *PEHHDR;

//以太网帧数据
typedef struct arphdr
{
	unsigned short arp_hrd;   //format of hardware address
	unsigned short arp_pro;   //format of protocol address
	unsigned char arp_hln;    //length of hardware address
	unsigned char arp_pln;    //length of protocol address
	unsigned short arp_op;    //ARP/RARP operation

	unsigned char arp_sha[6];   //sender hardware address
	unsigned char arp_spa[4];   //sender protocol address
	unsigned char arp_tha[6];   //target hardware address
	unsigned char arp_tpa[4];   //target protocol address
}ARPHDR, *PARPHDR;

//ARP报文包
typedef struct arpPacket
{
	EHHDR ehhdr;
	ARPHDR arphdr;
}ARPPACKET, *PARPPACKET;

/********************************************************************
*全局变量声明
*********************************************************************/
unsigned char eh_src[6] = {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC};   //MAC发送地址
unsigned char eh_dst[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};   //MAC目的地址
	
unsigned char ip_src[4] = {192, 168, 1, 150};   //IP发送地址
unsigned char ip_dst[4] = {192, 168, 1, 100};   //IP目的地址

/********************************************************************
*函数原型声明
*********************************************************************/
void requst_arp();
void create_packet(ARPPACKET *arp_packet);

void process_arp(ARPPACKET *arp_packet);

/********************************************************************
*名称:requst_arp
*参数:
*	none
*返回:
*	none
*功能:ARP请求
*********************************************************************/
void requst_arp(){
	ARPPACKET arp_packet;   //ARP报文包

	//创建ARP报文包
	create_packet(&arp_packet);
	
	//发送ARP报文包
	tx_dm9000(&arp_packet, PACKET_LENGTH);
}

/********************************************************************
*名称:create_packet
*参数:
*	arp_packet   报文包
*返回:
*	none
*功能:创建ARP报文包
*********************************************************************/
void create_packet(ARPPACKET *arp_packet){
	//填充以太网帧首部
	memcpy(arp_packet->ehhdr.eh_dst, eh_dst, MAC_LENGTH);   //MAC目的地址
	memcpy(arp_packet->ehhdr.eh_src, eh_src, MAC_LENGTH);   //MAC发送地址
	arp_packet->ehhdr.eh_type = HTONS(ETH_ARP);             //帧类型
	
	//填充以太网帧数据
	arp_packet->arphdr.arp_hrd = HTONS(ARP_ETH);   //硬件类型
	arp_packet->arphdr.arp_pro = HTONS(ARP_IP);    //协议类型
	arp_packet->arphdr.arp_hln = MAC_LENGTH;       //硬件地址长度
	arp_packet->arphdr.arp_pln = IP_LENGTH;        //协议地址长度
	arp_packet->arphdr.arp_op  = HTONS(ARP_REQ);   //操作类型
	
	memcpy(arp_packet->arphdr.arp_sha, eh_src, MAC_LENGTH);   //MAC发送地址
	memcpy(arp_packet->arphdr.arp_spa, ip_src, IP_LENGTH);    //IP发送地址
	memcpy(arp_packet->arphdr.arp_tha, eh_dst, MAC_LENGTH);   //MAC目的地址
	memcpy(arp_packet->arphdr.arp_tpa, ip_dst, IP_LENGTH);    //IP目的地址
}

/********************************************************************
*名称:process_arp
*参数:
*	arp_packet   报文包
*返回:
*	none
*功能:处理ARP报文包
*********************************************************************/
void process_arp(ARPPACKET *arp_packet){
	int i;
	unsigned char eh_addr[6];   //物理地址
	unsigned char ip_addr[4];   //协议地址

	//提取发送地址
	memcpy(eh_addr, arp_packet->arphdr.arp_sha, MAC_LENGTH);
	memcpy(ip_addr, arp_packet->arphdr.arp_spa, IP_LENGTH);
	
	//打印发送地址
	printf("IP is ");
	for(i = 0; i < IP_LENGTH; i++){
		printf("%3d.", ip_addr[i]);
	}
	printf("!");
	
	printf("MAC is ");
	for(i = 0; i < MAC_LENGTH; i++){
		printf("%02X:", eh_addr[i]);
	}
	printf("!
");
}
原文地址:https://www.cnblogs.com/d442130165/p/5001134.html