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