// all.h
// 2005/06/20,a.m. wenxy

#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 NIC's 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 < 6; 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 < 6; i++)
 {
  printf("%d_", arp.ethhdr.ether_dhost[i]);  
 }
 printf("|");
 for (int i = 0; i < 6; 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 < 6; i++)
 {
  printf("%d_", arp.arphdr.__ar_sha[i]);  
 }
 printf("|");
 for (int i = 0; i < 6; i++)
 {
  printf("%d_", arp.arphdr.__ar_sip[i]);  
 }
 printf("|"); 
 for (int i = 0; i < 6; i++)
 {
  printf("%d_", arp.arphdr.__ar_tha[i]);  
 }
 printf("|");

for (int i = 0; i < 6; 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 < 4; 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 < 4; 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 < 6; 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 < 6; 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代码。*/

  1. /*******************************************************************************
  2. * File: main.c
  3. * Description:
  4. * Author: Xiaoyong Wen <wen_kernel@163.com>, 2005/06/20,a.m.
  5. *
  6. * Fix hisoty:
  7. * v1.1.0    Xiaoyong Wen <wen_kernel@163.com>, 20130808, p.m., Reconstruct to c code
  8. *
  9. *******************************************************************************/
  10. #define DEBUG   /* show debug info only */
  11. #if defined(DEBUG)
  12. #define wenxy_debug(fmt, args...) \
  13. printf(fmt, ##args)
  14. #else
  15. #define wenxy_debug(fmt, ...)
  16. #endif
  17. #include <unistd.h>
  18. #include <memory.h>
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <sys/ioctl.h>
  22. #include <sys/types.h>
  23. #include <sys/socket.h>
  24. #include <net/if.h>
  25. #include <string.h>
  26. #include <errno.h>
  27. // ---------------------
  28. // 创建ARP包的头文件
  29. #include<netinet/in.h>
  30. #include<arpa/inet.h>
  31. /* #include<linux/if_ether.h> */
  32. #include<ctype.h>
  33. #include <fcntl.h>
  34. // ---------------------
  35. #define MAX_MAC_LEN 24  // MAC字串缓冲区的最大长度(byte)
  36. #define COMPART_MAC ":"  // MAC字串的分格符, Warnning:修改此宏,必须再修改源程序!!!
  37. #define MAX_BUF_LEN 128
  38. static char strETH[MAX_BUF_LEN] = {0};      // 本机NIC名称
  39. static char strLocalMAC[MAX_BUF_LEN] = {0}; // 本机MAC
  40. static char strSrcIP[MAX_BUF_LEN] = {0};    // 本机IP
  41. static char strDesMAC[MAX_BUF_LEN] = {0};   // 目的MAC
  42. static char strDesIP[MAX_BUF_LEN] = {0};    // 目的IP
  43. static char strTarIP[MAX_BUF_LEN] = {0};  /* Target IP address */
  44. static char strTarMAC[MAX_BUF_LEN] = {0};  /* Target hardware address */
  45. static int find_ip_flag = 0;     /* 1 means find, 0 means not find */
  46. // function declare
  47. static char * GetLocalMac(char *strEth); // get loacl NIC's MAC
  48. static void set_ip_addr(char *,char *);   // 填充IP
  49. static void set_hw_addr(char buf[], char *str); // 填充MAC
  50. static char * GetMacByIP(char *strSrcIP, char *strSrcMAC, char *strDesIP ,char *strNIC); // 获取指定IP的MAC
  51. int arp_main( char *nic_name, char *nic_ip, char *des_ip);
  52. /*
  53. #define SRC_IP   "10.0.1.77"   // 源IP
  54. #define DES_IP   "10.0.1.35"   // 目的IP
  55. #define LOCAL_HW        "00:C0:4C:39:0D:6F" // 10.0.1.77的eth0的MAC
  56. #define DEVICE          "eth0"    // 接口
  57. */
  58. #define PADD_MAC  "00:00:00:00:00:00"   // 填充的MAC
  59. #define DES_MAC   "FF:FF:FF:FF:FF:FF"   // 广播MAC
  60. #define ARP_SEND_COUNT 3                // 发送ARP请求的ARP包的个数
  61. #define RX_ARP_COUNT 3                  // rx count of ARP response
  62. #define SLEEP_MAX_US (1000 * 100)       /* unit microsecond */
  63. struct ether_header
  64. {
  65. unsigned char  ether_dhost[6];          /* destination eth addr */
  66. unsigned char  ether_shost[6];          /* source ether addr    */
  67. unsigned short ether_type;              /* packet type ID field */
  68. };
  69. struct arp_header
  70. {
  71. unsigned short int ar_hrd;              /* Format of hardware address.  */
  72. unsigned short int ar_pro;              /* Format of protocol address.  */
  73. unsigned char ar_hln;                   /* Length of hardware address.  */
  74. unsigned char ar_pln;                   /* Length of protocol address.  */
  75. // -------------------------
  76. unsigned short int ar_op;               /* ARP opcode (command).  */
  77. unsigned char __ar_sha[6];              /* Sender hardware address.  */
  78. unsigned char __ar_sip[4];              /* Sender IP address.  */
  79. unsigned char __ar_tha[6];              /* Target hardware address.  */
  80. unsigned char __ar_tip[4];              /* Target IP address.  */
  81. // -------------------------
  82. };
  83. struct arp_packet
  84. {
  85. struct ether_header ethhdr;
  86. struct arp_header arphdr;
  87. unsigned char padding[18];              /* filled with 0 */
  88. };
  89. /* arp reply:
  90. *      op = 2
  91. *      ethhdr.ether_dhost = arphdr.__ar_tha = switch hard addr
  92. *      ethhdr.ether_shost = arphdr.__ar_sha = local hard addr
  93. *      arphdr.__ar_tip = switch ip
  94. *      arphdr.__ar_sip = victim ip
  95. */
  96. #define FRAME_TYPE      0x0806                  /* arp=0x0806,rarp=0x8035 */
  97. #define HARD_TYPE       1                       /* ethernet is 1 */
  98. #define PROTO_TYPE      0x0800                  /* IP is 0x0800 */
  99. #define OP_CODE         1                       /* arp=1/2,1为请求,2为应答,rarp=3/4 */
  100. int main( int argc, char *argv[] )
  101. {
  102. // 检查参数
  103. if ( argc != 4 )
  104. {
  105. wenxy_debug("Useage: %s [interface name of the IP] [IP] [ARP IP]\n\n", argv[0]);
  106. return 0;
  107. }
  108. return arp_main( argv[1], argv[2], argv[3] );
  109. }
  110. // linux下获取LAN里指定IP的网卡MAC
  111. // In: nic_name: 本地网卡名字, nic_ip:本机IP,des_ip:目的IP
  112. // Out: 1表示获取MAC成功,des_ip已被使用, -1表示发生错误,0表示des_ip未使用
  113. int arp_main( char *nic_name, char *nic_ip, char *des_ip)
  114. {
  115. strcpy(strETH, nic_name); //"eth0";
  116. strcpy(strSrcIP, nic_ip); //"10.0.1.77";
  117. strcpy(strDesIP, des_ip); //"10.0.1.69";
  118. wenxy_debug("Run ......\n");
  119. wenxy_debug("获取 %s 接口的MAC ......\n", strETH);
  120. // 获取指定NIC名称的MAC
  121. /*strLocalMAC = GetLocalMac(strETH);*/
  122. GetLocalMac(strETH);
  123. #if 0
  124. wenxy_debug("Note: %s[%s]\n", strETH, strLocalMAC);
  125. #endif
  126. // 获取指定接口MAC
  127. if ( 0 == strcmp( (const char*)strLocalMAC, (const char*)"") )
  128. {
  129. wenxy_debug("Error: call strcmp() failed\n");
  130. wenxy_debug("--------------------------------\n\n");
  131. return -1;
  132. }
  133. else
  134. {
  135. wenxy_debug("获取接口MAC成功: %s [%s]\n", strETH, strLocalMAC);
  136. }
  137. // 获取指定IP网卡的MAC
  138. /*strDesMAC = GetMacByIP(strSrcIP, strLocalMAC, strDesIP, strETH);*/
  139. GetMacByIP(strSrcIP, strLocalMAC, strDesIP, strETH);
  140. wenxy_debug("strDesMAC = %s\n", strDesMAC);
  141. if(1 == find_ip_flag)
  142. {
  143. printf("Note:  strDesIP: %s,  strDesMAC: %s\n", strDesIP, strDesMAC);
  144. return 1;
  145. }
  146. else
  147. {
  148. printf("Note:  strDesIP: %s does not use\n", strDesIP);
  149. return 0;
  150. }
  151. }
  152. // 获取本地某网卡的MAC
  153. // In: strEth
  154. // Out: 若成功,返回MAC字符串,失败,返回""(空串)
  155. static char * GetLocalMac(char *strEth)
  156. {
  157. int s;
  158. struct ifreq buffer;
  159. char chBuff[MAX_MAC_LEN];
  160. unsigned int str_len = 0;
  161. unsigned int offset = 0;
  162. memset(chBuff, 0x0, sizeof(chBuff));
  163. //arp_process(NULL);
  164. s = socket(PF_INET, SOCK_DGRAM, 0);
  165. if (-1 == s)
  166. {
  167. wenxy_debug("Error: create socket failture\n");
  168. wenxy_debug("--------------------------------\n\n");
  169. return "";
  170. }
  171. memset(&buffer, 0x00, sizeof(buffer));
  172. strcpy(buffer.ifr_name, strEth);  // "eth0"
  173. if ( -1 == ioctl(s, SIOCGIFHWADDR, &buffer))
  174. {
  175. wenxy_debug("Error: 获取接口 %s MAC 失败\n", strEth);
  176. wenxy_debug("--------------------------------\n\n");
  177. return "";
  178. }
  179. close(s);
  180. offset = 0;
  181. for( s = 0; s < 6; s++ )
  182. {
  183. memset(chBuff, 0x0, sizeof(chBuff));
  184. sprintf( chBuff, "%.2X", (unsigned char)buffer.ifr_hwaddr.sa_data[s]);
  185. str_len = strlen(chBuff);
  186. memcpy(strLocalMAC + offset, chBuff, str_len);
  187. offset += str_len;
  188. //wenxy_debug("%.2X", (unsigned char)buffer.ifr_hwaddr.sa_data[s]);
  189. if (s < 5)
  190. {
  191. memset(chBuff, 0x0, sizeof(chBuff));
  192. sprintf( chBuff, "%s", COMPART_MAC);
  193. str_len = strlen(chBuff);
  194. memcpy(strLocalMAC + offset, chBuff, str_len);
  195. offset += str_len;
  196. //wenxy_debug(":");
  197. }
  198. }
  199. //wenxy_debug("\n");
  200. return strLocalMAC;
  201. }
  202. //-------------------------------------------------------
  203. // 发送ARP包,并接收ARP应答包,取出MAC
  204. // In: strSrcIP:本机IP,strSrcMAC:本机IP的MAC,strDesIP:被请求应答MAC的IP , strNIC:本地接口名
  205. // Out: 若成功,返回MAC,失败返回""(空串)
  206. static char * GetMacByIP(char *strSrcIP, char *strSrcMAC, char *strDesIP, char *strNIC)
  207. {
  208. int sockfd;     // socket handle
  209. struct arp_packet arp;  // arp 请求包
  210. struct arp_packet arpRes; // arp 应用答包
  211. struct sockaddr sa;   // eth
  212. char chSrcIP[24];
  213. char chDesIP[24];
  214. char chSrcMAC[24];
  215. char chNIC[8];
  216. unsigned int str_len = 0;
  217. unsigned int offset = 0;
  218. int i;
  219. int s;
  220. find_ip_flag = 0;
  221. memset(chSrcIP, 0x00, sizeof(chSrcIP));
  222. memset(chDesIP, 0x00, sizeof(chDesIP));
  223. memset(chSrcMAC, 0x00, sizeof(chSrcMAC));
  224. memset(chNIC, 0x00, sizeof(chNIC));
  225. sprintf(chSrcIP, "%s",  strSrcIP);
  226. sprintf(chDesIP, "%s",  strDesIP);
  227. sprintf(chSrcMAC, "%s", strSrcMAC);
  228. sprintf(chNIC, "%s", strNIC);
  229. #define SRC_IP   chSrcIP  // 源IP
  230. #define DES_IP   chDesIP  // 目的IP
  231. #define LOCAL_HW        chSrcMAC // eth0的MAC
  232. #define DEVICE   chNIC  // 本机接口名
  233. memset(&arp, 0x00, sizeof(arp));
  234. memset(&arpRes, 0x00, sizeof(arpRes));
  235. #if 1
  236. wenxy_debug("源IP[%s]  源MAC[%s] 目的IP[%s]\n", strSrcIP, strSrcMAC, strDesIP);
  237. #endif
  238. sockfd = socket(AF_INET, SOCK_PACKET, htons(0x0806));
  239. if(sockfd < 0)
  240. {
  241. wenxy_debug("Error: create socket failed\n");
  242. wenxy_debug("--------------------------------\n\n");
  243. return "";
  244. }
  245. /*
  246. // 设置socket为非阻塞模式
  247. if ( -1 != fcntl(sockfd, F_SETFL, O_NONBLOCK) )
  248. {
  249. wenxy_debug("设置socket为非阻塞模式成功\n");
  250. }
  251. else
  252. {
  253. wenxy_debug("Warning: 设置socket为非阻塞模式失败[errno = %d]\n", errno);
  254. }
  255. */
  256. // 设置socket接收超时
  257. struct timeval tv;
  258. tv.tv_sec = 0;
  259. tv.tv_usec= 100;
  260. if ( 0 == setsockopt( sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) )
  261. {
  262. wenxy_debug("设置socket接收超时成功\n");
  263. }
  264. else
  265. {
  266. wenxy_debug("Warning: 设置socket接收超时失败[errno = %d]\n", errno);
  267. }
  268. #if 1
  269. wenxy_debug("创建socket SOCK_PACKET 成功\n");
  270. wenxy_debug("Note: 创建ARP请求包 ......\n");
  271. wenxy_debug("--------------------------------\n\n");
  272. #endif
  273. // 创建ARP请求包
  274. /* init arp packet header */
  275. arp.ethhdr.ether_type = htons(FRAME_TYPE);
  276. set_hw_addr( (char *)arp.ethhdr.ether_dhost, DES_MAC );
  277. set_hw_addr( (char *)arp.ethhdr.ether_shost, LOCAL_HW );
  278. #if 1
  279. wenxy_debug("%x|", arp.ethhdr.ether_type);
  280. for (i = 0; i < 6; i++)
  281. {
  282. wenxy_debug("%d_", arp.ethhdr.ether_dhost[i]);
  283. }
  284. wenxy_debug("|");
  285. for (i = 0; i < 6; i++)
  286. {
  287. wenxy_debug("%d_", arp.ethhdr.ether_shost[i]);
  288. }
  289. wenxy_debug("\n--------------------------------\n");
  290. wenxy_debug("初始化ARP包帧头(以太网首部)成功\n\n");
  291. #endif
  292. /* init arp packet data */
  293. wenxy_debug("初始化ARP包帧数据(ARP请求分组) ......\n");
  294. wenxy_debug("--------------------------------\n");
  295. arp.arphdr.ar_hrd = htons(HARD_TYPE); // 1
  296. arp.arphdr.ar_pro = htons(PROTO_TYPE); // 0x0800
  297. arp.arphdr.ar_op = htons(OP_CODE);  // 1
  298. arp.arphdr.ar_hln = (unsigned char)(6);
  299. arp.arphdr.ar_pln = (unsigned char)(4);
  300. #if 1
  301. wenxy_debug("%d|%d|%d|%d|%d|\n", arp.arphdr.ar_hrd, arp.arphdr.ar_pro,
  302. arp.arphdr.ar_op, arp.arphdr.ar_hln, arp.arphdr.ar_pln);
  303. wenxy_debug("--------------------------------\n");
  304. #endif
  305. set_hw_addr((char *)arp.arphdr.__ar_tha, DES_MAC); // 请求IP的MAC
  306. set_hw_addr((char *)arp.arphdr.__ar_sha, LOCAL_HW); // 发送者的MAC
  307. set_ip_addr((char *)arp.arphdr.__ar_tip, DES_IP); // 请求MAC的IP
  308. set_ip_addr((char *)arp.arphdr.__ar_sip, SRC_IP); // 源IP
  309. bzero(arp.padding, 18); // 填充18个字节
  310. #if 1
  311. for (i = 0; i < 6; i++)
  312. {
  313. wenxy_debug("%d_", arp.arphdr.__ar_sha[i]);
  314. }
  315. wenxy_debug("|");
  316. for (i = 0; i < 6; i++)
  317. {
  318. wenxy_debug("%d_", arp.arphdr.__ar_sip[i]);
  319. }
  320. wenxy_debug("|");
  321. for (i = 0; i < 6; i++)
  322. {
  323. wenxy_debug("%d_", arp.arphdr.__ar_tha[i]);
  324. }
  325. wenxy_debug("|");
  326. for (i = 0; i < 6; i++)
  327. {
  328. wenxy_debug("%d_", arp.arphdr.__ar_tip[i]);
  329. }
  330. wenxy_debug("|");
  331. wenxy_debug("\n--------------------------------\n");
  332. #endif
  333. /* send arp reply packet */
  334. memset(&sa, 0x00, sizeof(sa));
  335. strcpy(sa.sa_data, DEVICE);
  336. // 发送ARP包
  337. int nSendCount = ARP_SEND_COUNT;
  338. int nRecvByte = 0;
  339. while( (nSendCount --) > 0)
  340. {
  341. wenxy_debug("发送ARP请求包[%d Bytes]...... [第%d个]\n", sizeof(arp), nSendCount);
  342. if( sendto(sockfd, &arp, sizeof(arp), 0, (struct sockaddr*) &sa, sizeof(sa)) < 0 )
  343. {
  344. wenxy_debug("Error: 发送ARP包失败 [errno = %d]\n", errno);
  345. return "";
  346. }
  347. // 接收ARP应答包
  348. wenxy_debug("Note: 接收ARP应答 ......\n");
  349. int nTryCount = RX_ARP_COUNT;
  350. int nAddrLen = sizeof(sa);
  351. do
  352. {
  353. /* because network and host delay */
  354. usleep(SLEEP_MAX_US);
  355. nRecvByte = recvfrom(sockfd, &arpRes, sizeof(arpRes),0, (struct sockaddr*)&sa, (socklen_t*)&nAddrLen);
  356. // 若是所请求IP的ARP应答包,退出while
  357. if ( nRecvByte >= 60 && 2 == ntohs(arpRes.arphdr.ar_op) )
  358. {
  359. char chBuff[MAX_MAC_LEN];
  360. // 格式化IP
  361. offset = 0;
  362. for (s = 0; s < 4; s++)
  363. {
  364. memset(chBuff, 0x00, sizeof(chBuff));
  365. sprintf( (char *)chBuff, "%d", (unsigned char)arpRes.arphdr.__ar_sip[s]);
  366. //wenxy_debug("chBuff: %s\n", chBuff);
  367. //strTarIP += chBuff;
  368. str_len = strlen(chBuff);
  369. memcpy(strTarIP + offset, chBuff, str_len);
  370. offset += str_len;
  371. if (s < 3)
  372. {
  373. memset(chBuff, 0x00, sizeof(chBuff));
  374. sprintf( (char *)chBuff, "%s", ".");
  375. //strTarIP += chBuff;
  376. str_len = 1;
  377. memcpy(strTarIP + offset, chBuff, str_len);
  378. offset += str_len;
  379. }
  380. }
  381. if ( !strcmp(strTarIP, strDesIP) )
  382. {
  383. wenxy_debug("\n请求IP[%s] = 应答IP[%s]\n", strDesIP, strTarIP);
  384. find_ip_flag = 1; /* find ip */
  385. goto analyse_arp_response;
  386. }
  387. }
  388. }while( nTryCount -- ); // 接收ARP应答包的次数
  389. }
  390. analyse_arp_response:
  391. wenxy_debug("已接收到ARP应答包 [%d Bytes]\n", nRecvByte);
  392. // 接收超时,或错误
  393. if ( nRecvByte == -1 )
  394. {
  395. wenxy_debug("Warning: 接收超时,或计算机[%s]没有响应\n", strDesIP);
  396. close(sockfd);
  397. return "";
  398. }
  399. wenxy_debug("分析ARP应答包 ......\n");
  400. char chBuff[MAX_MAC_LEN];
  401. memset(chBuff, 0x00, sizeof(chBuff));
  402. // 格式化IP
  403. offset = 0;
  404. for (s = 0; s < 4; s++)
  405. {
  406. memset(chBuff, 0x00, sizeof(chBuff));
  407. sprintf( (char *)chBuff, "%d", (unsigned char)arpRes.arphdr.__ar_sip[s]);
  408. //strTarIP += chBuff;
  409. str_len = strlen(chBuff);
  410. memcpy(strTarIP + offset, chBuff, str_len);
  411. offset += str_len;
  412. if (s < 3)
  413. {
  414. memset(chBuff, 0x00, sizeof(chBuff));
  415. sprintf( (char *)chBuff, "%s", ".");
  416. //strTarIP += chBuff;
  417. str_len = strlen(chBuff);
  418. memcpy(strTarIP + offset, chBuff, str_len);
  419. offset += str_len;
  420. }
  421. }
  422. // 格式化MAC
  423. memset(chBuff, 0x00, sizeof(chBuff));
  424. offset = 0;
  425. for (s = 0; s < 6; s++)
  426. {
  427. memset(chBuff, 0x00, sizeof(chBuff));
  428. sprintf( (char *)chBuff, "%02X", (unsigned char)arpRes.arphdr.__ar_sha[s]);
  429. //strTarMAC += chBuff;
  430. str_len = strlen(chBuff);
  431. memcpy(strTarMAC + offset, chBuff, str_len);
  432. offset += str_len;
  433. if (s < 5)
  434. {
  435. memset(chBuff, 0x00, sizeof(chBuff));
  436. sprintf( (char *)chBuff, "%s", COMPART_MAC);
  437. //strTarMAC += chBuff;
  438. str_len = strlen(chBuff);
  439. memcpy(strTarMAC + offset, chBuff, str_len);
  440. offset += str_len;
  441. }
  442. }
  443. // 输出目的IP,目的MAC
  444. wenxy_debug("应答IP[%s] 对应的MAC[%s]\n", strTarIP, strTarMAC);
  445. wenxy_debug("\n--------------------------------\n\n");
  446. close(sockfd);
  447. // 返回被请求的MAC
  448. strcpy(strDesMAC, strTarMAC);
  449. /* return */
  450. return strDesMAC;
  451. }
  452. // 填充MAC
  453. static void set_hw_addr (char buf[], char *str)
  454. {
  455. int i;
  456. char c, val;
  457. for(i = 0; i < 6; i++)
  458. {
  459. if (!(c = tolower(*str++)))
  460. perror("Invalid hardware address"),exit(1);
  461. if (isdigit(c))
  462. val = c - '0';
  463. else if (c >= 'a' && c <= 'f')
  464. val = c-'a'+10;
  465. else
  466. perror("Invalid hardware address"),exit(1);
  467. buf[i] = val << 4;
  468. if (!(c = tolower(*str++)))
  469. perror("Invalid hardware address"),exit(1);
  470. if (isdigit(c))
  471. val = c - '0';
  472. else if (c >= 'a' && c <= 'f')
  473. val = c-'a'+10;
  474. else
  475. perror("Invalid hardware address"),exit(1);
  476. buf[i] |= val;
  477. if (*str == ':')
  478. str++;
  479. }
  480. }
  481. // 填充IP
  482. static void set_ip_addr(char *buf, char *str)
  483. {
  484. struct in_addr addr;
  485. memset(&addr, 0x00, sizeof(addr));
  486. addr.s_addr = inet_addr(str);
  487. memcpy(buf, &addr, 4);
  488. }
  489. //-------------------------------------------------------
  490. // end file
  1. ################################################################################
  2. # File: Makefile
  3. # Description:
  4. # Author: Xiaoyong Wen <wen_kernel@163.com>, 20130807, AM.
  5. #
  6. # Fix hisoty:
  7. #
  8. ################################################################################
  9. debug := 1
  10. ifdef debug
  11. CFLAGS += -g
  12. else
  13. CFLAGS += -O2
  14. endif
  15. #CC := g++
  16. CC := gcc
  17. target_bin := lan_mac_scan
  18. bin := main
  19. obj := main.o
  20. #src := main.c
  21. src := $(wildcard *.c) $(wildcard *.h)
  22. .PHONY : clean all debug
  23. all : $(bin)
  24. cp main $(target_bin)
  25. @-ls -l $(target_bin)
  26. $(bin) : $(obj)
  27. $(obj) : $(src)
  28. debug:
  29. @echo $(src)
  30. @echo $(obj)
  31. @echo $(CFLAGS)
  32. @echo $(LDFLAGS)
  33. clean:
  34. 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包会被过滤而失效。

Linux 下获取LAN中指定IP的网卡的MAC(物理地址)的更多相关文章

  1. 获取局域网中指定IP或是主机名称的所有文件夹及其搜索文件

    最近做个功能在局域网中所有指定文件,于是花了点精力完成了部分功能,先贴上 using System; using System.Collections.Generic; using System.Co ...

  2. Linux下获取和设置IP

    在Linux下获取关于IP和网关的操作:重点是对struct ifreq 的操作. 那么进入目录/usr/include/net/if.h下看查找struct ifreq结构体. /* Interfa ...

  3. Linux下获取本机IP地址的代码

    Linux下获取本机IP地址的代码,返回值即为互联网标准点分格式的字符串. #define ETH_NAME "eth0" //获得本机IP地址 char* GetLocalAdd ...

  4. Linux下使用 ipset 封大量IP及ipset参数说明

    转载Linux下使用 ipset 封大量IP及ipset参数说明 Linux使用iptables封IP,是常用的应对网络攻击的方法,但要封禁成千上万个IP,如果添加成千上万条规则,对机器性能影响较大, ...

  5. linux下nginx服务器域名指定目录

    一般,域名指定ip之后,需要在ip所在的机器去指定相应站点的目录,否则域名会不起作用: 下面说说linux下的nginx服务器指定目录的细节: 域名绑定目录的配置文件都放到这里: /usr/local ...

  6. Linux下获取硬盘使用情况

    Linux下获取硬盘使用情况[总结] 1.前言 在嵌入式设备中,硬盘空间非常有限,在涉及到经常写日志的进程时候,需要考虑日志的大小和删除,不然很快就硬盘写满,导致日志程序崩溃.为了捕获硬盘写满的异常场 ...

  7. [转载]linux下编译php中configure参数具体含义

    编译N次了   原来这么回事 原文地址:linux下编译php中configure参数具体含义作者:捷心特 php编译参数的含义 ./configure –prefix=/usr/local/php ...

  8. 用JavaScript,获取Table中指定的行、列

    前言: 先要谢谢George Wing的慷慨赠书<悟透JavaScript>,让我更加感受到了技术交流的重要性,呵呵~ 进入正题,面试题中有一题:如何通过JavaScript获取Table ...

  9. window/linux下获取文件MD5

    MD5消息摘要算法(英语: MD5 Message-Digest Algorithm), 主要用于确保信息传输过程的一致性校验.   首先介绍两个工具: window: WinMD5Free Linu ...

随机推荐

  1. javascript得知 - js的Date对象函数

    js的Date功能很强大.通常使用. 首先获得当前的日期: var CurDate = new Date(); var Year = CurDate.getFullYear(); //年份(四位 例: ...

  2. ActionBar点击弹出下拉框操作

    首先: getActionBar().setDisplayShowTitleEnabled(false); ActionBar.LayoutParams lp = new ActionBar.Layo ...

  3. 小猪猪逆袭成博士之C++基础篇(二) 常量、处理类型、自定义头文件

    小猪猪逆袭成博士之C++基础篇(二) const .auto. decltype 上一章我们介绍了一些常用的类型和常见的问题,下面再介绍一些学习的时候不是特别常用但是在实际工程中很有用的一些东西. 一 ...

  4. 驱动: oops

    linux驱动调试--段错误之oops信息分析 http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=29401328&id= ...

  5. 【centos6 , 6】linux 查看帮助文档:

    1. 使用   命令 -h 或 命令 --help ,  例: ls -h 2. man命令  : man  命令              例:man ls 3.info命令:           ...

  6. FreePascal的VMT与Delphi不一致,没有负方向

    因为不需要与C++兼容嘛:http://www.freepascal.org/docs-html/prog/progsu168.html 如果要想取得它真正的VMT,可以Pointer强行转换+100 ...

  7. android如何让service不被杀死-提高进程优先级

    1.在service中重写下面的方法,这个方法有三个返回值, START_STICKY是service被kill掉后自动重写创建 @Override public int onStartCommand ...

  8. ethtool命令

    用途 显示或修改以太网卡的配置信息. 语法 ethtool [ -a | -c | -g | -i | -d | -k | -r | -S |] ethX ethtool [-A] ethX [aut ...

  9. Debian上安装TightVNC Server

    from:www.penlug.org/twiki/bin/view/Main/TightVNC Using VNC   The tool vncserver allows you to run ad ...

  10. Ubuntu 12.04 安装JDK 8和Eclipse

    Ubuntu 12.04 下安装 JDK8 方法一:(缺点是安装时附加openjdk等大量程序并无法去除,长处是安装简单) $ sudo apt-get install eclipse 方法二:(长处 ...