1 /* convert a tcpdump capture file to a netmon .cap file.
3 Andrew Tridgell, October 1997
5 This only works for 32 bit boxes at the moment. Change the typedefs
6 to work on other sytems
16 /* change the following 3 lines to make things work on
17 systems with different word sizes */
19 typedef unsigned int uint32;
20 typedef unsigned short uint16;
25 #define TCPDUMP_MAGIC 0xa1b2c3d4
27 /* tcpdump file format */
28 struct tcpdump_file_header {
38 struct tcpdump_packet {
45 /* .cap file format */
58 uint32 cap_time; /* milliseconds */
70 static void swap_uint32(uint32 *x)
72 char c, *p = (char *)x;
73 c = p[0]; p[0] = p[3]; p[3] = c;
74 c = p[1]; p[1] = p[2]; p[2] = c;
77 static void swap_int32(int32 *x)
79 char c, *p = (char *)x;
80 c = p[0]; p[0] = p[3]; p[3] = c;
81 c = p[1]; p[1] = p[2]; p[2] = c;
84 static void swap_uint16(uint16 *x)
86 char c, *p = (char *)x;
87 c = p[0]; p[0] = p[1]; p[1] = c;
91 static void swap_netmon_header(struct cap_header *h)
93 swap_uint16(&h->captype);
94 swap_uint32(&h->frameoffset);
95 swap_uint32(&h->framelength);
98 static void swap_netmon_packet(struct cap_packet *p)
100 swap_uint32(&p->cap_time);
101 swap_uint16(&p->len);
102 swap_uint16(&p->caplen);
105 static void swap_tcpdump_header(struct tcpdump_file_header *h)
107 swap_uint32(&h->magic);
108 swap_uint16(&h->major);
109 swap_uint16(&h->minor);
110 swap_int32(&h->zone);
111 swap_uint32(&h->sigfigs);
112 swap_uint32(&h->snaplen);
113 swap_uint32(&h->linktype);
116 static void swap_tcpdump_packet(struct tcpdump_packet *p)
118 swap_uint32(&p->ts.tv_sec);
119 swap_uint32(&p->ts.tv_usec);
120 swap_uint32(&p->len);
121 swap_uint32(&p->caplen);
125 int convert_tcpdump_to_cap(char *infile, char *outfile)
127 uint32 *framestart = NULL;
128 int maxframes = 1000000;
132 struct tcpdump_file_header tcpdump_header;
133 struct tcpdump_packet tcpdump_pkt;
135 struct cap_header cap_header;
136 struct cap_packet cap_pkt;
137 struct timeval tval1;
139 int swap_tcpdump = 0;
142 fd1 = open(infile, O_RDONLY);
148 fd2 = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, 0644);
154 fd3 = open("cap.dat", O_WRONLY | O_CREAT | O_TRUNC, 0644);
160 if (read(fd1, &tcpdump_header, sizeof(tcpdump_header)) !=
161 sizeof(tcpdump_header)) {
162 printf("can't read tcpdump header\n");
166 write(fd3, &tcpdump_header, sizeof(tcpdump_header));
168 /* tcpdump files can be in either byte order. */
169 if (tcpdump_header.magic != TCPDUMP_MAGIC) {
171 swap_tcpdump_header(&tcpdump_header);
174 if (tcpdump_header.magic != TCPDUMP_MAGIC) {
175 printf("bad magic number %x\n", tcpdump_header.magic);
179 /* check if we are little endian. If not, we need to
180 convert the network monitor output */
182 if (((char *)&i)[0] != 1) swap_netmon = 1;
184 /* setup the basic netmon header */
185 memset(&cap_header, 0, sizeof(cap_header));
186 strcpy(cap_header.rtss, "RTSS");
187 cap_header.minor = 1;
188 cap_header.major = 1;
189 cap_header.captype = tcpdump_header.linktype;
191 /* write it out. we will have to write it again once
192 we've worked out the rest of the parameters */
193 write(fd2, &cap_header, sizeof(cap_header));
195 snaplen = tcpdump_header.snaplen;
197 printf("tcpdump-%d.%d snaplen=%d linktype=%d\n",
198 tcpdump_header.major, tcpdump_header.minor,
199 snaplen, tcpdump_header.linktype);
201 data = (char *)malloc(snaplen);
203 framestart = (uint32 *)malloc(maxframes * sizeof(framestart[0]));
210 memset(pad, 0, sizeof(pad));
213 if (i == maxframes-1) {
214 framestart = (uint32 *)realloc(framestart,
216 sizeof(framestart[0]));
224 if (read(fd1, &tcpdump_pkt, sizeof(tcpdump_pkt)) !=
228 write(fd3, &tcpdump_pkt, sizeof(tcpdump_pkt));
231 swap_tcpdump_packet(&tcpdump_pkt);
234 tval1 = tcpdump_pkt.ts;
237 printf("frame %d of length=%d:%d\n",
238 i+1, tcpdump_pkt.caplen, tcpdump_pkt.len);
241 lseek(fd1, 8, SEEK_CUR);
243 if (read(fd1, data, tcpdump_pkt.caplen) != tcpdump_pkt.caplen)
246 write(fd3, data, tcpdump_pkt.caplen);
248 if (tcpdump_pkt.caplen > tcpdump_pkt.len)
249 tcpdump_pkt.caplen = tcpdump_pkt.len;
251 framestart[i] = lseek(fd2, 0, SEEK_CUR);
253 cap_pkt.cap_time = (tcpdump_pkt.ts.tv_sec - tval1.tv_sec)*1000 +
254 (tcpdump_pkt.ts.tv_usec - tval1.tv_usec)/1000;
255 cap_pkt.caplen = tcpdump_pkt.caplen;
256 cap_pkt.len = tcpdump_pkt.len;
259 swap_netmon_packet(&cap_pkt);
261 write(fd2, &cap_pkt, sizeof(cap_pkt));
262 write(fd2, data, tcpdump_pkt.caplen);
264 if (tcpdump_pkt.caplen % 4 != 0) {
265 write(fd2, pad, 4 - (tcpdump_pkt.caplen % 4));
269 printf("frame %d of length=%d:%d\n",
270 i+1, tcpdump_pkt.caplen, tcpdump_pkt.len);
274 cap_header.frameoffset = lseek(fd2, 0, SEEK_CUR);
275 cap_header.framelength = i*4;
280 swap_uint32(&framestart[j]);
281 swap_netmon_header(&cap_header);
284 write(fd2, framestart, i*4);
286 lseek(fd2, 0, SEEK_SET);
288 write(fd2, &cap_header, sizeof(cap_header));
294 printf("converted %d frames\n", i);
299 int main(int argc, char *argv[])
302 printf("Convert a tcpdump capture file to a netmon .cap file\n");
303 printf("\tUsage: capconvert <infile> <outfile>\n");
307 convert_tcpdump_to_cap(argv[1], argv[2]);