1 /* Reorder the frames from an input dump file, and write to output dump file.
2 * Martin Mathieson and Jakub Jawadzki
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
40 #include "wsutil/wsgetopt.h"
43 /* Show command-line usage */
44 static void usage(void)
46 fprintf(stderr
, "Reordercap %s"
48 " (" SVNVERSION
" from " SVNPATH
")"
51 fprintf(stderr
, "Reorder timestamps of input file frames into output file.\n");
52 fprintf(stderr
, "See http://www.wireshark.org for more information.\n");
53 fprintf(stderr
, "\n");
54 fprintf(stderr
, "Usage: reordercap [options] <infile> <outfile>\n");
55 fprintf(stderr
, "\n");
56 fprintf(stderr
, "Options:\n");
57 fprintf(stderr
, " -n don't write to output file if the input file is ordered.\n");
60 /* Remember where this frame was in the file */
61 typedef struct FrameRecord_t
{
70 /**************************************************/
73 /* Enable this symbol to see debug output */
74 /* #define REORDER_DEBUG */
77 #define DEBUG_PRINT printf
79 #define DEBUG_PRINT(...)
81 /**************************************************/
85 frame_write(FrameRecord_t
*frame
, wtap
*wth
, wtap_dumper
*pdh
, Buffer
*buf
,
90 struct wtap_pkthdr phdr
;
92 DEBUG_PRINT("\nDumping frame (offset=%" G_GINT64_MODIFIER
"u, length=%u)\n",
93 frame
->offset
, frame
->length
);
96 /* Re-read the first frame from the stored location */
97 if (!wtap_seek_read(wth
, frame
->offset
, &phdr
, buf
, frame
->length
,
100 /* Print a message noting that the read failed somewhere along the line. */
102 "reordercap: An error occurred while re-reading \"%s\": %s.\n",
103 infile
, wtap_strerror(err
));
106 case WTAP_ERR_UNSUPPORTED
:
107 case WTAP_ERR_UNSUPPORTED_ENCAP
:
108 case WTAP_ERR_BAD_FILE
:
109 fprintf(stderr
, "(%s)\n", err_info
);
117 /* Copy, and set length and timestamp from item. */
118 /* TODO: remove when wtap_seek_read() will read phdr */
119 phdr
.ts
= frame
->time
;
121 /* Dump frame to outfile */
122 if (!wtap_dump(pdh
, &phdr
, buffer_start_ptr(buf
), &err
)) {
123 fprintf(stderr
, "reordercap: Error (%s) writing frame to outfile\n",
129 /* Comparing timestamps between 2 frames.
135 frames_compare(gconstpointer a
, gconstpointer b
)
137 const FrameRecord_t
*frame1
= *(const FrameRecord_t
**) a
;
138 const FrameRecord_t
*frame2
= *(const FrameRecord_t
**) b
;
140 const nstime_t
*time1
= &frame1
->time
;
141 const nstime_t
*time2
= &frame2
->time
;
143 if (time1
->secs
> time2
->secs
)
145 if (time1
->secs
< time2
->secs
)
148 /* time1->secs == time2->secs */
149 if (time1
->nsecs
> time2
->nsecs
)
151 if (time1
->nsecs
< time2
->nsecs
)
154 /* time1->nsecs == time2->nsecs */
156 if (frame1
->num
> frame2
->num
)
158 if (frame1
->num
< frame2
->num
)
164 /********************************************************************/
166 /********************************************************************/
167 int main(int argc
, char *argv
[])
170 wtap_dumper
*pdh
= NULL
;
175 const struct wtap_pkthdr
*phdr
;
176 guint wrong_order_count
= 0;
177 gboolean write_output_regardless
= TRUE
;
179 wtapng_section_t
*shb_hdr
;
180 wtapng_iface_descriptions_t
*idb_inf
;
183 FrameRecord_t
*prevFrame
= NULL
;
190 /* Process the options first */
191 while ((opt
= getopt(argc
, argv
, "n")) != -1) {
194 write_output_regardless
= FALSE
;
202 /* Remaining args are file names */
203 file_count
= argc
- optind
;
204 if (file_count
== 2) {
205 infile
= argv
[optind
];
206 outfile
= argv
[optind
+1];
214 wth
= wtap_open_offline(infile
, &err
, &err_info
, TRUE
);
216 fprintf(stderr
, "reordercap: Can't open %s: %s\n", infile
,
220 case WTAP_ERR_UNSUPPORTED
:
221 case WTAP_ERR_UNSUPPORTED_ENCAP
:
222 case WTAP_ERR_BAD_FILE
:
223 fprintf(stderr
, "(%s)\n", err_info
);
229 DEBUG_PRINT("file_type_subtype is %u\n", wtap_file_type_subtype(wth
));
231 shb_hdr
= wtap_file_get_shb_info(wth
);
232 idb_inf
= wtap_file_get_idb_info(wth
);
234 /* Open outfile (same filetype/encap as input file) */
235 pdh
= wtap_dump_open_ng(outfile
, wtap_file_type_subtype(wth
), wtap_file_encap(wth
),
236 65535, FALSE
, shb_hdr
, idb_inf
, &err
);
239 fprintf(stderr
, "reordercap: Failed to open output file: (%s) - error %s\n",
240 outfile
, wtap_strerror(err
));
245 /* Allocate the array of frame pointers. */
246 frames
= g_ptr_array_new();
248 /* Read each frame from infile */
249 while (wtap_read(wth
, &err
, &err_info
, &data_offset
)) {
250 FrameRecord_t
*newFrameRecord
;
252 phdr
= wtap_phdr(wth
);
254 newFrameRecord
= g_slice_new(FrameRecord_t
);
255 newFrameRecord
->num
= frames
->len
+ 1;
256 newFrameRecord
->offset
= data_offset
;
257 newFrameRecord
->length
= phdr
->len
;
258 newFrameRecord
->time
= phdr
->ts
;
260 if (prevFrame
&& frames_compare(&newFrameRecord
, &prevFrame
) < 0) {
264 g_ptr_array_add(frames
, newFrameRecord
);
265 prevFrame
= newFrameRecord
;
268 /* Print a message noting that the read failed somewhere along the line. */
270 "reordercap: An error occurred while reading \"%s\": %s.\n",
271 infile
, wtap_strerror(err
));
274 case WTAP_ERR_UNSUPPORTED
:
275 case WTAP_ERR_UNSUPPORTED_ENCAP
:
276 case WTAP_ERR_BAD_FILE
:
277 fprintf(stderr
, "(%s)\n", err_info
);
283 printf("%u frames, %u out of order\n", frames
->len
, wrong_order_count
);
285 /* Sort the frames */
286 if (wrong_order_count
> 0) {
287 g_ptr_array_sort(frames
, frames_compare
);
290 /* Write out each sorted frame in turn */
291 buffer_init(&buf
, 1500);
292 for (i
= 0; i
< frames
->len
; i
++) {
293 FrameRecord_t
*frame
= (FrameRecord_t
*)frames
->pdata
[i
];
295 /* Avoid writing if already sorted and configured to */
296 if (write_output_regardless
|| (wrong_order_count
> 0)) {
297 frame_write(frame
, wth
, pdh
, &buf
, infile
);
299 g_slice_free(FrameRecord_t
, frame
);
303 if (!write_output_regardless
&& (wrong_order_count
== 0)) {
304 printf("Not writing output file because input file is already in order!\n");
307 /* Free the whole array */
308 g_ptr_array_free(frames
, TRUE
);
311 if (!wtap_dump_close(pdh
, &err
)) {
312 fprintf(stderr
, "reordercap: Error closing %s: %s\n", outfile
,
319 /* Finally, close infile */