/* * 写一个网络数据分析器 * 要求: * 1、对 arp/ip/tcp/udp 数据进行区分。 * 2、把数据包中的源信息,目的信息等重要的信息打印出来。 */ #include #include #include #include #include // memset #include // ether_header #include // ip #include // ether_arp #include // sleep int main(int argc, char const *argv[]) { char errbuf[PCAP_ERRBUF_SIZE]; // 用于存储错误信息的缓冲区 char *dev = pcap_lookupdev(errbuf); // 获取网络接口 if (dev == NULL) // 获取网络接口失败 { printf("pcap_lookupdev error: %s\n", errbuf); return -1; } printf("网络接口: %s\n", dev); // 获取网卡的网络号,掩码地址 bpf_u_int32 netip, netmask; if (pcap_lookupnet(dev, &netip, &netmask, NULL) == 0) { unsigned char ip[INET_ADDRSTRLEN] = ""; unsigned char mask[INET_ADDRSTRLEN] = ""; inet_ntop(AF_INET, &netip, ip, INET_ADDRSTRLEN); inet_ntop(AF_INET, &netmask, mask, INET_ADDRSTRLEN); printf("网络地址: %s 掩码地址: %s\n", ip, mask); } // 打开网络设备,开始捕获数据 pcap_t *pcap_handle = pcap_open_live(dev, BUFSIZ, 1, 0, errbuf); if (pcap_handle == NULL) { printf("pcap_open_live error: %s\n", errbuf); return -1; } while (1) { struct pcap_pkthdr pcap_hdr; // 数据包头 memset(&pcap_hdr, 0, sizeof(pcap_hdr)); // 清空结构体 const u_char *packet = pcap_next(pcap_handle, &pcap_hdr); // 获取数据包 if (packet == NULL) { printf("pcap_next error\n"); return -1; } // 分析 ethernet 报文类型 // 如果是 arp 报文,则打印 arp 报文信息 // 如果是 ip 报文,则打印 ip 报文信息 struct ether_header *eth_hdr = (struct ether_header *)packet; // 拆分源 mac 地址和目的 mac 地址 unsigned char src_mac_x[ETHER_ADDR_LEN] = ""; // 源 mac 地址 unsigned char dst_mac_x[ETHER_ADDR_LEN] = ""; // 目的 mac 地址 memcpy(src_mac_x, eth_hdr->ether_shost, ETHER_ADDR_LEN); // 拷贝源 mac 地址 memcpy(dst_mac_x, eth_hdr->ether_dhost, ETHER_ADDR_LEN); // 拷贝目的 mac 地址 char src_mac[18] = ""; // 存储 MAC 地址的字符串 char dst_mac[18] = ""; // 存储 MAC 地址的字符串 // 将 MAC 地址转换成字符串 sprintf(src_mac, "%02x:%02x:%02x:%02x:%02x:%02x", src_mac_x[0], src_mac_x[1], src_mac_x[2], src_mac_x[3], src_mac_x[4], src_mac_x[5]); sprintf(dst_mac, "%02x:%02x:%02x:%02x:%02x:%02x", dst_mac_x[0], dst_mac_x[1], dst_mac_x[2], dst_mac_x[3], dst_mac_x[4], dst_mac_x[5]); if (ntohs(eth_hdr->ether_type) == ETHERTYPE_ARP) { // 拆分源 ip 地址和目的 ip 地址 unsigned char src_ip[INET_ADDRSTRLEN] = ""; // 源 ip 地址 unsigned char dst_ip[INET_ADDRSTRLEN] = ""; // 目的 ip 地址 struct ether_arp *arp_hdr = (struct ether_arp *)(packet + sizeof(struct ether_header)); inet_ntop(AF_INET, arp_hdr->arp_spa, src_ip, INET_ADDRSTRLEN); // 拷贝源 ip 地址 inet_ntop(AF_INET, arp_hdr->arp_tpa, dst_ip, INET_ADDRSTRLEN); // 拷贝目的 ip 地址 printf("arp 报文\n"); printf("源地址: %s\t\t目的地址: %s\n源MAC: %s\t目的MAC: %s\n", src_ip, dst_ip, src_mac, dst_mac); // 打印 arp 报文信息 } else if (ntohs(eth_hdr->ether_type) == ETHERTYPE_IP) { // 拆分源 ip 地址和目的 ip 地址 unsigned char src_ip[INET_ADDRSTRLEN] = ""; // 源 ip 地址 unsigned char dst_ip[INET_ADDRSTRLEN] = ""; // 目的 ip 地址 struct ip *ip_hdr = (struct ip *)(packet + sizeof(struct ether_header)); inet_ntop(AF_INET, &ip_hdr->ip_src, src_ip, INET_ADDRSTRLEN); // 拷贝源 ip 地址 inet_ntop(AF_INET, &ip_hdr->ip_dst, dst_ip, INET_ADDRSTRLEN); // 拷贝目的 ip 地址 printf("ip 报文\n"); // 分析 ip 报文类型 // 如果是 tcp 报文,则打印 tcp 报文信息 // 如果是 udp 报文,则打印 udp 报文信息 if (ip_hdr->ip_p == IPPROTO_TCP) { printf("tcp 报文\n"); printf("源地址: %s\t\t目的地址: %s\n源MAC: %s\t目的MAC: %s\n", src_ip, dst_ip, src_mac, dst_mac); // 打印 ip 报文信息 } else if (ip_hdr->ip_p == IPPROTO_UDP) { printf("udp 报文\n"); printf("源地址: %s\t\t目的地址: %s\n源MAC: %s\t目的MAC: %s\n", src_ip, dst_ip, src_mac, dst_mac); // 打印 ip 报文信息 } else { printf("其他报文\n"); } } else { printf("其他报文\n"); } sleep(1); } // 关闭网络设备 pcap_close(pcap_handle); return 0; }