Linux 下获取LAN中指定IP的网卡的MAC(物理地址)
#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
相关文章
- Linux命令之exit - 退出当前shell【返回值状态】
- linux 添加secondary ip
- 理论+实例,带你掌握Linux的页目录和页表
- Linux网络编程(一):网络术语01【Mac地址(网卡标识,全球唯一)、ip地址(虚拟主机标识)、子网掩码/Netmask(结合ip来区分子网id和主机id)、端口(标识应用程序/进程)】
- Linux网络编程(四)-协议04:数据包封装【不同层数据包称谓:①传输层(TCP/UDP):段(segment);②网络层(IP):数据报(datagram);③链路层(Mac):帧(frame)】
- linux 配置静态ip实现上网
- Linux服务器安装Oracle服务端总结
- linux包之iproute之ip命令
- Linux 一行命令 仅显示某一个网卡的ip地址
- [linux学习]sysctl 以及 net.ipv4.ip_forward
- VMware下配置Linux IP,解决Linux ping不通
- linux系统语系$lang
- Linux - fuser 命令
- Linux 学习- Ubuntu 查看本机IP
- linux使用ip能ping通,但使用域名却不能访问的解决方法
- linux命令——磁盘管理cd
- linux设置静态获取ip
- Linux系列:Fedora虚拟机设置固定IP上网(配置IP、网关、DNS、防止resolv.conf被重写)
- linux驱动编写(总结篇)
- docker-linux下的部署和基本命令
- linux下配置ip地址四种方法(图文方法)
- apt vs. apt-get:Linux 上有什么区别?
- 查看windows和linux的内网ip地址,外网ip地址
- 如何在Linux中复制文档