免费ARP简单介绍和程序编写

原创 2013年05月15日 13:40:17

免费ARP,在网络上有很多的介绍。在《tcp/ip协议卷》中的第四章也有介绍,下面再啰嗦一下介绍其作用和操作:

免费ARP,主要用于检测网络中IP地址是否冲突,它是一种功能而非协议。当设备重启或代理ARP功能开启时就会向本地网络主动发免费ARP以检测IP地址是否冲突。免费ARP是以源、目的IP都是自己,源MAC也是自己,目标MAC是广播,即向自己所在网络请求自己的MAC地址,当网络中如果有其他主机使用了与自己相同的IP地址,他就会给主机一个ARP回复,此时如果发免费ARP的主机收到了回复就证明自己所用的IP地址有冲突,如果没有收到回复则说明没有IP地址冲突。

(若上面的文字有雷同,则以别人的文章为主;若有版权请告知我,本人会在24小时撤掉,谢谢~~~)

下面是免费ARP的代码,作为一个参考吧:

/////////////////////////////////////////////////////////////////////////////////
// 文件名: 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;
}

//////////////////////////////////////////////////////////////////////////
// 函数名: 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数据包,以及回应包,如下:


使用ioctl SIOCSIFHWADDR设置MAC要使用ARPHRD_ETHER

使用SIOCSIFHWADDR设置MAC要使用ARPHRD_ETHER,且要先停用网络接口。 #include stdio.h> #include string.h> ...

Linux内核ARP的处理函数分析(arp_rcv, arp_send)

Linux内核ARP的处理函数分析(arp_rcv, arp_send) int arp_rcv(struct sk_buff *skb, struct net_device *dev,    ...
  • dayancn
  • dayancn
  • 2015年04月26日 23:19
  • 1926

利用原始套接字抓取数据

项目需求,需要从链路层抓包,分析实现网络登录认证功能,现在网上找到两个不错的抓包程序,参考此文章,顺利完成任务,现将此文章收藏与此,便参考,同时感谢文章版主,谢谢! 一:抓包分析:http://blo...

arp_send()函数分析

  (代码基于linux2.4.0)void arp_send(int type,/*arp协议编码,如ARPOP_REPLY(arp响应)、ARPOP_REQUEST(arp请求)等*/      ...

socket()参数详解

原文链接:http://nhp19850407.blog.163.com/blog/static/241587520104129953564/ sock_raw(注意一定要在root下使用)原始套接...

ARP协议分析

前言:ARP协议的作用:1. 什么是ARP?   ARP (Address Resolution Protocol) 是个地址解析协议。最直白的说法是:在IP以太网中,当一个上层协议要发包时,有了该节...
  • tigerjb
  • tigerjb
  • 2012年03月14日 10:51
  • 39450

linux 下C++实现 ARP发布,和ARP监听

linux 下C++实现 ARP发布,和ARP监听

ARP C++实现源代码

转自:不变hi.baidu.com/wuxiaoming1733/blog/item/f7cebd191cfeb35a43a9ad92.html #ifndef MY_ARP_CHE...
  • fjb2080
  • fjb2080
  • 2012年02月03日 17:38
  • 5740

ARP协议(4)ARP编程

之前的几篇文章,分别介绍了 ARP 协议格式,在vs2012里配置winpcap环境,我们该做的准备都已经做完了,现在我们真正来实现了。 一、定义数据结构 根据ARP的协议格式...

ARP协议详解及如何编程实现ARP攻击

ARP协议详解及如何编程实现ARP攻击[转载]   一.             关于ARP协议的基础知识 1.ARP的工作原理 本来我不想在此重复那些遍地都是的关...
  • aasmfox
  • aasmfox
  • 2015年12月25日 08:13
  • 2086
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:免费ARP简单介绍和程序编写
举报原因:
原因补充:

(最多只允许输入30个字)