Clean up some 64-bit issues.
[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         long                    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, 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 _U_)
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
266         if (buffer[0] == PPPD_RESET_TIME &&
267                         (buffer[5] == PPPD_SENT_DATA ||
268                          buffer[5] == PPPD_RECV_DATA ||
269                          buffer[5] == PPPD_TIME_STEP_LONG ||
270                          buffer[5] == PPPD_TIME_STEP_SHORT ||
271                          buffer[5] == PPPD_RESET_TIME)) {
272
273                 goto my_file_type;
274         }
275         else {
276                 return 0;
277         }
278
279   my_file_type:
280
281         if (file_seek(wth->fh, 5, SEEK_SET, err) == -1)
282                 return -1;
283
284         state = wth->capture.generic = g_malloc(sizeof(pppdump_t));
285         state->timestamp = pntohl(&buffer[1]);
286         state->tenths = 0;
287
288         init_state(state);
289
290         state->offset = 5;
291         wth->file_encap = WTAP_ENCAP_PPP_WITH_PHDR;
292         wth->file_type = WTAP_FILE_PPPDUMP;
293
294         wth->snapshot_length = PPPD_BUF_SIZE; /* just guessing */
295         wth->subtype_read = pppdump_read;
296         wth->subtype_seek_read = pppdump_seek_read;
297         wth->subtype_close = pppdump_close;
298         wth->tsprecision = WTAP_FILE_TSPREC_DSEC;
299
300         state->seek_state = g_malloc(sizeof(pppdump_t));
301
302         /* If we have a random stream open, we're going to be reading
303            the file randomly; set up a GPtrArray of pointers to
304            information about how to retrieve the data for each packet. */
305         if (wth->random_fh != NULL)
306                 state->pids = g_ptr_array_new();
307         else
308                 state->pids = NULL;
309         state->pkt_cnt = 0;
310
311         return 1;
312 }
313
314 /* Find the next packet and parse it; called from wtap_read(). */
315 static gboolean
316 pppdump_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
317 {
318         int             num_bytes;
319         direction_enum  direction;
320         guint8          *buf;
321         pppdump_t       *state;
322         pkt_id          *pid;
323
324         buffer_assure_space(wth->frame_buffer, PPPD_BUF_SIZE);
325         buf = buffer_start_ptr(wth->frame_buffer);
326
327         state = wth->capture.generic;
328
329         /* If we have a random stream open, allocate a structure to hold
330            the information needed to read this packet's data again. */
331         if (wth->random_fh != NULL) {
332                 pid = g_new(pkt_id, 1);
333                 if (!pid) {
334                         *err = errno;   /* assume a malloc failed and set "errno" */
335                         return FALSE;
336                 }
337                 pid->offset = 0;
338         } else
339                 pid = NULL;     /* sequential only */
340
341         if (!collate(state, wth->fh, err, err_info, buf, &num_bytes, &direction,
342             pid, 0)) {
343                 if (pid != NULL)
344                         g_free(pid);
345                 return FALSE;
346         }
347
348         if (pid != NULL)
349                 pid->dir = direction;
350
351         if (pid != NULL)
352                 g_ptr_array_add(state->pids, pid);
353         /* The user's data_offset is not really an offset, but a packet number. */
354         *data_offset = state->pkt_cnt;
355         state->pkt_cnt++;
356
357         wth->phdr.len           = num_bytes;
358         wth->phdr.caplen        = num_bytes;
359         wth->phdr.ts.secs       = state->timestamp;
360         wth->phdr.ts.nsecs      = state->tenths * 100000000;
361         wth->phdr.pkt_encap     = WTAP_ENCAP_PPP_WITH_PHDR;
362
363         wth->pseudo_header.p2p.sent = (direction == DIRECTION_SENT ? TRUE : FALSE);
364
365         return TRUE;
366 }
367
368 /* Returns number of bytes copied for record, -1 if failure.
369  *
370  * This is modeled after pppdump.c, the utility to parse pppd log files; it
371  * comes with the ppp distribution.
372  */
373 static int
374 process_data(pppdump_t *state, FILE_T fh, pkt_t *pkt, int n, guint8 *pd,
375     int *err, pkt_id *pid)
376 {
377         int     c;
378         int     num_bytes = n;
379         int     num_written;
380
381         for (; num_bytes > 0; --num_bytes) {
382                 c = file_getc(fh);
383                 if (c == EOF) {
384                         *err = file_error(fh);
385                         if (*err == 0) {
386                                 *err = WTAP_ERR_SHORT_READ;
387                         }
388                         return -1;
389                 }
390                 state->offset++;
391                 switch (c) {
392                         case 0x7e:
393                                 /*
394                                  * Flag Sequence for RFC 1662 HDLC-like
395                                  * framing.
396                                  *
397                                  * As this is a raw trace of octets going
398                                  * over the wire, and that might include
399                                  * the login sequence, there is no
400                                  * guarantee that *only* PPP traffic
401                                  * appears in this file, so there is no
402                                  * guarantee that the first 0x7e we see is
403                                  * a start flag sequence, and therefore we
404                                  * cannot safely ignore all characters up
405                                  * to the first 0x7e, and therefore we
406                                  * might end up with some bogus PPP
407                                  * packets.
408                                  */
409                                 if (pkt->cnt > 0) {
410                                         /*
411                                          * We've seen stuff before this,
412                                          * so this is the end of a frame.
413                                          * Make a frame out of that stuff.
414                                          */
415                                         pkt->esc = FALSE;
416
417                                         num_written = pkt->cnt;
418                                         pkt->cnt = 0;
419                                         if (num_written <= 0) {
420                                                 return 0;
421                                         }
422
423                                         if (num_written > PPPD_BUF_SIZE) {
424                                                 *err = WTAP_ERR_UNC_OVERFLOW;
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                         default:
502                                 if (pkt->esc) {
503                                         /*
504                                          * This character was preceded by
505                                          * Control Escape, so XOR it with
506                                          * 0x20, as per RFC 1662's octet-
507                                          * stuffed framing, and clear
508                                          * the flag saying that the
509                                          * character should be escaped.
510                                          */
511                                         c ^= 0x20;
512                                         pkt->esc = FALSE;
513                                 }
514
515                                 pkt->buf[pkt->cnt++] = c;
516                                 if (pkt->cnt > PPPD_BUF_SIZE) {
517                                         *err = WTAP_ERR_UNC_OVERFLOW;
518                                         return -1;
519                                 }
520                                 break;
521                 }
522         }
523
524         /* we could have run out of bytes to read */
525         return 0;
526 }
527
528 /* Returns TRUE if packet data copied, FALSE if error occurred or EOF (no more records). */
529 static gboolean
530 collate(pppdump_t* state, FILE_T fh, int *err, gchar **err_info, guint8 *pd,
531                 int *num_bytes, direction_enum *direction, pkt_id *pid,
532                 gint64 num_bytes_to_skip)
533 {
534         int             id;
535         pkt_t           *pkt = NULL;
536         int             byte0, byte1;
537         int             n, num_written = 0;
538         long            start_offset;
539         guint32         time_long;
540         guint8          time_short;
541
542         /*
543          * Process any data left over in the current record when doing
544          * sequential processing.
545          */
546         if (state->num_bytes > 0) {
547                 g_assert(num_bytes_to_skip == 0);
548                 pkt = state->pkt;
549                 num_written = process_data(state, fh, pkt, state->num_bytes,
550                     pd, err, pid);
551
552                 if (num_written < 0) {
553                         return FALSE;
554                 }
555                 else if (num_written > 0) {
556                         *num_bytes = num_written;
557                         *direction = pkt->dir;
558                         return TRUE;
559                 }
560                 /* if 0 bytes written, keep processing */
561         } else {
562                 /*
563                  * We didn't have any data left over, so the packet will
564                  * start at the beginning of a record.
565                  */
566                 if (pid)
567                         pid->num_bytes_to_skip = 0;
568         }
569
570         /*
571          * That didn't get all the data for this packet, so process
572          * subsequent records.
573          */
574         start_offset = state->offset;
575         while ((id = file_getc(fh)) != EOF) {
576                 state->offset++;
577                 switch (id) {
578                         case PPPD_SENT_DATA:
579                         case PPPD_RECV_DATA:
580                                 pkt = id == PPPD_SENT_DATA ? &state->spkt : &state->rpkt;
581
582                                 /*
583                                  * Save the offset of the beginning of
584                                  * the current record.
585                                  */
586                                 pkt->cd_offset = state->offset - 1;
587
588                                 /*
589                                  * Get the length of the record.
590                                  */
591                                 byte0 = file_getc(fh);
592                                 if (byte0 == EOF)
593                                         goto done;
594                                 state->offset++;
595                                 byte1 = file_getc(fh);
596                                 if (byte1 == EOF)
597                                         goto done;
598                                 state->offset++;
599                                 n = (byte0 << 8) | byte1;
600
601                                 if (pkt->id_offset == 0) {
602                                         /*
603                                          * We don't have the initial data
604                                          * offset for this packet, which
605                                          * means this is the first
606                                          * data record for that packet.
607                                          * Save the offset of the
608                                          * beginning of that record and
609                                          * the offset of the first data
610                                          * byte in the packet, which is
611                                          * the first data byte in the
612                                          * record.
613                                          */
614                                         pkt->id_offset = pkt->cd_offset;
615                                         pkt->sd_offset = state->offset;
616                                 }
617
618                                 if (n == 0)
619                                         continue;
620
621                                 g_assert(num_bytes_to_skip < n);
622                                 while (num_bytes_to_skip) {
623                                         if (file_getc(fh) == EOF)
624                                                 goto done;
625                                         state->offset++;
626                                         num_bytes_to_skip--;
627                                         n--;
628                                 }
629                                 num_written = process_data(state, fh, pkt, n,
630                                     pd, err, pid);
631
632                                 if (num_written < 0) {
633                                         return FALSE;
634                                 }
635                                 else if (num_written > 0) {
636                                         *num_bytes = num_written;
637                                         *direction = pkt->dir;
638                                         return TRUE;
639                                 }
640                                 /* if 0 bytes written, keep looping */
641                                 break;
642
643                         case PPPD_SEND_DELIM:
644                         case PPPD_RECV_DELIM:
645                                 /* What can we do? */
646                                 break;
647
648                         case PPPD_RESET_TIME:
649                                 wtap_file_read_unknown_bytes(&time_long, sizeof(guint32), fh, err);
650                                 state->offset += sizeof(guint32);
651                                 state->timestamp = pntohl(&time_long);
652                                 state->tenths = 0;
653                                 break;
654
655                         case PPPD_TIME_STEP_LONG:
656                                 wtap_file_read_unknown_bytes(&time_long, sizeof(guint32), fh, err);
657                                 state->offset += sizeof(guint32);
658                                 state->tenths += pntohl(&time_long);
659
660                                 if (state->tenths >= 10) {
661                                         state->timestamp += state->tenths / 10;
662                                         state->tenths = state->tenths % 10;
663                                 }
664
665                                 break;
666
667                         case PPPD_TIME_STEP_SHORT:
668                                 wtap_file_read_unknown_bytes(&time_short, sizeof(guint8), fh, err);
669                                 state->offset += sizeof(guint8);
670                                 state->tenths += time_short;
671
672                                 if (state->tenths >= 10) {
673                                         state->timestamp += state->tenths / 10;
674                                         state->tenths = state->tenths % 10;
675                                 }
676
677                                 break;
678
679                         default:
680                                 /* XXX - bad file */
681                                 *err = WTAP_ERR_BAD_RECORD;
682                                 *err_info = g_strdup_printf("pppdump: bad ID byte 0x%02x", id);
683                                 return FALSE;
684                 }
685
686         }
687
688 done:
689         *err = file_error(fh);
690         if (*err == 0) {
691                 if (state->offset != start_offset) {
692                         /*
693                          * We read at least one byte, so we were working
694                          * on a record; an EOF means that record was
695                          * cut short.
696                          */
697                         *err = WTAP_ERR_SHORT_READ;
698                 }
699         }
700         return FALSE;
701 }
702
703
704
705 /* Used to read packets in random-access fashion */
706 static gboolean
707 pppdump_seek_read(wtap *wth,
708                  gint64 seek_off,
709                  union wtap_pseudo_header *pseudo_header,
710                  guint8 *pd,
711                  int len,
712                  int *err,
713                  gchar **err_info)
714 {
715         int             num_bytes;
716         direction_enum  direction;
717         pppdump_t       *state;
718         pkt_id          *pid;
719         gint64          num_bytes_to_skip;
720
721         state = wth->capture.generic;
722
723         pid = g_ptr_array_index(state->pids, seek_off);
724         if (!pid) {
725                 *err = WTAP_ERR_BAD_RECORD;     /* XXX - better error? */
726                 *err_info = g_strdup("pppdump: PID not found for record");
727                 return FALSE;
728         }
729
730         if (file_seek(wth->random_fh, pid->offset, SEEK_SET, err) == -1)
731                 return FALSE;
732
733         init_state(state->seek_state);
734         state->seek_state->offset = pid->offset;
735
736         /*
737          * We'll start reading at the first record containing data from
738          * this packet; however, that doesn't mean "collate()" will
739          * stop only when we've read that packet, as there might be
740          * data for packets going in the other direction as well, and
741          * we might finish processing one of those packets before we
742          * finish processing the packet we're reading.
743          *
744          * Therefore, we keep reading until we get a packet that's
745          * going in the direction we want.
746          */
747         num_bytes_to_skip = pid->num_bytes_to_skip;
748         do {
749                 if (!collate(state->seek_state, wth->random_fh, err, err_info,
750                     pd, &num_bytes, &direction, NULL, num_bytes_to_skip))
751                         return FALSE;
752                 num_bytes_to_skip = 0;
753         } while (direction != pid->dir);
754
755         if (len != num_bytes) {
756                 *err = WTAP_ERR_BAD_RECORD;     /* XXX - better error? */
757                 *err_info = g_strdup_printf("pppdump: requested length %d doesn't match record length %d",
758                     len, num_bytes);
759                 return FALSE;
760         }
761
762         pseudo_header->p2p.sent = (pid->dir == DIRECTION_SENT ? TRUE : FALSE);
763
764         return TRUE;
765 }
766
767 static void
768 pppdump_close(wtap *wth)
769 {
770         pppdump_t       *state;
771
772         state = wth->capture.generic;
773
774         if (state->seek_state) { /* should always be TRUE */
775                 g_free(state->seek_state);
776         }
777
778         if (state->pids) {
779                 unsigned int i;
780                 for (i = 0; i < g_ptr_array_len(state->pids); i++) {
781                         g_free(g_ptr_array_index(state->pids, i));
782                 }
783                 g_ptr_array_free(state->pids, TRUE);
784         }
785
786         g_free(state);
787
788 }