一、利用指令查看mac
注意:只有建立过连接的才能查看到对端mac,如果查找不到直接在命令行中ping一下对方ip即可查看到对方mac地址。
- arp -a
- cat /proc/net/arp
![](https://i-blog.csdnimg.cn/blog_migrate/2c95c449c6ff74ad4cf8724297abc308.png)
二、通过已建立的socket获取
注意:net_card_name为网卡的名称,如图一中 Device下的即为各网卡昵称。mac为十六进制总共6个字节,需要转换成字符串的可以用sprintf转换一下就可以。
int from_socket_get_mac( int sock_fd, char *mac, const char* net_card_name )
{
struct arpreq arpreq;
struct sockaddr_in dstadd_in;
socklen_t len = sizeof( struct sockaddr_in );
memset( &arpreq, 0, sizeof( struct arpreq ));
memset( &dstadd_in, 0, sizeof( struct sockaddr_in ));
if( getpeername( sock_fd, (struct sockaddr*)&dstadd_in, &len ) < 0 )
{
perror( "get peer name wrong, %s/n", strerror(errno) );
return -1;
}
else
{
memcpy( ( struct sockaddr_in * )&arpreq.arp_pa, ( struct sockaddr_in * )&dstadd_in, sizeof( struct sockaddr_in ));
strcpy(arpreq.arp_dev, net_card_name);
arpreq.arp_pa.sa_family = AF_INET;
arpreq.arp_ha.sa_family = AF_UNSPEC;
if( ioctl( sock_fd, SIOCGARP, &arpreq ) < 0 )
{
perror( "ioctl SIOCGARP wrong, %s/n", strerror(errno) );
return -1;
}
else
{
unsigned char* ptr = (unsigned char *)arpreq.arp_ha.sa_data;
memcpy(mac,ptr,6);
}
}
return 0;
}
三、通过ip查找MAC
注意:net_card_name为网卡的名称,如图一中 Device下的即为各网卡昵称。mac为十六进制总共6个字节,需要转换成字符串的可以用sprintf转换一下就可以。
static int32_t from_ip_addr_get_mac(int8_t *ip_addr, int8_t* mac,const int8_t* net_card_name )
{
int32_t sockfd;
uint8_t *ptr;
struct arpreq arpreq;
struct sockaddr_in *sin;
struct sockaddr_storage ss;
int8_t addr[INET_ADDRSTRLEN+1];
memset(addr, 0, INET_ADDRSTRLEN+1);
memset(&ss, 0, sizeof(ss));
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd == -1)
{
printf("socket error1\n");
return -1;
}
sin = (struct sockaddr_in *) &ss;
sin->sin_family = AF_INET;
if (inet_pton(AF_INET, (char *)ip_addr, &(sin->sin_addr)) <= 0)
{
close(sockfd);
printf("inet_pton error2\n");
return -1;
}
sin = (struct sockaddr_in *) &arpreq.arp_pa;
memcpy(sin, &ss, sizeof(struct sockaddr_in));
strcpy((char *)arpreq.arp_dev, (char *)net_card_name );
arpreq.arp_ha.sa_family = AF_UNSPEC;
if (ioctl(sockfd, SIOCGARP, &arpreq) < 0)
{
close(sockfd);
printf("ioctl SIOCGARP3\n");
return -1;
}
ptr = (uint8_t *)arpreq.arp_ha.sa_data;
memcpy(mac,ptr,6);
close(sockfd);
return 0;
}
四、通过 proc/net/arp下根据ip地址获取对端mac
注意:net_card_name为网卡的名称,如图一中 Device下的即为各网卡昵称。mac为字符串类型。如果没找到对应mac则将返回NULL;
char * from_arp_file_get_mac(const char *req_ip,uint8_t *get_mac,const char *net_card_name )
{
FILE *proc;
char ip[16];
char name[100];
char mac[18] = {0};
char * reply = NULL;
if (!(proc = fopen("/proc/net/arp", "r")))
{
DEBUG("fopen error!\n");
return NULL;
}
/* Skip first line */
while (!feof(proc) && fgetc(proc) != '\n');
/* Find ip, copy mac in reply */
reply = NULL;
while (!feof(proc) && (fscanf(proc, " %15[0-9.] %*s %*s %17[A-Fa-f0-9:] %*s %s", ip, mac,name) == 3))
{
if (0 == strcmp(ip, req_ip) && 0 == strcmp(name,net_card_name ))
{
memcpy(get_mac,mac,strlen(mac));
reply = get_mac;
break;
}
}
fclose(proc);
return reply;
}