/*拆解UDP数据报*/ #include #include #include #include #include #include #include int main(int argc, char const *argv[]) { // 创建原始套接字 int sock_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); if (sock_fd < 0) { perror("raw socket"); return -1; } printf("原始套接字创建成功\n"); // 多次接收数据 while (1) { // 接链路层的数据报文(MAC报文) unsigned char buf[1518] = ""; // 记得使用无符号类型 int len = recvfrom(sock_fd, buf, sizeof(buf), 0, NULL, NULL); if (len < 18) { perror("recvfrom"); continue; } // 拆解 MAC 数据报文 unsigned char dst_mac[18] = ""; // 目的MAC地址 unsigned char src_mac[18] = ""; // 源MAC地址 unsigned short mac_type = ntohs(*((unsigned short *)(buf + 12))); sprintf(dst_mac, "%02x:%02x:%02x:%02x:%02x:%02x", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); sprintf(src_mac, "%02x:%02x:%02x:%02x:%02x:%02x", buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]); if (strncmp(src_mac, "00:00:00", 8) != 0) printf("src_mac %s -> dst_mac %s type(%#x)\n", src_mac, dst_mac, mac_type); // sleep(1); // usleep(5); switch (mac_type) { case 0x0800: printf("-----ip 数据包-----\n"); // 拆解IP数据报 unsigned char *ip_buf = buf + 14; // 读取IP首部长度: 单位是 4 字节 unsigned char ip_head_len = (ip_buf[0] & 0x0f) * 4; printf("IP数据报的首部长度: %d\n", ip_head_len); unsigned char ip_type = ip_buf[9]; // 协议类型 // 读取源IP和目的IP unsigned char src_ip[INET_ADDRSTRLEN] = ""; // 源IP unsigned char dst_ip[INET_ADDRSTRLEN] = ""; // 目的IP inet_ntop(AF_INET, (unsigned int *)(ip_buf + 12), src_ip, INET_ADDRSTRLEN); inet_ntop(AF_INET, (unsigned int *)(ip_buf + 16), dst_ip, INET_ADDRSTRLEN); printf("src_ip: %s -> dst_ip: %s \n", src_ip, dst_ip); if (ip_type == 1) { printf("\t------ICMP 数据报-----\n"); } else if (ip_type == 2) { printf("\t------IGMP 数据报-----\n"); } else if (ip_type == 6) { printf("\t------TCP 数据报-----\n"); // 拆解TCP的数据报 unsigned char *tcp_buf = ip_buf + ip_head_len; // 取出TCP的报文 unsigned short src_port = ntohs(*((unsigned short *)(tcp_buf))); // 源端口 unsigned short dst_port = ntohs(*((unsigned short *)(tcp_buf + 2))); // 目的端口 printf("\tsrc_port: %d -> dst_port: %d\n", src_port, dst_port); // TCP 的数据报 } else if (ip_type == 17) { printf("\t------UDP 数据报-----\n"); // 拆解UDP的数据报 unsigned char *udp_buf = ip_buf + ip_head_len; // 取出UDP的报文 unsigned short src_port = ntohs(*((unsigned short *)udp_buf)); unsigned short dst_port = ntohs(*((unsigned short *)(udp_buf + 2))); printf("\tsrc_port: %d -> dst_port: %d\n", src_port, dst_port); // UDP 的数据报长度: 由首部+数据长度(偶数)组成 unsigned short udp_buf_len = ntohs(*((unsigned short *)(udp_buf + 4))); // ntohs 用于大端转小端 int udp_date_size = udp_buf_len - 8; char udp_date[128] = ""; // UDP 数据部分 strncpy(udp_date, udp_buf + 8, udp_buf_len - 8); printf("\t\t %d -> %d data: %s\n", src_port, dst_port, udp_date); } break; case 0x0806: printf("-----ARP 数据包-----\n"); break; case 0x8035: printf("-----RARP 数据包-----\n"); break; } } close(sock_fd); return 0; }