获取网卡的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