zl程序教程

您现在的位置是:首页 >  系统

当前栏目

Linux 下获取LAN中指定IP的网卡的MAC(物理地址)

LinuxIP网卡Mac 获取 指定 LAN 物理地址
2023-09-27 14:29:32 时间

#ifndef _ALL_H
#define _ALL_H

#include memory.h
#include stdio.h
#include stdlib.h
#include sys/ioctl.h
#include sys/types.h
#include sys/socket.h
#include net/if.h
#include string.h
#include errno.h  

// ---------------------
// 创建ARP包的头文件
#include netinet/in.h
#include arpa/inet.h
/* #include linux/if_ether.h */    
#include ctype.h
#include fcntl.h
// ---------------------

#include unistd.h

#include string
#include iostream
using namespace std;


#define MAX_MAC_LEN 24  // MAC字串缓冲区的最大长度(byte)
#define COMPART_MAC ":"  // MAC字串的分格符, Warnning:修改此宏,必须再修改源程序!!!


#endif /* end _ALL_h */

// end file

// -------------------------------------------------------------------------------------------------------------

// main.cpp
// 2005/06/20,a.m. wenxy

#include "all.h"


// function declare
static string GetLocalMac(string strEth); // get loacl NICs MAC
void set_ip_addr(char *,char *);   // 填充IP
void set_hw_addr(char buf[], char *str); // 填充MAC
static string GetMacByIP(string strSrcIP, string strSrcMAC, string strDesIP ,string strNIC); // 获取指定IP的MAC


/*
#define SRC_IP   "10.0.1.77"   // 源IP
#define DES_IP   "10.0.1.35"   // 目的IP
#define LOCAL_HW        "00:C0:4C:39:0D:6F" // 10.0.1.77的eth0的MAC
#define DEVICE          "eth0"    // 接口
*/
#define PADD_MAC  "00:00:00:00:00:00" // 填充的MAC
#define DES_MAC   "FF:FF:FF:FF:FF:FF" // 广播MAC
#define ARP_SEND_COUNT 3     // 发送ARP请求的ARP包的个数


 struct ether_header
 {
  unsigned char  ether_dhost[6];          /* destination eth addr */
  unsigned char  ether_shost[6];          /* source ether addr    */
  unsigned short ether_type;              /* packet type ID field */
 };
 struct arp_header
 {
  unsigned short int ar_hrd;              /* Format of hardware address.  */
  unsigned short int ar_pro;              /* Format of protocol address.  */
  unsigned char ar_hln;                   /* Length of hardware address.  */
  unsigned char ar_pln;                   /* Length of protocol address.  */
  // -------------------------
  unsigned short int ar_op;               /* ARP opcode (command).  */
  unsigned char __ar_sha[6];              /* Sender hardware address.  */
  unsigned char __ar_sip[4];              /* Sender IP address.  */
  unsigned char __ar_tha[6];              /* Target hardware address.  */
  unsigned char __ar_tip[4];              /* Target IP address.  */
  // -------------------------
 };
 struct arp_packet
 {
  struct ether_header ethhdr;
  struct arp_header arphdr;
  unsigned char padding[18];              /* filled with 0 */
 };
 
 /* arp reply:
 *      op = 2
 *      ethhdr.ether_dhost = arphdr.__ar_tha = switch hard addr
 *      ethhdr.ether_shost = arphdr.__ar_sha = local hard addr
 *      arphdr.__ar_tip = switch ip
 *      arphdr.__ar_sip = victim ip
 */
#define FRAME_TYPE      0x0806                  /* arp=0x0806,rarp=0x8035 */
#define HARD_TYPE       1                       /* ethernet is 1 */
#define PROTO_TYPE      0x0800                  /* IP is 0x0800 */
#define OP_CODE         1                       /* arp=1/2,1为请求,2为应答,rarp=3/4 */
   

 
// linux下获取LAN里指定IP的网卡MAC
// In: argv[1]:本机IP,argv[2]:目的IP
// Out: 
int main( int argc, char *argv[] )
{
 string strETH;  // 本机NIC名称
 string strLocalMAC; // 本机MAC
 string strSrcIP; // 本机IP
 string strDesMAC; // 目的MAC
 string strDesIP; // 目的IP
 
 // 检查参数
 if ( argc != 4 )
 {
  printf("Useage: get_mac [interface name of the IP] [IP] [ARP IP]/n/n");
  return 0;
 }  
 strETH = argv[1]; //"eth0";
 strSrcIP = argv[2]; //"10.0.1.77";
 strDesIP = argv[3]; //"10.0.1.69";
 
 printf("Run ....../n");
 printf("获取 %s 接口的MAC ....../n", strETH.c_str());
 // 获取指定NIC名称的MAC
 strLocalMAC = GetLocalMac(strETH); 
#if 0
 printf("Note: %s[%s]/n", strETH.c_str(), strLocalMAC.c_str());
#endif
 
 // 获取指定接口MAC
 if ( 0 == strcmp( (const char*)strLocalMAC.c_str(), (const char*)"") )
 {
  printf("Error: call strcmp() failed/n");
  printf("--------------------------------/n/n");
  return -1;
 }
 else
 {
  printf("获取接口MAC成功: %s [%s]/n", strETH.c_str(), strLocalMAC.c_str()); 
 }
 
 // 获取指定IP网卡的MAC
 strDesMAC = GetMacByIP(strSrcIP, strLocalMAC, strDesIP, strETH);   
 printf("strDesMAC = %s/n", strDesMAC.c_str());
 // 
 return 0;
}


// 获取本地某网卡的MAC
// In: strEth
// Out: 若成功,返回MAC字符串,失败,返回""(空串)
static string GetLocalMac(string strEth)
{
 string strLocalMAC;
 int s;
 struct ifreq buffer;
 char chBuff[MAX_MAC_LEN];
 
 memset(chBuff, 0x0, sizeof(chBuff));
 //arp_process(NULL);   
 s = socket(PF_INET, SOCK_DGRAM, 0); 
 if (-1 == s)
 {
  printf("Error: create socket failture/n");
  printf("--------------------------------/n/n");
  return "";
 }   
 memset( buffer, 0x00, sizeof(buffer));    
 strcpy(buffer.ifr_name, strEth.c_str());  // "eth0"    
 if ( -1 == ioctl(s, SIOCGIFHWADDR, buffer))
 {
  printf("Error: 获取接口 %S MAC 失败/n", strEth.c_str());
  printf("--------------------------------/n/n");
  return "";   
 }    
 close(s);
    
 for( s = 0; s s++ )
 {
  memset(chBuff, 0x0, sizeof(chBuff));
  sprintf( chBuff, "%.2X", (unsigned char)buffer.ifr_hwaddr.sa_data[s]);
  strLocalMAC += chBuff;
  
  //printf("%.2X", (unsigned char)buffer.ifr_hwaddr.sa_data[s]);
  if (s 5)
  {
   memset(chBuff, 0x0, sizeof(chBuff));
   sprintf( chBuff, "%s", COMPART_MAC);
   strLocalMAC += chBuff;
   //printf(":");
  }
 }    
 //printf("/n");
    
 return strLocalMAC; 
}


//-------------------------------------------------------
// 发送ARP包,并接收ARP应答包,取出MAC
// In: strSrcIP:本机IP,strSrcMAC:本机IP的MAC,strDesIP:被请求应答MAC的IP , strNIC:本地接口名
// Out: 若成功,返回MAC,失败返回""(空串)
static string GetMacByIP(string strSrcIP, string strSrcMAC, string strDesIP ,string strNIC)
{
 int sockfd;     // socket handle
 struct arp_packet arp;  // arp 请求包
 struct arp_packet arpRes; // arp 应用答包
 struct sockaddr sa;   // eth
 
 char chSrcIP[24];
 char chDesIP[24];
 char chSrcMAC[24];
 char chNIC[8];    
 memset(chSrcIP, 0x00, sizeof(chSrcIP));
 memset(chDesIP, 0x00, sizeof(chDesIP));
 memset(chSrcMAC, 0x00, sizeof(chSrcMAC));
 memset(chNIC, 0x00, sizeof(chNIC));
 sprintf(chSrcIP, "%s",  strSrcIP.c_str());
 sprintf(chDesIP, "%s",  strDesIP.c_str());
 sprintf(chSrcMAC, "%s", strSrcMAC.c_str());
 sprintf(chNIC, "%s", strNIC.c_str()); 
 #define SRC_IP   chSrcIP  // 源IP
 #define DES_IP   chDesIP  // 目的IP
 #define LOCAL_HW        chSrcMAC // eth0的MAC 
 #define DEVICE   chNIC  // 本机接口名
  
 memset( arp, 0x00, sizeof(arp));
 memset( arpRes, 0x00, sizeof(arpRes));
 #if 1
 printf("源IP[%s]  源MAC[%s] 目的IP[%s]/n", /
   strSrcIP.c_str(), strSrcMAC.c_str(), strDesIP.c_str());  
 #endif
 
 sockfd = socket(AF_INET, SOCK_PACKET, htons(0x0806));
 if(sockfd 0)
 {
  printf("Error: create socket failed/n");
  printf("--------------------------------/n/n");   
  return "";
 }
 
 /*
 // 设置socket为非阻塞模式
 if ( -1 != fcntl(sockfd, F_SETFL, O_NONBLOCK) )
 {
  printf("设置socket为非阻塞模式成功/n");
 }
 else
 {
  printf("Warning: 设置socket为非阻塞模式失败[errno = %d]/n", errno);
 }
 */
 
 // 设置socket接收超时
 struct timeval tv;
 tv.tv_sec = 0;
 tv.tv_usec= 100;
 if ( 0 == setsockopt( sockfd, SOL_SOCKET, SO_RCVTIMEO, tv, sizeof(tv)) )
 {
  printf("设置socket接收超时成功/n"); 
 }
 else
 {
  printf("Warning: 设置socket接收超时失败[errno = %d]/n", errno);
 }
 #if 1
 printf("创建socket SOCK_PACKET 成功/n");
 printf("Note: 创建ARP请求包 ....../n");
 printf("--------------------------------/n/n"); 
 #endif
 
 // 创建ARP请求包 
 /* init arp packet header */
 arp.ethhdr.ether_type = htons(FRAME_TYPE);
 set_hw_addr( (char *)arp.ethhdr.ether_dhost, DES_MAC );  
 set_hw_addr( (char *)arp.ethhdr.ether_shost, LOCAL_HW );
 #if 1
 printf("%x|", arp.ethhdr.ether_type);
 for (int i = 0; i i++)
 {
  printf("%d_", arp.ethhdr.ether_dhost[i]);  
 }
 printf("|");
 for (int i = 0; i i++)
 {
  printf("%d_", arp.ethhdr.ether_shost[i]);  
 } 
 printf("/n--------------------------------/n"); 
 printf("初始化ARP包帧头(以太网首部)成功/n/n");  
 #endif 
  
 /* init arp packet data */ 
 printf("初始化ARP包帧数据(ARP请求分组) ....../n"); 
 printf("--------------------------------/n"); 
 arp.arphdr.ar_hrd = htons(HARD_TYPE); // 1
 arp.arphdr.ar_pro = htons(PROTO_TYPE); // 0x0800
 arp.arphdr.ar_op = htons(OP_CODE);  // 1
 arp.arphdr.ar_hln = (unsigned char)(6);
 arp.arphdr.ar_pln = (unsigned char)(4);
 #if 1
 printf("%d|%d|%d|%d|%d|/n", arp.arphdr.ar_hrd, arp.arphdr.ar_pro, /
   arp.arphdr.ar_op, arp.arphdr.ar_hln, arp.arphdr.ar_pln);
 printf("--------------------------------/n");    
 #endif
 
 set_hw_addr((char *)arp.arphdr.__ar_tha, DES_MAC); // 请求IP的MAC 
 set_hw_addr((char *)arp.arphdr.__ar_sha, LOCAL_HW); // 发送者的MAC 
 set_ip_addr((char *)arp.arphdr.__ar_tip, DES_IP); // 请求MAC的IP 
 set_ip_addr((char *)arp.arphdr.__ar_sip, SRC_IP); // 源IP
 bzero(arp.padding, 18); // 填充18个字节
 #if 1 
 for (int i = 0; i i++)
 {
  printf("%d_", arp.arphdr.__ar_sha[i]);  
 }
 printf("|");
 for (int i = 0; i i++)
 {
  printf("%d_", arp.arphdr.__ar_sip[i]);  
 }
 printf("|"); 
 for (int i = 0; i i++)
 {
  printf("%d_", arp.arphdr.__ar_tha[i]);  
 }
 printf("|");

 for (int i = 0; i i++)
 {
  printf("%d_", arp.arphdr.__ar_tip[i]);  
 }
 printf("|");
 printf("/n--------------------------------/n");  
 #endif
  
 /* send arp reply packet */
 memset( sa, 0x00, sizeof(sa));
 strcpy(sa.sa_data, DEVICE);
 
 // 发送ARP包
 int nSendCount = ARP_SEND_COUNT;
 while( (nSendCount --) 0)
 {
  printf("发送ARP请求包[%d Bytes]...... [第%d个]/n", sizeof(arp), nSendCount);   
  if( sendto(sockfd, arp, sizeof(arp), 0, (struct sockaddr*) sa, sizeof(sa)) 0 )
  {
   printf("Error: 发送ARP包失败 [errno = %d]/n", errno);
   return "";
  }
 }
 
 // 接收ARP应答包
 printf("NOte: 接收ARP应答 ....../n");
 int nTryCount = 5;
 int nRecvByte = 0;
 int nAddrLen = sizeof(sa);
 do
 {
  nRecvByte = recvfrom(sockfd, arpRes, sizeof(arpRes),0, (struct sockaddr*) sa, (socklen_t*) nAddrLen); 
  
  // 若是所请求IP的ARP应答包,退出while
  string strTarIP;  /* Target IP address */
  if ( nRecvByte = 60 2 == ntohs(arpRes.arphdr.ar_op) )
  {
   char chBuff[MAX_MAC_LEN];   
   string strTarIP;  /* Target IP address */
   // 格式化IP
   for (int s = 0; s s++)
   {
    memset(chBuff, 0x00, sizeof(chBuff));
    sprintf( (char *)chBuff, "%d", (unsigned char)arpRes.arphdr.__ar_sip[s]);
    strTarIP += chBuff;
    if (s 3)
    {
     memset(chBuff, 0x00, sizeof(chBuff));
     sprintf( (char *)chBuff, "%s", ".");
     strTarIP += chBuff;
    }
   }
   if ( !strcmp(strTarIP.c_str(), strDesIP.c_str()) )
   {
    printf("/n请求IP[%s] = 应答IP[%s]/n", strDesIP.c_str(), strTarIP.c_str());
    break;
   }
  }
 }while( nTryCount -- ); // 接收ARP应答包的次数
 printf("已接收到ARP应答包 [%d Bytes]/n", nRecvByte);
 // 接收超时,或错误
 if ( nRecvByte == -1 )
 {
  printf("Warning: 接收超时,或计算机[%s]没有响应/n", strDesIP.c_str());
  close(sockfd);
  return "";
 }
 
 printf("分析ARP应答包 ....../n"); 
 char chBuff[MAX_MAC_LEN];   
 string strTarIP;  /* Target IP address */
 string strTarMAC;  /* Target hardware address */
 memset(chBuff, 0x00, sizeof(chBuff));
 // 格式化IP
 for (int s = 0; s s++)
 {
  memset(chBuff, 0x00, sizeof(chBuff));
  sprintf( (char *)chBuff, "%d", (unsigned char)arpRes.arphdr.__ar_sip[s]);
  strTarIP += chBuff;
  if (s 3)
  {
   memset(chBuff, 0x00, sizeof(chBuff));
   sprintf( (char *)chBuff, "%s", ".");
   strTarIP += chBuff;
  }
 } 
 // 格式化MAC
 memset(chBuff, 0x00, sizeof(chBuff));
 for (int s = 0; s s++)
 {
  memset(chBuff, 0x00, sizeof(chBuff));
  sprintf( (char *)chBuff, "%02X", (unsigned char)arpRes.arphdr.__ar_sha[s]);
  strTarMAC += chBuff;
  if (s 5)
  {
   memset(chBuff, 0x00, sizeof(chBuff));
   sprintf( (char *)chBuff, "%s", COMPART_MAC);
   strTarMAC += chBuff;
  }
 }
 // 输出目的IP,目的MAC  
 printf("应答IP[%s] 对应的MAC[%s]/n", strTarIP.c_str(), strTarMAC.c_str());
 printf("/n--------------------------------/n/n");
 close(sockfd); 
 // 返回被请求的MAC 
 return strTarMAC; 
 /* return */
}
    
    
// 填充MAC   
void set_hw_addr (char buf[], char *str)
{
              int i;
              char c, val;
              for(i = 0; i i++)
              {
                      if (!(c = tolower(*str++)))
                              perror("Invalid hardware address"),exit(1);
                     if (isdigit(c))
                             val = c - 0;
                     else if (c = a c = f)
                             val = c-a+10;
                     else
                             perror("Invalid hardware address"),exit(1);
                     buf[i] = val 4;
                     if (!(c = tolower(*str++)))
                             perror("Invalid hardware address"),exit(1);
                     if (isdigit(c))
                             val = c - 0;
                     else if (c = a c = f)
                             val = c-a+10;
                     else
                             perror("Invalid hardware address"),exit(1);
                     buf[i] |= val;
                     if (*str == :)
                             str++;
             }
}
 

// 填充IP
void set_ip_addr(char *buf, char *str)
{
  struct in_addr addr;
  memset( addr, 0x00, sizeof(addr));
  addr.s_addr = inet_addr(str);  
  memcpy(buf, addr, 4);
}

//-------------------------------------------------------


// end file

// --------------------------------------------------------------------------------------------------------------

# makefile

bin = get_mac
objets = main.o
rubbish = $(objets) $(bin)

$(bin) : main.o
 g++ -o $(bin) main.o

main.o : main.cpp all.h
 g++ -c main.cpp


.PHONY : clean
clean :
 -rm $(rubbish) 


# end makefile

 

/******************************************************************************/


/* 时光飞快流逝,2005年写的代码, 2005年是我工作2年后。7年后又可以重用, 我重新修改成C代码。*/

 

 


/*******************************************************************************  * File: main.c  * Description:   * Author: Xiaoyong Wen  wen_kernel@163.com , 2005/06/20,a.m.  * Fix hisoty:  * v1.1.0    Xiaoyong Wen  wen_kernel@163.com , 20130808, p.m., Reconstruct to c code  *******************************************************************************/   #define DEBUG   /* show debug info only */   #if defined(DEBUG)   #define wenxy_debug(fmt, args...) \       printf(fmt, ##args)   #else   #define wenxy_debug(fmt, ...)    #endif   #include  unistd.h    #include  memory.h    #include  stdio.h    #include  stdlib.h    #include  sys/ioctl.h    #include  sys/types.h    #include  sys/socket.h    #include  net/if.h    #include  string.h    #include  errno.h     // ---------------------   // 创建ARP包的头文件   #include netinet/in.h    #include arpa/inet.h    /* #include linux/if_ether.h  */      #include ctype.h    #include  fcntl.h    // ---------------------   #define MAX_MAC_LEN 24  // MAC字串缓冲区的最大长度(byte)   #define COMPART_MAC ":"  // MAC字串的分格符, Warnning:修改此宏,必须再修改源程序!!!   #define MAX_BUF_LEN 128   static char strETH[MAX_BUF_LEN] = {0};      // 本机NIC名称   static char strLocalMAC[MAX_BUF_LEN] = {0}; // 本机MAC   static char strSrcIP[MAX_BUF_LEN] = {0};    // 本机IP   static char strDesMAC[MAX_BUF_LEN] = {0};   // 目的MAC   static char strDesIP[MAX_BUF_LEN] = {0};    // 目的IP   static char strTarIP[MAX_BUF_LEN] = {0};  /* Target IP address */   static char strTarMAC[MAX_BUF_LEN] = {0};  /* Target hardware address */   static int find_ip_flag = 0;     /* 1 means find, 0 means not find */   // function declare   static char * GetLocalMac(char *strEth); // get loacl NICs MAC   static void set_ip_addr(char *,char *);   // 填充IP   static void set_hw_addr(char buf[], char *str); // 填充MAC   static char * GetMacByIP(char *strSrcIP, char *strSrcMAC, char *strDesIP ,char *strNIC); // 获取指定IP的MAC   int arp_main( char *nic_name, char *nic_ip, char *des_ip);   #define SRC_IP   "10.0.1.77"   // 源IP  #define DES_IP   "10.0.1.35"   // 目的IP  #define LOCAL_HW        "00:C0:4C:39:0D:6F" // 10.0.1.77的eth0的MAC  #define DEVICE          "eth0"    // 接口  #define PADD_MAC  "00:00:00:00:00:00"   // 填充的MAC   #define DES_MAC   "FF:FF:FF:FF:FF:FF"   // 广播MAC   #define ARP_SEND_COUNT 3                // 发送ARP请求的ARP包的个数   #define RX_ARP_COUNT 3                  // rx count of ARP response   #define SLEEP_MAX_US (1000 * 100)       /* unit microsecond */   struct ether_header       unsigned char  ether_dhost[6];          /* destination eth addr */       unsigned char  ether_shost[6];          /* source ether addr    */       unsigned short ether_type;              /* packet type ID field */   struct arp_header       unsigned short int ar_hrd;              /* Format of hardware address.  */       unsigned short int ar_pro;              /* Format of protocol address.  */       unsigned char ar_hln;                   /* Length of hardware address.  */       unsigned char ar_pln;                   /* Length of protocol address.  */       // -------------------------       unsigned short int ar_op;               /* ARP opcode (command).  */       unsigned char __ar_sha[6];              /* Sender hardware address.  */       unsigned char __ar_sip[4];              /* Sender IP address.  */       unsigned char __ar_tha[6];              /* Target hardware address.  */       unsigned char __ar_tip[4];              /* Target IP address.  */       // -------------------------   struct arp_packet       struct ether_header ethhdr;       struct arp_header arphdr;       unsigned char padding[18];              /* filled with 0 */   /* arp reply:  *      op = 2  *      ethhdr.ether_dhost = arphdr.__ar_tha = switch hard addr  *      ethhdr.ether_shost = arphdr.__ar_sha = local hard addr  *      arphdr.__ar_tip = switch ip  *      arphdr.__ar_sip = victim ip  #define FRAME_TYPE      0x0806                  /* arp=0x0806,rarp=0x8035 */   #define HARD_TYPE       1                       /* ethernet is 1 */   #define PROTO_TYPE      0x0800                  /* IP is 0x0800 */   #define OP_CODE         1                       /* arp=1/2,1为请求,2为应答,rarp=3/4 */   int main( int argc, char *argv[] )       // 检查参数       if ( argc != 4 )       {           wenxy_debug("Useage: %s [interface name of the IP] [IP] [ARP IP]\n\n", argv[0]);           return 0;       }         return arp_main( argv[1], argv[2], argv[3] );   // linux下获取LAN里指定IP的网卡MAC   // In: nic_name: 本地网卡名字, nic_ip:本机IP,des_ip:目的IP   // Out: 1表示获取MAC成功,des_ip已被使用, -1表示发生错误,0表示des_ip未使用   int arp_main( char *nic_name, char *nic_ip, char *des_ip)       strcpy(strETH, nic_name); //"eth0";       strcpy(strSrcIP, nic_ip); //"10.0.1.77";       strcpy(strDesIP, des_ip); //"10.0.1.69";              wenxy_debug("Run ......\n");       wenxy_debug("获取 %s 接口的MAC ......\n", strETH);       // 获取指定NIC名称的MAC       /*strLocalMAC = GetLocalMac(strETH);*/       GetLocalMac(strETH);          #if 0       wenxy_debug("Note: %s[%s]\n", strETH, strLocalMAC);   #endif              // 获取指定接口MAC       if ( 0 == strcmp( (const char*)strLocalMAC, (const char*)"") )       {           wenxy_debug("Error: call strcmp() failed\n");           wenxy_debug("--------------------------------\n\n");           return -1;       }       else       {           wenxy_debug("获取接口MAC成功: %s [%s]\n", strETH, strLocalMAC);       }              // 获取指定IP网卡的MAC       /*strDesMAC = GetMacByIP(strSrcIP, strLocalMAC, strDesIP, strETH);*/       GetMacByIP(strSrcIP, strLocalMAC, strDesIP, strETH);       wenxy_debug("strDesMAC = %s\n", strDesMAC);       if(1 == find_ip_flag)       {           printf("Note:  strDesIP: %s,  strDesMAC: %s\n", strDesIP, strDesMAC);           return 1;       }       else       {           printf("Note:  strDesIP: %s does not use\n", strDesIP);           return 0;       }   // 获取本地某网卡的MAC   // In: strEth   // Out: 若成功,返回MAC字符串,失败,返回""(空串)   static char * GetLocalMac(char *strEth)       int s;       struct ifreq buffer;       char chBuff[MAX_MAC_LEN];       unsigned int str_len = 0;       unsigned int offset = 0;              memset(chBuff, 0x0, sizeof(chBuff));       //arp_process(NULL);          s = socket(PF_INET, SOCK_DGRAM, 0);        if (-1 == s)       {           wenxy_debug("Error: create socket failture\n");           wenxy_debug("--------------------------------\n\n");           return "";       }          memset( buffer, 0x00, sizeof(buffer));           strcpy(buffer.ifr_name, strEth);  // "eth0"           if ( -1 == ioctl(s, SIOCGIFHWADDR,  buffer))       {           wenxy_debug("Error: 获取接口 %s MAC 失败\n", strEth);           wenxy_debug("--------------------------------\n\n");           return "";          }           close(s);       offset = 0;       for( s = 0; s   s++ )       {           memset(chBuff, 0x0, sizeof(chBuff));           sprintf( chBuff, "%.2X", (unsigned char)buffer.ifr_hwaddr.sa_data[s]);           str_len = strlen(chBuff);           memcpy(strLocalMAC + offset, chBuff, str_len);           offset += str_len;           //wenxy_debug("%.2X", (unsigned char)buffer.ifr_hwaddr.sa_data[s]);           if (s   5)           {               memset(chBuff, 0x0, sizeof(chBuff));               sprintf( chBuff, "%s", COMPART_MAC);               str_len = strlen(chBuff);               memcpy(strLocalMAC + offset, chBuff, str_len);               offset += str_len;               //wenxy_debug(":");           }       }           //wenxy_debug("\n");       return strLocalMAC;    //-------------------------------------------------------   // 发送ARP包,并接收ARP应答包,取出MAC   // In: strSrcIP:本机IP,strSrcMAC:本机IP的MAC,strDesIP:被请求应答MAC的IP , strNIC:本地接口名   // Out: 若成功,返回MAC,失败返回""(空串)   static char * GetMacByIP(char *strSrcIP, char *strSrcMAC, char *strDesIP, char *strNIC)       int sockfd;     // socket handle       struct arp_packet arp;  // arp 请求包       struct arp_packet arpRes; // arp 应用答包       struct sockaddr sa;   // eth              char chSrcIP[24];       char chDesIP[24];       char chSrcMAC[24];       char chNIC[8];       unsigned int str_len = 0;       unsigned int offset = 0;       int i;       int s;       find_ip_flag = 0;              memset(chSrcIP, 0x00, sizeof(chSrcIP));       memset(chDesIP, 0x00, sizeof(chDesIP));       memset(chSrcMAC, 0x00, sizeof(chSrcMAC));       memset(chNIC, 0x00, sizeof(chNIC));       sprintf(chSrcIP, "%s",  strSrcIP);       sprintf(chDesIP, "%s",  strDesIP);       sprintf(chSrcMAC, "%s", strSrcMAC);       sprintf(chNIC, "%s", strNIC);    #define SRC_IP   chSrcIP  // 源IP   #define DES_IP   chDesIP  // 目的IP   #define LOCAL_HW        chSrcMAC // eth0的MAC    #define DEVICE   chNIC  // 本机接口名              memset( arp, 0x00, sizeof(arp));       memset( arpRes, 0x00, sizeof(arpRes));   #if 1       wenxy_debug("源IP[%s]  源MAC[%s] 目的IP[%s]\n", strSrcIP, strSrcMAC, strDesIP);     #endif              sockfd = socket(AF_INET, SOCK_PACKET, htons(0x0806));       if(sockfd   0)       {           wenxy_debug("Error: create socket failed\n");           wenxy_debug("--------------------------------\n\n");              return "";       }              /*      // 设置socket为非阻塞模式      if ( -1 != fcntl(sockfd, F_SETFL, O_NONBLOCK) )      {      wenxy_debug("设置socket为非阻塞模式成功\n");      }      else      {      wenxy_debug("Warning: 设置socket为非阻塞模式失败[errno = %d]\n", errno);      }      */              // 设置socket接收超时       struct timeval tv;       tv.tv_sec = 0;       tv.tv_usec= 100;       if ( 0 == setsockopt( sockfd, SOL_SOCKET, SO_RCVTIMEO,  tv, sizeof(tv)) )       {           wenxy_debug("设置socket接收超时成功\n");        }       else       {           wenxy_debug("Warning: 设置socket接收超时失败[errno = %d]\n", errno);       }   #if 1       wenxy_debug("创建socket SOCK_PACKET 成功\n");       wenxy_debug("Note: 创建ARP请求包 ......\n");       wenxy_debug("--------------------------------\n\n");    #endif              // 创建ARP请求包        /* init arp packet header */       arp.ethhdr.ether_type = htons(FRAME_TYPE);       set_hw_addr( (char *)arp.ethhdr.ether_dhost, DES_MAC );         set_hw_addr( (char *)arp.ethhdr.ether_shost, LOCAL_HW );   #if 1       wenxy_debug("%x|", arp.ethhdr.ether_type);       for (i = 0; i   i++)       {           wenxy_debug("%d_", arp.ethhdr.ether_dhost[i]);         }       wenxy_debug("|");       for (i = 0; i   i++)       {           wenxy_debug("%d_", arp.ethhdr.ether_shost[i]);         }        wenxy_debug("\n--------------------------------\n");        wenxy_debug("初始化ARP包帧头(以太网首部)成功\n\n");     #endif               /* init arp packet data */        wenxy_debug("初始化ARP包帧数据(ARP请求分组) ......\n");        wenxy_debug("--------------------------------\n");        arp.arphdr.ar_hrd = htons(HARD_TYPE); // 1       arp.arphdr.ar_pro = htons(PROTO_TYPE); // 0x0800       arp.arphdr.ar_op = htons(OP_CODE);  // 1       arp.arphdr.ar_hln = (unsigned char)(6);       arp.arphdr.ar_pln = (unsigned char)(4);   #if 1       wenxy_debug("%d|%d|%d|%d|%d|\n", arp.arphdr.ar_hrd, arp.arphdr.ar_pro,            arp.arphdr.ar_op, arp.arphdr.ar_hln, arp.arphdr.ar_pln);       wenxy_debug("--------------------------------\n");       #endif              set_hw_addr((char *)arp.arphdr.__ar_tha, DES_MAC); // 请求IP的MAC        set_hw_addr((char *)arp.arphdr.__ar_sha, LOCAL_HW); // 发送者的MAC        set_ip_addr((char *)arp.arphdr.__ar_tip, DES_IP); // 请求MAC的IP        set_ip_addr((char *)arp.arphdr.__ar_sip, SRC_IP); // 源IP       bzero(arp.padding, 18); // 填充18个字节   #if 1       for (i = 0; i   i++)       {           wenxy_debug("%d_", arp.arphdr.__ar_sha[i]);         }       wenxy_debug("|");       for (i = 0; i   i++)       {           wenxy_debug("%d_", arp.arphdr.__ar_sip[i]);         }       wenxy_debug("|");        for (i = 0; i   i++)       {           wenxy_debug("%d_", arp.arphdr.__ar_tha[i]);         }       wenxy_debug("|");              for (i = 0; i   i++)       {           wenxy_debug("%d_", arp.arphdr.__ar_tip[i]);         }       wenxy_debug("|");       wenxy_debug("\n--------------------------------\n");     #endif              /* send arp reply packet */       memset( sa, 0x00, sizeof(sa));       strcpy(sa.sa_data, DEVICE);              // 发送ARP包       int nSendCount = ARP_SEND_COUNT;       int nRecvByte = 0;       while( (nSendCount --)   0)       {           wenxy_debug("发送ARP请求包[%d Bytes]...... [第%d个]\n", sizeof(arp), nSendCount);              if( sendto(sockfd,  arp, sizeof(arp), 0, (struct sockaddr*)  sa, sizeof(sa))   0 )           {               wenxy_debug("Error: 发送ARP包失败 [errno = %d]\n", errno);               return "";           }           // 接收ARP应答包           wenxy_debug("Note: 接收ARP应答 ......\n");           int nTryCount = RX_ARP_COUNT;           int nAddrLen = sizeof(sa);             do           {               /* because network and host delay */               usleep(SLEEP_MAX_US);                              nRecvByte = recvfrom(sockfd,  arpRes, sizeof(arpRes),0, (struct sockaddr*) sa, (socklen_t*) nAddrLen);                           // 若是所请求IP的ARP应答包,退出while               if ( nRecvByte  = 60   2 == ntohs(arpRes.arphdr.ar_op) )               {                   char chBuff[MAX_MAC_LEN];                      // 格式化IP                   offset = 0;                   for (s = 0; s   s++)                   {                       memset(chBuff, 0x00, sizeof(chBuff));                       sprintf( (char *)chBuff, "%d", (unsigned char)arpRes.arphdr.__ar_sip[s]);                       //wenxy_debug("chBuff: %s\n", chBuff);                       //strTarIP += chBuff;                       str_len = strlen(chBuff);                       memcpy(strTarIP + offset, chBuff, str_len);                       offset += str_len;                       if (s   3)                       {                           memset(chBuff, 0x00, sizeof(chBuff));                           sprintf( (char *)chBuff, "%s", ".");                           //strTarIP += chBuff;                           str_len = 1;                           memcpy(strTarIP + offset, chBuff, str_len);                           offset += str_len;                       }                   }                                      if ( !strcmp(strTarIP, strDesIP) )                   {                       wenxy_debug("\n请求IP[%s] = 应答IP[%s]\n", strDesIP, strTarIP);                       find_ip_flag = 1; /* find ip */                       goto analyse_arp_response;                   }               }           }while( nTryCount -- ); // 接收ARP应答包的次数       }       analyse_arp_response:       wenxy_debug("已接收到ARP应答包 [%d Bytes]\n", nRecvByte);       // 接收超时,或错误       if ( nRecvByte == -1 )       {           wenxy_debug("Warning: 接收超时,或计算机[%s]没有响应\n", strDesIP);           close(sockfd);           return "";       }              wenxy_debug("分析ARP应答包 ......\n");        char chBuff[MAX_MAC_LEN];          memset(chBuff, 0x00, sizeof(chBuff));       // 格式化IP       offset = 0;       for (s = 0; s   s++)       {           memset(chBuff, 0x00, sizeof(chBuff));           sprintf( (char *)chBuff, "%d", (unsigned char)arpRes.arphdr.__ar_sip[s]);           //strTarIP += chBuff;           str_len = strlen(chBuff);           memcpy(strTarIP + offset, chBuff, str_len);           offset += str_len;           if (s   3)           {               memset(chBuff, 0x00, sizeof(chBuff));               sprintf( (char *)chBuff, "%s", ".");               //strTarIP += chBuff;               str_len = strlen(chBuff);               memcpy(strTarIP + offset, chBuff, str_len);               offset += str_len;           }       }        // 格式化MAC       memset(chBuff, 0x00, sizeof(chBuff));       offset = 0;       for (s = 0; s   s++)       {           memset(chBuff, 0x00, sizeof(chBuff));           sprintf( (char *)chBuff, "%02X", (unsigned char)arpRes.arphdr.__ar_sha[s]);           //strTarMAC += chBuff;           str_len = strlen(chBuff);           memcpy(strTarMAC + offset, chBuff, str_len);           offset += str_len;           if (s   5)           {               memset(chBuff, 0x00, sizeof(chBuff));               sprintf( (char *)chBuff, "%s", COMPART_MAC);               //strTarMAC += chBuff;               str_len = strlen(chBuff);               memcpy(strTarMAC + offset, chBuff, str_len);               offset += str_len;           }       }       // 输出目的IP,目的MAC         wenxy_debug("应答IP[%s] 对应的MAC[%s]\n", strTarIP, strTarMAC);       wenxy_debug("\n--------------------------------\n\n");       close(sockfd);        // 返回被请求的MAC        strcpy(strDesMAC, strTarMAC);       /* return */               return strDesMAC;    // 填充MAC     static void set_hw_addr (char buf[], char *str)       int i;       char c, val;       for(i = 0; i   i++)       {           if (!(c = tolower(*str++)))               perror("Invalid hardware address"),exit(1);           if (isdigit(c))               val = c - 0;           else if (c  = a   c  = f)               val = c-a+10;           else               perror("Invalid hardware address"),exit(1);           buf[i] = val   4;           if (!(c = tolower(*str++)))               perror("Invalid hardware address"),exit(1);           if (isdigit(c))               val = c - 0;           else if (c  = a   c  = f)               val = c-a+10;           else               perror("Invalid hardware address"),exit(1);           buf[i] |= val;           if (*str == :)               str++;       }   // 填充IP   static void set_ip_addr(char *buf, char *str)       struct in_addr addr;       memset( addr, 0x00, sizeof(addr));       addr.s_addr = inet_addr(str);         memcpy(buf,  addr, 4);   //-------------------------------------------------------   // end file  
################################################################################   # File: Makefile   # Description:    # Author: Xiaoyong Wen  wen_kernel@163.com , 20130807, AM.   # Fix hisoty:   ################################################################################   debug := 1   ifdef debug   CFLAGS += -g   else   CFLAGS += -O2   endif   #CC := g++   CC := gcc   target_bin := lan_mac_scan   bin := main   obj := main.o   #src := main.c   src := $(wildcard *.c) $(wildcard *.h)   .PHONY : clean all debug   all : $(bin)       cp main $(target_bin)       @-ls -l $(target_bin)   $(bin) : $(obj)   $(obj) : $(src)   debug:       @echo $(src)       @echo $(obj)       @echo $(CFLAGS)        @echo $(LDFLAGS)    clean:         rm -f $(bin) $(obj) $(target_bin)  

Useage: ./lan_mac_scan [interface name of the IP] [IP] [ARP IP]

#./lan_mac_scan 本地网卡名字 本地网卡的IP地址 检查是否使用的IP地址
例如:
#./lan_mac_scan eth0 172.22.0.26 172.22.0.25

注意事项:
1. Unix类操作系统的内核已支持packet socket。
2. 需要root权限。
3. 只能在LAN中使用,ARP包不能跨越router,除非router上有ARP proxy.
4. 如果本地机器或者远程机器安装有firewall,ARP包会被过滤而失效。


Mac虚拟机设置静态IP 我们经常在做开发的时候都需要模拟生产环境, 但是一台真正的服务器显然不适合我们做开发, 因为我们要经常切换环境, 部署东西, 卸载东西, 此时就有了虚拟机, 但我们经常会遇到这样的问题, 虚拟机关机后或者电脑断网后虚拟机的IP地址就会变, 而我们在项目中设置的IP地址也就得改, 我们ssh工具还得重新输入一次IP进行连接, 所以我们需要设置静态IP