免费ARP简单介绍和程序编写
2016-05-24 13:56
519 查看
转自:
http://blog.csdn.net/cfjtaishan/article/details/8929718
免费ARP简单介绍和程序编写
免费ARP,在网络上有很多的介绍。在《tcp/ip协议卷》中的第四章也有介绍,下面再啰嗦一下介绍其作用和操作:
免费ARP,主要用于检测网络中IP地址是否冲突,它是一种功能而非协议。当设备重启或代理ARP功能开启时就会向本地网络主动发免费ARP以检测IP地址是否冲突。免费ARP是以源、目的IP都是自己,源MAC也是自己,目标MAC是广播,即向自己所在网络请求自己的MAC地址,当网络中如果有其他主机使用了与自己相同的IP地址,他就会给主机一个ARP回复,此时如果发免费ARP的主机收到了回复就证明自己所用的IP地址有冲突,如果没有收到回复则说明没有IP地址冲突。
(若上面的文字有雷同,则以别人的文章为主;若有版权请告知我,本人会在24小时撤掉,谢谢~~~)
下面是免费ARP的代码,作为一个参考吧:
[cpp]
view plain
copy
/////////////////////////////////////////////////////////////////////////////////
// 文件名: arp_func.c
// 作者: cfjtaishan
// 版本: 1.0
// 日期: 2013-05-14
// 描述: 免费ARP--用于检测IP地址是否冲突.
// 历史记录:
/////////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/if_packet.h>
#include <netdb.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <net/ethernet.h>
#include <netinet/ether.h>
#include <net/if.h>
#include <netinet/ip.h>
#define FAILURE -1
#define SUCCESS 0
unsigned char src_ip[4] = { 192, 168, 9, 118 }; //要检测的主机IP地址
unsigned char src_mac[6] = {0x00, 0x0c, 0x29, 0x4b, 0x6c, 0x13}; //要检测的主机的MAC地址
unsigned char dst_ip[4] = { 192, 168, 9, 118 }; //目标IP地址
unsigned char dst_mac[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; //ARP广播地址
int send_arp(int sockfd, struct sockaddr_ll *peer_addr);
int recv_arp(int sockfd, struct sockaddr_ll *peer_addr);
//ARP封装包
typedef struct _tagARP_PACKET{
struct ether_header eh;
struct ether_arp arp;
}ARP_PACKET_OBJ, *ARP_PACKET_HANDLE;
int main(int argc, char *argv[])
{
int sockfd;
int rtval = -1;
struct sockaddr_ll peer_addr;
//创建socket
sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP));
if (sockfd < 0)
{
fprintf(stderr, "socket error: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
memset(&peer_addr, 0, sizeof(peer_addr));
peer_addr.sll_family = AF_PACKET;
struct ifreq req;
bzero(&req, sizeof(struct ifreq));
strcpy(req.ifr_name, "eth0");
if(ioctl(sockfd, SIOCGIFINDEX, &req) != 0)
perror("ioctl()");
peer_addr.sll_ifindex = req.ifr_ifindex;
peer_addr.sll_protocol = htons(ETH_P_ARP);
//peer_addr.sll_family = AF_PACKET;
while (1)
{
rtval = send_arp(sockfd, &peer_addr);
if (FAILURE == rtval)
{
fprintf(stderr, "Send arp socket failed: %s\n", strerror(errno));
}
rtval = recv_arp(sockfd, &peer_addr);
if (rtval == SUCCESS)
{
printf ("Get packet from peer and IP conflicts!\n");
}
else if (rtval == FAILURE)
{
fprintf(stderr, "Recv arp IP not conflicts: %s\n", strerror(errno));
}
else
{
fprintf(stderr, "Recv arp socket failed: %s\n", strerror(errno));
}
//sleep(1);
}
return 0;
}
//////////////////////////////////////////////////////////////////////////
// 函数名: send_arp
// 描述 : 填充ARP数据包报文并发送出去。
// 参数:
// [in] sockfd -- 创建的socket描述符;
// [in] peer_addr -- 对端的IP信息
// 返回值:
// 成功: SUCCESS, 失败: FAILURE;
// 说明:
//////////////////////////////////////////////////////////////////////////
int send_arp(int sockfd, struct sockaddr_ll *peer_addr)
{
int rtval;
ARP_PACKET_OBJ frame;
memset(&frame, 0x00, sizeof(ARP_PACKET_OBJ));
//填充以太网头部
memcpy(frame.eh.ether_dhost, dst_mac, 6); //目的MAC地址
memcpy(frame.eh.ether_shost, src_mac, 6); //源MAC地址
frame.eh.ether_type = htons(ETH_P_ARP); //协议
//填充ARP报文头部
frame.arp.ea_hdr.ar_hrd = htons(ARPHRD_ETHER); //硬件类型
frame.arp.ea_hdr.ar_pro = htons(ETHERTYPE_IP); //协议类型 ETHERTYPE_IP | ETH_P_IP
frame.arp.ea_hdr.ar_hln = 6; //硬件地址长度
frame.arp.ea_hdr.ar_pln = 4; //协议地址长度
frame.arp.ea_hdr.ar_op = htons(ARPOP_REQUEST); //ARP请求操作
memcpy(frame.arp.arp_sha, src_mac, 6); //源MAC地址
memcpy(frame.arp.arp_spa, src_ip, 4); //源IP地址
memcpy(frame.arp.arp_tha, dst_mac, 6); //目的MAC地址
memcpy(frame.arp.arp_tpa, dst_ip, 4); //目的IP地址
rtval = sendto(sockfd, &frame, sizeof(ARP_PACKET_OBJ), 0,
(struct sockaddr*)peer_addr, sizeof(struct sockaddr_ll));
if (rtval < 0)
{
return FAILURE;
}
return SUCCESS;
}
[cpp]
view plain
copy
//////////////////////////////////////////////////////////////////////////
// 函数名: recv_arp
// 描述 : 接收ARP回复数据报文并判断是不是对免费ARP的回复。
// 参数:
// [in] sockfd -- 创建的socket描述符;
// [in] peer_addr -- 对端的IP信息
// 返回值:
// 成功: SUCCESS, 失败: FAILURE;
// 说明:
// 若是对免费arp请求的回复则返回:SUCCESS.
//////////////////////////////////////////////////////////////////////////
int recv_arp(int sockfd, struct sockaddr_ll *peer_addr)
{
int rtval;
ARP_PACKET_OBJ frame;
memset(&frame, 0, sizeof(ARP_PACKET_OBJ));
rtval = recvfrom(sockfd, &frame, sizeof(frame), 0,
NULL, NULL);
//判断是否接收到数据并且是否为回应包
if (htons(ARPOP_REPLY) == frame.arp.ea_hdr.ar_op && rtval > 0)
{
//判断源地址是否为冲突的IP地址
if (memcmp(frame.arp.arp_spa, src_ip, 4) == 0)
{
fprintf(stdout, "IP address is common~\n");
return SUCCESS;
}
}
if (rtval < 0)
{
return FAILURE;
}
return FAILURE;
}
该程序可以测试局域网中的某个IP地址是否有冲突的,以便于确定该地址是否可以作为本机的IP地址。下面是通过wireshark抓到了免费的ARP数据包,以及回应包,如下:
http://blog.csdn.net/cfjtaishan/article/details/8929718
免费ARP简单介绍和程序编写
免费ARP,在网络上有很多的介绍。在《tcp/ip协议卷》中的第四章也有介绍,下面再啰嗦一下介绍其作用和操作:免费ARP,主要用于检测网络中IP地址是否冲突,它是一种功能而非协议。当设备重启或代理ARP功能开启时就会向本地网络主动发免费ARP以检测IP地址是否冲突。免费ARP是以源、目的IP都是自己,源MAC也是自己,目标MAC是广播,即向自己所在网络请求自己的MAC地址,当网络中如果有其他主机使用了与自己相同的IP地址,他就会给主机一个ARP回复,此时如果发免费ARP的主机收到了回复就证明自己所用的IP地址有冲突,如果没有收到回复则说明没有IP地址冲突。
(若上面的文字有雷同,则以别人的文章为主;若有版权请告知我,本人会在24小时撤掉,谢谢~~~)
下面是免费ARP的代码,作为一个参考吧:
[cpp]
view plain
copy
/////////////////////////////////////////////////////////////////////////////////
// 文件名: arp_func.c
// 作者: cfjtaishan
// 版本: 1.0
// 日期: 2013-05-14
// 描述: 免费ARP--用于检测IP地址是否冲突.
// 历史记录:
/////////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/if_packet.h>
#include <netdb.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <net/ethernet.h>
#include <netinet/ether.h>
#include <net/if.h>
#include <netinet/ip.h>
#define FAILURE -1
#define SUCCESS 0
unsigned char src_ip[4] = { 192, 168, 9, 118 }; //要检测的主机IP地址
unsigned char src_mac[6] = {0x00, 0x0c, 0x29, 0x4b, 0x6c, 0x13}; //要检测的主机的MAC地址
unsigned char dst_ip[4] = { 192, 168, 9, 118 }; //目标IP地址
unsigned char dst_mac[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; //ARP广播地址
int send_arp(int sockfd, struct sockaddr_ll *peer_addr);
int recv_arp(int sockfd, struct sockaddr_ll *peer_addr);
//ARP封装包
typedef struct _tagARP_PACKET{
struct ether_header eh;
struct ether_arp arp;
}ARP_PACKET_OBJ, *ARP_PACKET_HANDLE;
int main(int argc, char *argv[])
{
int sockfd;
int rtval = -1;
struct sockaddr_ll peer_addr;
//创建socket
sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP));
if (sockfd < 0)
{
fprintf(stderr, "socket error: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
memset(&peer_addr, 0, sizeof(peer_addr));
peer_addr.sll_family = AF_PACKET;
struct ifreq req;
bzero(&req, sizeof(struct ifreq));
strcpy(req.ifr_name, "eth0");
if(ioctl(sockfd, SIOCGIFINDEX, &req) != 0)
perror("ioctl()");
peer_addr.sll_ifindex = req.ifr_ifindex;
peer_addr.sll_protocol = htons(ETH_P_ARP);
//peer_addr.sll_family = AF_PACKET;
while (1)
{
rtval = send_arp(sockfd, &peer_addr);
if (FAILURE == rtval)
{
fprintf(stderr, "Send arp socket failed: %s\n", strerror(errno));
}
rtval = recv_arp(sockfd, &peer_addr);
if (rtval == SUCCESS)
{
printf ("Get packet from peer and IP conflicts!\n");
}
else if (rtval == FAILURE)
{
fprintf(stderr, "Recv arp IP not conflicts: %s\n", strerror(errno));
}
else
{
fprintf(stderr, "Recv arp socket failed: %s\n", strerror(errno));
}
//sleep(1);
}
return 0;
}
//////////////////////////////////////////////////////////////////////////
// 函数名: send_arp
// 描述 : 填充ARP数据包报文并发送出去。
// 参数:
// [in] sockfd -- 创建的socket描述符;
// [in] peer_addr -- 对端的IP信息
// 返回值:
// 成功: SUCCESS, 失败: FAILURE;
// 说明:
//////////////////////////////////////////////////////////////////////////
int send_arp(int sockfd, struct sockaddr_ll *peer_addr)
{
int rtval;
ARP_PACKET_OBJ frame;
memset(&frame, 0x00, sizeof(ARP_PACKET_OBJ));
//填充以太网头部
memcpy(frame.eh.ether_dhost, dst_mac, 6); //目的MAC地址
memcpy(frame.eh.ether_shost, src_mac, 6); //源MAC地址
frame.eh.ether_type = htons(ETH_P_ARP); //协议
//填充ARP报文头部
frame.arp.ea_hdr.ar_hrd = htons(ARPHRD_ETHER); //硬件类型
frame.arp.ea_hdr.ar_pro = htons(ETHERTYPE_IP); //协议类型 ETHERTYPE_IP | ETH_P_IP
frame.arp.ea_hdr.ar_hln = 6; //硬件地址长度
frame.arp.ea_hdr.ar_pln = 4; //协议地址长度
frame.arp.ea_hdr.ar_op = htons(ARPOP_REQUEST); //ARP请求操作
memcpy(frame.arp.arp_sha, src_mac, 6); //源MAC地址
memcpy(frame.arp.arp_spa, src_ip, 4); //源IP地址
memcpy(frame.arp.arp_tha, dst_mac, 6); //目的MAC地址
memcpy(frame.arp.arp_tpa, dst_ip, 4); //目的IP地址
rtval = sendto(sockfd, &frame, sizeof(ARP_PACKET_OBJ), 0,
(struct sockaddr*)peer_addr, sizeof(struct sockaddr_ll));
if (rtval < 0)
{
return FAILURE;
}
return SUCCESS;
}
[cpp]
view plain
copy
//////////////////////////////////////////////////////////////////////////
// 函数名: recv_arp
// 描述 : 接收ARP回复数据报文并判断是不是对免费ARP的回复。
// 参数:
// [in] sockfd -- 创建的socket描述符;
// [in] peer_addr -- 对端的IP信息
// 返回值:
// 成功: SUCCESS, 失败: FAILURE;
// 说明:
// 若是对免费arp请求的回复则返回:SUCCESS.
//////////////////////////////////////////////////////////////////////////
int recv_arp(int sockfd, struct sockaddr_ll *peer_addr)
{
int rtval;
ARP_PACKET_OBJ frame;
memset(&frame, 0, sizeof(ARP_PACKET_OBJ));
rtval = recvfrom(sockfd, &frame, sizeof(frame), 0,
NULL, NULL);
//判断是否接收到数据并且是否为回应包
if (htons(ARPOP_REPLY) == frame.arp.ea_hdr.ar_op && rtval > 0)
{
//判断源地址是否为冲突的IP地址
if (memcmp(frame.arp.arp_spa, src_ip, 4) == 0)
{
fprintf(stdout, "IP address is common~\n");
return SUCCESS;
}
}
if (rtval < 0)
{
return FAILURE;
}
return FAILURE;
}
该程序可以测试局域网中的某个IP地址是否有冲突的,以便于确定该地址是否可以作为本机的IP地址。下面是通过wireshark抓到了免费的ARP数据包,以及回应包,如下:
相关文章推荐
- 回文数猜想
- C语言字符串数组与字符串指针详解
- 第10 11周 项目三 警察与厨师 (1)
- JS this
- 第11周-课后实践(4)
- linux基础命令学习(六)文件的特殊属性
- BZOJ1036 [ZJOI2008] 树的统计Count
- Mysql Join语法解析与性能分析
- Android Studio 代码混淆Gradle编译报input jar file is specified twice
- hdu 1385 Minimum Transport Cost(最短路+输出路径)
- 数据结构 --- 栈和队列
- SQL Server 维护计划实现数据库备份
- android之MTP框架和流程分析
- s3cmd 操作手册
- hive sql 语句学习
- 前端福利!10个短小却超实用的JavaScript 代码段
- textView结合selector点击改变文字颜色
- ? extends T 与 ? super T
- 【例题】【动规】NKOJ 1796 数字金字塔
- Android 反编译、Smali插桩、二次打包