程序运行结果IP地址及MAC地址不能显示

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "pcap.h"
#include "Packet32.h"
#pragma pack(1)
#pragma comment(lib,"ws2_32.lib")
#define IPTOSBUFFERS    12
#define ETH_ARP         0x0806  //以太网帧类型表示后面数据的类型,对于ARP请求或应答来说,该字段的值为x0806
#define ARP_HARDWARE    1  //硬件类型字段值为表示以太网地址
#define ETH_IP          0x0800  //协议类型字段表示要映射的协议地址类型值为x0800表示IP地址
#define ARP_REQUEST     1   //ARP请求
#define ARP_REPLY       2      //ARP应答
#define HOSTNUM         255   //主机数量

HANDLE sendthread;      //发送ARP包线程
HANDLE recvthread;       //接受ARP包线程


bool flag;
struct EthernetHeader
{
	u_char DestMAC[6];    //目的MAC地址 6字节
	u_char SourMAC[6];   //源MAC地址 6字节
	u_short EthType;         //上一层协议类型,如0x0800代表上一层是IP协议,0x0806为arp  2字节
};

//28字节ARP帧结构
struct Arpheader {
	unsigned short HardwareType; //硬件类型
	unsigned short ProtocolType; //协议类型
	unsigned char HardwareAddLen; //硬件地址长度
	unsigned char ProtocolAddLen; //协议地址长度
	unsigned short OperationField; //操作字段
	unsigned char SourceMacAdd[6]; //源mac地址
	unsigned long SourceIpAdd; //源ip地址
	unsigned char DestMacAdd[6]; //目的mac地址
	unsigned long DestIpAdd; //目的ip地址
};

//arp包结构
struct ArpPacket {
	EthernetHeader ed;
	Arpheader ah;
};

struct sparam {
	pcap_t* adhandle;
	char* ip;
	unsigned char* mac;
	char* netmask;
};
struct gparam {
	pcap_t* adhandle;
};

struct sparam sp;
struct gparam gp;
char* iptos(u_long in)
{
	static char output[IPTOSBUFFERS][3 * 4 + 3 + 1];
	static short which;
	u_char* p;
	
	p = (u_char*)&in;
	which = (which + 1 == IPTOSBUFFERS ? 0 : which + 1);
	sprintf_s(output[which], "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
	return output[which];
}
void ifget(pcap_if_t* d, char* ip_addr, char* ip_netmask) {
	pcap_addr_t* a;
	
	//遍历所有的地址,a代表一个pcap_addr
	for (a = d->addresses; a; a = a->next) {
		switch (a->addr->sa_family) {
		case AF_INET:  //sa_family :是2字节的地址家族,一般都是“AF_xxx”的形式。通常用的都是AF_INET。代表IPV4
			if (a->addr) {
				char* ipstr;
				//将地址转化为字符串
				ipstr = iptos(((struct sockaddr_in*)a->addr)->sin_addr.s_addr); //*ip_addr
				printf("ipstr:%s\n", ipstr);
				memcpy(ip_addr, ipstr, 16);
			}
			if (a->netmask) {
				char* netmaskstr;
				netmaskstr = iptos(((struct sockaddr_in*)a->netmask)->sin_addr.s_addr);
				printf("netmask:%s\n", netmaskstr);
				memcpy(ip_netmask, netmaskstr, 16);
			}
		case AF_INET6:
			break;
		}
	}
}

int GetSelfMac(pcap_t* adhandle, const char* ip_addr, unsigned char* ip_mac) {
	unsigned char sendbuf[42]; //arp包结构大小
	int i = -1;
	int res;
	EthernetHeader eh; //以太网帧头
	Arpheader ah;  //ARP帧头
	struct pcap_pkthdr* pkt_header;
	const u_char* pkt_data;
	//将已开辟内存空间 eh.dest_mac_add 的首 6个字节的值设为值 0xff。
	memset(eh.DestMAC, 0xff, 6); //目的地址为全为广播地址
	memset(eh.SourMAC, 0x0f, 6);
	memset(ah.DestMacAdd, 0x0f, 6);
	memset(ah.SourceMacAdd, 0x00, 6);
	//htons将一个无符号短整型的主机数值转换为网络字节顺序
	eh.EthType = htons(ETH_ARP);
	ah.HardwareType = htons(ARP_HARDWARE);
	ah.ProtocolType = htons(ETH_IP);
	ah.HardwareAddLen = 6;
	ah.ProtocolAddLen = 4;
	ah.SourceIpAdd = inet_addr("100.100.100.100"); //随便设的请求方ip
	ah.OperationField = htons(ARP_REQUEST);
	ah.DestIpAdd = inet_addr(ip_addr);
	memset(sendbuf, 0, sizeof(sendbuf));
	memcpy(sendbuf, &eh, sizeof(eh));
	memcpy(sendbuf + sizeof(eh), &ah, sizeof(ah));
	printf("%s", sendbuf);
	if (pcap_sendpacket(adhandle, sendbuf, 42) == 0) {
		printf("\nPacketSend succeed\n");
	}
	else {
		printf("PacketSendPacket in getmine Error: %d\n", GetLastError());
		return 0;
	}
	//从interface或离线记录文件获取一个报文
	//pcap_next_ex(pcap_t* p,struct pcap_pkthdr** pkt_header,const u_char** pkt_data)
	while ((res = pcap_next_ex(adhandle, &pkt_header, &pkt_data)) >= 0) {
		if (*(unsigned short*)(pkt_data + 12) == htons(ETH_ARP)
			&& *(unsigned short*)(pkt_data + 20) == htons(ARP_REPLY)
			&& *(unsigned long*)(pkt_data + 38)
			== inet_addr("100.100.100.100")) {
			for (i = 0; i < 6; i++) {
				ip_mac[i] = *(unsigned char*)(pkt_data + 22 + i);
			}
			printf("获取自己主机的MAC地址成功!\n");
			break;
		}
	}
	if (i == 6) {
		return 1;
	}
	else {
		return 0;
	}
}
DWORD WINAPI SendArpPacket(LPVOID lpParameter) //(pcap_t *adhandle,char *ip,unsigned char *mac,char *netmask)
{
	
	sparam* spara = (sparam*)lpParameter;
	pcap_t* adhandle = spara->adhandle;
	char* ip = spara->ip;
	unsigned char* mac = spara->mac;
	char* netmask = spara->netmask;
	
	printf("ip_mac:%02x-%02x-%02x-%02x-%02x-%02x\n", mac[0], mac[1], mac[2],
		mac[3], mac[4], mac[5]);
	printf("自身的IP地址为:%s\n", ip);
	printf("地址掩码NETMASK为:%s\n", netmask);
	printf("\n");
	unsigned char sendbuf[42]; //arp包结构大小
	EthernetHeader eh;
	Arpheader ah;
	//赋值MAC地址
	memset(eh.DestMAC, 0xff, 6);       //目的地址为全为广播地址
	memcpy(eh.SourMAC, mac, 6);
	memcpy(ah.SourceMacAdd, mac, 6);
	memset(ah.DestMacAdd, 0x00, 6);
	eh.EthType = htons(ETH_ARP);
	ah.HardwareType = htons(ARP_HARDWARE);
	ah.ProtocolType = htons(ETH_IP);
	ah.HardwareAddLen = 6;
	ah.ProtocolAddLen = 4;
	ah.SourceIpAdd = inet_addr(ip); //请求方的IP地址为自身的IP地址
	ah.OperationField = htons(ARP_REQUEST);
	//向局域网内广播发送arp包
	unsigned long myip = inet_addr(ip);
	unsigned long mynetmask = inet_addr(netmask);
	unsigned long hisip = htonl((myip & mynetmask));
	//向255个主机发送
	for (int i = 0; i < HOSTNUM; i++) 
	{
		ah.DestIpAdd = htonl(hisip + i);
		//构造一个ARP请求
		memset(sendbuf, 0, sizeof(sendbuf));
		memcpy(sendbuf, &eh, sizeof(eh));
		memcpy(sendbuf + sizeof(eh), &ah, sizeof(ah));
		//如果发送成功
		if (pcap_sendpacket(adhandle, sendbuf, 42) == 0) {
			//printf("\nPacketSend succeed\n");
		}
		else {
			printf("PacketSendPacket in getmine Error: %d\n", GetLastError());
		}
		Sleep(50);
	}
	Sleep(1000);
	flag = TRUE;
	return 0;
}
DWORD WINAPI GetLivePC(LPVOID lpParameter) //(pcap_t *adhandle)
{
	
	gparam* gpara = (gparam*)lpParameter;
	pcap_t* adhandle = gpara->adhandle;
	int res;
	unsigned char Mac[6];
	struct pcap_pkthdr* pkt_header;
	const u_char* pkt_data;
	
	while (true) {
		if (flag) {
			printf("获取MAC地址完毕,请输入你要发送对方的IP地址:\n");
			break;
		}
		if ((res = pcap_next_ex(adhandle, &pkt_header, &pkt_data)) >= 0) {
			if (*(unsigned short*)(pkt_data + 12) == htons(ETH_ARP)) {
				ArpPacket* recv = (ArpPacket*)pkt_data;
				if (*(unsigned short*)(pkt_data + 20) == htons(ARP_REPLY)) {
					printf("-------------------------------------------\n");
					printf("IP地址:%d.%d.%d.%d   MAC地址:",
						recv->ah.SourceIpAdd & 255,
						recv->ah.SourceIpAdd >> 8 & 255,
						recv->ah.SourceIpAdd >> 16 & 255,
						recv->ah.SourceIpAdd >> 24 & 255);
					for (int i = 0; i < 6; i++) {
						Mac[i] = *(unsigned char*)(pkt_data + 22 + i);
						printf("%02x", Mac[i]);
					}
					printf("\n");
				}
			}
		}
		Sleep(10);
	}
	return 0;
}
int main()
{
	char * ip_addr;                                    //IP地址
	char * ip_netmask;                             //子网掩码
	unsigned char * ip_mac;
	pcap_addr* next;
	sockaddr* addr;
	sockaddr* netmask;
	sockaddr* broadaddr;
	sockaddr* dstaddr;
	pcap_if_t* alldevs;       //所有网络适配器
	pcap_if_t* d;					//选中的网络适配器
	char errbuf[PCAP_ERRBUF_SIZE];   //错误缓冲区,大小为256
	pcap_t* adhandle;           //捕捉实例,是pcap_open返回的对象
	int i = 0;
	
	ip_addr = (char*)malloc(sizeof(char) * 16); //申请内存存放IP地址
	if (ip_addr == NULL)
	{
		printf("申请内存存放IP地址失败!\n");
		return -1;
	}
	ip_netmask = (char*)malloc(sizeof(char) * 16); //申请内存存放NETMASK地址
	if (ip_netmask == NULL)
	{
		printf("申请内存存放NETMASK地址失败!\n");
		return -1;
	}
	ip_mac = (unsigned char*)malloc(sizeof(unsigned char) * 6); //申请内存存放MAC地址
	if (ip_mac == NULL)
	{
		printf("申请内存存放MAC地址失败!\n");
		return -1;
	}
	if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1) {
		//结果为-1代表出现获取适配器列表失败
		fprintf(stderr, "Error in pcap_findalldevs_ex:\n", errbuf);
		//exit(0)代表正常退出,exit(other)为非正常退出,这个值会传给操作系统
		exit(1);
	}


	for (d = alldevs; d != NULL; d = d->next) {
		printf("-----------------------------------------------------------------\nnumber:%d\nname:%s\n", ++i, d->name);
		if (d->description) {
			//打印适配器的描述信息
			printf("description:%s\n", d->description);
		}
		else {
			//适配器不存在描述信息
			printf("description:%s", "no description\n");
		}
		//打印本地环回地址
		printf("\tLoopback: %s\n", (d->flags & PCAP_IF_LOOPBACK) ? "yes" : "no");
		/*
		pcap_addr *  next     指向下一个地址的指针
		sockaddr *  addr       IP地址
		sockaddr *  netmask  子网掩码
		sockaddr *  broadaddr   广播地址
		sockaddr *  dstaddr        目的地址
		*/
		pcap_addr_t* a;       //网络适配器的地址用来存储变量
		for (a = d->addresses; a; a = a->next) {
			//sa_family代表了地址的类型,是IPV4地址类型还是IPV6地址类型
			switch (a->addr->sa_family)
			{
			case AF_INET:  //代表IPV4类型地址
				printf("Address Family Name:AF_INET\n");
				if (a->addr) {
					//->的优先级等同于括号,高于强制类型转换,因为addr为sockaddr类型,对其进行操作须转换为sockaddr_in类型
					printf("Address:%s\n", iptos(((struct sockaddr_in*)a->addr)->sin_addr.s_addr));
				}
				if (a->netmask) {
					printf("\tNetmask: %s\n", iptos(((struct sockaddr_in*)a->netmask)->sin_addr.s_addr));
				}
				if (a->broadaddr) {
					printf("\tBroadcast Address: %s\n", iptos(((struct sockaddr_in*)a->broadaddr)->sin_addr.s_addr));
				}
				if (a->dstaddr) {
					printf("\tDestination Address: %s\n", iptos(((struct sockaddr_in*)a->dstaddr)->sin_addr.s_addr));
				}
				break;
			case AF_INET6: //代表IPV6类型地址
				printf("Address Family Name:AF_INET6\n");
				printf("this is an IPV6 address\n");
				break;
			default:
				break;
			}
		}
	}
	//i为0代表上述循环未进入,即没有找到适配器,可能的原因为Winpcap没有安装导致未扫描到
	if (i == 0) {
		printf("interface not found,please check winpcap installation");
	}

	int num;
	printf("Enter the interface number(1-%d):", i);
	//让用户选择选择哪个适配器进行抓包
	scanf_s("%d", &num);
	printf("\n");

	//用户输入的数字超出合理范围
	if (num<1 || num>i) {
		printf("number out of range\n");
		pcap_freealldevs(alldevs);
		return -1;
	}
	//跳转到选中的适配器
	for (d = alldevs, i = 0; i < num - 1; d = d->next, i++);

	//运行到此处说明用户的输入是合法的
	if ((adhandle = pcap_open(d->name,		//设备名称
		65535,       //存放数据包的内容长度
		PCAP_OPENFLAG_PROMISCUOUS,  //混杂模式
		1000,           //超时时间
		NULL,          //远程验证
		errbuf         //错误缓冲
	)) == NULL) {
		//打开适配器失败,打印错误并释放适配器列表
		fprintf(stderr, "\nUnable to open the adapter. %s is not supported by WinPcap\n", d->name);
		// 释放设备列表 
		pcap_freealldevs(alldevs);
		return -1;
	}
	char* iptos(u_long in);
	ifget(d, ip_addr, ip_netmask);
	sp.adhandle = adhandle;
	sp.ip = ip_addr;
	sp.mac = ip_mac;
	sp.netmask = ip_netmask;
	gp.adhandle = adhandle;
	sendthread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)SendArpPacket,&sp, 0, NULL);
	recvthread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)GetLivePC, &gp,0, NULL);
	printf("\nlistening on 网卡%d ...\n", i);
	return 0;
}

使用ARP协议获取局域网内活动主机物理地址程序
如题

最后运行结果应该是这样

 

你好,我是有问必答小助手,非常抱歉,本次您提出的有问必答问题,目前超出我们的服务范围,暂时无法为您解答。

首次提问人员可免费体验一次有问必答服务。目前首次提问的问题服务范围为:编程语言、Java开发、python、数据库、前端开发 领域专业技术问题,为您提供问题的解决思路和指导。不提供源码代写、项目文档代写、论文代写、作业代写、安装包资源发送或安装、软件使用指导等服务。

我们后续会持续优化,扩大我们的服务范围,为您带来更好地服务。