博客地址:http://home.cnblogs.com/u/zengjianrong/

  由于某种需求,需要获取某个ip的mac地址,在应用层实现例子如下代码。

  流程:1. 先遍历arp表,若存在对应mac地址,则取出并结束。否则继续。

     2. 构造arp包,发arp request,若收不到arp reply,则返回失败并结束。否则继续。

     3. 解析arp reply包,获取MAC,并将ip、mac信息存到内核的arp表。

  1. #include <errno.h>
  2. #include <net/if_arp.h>
  3. #include <netinet/if_ether.h>
  4. #include <netinet/in.h>
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <sys/ioctl.h>
  8. #include <sys/socket.h>
  9. #include <sys/types.h>
  10. #include <sys/time.h>
  11. #include <sys/types.h>
  12. #include <time.h>
  13. #include <unistd.h>
  14.  
  15. #define MAC_BCAST_ADDR (unsigned char *)"\xff\xff\xff\xff\xff\xff"
  16. #define LOCAL_MAC_ADDR (unsigned char *)"\x00\x50\x56\xCC\x99\x0E"
  17. #define LOCAL_DEV (unsigned char *)"eth0"
  18.  
  19. #ifndef ATF_FORCE_ADD
  20. #define ATF_FORCE_ADD 0x80 /* force to add an entry --add by zengjianrong */
  21. #endif
  22.  
  23. typedef unsigned int u_int32_t;
  24. typedef unsigned int u_int;
  25.  
  26. #ifdef ZJR_READ  /* just for reading */
  27. typedef unsigned short sa_family_t;
  28. struct sockaddr {
  29. sa_family_t sa_family; /* address family, AF_xxx */
  30. char sa_data[]; /* 14 bytes of protocol address */
  31. };
  32. struct sockaddr_in
  33. {
  34. sa_family_t sin_family; /* Address family */
  35. __be16 sin_port; /* Port number */
  36. struct in_addr sin_addr; /* Internet address */
  37.  
  38. /* Pad to size of `struct sockaddr'. */
  39. unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) -
  40. sizeof(unsigned short int) - sizeof(struct in_addr)];
  41. };
  42. struct arpreq
  43. {
  44. struct sockaddr arp_pa; /* protocol address */
  45. struct sockaddr arp_ha; /* hardware address */
  46. int arp_flags; /* flags */
  47. struct sockaddr arp_netmask; /* netmask (only for proxy arps) */
  48. char arp_dev[];
  49. };
  50. #endif
  51.  
  52. #define SYSTEM_ERROR 1
  53. #define PROCESS_PRINT 0
  54. #define DEBUGGING_LVL 0
  55. #define DEBUGGING
  56.  
  57. #ifdef DEBUGGING
  58. #define DEBUG(lvl, ...)\
  59. do\
  60. {\
  61. if (lvl >= DEBUGGING_LVL)\
  62. {\
  63. printf("[DEBUG] in %s:%d %s(), ",\
  64. __FILE__, __LINE__, __FUNCTION__);\
  65. printf(__VA_ARGS__);\
  66. printf("\n");\
  67. }\
  68. } while()
  69. #else
  70. #define DEBUG(lvl, ...) do {} while(0)
  71. #endif
  72.  
  73. typedef enum
  74. {
  75. ARP_TBL_BEGIN = ,
  76. ARP_TBL_GET,
  77. ARP_TBL_SET,
  78. ARP_TBL_DEL,
  79. ARP_TBL_END,
  80. }ARP_TBL_TRL_ENUM;
  81.  
  82. struct arpMsg
  83. {
  84. struct ethhdr ethhdr; /* Ethernet header */
  85. u_short htype; /* hardware type (must be ARPHRD_ETHER) */
  86. u_short ptype; /* protocol type (must be ETH_P_IP) */
  87. u_char hlen; /* hardware address length (must be 6) */
  88. u_char plen; /* protocol address length (must be 4) */
  89. u_short operation; /* ARP opcode */
  90. u_char sHaddr[]; /* sender's hardware address */
  91. u_char sInaddr[]; /* sender's IP address */
  92. u_char tHaddr[]; /* target's hardware address */
  93. u_char tInaddr[]; /* target's IP address */
  94. u_char pad[]; /* pad for min. Ethernet payload (60 bytes) */
  95. };
  96.  
  97. static int fd_arp_tbl = -;
  98.  
  99. /******************************************************************************
  100. * nSendArp - send arp, get mac from arp reply if have
  101. * DESCRIPTION: -
  102. * Input: unRemoteIp - remote ip
  103. * unLocalIp - our ip
  104. * pucLocalMac - our mac address
  105. * pchEth - interface to use
  106. * Output: pstArp - arp info
  107. * Returns: 1 - addr free
  108. * 0 - addr used, get mac ok
  109. * -1 - error
  110. *
  111. * modification history
  112. * --------------------
  113. * 2.00, 2014-12-25 , zengjianrong written
  114. * --------------------
  115. ******************************************************************************/
  116. int nSendArp(u_int32_t unRemoteIp, u_int32_t unLocalIp, unsigned char *pucLocalMac, char *pchEth, struct arpMsg *pstArp)
  117. {
  118. int nTimeOut = ;
  119. int nOptVal = ;
  120. int nSk = -; /* socket */
  121. int nRtVal = ; /* return value */
  122. fd_set fdset;
  123. time_t prevTime;
  124. struct sockaddr addr; /* for interface name */
  125. struct timeval tm;
  126.  
  127. if (- == (nSk=socket(PF_PACKET, SOCK_PACKET, htons(ETH_P_ARP))))
  128. {
  129. DEBUG(SYSTEM_ERROR, "func->socket error(%d:%s).", errno, strerror(errno));
  130. return -;
  131. }
  132.  
  133. if (- == setsockopt(nSk, SOL_SOCKET, SO_BROADCAST, &nOptVal, sizeof(nOptVal)))
  134. {
  135. DEBUG(SYSTEM_ERROR, "func->setsocketopt error(%d:%s).", errno, strerror(errno));
  136. close(nSk);
  137. return -;
  138. }
  139.  
  140. /* make a arp request */
  141. memset(pstArp, , sizeof(struct arpMsg));
  142. memcpy(pstArp->ethhdr.h_dest, MAC_BCAST_ADDR, ); /* MAC DA */
  143. memcpy(pstArp->ethhdr.h_source, pucLocalMac, ); /* MAC SA */
  144. pstArp->ethhdr.h_proto = htons(ETH_P_ARP); /* protocol type (Ethernet) */
  145. pstArp->htype = htons(ARPHRD_ETHER); /* hardware type */
  146. pstArp->ptype = htons(ETH_P_IP); /* protocol type (ARP message) */
  147. pstArp->hlen = ; /* hardware address length */
  148. pstArp->plen = ; /* protocol address length */
  149. pstArp->operation = htons(ARPOP_REQUEST); /* ARP op code */
  150. *((u_int *) pstArp->sInaddr) = unLocalIp; /* source IP address */
  151. memcpy(pstArp->sHaddr, pucLocalMac, ); /* source hardware address */
  152. //*((u_int *) pstArp->tInaddr) = unRemoteIp;
  153. memcpy(pstArp->tInaddr, (unsigned char *)&unRemoteIp, sizeof(pstArp->tInaddr));/* target IP address */
  154. memset(&addr, , sizeof(addr));
  155. strcpy(addr.sa_data, pchEth);
  156.  
  157. /* send arp request */
  158. if ( > sendto(nSk, pstArp, sizeof(struct arpMsg), , &addr, sizeof(addr)))
  159. {
  160. DEBUG(SYSTEM_ERROR, "func->sendto error(%d:%s).", errno, strerror(errno));
  161. close(nSk);
  162. return -;
  163. }
  164.  
  165. /* wait arp reply, and check it */
  166. tm.tv_usec = ;
  167. time(&prevTime);
  168. while (nTimeOut > )
  169. {
  170. FD_ZERO(&fdset);
  171. FD_SET(nSk, &fdset);
  172. tm.tv_sec = nTimeOut;
  173. if (select(nSk + , &fdset, (fd_set *) NULL, (fd_set *) NULL, &tm) < )
  174. {
  175. DEBUG(SYSTEM_ERROR, "func->select error(%d:%s).", errno, strerror(errno));
  176. if (errno != EINTR)
  177. {
  178. nRtVal = ;
  179. }
  180. }
  181. else if (FD_ISSET(nSk, &fdset))
  182. {
  183. if (recv(nSk, pstArp, sizeof(struct arpMsg), ) < )
  184. {
  185. nRtVal = ;
  186. }
  187. if (pstArp->operation == htons(ARPOP_REPLY) &&
  188. bcmp(pstArp->tHaddr, pucLocalMac, ) == &&
  189. *((u_int *) pstArp->sInaddr) == unRemoteIp)
  190. {
  191. //DEBUG(PROCESS_PRINT, "valid arp reply receved for this address.");
  192. nRtVal = ;
  193. break;
  194. }
  195. }
  196. nTimeOut -= time(NULL) - prevTime;
  197. time(&prevTime);
  198. }
  199. close(nSk);
  200. DEBUG(PROCESS_PRINT, "%salid arp replies for this address", nRtVal ? "no v" : "v");
  201. return nRtVal;
  202. }
  203.  
  204. /******************************************************************************
  205. * nArpTblCtl - get/set/del ip<->mac info
  206. * DESCRIPTION: -
  207. * Input:
  208. * Output:
  209. * Returns:
  210. *
  211. * modification history
  212. * --------------------
  213. * 2.00, 2014-12-25 , zengjianrong written
  214. * --------------------
  215. ******************************************************************************/
  216. int nArpTblCtl(ARP_TBL_TRL_ENUM cmd, struct in_addr stRemoteIp, char *pcDevName, unsigned char *pucMac)
  217. {
  218. unsigned int unCmd = ;
  219. unsigned char *pucHwAddr = NULL;
  220. struct sockaddr_in *pSin = NULL;
  221. struct arpreq stArpreq;
  222.  
  223. if (( == stRemoteIp.s_addr)
  224. || (cmd <= ARP_TBL_BEGIN)
  225. || (cmd >= ARP_TBL_END)
  226. || (ARP_TBL_DEL != cmd && NULL == pucMac))
  227. {
  228. DEBUG(SYSTEM_ERROR, "param error.");
  229. return -;
  230. }
  231.  
  232. memset(&stArpreq, , sizeof(struct arpreq));
  233. switch (cmd)
  234. {
  235. case ARP_TBL_GET:
  236. unCmd = SIOCGARP;
  237. break;
  238. case ARP_TBL_DEL:
  239. stArpreq.arp_ha.sa_family = AF_UNSPEC;
  240. unCmd = SIOCDARP;
  241. break;
  242. case ARP_TBL_SET:
  243. stArpreq.arp_ha.sa_family = AF_UNSPEC;
  244. //stArpreq.arp_flags = ATF_PERM | ATF_PUBL | ATF_FORCE_ADD;
  245. stArpreq.arp_flags = ATF_COM;
  246. memcpy((char *)stArpreq.arp_ha.sa_data, pucMac, );
  247. unCmd = SIOCSARP;
  248. break;
  249. default:
  250. return -;
  251. }
  252.  
  253. if (- == fd_arp_tbl)
  254. {
  255. fd_arp_tbl = socket(AF_INET, SOCK_DGRAM, );
  256. if (fd_arp_tbl < )
  257. {
  258. DEBUG(SYSTEM_ERROR, "func->socket error(%d:%s).", errno, strerror(errno));
  259. return -;
  260. }
  261. }
  262.  
  263. pSin = (struct sockaddr_in *) &stArpreq.arp_pa;
  264. pSin->sin_family = AF_INET;
  265. memcpy(&(pSin->sin_addr), &stRemoteIp, sizeof(struct in_addr));
  266. strcpy(stArpreq.arp_dev, pcDevName);
  267.  
  268. if ( > ioctl(fd_arp_tbl, unCmd, &stArpreq))
  269. {
  270. DEBUG(SYSTEM_ERROR, "func->ioctl error(%d:%s).", errno, strerror(errno));
  271. close(fd_arp_tbl);
  272. fd_arp_tbl = -;
  273. return -;
  274. }
  275. else if (ARP_TBL_GET == cmd)
  276. {
  277. pucHwAddr = (unsigned char *) stArpreq.arp_ha.sa_data;
  278. memcpy(pucMac, pucHwAddr, );
  279. if ( == pucMac[] && == pucMac[] && == pucMac[]
  280. && == pucMac[] && == pucMac[] && == pucMac[])
  281. {
  282. return -;
  283. }
  284. }
  285.  
  286. return ;
  287. }
  288.  
  289. int main(int argc, char *argv[])
  290. {
  291. unsigned char aucMac[];
  292. struct in_addr sin_remote_addr;
  293. struct in_addr sin_local_addr;
  294. struct arpMsg stArpMsg;
  295.  
  296. memset(&sin_local_addr, , sizeof(struct in_addr));
  297. memset(&stArpMsg, , sizeof(struct arpMsg));
  298. memset(aucMac, , );
  299.  
  300. if (argc!=)
  301. {
  302. DEBUG(SYSTEM_ERROR, "usage: %s <IP address>\n",argv[]);
  303. return -;
  304. }
  305.  
  306. /* initial global values */
  307. fd_arp_tbl = -;
  308.  
  309. if ( == (inet_aton("138.0.225.226", &sin_local_addr)))
  310. {
  311. DEBUG(SYSTEM_ERROR, "func->inet_aton error(%d:%s).", errno, strerror(errno));
  312. return -;
  313. }
  314.  
  315. if ( == (inet_aton(argv[], &sin_remote_addr)))
  316. {
  317. DEBUG(SYSTEM_ERROR, "func->inet_aton error(%d:%s), '%s' not valid.",
  318. errno, strerror(errno), argv[]);
  319. return -;
  320. }
  321.  
  322. if ( > (nArpTblCtl(ARP_TBL_GET, sin_remote_addr, LOCAL_DEV, aucMac)))
  323. {
  324. DEBUG(PROCESS_PRINT, "no entry in arp_cache for '%s', send arp request.", argv[]);
  325. if ( != (nSendArp(sin_remote_addr.s_addr, sin_local_addr.s_addr,
  326. LOCAL_MAC_ADDR, LOCAL_DEV, &stArpMsg)))
  327. {
  328. DEBUG(SYSTEM_ERROR, "there is no device using '%s', or nSendArp error.", argv[]);
  329. return -;
  330. }
  331. else
  332. {
  333. if ( > (nArpTblCtl(ARP_TBL_SET, sin_remote_addr, LOCAL_DEV, stArpMsg.sHaddr)))
  334. {
  335. DEBUG(SYSTEM_ERROR, "func->nArpTblCtl set error.");
  336. return -;
  337. }
  338. if ( > (nArpTblCtl(ARP_TBL_GET, sin_remote_addr, LOCAL_DEV, aucMac)))
  339. {
  340. DEBUG(PROCESS_PRINT, "there is no device using '%s'.", argv[]);
  341. return ;
  342. }
  343. }
  344. }
  345. DEBUG(PROCESS_PRINT, "%s-->%02x:%02x:%02x:%02x:%02x:%02x.", argv[],
  346. aucMac[], aucMac[], aucMac[], aucMac[], aucMac[], aucMac[]);
  347.  
  348. return ;
  349. }

  测试结果如下:

  1. [root@zeng test]# ifconfig
  2. eth0 Link encap:Ethernet HWaddr :::CC::0E
  3. inet addr:138.0.225.226 Bcast:138.0.255.255 Mask:255.255.0.0
  4. inet6 addr: fe80:::56ff:fecc:990e/ Scope:Link
  5. UP BROADCAST RUNNING MULTICAST MTU: Metric:
  6. RX packets: errors: dropped: overruns: frame:
  7. TX packets: errors: dropped: overruns: carrier:
  8. collisions: txqueuelen:
  9. RX bytes: (154.2 MiB) TX bytes: (17.9 MiB)
  10. Interrupt: Base address:0x2024
  11.  
  12. eth1 Link encap:Ethernet HWaddr :::DE::0E
  13. inet addr:192.168.123.225 Bcast:192.168.123.255 Mask:255.255.255.0
  14. inet6 addr: fe80:::56ff:fede:990e/ Scope:Link
  15. UP BROADCAST RUNNING MULTICAST MTU: Metric:
  16. RX packets: errors: dropped: overruns: frame:
  17. TX packets: errors: dropped: overruns: carrier:
  18. collisions: txqueuelen:
  19. RX bytes: (2.4 MiB) TX bytes: (1016.2 KiB)
  20. Interrupt: Base address:0x20a4
  21.  
  22. eth2 Link encap:Ethernet HWaddr :::DC::0E
  23. inet addr:192.168.213.225 Bcast:192.168.213.255 Mask:255.255.255.0
  24. inet6 addr: fe80:::56ff:fedc:990e/ Scope:Link
  25. UP BROADCAST RUNNING MULTICAST MTU: Metric:
  26. RX packets: errors: dropped: overruns: frame:
  27. TX packets: errors: dropped: overruns: carrier:
  28. collisions: txqueuelen:
  29. RX bytes: (324.9 MiB) TX bytes: (1.3 GiB)
  30. Interrupt: Base address:0x2424
  31.  
  32. lo Link encap:Local Loopback
  33. inet addr:127.0.0.1 Mask:255.0.0.0
  34. inet6 addr: ::/ Scope:Host
  35. UP LOOPBACK RUNNING MTU: Metric:
  36. RX packets: errors: dropped: overruns: frame:
  37. TX packets: errors: dropped: overruns: carrier:
  38. collisions: txqueuelen:
  39. RX bytes: (54.7 KiB) TX bytes: (54.7 KiB)
  40.  
  41. [root@zeng test]# ./getMacFromIp.o 138.0.0.90
  42. [DEBUG] in /mnt/hgfs/source_code_20140312/test/2getMacFromIp.c: nArpTblCtl(), func->ioctl error(:No such device or address).
  43. [DEBUG] in /mnt/hgfs/source_code_20140312/test/2getMacFromIp.c: main(), no entry in arp_cache for '138.0.0.90', send arp request.
  44. [DEBUG] in /mnt/hgfs/source_code_20140312/test/2getMacFromIp.c: nSendArp(), valid arp replies for this address
  45. [DEBUG] in /mnt/hgfs/source_code_20140312/test/2getMacFromIp.c: main(), 138.0.0.90-->:d4:::5b:7c.
  46. [root@zeng test]# ./getMacFromIp.o 138.0.156.125
  47. [DEBUG] in /mnt/hgfs/source_code_20140312/test/2getMacFromIp.c: nArpTblCtl(), func->ioctl error(:No such device or address).
  48. [DEBUG] in /mnt/hgfs/source_code_20140312/test/2getMacFromIp.c: main(), no entry in arp_cache for '138.0.156.125', send arp request.
  49. [DEBUG] in /mnt/hgfs/source_code_20140312/test/2getMacFromIp.c: nSendArp(), no valid arp replies for this address
  50. [DEBUG] in /mnt/hgfs/source_code_20140312/test/2getMacFromIp.c: main(), there is no device using '138.0.156.125', or nSendArp error.
  51. [root@zeng test]#

通过IP获取MAC地址例子(应用层)的更多相关文章

  1. 通过IP获取MAC地址例子(内核层)

    博客地址:http://home.cnblogs.com/u/zengjianrong/ 在内核处理此流程,反而更加简单些,代码如下: #include <net/arp.h> #incl ...

  2. java根据本地Ip获取mac地址

    import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; impo ...

  3. android获取Mac地址和IP地址

    获取Mac地址实际项目中测试了如下几种方法:(1)设备开通Wifi连接,获取到网卡的MAC地址(但是不开通wifi,这种方法获取不到Mac地址,这种方法也是网络上使用的最多的方法) //根据Wifi信 ...

  4. Java获取本机的IP与MAC地址

    有些机器有许多虚拟的网卡,获取IP地址时会出现一些意外,所以需要一些验证: // 获取mac地址 public static String getMacAddress() { try { Enumer ...

  5. .net获取IP和MAC地址

    获取IP  解决request.UserHostAddress取不到真实IP private string GetClientIP()   {    string result = HttpConte ...

  6. 获取平台所有接口的IP和MAC地址

    我们有时候会有获取网口的IP和MAC地址的需求.可以通过ioctl来获取. #include <sys/ioctl.h>#include <net/if.h>#include ...

  7. 获取本机IP、mac地址、计算机名

    python获取本机IP.mac地址.计算机名 在python中获取ip地址和在php中有很大不同,我们先来看一下python 获得本机MAC地址: >>> import uuid ...

  8. Java根据ip地址获取Mac地址,Java获取Mac地址

    Java根据ip地址获取Mac地址,Java获取Mac地址 >>>>>>>>>>>>>>>>>&g ...

  9. Linux 获取本机IP、MAC地址用法大全

    getifaddrs()和struct ifaddrs的使用,获取本机IP ifaddrs结构体定义如下: struct ifaddrs { struct ifaddrs *ifa_next; /* ...

随机推荐

  1. tkinter中的message

    from tkinter import * root =Tk() root.title("message练习") myText = "2019年12月13日,下午一个人, ...

  2. iFrmae_HTML

    iframe(HTML框架) <iframe src="URL"></iframe> 该URL指向的页面 会显示在当前页面的一个窗口上,默认大小为 widt ...

  3. 转 Fortofy扫描漏洞解决方案2

    Fortify漏洞之Portability Flaw: File Separator 和 Poor Error Handling: Return Inside Finally   继续对Fortify ...

  4. 汇编之JCC指令

    版权声明:本文为博主原创文章,转载请附上原文出处链接和本声明.2019-09-06,21:59:16.作者By-----溺心与沉浮----博客园 JCC指令决定它跳不跳转跟别的没关系,只跟EFLAG标 ...

  5. 基于rtmp+nginx 、vlc实现FFmpeg推流与wpf端拉流

    这周在研究基于rtmp+nginx直播流的实现,现总结如下: 0.所需文件: 链接:https://pan.baidu.com/s/1U5gsNI8Rcl684l5gVL6swg 提取码:dli9 1 ...

  6. linux设备驱动程序-设备树(1)-dtb转换成device_node

    linux设备驱动程序-设备树(1)-dtb转换成device_node 本设备树解析基于arm平台 从start_kernel开始 linux最底层的初始化部分在HEAD.s中,这是汇编代码,我们暂 ...

  7. 设置VMware中Kali 共享文件夹

    (软件环境: Vmware Workstation 15.5 Pro , Kali Linux2019.3) 1. VMware设置共享目录 2. 安装VMware-Tools 命令: apt-get ...

  8. 2019面向对象程序设计(Java) 第17周-18周学习指导及要求

    2019面向对象程序设计(Java)第17周-18周学习指导及要求 (2019.12.20-2019.12.31)   学习目标 (1) 理解和掌握线程的优先级属性及调度方法: (2) 掌握线程同步的 ...

  9. 逆向工程文件example完美结合使用PageHelper分页插件及分页不成功原因

    原生的mybatis需要手写sql语句,项目数据库表多了之后,可以让你写sql语句写到手软,于是mybatis官方提供了mybatis-generator:mybatis逆向工程代码生成工具,用于简化 ...

  10. python27期day18:模块和包、作业。

    1.模块和包: 我们今天来讲解一下模块和包,模块我们已经知道是什么东西了,我们现在来看看这个包是个什么? 我说的包可不是女同胞一看见就走不动的包,而是程序中一种组织文件的形式. 只要文件夹下含有__i ...