从IP地址查找MAC地址

我正在研究一个具有客户端 – 服务器架构的模块。 我必须根据MAC地址validation连接对等机器。

在安装时,我存储有效MAC地址的加密列表。

请注意,我无法控制此对等计算机,并且某些第三方应用程序将在此运行,我无法在此对等计算机上安装任何应用程序。

在发生套接字连接的运行时,我需要知道连接中使用的IP地址的MAC地址,以便我可以根据先前存储的MAC地址对其进行validation。

是否有可用的C / C ++ API可以帮助我从IP地址获取MAC地址。 这台机器通常连接在局域网中,但它可以在不同的子网上。

我的模块是多平台的,可在Windows,Solaris和Linux上运行,类似地,对等机可以在任何操作系统上运行。

不幸的是,简单的答案实际上是“不要那样做”。

如果你的对等机器在不同的子网上(因此你和对等体之间的流量通过路由器),那么就没有办法做你想要的 – 你收到的数据包的MAC地址将是你的MAC地址将它们转发给您的路由器,因为它是您正在与之通信的链路层设备。 只有离对等机最近的路由器才能知道对等体的MAC地址是什么 – 并且该信息不会被传递。

如果对等计算机位于同一子网上,则传入的数据包将包含以太网报头中对等方的MAC地址……但在将数据包传递到应用程序之前,这将被剥离。 您的选项几乎限于您正在侦听以获取整个数据包的网络接口上的数据包捕获,或者使用系统提供的任何工具来检查本地ARP表。 这两个选项都非常依赖于平台!

此外,如果您正在处理的接口不是以太网接口(也许它们是PPP链接,或者WiFi,或某种类型的时髦虚拟化接口,……),也没有任何选项可能继续工作而不进行修改。他们将与IPv6合作吗?

如果毕竟还没有确定,请查看libpcap / WinPCap进行数据包捕获,这是最容易想到的便携式选项。 要检查本地ARP表,Linux,OS X,Solaris和Windows都提供了一个arp命令行实用程序,但语法可能会有所不同。 如果API可用,我不希望平台之间有任何共性 – 这种事情没有标准,因为你真的不应该这样做!

这是不可能的。 无法保证您的连接对等体甚至具有MAC地址。 对等体完全有可能通过拨号(PPP)或其他非以太网接口连接到网络。

不要通过MAC地址进行身份validation。 很容易欺骗他们。 使用像Chilkat这样的HTTP身份validation库。

正如mcandre所说,欺骗MAC地址非常容易,但仍然回答你的问题,我认为你可以通过BSD风格的套接字在所有操作系统上执行此操作,如果你在同一个局域网上:

以下是此论坛post中的一些示例代码

 #include  #include  #include  #include  #include  #include  #include  int main(int argc, char *argv[]) { struct ifreq ifr; int sock, j, k; char *p, addr[32], mask[32], mac[32]; if (argc<2) { fprintf(stderr,"missing argument, example: eth0\n"); return 1; } sock=socket(PF_INET, SOCK_STREAM, 0); if (-1==sock) { perror("socket() "); return 1; } strncpy(ifr.ifr_name,argv[1],sizeof(ifr.ifr_name)-1); ifr.ifr_name[sizeof(ifr.ifr_name)-1]='\0'; if (-1==ioctl(sock, SIOCGIFADDR, &ifr)) { perror("ioctl(SIOCGIFADDR) "); return 1; } p=inet_ntoa(((struct sockaddr_in *)(&ifr.ifr_addr))->sin_addr); strncpy(addr,p,sizeof(addr)-1); addr[sizeof(addr)-1]='\0'; if (-1==ioctl(sock, SIOCGIFNETMASK, &ifr)) { perror("ioctl(SIOCGIFNETMASK) "); return 1; } p=inet_ntoa(((struct sockaddr_in *)(&ifr.ifr_netmask))->sin_addr); strncpy(mask,p,sizeof(mask)-1); mask[sizeof(mask)-1]='\0'; if (-1==ioctl(sock, SIOCGIFHWADDR, &ifr)) { perror("ioctl(SIOCGIFHWADDR) "); return 1; } for (j=0, k=0; j<6; j++) { k+=snprintf(mac+k, sizeof(mac)-k-1, j ? ":%02X" : "%02X", (int)(unsigned int)(unsigned char)ifr.ifr_hwaddr.sa_data[j]); } mac[sizeof(mac)-1]='\0'; printf("\n"); printf("name: %s\n",ifr.ifr_name); printf("address: %s\n",addr); printf("netmask: %s\n",mask); printf("macaddr: %s\n",mac); printf("\n"); close(sock); return 0; }