【发布时间】:2018-01-18 14:57:14
【问题描述】:
我必须向服务器发送我的客户端套接字连接并与服务器通信的网络接口的 IP 地址和 MAC 地址。 所有机器都在 Intra-net 上。 我已经提取了我的套接字的 IP,我正在尝试提取 H/W 地址。
我的策略:
- 使用
getsockname()系统调用提取套接字的IP。 - 使用
getifaddrs()系统调用列出所有可用的网络接口。在 for 循环中,我使用getnameinfo()系统调用来查找当前迭代接口名称的 IP,然后将此 IP 与套接字 IP(从步骤 1 中提取)进行比较,以查找已连接套接字的接口名称。 - 使用
ioctl(fd, SIOCGIFHWADDR, &ifr)系统调用,使用在阶段2中找到的接口名称获取硬件地址。
我遇到问题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;
}
【问题讨论】:
-
C 代码在哪里?似乎你在 C++ cast 那里苦苦挣扎。
-
我必须向服务器发送连接我的客户端套接字的网络接口的 IP 地址和 MAC 地址 为什么需要这样做?服务器可以知道您从哪个 IP 地址进行连接,并且它可能也可以访问您的 MAC 地址。这似乎是an XY problem
-
@AndrewHenle 它当然不知道。
-
该程序部署在嵌入式硬件(基于 Linux 的 SBC)上。我被要求提供的 PC 软件开发人员要求提供硬件 IP 和 MAC。
-
@AnttiHaapala 它当然不知道 什么?!?!
getpeername()提供网络连接的远程 IP 地址:“getpeername()函数应检索指定套接字的对等地址 ...” 如果您不这样做,连接 将无法工作知道你在和谁说话。回复数据包如何返回给发送者?
标签: c++ c linux sockets system-calls