無料ARPの簡単な紹介とプログラムの作成


無料ARPは、ネットでいろいろ紹介されています.「tcp/ipプロトコルボリューム」の第4章でも紹介されていますが、その役割と操作について説明します.
無料ARPは、主にネットワーク内のIPアドレスが競合しているかどうかを検出するために使用され、プロトコルではなく機能です.デバイスが再起動したり、プロキシARP機能がオンになったりすると、IPアドレスが競合しているかどうかを検出するために、ローカルネットワークに無料ARPがアクティブに送信されます.無料ARPはソース、目的IPはすべて自分で、ソースMACも自分で、目標MACは放送で、つまり自分の所在するネットワークに自分のMACアドレスを要求して、ネットワークの中でもし他のホストが自分と同じIPアドレスを使ったならば、彼はホストに1つの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
", 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
", strerror(errno)); } rtval = recv_arp(sockfd, &peer_addr); if (rtval == SUCCESS) { printf ("Get packet from peer and IP conflicts!
"); } else if (rtval == FAILURE) { fprintf(stderr, "Recv arp IP not conflicts: %s
", strerror(errno)); } else { fprintf(stderr, "Recv arp socket failed: %s
", 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~
"); return SUCCESS; } } if (rtval < 0) { return FAILURE; } return FAILURE; }

このプログラムは、ローカルエリアネットワーク内のIPアドレスが競合しているかどうかをテストし、そのアドレスがホストのIPアドレスとして使用できるかどうかを判断することができる.以下はwiresharkで無料のARPパケットを捕まえたものと、以下のような応答パケットです.