ARP 探测 C语言实现

#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> 
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netdb.h>  
#include <sys/time.h> 
#include "common_ifaddrs.h"
#include "prod_common_wan.h"


#define    FAILURE   -1
#define    SUCCESS    0
#define    IP_LENGTH  4
#define    MAC_LENGTH 6
#define    ARP_DELAY  20*10000

static unsigned char g_arp_src_ip[IP_LENGTH]   = {0};                						    //要检测的主机IP地址  
static unsigned char g_arp_src_mac[MAC_LENGTH] = {0};   										//要检测的主机的MAC地址  
static unsigned char g_arp_dst_ip[IP_LENGTH]   = {0};                    					    //目标IP地址  
static unsigned char g_arp_dst_mac[MAC_LENGTH] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };    	//ARP广播地址  
static char *g_Network_card_name = NULL;

static struct  tar_arp_packet
{    
    struct ether_header  eh;    
    struct ether_arp     arp;    
};

static int send_arp(int sockfd, struct sockaddr_ll *peer_addr); 
static int recv_arp(int sockfd, struct sockaddr_ll *peer_addr);

/*************************************** 
函数名:get_wan_ip   
描述 : 获取IP地址并转换为unsigned char 型数据
参数:   
    [in] 无  
返回值   
         0:SUCCESS 
        -1:FAILURE  
说明:   
         无
*******************************************/
int get_wan_ip()
{
    int i = 0,j = 0;
    char  *str = NULL;
    unsigned char num[4]={0};
    char tmp[3];
    int n = 0,value=0;
    
    WAN_ID_NUM_ENUM  wan_id = 0;
    WAN_IP_INFO_STRU ip_info;
    
    memset(&ip_info,0x0,sizeof(ip_info));
    if(currently_lte_working_mode())
    {
        wan_id = LTE_WANID;             
    }
    else
    {
        wan_id = ETH_WANID;
    }
    
    file_wan_ip_info_get(wan_id, &ip_info);
    if(0 == strlen(ip_info.wan_ip))
    {
        printf("plaese check internet connection\n");
        return -1;
    }
    //将字符串形式的IP转化为 unsigned char 型
    str = ip_info.wan_ip;
    for(i=0;i<4;i++)
    {
        // 每次最多转化3位字符
        for( j = 0;j<3;j++)
        {
          if((*str == '.') || (*str == '\0'))
          break;
          tmp[j] = *str;
          value = value * 10 + tmp[j] - '0';
          str += 1;
        }

        num[n] = value;
        value = 0;

        if(*str == '\0')
        {
          break;
        }
        else
        {
          str += 1;
          n += 1;
        }
    };
      
    for( i = 0;i<IP_LENGTH;i++)
    {
        g_arp_src_ip[i] = num[i];
    }   

    return 0;
}
/********************************
函数名:get_wan_mac   
描述 : 获取MAC地址
参数:   
    [in] 无  
返回值   
         0:SUCCESS 
        -1:FAILURE  
说明:   
        无  
*********************************/
int get_wan_mac()
{

    int i = 0 ;
    int ret = 0;
    int wanid = 0;
    unsigned char  wan_mac[MAC_LENGTH] = {0};
    char mac_str[32] = {0};
    int sysmode = UGW_SYS_MODE_GW;
    UGW_WAN_CONNECT_TYPE_ENUM wantype;

    memset(&wantype,0x0,sizeof(wantype));
    if(currently_lte_working_mode())
    {
        wanid = LTE_WANID;              
    }
    else
    {
        wanid = ETH_WANID;
    }
    
    wantype = getWanConnType(wanid);
    g_Network_card_name = ifaddrs_get_wan_ifname(wanid, sysmode, wantype);

    if(NULL == g_Network_card_name)
    {
        return -1;
    }
    printf("MAC:Network_card_name:%s\n",g_Network_card_name);
    
    ret = ifaddrs_get_if_netmac("eth1", wan_mac);
    if(ret < 0)
    {
        return -1;
    }
    snprintf(mac_str, sizeof(mac_str), "%02X:%02X:%02X:%02X:%02X:%02X", 
        wan_mac[0], wan_mac[1], wan_mac[2], wan_mac[3], wan_mac[4], wan_mac[5]);


    for( i = 0;i<MAC_LENGTH;i++)
    {
        g_arp_src_mac[i] = wan_mac[i];
    }
    return 0;
    
}

/************************************************
函数名:get_wan_ip   
描述 : 获取IP地址并转换为unsigned char 型数据
参数:   
  [in] 无  
返回值   
  	   无  
说明:   
   	   无  
**************************************************/
int send_arp(int sockfd, struct sockaddr_ll *peer_addr)
{
	int rtval = 0 ;
	struct  tar_arp_packet frame;
	memset(&frame, 0x0, sizeof(struct  tar_arp_packet));
	
//填充以太网头部
    memcpy(frame.eh.ether_dhost, g_arp_dst_mac, MAC_LENGTH);    //目的MAC地址
    memcpy(frame.eh.ether_shost, g_arp_src_mac, MAC_LENGTH);    //源MAC地址
    frame.eh.ether_type = htons(ETHERTYPE_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, g_arp_src_mac, MAC_LENGTH);    //源MAC地址
    memcpy(frame.arp.arp_spa, g_arp_src_ip,  IP_LENGTH);     //源IP地址
    memcpy(frame.arp.arp_tha, g_arp_dst_mac, MAC_LENGTH);    //目的MAC地址
    memcpy(frame.arp.arp_tpa, g_arp_dst_ip,  IP_LENGTH);     //目的IP地址

    rtval = sendto(sockfd, &frame, sizeof(struct  tar_arp_packet), 0, 
			(struct sockaddr*)peer_addr, sizeof(struct sockaddr_ll));  
	if (rtval < 0)
	{
		return FAILURE;
	}
	else
	{
		return SUCCESS;
	}
	
}
/******************************************************** 
函数名: recv_arp   
描述 : 接收ARP回复数据报文并判断是不是对免费ARP的回复。  
参数:   
[in] sockfd -- 创建的socket描述符;  
[in] peer_addr -- 对端的IP信息  
返回值:   
成功: SUCCESS, 失败: FAILURE;  
********************************************************/ 
int recv_arp(int sockfd, struct sockaddr_ll *peer_addr)  
{  
    int rtval = 0; 
    static int i = 0;
    char arp_tpa_buf[32] = {0};
    char src_ip_buf[32] = {0};
    struct  tar_arp_packet frame;  
      
    memset(&frame, 0, sizeof(struct  tar_arp_packet));  
    rtval = recvfrom(sockfd, &frame, sizeof(frame), 0,   
        NULL, NULL); 

    u_short etherType = ntohs(frame.arp.ea_hdr.ar_op);

    sprintf(src_ip_buf,"%d.%d.%d.%d",g_arp_src_ip[0],g_arp_src_ip[1],g_arp_src_ip[2],g_arp_src_ip[3]);
    sprintf(arp_tpa_buf,"%d.%d.%d.%d",frame.arp.arp_tpa[0],frame.arp.arp_tpa[1],
            frame.arp.arp_tpa[2],frame.arp.arp_tpa[3]);

    if(2 == etherType)
    {
        if (0 == strcmp(arp_tpa_buf,src_ip_buf))
        { 
            printf("[%d]Target  IP:%d.%d.%d.%d\t\tTarget Mac:%02x:%02x:%02x:%02x:%02x:%02x\n", i,frame.arp.arp_spa[0],frame.arp.arp_spa[1],
                    frame.arp.arp_spa[2],frame.arp.arp_spa[3],frame.arp.arp_sha[0],frame.arp.arp_sha[1],
                    frame.arp.arp_sha[2],frame.arp.arp_sha[3],frame.arp.arp_sha[4],frame.arp.arp_sha[5]);
            i++;
        }
    }
      
    if (rtval < 0)  
    {  
        return FAILURE;  
    } 
    else
	{
		return SUCCESS;
	} 
} 

int main(int argc,char *argv[])
{
	int rtval  = 0;
    int i      = 0;
    int times  = 0;
	int sockfd = 0;
	struct sockaddr_ll peer_addr;

	//1, 创建一个UDP套接字  SOCK_DGRAM ==> UDP套接字
	if ((sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ARP))) == -1)
	{
		perror("socket failed");
		return -1;
	}
	
	//3,配置参数
	memset(&peer_addr, 0, sizeof(peer_addr));  
    peer_addr.sll_family = PF_PACKET;  

    struct ifreq req;
	bzero(&req, sizeof(struct ifreq));
    strcpy(req.ifr_name, g_Network_card_name);  

    if(ioctl(sockfd, SIOCGIFINDEX, &req) != 0)
    {
    	perror("ioctl()");  
    }

    peer_addr.sll_ifindex = req.ifr_ifindex;  
    peer_addr.sll_protocol = htons(ETH_P_ARP);

	get_wan_mac();
    get_wan_ip();
	while(1)
    {
		if(0 == get_wan_ip())
		{
			break;
		}
		else
	    {
			sleep(2);
	    }
	}

    //初始化目的IP
    for( i = 0;i<4;i++)
    {
        g_arp_dst_ip[i] = g_arp_src_ip[i];
    }
    printf("arp test start**********************************************************\n");
	
    for(i=1;i<255;i++)
    {
        g_arp_dst_ip[3] = i;
        //arp发送
        rtval = send_arp(sockfd, &peer_addr);  
		
        times = 3;
        while(times--)
        {
            //arp接收
            rtval = recv_arp(sockfd, &peer_addr);
            if(FAILURE == rtval)
            { 
                usleep(ARP_DELAY);
                rtval = send_arp(sockfd, &peer_addr);
                continue;
            }
            else //success
            {
                break;
            }
        }
        
        usleep(ARP_DELAY);
    }
	
	close(sockfd);
    printf("arp test end*************************************************************\n");
   
	return 0;
}

  • 2
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值