zoukankan      html  css  js  c++  java
  • Linux 下获取LAN中指定IP的网卡的MAC(物理地址)

    // 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代码。*/

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

  • 相关阅读:
    PHP与MongoDB简介|安全|M+PHP应用实例(转)
    在CentOS中安装gcc配置c语言开发环境(转)
    linux svn客户端入门心得(转)
    php socket成功实例
    PHP date函数参数详解(转)
    php socket(fsockopen)的应用实例
    文件字符输出流FileWriter
    TCP(socket)实例
    文件字符输入流FileReader
    卡曼滤波python
  • 原文地址:https://www.cnblogs.com/lidabo/p/3803875.html
Copyright © 2011-2022 走看看