C/C++ Linux 所有接口的 MAC 地址
我使用以下代码来检索当前计算机的所有 MAC 地址:
ifreq ifr;
ifconf ifc;
char buf[1024];
int sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
if (sock == -1) { ... };
ifc.ifc_len = sizeof(buf);
ifc.ifc_buf = buf;
if (ioctl(sock, SIOCGIFCONF, &ifc) == -1) { ... }
ifreq *it = ifc.ifc_req;
const ifreq* const end = it + (ifc.ifc_len / sizeof(ifreq));
for (; it != end; ++it) {
strcpy(ifr.ifr_name, it->ifr_name);
if (ioctl(sock, SIOCGIFFLAGS, &ifr) == 0) {
if (!(ifr.ifr_flags & IFF_LOOPBACK)) {
if (ioctl(sock, SIOCGIFHWADDR, &ifr) == 0) {
unsigned char mac_address[6];
memcpy(mac_address, ifr.ifr_hwaddr.sa_data, 6);
...
}
}
}
else { ... }
}
通过运行简单的 shell 命令 ifconfig 我可以看到 lo、eth0 和 wlan0。我想通过我的 C/C++ 代码检索 eth0 和 wlan0 的 MAC 地址。但只返回了 wlan0 - eth0 丢失(我得到了 ifr_names lo, lo, wlan0)。可能是因为 eth0 未激活(未连接以太网电缆,已返回电缆)。我是否可以以某种方式更改 ioctl(SIOCGIFCONF) 命令来检索 eth0,即使它已“关闭”?
我可以直接使用它来获取其硬件地址,
struct ifreq s;
int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
strcpy(s.ifr_name, "eth0");
if (0 == ioctl(fd, SIOCGIFHWADDR, &s)) { ... }
但如果名称不是 eth0 而是其他名称(eth1、em0,...)怎么办?我想全部得到。感谢您的帮助。
I am using the following code to retrieve all MAC addresses for current computer:
ifreq ifr;
ifconf ifc;
char buf[1024];
int sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
if (sock == -1) { ... };
ifc.ifc_len = sizeof(buf);
ifc.ifc_buf = buf;
if (ioctl(sock, SIOCGIFCONF, &ifc) == -1) { ... }
ifreq *it = ifc.ifc_req;
const ifreq* const end = it + (ifc.ifc_len / sizeof(ifreq));
for (; it != end; ++it) {
strcpy(ifr.ifr_name, it->ifr_name);
if (ioctl(sock, SIOCGIFFLAGS, &ifr) == 0) {
if (!(ifr.ifr_flags & IFF_LOOPBACK)) {
if (ioctl(sock, SIOCGIFHWADDR, &ifr) == 0) {
unsigned char mac_address[6];
memcpy(mac_address, ifr.ifr_hwaddr.sa_data, 6);
...
}
}
}
else { ... }
}
By running simple shell command ifconfig i can see lo, eth0 and wlan0. I would like to retrieve MAC addresses for eth0 and wlan0 by my C/C++ code. But only wlan0 is returned - eth0 is missing (I got ifr_names lo, lo, wlan0). Probably because eth0 is not active (no ethernet cable connected, with cable it is returned). Can I somehow alter that ioctl(SIOCGIFCONF) command to retrieve eth0 too even if it is "turned off"?
I can get its HW address by using directly
struct ifreq s;
int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
strcpy(s.ifr_name, "eth0");
if (0 == ioctl(fd, SIOCGIFHWADDR, &s)) { ... }
but what if the name would be not eth0 but something else (eth1, em0,...)? I would like to get all of them. Thanks for help.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您应该停止使用 net-tools 和过时的 ioctl 接口,并开始使用现代的 Netlink/sysfs 接口。您有不少于 5 种可能性:
ip -o link
(-o 是获取用于文本解析的输出,与 ifconfig 不同)/sys/class/net/eth0/address
You should stop using net-tools and the archaic ioctl interface, and start on using the modern Netlink/sysfs interfaces. You have no less than 5 possibilities:
ip -o link
(-o is to get output meant for text parsing, unlike ifconfig)/sys/class/net/eth0/address
您可以在这里找到解决方案: 获取给定特定接口的mac地址
您可以跳过特定接口部分。
You can find a solution here: Get mac address given a specific interface
You can just skip the specific interface part.
也许不那么优雅,但你可以捕捉和解析 ifconfig 的结果,因为听起来它正是您正在寻找的内容。
Maybe not as elegant, but you could capture & parse the results from ifconfig, since it sounds like it has just what you are looking for.
受到 jørgensen 的回答的启发,下面的 C++17 代码使用 Netlink 来获取每个接口的 MAC 地址和名称。它是这个要点的修改版本,它帮助我克服了使用 Netlink 的羞怯。它实际上并不像乍看起来那么复杂。
Inspired by jørgensen's answer, the C++17 code below uses Netlink to get the MAC address and name of each interface. It is a modified version of this gist, which helped me overcome my shyness about using Netlink. It really isn't as complex as it seems at first.