/* convert a tcpdump capture file to a netmon .cap file. Andrew Tridgell, October 1997 This only works for 32 bit boxes at the moment. Change the typedefs to work on other sytems */ #include #include #include #include #include #include /* change the following 3 lines to make things work on systems with different word sizes */ typedef int int32; typedef unsigned int uint32; typedef unsigned short uint16; #define DEBUG 0 #define TCPDUMP_MAGIC 0xa1b2c3d4 /* tcpdump file format */ struct tcpdump_file_header { uint32 magic; uint16 major; uint16 minor; int32 zone; uint32 sigfigs; uint32 snaplen; uint32 linktype; }; struct tcpdump_packet { struct timeval ts; uint32 caplen; uint32 len; }; /* .cap file format */ struct cap_header { char rtss[4]; char minor; char major; uint16 captype; char starttime[16]; uint32 frameoffset; uint32 framelength; uint32 unknown[24]; }; struct cap_packet { uint32 cap_time; /* milliseconds */ uint16 len; uint16 caplen; }; /* file format is: header frames frameoffsets */ static void swap_uint32(uint32 *x) { char c, *p = (char *)x; c = p[0]; p[0] = p[3]; p[3] = c; c = p[1]; p[1] = p[2]; p[2] = c; } static void swap_int32(int32 *x) { char c, *p = (char *)x; c = p[0]; p[0] = p[3]; p[3] = c; c = p[1]; p[1] = p[2]; p[2] = c; } static void swap_uint16(uint16 *x) { char c, *p = (char *)x; c = p[0]; p[0] = p[1]; p[1] = c; } static void swap_netmon_header(struct cap_header *h) { swap_uint16(&h->captype); swap_uint32(&h->frameoffset); swap_uint32(&h->framelength); } static void swap_netmon_packet(struct cap_packet *p) { swap_uint32(&p->cap_time); swap_uint16(&p->len); swap_uint16(&p->caplen); } static void swap_tcpdump_header(struct tcpdump_file_header *h) { swap_uint32(&h->magic); swap_uint16(&h->major); swap_uint16(&h->minor); swap_int32(&h->zone); swap_uint32(&h->sigfigs); swap_uint32(&h->snaplen); swap_uint32(&h->linktype); } static void swap_tcpdump_packet(struct tcpdump_packet *p) { swap_uint32(&p->ts.tv_sec); swap_uint32(&p->ts.tv_usec); swap_uint32(&p->len); swap_uint32(&p->caplen); } int convert_tcpdump_to_cap(char *infile, char *outfile) { uint32 *framestart = NULL; int maxframes = 1000; int i; int fd1, fd2; int snaplen; struct tcpdump_file_header tcpdump_header; struct tcpdump_packet tcpdump_pkt; char *data; struct cap_header cap_header; struct cap_packet cap_pkt; struct timeval tval1; char pad[4]; int swap_tcpdump = 0; int swap_netmon = 0; fd1 = open(infile, O_RDONLY); if (fd1 == -1) { perror(infile); exit(1); } fd2 = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, 0644); if (fd2 == -1) { perror(outfile); exit(1); } if (read(fd1, &tcpdump_header, sizeof(tcpdump_header)) != sizeof(tcpdump_header)) { printf("can't read tcpdump header\n"); return 0; } /* tcpdump files can be in either byte order. */ if (tcpdump_header.magic != TCPDUMP_MAGIC) { swap_tcpdump = 1; swap_tcpdump_header(&tcpdump_header); } if (tcpdump_header.magic != TCPDUMP_MAGIC) { printf("bad magic number %x\n", tcpdump_header.magic); return 0; } /* check if we are little endian. If not, we need to convert the network monitor output */ i=1; if (((char *)&i)[0] != 1) swap_netmon = 1; /* setup the basic netmon header */ memset(&cap_header, 0, sizeof(cap_header)); strcpy(cap_header.rtss, "RTSS"); cap_header.minor = 1; cap_header.major = 1; cap_header.captype = tcpdump_header.linktype; /* write it out. we will have to write it again once we've worked out the rest of the parameters */ write(fd2, &cap_header, sizeof(cap_header)); snaplen = tcpdump_header.snaplen; printf("tcpdump-%d.%d snaplen=%d linktype=%d\n", tcpdump_header.major, tcpdump_header.minor, snaplen, tcpdump_header.linktype); data = (char *)malloc(snaplen); framestart = (uint32 *)malloc(maxframes * sizeof(framestart[0])); if (!framestart) { perror("malloc"); exit(1); } memset(pad, 0, sizeof(pad)); for (i=0; 1 ; i++) { if (i == maxframes) { framestart = (uint32 *)realloc(framestart, maxframes*2* sizeof(framestart[0])); maxframes *= 2; if (!framestart) { perror("malloc"); exit(1); } } if (read(fd1, &tcpdump_pkt, sizeof(tcpdump_pkt)) != sizeof(tcpdump_pkt)) break; if (swap_tcpdump) swap_tcpdump_packet(&tcpdump_pkt); if (i == 0) tval1 = tcpdump_pkt.ts; if (read(fd1, data, tcpdump_pkt.caplen) != tcpdump_pkt.caplen) break; #if DEBUG printf("frame %d of length=%d:%d\n", i+1, tcpdump_pkt.caplen, tcpdump_pkt.len); #endif if (tcpdump_pkt.caplen > tcpdump_pkt.len) tcpdump_pkt.caplen = tcpdump_pkt.len; framestart[i] = lseek(fd2, 0, SEEK_CUR); cap_pkt.cap_time = (tcpdump_pkt.ts.tv_sec - tval1.tv_sec)*1000 + (tcpdump_pkt.ts.tv_usec - tval1.tv_usec)/1000; cap_pkt.caplen = tcpdump_pkt.caplen; cap_pkt.len = tcpdump_pkt.len; if (swap_netmon) swap_netmon_packet(&cap_pkt); write(fd2, &cap_pkt, sizeof(cap_pkt)); write(fd2, data, tcpdump_pkt.caplen); if (tcpdump_pkt.caplen % 4 != 0) { write(fd2, pad, 4 - (tcpdump_pkt.caplen % 4)); } #if DEBUG printf("frame %d of length=%d:%d\n", i+1, tcpdump_pkt.caplen, tcpdump_pkt.len); #endif } cap_header.frameoffset = lseek(fd2, 0, SEEK_CUR); cap_header.framelength = i*4; if (swap_netmon) { int j; for (j=0;j \n"); exit(1); } convert_tcpdump_to_cap(argv[1], argv[2]); return 0; }