国产精品免费嫩草研究院|无遮羞动漫在线观看AV|国产麻豆精品传媒AV国产在线|村在线观看|寂寞情人1正版|韩国床震韩国床震古|精品系列专区久久

自身 如何在linux下檢測IP沖突

【自身 如何在linux下檢測IP沖突】最近遇到一個需求 , 或者說是一個用戶現場問題 。
我們設備先安裝 , 設置dhcp模式獲取ip進行聯網 , 后來又安裝了其他設備 , 但該設備是手動設置的靜態ip地址 , 正好與我們設備沖突 , 造成網絡故障 。
那我們就需要有一個能夠檢測ip沖突的方法 , 這個可以使用ARP協議的ACD功能(Address Conflict Detection , 在RFC 5227中提出) 。
(ARP協議主要用于局域網IP地址與MAC地址轉換 , 因為我們網絡主機之間收發數據其實是使用的硬件地址而非IP地址;向外網發數據時其實就是發給網關 , 網關再發給網關以此類推)
ACD功能中使用ARP Request的不同兩種參數填充方式分別作為ARP Probe和ARP Announcement , 后者是告訴別人我要用某個IP地址了 , 前者是聞訊局域網內是否有人已經用了某個IP地址 。
因此我們可以使用ARP Probe來檢測IP沖突 。
當我們通過網卡向局域網廣播ARP Probe時 , 如果其他主機使用了我們聞訊的IP地址 , 則會響應 , 我們就知道IP沖突了 。
代碼如下
1 #include <stdio.h>2 #include <stdlib.h>3 #include <string.h>4 #include <errno.h>5 #include <sys/types.h>6 #include <sys/socket.h>7 #include <linux/if_packet.h>8 #include <netdb.h>9 #include <unistd.h> 10 #include <arpa/inet.h> 11 #include <sys/ioctl.h> 12 #include <net/ethernet.h> 13 #include <netinet/ether.h> 14 #include <net/if.h> 15 #include <netinet/ip.h> 16 #include <sys/ioctl.h> 17 #include <net/if.h> 18 #include <netinet/in.h> 19 #include <netdb.h> 20 #include <sys/time.h> 21 22 static int get_mac(const char *if_name, char *mac); 23 static int get_ifidx(const char *if_name, int *idx); 24 25 int main(int argc, char *argv[]) 26 { 27if (argc < 3) 28{ 29printf("Usage: %s if_name detect_ip\n\tLike: %s wlan0 192.168.0.211\n", argv[0], argv[0]); 30exit(EXIT_FAILURE); 31} 32 33const char *if_name = argv[1]; 34const char *dst_ip = argv[2]; 35 36unsigned int ip4bit = 0; 37{ 38struct in_addr addr = {0}; 39if (inet_aton(dst_ip, &addr) == 0) 40{ 41perror("inet_aton"); 42exit(EXIT_FAILURE); 43} 44ip4bit = addr.s_addr; 45} 46 47char mac[6] = {0}; 48if (get_mac(if_name, mac) != 0) 49{ 50perror("inet_aton"); 51exit(EXIT_FAILURE); 52} 53 54int sock_client = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); 55if (sock_client < 0) 56{ 57perror("socket"); 58exit(EXIT_FAILURE); 59} 60int sock_server; 61if ((sock_server = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP))) < 0) 62{ 63perror("cannot create socket"); 64exit(EXIT_FAILURE); 65} 66struct timeval tv_out; 67tv_out.tv_sec = 1; 68tv_out.tv_usec = 0; 69setsockopt(sock_server, SOL_SOCKET, SO_RCVTIMEO, &tv_out, sizeof(tv_out)); 70 71unsigned char arp_probe_msg[] = { 720xff, 0xff, 0xff, 0xff, 0xff, 0xff, /*目的mac地址*/ 730x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*源mac地址*/ 740x08, 0x06,/*幀類型*/ 75 76/*ARP報文頭部(28個字節)*/ 770x00, 0x01,/*硬件類型*/ 780x08, 0x00,/*協議類型*/ 796,/*硬件地址長度*/ 804,/*協議地址長度*/ 810x00, 0x01,/*ARP請求*/ 820x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*源mac地址*/ 830, 0, 0, 0,/*源IP*/ 840xff, 0xff, 0xff, 0xff, 0xff, 0xff, /*目的mac地址*/ 850, 0, 0, 0/*目的IP*/ 86}; 87 88memcpy(arp_probe_msg + 6, mac, 6); 89memcpy(arp_probe_msg + 22, mac, 6); 90memcpy(arp_probe_msg + 38, &ip4bit, 4); 91 92int if_idx; 93if (get_ifidx(if_name, &if_idx) != 0) 94exit(EXIT_FAILURE); 95 96// 發送5次 97for (int i = 0; i < 5; ++i) 98{ 99struct sockaddr_ll sll;100bzero(&sll, sizeof(sll));101sll.sll_ifindex = if_idx;102103if (sendto(sock_client, arp_probe_msg, sizeof arp_probe_msg, 0, (struct sockaddr *)&sll, sizeof(sll)) < sizeof arp_probe_msg)104{105perror("sendto");106exit(EXIT_FAILURE);107}108}109110char buffer[42] = {0};111int recv_count = 0;112// 接受最多100條或3秒超時113struct timeval recv_start_time;114gettimeofday(&recv_start_time, NULL);115while (recv_count++ < 100 && recv(sock_server, buffer, sizeof(buffer), 0))116{117if ((((buffer[12]) << 8) + buffer[13]) != ETH_P_ARP)118continue;119struct timeval now_time;120gettimeofday(&now_time, NULL);121if (now_time.tv_sec - recv_start_time.tv_sec > 2)122break;123char arp_rsp_mac[18] = {0};124char arp_rsp_ip[18] = {0};125sprintf(arp_rsp_mac, "%02x:%02x:%02x:%02x:%02x:%02x", buffer[22], buffer[23], buffer[24], buffer[25], buffer[26], buffer[27]);126sprintf(arp_rsp_ip, "%d.%d.%d.%d", buffer[28], buffer[29], buffer[30], buffer[31]);127// printf("%s %s\n", arp_rsp_mac, arp_rsp_ip);128if (strcmp(arp_rsp_ip, dst_ip) == 0)129{130printf("%s", arp_rsp_mac);131return 0;132}133}134135return 0;136 }137138 int get_mac(const char *if_name, char *mac)139 {140int fd, rtn;141struct ifreq ifr;142143if (!if_name || !mac)144{145return -1;146}147fd = socket(AF_INET, SOCK_DGRAM, 0);148if (fd < 0)149{150perror("socket");151return -1;152}153ifr.ifr_addr.sa_family = AF_INET;154strncpy(ifr.ifr_name, (const char *)if_name, IFNAMSIZ - 1);155156if ((rtn = ioctl(fd, SIOCGIFHWADDR, &ifr)) == 0)157memcpy(mac, (unsigned char *)ifr.ifr_hwaddr.sa_data, 6);158close(fd);159return rtn;160 }161162 int get_ifidx(const char *if_name, int *idx)163 {164int fd, rtn;165struct ifreq ifr;166167if (!if_name || !idx)168{169return -1;170}171fd = socket(AF_INET, SOCK_DGRAM, 0);172if (fd < 0)173{174perror("socket");175return -1;176}177ifr.ifr_addr.sa_family = AF_INET;178strncpy(ifr.ifr_name, (const char *)if_name, IFNAMSIZ - 1);179180if ((rtn = ioctl(fd, SIOCGIFINDEX, &ifr)) == 0)181*idx = ifr.ifr_ifindex;182close(fd);183return rtn;184 }

經驗總結擴展閱讀