精华内容
下载资源
问答
  • 当主机启动的时候,将发送一个...2、另外一个目的就是检测ip地址冲突,如果有主机的ip和我的相同,他将回一个arp响应,当我接受到这个响应的时候,我知道lan内有一个主机的ip与我相同,于是我报一个ip地址冲突的错误

    当主机启动的时候,将发送一个免费的arp请求,即请求自己的ip地址的mac地址。
    此免费arp请求有两个作用:
    1、通告整个lan说ip地址XXX是我的,对应的mac是XXX,他没有期望有人会应答这个请求
    2、另外一个目的就是检测ip地址冲突,如果有主机的ip和我的相同,他将回一个arp响应,当我接受到这个响应的时候,我知道lan内有一个主机的ip与我相同,于是我报一个ip地址冲突的错误

    值 得注意的是:lan中的路由器始终不会发现ip地址冲突的问题,每次收到该ip的arp报文之后,只是简单的将arp表修改。因为目前的主机的实现都很文 明,即当检测到lan中有一个同ip的主机存在之后是先封闭自己而不是继续竞争,所以一开始连接成功的主机会一直成功。

    本程序是网上很多被人采用的IP冲突检测程序,在这里感谢作者的分享。

      首先是头文件,这一部分定义了两个结构,一个是ARP包,arpMsg,其中包含了ARP请求和应答的分组格式,实际就是一个固定的arp封装。另外一个是对所有本地信息的配置,这里作者也封装了一个包server_config_t。

     

    1. #ifndef __CHECKIP_H   
    2. #define __CHECKIP_H   
    3.   
    4. struct arpMsg {  
    5.     struct ethhdr ethhdr;       /* Ethernet header */  
    6.     u_short htype;              /* hardware type (must be ARPHRD_ETHER) */  
    7.     u_short ptype;              /* protocol type (must be ETH_P_IP) */  
    8.     u_char  hlen;               /* hardware address length (must be 6) */  
    9.     u_char  plen;               /* protocol address length (must be 4) */  
    10.     u_short operation;          /* ARP opcode */  
    11.     u_char  sHaddr[6];          /* sender's hardware address */  
    12.     u_char  sInaddr[4];         /* sender's IP address */  
    13.     u_char  tHaddr[6];          /* target's hardware address */  
    14.     u_char  tInaddr[4];         /* target's IP address */  
    15.     u_char  pad[18];            /* pad for min. Ethernet payload (60 bytes) */  
    16. };  
    17.   
    18. struct server_config_t {  
    19.     u_int32_t server;       /* Our IP, in network order */  
    20.     u_int32_t start;        /* Start address of leases, network order */  
    21.     u_int32_t end;          /* End of leases, network order */  
    22.     struct option_set *options; /* List of DHCP options loaded from the config file */  
    23.     char *interface;        /* The name of the interface to use */  
    24.     int ifindex;            /* Index number of the interface to use */  
    25.     unsigned char arp[6];       /* Our arp address */  
    26.     unsigned long lease;        /* lease time in seconds (host order) */  
    27.     unsigned long max_leases;   /* maximum number of leases (including reserved address) */  
    28.     char remaining;         /* should the lease file be interpreted as lease time remaining, or 
    29.                      * as the time the lease expires */  
    30.     unsigned long auto_time;    /* how long should udhcpd wait before writing a config file. 
    31.                      * if this is zero, it will only write one on SIGUSR1 */  
    32.     unsigned long decline_time;     /* how long an address is reserved if a client returns a 
    33.                          * decline message */  
    34.     unsigned long conflict_time;    /* how long an arp conflict offender is leased for */  
    35.     unsigned long offer_time;   /* how long an offered address is reserved */  
    36.     unsigned long min_lease;    /* minimum lease a client can request*/  
    37.     char *lease_file;  
    38.     char *pidfile;  
    39.     char *notify_file;      /* What to run whenever leases are written */  
    40.     u_int32_t siaddr;       /* next server bootp option */  
    41.     char *sname;            /* bootp server name */  
    42.     char *boot_file;        /* bootp boot file option */  
    43. };    
    44.   
    45. #endif /* __CHECKIP_H */  

     

     

     

    之后是C文件checkip.c,首先是主函数main()

    1. #include <stdio.h>  
    2. #include <stdlib.h>  
    3. #include <unistd.h>   
    4. #include <string.h>  
    5. #include <errno.h>  
    6. #include <time.h>  
    7.  
    8. #include <sys/types.h>  
    9. #include <sys/socket.h>  
    10. #include <sys/ioctl.h>  
    11.                  
    12. #include <netinet/in.h>   
    13. #include <netinet/if_ether.h>  
    14. #include <net/if.h>  
    15. #include <net/if_arp.h>  
    16. #include <arpa/inet.h>    
    17.                  
    18. #include "checkip.h"  
    19.          
    20. #define MAC_BCAST_ADDR      (unsigned char *) "/xff/xff/xff/xff/xff/xff"  
    21. #define ETH_INTERFACE       "eth0"   
    22.               
    23. struct server_config_t server_config;  
    24.   
    25. int main(int argc, char *argv[])  
    26. {         
    27.     if(argc < 2)  
    28.     {     
    29.         printf("Usage: checkip ipaddr/n");  
    30.         exit(0);  
    31.     }  
    32.       
    33.     /*读以太网接口函数,获取一些配置信息*/  
    34.     if (read_interface(ETH_INTERFACE, &server_config.ifindex,  
    35.                &server_config.server, server_config.arp) < 0)  
    36.     {  
    37.         exit(0);  
    38.     }  
    39.       
    40.     /*IP检测函数*/  
    41.     if(check_ip(inet_addr(argv[1])) == 0)  
    42.     {  
    43.         printf("IP:%s can use/n", argv[1]);   
    44.     }  
    45.     else  
    46.     {  
    47.         printf("IP:%s conflict/n", argv[1]);  
    48.     }  
    49.       
    50.     return 0;  
    51. }  

     

    先分析read_interface函数

     

    1. /*参数分别表示 网卡设备类型 接口检索索引 主机IP地址 主机arp地址*/  
    2. int read_interface(char *interface, int *ifindex, u_int32_t *addr, unsigned char *arp)  
    3. {  
    4.     int fd;  
    5.     /*ifreq结构定义在/usr/include/net/if.h,用来配置ip地址,激活接口,配置MTU等接口信息的。 
    6.     其中包含了一个接口的名字和具体内容——(是个共用体,有可能是IP地址,广播地址,子网掩码,MAC号,MTU或其他内容)。 
    7.     ifreq包含在ifconf结构中。而ifconf结构通常是用来保存所有接口的信息的。 
    8.     */  
    9.     struct ifreq ifr;  
    10.     struct sockaddr_in *our_ip;  
    11.   
    12.     memset(&ifr, 0, sizeof(struct ifreq));  
    13.     /*建立一个socket函数,SOCK_RAW是为了获取第三个参数的IP包数据, 
    14.      IPPROTO_RAW提供应用程序自行指定IP头部的功能。 
    15.     */  
    16.     if((fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) >= 0) {  
    17.         ifr.ifr_addr.sa_family = AF_INET;  
    18.         /*将网卡类型赋值给ifr_name*/  
    19.         strcpy(ifr.ifr_name, interface);  
    20.   
    21.         if (addr) {  
    22.             /*SIOCGIFADDR用于检索接口地址*/  
    23.             if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {  
    24.                 /*获取本机IP地址,addr是一个指向该地址的指针*/  
    25.                 our_ip = (struct sockaddr_in *) &ifr.ifr_addr;  
    26.                 *addr = our_ip->sin_addr.s_addr;  
    27.                 printf("%s (our ip) = %s/n", ifr.ifr_name, inet_ntoa(our_ip->sin_addr));  
    28.             } else {  
    29.                 printf("SIOCGIFADDR failed, is the interface up and configured?: %s/n",  
    30.                         strerror(errno));  
    31.                 return -1;  
    32.             }  
    33.         }  
    34.   
    35.         /*SIOCGIFINDEX用于检索接口索引*/  
    36.         if (ioctl(fd, SIOCGIFINDEX, &ifr) == 0) {  
    37.             printf("adapter index %d/n", ifr.ifr_ifindex);  
    38.             /*指针ifindex 获取索引*/  
    39.             *ifindex = ifr.ifr_ifindex;  
    40.         } else {  
    41.             printf("SIOCGIFINDEX failed!: %s/n", strerror(errno));  
    42.             return -1;  
    43.         }  
    44.         /*SIOCGIFHWADDR用于检索硬件地址*/  
    45.         if (ioctl(fd, SIOCGIFHWADDR, &ifr) == 0) {  
    46.             /*所获取的硬件地址复制到结构server_config的数组arp[6]参数中*/  
    47.             memcpy(arp, ifr.ifr_hwaddr.sa_data, 6);  
    48.             printf("adapter hardware address %02x:%02x:%02x:%02x:%02x:%02x/n",  
    49.                 arp[0], arp[1], arp[2], arp[3], arp[4], arp[5]);  
    50.         } else {  
    51.             printf("SIOCGIFHWADDR failed!: %s/n", strerror(errno));  
    52.             return -1;  
    53.         }  
    54.     }  
    55.     else {  
    56.         printf("socket failed!: %s/n", strerror(errno));  
    57.         return -1;  
    58.     }  
    59.     close(fd);  
    60.     return 0;  
    61. }  

     

    读取所有本地网络信息后,执行函数check_ip(),该函数主要执行了arrpping()函数,如果arpping函数的返回值为0,说明检测发出的到ip是冲突的

    1. int check_ip(u_int32_t addr)  
    2. {  
    3.     struct in_addr temp;  
    4.   
    5.     if (arpping(addr, server_config.server, server_config.arp, ETH_INTERFACE) == 0)  
    6.     {  
    7.         temp.s_addr = addr;  
    8.         printf("%s belongs to someone, reserving it for %ld seconds/n",  
    9.             inet_ntoa(temp), server_config.conflict_time);  
    10.         return 1;  
    11.     }  
    12.     else  
    13.         return 0;  
    14. }  

     

    1. /*参数说明 目标IP地址,本机IP地址,本机mac地址,网卡类型*/  
    2. int arpping(u_int32_t yiaddr, u_int32_t ip, unsigned char *mac, char *interface)  
    3. {  
    4.     int timeout = 2;  
    5.     int optval = 1;  
    6.     int s;                      /* socket */  
    7.     int rv = 1;                 /* return value */  
    8.     struct sockaddr addr;       /* for interface name */  
    9.     struct arpMsg arp;  
    10.     fd_set fdset;  
    11.     struct timeval tm;  
    12.     time_t prevTime;  
    13.   
    14.     /*socket发送一个arp包*/  
    15.     if ((s = socket (PF_PACKET, SOCK_PACKET, htons(ETH_P_ARP))) == -1) {  
    16.         printf("Could not open raw socket/n");  
    17.         return -1;  
    18.     }  
    19.       
    20.     /*设置套接口类型为广播,把这个arp包是广播到这个局域网*/  
    21.     if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval)) == -1) {  
    22.         printf("Could not setsocketopt on raw socket/n");  
    23.         close(s);  
    24.         return -1;  
    25.     }  
    26.   
    27.     /* 对arp设置,这里按照arp包的封装格式赋值即可,详见http://blog.csdn.net/wanxiao009/archive/2010/05/21/5613581.aspx */  
    28.     memset(&arp, 0, sizeof(arp));  
    29.     memcpy(arp.ethhdr.h_dest, MAC_BCAST_ADDR, 6);   /* MAC DA */  
    30.     memcpy(arp.ethhdr.h_source, mac, 6);        /* MAC SA */  
    31.     arp.ethhdr.h_proto = htons(ETH_P_ARP);      /* protocol type (Ethernet) */  
    32.     arp.htype = htons(ARPHRD_ETHER);        /* hardware type */  
    33.     arp.ptype = htons(ETH_P_IP);            /* protocol type (ARP message) */  
    34.     arp.hlen = 6;                   /* hardware address length */  
    35.     arp.plen = 4;                   /* protocol address length */  
    36.     arp.operation = htons(ARPOP_REQUEST);       /* ARP op code */  
    37.     *((u_int *) arp.sInaddr) = ip;          /* source IP address */  
    38.     memcpy(arp.sHaddr, mac, 6);         /* source hardware address */  
    39.     *((u_int *) arp.tInaddr) = yiaddr;      /* target IP address */  
    40.   
    41.     memset(&addr, 0, sizeof(addr));  
    42.     strcpy(addr.sa_data, interface);  
    43.     /*发送arp请求*/  
    44.     if (sendto(s, &arp, sizeof(arp), 0, &addr, sizeof(addr)) < 0)  
    45.         rv = 0;  
    46.   
    47.     /* 利用select函数进行多路等待*/  
    48.     tm.tv_usec = 0;  
    49.     time(&prevTime);  
    50.     while (timeout > 0) {  
    51.         FD_ZERO(&fdset);  
    52.         FD_SET(s, &fdset);  
    53.         tm.tv_sec = timeout;  
    54.         if (select(s + 1, &fdset, (fd_set *) NULL, (fd_set *) NULL, &tm) < 0) {  
    55.             printf("Error on ARPING request: %s/n", strerror(errno));  
    56.             if (errno != EINTR) rv = 0;  
    57.         } else if (FD_ISSET(s, &fdset)) {  
    58.             if (recv(s, &arp, sizeof(arp), 0) < 0 )   
    59.                 rv = 0;  
    60.             /*如果条件 htons(ARPOP_REPLY) bcmp(arp.tHaddr, mac, 6) == 0 *((u_int *) arp.sInaddr) == yiaddr 三者都为真,则ARP应答有效,说明这个地址是已近存在的*/  
    61.             if (arp.operation == htons(ARPOP_REPLY) &&  
    62.                 bcmp(arp.tHaddr, mac, 6) == 0 &&  
    63.                 *((u_int *) arp.sInaddr) == yiaddr) {  
    64.                 printf("Valid arp reply receved for this address/n");  
    65.                 rv = 0;  
    66.                 break;  
    67.             }  
    68.         }  
    69.         timeout -= time(NULL) - prevTime;  
    70.         time(&prevTime);  
    71.     }  
    72.     close(s);  
    73.     return rv;  
    74. }  

     

    综上所述,该程序是主要流程是封装好一个arp包,然后广播到局域网中,然后接收,通过接受的应答来解析发出的IP地址是不是一个可用IP。
    展开全文
  • 它是指主机发送ARP requset报文查询自己的IP地址,一般在ARP功能开启或者端口初始化配置完成时,主机向网络发送免费ARP来查询自己的IP地址确认地址唯一可用。 免费ARP作用: 确定网络中是否有其他的主机使用了该IP...

    标题
    如果没有看过第一篇文章可以点击链接 一、ARP基本功能流程

    免费ARP(gratuitous ARP)

    • 又能称无偿ARP无故ARP。它是指主机发送ARP requset报文查询自己的IP地址,一般在ARP功能开启或者端口初始化配置完成时,主机向网络发送免费ARP来查询自己的IP地址确认地址唯一可用。

    免费ARP作用:

    1. 确定网络中是否有其他的主机使用了该IP地址,如果有应答则产生错误消息。
    2. 免费ARP可以更新ARP表项用,网络中其他主机收到该广播则在缓存中更新条目,收到主机强制更新,如果存在旧条目会将MAC更新为广播包中MAC。

    数据包解析:

    采用实验解释,模拟器使用的是GNS3中VPC,抓包工具为:Wireshark

    实验拓扑:

    ARP拓扑

    在主机PC-1配置IP地址时:
    • 连续发送3个ARP请求报文,在确认本网段中没有其他的主机使用该地址
      1
      2

    目的mac地址全为F表示改以太网数据帧为广播帧

    3

    在主机PC-2配置相同的IP地址时:
    • 在PC-2配置同样的192.168.1.1地址时,PC2也发出了ARP广播来确认地址是否冲突
      45

    数据包发出时——检测到192.168.1.1(00:50:79:66:68:01)的重复IP地址 - 也在00:50:79:66:68:00(第3帧)中使用

    6

    随即PC1回复PC2 ARP reply 告诉PC2192.168.1.1自己已经使用了(这里由于PC2没有IP地址所以这里是纯2层数据帧通信)

    看完觉得有用可以点赞支持一下。

    展开全文
  • ARP 应用——检测IP地址冲突

    千次阅读 2017-08-10 19:44:29
    在给主机分配IP地址或更改了IP地址后,要检测新的IP地址是否与其他设备所冲突。利用ARP可以检测,避免冲突。  以自己的IP地址作为目的IP地址,进行ARP Request广播。如果该网段下有重复的IP地址,则会接收到ARP ...

        在给主机分配IP地址或更改了IP地址后,要检测新的IP地址是否与其他设备所冲突。利用ARP可以检测,避免冲突。

         以自己的IP地址作为目的IP地址,进行ARP Request广播。如果该网段下有重复的IP地址,则会接收到ARP reply报文,并且可以知道那个网卡与此IP重复了,从而可以避免IP的复用。

    展开全文
  • 原理其实很简单,那就是广播一个arp包,然后recv,如果没有数据(这里要设置延时),那么说明这个ip是可用的,否则就检测这个数据是否为回复我们发出的arp的应答包.如果是则证明ip已被使用,否则继续等待.  这里...

    原理其实很简单,那就是广播一个arp包,然后recv,如果没有数据(这里要设置延时),那么说明这个ip是可用的,否则就检测这个数据是否为回复我们发出的arp的应答包.如果是则证明ip已被使用,否则继续等待. 

    这里可以看下busybox的dhcp中的检测程序。 
    networking/udhcp/arpping.c 

    C代码 复制代码
    1. /* vi: set sw=4 ts=4: */  
    2. /*  
    3.  * arpping.c  
    4.  *  
    5.  * Mostly stolen from: dhcpcd - DHCP client daemon  
    6.  * by Yoichi Hariguchi <yoichi@fore.com>  
    7.  */  
    8.   
    9. #include <netinet/if_ether.h>   
    10. #include <net/if_arp.h>   
    11.   
    12. #include "common.h"   
    13. #include "dhcpd.h"   
    14.   
    15. //这里是arp包的格式,其中的数据格式都是宏了,比如uint_8_t为无符char.   
    16. struct arpMsg {   
    17.     /* Ethernet header */  
    18.     uint8_t  h_dest[6];     /* 00 destination ether addr */  
    19.     uint8_t  h_source[6];   /* 06 source ether addr */  
    20.     uint16_t h_proto;       /* 0c packet type ID field */  
    21.   
    22.     /* ARP packet */  
    23.     uint16_t htype;         /* 0e hardware type (must be ARPHRD_ETHER) */  
    24.     uint16_t ptype;         /* 10 protocol type (must be ETH_P_IP) */  
    25.     uint8_t  hlen;          /* 12 hardware address length (must be 6) */  
    26.     uint8_t  plen;          /* 13 protocol address length (must be 4) */  
    27.     uint16_t operation;     /* 14 ARP opcode */  
    28.     uint8_t  sHaddr[6];     /* 16 sender's hardware address */  
    29.     uint8_t  sInaddr[4];    /* 1c sender's IP address */  
    30.     uint8_t  tHaddr[6];     /* 20 target's hardware address */  
    31.     uint8_t  tInaddr[4];    /* 26 target's IP address */  
    32.     uint8_t  pad[18];       /* 2a pad for min. ethernet payload (60 bytes) */  
    33. } PACKED;   
    34.   
    35. enum {   
    36.     ARP_MSG_SIZE = 0x2a   
    37. };   
    38.   
    39.   
    40. /* Returns 1 if no reply received */  
    41.   
    42. //主程序,如果返回1说明此ip可用   
    43. int arpping(uint32_t test_ip, uint32_t from_ip, uint8_t *from_mac, const char *interface)   
    44. {   
    45.   
    46.     int timeout_ms;   
    47. //这里使用poll来检测句柄。   
    48.     struct pollfd pfd[1];   
    49. #define s (pfd[0].fd)           /* socket */   
    50.     int rv = 1;             /* "no reply received" yet */  
    51.     struct sockaddr addr;   /* for interface name */  
    52.     struct arpMsg arp;   
    53.   
    54. //建立scoket.由于我们是要直接访问访问链路层并自己组arp包.因此我们使用PF_PACKET协议簇.socket类型为SOCK_PACKET.   
    55.   
    56.     s = socket(PF_PACKET, SOCK_PACKET, htons(ETH_P_ARP));   
    57.     if (s == -1) {   
    58.         bb_perror_msg(bb_msg_can_not_create_raw_socket);   
    59.         return -1;   
    60.     }   
    61.   
    62.     if (setsockopt_broadcast(s) == -1) {   
    63.         bb_perror_msg("cannot enable bcast on raw socket");   
    64.         goto ret;   
    65.     }   
    66. //进行组包,由于是要广播,因此目的mac地址为全0.   
    67.     /* send arp request */  
    68.     memset(&arp, 0, sizeof(arp));   
    69.     memset(arp.h_dest, 0xff, 6);                    /* MAC DA */  
    70.     memcpy(arp.h_source, from_mac, 6);              /* MAC SA */  
    71.     arp.h_proto = htons(ETH_P_ARP);                 /* protocol type (Ethernet) */  
    72.     arp.htype = htons(ARPHRD_ETHER);                /* hardware type */  
    73.     arp.ptype = htons(ETH_P_IP);                    /* protocol type (ARP message) */  
    74.     arp.hlen = 6;                                   /* hardware address length */  
    75.     arp.plen = 4;                                   /* protocol address length */  
    76.     arp.operation = htons(ARPOP_REQUEST);           /* ARP op code */  
    77.     memcpy(arp.sHaddr, from_mac, 6);                /* source hardware address */  
    78.     memcpy(arp.sInaddr, &from_ip, sizeof(from_ip)); /* source IP address */  
    79.     /* tHaddr is zero-fiiled */                     /* target hardware address */  
    80.     memcpy(arp.tInaddr, &test_ip, sizeof(test_ip)); /* target IP address */  
    81.   
    82.     memset(&addr, 0, sizeof(addr));   
    83.     safe_strncpy(addr.sa_data, interface, sizeof(addr.sa_data));   
    84. //广播arp包.   
    85.     if (sendto(s, &arp, sizeof(arp), 0, &addr, sizeof(addr)) < 0) {   
    86.         // TODO: error message? caller didn't expect us to fail,   
    87.         // just returning 1 "no reply received" misleads it.   
    88.         goto ret;   
    89.     }   
    90.   
    91.     /* wait for arp reply, and check it */  
    92. //等待时间,超时则认为此ip地址可用   
    93.     timeout_ms = 2000;   
    94.     do {   
    95.         int r;   
    96.         unsigned prevTime = monotonic_us();   
    97.   
    98.         pfd[0].events = POLLIN;   
    99. //这边他是害怕poll被信号打断,因此加了层循环,其实这边我们还可以使用ppoll的,就可以了。   
    100.         r = safe_poll(pfd, 1, timeout_ms);   
    101.         if (r < 0)   
    102.             break;   
    103.         if (r) {   
    104. //读取返回数据.   
    105.             r = read(s, &arp, sizeof(arp));   
    106.             if (r < 0)   
    107.                 break;   
    108. //检测是否为应打包,发送ip是否为我们所请求的ip,这里是为了防止其他的数据包干扰我们检测。   
    109.             if (r >= ARP_MSG_SIZE   
    110.              && arp.operation == htons(ARPOP_REPLY)   
    111.              /* don't check it: Linux doesn't return proper tHaddr (fixed in 2.6.24?) */  
    112.              /* && memcmp(arp.tHaddr, from_mac, 6) == 0 */  
    113.              && *((uint32_t *) arp.sInaddr) == test_ip   
    114.             ) {   
    115. //说明ip地址已被使用   
    116.                 rv = 0;   
    117.                 break;   
    118.             }   
    119.         }   
    120.         timeout_ms -= ((unsigned)monotonic_us() - prevTime) / 1000;   
    121.     } while (timeout_ms > 0);   
    122.   
    123.  ret:   
    124.     close(s);   
    125.     DEBUG("%srp reply received for this address", rv ? "No a" : "A");   
    126.     return rv;   

     

    Ref: http://simohayha.javaeye.com/blog/267955



    project:

    bool CNetInterface::IPIsCollision(unsigned long ip, const char* name/* = "eth0"*/, unsigned short len/* = 4*/)

    {
    u_long hostIp = ip; //记录本地IP
    u_char  hostMac[6] = {0}; //记录本地MAC


    int fd_arp = socket(AF_INET, SOCK_PACKET, htons(0x0806));
    if( fd_arp < 0 )
    {
    printf("(%s %d) Failed: open socket failed\n",__FILE__,__LINE__);
    return false;  
    }


    struct  ifreq   ifr;  
    strcpy(ifr.ifr_name,  name);
    ifr.ifr_addr.sa_family = AF_INET;


    //获取本机IP地址
    if(ioctl(fd_arp, SIOCGIFADDR,  &ifr)<0) 
    {
    printf("(%s %d) Attention: no ip binded to interface %s\n",__FILE__,__LINE__,name);

    else
    {
    struct  sockaddr_in    *sin_ptr=(struct  sockaddr_in*)&ifr.ifr_addr; 
    hostIp = sin_ptr->sin_addr.s_addr;
    }


    if (hostIp == ip)
    {
    hostIp = 0;
    }


    //获取本机MAC地址  
    if (ioctl(fd_arp, SIOCGIFHWADDR, &ifr)<0)  
    {  
    printf("(%s %d) Error: no mac binded to interface %s\n",__FILE__,__LINE__,name);
    close(fd_arp);
    return false;
    }
    else
    {
    u_char * ptr=(u_char *)&ifr.ifr_ifru.ifru_hwaddr.sa_data[0]; 
    memcpy(hostMac, ptr, 6);
    }



    //构造ARP请求报文
    ARP_PACKET arp_packets;
    memset(&arp_packets.target_Mac,0xff,6);
    memcpy(&arp_packets.send_Mac,hostMac,6);
    arp_packets.ethnet_type = htons(0x0806);
    arp_packets.had_Type = htons(0x0001);
    arp_packets.pro_Type = htons(0x0800);
    arp_packets.had_Size = 0x06;
    arp_packets.pro_Size = 0x04;
    arp_packets.operate =  htons(ARP_REQUEST);
    memcpy(&arp_packets.send_Mac1,hostMac,6);
    arp_packets.send_Ip  = hostIp;
    arp_packets.target_ip = ip;
    memset(&arp_packets.target_Mac1,0,6);


    struct sockaddr to;
    memset(&to,0,sizeof(to));
    strcpy(to.sa_data, name); 


    //设置超时时间
    timeval timeout;
    timeout.tv_sec = 1;
    timeout.tv_usec = 0;
    fd_set   rdfd;
    bool isCollision = false;


    for (int timer = 0; timer<5 ;timer++) 
    {
    int len = sendto(fd_arp,&arp_packets,sizeof(arp_packets),0,&to,sizeof(to) );
    if( len < 0 )
    {  
    //printf("(%s %d) Failed: sendto failed\n",__FILE__,__LINE__);
    continue;
    }   


    FD_ZERO(&rdfd);
    FD_SET(fd_arp, &rdfd);
    len = select(fd_arp+1, &rdfd, NULL, NULL, &timeout);
    if( len > 0 )
    {
    socklen_t fromlen = 0;
    ARP_PACKET arp_packet_rev;
    memset(&arp_packet_rev,0,sizeof(arp_packet_rev));
    len = recvfrom(fd_arp,&arp_packet_rev,sizeof(arp_packet_rev), 0,&to,&fromlen);
    if( ( ARP_REPLAY==ntohs(arp_packet_rev.operate) ) && (arp_packet_rev.send_Ip == ip ) )
    {
    long ipReply = arp_packet_rev.send_Ip;
    printf("(%s %d) Send    Arp request ip=%lu.%lu.%lu.%lu\n",__FILE__,__LINE__,(ip&0xff),((ip>>8)&0xff),((ip>>16)&0xff),((ip>>24)&0xff));
    printf("(%s %d) Receive Arp reply,  ip=%lu.%lu.%lu.%lu, ",__FILE__,__LINE__,(ipReply&0xff),((ipReply>>8)&0xff),((ipReply>>16)&0xff),((ipReply>>24)&0xff));
    printf(" mac=%02x.%02x.%02x.%02x.%02x.%02x\n",arp_packet_rev.send_Mac1[0],arp_packet_rev.send_Mac1[1],arp_packet_rev.send_Mac1[2],arp_packet_rev.send_Mac1[3],arp_packet_rev.send_Mac1[4],arp_packet_rev.send_Mac1[5]);
    printf("(%s %d) This ip has been used: %lu.%lu.%lu.%lu\n",__FILE__,__LINE__,(ip&0xff),((ip>>8)&0xff),((ip>>16)&0xff),((ip>>24)&0xff));
    isCollision  = true;
    break;
    }
    }
    else
    {
    //printf("(%s %d) Failed: select timeout\n",__FILE__,__LINE__);
    }
    }


    close(fd_arp);
    return isCollision;
    }

    展开全文
  • linux下写程序检测ip冲突(ARP)

    千次阅读 2013-10-10 09:49:42
    原理其实很简单,那就是广播一个arp包,然后recv,如果没有数据(这里要设置延时),那么说明这个ip是可用的,否则就检测这个数据是否为回复我们发出的arp的应答包.如果是则证明ip已被使用,否则继续等待. 这里...
  • linux下ip冲突检测 ARP协议具体解释之Gratuitous ARP(免费ARP
  • 检测ip冲突的方法

    千次阅读 2019-06-14 11:35:00
    1、 检测ip冲突的方法; 1) arping是系统自带的检测arp工具。 使用方法为arping -I device x.x.x.x(device为网卡名称,x.x.x.x为网卡上面的ip)下图中可以看到一个ip对应了两个mac地址: 2) arp-scan工具在...
  • CentOS中如何检测IP冲突 需要利用arp-scan这款工具,它可以检测局域网内所有机器的IP地址,MAC地址,主机品牌等信息,另外,还可以检测TP-LINK这种路由器信息。 默认是无法通过以下的命令来安装arp-scan的,因为...
  • 检测ip是否冲突

    2012-06-13 22:36:50
    检测IP是否冲突,发送arp
  • ARP请求过程(可用于ip冲突检测

    千次阅读 2015-07-02 10:31:06
     先来回忆一下IP包到MAC帧封装的过程,在ARP协议浅析(二)中,已经提出过结论,MAC帧封装是根据路由下一跳的IP地址,进行本地ARP查表,然后封装MAC帧的。如果ARP表项中没有对应的ARP表项,这时
  • linux下检测ip冲突

    千次阅读 2013-10-29 10:43:59
    原理其实很简单,那就是广播一个arp包,然后recv,如果没有数据(这里要设置延时),那么说明这个ip是可用的,否则就检测这个数据是否为回复我们发出的arp的应答包.如果是则证明ip已被使用,否则继续等待. 这里...
  • [摘]linux下检测ip冲突

    2019-10-09 00:21:33
    原理其实很简单,那就是广播一个arp包,然后recv,如果没有数据(这里要设置延时),那么说明这个ip是可用的,否则就检测这个数据是否为回复我们发出的arp的应答包.如果是则证明ip已被使用,否则继续等待.这里可以看下...
  • Ip冲突检测

    千次阅读 2016-04-22 16:44:30
    有一个IP地址冲突意味着有一个以上的网络设备或计算机的IP地址相同。在给服务器配置IP的时候,如果前期没有做好IP地址规划,IP地址使用明细登记,有可能就...如果一个IP地址对应多个MAC地址,就说明IP冲突了。 1. 安装
  • 在linux下检测arp冲突

    2015-06-26 14:25:43
    app 在linux下检测arp冲突/* 得到本机的mac地址和ip地址 */ int GetLocalMac ( const char *device,char *mac,char *ip ) { int sockfd; struct ifreq req; struct sockaddr_in * sin; if ( ( sockfd
  • 该程序运行在Linux环境下,可以检测ip冲突, 我试过, 挺靠谱的,现摘录如下:(该程序涉及免费arp, 关于免费arp的概念和原理, 请自己在网上学习) [cpp] view plain copy #include  ...
  • 在Linux系统中,并没有提供相关的功能,如果本地网络采用静态IP地址配置,出现比较奇怪的网络连接问题,如ssh连接复位,可以考虑检测一下是否是出现了IP地址冲突问题。 arping命令提供了检测地址冲突的功能。 ...
  • 如何发生ARP直接交付:直接交付发生在 一个IP数据报被发送到一个IP地址,而该地址与发送方具有相同IP前缀的情况下 ARP用于运行IPv4的多接人链路层网络,每个主机都有自已首选的硬件地址。点到点链路(例如PPP)不使用...
  • /*参数分别表示 网卡设备类型 接口检索索引 主机IP地址 主机arp地址*/   int  read_interface( char  *interface,  int  *ifindex, u_int32_t *addr, unsigned  char  *arp)  {    int  ...
  • IPwatchD是一个简单的守护程序,它分析所有传入的ARP数据包以检测Linux上的IP冲突。 可以将其配置为在主动或被动模式下侦听一个或多个网络接口。 在活动模式下,它通过回答从冲突系统收到的免费ARP请求,在IP接管...
  • arping 检测IP地址冲突

    千次阅读 2015-01-06 12:59:02
    通过命令 假如当前主机IP 192.168.10.147: arping192.168.10.147-f默认使用eth0,向局域网内所有的主机发送...Unicastreplyfrom192.168.10.147[74:27:ea:f9:de:a6]0.458ms说明此IP的,在其他主机也在使用,IP冲突!/...
  • 2取证DHCP中继代理的工作原理与IP地址冲突(因为不在一个子网,所以gratuitous ARP肯定不行老) 关于DHCP服务器的冲突检测  业内常有工程师提出这样一个问题:当在一个子网内为了提高DHCP的冗余,同时架设了两台...

空空如也

空空如也

1 2 3 4 5 ... 9
收藏数 162
精华内容 64
关键字:

arp检测ip冲突