关闭

Linux下IP冲突检测程序源码及分析(利用免费arp)---感谢原作者

3052人阅读 评论(5) 收藏 举报
分类:

       由于没有找到源代码原作者, 所以就给出一个间接的转载地址:http://blog.csdn.net/wanxiao009/article/details/5622296, 再次感谢源代码原作者奋斗


       该程序运行在linux环境下,可以检测ip冲突, 我试过, 挺靠谱的,现摘录如下:(该程序涉及免费arp, 关于免费arp的概念和原理, 请自己在网上学习)

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

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
                
#include <netinet/in.h> 
#include <netinet/if_ether.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <arpa/inet.h>  
    
#define MAC_BCAST_ADDR      (unsigned char *) "/xff/xff/xff/xff/xff/xff"
#define ETH_INTERFACE       "eth0"

struct arpMsg {
    struct ethhdr ethhdr;       /* Ethernet header */
    u_short htype;              /* hardware type (must be ARPHRD_ETHER) */
    u_short ptype;              /* protocol type (must be ETH_P_IP) */
    u_char  hlen;               /* hardware address length (must be 6) */
    u_char  plen;               /* protocol address length (must be 4) */
    u_short operation;          /* ARP opcode */
    u_char  sHaddr[6];          /* sender's hardware address */
    u_char  sInaddr[4];         /* sender's IP address */
    u_char  tHaddr[6];          /* target's hardware address */
    u_char  tInaddr[4];         /* target's IP address */
    u_char  pad[18];            /* pad for min. Ethernet payload (60 bytes) */
};

struct server_config_t {
    u_int32_t server;       /* Our IP, in network order */
    u_int32_t start;        /* Start address of leases, network order */
    u_int32_t end;          /* End of leases, network order */
    struct option_set *options; /* List of DHCP options loaded from the config file */
    char *interface;        /* The name of the interface to use */
    int ifindex;            /* Index number of the interface to use */
    unsigned char arp[6];       /* Our arp address */
    unsigned long lease;        /* lease time in seconds (host order) */
    unsigned long max_leases;   /* maximum number of leases (including reserved address) */
    char remaining;         /* should the lease file be interpreted as lease time remaining, or
                     * as the time the lease expires */
    unsigned long auto_time;    /* how long should udhcpd wait before writing a config file.
                     * if this is zero, it will only write one on SIGUSR1 */
    unsigned long decline_time;     /* how long an address is reserved if a client returns a
                         * decline message */
    unsigned long conflict_time;    /* how long an arp conflict offender is leased for */
    unsigned long offer_time;   /* how long an offered address is reserved */
    unsigned long min_lease;    /* minimum lease a client can request*/
    char *lease_file;
    char *pidfile;
    char *notify_file;      /* What to run whenever leases are written */
    u_int32_t siaddr;       /* next server bootp option */
    char *sname;            /* bootp server name */
    char *boot_file;        /* bootp boot file option */
};  

struct server_config_t server_config;           


/*参数分别表示 网卡设备类型 接口检索索引 主机IP地址 主机arp地址*/
int read_interface(char *interface, int *ifindex, u_int32_t *addr, unsigned char *arp)
{
    int fd;
    /*ifreq结构定义在/usr/include/net/if.h,用来配置ip地址,激活接口,配置MTU等接口信息的。
    其中包含了一个接口的名字和具体内容——(是个共用体,有可能是IP地址,广播地址,子网掩码,MAC号,MTU或其他内容)。
    ifreq包含在ifconf结构中。而ifconf结构通常是用来保存所有接口的信息的。
    */
    struct ifreq ifr;
    struct sockaddr_in *our_ip;

    memset(&ifr, 0, sizeof(struct ifreq));
    /*建立一个socket函数,SOCK_RAW是为了获取第三个参数的IP包数据,
     IPPROTO_RAW提供应用程序自行指定IP头部的功能。
    */
    if((fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) >= 0) {
        ifr.ifr_addr.sa_family = AF_INET;
        /*将网卡类型赋值给ifr_name*/
        strcpy(ifr.ifr_name, interface);

        if (addr) {
            /*SIOCGIFADDR用于检索接口地址*/
            if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
                /*获取本机IP地址,addr是一个指向该地址的指针*/
                our_ip = (struct sockaddr_in *) &ifr.ifr_addr;
                *addr = our_ip->sin_addr.s_addr;
                printf("%s (our ip) = %s/n", ifr.ifr_name, inet_ntoa(our_ip->sin_addr));
            } else {
                printf("SIOCGIFADDR failed, is the interface up and configured?: %s/n",
                        strerror(errno));
                return -1;
            }
        }

        /*SIOCGIFINDEX用于检索接口索引*/
        if (ioctl(fd, SIOCGIFINDEX, &ifr) == 0) {
            printf("adapter index %d/n", ifr.ifr_ifindex);
            /*指针ifindex 获取索引*/
            *ifindex = ifr.ifr_ifindex;
        } else {
            printf("SIOCGIFINDEX failed!: %s/n", strerror(errno));
            return -1;
        }
        /*SIOCGIFHWADDR用于检索硬件地址*/
        if (ioctl(fd, SIOCGIFHWADDR, &ifr) == 0) {
            /*所获取的硬件地址复制到结构server_config的数组arp[6]参数中*/
            memcpy(arp, ifr.ifr_hwaddr.sa_data, 6);
            printf("adapter hardware address %02x:%02x:%02x:%02x:%02x:%02x/n",
                arp[0], arp[1], arp[2], arp[3], arp[4], arp[5]);
        } else {
            printf("SIOCGIFHWADDR failed!: %s/n", strerror(errno));
            return -1;
        }
    }
    else {
        printf("socket failed!: %s/n", strerror(errno));
        return -1;
    }
    close(fd);
    return 0;
}


/*参数说明 目标IP地址,本机IP地址,本机mac地址,网卡类型*/
int arpping(u_int32_t yiaddr, u_int32_t ip, unsigned char *mac, char *interface)
{
    int timeout = 2;
    int optval = 1;
    int s;                      /* socket */
    int rv = 1;                 /* return value */
    struct sockaddr addr;       /* for interface name */
    struct arpMsg arp;
    fd_set fdset;
    struct timeval tm;
    time_t prevTime;

    /*socket发送一个arp包*/
    if ((s = socket (PF_PACKET, SOCK_PACKET, htons(ETH_P_ARP))) == -1) {
        printf("Could not open raw socket/n");
        return -1;
    }
    
    /*设置套接口类型为广播,把这个arp包是广播到这个局域网*/
    if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval)) == -1) {
        printf("Could not setsocketopt on raw socket/n");
        close(s);
        return -1;
    }

    /* 对arp设置,这里按照arp包的封装格式赋值即可,详见http://blog.csdn.net/wanxiao009/archive/2010/05/21/5613581.aspx */
    memset(&arp, 0, sizeof(arp));
    memcpy(arp.ethhdr.h_dest, MAC_BCAST_ADDR, 6);   /* MAC DA */
    memcpy(arp.ethhdr.h_source, mac, 6);        /* MAC SA */
    arp.ethhdr.h_proto = htons(ETH_P_ARP);      /* protocol type (Ethernet) */
    arp.htype = htons(ARPHRD_ETHER);        /* hardware type */
    arp.ptype = htons(ETH_P_IP);            /* protocol type (ARP message) */
    arp.hlen = 6;                   /* hardware address length */
    arp.plen = 4;                   /* protocol address length */
    arp.operation = htons(ARPOP_REQUEST);       /* ARP op code */
    *((u_int *) arp.sInaddr) = ip;          /* source IP address */
    memcpy(arp.sHaddr, mac, 6);         /* source hardware address */
    *((u_int *) arp.tInaddr) = yiaddr;      /* target IP address */

    memset(&addr, 0, sizeof(addr));
    strcpy(addr.sa_data, interface);
    /*发送arp请求*/
    if (sendto(s, &arp, sizeof(arp), 0, &addr, sizeof(addr)) < 0)
        rv = 0;

    /* 利用select函数进行多路等待*/
    tm.tv_usec = 0;
    time(&prevTime);
    while (timeout > 0) {
        FD_ZERO(&fdset);
        FD_SET(s, &fdset);
        tm.tv_sec = timeout;
        if (select(s + 1, &fdset, (fd_set *) NULL, (fd_set *) NULL, &tm) < 0) {
            printf("Error on ARPING request: %s/n", strerror(errno));
            if (errno != EINTR) rv = 0;
        } else if (FD_ISSET(s, &fdset)) {
            if (recv(s, &arp, sizeof(arp), 0) < 0 ) 
                rv = 0;
            /*如果条件 htons(ARPOP_REPLY) bcmp(arp.tHaddr, mac, 6) == 0 *((u_int *) arp.sInaddr) == yiaddr 三者都为真,则ARP应答有效,说明这个地址是已近存在的*/
            if (arp.operation == htons(ARPOP_REPLY) &&
                bcmp(arp.tHaddr, mac, 6) == 0 &&
                *((u_int *) arp.sInaddr) == yiaddr) {
                printf("Valid arp reply receved for this address/n");
                rv = 0;
                break;
            }
        }
        timeout -= time(NULL) - prevTime;
        time(&prevTime);
    }
    close(s);
    return rv;
}


int check_ip(u_int32_t addr)
{
    struct in_addr temp;

    if (arpping(addr, server_config.server, server_config.arp, ETH_INTERFACE) == 0)
    {
        temp.s_addr = addr;
        printf("%s belongs to someone, reserving it for %ld seconds/n",
            inet_ntoa(temp), server_config.conflict_time);
        return 1;
    }
    else
        return 0;
}


int main(int argc, char *argv[])
{       
    if(argc < 2)
    {   
        printf("Usage: checkip ipaddr/n");
        exit(0);
    }
    
    /*读以太网接口函数,获取一些配置信息*/
    if (read_interface(ETH_INTERFACE, &server_config.ifindex,
               &server_config.server, server_config.arp) < 0)
    {
        exit(0);
    }
    
    /*IP检测函数*/
    if(check_ip(inet_addr(argv[1])) == 0)
    {
        printf("IP:%s can use/n", argv[1]); 
    }
    else
    {
        printf("IP:%s conflict/n", argv[1]);
    }
    
    return 0;
}

        再次, 真心赞一个原作者羡慕羡慕羡慕








1
0
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

IP冲突检测程序源码及分析 (arp实现IP冲突检测)

当主机启动的时候,将发送一个免费的arp请求,即请求自己的ip地址的mac地址。 此免费arp请求有两个作用: 1、通告整个lan说ip地址XXX是我的,对应的mac是XXX,他没有期望有人会应答...
  • lihangde1990
  • lihangde1990
  • 2013-12-15 11:47
  • 1227

Linux中如何检测IP地址冲突问题

在Windows系统中,如果本地网络IP地址出现冲突,会出现图标提示,问题比较容易解决。但在Linux系统中,并没有提供相关的功能,如果本地网络采用静态IP地址配置,出现比较奇怪的网络连接问题,如ss...
  • u010096900
  • u010096900
  • 2017-08-23 09:44
  • 556

linux下ip冲突检测

1. 检测网域内是否存在和本机ip相同的主机windows主机会提示IP地址冲突,而linux主机无任何提示那么如何知道自己的linux主机是否与网络中其它的windows主机IP地址冲突呢? 在...
  • lidonghat
  • lidonghat
  • 2016-09-15 21:54
  • 2388

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

免费ARP,在网络上有很多的介绍。在《tcp/ip协议卷》中的第四章也有介绍,下面再啰嗦一下介绍其作用和操作: 免费ARP,主要用于检测网络中IP地址是否冲突,它是一种功能而非协议。当设备重启或代理...
  • cfjtaishan
  • cfjtaishan
  • 2013-05-15 13:40
  • 5030

IP冲突检测程序源码及分析

本程序是网上很多被人采用的IP冲突检测程序,在这里感谢作者的分享。  首先是头文件,这一部分定义了两个结构,一个是ARP包,arpMsg,其中包含了ARP请求和应答的分组格式,实际就是一个固定的arp...
  • wanxiao009
  • wanxiao009
  • 2010-05-25 11:37
  • 5964

ARP的C代码实现

linux下C语言实现ARP数据包发送 #include #include #include #include #include #include #include #include ...
  • lee244868149
  • lee244868149
  • 2015-02-11 09:32
  • 2371

IP冲突检测程序源码及分析 (arp实现IP冲突检测)

当主机启动的时候,将发送一个免费的arp请求,即请求自己的ip地址的mac地址。 此免费arp请求有两个作用: 1、通告整个lan说ip地址XXX是我的,对应的mac是XXX,他没有期望有人会应答...
  • lihangde1990
  • lihangde1990
  • 2013-12-15 11:47
  • 1227

Linux检测IP地址冲突

测试环境中因为没有人统一管理IP分配,或是因为各种各样的问题,总是会出现IP地址冲突的问题。 windows方向不做介绍,本文主要讲解一下linux环境中的IP地址冲突。 给开发开了一台虚机,DH...
  • vast0906
  • vast0906
  • 2017-08-03 20:50
  • 351

Linux中如何检测IP地址冲突问题

在Windows系统中,如果本地网络IP地址出现冲突,会出现图标提示,问题比较容易解决。但在Linux系统中,并没有提供相关的功能,如果本地网络采用静态IP地址配置,出现比较奇怪的网络连接问题,如ss...
  • u010096900
  • u010096900
  • 2017-08-23 09:44
  • 556

DHCP的工作原理、怎么检测IP地址冲突

原帖地址:http://7658423.blog.51cto.com/7648423/1270601 理解DHCP的雏形BOOTP(Bootstrap Protocol) ...
  • a1232345
  • a1232345
  • 2015-04-07 14:47
  • 2807
    个人资料
    • 访问:5273084次
    • 积分:63735
    • 等级:
    • 排名:第42名
    • 原创:1976篇
    • 转载:198篇
    • 译文:0篇
    • 评论:2184条
    文章分类