Mir*_*sin 11
复制粘贴到main.c和gcc main.c && ./a.out应该工作(列出所有网络接口,它们的IPv4/6地址,子网掩码和MAC地址,如果相关的):
适用于Mac OSX和iOS iPad/iPhone:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <ifaddrs.h>
#include <errno.h>
int main() {
struct ifaddrs *if_addrs = NULL;
struct ifaddrs *if_addr = NULL;
void *tmp = NULL;
char buf[INET6_ADDRSTRLEN];
if (0 == getifaddrs(&if_addrs)) {
for (if_addr = if_addrs; if_addr != NULL; if_addr = if_addr->ifa_next) {
printf("name : %s\n", if_addr->ifa_name);
// Address
if (if_addr->ifa_addr->sa_family == AF_INET) {
tmp = &((struct sockaddr_in *)if_addr->ifa_addr)->sin_addr;
} else {
tmp = &((struct sockaddr_in6 *)if_addr->ifa_addr)->sin6_addr;
}
printf("addr : %s\n",
inet_ntop(if_addr->ifa_addr->sa_family,
tmp,
buf,
sizeof(buf)));
// Mask
if (if_addr->ifa_netmask != NULL) {
if (if_addr->ifa_netmask->sa_family == AF_INET) {
tmp = &((struct sockaddr_in *)if_addr->ifa_netmask)->sin_addr;
} else {
tmp = &((struct sockaddr_in6 *)if_addr->ifa_netmask)->sin6_addr;
}
printf("mask : %s\n",
inet_ntop(if_addr->ifa_netmask->sa_family,
tmp,
buf,
sizeof(buf)));
}
// MAC address
if (if_addr->ifa_addr != NULL && if_addr->ifa_addr->sa_family == AF_LINK) {
struct sockaddr_dl* sdl = (struct sockaddr_dl *)if_addr->ifa_addr;
unsigned char mac[6];
if (6 == sdl->sdl_alen) {
memcpy(mac, LLADDR(sdl), sdl->sdl_alen);
printf("mac : %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
}
}
printf("\n");
}
freeifaddrs(if_addrs);
if_addrs = NULL;
} else {
printf("getifaddrs() failed with errno = %i %s\n", errno, strerror(errno));
return -1;
}
}
Run Code Online (Sandbox Code Playgroud)
获取MAC地址的机制在BSD派生的操作系统上与在Linux上完全不同.这包括OS X.
这里使用的代码适用于Linux和OS X,也可能适用于BSD:
#if defined(HAVE_SIOCGIFHWADDR)
bool get_mac_address(char* mac_addr, const char* if_name = "eth0")
{
struct ifreq ifinfo;
strcpy(ifinfo.ifr_name, if_name);
int sd = socket(AF_INET, SOCK_DGRAM, 0);
int result = ioctl(sd, SIOCGIFHWADDR, &ifinfo);
close(sd);
if ((result == 0) && (ifinfo.ifr_hwaddr.sa_family == 1)) {
memcpy(mac_addr, ifinfo.ifr_hwaddr.sa_data, IFHWADDRLEN);
return true;
}
else {
return false;
}
}
#elif defined(HAVE_GETIFADDRS)
bool get_mac_address(char* mac_addr, const char* if_name = "en0")
{
ifaddrs* iflist;
bool found = false;
if (getifaddrs(&iflist) == 0) {
for (ifaddrs* cur = iflist; cur; cur = cur->ifa_next) {
if ((cur->ifa_addr->sa_family == AF_LINK) &&
(strcmp(cur->ifa_name, if_name) == 0) &&
cur->ifa_addr) {
sockaddr_dl* sdl = (sockaddr_dl*)cur->ifa_addr;
memcpy(mac_addr, LLADDR(sdl), sdl->sdl_alen);
found = true;
break;
}
}
freeifaddrs(iflist);
}
return found;
}
#else
# error no definition for get_mac_address() on this platform!
#endif
Run Code Online (Sandbox Code Playgroud)
由您来决定如何HAVE_*为平台定义正确的宏.我碰巧使用autoconf,但你可能有另一种方法来处理平台差异.
请注意,这些函数的默认接口名称参数对于Linux和OS X盒第一个以太网接口的默认.您可能需要重写此对于其他操作系统,或者如果你有兴趣的MAC地址不同的接口通过另一个值.
该线程在某种程度上符合我的问题:
http://discussions.apple.com/thread.jspa?messageID=10935410&tstart=0
该线程有很大帮助:
https://lists.isc.org/pipermail/dhcp-hackers/2007-September/000767.html
因为该线程最终提到应该使用 getifaddrs() 来代替。Ubuntu 10.04 上的手册页有一个关于如何使用 getifaddrs 的很好的示例,并将其用作参考帮助我找出在 Mac 和 Linux 上都可以运行的代码。我不想让其他人在如此简单的事情上浪费时间,所以我在这里发帖并回答自己。希望我的帖子对你有帮助...