您的位置:首页 > 理论基础 > 计算机网络

[置顶] linux网络编程之:接受网络中的ARP数据并分析(附C语言实现)

2012-04-16 20:44 756 查看
   ARP协议是“Address Resolution Protocol”的缩写,它的作用是将IP地址转换成物理地址(就是常说的MAC地址),

   协议ARP的分组格式如下:
------------------------------------------
以太网目的地址(6个字节)
以太网源地址(6个字节)
帧类型(ARP = 0806)(2个字节)
------------------------------------------
硬件类型(Ethernet=01)(2个字节)
协议类型(IPv4=0800)(2个字节)
硬件地址长度(1个字节)
协议地址长度(1个字节)
OP操作选项(ARP request=01,ARP reply=02)(2个字节)
发送端以太网地址(6个字节)
发送端IP地址(4个字节)
目的以太网地址(6个字节)
目的IP地址(4个字节)
--------------------------------------------
   我们向目标主机发送一个ARP请求,如果目标主机处于活动状态则会返回其MAC地址,如果对方返回MAC地址,则表明对方处于活动状态,这样达到探测目的。ARP请求包内容如下:
------------------------------------------
以太网目的地址 |FFFFFFFFFFFF(广播地址)
以太网源地址 |本地MAC地址
帧类型 |0806
------------------------------------------
硬件类型 |01
协议类型 |0800
硬件地址长度 |06
协议地址长度 |04
OP操作选项 |01
发送端以太网地址|本地MAC地址
发送端IP地址 |目标主机IP地址
目的以太网地址 |000000000000
目的IP地址 |目标主机IP地址
--------------------------------------------
注意:这里以太网目的地址为FFFFFFFFFFFF,这是广播地址,以太网上所有主机都能收到这个包,在收到这个数据包后,操作系统判断目的IP地址是不是这台主机,如果不是则丢弃(不作处理),否则发送回一个ARP应答包,包的内容如下:
------------------------------------------
以太网目的地址 |探测主机的MAC地址
以太网源地址 |本地MAC地址 (这里本地指被探测主机)
帧类型 |0806
------------------------------------------
硬件类型 |01
协议类型 |0800
硬件地址长度 |06
协议地址长度 |04
OP操作选项 |02
发送端以太网地址|本地MAC地址 (这里本地指被探测主机)
发送端IP地址 |本机IP地址 (这里本地指被探测主机)
目的以太网地址 |探测主机的MAC地址
目的IP地址 |探测主机的IP地址
--------------------------------------------


源代码实现:
#include <stdio.h>
#include <stdlib.h>
#include <pcap.h>
#include <string.h>
#define ARP_REQUEST 1
typedef struct aprhdr{
u_int16_t htype;	//Hardware type
u_int16_t ptype;	//protocol type
u_char hlen;		//Hardware address length
u_char plen;		//protocol address length
u_int16_t oper;		//operation code
u_char sha[6];		//sender hardware address
u_char spa[4];		//sender ip address
u_char tha[6];		//target hardware address
u_char tpa[4];		//target ip address
}arphdr_t;

#define MAX 2048

int main(void){
int i = 0;
bpf_u_int32 net = 0, mast = 0;
struct bpf_program filter;
char errbuf[PCAP_ERRBUF_SIZE];
pcap_t *des = NULL;
struct pcap_pkthdr hk;
const unsigned char *packet = NULL;
arphdr_t *arp = NULL;

memset(errbuf, 0, PCAP_ERRBUF_SIZE);

des = pcap_open_live("eth0", MAX, 0, 512, errbuf);
pcap_lookupnet("eth0", &net, &mast, errbuf);
pcap_compile(des, &filter, "arp", 1, 0);
pcap_setfilter(des, &filter);

while(1){
packet  = pcap_next(des, &hk);
arp = (struct arphdr*)(packet + 14);
if(arp != NULL){
printf("\nRecived packet size:\t%d\n", hk.len);
printf("Hardware type:\t%s\n", (ntohs(arp->htype) == 1) ? "Ethernet" : "Unknown");
printf("Protocol type:\t%s\n", (ntohs(arp->ptype) == 0x0800) ? "IPv4" : "Unknown");
printf("Operation:\t%s\n", (ntohs(arp->oper) == ARP_REQUEST) ? "ARP Request" : "ARP Reply");

if(ntohs(arp->htype) == 1 && ntohs(arp->ptype) == 0x0800){
printf("Sender MAC:\t");
for(; i < 6; i++){
printf("%02X:", arp->sha[i]);
}
printf("\nSender IP:\t");
for(i = 0; i < 4; i++){
printf("%d.", arp->spa[i]);
}
printf("\nTarget MAC\t");
for(i = 0; i < 6; i++){
printf("%02X:", arp->tha[i]);
}
printf("\nTarget IP:\t");
for(i = 0; i < 4; i++){
printf("%d.", arp->tpa[i]);
}

}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: