linux 指定网卡获取对方(对端)mac地址

一、利用指令查看mac

注意:只有建立过连接的才能查看到对端mac,如果查找不到直接在命令行中ping一下对方ip即可查看到对方mac地址。

  1. arp -a
  2. cat /proc/net/arp

       

linux 指定网卡获取对方(对端)mac地址_第1张图片 图一

 二、通过已建立的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;
}

 

你可能感兴趣的:(linux)