Linux平台使用原始Socket发送ARP报文

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <linux/if_packet.h>
#include <linux/if_arp.h>
#include <netinet/in.h>
#include <arpa/inet.h>


#define MAC_LEN   (6)
#define IP_LEN    (4)
struct Eth_hread
{
    unsigned char dst_mac[MAC_LEN];
    unsigned char src_mac[MAC_LEN];
    unsigned short type;
}__attribute__ ((__packed__));

struct Arp_t
{
    unsigned short h_type;  // 硬件类型 eth = 1
    unsigned short p_type;  // 协议类型 ipv4 = 0x0800
    unsigned char mac_len; // 硬件地址长度
    unsigned char ip_len;   // 协议地址长度
    unsigned short op;     // 操作码,0x1=ARP请求,0x2=ARP应答
    unsigned char send_mac[MAC_LEN];
    unsigned char send_ip[IP_LEN];
    unsigned char dst_mac[MAC_LEN];
    unsigned char dst_ip[IP_LEN];
    unsigned char reserve[18];
}__attribute__ ((__packed__));

struct Arp_pkt
{
    struct Eth_hread eth_head;   
    struct Arp_t arp; 
}__attribute__ ((__packed__));

const static unsigned char eth_dst_mac[5][MAC_LEN] = 
			{{0x00, 0x03, 0xc0, 0xa8, 0xfd, 0x03},
			 {0x00, 0x03, 0xde, 0x6f, 0x70, 0x03},
			 {0x00, 0x03, 0xc4, 0x05, 0x01, 0x03},
			 {0x00, 0x03, 0xc4, 0x05, 0x02, 0x03},
			 {0x00, 0x03, 0xc4, 0x05, 0x03, 0x03}};
const static unsigned char erh_src_mac[MAC_LEN] = {0x00, 0x50, 0x56, 0x2f, 0xb6, 0x33};
#define ARP_TYPE   (0x0806)
void eth_head_init(struct Eth_hread* head, const unsigned char* dst_mac, 
		const unsigned char* src_mac)
{
    memcpy(head->dst_mac, dst_mac, MAC_LEN);
    memcpy(head->src_mac, src_mac, IP_LEN);
    head->type = htons(ARP_TYPE);
}

const static unsigned char arp_send_mac[5][MAC_LEN] = 
			{{0x00, 0x00, 0x08, 0x0a, 0x00, 0x64},
			 {0x00, 0x01, 0x08, 0x0a, 0x01, 0x64},
			 {0x00, 0x02, 0x08, 0x0a, 0x02, 0x64},
			 {0x00, 0x03, 0x08, 0x0a, 0x03, 0x64},
			 {0x00, 0x04, 0x08, 0x0a, 0x04, 0x64}};
const static unsigned char arp_send_ip[5][IP_LEN] = 
			{{0xc0, 0xa8, 0xfd, 0x64},
			 {0xde, 0x6f, 0x70, 0x64},
			 {0xc4, 0x05, 0x01, 0x64},
			 {0xc4, 0x05, 0x02, 0x64},
			 {0xc4, 0x05, 0x03, 0x64}};
const static unsigned char arp_dst_ip[5][IP_LEN] = 
			{{0xc0, 0xa8, 0xfd, 0x03},
			 {0xde, 0x6f, 0x70, 0x03},
			 {0xc4, 0x05, 0x01, 0x03},
			 {0xc4, 0x05, 0x02, 0x03},
			 {0xc4, 0x05, 0x03, 0x03}};
void arp_replay_init(struct Arp_t* arp, const unsigned char* send_mac, 
		const unsigned char* send_ip, const unsigned char* dst_mac, 
		unsigned const char* dst_ip)
{
    arp->h_type = htons(ARPHRD_ETHER);
    arp->p_type = htons(ETHERTYPE_IP);
    arp->mac_len = MAC_LEN;
    arp->ip_len = IP_LEN;
    arp->op = htons(ARPOP_REPLY);  // ARPOP_REPLY ARPOP_REQUEST
    memcpy(arp->send_mac, send_mac, MAC_LEN);
    memcpy(arp->send_ip, send_ip, IP_LEN);
    memcpy(arp->dst_mac, dst_mac, MAC_LEN);
    memcpy(arp->dst_ip, dst_ip, IP_LEN);
    memset(arp->reserve, 0, sizeof(arp->reserve));
}

#define print_errno(fmt, ...) \
    printf("[%d] errno=%d (%s) #" fmt, \
        __LINE__, errno, strerror(errno), ##__VA_ARGS__)
 
void arp_init(struct Arp_pkt* pkt, int cnt)
{
	int index = cnt % 5;
	int net = index;
	static int val = 0, per = 0;
	eth_head_init(&pkt->eth_head, eth_dst_mac[net], erh_src_mac);
	arp_replay_init(&pkt->arp, arp_send_mac[net], arp_send_ip[net], 
			eth_dst_mac[net], arp_dst_ip[net]);
	
    pkt->arp.send_mac[MAC_LEN - 1] = val;
    pkt->arp.send_ip[IP_LEN - 1] = val;
    ++per;
    if (5 == per) {
    	per = 0;
    	++val;
    	if ((3 == val)|| (100 == val))
    		++val;
    	if (255 == val)
    		val = 0;
	}
} 
 
int main(int argc,char** argv)
{
    struct ifreq ifr;
    struct sockaddr_ll sll;
    struct Arp_pkt arp_pkt;
    int skfd, ret = 0;
    unsigned char cnt = 0;
    unsigned char *mac, *ip;

    /*创建原始套接字*/
    skfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
    if (skfd < 0) {
        print_errno("socket() failed! \n");
        return -1;
    }
    bzero(&ifr, sizeof(ifr));
    strcpy(ifr.ifr_name, "ens33");
    if (-1 == ioctl(skfd, SIOCGIFINDEX, &ifr)) {
        close(skfd);
        print_errno("ioctl() SIOCGIFINDEX failed!\n");
        return -1;
    }
    printf("ifr_ifindex = %d\n", ifr.ifr_ifindex);
 
    bzero(&sll, sizeof(sll));
    sll.sll_ifindex  = ifr.ifr_ifindex;
    sll.sll_family   = PF_PACKET;
    sll.sll_protocol = htons(ETH_P_ALL);
	
    while (1) {
    	if (cnt != 3) {
			arp_init(&arp_pkt, cnt);
			ret = sendto(skfd, &arp_pkt, sizeof(struct Arp_pkt), \
					0, (struct sockaddr*)&sll, sizeof(sll));
			if (ret < 0) {
				close(skfd);
				print_errno("sendto() failed!\n");
				return -1;
			} else {
				mac = (unsigned char*)arp_pkt.arp.send_mac;
				ip = (unsigned char*)arp_pkt.arp.send_ip;
				printf("send ip %.3u:%.3u:%.3u:%.3u, ", ip[0], ip[1], ip[2], ip[3]);
				printf("send mac %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", 
						mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
			}
		}
		++cnt;
		if (cnt == 254)
			cnt = 1;
		usleep(100 * 1000);
    }
    close(skfd);
    return ret;
}
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值