1 /* Reorder the frames from an input dump file, and write to output dump file.
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.
34 /* Show command-line usage */
35 /* TODO: add reoder list length as an optional param? */
36 static void usage(void)
38 printf("usage: reorder <infile> <outfile>\n");
41 /* Remember where this frame was in the file */
42 typedef struct FrameRecord_t {
46 struct wtap_nstime time;
48 /* List item pointers */
49 struct FrameRecord_t *prev;
50 struct FrameRecord_t *next;
53 /* This is pretty big, but I don't mind waiting a few seconds */
54 #define MAX_REORDER_LIST_LENGTH 3000
55 static int g_FrameRecordCount;
57 /* This is the list of frames, sorted by time. Later frames at the front, earlier
59 static FrameRecord_t *g_FrameListHead;
60 static FrameRecord_t *g_FrameListTail;
63 /**************************************************/
66 /* Enable this symbol to see debug output */
67 /* #define REORDER_DEBUG */
70 static void ReorderListDebugPrint(void)
73 FrameRecord_t *tmp = g_FrameListHead;
76 printf("%6d: offset=%6llu, length=%6u, time=%lu:%u",
77 ++count, tmp->offset, tmp->length, tmp->time.secs, tmp->time.nsecs);
79 if (tmp == g_FrameListHead) {
82 if (tmp == g_FrameListTail) {
92 #define ReorderListDebugPrint()
96 #define DEBUG_PRINT printf
98 #define DEBUG_PRINT(...)
101 /**************************************************/
103 /* Counting frames that weren't in order */
104 static int g_OutOfOrder = 0;
107 /* Is time1 later than time2? */
108 static gboolean isLaterTime(struct wtap_nstime time1,
109 struct wtap_nstime time2)
111 if (time1.secs > time2.secs) {
114 if (time1.secs == time2.secs) {
115 return (time1.nsecs > time2.nsecs);
122 /* Is the reorder list empty? */
123 static gboolean ReorderListEmpty(void)
125 return (g_FrameRecordCount == 0);
128 /* Is the reorder list full? */
129 static gboolean ReorderListFull(void)
131 return (g_FrameRecordCount >= MAX_REORDER_LIST_LENGTH);
134 /* Add a new frame to the reorder list */
135 /* Adding later ones to the front */
136 static void ReorderListAdd(gint64 offset, guint32 length,
137 struct wtap_nstime time)
140 FrameRecord_t *newFrameRecord = g_malloc(sizeof(FrameRecord_t));
142 /* Populate fields */
143 DEBUG_PRINT("\nAdded with offset=%06llu, length=%05u, secs=%lu, nsecs=%d\n",
144 offset, length, time.secs, time.nsecs);
145 newFrameRecord->offset = offset;
146 newFrameRecord->length = length;
147 newFrameRecord->time = time;
149 /* We will definitely add it below, so inc counter */
150 g_FrameRecordCount++;
152 /* First time, this will be the head */
153 if (g_FrameListHead == NULL) {
154 DEBUG_PRINT("this item will be head - only item\n");
155 g_FrameListHead = newFrameRecord;
156 newFrameRecord->prev = NULL;
157 newFrameRecord->next = NULL;
158 g_FrameListTail = newFrameRecord;
162 /* Look for the place in the list where this item fits */
163 tmp = g_FrameListHead;
164 while (tmp != NULL) {
165 if (isLaterTime(time, tmp->time)) {
166 DEBUG_PRINT("Time was Later, writing before element\n");
168 /* Insert newFrameRecord *before* tmp */
170 /* Fix up prev item */
171 if (tmp == g_FrameListHead) {
172 /* Inserting before existing head */
173 g_FrameListHead = newFrameRecord;
176 /* Our prev is tmps old prev */
177 newFrameRecord->prev = tmp->prev;
178 /* Its next points to us */
179 newFrameRecord->prev->next = newFrameRecord;
182 /* Fix up next item */
183 newFrameRecord->next = tmp;
184 tmp->prev = newFrameRecord;
191 /* Didn't find an item to insert in front of */
192 if (tmp->next == NULL) {
193 DEBUG_PRINT("Reached the end of the list, so insert here\n");
195 /* We are the new last item */
196 tmp->next = newFrameRecord;
197 newFrameRecord->prev = tmp;
198 newFrameRecord->next = NULL;
199 g_FrameListTail = newFrameRecord;
204 /* Move onto the next item */
205 DEBUG_PRINT("Time was earlier, move to next position\n");
211 /* Dump the earliest item in the reorder list to the output file, and pop it */
212 static void ReorderListDumpEarliest(wtap *wth, wtap_dumper *pdh)
214 union wtap_pseudo_header pseudo_header;
217 const struct wtap_pkthdr *phdr;
219 struct wtap_pkthdr new_phdr;
221 FrameRecord_t *prev_tail = g_FrameListTail;
223 DEBUG_PRINT("\nDumping frame (offset=%llu, length=%u) (%u items in list)\n",
224 g_FrameListHead->offset, g_FrameListHead->length,
227 /* Re-read the first frame from the stored location */
229 g_FrameListTail->offset,
232 g_FrameListTail->length,
235 DEBUG_PRINT("re-read: err is %u, buf is (%s)\n", err, buf);
237 /* Get packet header */
238 phdr = wtap_phdr(wth);
240 /* Copy, and set length and timestamp from item. */
241 memcpy((void*)&new_phdr, phdr, sizeof(struct wtap_pkthdr));
242 new_phdr.len = g_FrameListTail->length;
243 new_phdr.ts.secs = g_FrameListTail->time.secs;
244 new_phdr.ts.nsecs = g_FrameListTail->time.nsecs;
246 /* Dump frame to outfile */
247 if (!wtap_dump(pdh, &new_phdr, &pseudo_header, buf, &err)) {
248 printf("Error (%s) writing frame to outfile\n", wtap_strerror(err));
252 /* Now remove this (the last/earliest) item from the list */
253 if (g_FrameListTail->prev == NULL) {
254 g_FrameListTail = NULL;
255 g_FrameListHead = NULL;
258 /* 2nd last item is now last */
259 g_FrameListTail->prev->next = NULL;
260 g_FrameListTail = g_FrameListTail->prev;
263 /* And free the struct */
265 g_FrameRecordCount--;
267 DEBUG_PRINT("Frame written, %u remaining\n", g_FrameRecordCount);
272 /********************************************************************/
274 /********************************************************************/
275 int main(int argc, char *argv[])
278 wtap_dumper *pdh = NULL;
282 const struct wtap_pkthdr *phdr;
283 guint32 read_count = 0;
285 /* 1st arg is infile, 2nd arg is outfile */
298 wth = wtap_open_offline(infile, &err, &err_info, TRUE);
300 printf("reorder: Can't open %s: %s\n", infile, wtap_strerror(err));
304 DEBUG_PRINT("file_type is %u\n", wtap_file_type(wth));
306 /* Open outfile (same filetype/encap as input file) */
307 pdh = wtap_dump_open(outfile, wtap_file_type(wth), wtap_file_encap(wth), 65535, FALSE, &err);
309 printf("Failed to open output file: (%s) - error %s\n", outfile, wtap_strerror(err));
314 /* Read each frame from infile */
315 while (wtap_read(wth, &err, &err_info, &data_offset)) {
317 phdr = wtap_phdr(wth);
319 /* Add it to the reordering list */
320 ReorderListAdd(data_offset, phdr->len, phdr->ts);
321 ReorderListDebugPrint();
323 /* If/when the list gets full, dump the earliest item out */
324 if (ReorderListFull()) {
325 DEBUG_PRINT("List is full, dumping earliest!\n");
327 /* Write out the earliest one */
328 ReorderListDumpEarliest(wth, pdh);
329 ReorderListDebugPrint();
333 /* Flush out the remaining (ordered) frames */
334 while (!ReorderListEmpty()) {
335 ReorderListDumpEarliest(wth, pdh);
336 ReorderListDebugPrint();
340 if (!wtap_dump_close(pdh, &err)) {
341 printf("reorder: Error closing %s: %s\n", outfile, wtap_strerror(err));
345 /* Write how many frames, and how many were out of order */
346 printf("%u frames, %u out of order\n", read_count, g_OutOfOrder);
348 /* Finally, close infile */