Revert "TODO: smb2: simplify preauth_hash calculation..."
[wireshark-sm.git] / reordercap.c
bloba8aba0043c73dfd21af009f1cc61fe9b01d9d9da
1 /* Reorder the frames from an input dump file, and write to output dump file.
2 * Martin Mathieson and Jakub Jawadzki
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
11 #include <config.h>
12 #define WS_LOG_DOMAIN LOG_DOMAIN_MAIN
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <glib.h>
19 #include <ws_exit_codes.h>
20 #include <wsutil/ws_getopt.h>
22 #include <wiretap/wtap.h>
24 #include <wsutil/cmdarg_err.h>
25 #include <wsutil/filesystem.h>
26 #include <wsutil/file_util.h>
27 #include <wsutil/privileges.h>
28 #include <cli_main.h>
29 #include <wsutil/version_info.h>
30 #include <wiretap/wtap_opttypes.h>
32 #ifdef HAVE_PLUGINS
33 #include <wsutil/plugins.h>
34 #endif
36 #include <wsutil/report_message.h>
37 #include <wsutil/wslog.h>
39 #include "ui/failure_message.h"
41 /* Additional exit codes */
42 #define OUTPUT_FILE_ERROR 1
44 /* Show command-line usage */
45 static void
46 print_usage(FILE *output)
48 fprintf(output, "\n");
49 fprintf(output, "Usage: reordercap [options] <infile> <outfile>\n");
50 fprintf(output, "\n");
51 fprintf(output, "Options:\n");
52 fprintf(output, " -n don't write to output file if the input file is ordered.\n");
53 fprintf(output, " -h, --help display this help and exit.\n");
54 fprintf(output, " -v, --version print version information and exit.\n");
57 /* Remember where this frame was in the file */
58 typedef struct FrameRecord_t {
59 gint64 offset;
60 guint num;
62 nstime_t frame_time;
63 } FrameRecord_t;
66 /**************************************************/
67 /* Debugging only */
69 /* Enable this symbol to see debug output */
70 /* #define REORDER_DEBUG */
72 #ifdef REORDER_DEBUG
73 #define DEBUG_PRINT printf
74 #else
75 #define DEBUG_PRINT(...)
76 #endif
77 /**************************************************/
80 static void
81 frame_write(FrameRecord_t *frame, wtap *wth, wtap_dumper *pdh,
82 wtap_rec *rec, Buffer *buf, const char *infile,
83 const char *outfile)
85 int err;
86 gchar *err_info;
88 DEBUG_PRINT("\nDumping frame (offset=%" PRIu64 ")\n",
89 frame->offset);
92 /* Re-read the frame from the stored location */
93 if (!wtap_seek_read(wth, frame->offset, rec, buf, &err, &err_info)) {
94 if (err != 0) {
95 /* Print a message noting that the read failed somewhere along the line. */
96 fprintf(stderr,
97 "reordercap: An error occurred while re-reading \"%s\".\n",
98 infile);
99 cfile_read_failure_message(infile, err, err_info);
100 exit(1);
104 /* Copy, and set length and timestamp from item. */
105 /* TODO: remove when wtap_seek_read() fills in rec,
106 including time stamps, for all file types */
107 rec->ts = frame->frame_time;
109 /* Dump frame to outfile */
110 if (!wtap_dump(pdh, rec, ws_buffer_start_ptr(buf), &err, &err_info)) {
111 cfile_write_failure_message(infile, outfile, err, err_info, frame->num,
112 wtap_file_type_subtype(wth));
113 exit(1);
115 wtap_rec_reset(rec);
118 /* Comparing timestamps between 2 frames.
119 negative if (t1 < t2)
120 zero if (t1 == t2)
121 positive if (t1 > t2)
123 static int
124 frames_compare(gconstpointer a, gconstpointer b)
126 const FrameRecord_t *frame1 = *(const FrameRecord_t *const *) a;
127 const FrameRecord_t *frame2 = *(const FrameRecord_t *const *) b;
129 const nstime_t *time1 = &frame1->frame_time;
130 const nstime_t *time2 = &frame2->frame_time;
132 return nstime_cmp(time1, time2);
136 * General errors and warnings are reported with an console message
137 * in reordercap.
139 static void
140 reordercap_cmdarg_err(const char *msg_format, va_list ap)
142 fprintf(stderr, "reordercap: ");
143 vfprintf(stderr, msg_format, ap);
144 fprintf(stderr, "\n");
148 * Report additional information for an error in command-line arguments.
150 static void
151 reordercap_cmdarg_err_cont(const char *msg_format, va_list ap)
153 vfprintf(stderr, msg_format, ap);
154 fprintf(stderr, "\n");
157 /********************************************************************/
158 /* Main function. */
159 /********************************************************************/
161 main(int argc, char *argv[])
163 char *configuration_init_error;
164 static const struct report_message_routines reordercap_message_routines = {
165 failure_message,
166 failure_message,
167 open_failure_message,
168 read_failure_message,
169 write_failure_message,
170 cfile_open_failure_message,
171 cfile_dump_open_failure_message,
172 cfile_read_failure_message,
173 cfile_write_failure_message,
174 cfile_close_failure_message
176 wtap *wth = NULL;
177 wtap_dumper *pdh = NULL;
178 wtap_rec rec;
179 Buffer buf;
180 int err;
181 gchar *err_info;
182 gint64 data_offset;
183 guint wrong_order_count = 0;
184 gboolean write_output_regardless = TRUE;
185 guint i;
186 wtap_dump_params params;
187 int ret = EXIT_SUCCESS;
189 GPtrArray *frames;
190 FrameRecord_t *prevFrame = NULL;
192 int opt;
193 static const struct ws_option long_options[] = {
194 {"help", ws_no_argument, NULL, 'h'},
195 {"version", ws_no_argument, NULL, 'v'},
196 {0, 0, 0, 0 }
198 int file_count;
199 char *infile;
200 const char *outfile;
202 cmdarg_err_init(reordercap_cmdarg_err, reordercap_cmdarg_err_cont);
204 /* Initialize log handler early so we can have proper logging during startup. */
205 ws_log_init("reordercap", vcmdarg_err);
207 /* Early logging command-line initialization. */
208 ws_log_parse_args(&argc, argv, vcmdarg_err, WS_EXIT_INVALID_OPTION);
210 ws_noisy("Finished log init and parsing command line log arguments");
212 /* Initialize the version information. */
213 ws_init_version_info("Reordercap", NULL, NULL);
216 * Get credential information for later use.
218 init_process_policies();
221 * Attempt to get the pathname of the directory containing the
222 * executable file.
224 configuration_init_error = configuration_init(argv[0], NULL);
225 if (configuration_init_error != NULL) {
226 fprintf(stderr,
227 "reordercap: Can't get pathname of directory containing the reordercap program: %s.\n",
228 configuration_init_error);
229 g_free(configuration_init_error);
232 init_report_message("reordercap", &reordercap_message_routines);
234 wtap_init(TRUE);
236 /* Process the options first */
237 while ((opt = ws_getopt_long(argc, argv, "hnv", long_options, NULL)) != -1) {
238 switch (opt) {
239 case 'n':
240 write_output_regardless = FALSE;
241 break;
242 case 'h':
243 show_help_header("Reorder timestamps of input file frames into output file.");
244 print_usage(stdout);
245 goto clean_exit;
246 case 'v':
247 show_version();
248 goto clean_exit;
249 case '?':
250 print_usage(stderr);
251 ret = WS_EXIT_INVALID_OPTION;
252 goto clean_exit;
256 /* Remaining args are file names */
257 file_count = argc - ws_optind;
258 if (file_count == 2) {
259 infile = argv[ws_optind];
260 outfile = argv[ws_optind+1];
262 else {
263 print_usage(stderr);
264 ret = WS_EXIT_INVALID_OPTION;
265 goto clean_exit;
268 /* Open infile */
269 /* TODO: if reordercap is ever changed to give the user a choice of which
270 open_routine reader to use, then the following needs to change. */
271 wth = wtap_open_offline(infile, WTAP_TYPE_AUTO, &err, &err_info, TRUE);
272 if (wth == NULL) {
273 cfile_open_failure_message(infile, err, err_info);
274 ret = WS_EXIT_OPEN_ERROR;
275 goto clean_exit;
277 DEBUG_PRINT("file_type_subtype is %d\n", wtap_file_type_subtype(wth));
279 /* Allocate the array of frame pointers. */
280 frames = g_ptr_array_new();
282 /* Read each frame from infile */
283 wtap_rec_init(&rec);
284 ws_buffer_init(&buf, 1514);
285 while (wtap_read(wth, &rec, &buf, &err, &err_info, &data_offset)) {
286 FrameRecord_t *newFrameRecord;
288 newFrameRecord = g_slice_new(FrameRecord_t);
289 newFrameRecord->num = frames->len + 1;
290 newFrameRecord->offset = data_offset;
291 if (rec.presence_flags & WTAP_HAS_TS) {
292 newFrameRecord->frame_time = rec.ts;
293 } else {
294 nstime_set_unset(&newFrameRecord->frame_time);
297 if (prevFrame && frames_compare(&newFrameRecord, &prevFrame) < 0) {
298 wrong_order_count++;
301 g_ptr_array_add(frames, newFrameRecord);
302 prevFrame = newFrameRecord;
303 wtap_rec_reset(&rec);
305 wtap_rec_cleanup(&rec);
306 ws_buffer_free(&buf);
307 if (err != 0) {
308 /* Print a message noting that the read failed somewhere along the line. */
309 cfile_read_failure_message(infile, err, err_info);
312 printf("%u frames, %u out of order\n", frames->len, wrong_order_count);
314 wtap_dump_params_init(&params, wth);
316 /* Sort the frames */
317 /* XXX - Does this handle multiple SHBs correctly? */
318 if (wrong_order_count > 0) {
319 g_ptr_array_sort(frames, frames_compare);
323 /* Avoid writing if already sorted and configured to */
324 if (write_output_regardless || (wrong_order_count > 0)) {
325 /* Open outfile (same filetype/encap as input file) */
326 if (strcmp(outfile, "-") == 0) {
327 pdh = wtap_dump_open_stdout(wtap_file_type_subtype(wth),
328 WTAP_UNCOMPRESSED, &params, &err, &err_info);
329 } else {
330 pdh = wtap_dump_open(outfile, wtap_file_type_subtype(wth),
331 WTAP_UNCOMPRESSED, &params, &err, &err_info);
333 g_free(params.idb_inf);
334 params.idb_inf = NULL;
336 if (pdh == NULL) {
337 cfile_dump_open_failure_message(outfile, err, err_info,
338 wtap_file_type_subtype(wth));
339 wtap_dump_params_cleanup(&params);
340 ret = OUTPUT_FILE_ERROR;
341 goto clean_exit;
345 /* Write out each sorted frame in turn */
346 wtap_rec_init(&rec);
347 ws_buffer_init(&buf, 1514);
348 for (i = 0; i < frames->len; i++) {
349 FrameRecord_t *frame = (FrameRecord_t *)frames->pdata[i];
351 frame_write(frame, wth, pdh, &rec, &buf, infile, outfile);
353 g_slice_free(FrameRecord_t, frame);
356 wtap_rec_cleanup(&rec);
357 ws_buffer_free(&buf);
361 /* Close outfile */
362 if (!wtap_dump_close(pdh, NULL, &err, &err_info)) {
363 cfile_close_failure_message(outfile, err, err_info);
364 wtap_dump_params_cleanup(&params);
365 ret = OUTPUT_FILE_ERROR;
366 goto clean_exit;
368 } else {
369 printf("Not writing output file because input file is already in order.\n");
371 /* Free frame memory */
372 for (i = 0; i < frames->len; i++) {
373 FrameRecord_t *frame = (FrameRecord_t *)frames->pdata[i];
375 g_slice_free(FrameRecord_t, frame);
380 /* Free the whole array */
381 g_ptr_array_free(frames, TRUE);
383 wtap_dump_params_cleanup(&params);
385 /* Finally, close infile and release resources. */
386 wtap_close(wth);
388 clean_exit:
389 wtap_cleanup();
390 free_progdirs();
391 return ret;
395 * Editor modelines - https://www.wireshark.org/tools/modelines.html
397 * Local variables:
398 * c-basic-offset: 4
399 * tab-width: 8
400 * indent-tabs-mode: nil
401 * End:
403 * vi: set shiftwidth=4 tabstop=8 expandtab:
404 * :indentSize=4:tabSize=8:noTabs=true: