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

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

[cpp]  view plain  copy
  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. #define MAC_BCAST_ADDR      (unsigned char *) "/xff/xff/xff/xff/xff/xff"  
  19. #define ETH_INTERFACE       "eth0"  
  20.   
  21. struct arpMsg {  
  22.     struct ethhdr ethhdr;       /* Ethernet header */  
  23.     u_short htype;              /* hardware type (must be ARPHRD_ETHER) */  
  24.     u_short ptype;              /* protocol type (must be ETH_P_IP) */  
  25.     u_char  hlen;               /* hardware address length (must be 6) */  
  26.     u_char  plen;               /* protocol address length (must be 4) */  
  27.     u_short operation;          /* ARP opcode */  
  28.     u_char  sHaddr[6];          /* sender's hardware address */  
  29.     u_char  sInaddr[4];         /* sender's IP address */  
  30.     u_char  tHaddr[6];          /* target's hardware address */  
  31.     u_char  tInaddr[4];         /* target's IP address */  
  32.     u_char  pad[18];            /* pad for min. Ethernet payload (60 bytes) */  
  33. };  
  34.   
  35. struct server_config_t {  
  36.     u_int32_t server;       /* Our IP, in network order */  
  37.     u_int32_t start;        /* Start address of leases, network order */  
  38.     u_int32_t end;          /* End of leases, network order */  
  39.     struct option_set *options; /* List of DHCP options loaded from the config file */  
  40.     char *interface;        /* The name of the interface to use */  
  41.     int ifindex;            /* Index number of the interface to use */  
  42.     unsigned char arp[6];       /* Our arp address */  
  43.     unsigned long lease;        /* lease time in seconds (host order) */  
  44.     unsigned long max_leases;   /* maximum number of leases (including reserved address) */  
  45.     char remaining;         /* should the lease file be interpreted as lease time remaining, or 
  46.                      * as the time the lease expires */  
  47.     unsigned long auto_time;    /* how long should udhcpd wait before writing a config file. 
  48.                      * if this is zero, it will only write one on SIGUSR1 */  
  49.     unsigned long decline_time;     /* how long an address is reserved if a client returns a 
  50.                          * decline message */  
  51.     unsigned long conflict_time;    /* how long an arp conflict offender is leased for */  
  52.     unsigned long offer_time;   /* how long an offered address is reserved */  
  53.     unsigned long min_lease;    /* minimum lease a client can request*/  
  54.     char *lease_file;  
  55.     char *pidfile;  
  56.     char *notify_file;      /* What to run whenever leases are written */  
  57.     u_int32_t siaddr;       /* next server bootp option */  
  58.     char *sname;            /* bootp server name */  
  59.     char *boot_file;        /* bootp boot file option */  
  60. };    
  61.   
  62. struct server_config_t server_config;             
  63.   
  64.   
  65. /*参数分别表示 网卡设备类型 接口检索索引 主机IP地址 主机arp地址*/  
  66. int read_interface(char *interface, int *ifindex, u_int32_t *addr, unsigned char *arp)  
  67. {  
  68.     int fd;  
  69.     /*ifreq结构定义在/usr/include/net/if.h,用来配置ip地址,激活接口,配置MTU等接口信息的。 
  70.     其中包含了一个接口的名字和具体内容——(是个共用体,有可能是IP地址,广播地址,子网掩码,MAC号,MTU或其他内容)。 
  71.     ifreq包含在ifconf结构中。而ifconf结构通常是用来保存所有接口的信息的。 
  72.     */  
  73.     struct ifreq ifr;  
  74.     struct sockaddr_in *our_ip;  
  75.   
  76.     memset(&ifr, 0, sizeof(struct ifreq));  
  77.     /*建立一个socket函数,SOCK_RAW是为了获取第三个参数的IP包数据, 
  78.      IPPROTO_RAW提供应用程序自行指定IP头部的功能。 
  79.     */  
  80.     if((fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) >= 0) {  
  81.         ifr.ifr_addr.sa_family = AF_INET;  
  82.         /*将网卡类型赋值给ifr_name*/  
  83.         strcpy(ifr.ifr_name, interface);  
  84.   
  85.         if (addr) {  
  86.             /*SIOCGIFADDR用于检索接口地址*/  
  87.             if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {  
  88.                 /*获取本机IP地址,addr是一个指向该地址的指针*/  
  89.                 our_ip = (struct sockaddr_in *) &ifr.ifr_addr;  
  90.                 *addr = our_ip->sin_addr.s_addr;  
  91.                 printf("%s (our ip) = %s/n", ifr.ifr_name, inet_ntoa(our_ip->sin_addr));  
  92.             } else {  
  93.                 printf("SIOCGIFADDR failed, is the interface up and configured?: %s/n",  
  94.                         strerror(errno));  
  95.                 return -1;  
  96.             }  
  97.         }  
  98.   
  99.         /*SIOCGIFINDEX用于检索接口索引*/  
  100.         if (ioctl(fd, SIOCGIFINDEX, &ifr) == 0) {  
  101.             printf("adapter index %d/n", ifr.ifr_ifindex);  
  102.             /*指针ifindex 获取索引*/  
  103.             *ifindex = ifr.ifr_ifindex;  
  104.         } else {  
  105.             printf("SIOCGIFINDEX failed!: %s/n", strerror(errno));  
  106.             return -1;  
  107.         }  
  108.         /*SIOCGIFHWADDR用于检索硬件地址*/  
  109.         if (ioctl(fd, SIOCGIFHWADDR, &ifr) == 0) {  
  110.             /*所获取的硬件地址复制到结构server_config的数组arp[6]参数中*/  
  111.             memcpy(arp, ifr.ifr_hwaddr.sa_data, 6);  
  112.             printf("adapter hardware address %02x:%02x:%02x:%02x:%02x:%02x/n",  
  113.                 arp[0], arp[1], arp[2], arp[3], arp[4], arp[5]);  
  114.         } else {  
  115.             printf("SIOCGIFHWADDR failed!: %s/n", strerror(errno));  
  116.             return -1;  
  117.         }  
  118.     }  
  119.     else {  
  120.         printf("socket failed!: %s/n", strerror(errno));  
  121.         return -1;  
  122.     }  
  123.     close(fd);  
  124.     return 0;  
  125. }  
  126.   
  127.   
  128. /*参数说明 目标IP地址,本机IP地址,本机mac地址,网卡类型*/  
  129. int arpping(u_int32_t yiaddr, u_int32_t ip, unsigned char *mac, char *interface)  
  130. {  
  131.     int timeout = 2;  
  132.     int optval = 1;  
  133.     int s;                      /* socket */  
  134.     int rv = 1;                 /* return value */  
  135.     struct sockaddr addr;       /* for interface name */  
  136.     struct arpMsg arp;  
  137.     fd_set fdset;  
  138.     struct timeval tm;  
  139.     time_t prevTime;  
  140.   
  141.     /*socket发送一个arp包*/  
  142.     if ((s = socket (PF_PACKET, SOCK_PACKET, htons(ETH_P_ARP))) == -1) {  
  143.         printf("Could not open raw socket/n");  
  144.         return -1;  
  145.     }  
  146.       
  147.     /*设置套接口类型为广播,把这个arp包是广播到这个局域网*/  
  148.     if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval)) == -1) {  
  149.         printf("Could not setsocketopt on raw socket/n");  
  150.         close(s);  
  151.         return -1;  
  152.     }  
  153.   
  154.     /* 对arp设置,这里按照arp包的封装格式赋值即可,详见http://blog.csdn.net/wanxiao009/archive/2010/05/21/5613581.aspx */  
  155.     memset(&arp, 0, sizeof(arp));  
  156.     memcpy(arp.ethhdr.h_dest, MAC_BCAST_ADDR, 6);   /* MAC DA */  
  157.     memcpy(arp.ethhdr.h_source, mac, 6);        /* MAC SA */  
  158.     arp.ethhdr.h_proto = htons(ETH_P_ARP);      /* protocol type (Ethernet) */  
  159.     arp.htype = htons(ARPHRD_ETHER);        /* hardware type */  
  160.     arp.ptype = htons(ETH_P_IP);            /* protocol type (ARP message) */  
  161.     arp.hlen = 6;                   /* hardware address length */  
  162.     arp.plen = 4;                   /* protocol address length */  
  163.     arp.operation = htons(ARPOP_REQUEST);       /* ARP op code */  
  164.     *((u_int *) arp.sInaddr) = ip;          /* source IP address */  
  165.     memcpy(arp.sHaddr, mac, 6);         /* source hardware address */  
  166.     *((u_int *) arp.tInaddr) = yiaddr;      /* target IP address */  
  167.   
  168.     memset(&addr, 0, sizeof(addr));  
  169.     strcpy(addr.sa_data, interface);  
  170.     /*发送arp请求*/  
  171.     if (sendto(s, &arp, sizeof(arp), 0, &addr, sizeof(addr)) < 0)  
  172.         rv = 0;  
  173.   
  174.     /* 利用select函数进行多路等待*/  
  175.     tm.tv_usec = 0;  
  176.     time(&prevTime);  
  177.     while (timeout > 0) {  
  178.         FD_ZERO(&fdset);  
  179.         FD_SET(s, &fdset);  
  180.         tm.tv_sec = timeout;  
  181.         if (select(s + 1, &fdset, (fd_set *) NULL, (fd_set *) NULL, &tm) < 0) {  
  182.             printf("Error on ARPING request: %s/n", strerror(errno));  
  183.             if (errno != EINTR) rv = 0;  
  184.         } else if (FD_ISSET(s, &fdset)) {  
  185.             if (recv(s, &arp, sizeof(arp), 0) < 0 )   
  186.                 rv = 0;  
  187.             /*如果条件 htons(ARPOP_REPLY) bcmp(arp.tHaddr, mac, 6) == 0 *((u_int *) arp.sInaddr) == yiaddr 三者都为真,则ARP应答有效,说明这个地址是已近存在的*/  
  188.             if (arp.operation == htons(ARPOP_REPLY) &&  
  189.                 bcmp(arp.tHaddr, mac, 6) == 0 &&  
  190.                 *((u_int *) arp.sInaddr) == yiaddr) {  
  191.                 printf("Valid arp reply receved for this address/n");  
  192.                 rv = 0;  
  193.                 break;  
  194.             }  
  195.         }  
  196.         timeout -= time(NULL) - prevTime;  
  197.         time(&prevTime);  
  198.     }  
  199.     close(s);  
  200.     return rv;  
  201. }  
  202.   
  203.   
  204. int check_ip(u_int32_t addr)  
  205. {  
  206.     struct in_addr temp;  
  207.   
  208.     if (arpping(addr, server_config.server, server_config.arp, ETH_INTERFACE) == 0)  
  209.     {  
  210.         temp.s_addr = addr;  
  211.         printf("%s belongs to someone, reserving it for %ld seconds/n",  
  212.             inet_ntoa(temp), server_config.conflict_time);  
  213.         return 1;  
  214.     }  
  215.     else  
  216.         return 0;  
  217. }  
  218.   
  219.   
  220. int main(int argc, char *argv[])  
  221. {         
  222.     if(argc < 2)  
  223.     {     
  224.         printf("Usage: checkip ipaddr/n");  
  225.         exit(0);  
  226.     }  
  227.       
  228.     /*读以太网接口函数,获取一些配置信息*/  
  229.     if (read_interface(ETH_INTERFACE, &server_config.ifindex,  
  230.                &server_config.server, server_config.arp) < 0)  
  231.     {  
  232.         exit(0);  
  233.     }  
  234.       
  235.     /*IP检测函数*/  
  236.     if(check_ip(inet_addr(argv[1])) == 0)  
  237.     {  
  238.         printf("IP:%s can use/n", argv[1]);   
  239.     }  
  240.     else  
  241.     {  
  242.         printf("IP:%s conflict/n", argv[1]);  
  243.     }  
  244.       
  245.     return 0;  
  246. }  

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




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值