#include<stdlib.h>
#include<stdio.h>
#include<pcap.h>
struct ethernet_head
{
unsigned char dest_mac[6]; //目标主机MAC 地址
unsigned char source_mac[6]; //源端MAC 地址
unsigned short eh_type; //以太网类型
};
struct arp_head
{
unsigned short hardware_type; //硬件类型:以太网接口类型为1
unsigned short protocol_type; //协议类型:IP 协议类型为0X0800
unsigned char add_len; //硬件地址长度:MAC 地址长度为6B
unsigned char pro_len; //协议地址长度:IP 地址长度为4B
unsigned short option; //操作:ARP 请求为1,ARP 应答为2
unsigned char sour_addr[6]; //源MAC 地址:发送方的MAC 地址
unsigned long sour_ip; //源IP 地址:发送方的IP 地址
unsigned char dest_addr[6]; //目的MAC 地址:ARP 请求中该字段没有意义;ARP响应中为接收方的MAC 地址
unsigned long dest_ip; //目的IP 地址:ARP 请求中为请求解析的IP 地址;ARP响应中为接收方的IP 地址
unsigned char padding[18];
};
struct arp_packet //最终arp 包结构
{
ethernet_head eth; //以太网头部
arp_head arp; //arp 数据包头部
};
int main()
{
unsigned char* GetSelfMac(char* pDevName, unsigned long chLocalIP);
int i=0;
pcap_if_t *alldevs; //指向设备链表首部的指针
pcap_if_t *d;
pcap_addr_t *a;
unsigned char* mac;
unsigned long chLocalIp;
char errbuf[PCAP_ERRBUF_SIZE]; //错误信息缓冲区
//获得本机的设备列表
if(pcap_findalldevs_ex(PCAP_SRC_IF_STRING,NULL,&alldevs,errbuf) == -1)
{
printf("PCAP出错/n");
}
//显示接口列表
for(d= alldevs; d != NULL; d= d->next)
{
printf("%d. %s", ++i, d->name);
if (d->description)
printf(" (%s)/n", d->description);
else
printf(" (No description available)/n");
for(a=d->addresses; a!=NULL; a=a->next)
{
if (a->addr->sa_family==AF_INET) //判断该地址是否IP地址
{
chLocalIp=((struct sockaddr_in *)a->addr)->sin_addr.s_addr;
printf("%ld/n",chLocalIp); //利用a->addr获取IP地址
}
}
mac=GetSelfMac(d->name,chLocalIp);
printf("%s",mac);
}
return 0;
}
unsigned char* GetSelfMac(char* pDevName, unsigned long chLocalIP)//设备名和本机IP作为参数
{
unsigned char* BuildArpRequestPacket(unsigned char* source_mac_add, unsigned long source_ip_add, unsigned long dest_ip_add);
//获得自己的MAC
pcap_t* pAdaptHandle;//打开网卡适配器时用
char errbuf[PCAP_ERRBUF_SIZE + 1];
if((pAdaptHandle = pcap_open_live(pDevName, 60, 1, 100, errbuf)) == NULL)//arp请求包60字节
{
//MessageBox(NULL, "无法打开适配器,可能与之不兼容!", "Note", MB_OK);
return NULL;
}
struct pcap_pkthdr *header;
const u_char *pkt_data;
int res;
int GetMacSignal=1;
unsigned short arp_op; //
static unsigned char arp_sha[6];
unsigned long arp_spa = 0;
unsigned long arp_tpa = 0;
unsigned char source_mac[6] = {0,0,0,0,0,0};
unsigned char* arp_packet_for_self;
arp_packet_for_self = BuildArpRequestPacket(source_mac,chLocalIP,chLocalIP);
while(GetMacSignal)
{
pcap_sendpacket(pAdaptHandle, arp_packet_for_self, 60);
Sleep(10);
res = pcap_next_ex(pAdaptHandle, &header, &pkt_data);
if(res == 0)
{
continue;
}
memcpy(&arp_op, pkt_data + 20, 2); //arp类型
memcpy(arp_sha, pkt_data + 22, 6); //源mac
memcpy(&arp_spa, pkt_data + 28, 4); //源IP
memcpy(&arp_tpa, pkt_data + 38, 4); //目的IP
if(arp_op == 2 && arp_spa == chLocalIP && arp_tpa == chLocalIP)
{ GetMacSignal = 0;
pcap_close(pAdaptHandle);
return arp_sha;//返回源mac,就是本地的mac
}
Sleep(100); //若不成功再等100ms再发,让网卡歇歇:) 20061025
}
pcap_close(pAdaptHandle);
return arp_sha;
}
unsigned char* BuildArpRequestPacket(unsigned char* source_mac_add, unsigned long source_ip_add, unsigned long dest_ip_add)
{
int i;
//这是arp请求包,目的mac不用填,重点是arpPackStru.arp.option、源mac、源IP和目的IP,
//这三项通过参数传递进来构造请求包
arp_packet arpPackStru;
for(i=0;i<6;i++) arpPackStru.eth.dest_mac[i]=0xff;
//for(i=0;i<6;i++) arpPackStru.eth.source_mac[i]= ; //
arpPackStru.eth.eh_type=htons(0x0806);
arpPackStru.arp.hardware_type=htons(0x0001);
arpPackStru.arp.protocol_type=htons(0x0800);
arpPackStru.arp.add_len=0x06;
arpPackStru.arp.pro_len=0x04;
arpPackStru.arp.option=0x01; //请求
memcpy(arpPackStru.arp.sour_addr,source_mac_add,6); //自己的mac
arpPackStru.arp.sour_ip=source_ip_add; //需要用到查询自己IP的结构
arpPackStru.arp.dest_ip=dest_ip_add; //目的IP
for(i=0;i<18;i++) arpPackStru.arp.padding[i]=0x00;
return (unsigned char *)&arpPackStru;
}