decrypt
[metze/wireshark/wip.git] / wiretap / pppdump.c
1 /* pppdump.c
2  *
3  * Copyright (c) 2000 by Gilbert Ramirez <gram@alumni.rice.edu>
4  *
5  * SPDX-License-Identifier: GPL-2.0-or-later
6  */
7
8 #include "config.h"
9 #include "wtap-int.h"
10 #include "pppdump.h"
11 #include "file_wrappers.h"
12
13 #include <stdlib.h>
14 #include <errno.h>
15 #include <string.h>
16
17 /*
18 pppdump records
19 Daniel Thompson (STMicroelectronics) <daniel.thompson@st.com>
20
21 +------+
22 | 0x07 |                              Reset time
23 +------+------+------+------+
24 |  t3  |  t2  |  t1  |  t0  |         t = time_t
25 +------+------+------+------+
26
27 +------+
28 | 0x06 |                              Time step (short)
29 +------+
30 |  ts  |                              ts = time step (tenths of seconds)
31 +------+
32
33 +------+
34 | 0x05 |                              Time step (long)
35 +------+------+------+------+
36 | ts3  | ts2  | ts1  | ts0  |         ts = time step (tenths of seconds)
37 +------+------+------+------+
38
39 +------+
40 | 0x04 |                              Receive deliminator (not seen in practice)
41 +------+
42
43 +------+
44 | 0x03 |                              Send deliminator (not seen in practice)
45 +------+
46
47 +------+
48 | 0x02 |                              Received data
49 +------+------+
50 |  n1  |  n0  |                       n = number of bytes following
51 +------+------+
52 |    data     |
53 |             |
54
55 +------+
56 | 0x01 |                              Sent data
57 +------+------+
58 |  n1  |  n0  |                       n = number of bytes following
59 +------+------+
60 |    data     |
61 |             |
62 */
63
64 #define PPPD_SENT_DATA          0x01
65 #define PPPD_RECV_DATA          0x02
66 #define PPPD_SEND_DELIM         0x03
67 #define PPPD_RECV_DELIM         0x04
68 #define PPPD_TIME_STEP_LONG     0x05
69 #define PPPD_TIME_STEP_SHORT    0x06
70 #define PPPD_RESET_TIME         0x07
71
72 /* this buffer must be at least (2*PPPD_MTU) + sizeof(ppp_header) +
73  * sizeof(lcp_header) + sizeof(ipcp_header).  PPPD_MTU is *very* rarely
74  * larger than 1500 so this value is fine.
75  *
76  * It's less than WTAP_MAX_PACKET_SIZE_STANDARD, so we don't have to worry about
77  * too-large packets.
78  */
79 #define PPPD_BUF_SIZE           8192
80
81 typedef enum {
82         DIRECTION_SENT,
83         DIRECTION_RECV
84 } direction_enum;
85
86 static gboolean pppdump_read(wtap *wth, int *err, gchar **err_info,
87         gint64 *data_offset);
88 static gboolean pppdump_seek_read(wtap *wth, gint64 seek_off,
89         wtap_rec *rec, Buffer *buf, int *err, gchar **err_info);
90
91 /*
92  * Information saved about a packet, during the initial sequential pass
93  * through the file, to allow us to later re-read it when randomly
94  * reading packets.
95  *
96  * "offset" is the offset in the file of the first data chunk containing data
97  * from that packet; note that it may also contain data from previous
98  * packets.
99  *
100  * "num_bytes_to_skip" is the number of bytes from previous packets in that
101  * first data chunk.
102  *
103  * "dir" is the direction of the packet.
104  */
105 typedef struct {
106         gint64          offset;
107         gint64          num_bytes_to_skip;
108         direction_enum  dir;
109 } pkt_id;
110
111 /*
112  * Information about a packet currently being processed.  There is one of
113  * these for the sent packet being processed and one of these for the
114  * received packet being processed, as we could be in the middle of
115  * processing both a received packet and a sent packet.
116  *
117  * "dir" is the direction of the packet.
118  *
119  * "cnt" is the number of bytes of packet data we've accumulated.
120  *
121  * "esc" is TRUE if the next byte we see is escaped (and thus must be XORed
122  * with 0x20 before saving it), FALSE otherwise.
123  *
124  * "buf" is a buffer containing the packet data we've accumulated.
125  *
126  * "id_offset" is the offset in the file of the first data chunk
127  * containing data from the packet we're processing.
128  *
129  * "sd_offset" is the offset in the file of the first data byte from
130  * the packet we're processing - which isn't necessarily right after
131  * the header of the first data chunk, as we may already have assembled
132  * packets from that chunk.
133  *
134  * "cd_offset" is the offset in the file of the current data chunk we're
135  * processing.
136  */
137 typedef struct {
138         direction_enum  dir;
139         int             cnt;
140         gboolean        esc;
141         guint8          buf[PPPD_BUF_SIZE];
142         gint64          id_offset;
143         gint64          sd_offset;
144         gint64          cd_offset;
145 } pkt_t;
146
147 /*
148  * This keeps state used while processing records.
149  *
150  * "timestamp" is the seconds portion of the current time stamp value,
151  * as updated from PPPD_RESET_TIME, PPPD_TIME_STEP_LONG, and
152  * PPPD_TIME_STEP_SHORT records.  "tenths" is the tenths-of-seconds
153  * portion.
154  *
155  * "spkt" and "rpkt" are "pkt_t" structures for the sent and received
156  * packets we're currently working on.
157  *
158  * "offset" is the current offset in the file.
159  *
160  * "num_bytes" and "pkt" are information saved when we finish accumulating
161  * the data for a packet, if the data chunk we're working on still has more
162  * data in it:
163  *
164  *      "num_bytes" is the number of bytes of additional data remaining
165  *      in the chunk after we've finished accumulating the data for the
166  *      packet.
167  *
168  *      "pkt" is the "pkt_t" for the type of packet the data chunk is for
169  *      (sent or received packet).
170  *
171  * "seek_state" is another state structure used while processing records
172  * when doing a seek-and-read.  (That structure doesn't itself have a
173  * "seek_state" structure.)
174  *
175  * "pids" is a GPtrArray of pointers to "pkt_id" structures for all the
176  * packets we've seen during the initial sequential pass, to allow us to
177  * later retrieve them with random accesses.
178  *
179  * "pkt_cnt" is the number of packets we've seen up to this point in the
180  * sequential pass.
181  */
182 typedef struct _pppdump_t {
183         time_t                  timestamp;
184         guint                   tenths;
185         pkt_t                   spkt;
186         pkt_t                   rpkt;
187         gint64                  offset;
188         int                     num_bytes;
189         pkt_t                   *pkt;
190         struct _pppdump_t       *seek_state;
191         GPtrArray               *pids;
192         guint                   pkt_cnt;
193 } pppdump_t;
194
195 static int
196 process_data(pppdump_t *state, FILE_T fh, pkt_t *pkt, int n, guint8 *pd,
197     int *err, gchar **err_info, pkt_id *pid);
198
199 static gboolean
200 collate(pppdump_t*, FILE_T fh, int *err, gchar **err_info, guint8 *pd,
201                 int *num_bytes, direction_enum *direction, pkt_id *pid,
202                 gint64 num_bytes_to_skip);
203
204 static void
205 pppdump_close(wtap *wth);
206
207 static void
208 init_state(pppdump_t *state)
209 {
210
211         state->num_bytes = 0;
212         state->pkt = NULL;
213
214         state->spkt.dir = DIRECTION_SENT;
215         state->spkt.cnt = 0;
216         state->spkt.esc = FALSE;
217         state->spkt.id_offset = 0;
218         state->spkt.sd_offset = 0;
219         state->spkt.cd_offset = 0;
220
221         state->rpkt.dir = DIRECTION_RECV;
222         state->rpkt.cnt = 0;
223         state->rpkt.esc = FALSE;
224         state->rpkt.id_offset = 0;
225         state->rpkt.sd_offset = 0;
226         state->rpkt.cd_offset = 0;
227
228         state->seek_state = NULL;
229         state->offset = 0x100000; /* to detect errors during development */
230 }
231
232
233 wtap_open_return_val
234 pppdump_open(wtap *wth, int *err, gchar **err_info)
235 {
236         guint8          buffer[6];      /* Looking for: 0x07 t3 t2 t1 t0 ID */
237         pppdump_t       *state;
238
239         /* There is no file header, only packet records. Fortunately for us,
240         * timestamp records are separated from packet records, so we should
241         * find an "initial time stamp" (i.e., a "reset time" record, or
242         * record type 0x07) at the beginning of the file. We'll check for
243         * that, plus a valid record following the 0x07 and the four bytes
244         * representing the timestamp.
245         */
246
247         if (!wtap_read_bytes(wth->fh, buffer, sizeof(buffer),
248             err, err_info)) {
249                 if (*err != WTAP_ERR_SHORT_READ)
250                         return WTAP_OPEN_ERROR;
251                 return WTAP_OPEN_NOT_MINE;
252         }
253
254         if (buffer[0] == PPPD_RESET_TIME &&
255                         (buffer[5] == PPPD_SENT_DATA ||
256                          buffer[5] == PPPD_RECV_DATA ||
257                          buffer[5] == PPPD_TIME_STEP_LONG ||
258                          buffer[5] == PPPD_TIME_STEP_SHORT ||
259                          buffer[5] == PPPD_RESET_TIME)) {
260
261                 goto my_file_type;
262         }
263         else {
264                 return WTAP_OPEN_NOT_MINE;
265         }
266
267   my_file_type:
268
269         if (file_seek(wth->fh, 5, SEEK_SET, err) == -1)
270                 return WTAP_OPEN_ERROR;
271
272         state = (pppdump_t *)g_malloc(sizeof(pppdump_t));
273         wth->priv = (void *)state;
274         state->timestamp = pntoh32(&buffer[1]);
275         state->tenths = 0;
276
277         init_state(state);
278
279         state->offset = 5;
280         wth->file_encap = WTAP_ENCAP_PPP_WITH_PHDR;
281         wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_PPPDUMP;
282
283         wth->snapshot_length = PPPD_BUF_SIZE; /* just guessing */
284         wth->subtype_read = pppdump_read;
285         wth->subtype_seek_read = pppdump_seek_read;
286         wth->subtype_close = pppdump_close;
287         wth->file_tsprec = WTAP_TSPREC_DSEC;
288
289         state->seek_state = g_new(pppdump_t,1);
290
291         /* If we have a random stream open, we're going to be reading
292            the file randomly; set up a GPtrArray of pointers to
293            information about how to retrieve the data for each packet. */
294         if (wth->random_fh != NULL)
295                 state->pids = g_ptr_array_new();
296         else
297                 state->pids = NULL;
298         state->pkt_cnt = 0;
299
300         return WTAP_OPEN_MINE;
301 }
302
303 /* Set part of the struct wtap_pkthdr. */
304 static void
305 pppdump_set_phdr(wtap_rec *rec, int num_bytes,
306     direction_enum direction)
307 {
308         rec->rec_type = REC_TYPE_PACKET;
309         rec->rec_header.packet_header.len = num_bytes;
310         rec->rec_header.packet_header.caplen = num_bytes;
311         rec->rec_header.packet_header.pkt_encap = WTAP_ENCAP_PPP_WITH_PHDR;
312
313         rec->rec_header.packet_header.pseudo_header.p2p.sent = (direction == DIRECTION_SENT ? TRUE : FALSE);
314 }
315
316 /* Find the next packet and parse it; called from wtap_read(). */
317 static gboolean
318 pppdump_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
319 {
320         int             num_bytes;
321         direction_enum  direction;
322         guint8          *buf;
323         pppdump_t       *state;
324         pkt_id          *pid;
325
326         state = (pppdump_t *)wth->priv;
327
328         /* If we have a random stream open, allocate a structure to hold
329            the information needed to read this packet's data again. */
330         if (wth->random_fh != NULL) {
331                 pid = g_new(pkt_id, 1);
332                 if (!pid) {
333                         *err = errno;   /* assume a malloc failed and set "errno" */
334                         return FALSE;
335                 }
336                 pid->offset = 0;
337         } else
338                 pid = NULL;     /* sequential only */
339
340         ws_buffer_assure_space(wth->rec_data, PPPD_BUF_SIZE);
341         buf = ws_buffer_start_ptr(wth->rec_data);
342
343         if (!collate(state, wth->fh, err, err_info, buf, &num_bytes, &direction,
344             pid, 0)) {
345                 g_free(pid);
346                 return FALSE;
347         }
348
349         if (pid != NULL)
350                 pid->dir = direction;
351
352         if (pid != NULL)
353                 g_ptr_array_add(state->pids, pid);
354         /* The user's data_offset is not really an offset, but a packet number. */
355         *data_offset = state->pkt_cnt;
356         state->pkt_cnt++;
357
358         pppdump_set_phdr(&wth->rec, num_bytes, direction);
359         wth->rec.presence_flags = WTAP_HAS_TS;
360         wth->rec.ts.secs        = state->timestamp;
361         wth->rec.ts.nsecs       = state->tenths * 100000000;
362
363         return TRUE;
364 }
365
366 /* Returns number of bytes copied for record, -1 if failure.
367  *
368  * This is modeled after pppdump.c, the utility to parse pppd log files; it
369  * comes with the ppp distribution.
370  */
371 static int
372 process_data(pppdump_t *state, FILE_T fh, pkt_t *pkt, int n, guint8 *pd,
373     int *err, gchar **err_info, pkt_id *pid)
374 {
375         int     c;
376         int     num_bytes = n;
377         int     num_written;
378
379         for (; num_bytes > 0; --num_bytes) {
380                 c = file_getc(fh);
381                 if (c == EOF) {
382                         *err = file_error(fh, err_info);
383                         if (*err == 0) {
384                                 *err = WTAP_ERR_SHORT_READ;
385                         }
386                         return -1;
387                 }
388                 state->offset++;
389                 switch (c) {
390                         case 0x7e:
391                                 /*
392                                  * Flag Sequence for RFC 1662 HDLC-like
393                                  * framing.
394                                  *
395                                  * As this is a raw trace of octets going
396                                  * over the wire, and that might include
397                                  * the login sequence, there is no
398                                  * guarantee that *only* PPP traffic
399                                  * appears in this file, so there is no
400                                  * guarantee that the first 0x7e we see is
401                                  * a start flag sequence, and therefore we
402                                  * cannot safely ignore all characters up
403                                  * to the first 0x7e, and therefore we
404                                  * might end up with some bogus PPP
405                                  * packets.
406                                  */
407                                 if (pkt->cnt > 0) {
408                                         /*
409                                          * We've seen stuff before this,
410                                          * so this is the end of a frame.
411                                          * Make a frame out of that stuff.
412                                          */
413                                         pkt->esc = FALSE;
414
415                                         num_written = pkt->cnt;
416                                         pkt->cnt = 0;
417                                         if (num_written <= 0) {
418                                                 return 0;
419                                         }
420
421                                         if (num_written > PPPD_BUF_SIZE) {
422                                                 *err = WTAP_ERR_BAD_FILE;
423                                                 *err_info = g_strdup_printf("pppdump: File has %u-byte packet, bigger than maximum of %u",
424                                                     num_written, PPPD_BUF_SIZE);
425                                                 return -1;
426                                         }
427
428                                         memcpy(pd, pkt->buf, num_written);
429
430                                         /*
431                                          * Remember the offset of the
432                                          * first record containing data
433                                          * for this packet, and how far
434                                          * into that record to skip to
435                                          * get to the beginning of the
436                                          * data for this packet; the number
437                                          * of bytes to skip into that record
438                                          * is the file offset of the first
439                                          * byte of this packet minus the
440                                          * file offset of the first byte of
441                                          * this record, minus 3 bytes for the
442                                          * header of this record (which, if
443                                          * we re-read this record, we will
444                                          * process, not skip).
445                                          */
446                                         if (pid) {
447                                                 pid->offset = pkt->id_offset;
448                                                 pid->num_bytes_to_skip =
449                                                     pkt->sd_offset - pkt->id_offset - 3;
450                                                 g_assert(pid->num_bytes_to_skip >= 0);
451                                         }
452
453                                         num_bytes--;
454                                         if (num_bytes > 0) {
455                                                 /*
456                                                  * There's more data in this
457                                                  * record.
458                                                  * Set the initial data offset
459                                                  * for the next packet.
460                                                  */
461                                                 pkt->id_offset = pkt->cd_offset;
462                                                 pkt->sd_offset = state->offset;
463                                         } else {
464                                                 /*
465                                                  * There is no more data in
466                                                  * this record.
467                                                  * Thus, we don't have the
468                                                  * initial data offset for
469                                                  * the next packet.
470                                                  */
471                                                 pkt->id_offset = 0;
472                                                 pkt->sd_offset = 0;
473                                         }
474                                         state->num_bytes = num_bytes;
475                                         state->pkt = pkt;
476                                         return num_written;
477                                 }
478                                 break;
479
480                         case 0x7d:
481                                 /*
482                                  * Control Escape octet for octet-stuffed
483                                  * RFC 1662 HDLC-like framing.
484                                  */
485                                 if (!pkt->esc) {
486                                         /*
487                                          * Control Escape not preceded by
488                                          * Control Escape; discard it
489                                          * but XOR the next octet with
490                                          * 0x20.
491                                          */
492                                         pkt->esc = TRUE;
493                                         break;
494                                 }
495                                 /*
496                                  * Control Escape preceded by Control Escape;
497                                  * treat it as an ordinary character,
498                                  * by falling through.
499                                  */
500
501                         /* FALL THROUGH */
502                         default:
503                                 if (pkt->esc) {
504                                         /*
505                                          * This character was preceded by
506                                          * Control Escape, so XOR it with
507                                          * 0x20, as per RFC 1662's octet-
508                                          * stuffed framing, and clear
509                                          * the flag saying that the
510                                          * character should be escaped.
511                                          */
512                                         c ^= 0x20;
513                                         pkt->esc = FALSE;
514                                 }
515
516                                 if (pkt->cnt >= PPPD_BUF_SIZE) {
517                                         *err = WTAP_ERR_BAD_FILE;
518                                         *err_info = g_strdup_printf("pppdump: File has %u-byte packet, bigger than maximum of %u",
519                                             pkt->cnt - 1, PPPD_BUF_SIZE);
520                                         return -1;
521                                 }
522                                 pkt->buf[pkt->cnt++] = c;
523                                 break;
524                 }
525         }
526
527         /* we could have run out of bytes to read */
528         return 0;
529 }
530
531 /* Returns TRUE if packet data copied, FALSE if error occurred or EOF (no more records). */
532 static gboolean
533 collate(pppdump_t* state, FILE_T fh, int *err, gchar **err_info, guint8 *pd,
534                 int *num_bytes, direction_enum *direction, pkt_id *pid,
535                 gint64 num_bytes_to_skip)
536 {
537         int             id;
538         pkt_t           *pkt = NULL;
539         int             byte0, byte1;
540         int             n, num_written = 0;
541         gint64          start_offset;
542         guint32         time_long;
543         guint8          time_short;
544
545         /*
546          * Process any data left over in the current record when doing
547          * sequential processing.
548          */
549         if (state->num_bytes > 0) {
550                 g_assert(num_bytes_to_skip == 0);
551                 pkt = state->pkt;
552                 num_written = process_data(state, fh, pkt, state->num_bytes,
553                     pd, err, err_info, pid);
554
555                 if (num_written < 0) {
556                         return FALSE;
557                 }
558                 else if (num_written > 0) {
559                         *num_bytes = num_written;
560                         *direction = pkt->dir;
561                         return TRUE;
562                 }
563                 /* if 0 bytes written, keep processing */
564         } else {
565                 /*
566                  * We didn't have any data left over, so the packet will
567                  * start at the beginning of a record.
568                  */
569                 if (pid)
570                         pid->num_bytes_to_skip = 0;
571         }
572
573         /*
574          * That didn't get all the data for this packet, so process
575          * subsequent records.
576          */
577         start_offset = state->offset;
578         while ((id = file_getc(fh)) != EOF) {
579                 state->offset++;
580                 switch (id) {
581                         case PPPD_SENT_DATA:
582                         case PPPD_RECV_DATA:
583                                 pkt = id == PPPD_SENT_DATA ? &state->spkt : &state->rpkt;
584
585                                 /*
586                                  * Save the offset of the beginning of
587                                  * the current record.
588                                  */
589                                 pkt->cd_offset = state->offset - 1;
590
591                                 /*
592                                  * Get the length of the record.
593                                  */
594                                 byte0 = file_getc(fh);
595                                 if (byte0 == EOF)
596                                         goto done;
597                                 state->offset++;
598                                 byte1 = file_getc(fh);
599                                 if (byte1 == EOF)
600                                         goto done;
601                                 state->offset++;
602                                 n = (byte0 << 8) | byte1;
603
604                                 if (pkt->id_offset == 0) {
605                                         /*
606                                          * We don't have the initial data
607                                          * offset for this packet, which
608                                          * means this is the first
609                                          * data record for that packet.
610                                          * Save the offset of the
611                                          * beginning of that record and
612                                          * the offset of the first data
613                                          * byte in the packet, which is
614                                          * the first data byte in the
615                                          * record.
616                                          */
617                                         pkt->id_offset = pkt->cd_offset;
618                                         pkt->sd_offset = state->offset;
619                                 }
620
621                                 if (n == 0)
622                                         continue;
623
624                                 g_assert(num_bytes_to_skip < n);
625                                 while (num_bytes_to_skip) {
626                                         if (file_getc(fh) == EOF)
627                                                 goto done;
628                                         state->offset++;
629                                         num_bytes_to_skip--;
630                                         n--;
631                                 }
632                                 num_written = process_data(state, fh, pkt, n,
633                                     pd, err, err_info, pid);
634
635                                 if (num_written < 0) {
636                                         return FALSE;
637                                 }
638                                 else if (num_written > 0) {
639                                         *num_bytes = num_written;
640                                         *direction = pkt->dir;
641                                         return TRUE;
642                                 }
643                                 /* if 0 bytes written, keep looping */
644                                 break;
645
646                         case PPPD_SEND_DELIM:
647                         case PPPD_RECV_DELIM:
648                                 /* What can we do? */
649                                 break;
650
651                         case PPPD_RESET_TIME:
652                                 if (!wtap_read_bytes(fh, &time_long, sizeof(guint32), err, err_info))
653                                         return FALSE;
654                                 state->offset += sizeof(guint32);
655                                 state->timestamp = pntoh32(&time_long);
656                                 state->tenths = 0;
657                                 break;
658
659                         case PPPD_TIME_STEP_LONG:
660                                 if (!wtap_read_bytes(fh, &time_long, sizeof(guint32), err, err_info))
661                                         return FALSE;
662                                 state->offset += sizeof(guint32);
663                                 state->tenths += pntoh32(&time_long);
664
665                                 if (state->tenths >= 10) {
666                                         state->timestamp += state->tenths / 10;
667                                         state->tenths = state->tenths % 10;
668                                 }
669
670                                 break;
671
672                         case PPPD_TIME_STEP_SHORT:
673                                 if (!wtap_read_bytes(fh, &time_short, sizeof(guint8), err, err_info))
674                                         return FALSE;
675                                 state->offset += sizeof(guint8);
676                                 state->tenths += time_short;
677
678                                 if (state->tenths >= 10) {
679                                         state->timestamp += state->tenths / 10;
680                                         state->tenths = state->tenths % 10;
681                                 }
682
683                                 break;
684
685                         default:
686                                 /* XXX - bad file */
687                                 *err = WTAP_ERR_BAD_FILE;
688                                 *err_info = g_strdup_printf("pppdump: bad ID byte 0x%02x", id);
689                                 return FALSE;
690                 }
691
692         }
693
694 done:
695         *err = file_error(fh, err_info);
696         if (*err == 0) {
697                 if (state->offset != start_offset) {
698                         /*
699                          * We read at least one byte, so we were working
700                          * on a record; an EOF means that record was
701                          * cut short.
702                          */
703                         *err = WTAP_ERR_SHORT_READ;
704                 }
705         }
706         return FALSE;
707 }
708
709
710
711 /* Used to read packets in random-access fashion */
712 static gboolean
713 pppdump_seek_read(wtap *wth,
714                  gint64 seek_off,
715                  wtap_rec *rec,
716                  Buffer *buf,
717                  int *err,
718                  gchar **err_info)
719 {
720         int             num_bytes;
721         guint8          *pd;
722         direction_enum  direction;
723         pppdump_t       *state;
724         pkt_id          *pid;
725         gint64          num_bytes_to_skip;
726
727         state = (pppdump_t *)wth->priv;
728
729         pid = (pkt_id *)g_ptr_array_index(state->pids, seek_off);
730         if (!pid) {
731                 *err = WTAP_ERR_BAD_FILE;       /* XXX - better error? */
732                 *err_info = g_strdup("pppdump: PID not found for record");
733                 return FALSE;
734         }
735
736         if (file_seek(wth->random_fh, pid->offset, SEEK_SET, err) == -1)
737                 return FALSE;
738
739         init_state(state->seek_state);
740         state->seek_state->offset = pid->offset;
741
742         ws_buffer_assure_space(buf, PPPD_BUF_SIZE);
743         pd = ws_buffer_start_ptr(buf);
744
745         /*
746          * We'll start reading at the first record containing data from
747          * this packet; however, that doesn't mean "collate()" will
748          * stop only when we've read that packet, as there might be
749          * data for packets going in the other direction as well, and
750          * we might finish processing one of those packets before we
751          * finish processing the packet we're reading.
752          *
753          * Therefore, we keep reading until we get a packet that's
754          * going in the direction we want.
755          */
756         num_bytes_to_skip = pid->num_bytes_to_skip;
757         do {
758                 if (!collate(state->seek_state, wth->random_fh, err, err_info,
759                     pd, &num_bytes, &direction, NULL, num_bytes_to_skip))
760                         return FALSE;
761                 num_bytes_to_skip = 0;
762         } while (direction != pid->dir);
763
764         pppdump_set_phdr(rec, num_bytes, pid->dir);
765
766         return TRUE;
767 }
768
769 static void
770 pppdump_close(wtap *wth)
771 {
772         pppdump_t       *state;
773
774         state = (pppdump_t *)wth->priv;
775
776         if (state->seek_state) { /* should always be TRUE */
777                 g_free(state->seek_state);
778         }
779
780         if (state->pids) {
781                 unsigned int i;
782                 for (i = 0; i < g_ptr_array_len(state->pids); i++) {
783                         g_free(g_ptr_array_index(state->pids, i));
784                 }
785                 g_ptr_array_free(state->pids, TRUE);
786         }
787 }
788
789 /*
790  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
791  *
792  * Local variables:
793  * c-basic-offset: 8
794  * tab-width: 8
795  * indent-tabs-mode: t
796  * End:
797  *
798  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
799  * :indentSize=8:tabSize=8:noTabs=false:
800  */