struct arpreq{
struct sockaddr arp_pa; //协议地址
struct sockaddr arp_ha; //硬件地址
int arp_flags;//标志位
struct sockaddr arp_netmask;//网络掩码
char arp_dev[16];
}
#define ATF_COM 0x02 //已完成的邻居 (成员ha有效,且含有正确的MAC地址)
#define ATF_PERM 0x04 //永久性的邻居(邻居状态有NUD_PERMANENT)
#define ATF_PUBL 0x08 //发布该邻居。
#define ATF_USETRAILERS 0x10 //不是非常清楚。
#define ATF_NETMASK 0x20 //仅用于代理ARP。
#define ATF_DONTPUB 0x40 //不处理该邻居。
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/if_ether.h>
char *ip = "192.168.66.1";
int main()
{
int sfd, saved_errno, ret;
unsigned char *mac;
struct arpreq arp_req;
struct sockaddr_in *sin;
sin = (struct sockaddr_in *)&(arp_req.arp_pa);
memset(&arp_req, 0, sizeof(arp_req));
sin->sin_family = AF_INET;
inet_pton(AF_INET, ip, &(sin->sin_addr));
printf("get Arp Entry inet_pton: 0x%x\n", sin->sin_addr.s_addr);
strncpy(arp_req.arp_dev, "eth0", IFNAMSIZ-1);
sfd = socket(AF_INET, SOCK_DGRAM, 0);
saved_errno = errno;
ret = ioctl(sfd, SIOCGARP, &arp_req);
if (ret < 0) {
fprintf(stderr, "Get ARP entry failed : %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
errno = saved_errno;
if (arp_req.arp_flags & ATF_COM) {
mac = (unsigned char *)arp_req.arp_ha.sa_data;
printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
} else {
printf("MAC: Not in the ARP cache.\n");
}
}
获取ARP条目时,需要初始化arp_pa,arp_dev,然后调用ioctl(SIOCGARP),成功返回后arp_pa中包含的IP地址对应的mac地址保存在arp_ha.sa_data中;若指定的网络接口不存在,或存在但与指定的目标主机IP地址不对应,则ioctl以"(ENXIO)No such device or address"错误调用失败无法通过ioctl操作获取整个ARP表,arp(8)命令的-a选项是通过读取系统中的/proc/net/arp文件内容实现该目的。