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