int main(int argc, char **argv) { int raw_mode = 0; struct GlobalHeader ghead; // parameter check if(argc == 1) { raw_mode = 0; } else if(argc == 2) { if(0 != strcmp(argv[1], "-r")) { usage(); return 0; } raw_mode = 1; } else { usage(); return 0; } // read global header if(!raw_mode) { // XXX Should check link type and record snapshot length. fread(&ghead, sizeof(unsigned char), sizeof(struct GlobalHeader), stdin); if(ghead.magic != MAGIC_NUMBER) { printf("invalid file format\n"); return 0; } printf("PCAP format v%d.%d, ", ghead.majorver, ghead.minorver); if(ghead.linklayertype != 1) { printf("unsupported link layer type\n"); return 0; } printf("link layer type: Ethernet.\n"); } // read each packet while (1) { int i; struct PacketHeader phead; struct EthernetHeader ehead; printf("\n"); // packet header if (!raw_mode) { // XXX Should use length information in decoding below. if(sizeof(struct PacketHeader) != fread(&phead, sizeof(unsigned char), sizeof(struct PacketHeader), stdin)) break; if(phead.packetsize > ghead.snapshotlength) { printf("wrong packet at 0x%08x\n", (int)ftell(stdin)); return 0; } printf("<<<PCAP packet\n"); printf(" packet size: %d\n", phead.packetsize); printf(" payload size: %d\n", phead.payloadsize); } // data captured from wire get_ether(&ehead); print_ether(&ehead); if (ehead.length_type <= 1500) { // old style packet printf("Old style packet, length = %d\n", ehead.length_type); printf("We don't support this packet now\n"); if (!raw_mode) { dump(phead.packetsize-sizeof(ehead), 1); } } else if (ehead.length_type == 0x0800) { // ASSIGNMENT: MODIFY THIS TO PRINT INFORMATION ABOUT ENCAPSULATED PAYLOAD. struct IPv4Header ipv4head; get_ipv4(&ipv4head); print_ipv4(&ipv4head); if(ipv4head.protocol == 4) { printf("IP packet\n"); printf("Wedon't support this packet now\n"); dump(ipv4head.datalen-sizeof(ipv4head), 1); } else if(ipv4head.protocol == 6) { struct TCPHeader tcphead; get_tcp(&tcphead); print_tcp(&tcphead); // get payload in TCP packet //dump(ipv4head.datalen-sizeof(ipv4head)-sizeof(tcphead), 2); if(phead.packetsize >= sizeof(ehead)+ipv4head.datalen) { dump(ipv4head.datalen-sizeof(ipv4head)-sizeof(tcphead), 0); } else { dump((ipv4head.datalen-sizeof(ipv4head)-sizeof(tcphead))-(sizeof(ehead)+ipv4head.datalen-phead.packetsize), 0); } } else if(ipv4head.protocol == 17) { struct UDPHeader udphead; get_udp(&udphead); assert(udphead.size == ipv4head.datalen-sizeof(ipv4head)); print_udp(&udphead); // get payload in UDP packet if(phead.packetsize >= sizeof(ehead)+ipv4head.datalen) { dump(udphead.size-sizeof(udphead), 0); } else { dump((udphead.size-sizeof(udphead))-(sizeof(ehead)+ipv4head.datalen-phead.packetsize), 0); } } else { printf("Unexpected IP packet\n"); dump(ipv4head.datalen-sizeof(ipv4head), 1); } if(!raw_mode) { if(phead.packetsize > sizeof(ehead)+ipv4head.datalen) { printf("pad:\n"); dump(phead.packetsize-sizeof(ehead)-ipv4head.datalen, 1); } } } else if(ehead.length_type == 0x0806) { printf("ARP packet\n"); printf("We don't support this packet now\n"); if (!raw_mode) { dump(phead.packetsize-sizeof(ehead), 1); } } else if(ehead.length_type == 0x86DD) { printf("IPv6 packet\n"); printf("We don't support this packet now\n"); if (!raw_mode) { dump(phead.packetsize-sizeof(ehead), 1); } } else { printf("Unexpected Ethernet packet\n"); if (!raw_mode) { dump(phead.packetsize-sizeof(ehead), 1); } } } return 0; }
/* for local debug */ void ofp_print_packet_buffer(const char *comment, uint8_t *p) { static int first = 1; FILE *f; struct ofp_ip *ip; uint16_t proto; char *g; /* * Filter "noise" */ #if 0 if (p[12] == 0x00 && p[13] == 0x27) return; if (p[12] == 0x01 && p[13] == 0x98) return; #endif if (first) { f = fopen(DEFAULT_DEBUG_TXT_FILE_NAME, "w"); fclose(f); first = 0; } f = fopen(DEFAULT_DEBUG_TXT_FILE_NAME, "a"); if (!f) return; static struct timeval tv0; struct timeval tv; gettimeofday(&tv, NULL); if (tv0.tv_sec == 0) tv0 = tv; int ms = (tv.tv_sec*1000+tv.tv_usec/1000) - (tv0.tv_sec*1000+tv0.tv_usec/1000); ofp_printf(f, "\n*************\n"); ofp_printf(f, "[%d] %s: %d.%03d\n", odp_cpu_id(), comment, ms/1000, ms%1000); ofp_printf(f, "%s ->%s\n ", ofp_print_mac(p+6), ofp_print_mac(p)); if (p[12] == 0x81 && p[13] == 0x00) { ofp_printf(f, "VLAN %d ", (p[14]<<8)|p[15]); p += 4; } if (p[12] == 0x88 && p[13] == 0x47) { uint8_t *label = p+14; int i; ofp_printf(f, "MPLS "); while (1) { ofp_printf(f, "[label=%d ttl=%d] ", label[0]*16*256 + label[1]*16 + label[2]/16, label[3]); if (label[2] & 1) break; label += 4; } if ((label[4] & 0xf0) == 0x40) { label[2] = 0x08; /* ipv4 */ label[3] = 0x00; } else { label[2] = 0x86; /* ipv6 */ label[3] = 0xdd; } label++; for (i = 0; i < 12; i++) *label-- = p[11 - i]; p = label+1; } if (p[12] == 0x08 && p[13] == 0x06) { print_arp(f, (char *)(p + L2_HEADER_NO_VLAN_SIZE)); } else if (p[12] == 0x86 && p[13] == 0xdd) { print_ipv6(f, (char *)(p + L2_HEADER_NO_VLAN_SIZE)); } else if (p[12] == 0x08 && p[13] == 0x00) { ip = (struct ofp_ip *)(p + L2_HEADER_NO_VLAN_SIZE); if (ip->ip_p == 47) { /* GRE */ g = ((char *)ip) + (ip->ip_hl << 2); g += print_gre(f, g, &proto); if (proto == 0x0800) print_ipv4(f, g); else if (proto == 0x86dd) print_ipv6(f, g); } else print_ipv4(f, (char *)(p + L2_HEADER_NO_VLAN_SIZE)); } else { ofp_printf(f, "UNKNOWN ETH PACKET TYPE 0x%02x%02x ", p[12], p[13]); } ofp_printf(f, "\n"); fclose(f); fflush(stdout); }