Move the new files to the same places as in automake.
[obnox/wireshark/wip.git] / wiretap / pppdump.c
1 /* pppdump.c
2  *
3  * $Id$
4  *
5  * Copyright (c) 2000 by Gilbert Ramirez <gram@alumni.rice.edu>
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 #include "wtap-int.h"
26 #include "buffer.h"
27 #include "pppdump.h"
28 #include "file_wrappers.h"
29
30 #include <glib.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <errno.h>
34 #include <string.h>
35
36 /*
37 pppdump records
38 Daniel Thompson (STMicroelectronics) <daniel.thompson@st.com>
39
40 +------+
41 | 0x07 |                              Reset time
42 +------+------+------+------+
43 |  t3  |  t2  |  t1  |  t0  |         t = time_t
44 +------+------+------+------+
45
46 +------+
47 | 0x06 |                              Time step (short)
48 +------+
49 |  ts  |                              ts = time step (tenths of seconds)
50 +------+
51
52 +------+
53 | 0x05 |                              Time step (long)
54 +------+------+------+------+
55 | ts3  | ts2  | ts1  | ts0  |         ts = time step (tenths of seconds)
56 +------+------+------+------+
57
58 +------+
59 | 0x04 |                              Receive deliminator (not seen in practice)
60 +------+
61
62 +------+
63 | 0x03 |                              Send deliminator (not seen in practice)
64 +------+
65
66 +------+
67 | 0x02 |                              Received data
68 +------+------+
69 |  n1  |  n0  |                       n = number of bytes following
70 +------+------+
71 |    data     |
72 |             |
73
74 +------+
75 | 0x01 |                              Sent data
76 +------+------+
77 |  n1  |  n0  |                       n = number of bytes following
78 +------+------+
79 |    data     |
80 |             |
81 */
82
83 #define PPPD_SENT_DATA          0x01
84 #define PPPD_RECV_DATA          0x02
85 #define PPPD_SEND_DELIM         0x03
86 #define PPPD_RECV_DELIM         0x04
87 #define PPPD_TIME_STEP_LONG     0x05
88 #define PPPD_TIME_STEP_SHORT    0x06
89 #define PPPD_RESET_TIME         0x07
90
91 /* this buffer must be at least (2*PPPD_MTU) + sizeof(ppp_header) +
92  * sizeof(lcp_header) + sizeof(ipcp_header).  PPPD_MTU is *very* rarely
93  * larger than 1500 so this value is fine.
94  */
95 #define PPPD_BUF_SIZE           8192
96
97 typedef enum {
98         DIRECTION_SENT,
99         DIRECTION_RECV
100 } direction_enum;
101
102 static gboolean pppdump_read(wtap *wth, int *err, gchar **err_info,
103         gint64 *data_offset);
104 static gboolean pppdump_seek_read(wtap *wth, gint64 seek_off,
105         union wtap_pseudo_header *pseudo_header, guint8 *pd, int len,
106         int *err, gchar **err_info);
107
108 /*
109  * Information saved about a packet, during the initial sequential pass
110  * through the file, to allow us to later re-read it when randomly
111  * reading packets.
112  *
113  * "offset" is the offset in the file of the first data chunk containing data
114  * from that packet; note that it may also contain data from previous
115  * packets.
116  *
117  * "num_bytes_to_skip" is the number of bytes from previous packets in that
118  * first data chunk.
119  *
120  * "dir" is the direction of the packet.
121  */
122 typedef struct {
123         gint64          offset;
124         gint64          num_bytes_to_skip;
125         direction_enum  dir;
126 } pkt_id;
127
128 /*
129  * Information about a packet currently being processed.  There is one of
130  * these for the sent packet being processed and one of these for the
131  * received packet being processed, as we could be in the middle of
132  * processing both a received packet and a sent packet.
133  *
134  * "dir" is the direction of the packet.
135  *
136  * "cnt" is the number of bytes of packet data we've accumulated.
137  *
138  * "esc" is TRUE if the next byte we see is escaped (and thus must be XORed
139  * with 0x20 before saving it), FALSE otherwise.
140  *
141  * "buf" is a buffer containing the packet data we've accumulated.
142  *
143  * "id_offset" is the offset in the file of the first data chunk
144  * containing data from the packet we're processing.
145  *
146  * "sd_offset" is the offset in the file of the first data byte from
147  * the packet we're processing - which isn't necessarily right after
148  * the header of the first data chunk, as we may already have assembled
149  * packets from that chunk.
150  *
151  * "cd_offset" is the offset in the file of the current data chunk we're
152  * processing.
153  */
154 typedef struct {
155         direction_enum  dir;
156         int             cnt;
157         gboolean        esc;
158         guint8          buf[PPPD_BUF_SIZE];
159         gint64          id_offset;
160         gint64          sd_offset;
161         gint64          cd_offset;
162 } pkt_t;
163
164 /*
165  * This keeps state used while processing records.
166  *
167  * "timestamp" is the seconds portion of the current time stamp value,
168  * as updated from PPPD_RESET_TIME, PPPD_TIME_STEP_LONG, and
169  * PPPD_TIME_STEP_SHORT records.  "tenths" is the tenths-of-seconds
170  * portion.
171  *
172  * "spkt" and "rpkt" are "pkt_t" structures for the sent and received
173  * packets we're currently working on.
174  *
175  * "offset" is the current offset in the file.
176  *
177  * "num_bytes" and "pkt" are information saved when we finish accumulating
178  * the data for a packet, if the data chunk we're working on still has more
179  * data in it:
180  *
181  *      "num_bytes" is the number of bytes of additional data remaining
182  *      in the chunk after we've finished accumulating the data for the
183  *      packet.
184  *
185  *      "pkt" is the "pkt_t" for the type of packet the data chunk is for
186  *      (sent or received packet).
187  *
188  * "seek_state" is another state structure used while processing records
189  * when doing a seek-and-read.  (That structure doesn't itself have a
190  * "seek_state" structure.)
191  *
192  * "pids" is a GPtrArray of pointers to "pkt_id" structures for all the
193  * packets we've seen during the initial sequential pass, to allow us to
194  * later retrieve them with random accesses.
195  *
196  * "pkt_cnt" is the number of packets we've seen up to this point in the
197  * sequential pass.
198  */
199 typedef struct _pppdump_t {
200         time_t                  timestamp;
201         guint                   tenths;
202         pkt_t                   spkt;
203         pkt_t                   rpkt;
204         gint64                  offset;
205         int                     num_bytes;
206         pkt_t                   *pkt;
207         struct _pppdump_t       *seek_state;
208         GPtrArray               *pids;
209         guint                   pkt_cnt;
210 } pppdump_t;
211
212 static int
213 process_data(pppdump_t *state, FILE_T fh, pkt_t *pkt, int n, guint8 *pd,
214     int *err, gchar **err_info, pkt_id *pid);
215
216 static gboolean
217 collate(pppdump_t*, FILE_T fh, int *err, gchar **err_info, guint8 *pd,
218                 int *num_bytes, direction_enum *direction, pkt_id *pid,
219                 gint64 num_bytes_to_skip);
220
221 static void
222 pppdump_close(wtap *wth);
223
224 static void
225 init_state(pppdump_t *state)
226 {
227
228         state->num_bytes = 0;
229         state->pkt = NULL;
230
231         state->spkt.dir = DIRECTION_SENT;
232         state->spkt.cnt = 0;
233         state->spkt.esc = FALSE;
234         state->spkt.id_offset = 0;
235         state->spkt.sd_offset = 0;
236         state->spkt.cd_offset = 0;
237
238         state->rpkt.dir = DIRECTION_RECV;
239         state->rpkt.cnt = 0;
240         state->rpkt.esc = FALSE;
241         state->rpkt.id_offset = 0;
242         state->rpkt.sd_offset = 0;
243         state->rpkt.cd_offset = 0;
244
245         state->seek_state = NULL;
246         state->offset = 0x100000; /* to detect errors during development */
247 }
248
249
250 int
251 pppdump_open(wtap *wth, int *err, gchar **err_info)
252 {
253         guint8          buffer[6];      /* Looking for: 0x07 t3 t2 t1 t0 ID */
254         pppdump_t       *state;
255
256         /* There is no file header, only packet records. Fortunately for us,
257         * timestamp records are separated from packet records, so we should
258         * find an "initial time stamp" (i.e., a "reset time" record, or
259         * record type 0x07) at the beginning of the file. We'll check for
260         * that, plus a valid record following the 0x07 and the four bytes
261         * representing the timestamp.
262         */
263
264         wtap_file_read_unknown_bytes(buffer, sizeof(buffer), wth->fh, err,
265             err_info);
266
267         if (buffer[0] == PPPD_RESET_TIME &&
268                         (buffer[5] == PPPD_SENT_DATA ||
269                          buffer[5] == PPPD_RECV_DATA ||
270                          buffer[5] == PPPD_TIME_STEP_LONG ||
271                          buffer[5] == PPPD_TIME_STEP_SHORT ||
272                          buffer[5] == PPPD_RESET_TIME)) {
273
274                 goto my_file_type;
275         }
276         else {
277                 return 0;
278         }
279
280   my_file_type:
281
282         if (file_seek(wth->fh, 5, SEEK_SET, err) == -1)
283                 return -1;
284
285         state = (pppdump_t *)g_malloc(sizeof(pppdump_t));
286         wth->priv = (void *)state;
287         state->timestamp = pntohl(&buffer[1]);
288         state->tenths = 0;
289
290         init_state(state);
291
292         state->offset = 5;
293         wth->file_encap = WTAP_ENCAP_PPP_WITH_PHDR;
294         wth->file_type = WTAP_FILE_PPPDUMP;
295
296         wth->snapshot_length = PPPD_BUF_SIZE; /* just guessing */
297         wth->subtype_read = pppdump_read;
298         wth->subtype_seek_read = pppdump_seek_read;
299         wth->subtype_close = pppdump_close;
300         wth->tsprecision = WTAP_FILE_TSPREC_DSEC;
301
302         state->seek_state = g_malloc(sizeof(pppdump_t));
303
304         /* If we have a random stream open, we're going to be reading
305            the file randomly; set up a GPtrArray of pointers to
306            information about how to retrieve the data for each packet. */
307         if (wth->random_fh != NULL)
308                 state->pids = g_ptr_array_new();
309         else
310                 state->pids = NULL;
311         state->pkt_cnt = 0;
312
313         return 1;
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         buffer_assure_space(wth->frame_buffer, PPPD_BUF_SIZE);
327         buf = buffer_start_ptr(wth->frame_buffer);
328
329         state = wth->priv;
330
331         /* If we have a random stream open, allocate a structure to hold
332            the information needed to read this packet's data again. */
333         if (wth->random_fh != NULL) {
334                 pid = g_new(pkt_id, 1);
335                 if (!pid) {
336                         *err = errno;   /* assume a malloc failed and set "errno" */
337                         return FALSE;
338                 }
339                 pid->offset = 0;
340         } else
341                 pid = NULL;     /* sequential only */
342
343         if (!collate(state, wth->fh, err, err_info, buf, &num_bytes, &direction,
344             pid, 0)) {
345                 if (pid != NULL)
346                         g_free(pid);
347                 return FALSE;
348         }
349
350         if (pid != NULL)
351                 pid->dir = direction;
352
353         if (pid != NULL)
354                 g_ptr_array_add(state->pids, pid);
355         /* The user's data_offset is not really an offset, but a packet number. */
356         *data_offset = state->pkt_cnt;
357         state->pkt_cnt++;
358
359         wth->phdr.presence_flags = WTAP_HAS_TS;
360         wth->phdr.len           = num_bytes;
361         wth->phdr.caplen        = num_bytes;
362         wth->phdr.ts.secs       = state->timestamp;
363         wth->phdr.ts.nsecs      = state->tenths * 100000000;
364         wth->phdr.pkt_encap     = WTAP_ENCAP_PPP_WITH_PHDR;
365
366         wth->pseudo_header.p2p.sent = (direction == DIRECTION_SENT ? TRUE : FALSE);
367
368         return TRUE;
369 }
370
371 /* Returns number of bytes copied for record, -1 if failure.
372  *
373  * This is modeled after pppdump.c, the utility to parse pppd log files; it
374  * comes with the ppp distribution.
375  */
376 static int
377 process_data(pppdump_t *state, FILE_T fh, pkt_t *pkt, int n, guint8 *pd,
378     int *err, gchar **err_info, pkt_id *pid)
379 {
380         int     c;
381         int     num_bytes = n;
382         int     num_written;
383
384         for (; num_bytes > 0; --num_bytes) {
385                 c = file_getc(fh);
386                 if (c == EOF) {
387                         *err = file_error(fh, err_info);
388                         if (*err == 0) {
389                                 *err = WTAP_ERR_SHORT_READ;
390                         }
391                         return -1;
392                 }
393                 state->offset++;
394                 switch (c) {
395                         case 0x7e:
396                                 /*
397                                  * Flag Sequence for RFC 1662 HDLC-like
398                                  * framing.
399                                  *
400                                  * As this is a raw trace of octets going
401                                  * over the wire, and that might include
402                                  * the login sequence, there is no
403                                  * guarantee that *only* PPP traffic
404                                  * appears in this file, so there is no
405                                  * guarantee that the first 0x7e we see is
406                                  * a start flag sequence, and therefore we
407                                  * cannot safely ignore all characters up
408                                  * to the first 0x7e, and therefore we
409                                  * might end up with some bogus PPP
410                                  * packets.
411                                  */
412                                 if (pkt->cnt > 0) {
413                                         /*
414                                          * We've seen stuff before this,
415                                          * so this is the end of a frame.
416                                          * Make a frame out of that stuff.
417                                          */
418                                         pkt->esc = FALSE;
419
420                                         num_written = pkt->cnt;
421                                         pkt->cnt = 0;
422                                         if (num_written <= 0) {
423                                                 return 0;
424                                         }
425
426                                         if (num_written > PPPD_BUF_SIZE) {
427                                                 *err = WTAP_ERR_UNC_OVERFLOW;
428                                                 return -1;
429                                         }
430
431                                         memcpy(pd, pkt->buf, num_written);
432
433                                         /*
434                                          * Remember the offset of the
435                                          * first record containing data
436                                          * for this packet, and how far
437                                          * into that record to skip to
438                                          * get to the beginning of the
439                                          * data for this packet; the number
440                                          * of bytes to skip into that record
441                                          * is the file offset of the first
442                                          * byte of this packet minus the
443                                          * file offset of the first byte of
444                                          * this record, minus 3 bytes for the
445                                          * header of this record (which, if
446                                          * we re-read this record, we will
447                                          * process, not skip).
448                                          */
449                                         if (pid) {
450                                                 pid->offset = pkt->id_offset;
451                                                 pid->num_bytes_to_skip =
452                                                     pkt->sd_offset - pkt->id_offset - 3;
453                                                 g_assert(pid->num_bytes_to_skip >= 0);
454                                         }
455
456                                         num_bytes--;
457                                         if (num_bytes > 0) {
458                                                 /*
459                                                  * There's more data in this
460                                                  * record.
461                                                  * Set the initial data offset
462                                                  * for the next packet.
463                                                  */
464                                                 pkt->id_offset = pkt->cd_offset;
465                                                 pkt->sd_offset = state->offset;
466                                         } else {
467                                                 /*
468                                                  * There is no more data in
469                                                  * this record.
470                                                  * Thus, we don't have the
471                                                  * initial data offset for
472                                                  * the next packet.
473                                                  */
474                                                 pkt->id_offset = 0;
475                                                 pkt->sd_offset = 0;
476                                         }
477                                         state->num_bytes = num_bytes;
478                                         state->pkt = pkt;
479                                         return num_written;
480                                 }
481                                 break;
482
483                         case 0x7d:
484                                 /*
485                                  * Control Escape octet for octet-stuffed
486                                  * RFC 1662 HDLC-like framing.
487                                  */
488                                 if (!pkt->esc) {
489                                         /*
490                                          * Control Escape not preceded by
491                                          * Control Escape; discard it
492                                          * but XOR the next octet with
493                                          * 0x20.
494                                          */
495                                         pkt->esc = TRUE;
496                                         break;
497                                 }
498                                 /*
499                                  * Control Escape preceded by Control Escape;
500                                  * treat it as an ordinary character,
501                                  * by falling through.
502                                  */
503
504                         default:
505                                 if (pkt->esc) {
506                                         /*
507                                          * This character was preceded by
508                                          * Control Escape, so XOR it with
509                                          * 0x20, as per RFC 1662's octet-
510                                          * stuffed framing, and clear
511                                          * the flag saying that the
512                                          * character should be escaped.
513                                          */
514                                         c ^= 0x20;
515                                         pkt->esc = FALSE;
516                                 }
517
518                                 if (pkt->cnt >= PPPD_BUF_SIZE) {
519                                         *err = WTAP_ERR_UNC_OVERFLOW;
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                                 wtap_file_read_unknown_bytes(&time_long, sizeof(guint32), fh, err, err_info);
653                                 state->offset += sizeof(guint32);
654                                 state->timestamp = pntohl(&time_long);
655                                 state->tenths = 0;
656                                 break;
657
658                         case PPPD_TIME_STEP_LONG:
659                                 wtap_file_read_unknown_bytes(&time_long, sizeof(guint32), fh, err, err_info);
660                                 state->offset += sizeof(guint32);
661                                 state->tenths += pntohl(&time_long);
662
663                                 if (state->tenths >= 10) {
664                                         state->timestamp += state->tenths / 10;
665                                         state->tenths = state->tenths % 10;
666                                 }
667
668                                 break;
669
670                         case PPPD_TIME_STEP_SHORT:
671                                 wtap_file_read_unknown_bytes(&time_short, sizeof(guint8), fh, err, err_info);
672                                 state->offset += sizeof(guint8);
673                                 state->tenths += time_short;
674
675                                 if (state->tenths >= 10) {
676                                         state->timestamp += state->tenths / 10;
677                                         state->tenths = state->tenths % 10;
678                                 }
679
680                                 break;
681
682                         default:
683                                 /* XXX - bad file */
684                                 *err = WTAP_ERR_BAD_FILE;
685                                 *err_info = g_strdup_printf("pppdump: bad ID byte 0x%02x", id);
686                                 return FALSE;
687                 }
688
689         }
690
691 done:
692         *err = file_error(fh, err_info);
693         if (*err == 0) {
694                 if (state->offset != start_offset) {
695                         /*
696                          * We read at least one byte, so we were working
697                          * on a record; an EOF means that record was
698                          * cut short.
699                          */
700                         *err = WTAP_ERR_SHORT_READ;
701                 }
702         }
703         return FALSE;
704 }
705
706
707
708 /* Used to read packets in random-access fashion */
709 static gboolean
710 pppdump_seek_read(wtap *wth,
711                  gint64 seek_off,
712                  union wtap_pseudo_header *pseudo_header,
713                  guint8 *pd,
714                  int len,
715                  int *err,
716                  gchar **err_info)
717 {
718         int             num_bytes;
719         direction_enum  direction;
720         pppdump_t       *state;
721         pkt_id          *pid;
722         gint64          num_bytes_to_skip;
723
724         state = wth->priv;
725
726         pid = g_ptr_array_index(state->pids, seek_off);
727         if (!pid) {
728                 *err = WTAP_ERR_BAD_FILE;       /* XXX - better error? */
729                 *err_info = g_strdup("pppdump: PID not found for record");
730                 return FALSE;
731         }
732
733         if (file_seek(wth->random_fh, pid->offset, SEEK_SET, err) == -1)
734                 return FALSE;
735
736         init_state(state->seek_state);
737         state->seek_state->offset = pid->offset;
738
739         /*
740          * We'll start reading at the first record containing data from
741          * this packet; however, that doesn't mean "collate()" will
742          * stop only when we've read that packet, as there might be
743          * data for packets going in the other direction as well, and
744          * we might finish processing one of those packets before we
745          * finish processing the packet we're reading.
746          *
747          * Therefore, we keep reading until we get a packet that's
748          * going in the direction we want.
749          */
750         num_bytes_to_skip = pid->num_bytes_to_skip;
751         do {
752                 if (!collate(state->seek_state, wth->random_fh, err, err_info,
753                     pd, &num_bytes, &direction, NULL, num_bytes_to_skip))
754                         return FALSE;
755                 num_bytes_to_skip = 0;
756         } while (direction != pid->dir);
757
758         if (len != num_bytes) {
759                 *err = WTAP_ERR_BAD_FILE;       /* XXX - better error? */
760                 *err_info = g_strdup_printf("pppdump: requested length %d doesn't match record length %d",
761                     len, num_bytes);
762                 return FALSE;
763         }
764
765         pseudo_header->p2p.sent = (pid->dir == DIRECTION_SENT ? TRUE : FALSE);
766
767         return TRUE;
768 }
769
770 static void
771 pppdump_close(wtap *wth)
772 {
773         pppdump_t       *state;
774
775         state = (pppdump_t *)wth->priv;
776
777         if (state->seek_state) { /* should always be TRUE */
778                 g_free(state->seek_state);
779         }
780
781         if (state->pids) {
782                 unsigned int i;
783                 for (i = 0; i < g_ptr_array_len(state->pids); i++) {
784                         g_free(g_ptr_array_index(state->pids, i));
785                 }
786                 g_ptr_array_free(state->pids, TRUE);
787         }
788 }