一、前言
主机的IP地址一般是可能会随着时间变化,例如DHCP的网络中会在不同的时间段分配不同的地址,而主机的MAC地址理论上是全球唯一的硬件地址,但是在虚拟化环境中,是可以被被伪造或更改。因此,MAC地址、IP地址并不能相对唯一的标识某一台主机设备,对于应用程序而言,更好的做法可能是使用应用程序级别的身份验证和授权机制,或者为每台主机生成一个唯一的ID(如UUID)并存储在安全的地方(如注册表、文件系统或数据库中。当然,本文只是简单学习如果编程在linux系统中获取MAC_IP地址对。
二、获取MAC地址和IP地址
1、有线网卡、无线网卡常见名称
1) 有线网卡名称
- eth:例如 eth0, eth1
- en:例如 enp0s3, ens33
- em:例如 em1, em2
- p:例如 p1p1,p2p1
- br:例如 br-lan(桥接接口)
- usb:例如 usb0(USB 网络设备)
- can:例如 can0(CAN总线接口)
3)无线网卡名称
- wlan:例如 wlan0, wlan1
- wl:例如 wlp2s0, wlp3s0
- wlp:例如 wlp2s0, wlp3s0
- wlo:例如 wlo1, wlo2
- ra:例如 ra0(Realtek 无线网卡)
- ath:例如 ath0(Atheros 无线网卡)
- wlan:例如 wlan0(通用无线网卡)
- sta:例如 sta0(站模式无线网卡)
- ap:例如 ap0(接入点模式无线网卡)
2、判断网卡名称
这里采用列举的方式检索有线、无线常见的网卡名称,使用is_valid_interface
函数来判断
int is_valid_interface(const char *interface_name) {
// 排除 lo 网卡
if (strcmp(interface_name, "lo") == 0) {
return 0;
}
// 检查是否为 eth 或 en 开头的有线网卡
if (strncmp(interface_name, "eth", 3) == 0 || strncmp(interface_name, "en", 2) == 0 ||
strncmp(interface_name, "em", 2) == 0 || strncmp(interface_name, "p", 1) == 0 ||
strncmp(interface_name, "br", 2) == 0 || strncmp(interface_name, "usb", 3) == 0 ||
strncmp(interface_name, "can", 3) == 0) {
return 1;
}
// 检查是否为 wlan 或 wl 开头的无线网卡
if (strncmp(interface_name, "wlan", 4) == 0 || strncmp(interface_name, "wl", 2) == 0 ||
strncmp(interface_name, "wlp", 3) == 0 || strncmp(interface_name, "wlo", 3) == 0 ||
strncmp(interface_name, "ra", 2) == 0 || strncmp(interface_name, "ath", 3) == 0 ||
strncmp(interface_name, "sta", 3) == 0 || strncmp(interface_name, "ap", 2) == 0) {
return 1;
}
return 0;
}
3、查找可用网卡
这里使用find_available_interface
函数来遍历查找符合条件的网卡并打印MAC地址、IP地址
int find_available_interface(char *interface_name, char *mac_str, char *ip_str) {
struct ifaddrs *ifaddr, *ifa;
int sockfd;
if (getifaddrs(&ifaddr) == -1) {
perror("getifaddrs");
return 0;
}
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) {
perror("socket");
freeifaddrs(ifaddr);
return 0;
}
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
if (ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != AF_INET)
continue;
// 检查是否为有效的有线或无线网卡
if (!is_valid_interface(ifa->ifa_name)) {
continue;
}
printf("Checking interface: %s\n", ifa->ifa_name); // 添加日志
// 获取接口标志
struct ifreq ifr;
strncpy(ifr.ifr_name, ifa->ifa_name, IFNAMSIZ);
// 获取接口标志
if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) == -1) {
perror("ioctl SIOCGIFFLAGS");
continue;
}
// 检查接口是否处于运行状态
if (!(ifr.ifr_flags & IFF_UP)) {
continue;
}
// 获取接口硬件地址
if (ioctl(sockfd, SIOCGIFHWADDR, &ifr) == -1) {
perror("ioctl SIOCGIFHWADDR");
continue;
}
// 格式化 MAC 地址
snprintf(mac_str, 18, "%02X:%02X:%02X:%02X:%02X:%02X",
(unsigned char)ifr.ifr_hwaddr.sa_data[0],
(unsigned char)ifr.ifr_hwaddr.sa_data[1],
(unsigned char)ifr.ifr_hwaddr.sa_data[2],
(unsigned char)ifr.ifr_hwaddr.sa_data[3],
(unsigned char)ifr.ifr_hwaddr.sa_data[4],
(unsigned char)ifr.ifr_hwaddr.sa_data[5]);
printf("MAC Address: %s\n", mac_str); // 添加日志
// 查找对应的 IPv4 地址
struct sockaddr_in *ipv4 = (struct sockaddr_in *)ifa->ifa_addr;
inet_ntop(AF_INET, &(ipv4->sin_addr), ip_str, INET_ADDRSTRLEN);
printf("IP Address: %s\n", ip_str); // 添加日志
}
close(sockfd);
freeifaddrs(ifaddr);
return 0;
}