通过IP获取MAC地址例子(应用层)
博客地址:http://home.cnblogs.com/u/zengjianrong/
由于某种需求,需要获取某个ip的mac地址,在应用层实现例子如下代码。
流程:1. 先遍历arp表,若存在对应mac地址,则取出并结束。否则继续。
2. 构造arp包,发arp request,若收不到arp reply,则返回失败并结束。否则继续。
3. 解析arp reply包,获取MAC,并将ip、mac信息存到内核的arp表。
#include <errno.h>
#include <net/if_arp.h>
#include <netinet/if_ether.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h> #define MAC_BCAST_ADDR (unsigned char *)"\xff\xff\xff\xff\xff\xff"
#define LOCAL_MAC_ADDR (unsigned char *)"\x00\x50\x56\xCC\x99\x0E"
#define LOCAL_DEV (unsigned char *)"eth0" #ifndef ATF_FORCE_ADD
#define ATF_FORCE_ADD 0x80 /* force to add an entry --add by zengjianrong */
#endif typedef unsigned int u_int32_t;
typedef unsigned int u_int; #ifdef ZJR_READ /* just for reading */
typedef unsigned short sa_family_t;
struct sockaddr {
sa_family_t sa_family; /* address family, AF_xxx */
char sa_data[]; /* 14 bytes of protocol address */
};
struct sockaddr_in
{
sa_family_t sin_family; /* Address family */
__be16 sin_port; /* Port number */
struct in_addr sin_addr; /* Internet address */ /* Pad to size of `struct sockaddr'. */
unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) -
sizeof(unsigned short int) - sizeof(struct in_addr)];
};
struct arpreq
{
struct sockaddr arp_pa; /* protocol address */
struct sockaddr arp_ha; /* hardware address */
int arp_flags; /* flags */
struct sockaddr arp_netmask; /* netmask (only for proxy arps) */
char arp_dev[];
};
#endif #define SYSTEM_ERROR 1
#define PROCESS_PRINT 0
#define DEBUGGING_LVL 0
#define DEBUGGING #ifdef DEBUGGING
#define DEBUG(lvl, ...)\
do\
{\
if (lvl >= DEBUGGING_LVL)\
{\
printf("[DEBUG] in %s:%d %s(), ",\
__FILE__, __LINE__, __FUNCTION__);\
printf(__VA_ARGS__);\
printf("\n");\
}\
} while()
#else
#define DEBUG(lvl, ...) do {} while(0)
#endif typedef enum
{
ARP_TBL_BEGIN = ,
ARP_TBL_GET,
ARP_TBL_SET,
ARP_TBL_DEL,
ARP_TBL_END,
}ARP_TBL_TRL_ENUM; struct arpMsg
{
struct ethhdr ethhdr; /* Ethernet header */
u_short htype; /* hardware type (must be ARPHRD_ETHER) */
u_short ptype; /* protocol type (must be ETH_P_IP) */
u_char hlen; /* hardware address length (must be 6) */
u_char plen; /* protocol address length (must be 4) */
u_short operation; /* ARP opcode */
u_char sHaddr[]; /* sender's hardware address */
u_char sInaddr[]; /* sender's IP address */
u_char tHaddr[]; /* target's hardware address */
u_char tInaddr[]; /* target's IP address */
u_char pad[]; /* pad for min. Ethernet payload (60 bytes) */
}; static int fd_arp_tbl = -; /******************************************************************************
* nSendArp - send arp, get mac from arp reply if have
* DESCRIPTION: -
* Input: unRemoteIp - remote ip
* unLocalIp - our ip
* pucLocalMac - our mac address
* pchEth - interface to use
* Output: pstArp - arp info
* Returns: 1 - addr free
* 0 - addr used, get mac ok
* -1 - error
*
* modification history
* --------------------
* 2.00, 2014-12-25 , zengjianrong written
* --------------------
******************************************************************************/
int nSendArp(u_int32_t unRemoteIp, u_int32_t unLocalIp, unsigned char *pucLocalMac, char *pchEth, struct arpMsg *pstArp)
{
int nTimeOut = ;
int nOptVal = ;
int nSk = -; /* socket */
int nRtVal = ; /* return value */
fd_set fdset;
time_t prevTime;
struct sockaddr addr; /* for interface name */
struct timeval tm; if (- == (nSk=socket(PF_PACKET, SOCK_PACKET, htons(ETH_P_ARP))))
{
DEBUG(SYSTEM_ERROR, "func->socket error(%d:%s).", errno, strerror(errno));
return -;
} if (- == setsockopt(nSk, SOL_SOCKET, SO_BROADCAST, &nOptVal, sizeof(nOptVal)))
{
DEBUG(SYSTEM_ERROR, "func->setsocketopt error(%d:%s).", errno, strerror(errno));
close(nSk);
return -;
} /* make a arp request */
memset(pstArp, , sizeof(struct arpMsg));
memcpy(pstArp->ethhdr.h_dest, MAC_BCAST_ADDR, ); /* MAC DA */
memcpy(pstArp->ethhdr.h_source, pucLocalMac, ); /* MAC SA */
pstArp->ethhdr.h_proto = htons(ETH_P_ARP); /* protocol type (Ethernet) */
pstArp->htype = htons(ARPHRD_ETHER); /* hardware type */
pstArp->ptype = htons(ETH_P_IP); /* protocol type (ARP message) */
pstArp->hlen = ; /* hardware address length */
pstArp->plen = ; /* protocol address length */
pstArp->operation = htons(ARPOP_REQUEST); /* ARP op code */
*((u_int *) pstArp->sInaddr) = unLocalIp; /* source IP address */
memcpy(pstArp->sHaddr, pucLocalMac, ); /* source hardware address */
//*((u_int *) pstArp->tInaddr) = unRemoteIp;
memcpy(pstArp->tInaddr, (unsigned char *)&unRemoteIp, sizeof(pstArp->tInaddr));/* target IP address */
memset(&addr, , sizeof(addr));
strcpy(addr.sa_data, pchEth); /* send arp request */
if ( > sendto(nSk, pstArp, sizeof(struct arpMsg), , &addr, sizeof(addr)))
{
DEBUG(SYSTEM_ERROR, "func->sendto error(%d:%s).", errno, strerror(errno));
close(nSk);
return -;
} /* wait arp reply, and check it */
tm.tv_usec = ;
time(&prevTime);
while (nTimeOut > )
{
FD_ZERO(&fdset);
FD_SET(nSk, &fdset);
tm.tv_sec = nTimeOut;
if (select(nSk + , &fdset, (fd_set *) NULL, (fd_set *) NULL, &tm) < )
{
DEBUG(SYSTEM_ERROR, "func->select error(%d:%s).", errno, strerror(errno));
if (errno != EINTR)
{
nRtVal = ;
}
}
else if (FD_ISSET(nSk, &fdset))
{
if (recv(nSk, pstArp, sizeof(struct arpMsg), ) < )
{
nRtVal = ;
}
if (pstArp->operation == htons(ARPOP_REPLY) &&
bcmp(pstArp->tHaddr, pucLocalMac, ) == &&
*((u_int *) pstArp->sInaddr) == unRemoteIp)
{
//DEBUG(PROCESS_PRINT, "valid arp reply receved for this address.");
nRtVal = ;
break;
}
}
nTimeOut -= time(NULL) - prevTime;
time(&prevTime);
}
close(nSk);
DEBUG(PROCESS_PRINT, "%salid arp replies for this address", nRtVal ? "no v" : "v");
return nRtVal;
} /******************************************************************************
* nArpTblCtl - get/set/del ip<->mac info
* DESCRIPTION: -
* Input:
* Output:
* Returns:
*
* modification history
* --------------------
* 2.00, 2014-12-25 , zengjianrong written
* --------------------
******************************************************************************/
int nArpTblCtl(ARP_TBL_TRL_ENUM cmd, struct in_addr stRemoteIp, char *pcDevName, unsigned char *pucMac)
{
unsigned int unCmd = ;
unsigned char *pucHwAddr = NULL;
struct sockaddr_in *pSin = NULL;
struct arpreq stArpreq; if (( == stRemoteIp.s_addr)
|| (cmd <= ARP_TBL_BEGIN)
|| (cmd >= ARP_TBL_END)
|| (ARP_TBL_DEL != cmd && NULL == pucMac))
{
DEBUG(SYSTEM_ERROR, "param error.");
return -;
} memset(&stArpreq, , sizeof(struct arpreq));
switch (cmd)
{
case ARP_TBL_GET:
unCmd = SIOCGARP;
break;
case ARP_TBL_DEL:
stArpreq.arp_ha.sa_family = AF_UNSPEC;
unCmd = SIOCDARP;
break;
case ARP_TBL_SET:
stArpreq.arp_ha.sa_family = AF_UNSPEC;
//stArpreq.arp_flags = ATF_PERM | ATF_PUBL | ATF_FORCE_ADD;
stArpreq.arp_flags = ATF_COM;
memcpy((char *)stArpreq.arp_ha.sa_data, pucMac, );
unCmd = SIOCSARP;
break;
default:
return -;
} if (- == fd_arp_tbl)
{
fd_arp_tbl = socket(AF_INET, SOCK_DGRAM, );
if (fd_arp_tbl < )
{
DEBUG(SYSTEM_ERROR, "func->socket error(%d:%s).", errno, strerror(errno));
return -;
}
} pSin = (struct sockaddr_in *) &stArpreq.arp_pa;
pSin->sin_family = AF_INET;
memcpy(&(pSin->sin_addr), &stRemoteIp, sizeof(struct in_addr));
strcpy(stArpreq.arp_dev, pcDevName); if ( > ioctl(fd_arp_tbl, unCmd, &stArpreq))
{
DEBUG(SYSTEM_ERROR, "func->ioctl error(%d:%s).", errno, strerror(errno));
close(fd_arp_tbl);
fd_arp_tbl = -;
return -;
}
else if (ARP_TBL_GET == cmd)
{
pucHwAddr = (unsigned char *) stArpreq.arp_ha.sa_data;
memcpy(pucMac, pucHwAddr, );
if ( == pucMac[] && == pucMac[] && == pucMac[]
&& == pucMac[] && == pucMac[] && == pucMac[])
{
return -;
}
} return ;
} int main(int argc, char *argv[])
{
unsigned char aucMac[];
struct in_addr sin_remote_addr;
struct in_addr sin_local_addr;
struct arpMsg stArpMsg; memset(&sin_local_addr, , sizeof(struct in_addr));
memset(&stArpMsg, , sizeof(struct arpMsg));
memset(aucMac, , ); if (argc!=)
{
DEBUG(SYSTEM_ERROR, "usage: %s <IP address>\n",argv[]);
return -;
} /* initial global values */
fd_arp_tbl = -; if ( == (inet_aton("138.0.225.226", &sin_local_addr)))
{
DEBUG(SYSTEM_ERROR, "func->inet_aton error(%d:%s).", errno, strerror(errno));
return -;
} if ( == (inet_aton(argv[], &sin_remote_addr)))
{
DEBUG(SYSTEM_ERROR, "func->inet_aton error(%d:%s), '%s' not valid.",
errno, strerror(errno), argv[]);
return -;
} if ( > (nArpTblCtl(ARP_TBL_GET, sin_remote_addr, LOCAL_DEV, aucMac)))
{
DEBUG(PROCESS_PRINT, "no entry in arp_cache for '%s', send arp request.", argv[]);
if ( != (nSendArp(sin_remote_addr.s_addr, sin_local_addr.s_addr,
LOCAL_MAC_ADDR, LOCAL_DEV, &stArpMsg)))
{
DEBUG(SYSTEM_ERROR, "there is no device using '%s', or nSendArp error.", argv[]);
return -;
}
else
{
if ( > (nArpTblCtl(ARP_TBL_SET, sin_remote_addr, LOCAL_DEV, stArpMsg.sHaddr)))
{
DEBUG(SYSTEM_ERROR, "func->nArpTblCtl set error.");
return -;
}
if ( > (nArpTblCtl(ARP_TBL_GET, sin_remote_addr, LOCAL_DEV, aucMac)))
{
DEBUG(PROCESS_PRINT, "there is no device using '%s'.", argv[]);
return ;
}
}
}
DEBUG(PROCESS_PRINT, "%s-->%02x:%02x:%02x:%02x:%02x:%02x.", argv[],
aucMac[], aucMac[], aucMac[], aucMac[], aucMac[], aucMac[]); return ;
}
测试结果如下:
[root@zeng test]# ifconfig
eth0 Link encap:Ethernet HWaddr :::CC::0E
inet addr:138.0.225.226 Bcast:138.0.255.255 Mask:255.255.0.0
inet6 addr: fe80:::56ff:fecc:990e/ Scope:Link
UP BROADCAST RUNNING MULTICAST MTU: Metric:
RX packets: errors: dropped: overruns: frame:
TX packets: errors: dropped: overruns: carrier:
collisions: txqueuelen:
RX bytes: (154.2 MiB) TX bytes: (17.9 MiB)
Interrupt: Base address:0x2024 eth1 Link encap:Ethernet HWaddr :::DE::0E
inet addr:192.168.123.225 Bcast:192.168.123.255 Mask:255.255.255.0
inet6 addr: fe80:::56ff:fede:990e/ Scope:Link
UP BROADCAST RUNNING MULTICAST MTU: Metric:
RX packets: errors: dropped: overruns: frame:
TX packets: errors: dropped: overruns: carrier:
collisions: txqueuelen:
RX bytes: (2.4 MiB) TX bytes: (1016.2 KiB)
Interrupt: Base address:0x20a4 eth2 Link encap:Ethernet HWaddr :::DC::0E
inet addr:192.168.213.225 Bcast:192.168.213.255 Mask:255.255.255.0
inet6 addr: fe80:::56ff:fedc:990e/ Scope:Link
UP BROADCAST RUNNING MULTICAST MTU: Metric:
RX packets: errors: dropped: overruns: frame:
TX packets: errors: dropped: overruns: carrier:
collisions: txqueuelen:
RX bytes: (324.9 MiB) TX bytes: (1.3 GiB)
Interrupt: Base address:0x2424 lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::/ Scope:Host
UP LOOPBACK RUNNING MTU: Metric:
RX packets: errors: dropped: overruns: frame:
TX packets: errors: dropped: overruns: carrier:
collisions: txqueuelen:
RX bytes: (54.7 KiB) TX bytes: (54.7 KiB) [root@zeng test]# ./getMacFromIp.o 138.0.0.90
[DEBUG] in /mnt/hgfs/source_code_20140312/test/2getMacFromIp.c: nArpTblCtl(), func->ioctl error(:No such device or address).
[DEBUG] in /mnt/hgfs/source_code_20140312/test/2getMacFromIp.c: main(), no entry in arp_cache for '138.0.0.90', send arp request.
[DEBUG] in /mnt/hgfs/source_code_20140312/test/2getMacFromIp.c: nSendArp(), valid arp replies for this address
[DEBUG] in /mnt/hgfs/source_code_20140312/test/2getMacFromIp.c: main(), 138.0.0.90-->:d4:::5b:7c.
[root@zeng test]# ./getMacFromIp.o 138.0.156.125
[DEBUG] in /mnt/hgfs/source_code_20140312/test/2getMacFromIp.c: nArpTblCtl(), func->ioctl error(:No such device or address).
[DEBUG] in /mnt/hgfs/source_code_20140312/test/2getMacFromIp.c: main(), no entry in arp_cache for '138.0.156.125', send arp request.
[DEBUG] in /mnt/hgfs/source_code_20140312/test/2getMacFromIp.c: nSendArp(), no valid arp replies for this address
[DEBUG] in /mnt/hgfs/source_code_20140312/test/2getMacFromIp.c: main(), there is no device using '138.0.156.125', or nSendArp error.
[root@zeng test]#
通过IP获取MAC地址例子(应用层)的更多相关文章
- 通过IP获取MAC地址例子(内核层)
		
博客地址:http://home.cnblogs.com/u/zengjianrong/ 在内核处理此流程,反而更加简单些,代码如下: #include <net/arp.h> #incl ...
 - java根据本地Ip获取mac地址
		
import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; impo ...
 - android获取Mac地址和IP地址
		
获取Mac地址实际项目中测试了如下几种方法:(1)设备开通Wifi连接,获取到网卡的MAC地址(但是不开通wifi,这种方法获取不到Mac地址,这种方法也是网络上使用的最多的方法) //根据Wifi信 ...
 - Java获取本机的IP与MAC地址
		
有些机器有许多虚拟的网卡,获取IP地址时会出现一些意外,所以需要一些验证: // 获取mac地址 public static String getMacAddress() { try { Enumer ...
 - .net获取IP和MAC地址
		
获取IP 解决request.UserHostAddress取不到真实IP private string GetClientIP() { string result = HttpConte ...
 - 获取平台所有接口的IP和MAC地址
		
我们有时候会有获取网口的IP和MAC地址的需求.可以通过ioctl来获取. #include <sys/ioctl.h>#include <net/if.h>#include ...
 - 获取本机IP、mac地址、计算机名
		
python获取本机IP.mac地址.计算机名 在python中获取ip地址和在php中有很大不同,我们先来看一下python 获得本机MAC地址: >>> import uuid ...
 - Java根据ip地址获取Mac地址,Java获取Mac地址
		
Java根据ip地址获取Mac地址,Java获取Mac地址 >>>>>>>>>>>>>>>>>&g ...
 - Linux 获取本机IP、MAC地址用法大全
		
getifaddrs()和struct ifaddrs的使用,获取本机IP ifaddrs结构体定义如下: struct ifaddrs { struct ifaddrs *ifa_next; /* ...
 
随机推荐
- laravel Method Illuminate\Validation\Validator::validateReuqired does not exist.
			
Method Illuminate\Validation\Validator::validateReuqired does not exist. 此错误是由于我们在配置验证时,写错了关键字, publ ...
 - .Net常见的IOC框架及AOP框架
			
IOC框架 Unity:微软patterns&practicest团队开发的IOC依赖注入框架,支持AOP横切关注点. MEF(Managed Extensibility Framework) ...
 - SQLMAP 速查手册
			
/pentest/database/sqlmap/txt/ common-columns.txt 字段字典 common-outputs.txt common-tables.txt 表字典 keywo ...
 - MySQL循环日期
			
DROP PROCEDURE IF EXISTS `insertManyDate`$$ CREATE DEFINER=`root`@`%` PROCEDURE `insertManyDate`(IN ...
 - Redis缓存和MySQL数据一致性方案(转)
			
需求起因 在高并发的业务场景下,数据库大多数情况都是用户并发访问最薄弱的环节.所以,就需要使用redis做一个缓冲操作,让请求先访问到redis,而不是直接访问MySQL等数据库. 这个业务场景,主要 ...
 - seafile部署安装
			
安装epel源 yum install epel-release -y 安装docker yum install -y docker service docker start systemctl en ...
 - 防止xss攻击的前端的方法
			
项目当中在进行安全测试的时候,遇到了xss的攻击,要求前端来做个防御,针对于遇到的xss攻击,做个总结 1.xss---存储型xss的攻击 前端只要在接收到后台数据的时候做个特殊字符的过滤,即可抵制攻 ...
 - c# 第8节 变量、变量名命令规则、作用域、@的作用
			
本节内容: 1:变量 2:变量名命令规则 3:常量 4:变量和常量的作用域 5:@的作用 1:变量是什么? 计算即中存储变量的也是三步骤: 实例: 2:变量命令规则 练习: 3.常量 实现: 4:变量 ...
 - 子进程回收资源两种方式,僵尸进程与孤儿进程,守护进程,进程间数据隔离,进程互斥锁,队列,IPC机制,线程,守护线程,线程池,回调函数add_done_callback,TCP服务端实现并发
			
子进程回收资源两种方式 - 1) join让主进程等待子进程结束,并回收子进程资源,主进程再结束并回收资源. - 2) 主进程 “正常结束” ,子进程与主进程一并被回收资源. from multipr ...
 - JAVA并发-CountDownLatch
			
源码: 内部类Sync private static final class Sync extends AbstractQueuedSynchronizer { private static fina ...