ARP协议获得局域网内活动主机物理地3

/***************************************************************
* 第三次作业 ARP协议获得局域网内活动主机物理地址 *
* 作者:微电子系 董巍 2120070223 *
****************************************************************/
#include <PACKET32.H>
#include <NTDDNDIS.H>
#include <STDIO.H>
#include <CONIO.H>
//#include <STDLIB.H>

#pragma comment(lib,"ws2_32")
#pragma comment(lib,"packet")

#define ETH_IP 0x0800
#define ETH_ARP 0x0806
#define ARP_REQUEST 0x0001
#define ARP_REPLY 0x0002
#define ARP_HARDWARE 0x0001
#define MAX_NUM_ADAPTER 10

#pragma pack(push,1)

/****************
*物理帧头部结构
*****************/
typedef struct ethernet_head
{
unsigned char eh_dest_mac[6]; //目标主机mac
unsigned char eh_source_mac[6]; //本地主机mac
unsigned short eh_type; //类型
}ethernet_head, *pEthernetHead;

/************
*ARP帧结构
*************/
typedef struct arpHead
{
unsigned short arp_hardwaretype; //硬件类型(2 bit)
unsigned short arp_protocoltype; //协议类型(2 bit)
unsigned char arp_har_len; //硬件地址长度(1 bit)
unsigned char arp_pro_len; //协议地址长度(1 bit)
unsigned short arp_option; //操作号(2 bit)
unsigned char arp_sour_addr[6]; //源硬件地址(6 bit)
unsigned long arp_sour_ip; //源协议地址(4 bit)
unsigned char arp_dest_addr[6]; //目的硬件地址(6 bit)
unsigned long arp_dest_ip; //目的协议地址(4 bit)
unsigned char padding[18]; //填充数据(18 bit)
}arpHead, *pArpHead;

/****************
*IP数据报头结构
*****************/
typedef struct ipHead
{
unsigned char h_lenver; // 版本 (4 bits) + 首部长度 (4 bits)
unsigned char tos; // 服务类型(Type of service)
unsigned short total_len; // 总长(Total length)
unsigned short ident; // 标识(Identification)
unsigned short frag_and_flags; // 标志位(Flags) (3 bits) + 段偏移量(Fragment offset) (13 bits)
unsigned char ttl; // 存活时间(Time to live)
unsigned char proto; // 协议(Protocol)
unsigned short checksum; // 首部校验和(Header checksum)
unsigned int sourceip; // 源地址(Source address)
unsigned int destip; // 目的地址(Destination address)
}ipHead, *PipHead;

#pragma pack(push)

LPADAPTER lpadapter = 0; //define a pointer to an ADAPTER structure设备指针
LPPACKET lppacketr, lppackets; //define a pointer to a PACKET structure包指针
unsigned long myip; //本地主机IP
unsigned char mymac[6] = {0}; //本地主机mac初始化
char adapterlist[MAX_NUM_ADAPTER][1024]; //本地主机网卡列表
int num = 0; //用于发送ARP包时候递增

void start()
{
printf("************************************\n");
printf("* *\n");
printf("* 局域网内活动主机检测 *\n");
printf("* 07微电子 董巍 2120070223 *\n");
printf("* *\n");
printf("************************************\n");
return;
}

/**********************
*获得本地主机的mac地址
***********************/
int getmine()
{
char sendbuf[1024];
int k;
ethernet_head eth;
arpHead arp;

for(k=0;k<6;k++)
{
eth.eh_dest_mac[k] =0xff;
eth.eh_source_mac[k]=0x82;
arp.arp_sour_addr[k]=0x82;
arp.arp_dest_addr[k]=0x00;
}

eth.eh_type=htons(ETH_ARP);
arp.arp_hardwaretype=htons(ARP_HARDWARE);
arp.arp_protocoltype=htons(ETH_IP);
arp.arp_har_len=6;
arp.arp_pro_len=4;
arp.arp_option=htons(ARP_REQUEST);

arp.arp_dest_ip=htonl(myip);
arp.arp_sour_ip=inet_addr("112.112.112.112");

memset(sendbuf,0,sizeof(sendbuf));
memcpy(sendbuf,ð,sizeof(eth));
memcpy(sendbuf+sizeof(eth),&arp,sizeof(arp));

PacketInitPacket(lppackets,sendbuf,sizeof(eth)+sizeof(arp));

if(PacketSendPacket(lpadapter,lppackets,TRUE)==FALSE)
{
printf("PacketSendPacket in getmine Error: %d\n",GetLastError());
return -1;
}
return 0;
}

/****************
*解析数据报
*****************/
void receivedata(LPPACKET lppktr)
{
unsigned long ulbytesreceived, off;
unsigned long j;
char *buf, *pChar, *base;
PipHead ip;
struct bpf_hdr *hdr; //数据报头部
struct sockaddr_in sin;
ethernet_head *eth;
arpHead *arp;

ulbytesreceived = lppktr->ulBytesReceived;
buf = (char *)lppktr->Buffer;

off = 0;

//解析数据报
while (off < ulbytesreceived)
{
if(kbhit())
{
return;
}

hdr = (struct bpf_hdr *)(buf+off);
off += hdr->bh_hdrlen; //数据报头部长度

pChar = (char *)(buf+off);
base = pChar;
off = Packet_WORDALIGN(off + hdr->bh_caplen);

eth = (pEthernetHead)pChar;
arp = (pArpHead)(pChar + sizeof(ethernet_head));

if (eth->eh_type == htons(ETH_IP))
{
ip = (PipHead)(pChar+sizeof(ethernet_head));
}
else if((eth->eh_type==htons(ETH_ARP)) && (arp->arp_option==htons(ARP_REPLY)))
{
sin.sin_addr.s_addr = arp->arp_sour_ip;

if (sin.sin_addr.s_addr == htonl(myip))
{
memcpy(mymac, eth->eh_source_mac, 6);
}

//输出ip地址

printf("\n[IP:] %.16s [MAC:] ", inet_ntoa(sin.sin_addr));

//输出mac地址
for(j=0;j<5;j++)
{
printf("%.2x-",eth->eh_source_mac[j]);
}
printf("%.2x\n",eth->eh_source_mac[5]);
}
}
return ;
}

/************************************************
*将网卡设置为混杂模式,接收所有流过的数据报
************************************************/
DWORD WINAPI sniff(LPVOID no)
{

char recvbuf[1024*250];

//设置网卡为混杂模式失败
if (PacketSetHwFilter(lpadapter, NDIS_PACKET_TYPE_PROMISCUOUS)==FALSE)
{
printf("Warning:Unable to set the adapter to promiscuous mode\n");
}

//设置网卡内核缓冲的大小为500*1024失败,返回错误代码
if (PacketSetBuff(lpadapter, 500*1024)==FALSE)
{
printf("PacketSetBuff Error:%d\n",GetLastError());
return -1;
}

//设置接收一个数据报后等待的时间为1毫秒失败
if (PacketSetReadTimeout(lpadapter, 1)==FALSE)
{
printf("Warning: Unable to set the timeout\n");
}

//接收PACKET指针失败
if ((lppacketr=PacketAllocatePacket())==FALSE)
{
printf("PacketAllocatePacket receive Error! ");
return -1;
}

//初始化一个_PACKET结构
PacketInitPacket(lppacketr, (char *)recvbuf, sizeof(recvbuf));

//当没有按键按下时,从NPF驱动程序读取网络数据报,不成功则退出,读取成功调用解析函数
while (!kbhit())
{

if (PacketReceivePacket(lpadapter, lppacketr, TRUE)==FALSE)
{
if(GetLastError()==6)
return 0;
printf("PacketReceivePacket Error:%d\n",GetLastError());
return -1;
}

receivedata(lppacketr);
}

return 0;
}

/**********************************************
*发送ARP Request数据报,请求获得目的ip的mac地址
***********************************************/
DWORD WINAPI transmit(LPVOID no)
{
int i;
char sendbuf[1024]; //发送缓存
ethernet_head eth;
arpHead arp;

/***************************************************
*初始化mac地址和ip地址,以本地主机mac地址作为源地址,
*以物理广播地址作为物理帧目的地址,
*ARP帧目的地址置0
****************************************************/
for (i=0; i<6; i++)
{
eth.eh_dest_mac[i] = 0xff;
arp.arp_dest_addr[i] = 0x00;
}

memcpy(eth.eh_source_mac,mymac,6);

eth.eh_type = htons(ETH_ARP);
arp.arp_hardwaretype = htons(ARP_HARDWARE); //硬件类型0x0001,并将16位的主机字节顺序转化为16位的网络字节顺序
arp.arp_protocoltype = htons(ETH_IP); //协议类型0x0800
arp.arp_har_len = 6;
arp.arp_pro_len = 4;
arp.arp_option = htons(ARP_REQUEST); //操作字段写入1

arp.arp_sour_ip = htonl(myip); //将本机ip地址作为源ip地址,并将32位的主机字节顺序转化为32位的网络字节顺序
memcpy(arp.arp_sour_addr, mymac,6); //本机mac地址作为源mac地址
arp.arp_dest_ip = htonl((myip&0xffffff00)+1+(num++)); //本地主机IP与子网掩码“与”运算得到网关IP

memset(sendbuf, 0, sizeof(sendbuf)); //初始化发送缓存
memcpy(sendbuf, ð, sizeof(eth)); //把eth放入发送缓存
memcpy(sendbuf+sizeof(eth), &arp, sizeof(arp)); //把arp放入发送缓存

//初始化一个_PACKET结构
PacketInitPacket(lppackets, sendbuf, sizeof(eth)+sizeof(arp));

//发送数据报,不成功时退出
if (PacketSendPacket(lpadapter, lppackets, TRUE)==FALSE)
{
printf("PacketSendPacket in transmit Error:&d\n",GetLastError());
return -1;
}

return 0;
}



/***************************************************************
*主函数:首先获得本地主机网卡数量,如有多块网卡由用户打开指定网卡
*调用函数发送和解析ARP数据报
****************************************************************/
int main(int argc,char *argv[])
{
HANDLE sthread,rthread;
DWORD threadsid,threadrid;
unsigned char adaptername[8192];
unsigned char *name1, *name2;
unsigned long adapterlength;
struct NetType ntype;
struct bpf_stat stat;
struct sockaddr_in sin;
struct npf_if_addr ipbuff;
int adapternum = 0; //网卡数量,初始化为0
int open; //标识打开第几块网卡
int opti=1;
int k;
long npflen;

system("cls.exe"); //清屏
start();

adapterlength = sizeof(adaptername);

/*********************************************************
*获得本地主机网卡列表和描述,
*将返回的本地主机中安装的网卡的名字放在缓冲区adaptername中
**********************************************************/
if (PacketGetAdapterNames((char *)adaptername, &adapterlength)==FALSE)
{
printf("PacketGetAdapterNames Error:%d\n",GetLastError());
return -1;
}
name1 = adaptername;
name2 = adaptername;
k = 0;

//计算网卡个数

while((*name1!='\0') || (*(name1-1)!='\0'))
{
if(*name1=='\0')
{
memcpy(adapterlist[k],name2,(name1-name2)*2);
name2=name1+1;
k++;
}
name1++;
}

//将网卡名称存入adapterlist,分别输出网卡名称
adapternum=k;
printf("\n[本机网卡列表:]\n");

for(k=0;k<ADAPTERNUM;K++) - printf(?%d> %s\n",k+1,adapterlist[k]);

//打开指定的网卡
do
{
printf("\n请选择要打开的网卡号: ");
scanf("%d",&open);
if(open>=1 && open<=adapternum)
break;
}while(open<1 || open>adapternum);


lpadapter=PacketOpenAdapter(adapterlist[open-1]);

//网卡无法打开时,出示错误信息:
if(!lpadapter || (lpadapter->hFile==INVALID_HANDLE_VALUE))
{
printf("PacketOpenAdapter Error: %d\n",GetLastError());
return -1;
}

//输出指定网卡的MAC类型
if(PacketGetNetType(lpadapter,&ntype))
{
printf("\n\n******本地主机信息******\n\n");
printf("[连接类型: ]\t%d\t\t\n",ntype.LinkType);
printf("[连接速度: ]\t%d b/s\n",ntype.LinkSpeed);
}

//输出指定网卡的相关信息
npflen=sizeof(ipbuff);

if(PacketGetNetInfoEx(adapterlist[open-1],&ipbuff,&npflen))
{
sin=*(struct sockaddr_in *)&(ipbuff.Broadcast);
printf("[广播地址: ]\t%.16s\t\n",inet_ntoa(sin.sin_addr));

sin=*(struct sockaddr_in *)&(ipbuff.SubnetMask);
printf("[子网掩码: ]\t%.16s\n",inet_ntoa(sin.sin_addr));

sin=*(struct sockaddr_in *)&(ipbuff.IPAddress);
printf("[本机IP地址:]\t%.16s\t\n\n\n",inet_ntoa(sin.sin_addr));

myip=ntohl(sin.sin_addr.s_addr); //本机IP地址

}
else
{
printf("\nNot get enough data\n");
PacketFreePacket(lppackets);
PacketCloseAdapter(lpadapter);
return -1;
}

if((lppackets=PacketAllocatePacket())==FALSE)
{
printf("PacketAllocatePacket send Error: %d\n",GetLastError());
return -1;
}

printf("*****本网段内活动主机IP地址与MAC地址对应列表*****\n");

//创建一个新的线程,调用sniff函数接收流过的数据包,并解析数据报内容
rthread=CreateThread(NULL,0,sniff,(LPVOID)&opti,0,&threadrid);
Sleep(300);


if(getmine())
{
PacketFreePacket(lppackets);
PacketFreePacket(lppacketr);
PacketCloseAdapter(lpadapter);
return -1;
}
Sleep(300);

/*********************************************
*创建线程,调用transmit函数发送ARP请求数据报,
*共发送256次,每次间隔30ms
**********************************************/
for(k=0;k<256;k++)
{
sthread=CreateThread(NULL,0,transmit,(LPVOID)&opti,0,&threadsid);
Sleep(30);
}

//等待发送ARP数据报的线程结束
WaitForSingleObject(sthread,INFINITE);
CloseHandle(sthread);
CloseHandle(rthread);

//统计从网卡捕获数据报开始收到的数目和丢失的数目
if(PacketGetStats(lpadapter,&stat)==FALSE)
{
printf("Warning: Unable to get the adapter stat\n");
}
else
{
printf("\n\n接收数据包 %d, 丢失数据包 %d\n\n",stat.bs_recv,stat.bs_drop);
}

PacketFreePacket(lppackets); //释放由lpPackets指向的结构
PacketFreePacket(lppacketr); //释放由lpPacket指向的结构
PacketCloseAdapter(lpadapter); //关闭网卡指针并退出

Sleep(10000); //主程序挂起

return 0;
}
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值