获取网卡的MAC地址、IP地址、子网掩码以及ARP缓存中的主机IP及MAC地址

获取网卡的MAC地址、IP地址、子网掩码以及ARP缓存中的主机IP及MAC地址

一、代码实现

eth_test.c

#include <stdio.h> 
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <net/if_arp.h>
#include <string.h>
#include <net/if.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>

int GetMac(const char* device_name, unsigned char* nic_mac)
{
	struct ifreq ifr;
	int socket_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP));
	if (socket_fd < 0)
	{
		printf("GetMac device name<%s> create socket failed\n", device_name);
		return -1;
	}

	strcpy(ifr.ifr_name, device_name);
	if (ioctl(socket_fd, SIOCGIFHWADDR, &ifr) != 0)
	{
		printf("GetMac device name<%s> failed\n", device_name);
		close(socket_fd);
		return -1;
	}
	unsigned char* hw = (unsigned char*)ifr.ifr_hwaddr.sa_data;
	memcpy(nic_mac, hw, 6);
	printf("GetMac device name<%s> mac<%02x-%02x-%02x-%02x-%02x-%02x> success\n", device_name, nic_mac[0], nic_mac[1], nic_mac[2], nic_mac[3], nic_mac[4], nic_mac[5]);
	close(socket_fd);

	return 0;
}

int GetIp(const char* device_name, uint32_t* ip_addr)
{
	struct ifreq ifr;
	int socket_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP));
	if (socket_fd < 0)
	{
		printf( "GetIp device name<%s> create socket failed\n", device_name);
		return -1;
	}
	strcpy(ifr.ifr_name, device_name);
	if (ioctl(socket_fd, SIOCGIFADDR, &ifr) != 0)
	{
		printf("GetIp device name<%s> failed\n", device_name);
		close(socket_fd);
		return -1;
	}
	*ip_addr = ntohl(((struct sockaddr_in*)&ifr.ifr_addr)->sin_addr.s_addr);
	printf("GetIp device name<%s> ip<%s> success\n", device_name, inet_ntoa(((struct sockaddr_in*)&ifr.ifr_addr)->sin_addr));
	close(socket_fd);

	return 0;
}

int GetNetmask(const char* device_name, uint32_t* netmask_addr)
{
	struct ifreq ifr;
	int socket_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP));
	if (socket_fd < 0)
	{
		printf("GetNetmask device name<%s> create socket failed\n", device_name);
		return -1;
	}
	strcpy(ifr.ifr_name, device_name);
	if (ioctl(socket_fd, SIOCGIFNETMASK, &ifr) != 0)
	{
		printf("GetNetmask device name<%s> failed\n", device_name);
		close(socket_fd);
		return -1;
	}
	*netmask_addr = ntohl(((struct sockaddr_in*)&ifr.ifr_addr)->sin_addr.s_addr);
	printf("GetNetmask device name<%s> netmask<%s> success\n", device_name, inet_ntoa(((struct sockaddr_in*)&ifr.ifr_addr)->sin_addr));
	close(socket_fd);

	return 0;
}

int ArpGetMac(const char* device_name, uint32_t ip_addr)
{
	struct arpreq req;
	struct sockaddr_in* sin;
	int sock_fd = 0;
	memset(&req, 0, sizeof(struct arpreq));
	sin = (struct sockaddr_in*)&req.arp_pa;
	sin->sin_family = AF_INET;
	sin->sin_addr.s_addr = ip_addr;
	char* ip = inet_ntoa(sin->sin_addr);
	strncpy(req.arp_dev, device_name, 16);

	sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
	if (sock_fd < 0)
	{
		printf("ArpGetMac device name<%s> ip<%s> create socket failed\n", device_name, ip);
		return -1;
	}

	if (ioctl(sock_fd, SIOCGARP, &req) != 0)
	{
		//printf("ArpGetMac device name<%s> ip<%s> failed\n", device_name, ip);
		close(sock_fd);
		return -1;
	}
	unsigned char* hw = (unsigned char*)req.arp_ha.sa_data;
	printf("ArpGetMac device name<%s> ip<%s> mac<%02x-%02x-%02x-%02x-%02x-%02x> success\n", device_name, ip, hw[0], hw[1], hw[2], hw[3], hw[4], hw[5]);
	close(sock_fd);

	return 0;
}

//通过ARP缓存获取同一网段内的主机MAC地址
void LearnHostMacByArpCache(const char* device_name)
{
	uint32_t ip_addr = 0;
	uint32_t netmask_addr = 0;
	unsigned char nic_mac[6] = { 0 };
	if (GetMac(device_name, nic_mac) != 0)
	{
		return;
	}

	if (GetIp(device_name, &ip_addr) != 0)
	{
		return;
	}

	if (GetNetmask(device_name, &netmask_addr) != 0)
	{
		return;
	}

	uint32_t host_ip_begin = ip_addr & netmask_addr;
	uint16_t host_ip_end = netmask_addr ^ 0XFFFFFFFF;
	int i = 0;
	for (; i <= host_ip_end; i++)
	{
		uint32_t ip_addr_net = htonl(host_ip_begin + i);
		ArpGetMac(device_name, ip_addr_net);
	}
}

int main(int argc, char** argv)
{
	if (argc < 2)
	{
		printf("Error ! Need input device name!\n");
		return -1;
	}
	LearnHostMacByArpCache(argv[1]);
	return 0;
}

二、编译及测试

1、编译:gcc -o eth_test eth_test.c
2、运行:./eth_test ens33
3、结果如下:
在这里插入图片描述
4、网卡信息查询:ifconfig
在这里插入图片描述
5、ARP缓存查询:arp -a |grep ens33
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值