added writesize
[tridge/junkcode.git] / capconvert.c
1 /* convert a tcpdump capture file to a netmon .cap file.
2
3    Andrew Tridgell, October 1997
4
5    This only works for 32 bit boxes at the moment. Change the typedefs
6    to work on other sytems
7 */
8
9 #include <stdlib.h>
10 #include <unistd.h>
11 #include <memory.h>
12 #include <sys/time.h>
13 #include <stdio.h>
14 #include <fcntl.h>
15
16 /* change the following 3 lines to make things work on
17    systems with different word sizes */
18 typedef int int32;
19 typedef unsigned int uint32;
20 typedef unsigned short uint16;
21
22
23 #define DEBUG 0
24
25 #define TCPDUMP_MAGIC 0xa1b2c3d4
26
27 /* tcpdump file format */
28 struct tcpdump_file_header {
29         uint32 magic;
30         uint16 major;
31         uint16 minor;
32         int32 zone;
33         uint32 sigfigs;
34         uint32 snaplen;
35         uint32 linktype;
36 };
37
38 struct tcpdump_packet {
39         struct timeval ts;
40         uint32 caplen;
41         uint32 len;
42 };
43
44
45 /* .cap file format */
46 struct cap_header {
47     char             rtss[4];
48     char             minor;
49     char             major;
50     uint16           captype; 
51     char             starttime[16];
52     uint32           frameoffset;
53     uint32           framelength;
54     uint32           unknown[24];
55 };
56
57 struct cap_packet {
58         uint32 cap_time; /* milliseconds */
59         uint16 len;
60         uint16 caplen;
61 };
62
63 /* file format is:
64    header
65    frames
66    frameoffsets
67    */
68
69
70 static void swap_uint32(uint32 *x)
71 {
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;
75 }
76
77 static void swap_int32(int32 *x)
78 {
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;
82 }
83
84 static void swap_uint16(uint16 *x)
85 {
86         char c, *p = (char *)x;
87         c = p[0]; p[0] = p[1]; p[1] = c;
88 }
89
90
91 static void swap_netmon_header(struct cap_header *h)
92 {
93         swap_uint16(&h->captype);
94         swap_uint32(&h->frameoffset);
95         swap_uint32(&h->framelength);
96 }
97
98 static void swap_netmon_packet(struct cap_packet *p)
99 {
100         swap_uint32(&p->cap_time);
101         swap_uint16(&p->len);
102         swap_uint16(&p->caplen);
103 }
104
105 static void swap_tcpdump_header(struct tcpdump_file_header *h)
106 {
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);
114 }
115
116 static void swap_tcpdump_packet(struct tcpdump_packet *p)
117 {
118         swap_uint32(&p->ts.tv_sec);
119         swap_uint32(&p->ts.tv_usec);
120         swap_uint32(&p->len);
121         swap_uint32(&p->caplen);
122 }
123
124
125 int convert_tcpdump_to_cap(char *infile, char *outfile)
126 {
127         uint32 *framestart = NULL;
128         int maxframes = 1000000;
129         int i;
130         int fd1, fd2, fd3;
131         int snaplen;
132         struct tcpdump_file_header tcpdump_header;
133         struct tcpdump_packet tcpdump_pkt;
134         char *data;
135         struct cap_header cap_header;
136         struct cap_packet cap_pkt;
137         struct timeval tval1;
138         char pad[4];
139         int swap_tcpdump = 0;
140         int swap_netmon = 0;
141
142         fd1 = open(infile, O_RDONLY);
143         if (fd1 == -1) {
144                 perror(infile);
145                 exit(1);
146         }
147
148         fd2 = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, 0644);
149         if (fd2 == -1) {
150                 perror(outfile);
151                 exit(1);
152         }
153
154         fd3 = open("cap.dat", O_WRONLY | O_CREAT | O_TRUNC, 0644);
155         if (fd3 == -1) {
156                 perror("cap.dat");
157                 exit(1);
158         }
159
160         if (read(fd1, &tcpdump_header, sizeof(tcpdump_header)) != 
161             sizeof(tcpdump_header)) {
162                 printf("can't read tcpdump header\n");
163                 return 0;
164         }
165
166         write(fd3, &tcpdump_header, sizeof(tcpdump_header));
167
168         /* tcpdump files can be in either byte order. */
169         if (tcpdump_header.magic != TCPDUMP_MAGIC) {
170                 swap_tcpdump = 1;
171                 swap_tcpdump_header(&tcpdump_header);
172         }
173
174         if (tcpdump_header.magic != TCPDUMP_MAGIC) {
175                 printf("bad magic number %x\n", tcpdump_header.magic);
176                 return 0;
177         }
178
179         /* check if we are little endian. If not, we need to
180            convert the network monitor output */
181         i=1;
182         if (((char *)&i)[0] != 1) swap_netmon = 1;
183
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;
190         
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));
194
195         snaplen = tcpdump_header.snaplen;
196
197         printf("tcpdump-%d.%d snaplen=%d linktype=%d\n", 
198                tcpdump_header.major, tcpdump_header.minor,
199                snaplen, tcpdump_header.linktype);
200
201         data = (char *)malloc(snaplen);
202
203         framestart = (uint32 *)malloc(maxframes * sizeof(framestart[0]));
204
205         if (!framestart) {
206                 perror("malloc");
207                 exit(1);
208         }
209
210         memset(pad, 0, sizeof(pad));
211         
212         for (i=0; 1 ; i++) {
213                 if (i == maxframes-1) {
214                         framestart = (uint32 *)realloc(framestart, 
215                                                        maxframes*2*
216                                                        sizeof(framestart[0]));
217                         maxframes *= 2;
218                         if (!framestart) {
219                                 perror("malloc");
220                                 exit(1);
221                         }
222                 }
223
224                 if (read(fd1, &tcpdump_pkt, sizeof(tcpdump_pkt)) != 
225                     sizeof(tcpdump_pkt))
226                         break;
227
228                 write(fd3, &tcpdump_pkt, sizeof(tcpdump_pkt));
229
230                 if (swap_tcpdump)
231                         swap_tcpdump_packet(&tcpdump_pkt);
232
233                 if (i == 0)
234                         tval1 = tcpdump_pkt.ts;
235
236 #if DEBUG
237                 printf("frame %d of length=%d:%d\n",
238                        i+1, tcpdump_pkt.caplen, tcpdump_pkt.len);
239 #endif
240
241                 lseek(fd1, 8, SEEK_CUR);
242
243                 if (read(fd1, data, tcpdump_pkt.caplen) != tcpdump_pkt.caplen)
244                         break;
245
246                 write(fd3, data, tcpdump_pkt.caplen);
247
248                 if (tcpdump_pkt.caplen > tcpdump_pkt.len)
249                         tcpdump_pkt.caplen = tcpdump_pkt.len;
250
251                 framestart[i] = lseek(fd2, 0, SEEK_CUR);
252
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;
257
258                 if (swap_netmon)
259                         swap_netmon_packet(&cap_pkt);
260
261                 write(fd2, &cap_pkt, sizeof(cap_pkt));
262                 write(fd2, data, tcpdump_pkt.caplen);
263
264                 if (tcpdump_pkt.caplen % 4 != 0) {
265                         write(fd2, pad, 4 - (tcpdump_pkt.caplen % 4));
266                 }
267
268 #if DEBUG
269                 printf("frame %d of length=%d:%d\n",
270                        i+1, tcpdump_pkt.caplen, tcpdump_pkt.len);
271 #endif
272         }
273
274         cap_header.frameoffset = lseek(fd2, 0, SEEK_CUR);
275         cap_header.framelength = i*4;
276
277         if (swap_netmon) {
278                 int j;
279                 for (j=0;j<i;j++)
280                         swap_uint32(&framestart[j]);
281                 swap_netmon_header(&cap_header);
282         }
283
284         write(fd2, framestart, i*4);
285
286         lseek(fd2, 0, SEEK_SET);
287
288         write(fd2, &cap_header, sizeof(cap_header));
289
290         close(fd1);
291         close(fd2);
292         close(fd3);
293
294         printf("converted %d frames\n", i);
295
296         return i;
297 }
298
299 int main(int argc, char *argv[])
300 {
301         if (argc < 3) {
302                 printf("Convert a tcpdump capture file to a netmon .cap file\n");
303                 printf("\tUsage: capconvert <infile> <outfile>\n");
304                 exit(1);
305         }
306
307         convert_tcpdump_to_cap(argv[1], argv[2]);
308
309         return 0;
310 }