/************************************************************ * IP实验 * * 2016年3月26日 * * 130342132 * ************************************************************/ #include "pcap.h" typedef unsigned char u8_t; // 无符号8bit长度类型 typedef unsigned short u16_t; // 无符号16 bit长度类型 typedef unsigned long u32_t; // 无符号32 bit长度类型 // 以太网头部 struct ether_header { u8_t ether_dhost[6]; // 目的以太网地址6B u8_t ether_shost[6]; // 源以太网地址6B u16_t ether_type; // 以太网类型字段2B }; // IP格式 struct ip_header { u8_t ver_HeadLen; // Version (4 bits) + Internet header length (4 bits) u8_t serType; // Type of service u16_t lenSum; // Total length u16_t identification; // Identification 标识 u16_t flags_Offset; // Flags (3 bits) + Fragment offset (13 bits) 标志+分片偏移 u8_t _TTL; // Time to live u8_t proto; // Protocol u16_t checksum; // Header checksum u8_t s_ipAddr[4]; // 源IP 4B u8_t d_ipAddr[4]; // 目的IP 4B }; struct ip_packet { struct ether_header eth; // Ethernet头部 struct ip_header ip; // ip报文首部 }; void packet_handler(u_char *user_data, const struct pcap_pkthdr *header, const u_char *pkt_content); int main() { pcap_if_t *alldevs; pcap_if_t *d; int inum; int i=0; pcap_t *adhandle; char errbuf[PCAP_ERRBUF_SIZE]; // u8_t *send_buff; // 待发送的数据帧 // int packet_len; // 创建以太网帧的首部结构 // struct ip_packet ip_pkt; // 包 // 获取本机设备列表 if (pcap_findalldevs(&alldevs, errbuf) == -1) { fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf); exit(1); } // 打印列表 for(d=alldevs; d; d=d->next) { printf("%d. %s", ++i, d->name); if (d->description) printf(" (%s)\n", d->description); else printf(" (No description available)\n"); } if(i==0) { printf("\nNo interfaces found! Make sure WinPcap is installed.\n"); return -1; } printf("Enter the interface number (1-%d):",i); scanf("%d", &inum); if(inum < 1 || inum > i) { printf("\nInterface number out of range.\n"); // 释放设备列表 pcap_freealldevs(alldevs); return -1; } // 跳转到选中的适配器 for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++); // 打开设备 if ( (adhandle= pcap_open_live(d->name, // 设备名 65536, // 65535保证能捕获到不同数据链路层上的每个数据包的全部内容 1, // 混杂模式 1000, // 读取超时时间 // NULL, // 远程机器验证 errbuf // 错误缓冲池 ) ) == NULL) { fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n", d->name); // 释放设备列表 pcap_freealldevs(alldevs); return -1; } // 释放设备列表 pcap_freealldevs(alldevs); pcap_loop(adhandle, 0, packet_handler, NULL); pcap_close(adhandle); return 0; } void packet_handler(u_char *user_data, const struct pcap_pkthdr *header, const u_char *pkt_content) { u_short ethernet_type; // 以太网类型 struct ip_packet *sip_pkt; // struct ether_header *ethernet_protocol; // 以太网首部协议 u_char *mac_addr; u8_t version; u8_t headLen; u16_t f_o; u8_t DF, MF; u16_t offset; u8_t proto; u_char *ip_addr; static int packet_number = 1; // 统计捕获报文个数 sip_pkt = (struct ip_packet*)pkt_content; // 获得帧首部信息 ethernet_type = ntohs(sip_pkt->eth.ether_type); // ethernet_protocol->ether_type); if (ethernet_type == 0x0800) { printf("*********************************************\n"); printf("第%d个数据包\n%s\n", packet_number, ctime((const time_t*)&header->ts.tv_sec)); // 捕获时间 // MAC首部 printf("\tMAC首部\n"); // printf("源MAC\t\t"); mac_addr = sip_pkt->eth.ether_shost; printf("源MAC\t\t%02x:%02x:%02x:%02x:%02x:%02x\n", *mac_addr, *(mac_addr + 1), *(mac_addr + 2), *(mac_addr + 3), *(mac_addr + 4), *(mac_addr + 5)); // printf("目的MAC\t"); mac_addr = sip_pkt->eth.ether_dhost; printf("目的MAC\t\t%02x:%02x:%02x:%02x:%02x:%02x\n", *mac_addr, *(mac_addr + 1), *(mac_addr + 2), *(mac_addr + 3), *(mac_addr + 4), *(mac_addr + 5)); printf("协议类型\tIP协议\n"); // IP首部 printf("\n\tIP首部\n"); version = sip_pkt->ip.ver_HeadLen >> 4; printf("版本\t\t%d\n", version); // 头部长度 headLen = (sip_pkt->ip.ver_HeadLen & 0x0f) *4; printf("头部长度\t%d\n", headLen); // 总长度 printf("总长度\t\t%d\n", ntohs(sip_pkt->ip.lenSum)); // 标识符 printf("标识\t\t%d\n", ntohs(sip_pkt->ip.identification)); f_o = ntohs(sip_pkt->ip.flags_Offset); // 标志位 DF = (f_o >> 14) & 0x03; MF = (f_o >> 13) & 0x01; printf("标志位\t\tDF = %d, MF = %d\n", DF, MF); // IP片偏移 offset = f_o & 0x1fff; printf("片偏移\t\t%d\n", offset); // TTL printf("TTL\t\t%d\n", sip_pkt->ip._TTL); // IP协议类型 proto = sip_pkt->ip.proto; printf("协议类型\t%d,", proto); switch (proto) { case 1: printf("ICMP\n"); break; case 2: printf("IGMP\n"); break; case 4: printf("IP\n"); break; case 6: printf("TCP\n"); break; case 8: printf("EGP\n"); break; case 9: printf("IGP\n"); break; case 17: printf("UDP\n"); break; case 41: printf("IPv6\n"); break; case 50: printf("ESP\n"); break; case 89: printf("OSPF\n"); break; default: printf("其他类型\n"); break; } // 首部校验和 printf("首部校验和\t0x%0x\n", ntohs(sip_pkt->ip.checksum)); // printf("源IP\t\t"); ip_addr = sip_pkt->ip.s_ipAddr; printf("源IP\t\t%i.%i.%i.%i\n", *ip_addr, *(ip_addr + 1), *(ip_addr + 2), *(ip_addr + 3)); // printf("目的IP\t\t"); ip_addr = sip_pkt->ip.d_ipAddr; printf("目的IP\t\t%i.%i.%i.%i\n", *ip_addr, *(ip_addr + 1), *(ip_addr + 2), *(ip_addr + 3)); packet_number++; system("pause"); } }
