gpt4 book ai didi

c++ - getnameinfo() 编译时错误 - 在 Linux 中提取 MAC 地址

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:38:34 36 4
gpt4 key购买 nike

我必须向服务器发送我的客户端套接字连接并与服务器通信的网络接口(interface)的 IP 地址和 MAC 地址。所有机器都在内部网上。我已经提取了套接字的 IP,并且正在尝试提取硬件地址。

我的策略:

  1. 使用getsockname() 提取套接字的IP系统调用。
  2. 使用getifaddrs()列出所有可用网络接口(interface)的系统调用。在 for 循环中我使用 getnameinfo()系统调用以查找当前迭代接口(interface)名称的 IP,然后将此 IP 与套接字 IP(从步骤 1 中提取)进行比较以查找已连接套接字的接口(interface)名称。
  3. 使用ioctl(fd, SIOCGIFHWADDR, &ifr)使用在第 2 阶段找到的接口(interface)名称获取硬件地址的系统调用。

我面临问题 getnameinfo()系统调用。

如果我不将第一个参数类型转换为 (struct sockaddr_in*),我会收到以下错误:ai_family not supported

getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in), host, NI_MAXHOST,
NULL, 0, NI_NUMERICHOST);

如果我将第一个参数类型转换为 (struct sockaddr_in*),我会收到以下错误:error: cannot convert ‘sockaddr_in*’ to ‘const sockaddr*’ for argument ‘1’ to ‘int getnameinfo(const sockaddr*, socklen_t, char*, socklen_t, char*, socklen_t, int)’

getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in), host, NI_MAXHOST,
NULL, 0, NI_NUMERICHOST);

多多指教。我什至愿意接受一些替代策略,以编程方式动态获取套接字 IP 和 MAC 地址。

bool Ethernet::getIp(void)
{
struct sockaddr_in addr;
char bufferIp[INET_ADDRSTRLEN];
socklen_t addrLen = sizeof(addr);
if(getsockname(this->clientSocket, (struct sockaddr*) &addr, &addrLen) == -1)
{
string errStr = strerror(errno);
FileOperations fo;
string str;
str = "Unable to extract IP address of socket";
str += " Error : " + errStr;
fo.printError(str);
return RETURN_FAILURE;
}

if(inet_ntop(AF_INET, &addr.sin_addr, bufferIp, INET_ADDRSTRLEN) == NULL)
{
string errStr = strerror(errno);
FileOperations fo;
string str;
str = "Unable to convert extracted IP address from binary to char* in Ethernet::getInterfaceDetails.";
str += " Error : " + errStr;
fo.printError(str);
return RETURN_FAILURE;
}
this->ip = string(bufferIp);
return RETURN_SUCCESS;
}

bool Ethernet::getMac(void)
{
int fd;
struct ifreq ifr;
// char *iface = "eth0";
unsigned char *mac;
fd = socket(AF_INET, SOCK_DGRAM, 0);
ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name , this->interfaceName.c_str(), IFNAMSIZ-1);
ioctl(fd, SIOCGIFHWADDR, &ifr);
close(fd);
mac = (unsigned char *)ifr.ifr_hwaddr.sa_data;

//display mac address
printf("Mac : %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n" , mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
return RETURN_SUCCESS;

}

bool Ethernet::getInterfaceDetails(void)
{
struct ifaddrs *ifaddr, *ifa;
int s;
char host[NI_MAXHOST];
string tempAddr;
char buffer[INET_ADDRSTRLEN];
if (getifaddrs(&ifaddr) == -1)
{
string errStr = strerror(errno);
FileOperations fo;
string str;
str = "System call 'getifaddrs' failed in Ethernet::getInterfaceDetails.";
str += " Error : " + errStr;
fo.printError(str);
return RETURN_FAILURE;
}

for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
{
if (ifa->ifa_addr == NULL)
continue;

this->interfaceName = string(ifa->ifa_name);
if(this->interfaceName == string("lo"))
continue;

s = getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in), host, NI_MAXHOST,
NULL, 0, NI_NUMERICHOST);

if(s != 0)
{
string errStr = gai_strerror(s);
cout << "Error : " << errStr << endl;
FileOperations fo;
string str;
str = "Unable to convert extracted IP address address from binary to char* in Ethernet::getInterfaceDetails.";
str += " Error : " + errStr;
fo.printError(str);
return RETURN_FAILURE;
}
tempAddr = string(host);
if(tempAddr == this->ip)
{
freeifaddrs(ifaddr);
return RETURN_SUCCESS;
}
}
return RETURN_FAILURE;
}

最佳答案

关于您对 getnameinfo 的调用,我看到一件奇怪的事情:您假设非空 ifa_addr 等于 sockaddr_in 类型,但我可以想象你可以获得其他类型,例如sockaddr_in6。所以你应该检查 ifa_addr->sa_family 字段以确保它是 AF_INET。也许您也应该处理 IPv6?

我的理论是调用 getnameinfo 时使用的结构大小与地址族的预期大小不匹配可能是导致错误的原因。

另请参阅 MAC address with getifaddrs进行相关讨论。

关于c++ - getnameinfo() 编译时错误 - 在 Linux 中提取 MAC 地址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45612358/

36 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com