File Coverage

blib/lib/File/PCAP/Reader.pm
Criterion Covered Total %
statement 58 70 82.8
branch 13 24 54.1
condition 3 9 33.3
subroutine 13 13 100.0
pod 4 4 100.0
total 91 120 75.8


line stmt bran cond sub pod time code
1             package File::PCAP::Reader;
2              
3 2     2   90798 use 5.006;
  2         25  
4 2     2   17 use strict;
  2         7  
  2         76  
5 2     2   11 use warnings;
  2         5  
  2         74  
6              
7 2     2   11 use Carp;
  2         3  
  2         137  
8 2     2   807 use File::PCAP;
  2         6  
  2         77  
9              
10             =head1 NAME
11              
12             File::PCAP::Reader - read PCAP files with pure Perl
13              
14             =head1 VERSION
15              
16             Version v0.0.7
17              
18             =cut
19              
20 2     2   12 use version; our $VERSION = qv('v0.0.7');
  2         4  
  2         8  
21              
22              
23             =head1 SYNOPSIS
24              
25             This module reads PCAP files that are written with tcpdump.
26              
27             use File::PCAP::Reader;
28              
29             my $fpr = File::PCAP::Reader->new( $fname );
30              
31             my $gh = $fpr->global_header();
32              
33             my $tsec = $fpr->next_packet();
34              
35             =head1 SUBROUTINES/METHODS
36              
37             =head2 new( $fname )
38              
39             Open a PCAP file and read it's global header.
40              
41             =cut
42              
43             sub new {
44 2     2 1 791 my ($self,$fname) = @_;
45 2   33     15 my $type = ref($self) || $self;
46              
47 2         42 $self = bless {
48             fname => $fname,
49             }, $type;
50              
51 2         12 $self->_init();
52              
53 2         8 return $self;
54             } # new()
55              
56             =head2 global_header()
57              
58             Return a reference to a hash that contains the data of the global header of
59             the PCAP file.
60              
61             This hash contains the following keys:
62              
63             =over 4
64              
65             =item magic_number
66              
67             The magic number 0xa1b2c3d4 or 0xa1b23c4d for nanosecond-resolution files.
68              
69             At the moment this version of the library does not handle files from
70             architectures with a different byte ordering.
71              
72             =item version_major
73              
74             The major version number.
75              
76             =item version_minor
77              
78             The minor version number.
79              
80             =item thiszone
81              
82             The GMT to local time correction.
83              
84             =item sigfigs
85              
86             The accuracy of the timestamps in the file.
87              
88             =item snaplen
89              
90             The maximum length of the captured packets in octets.
91              
92             =item network
93              
94             The data link type of the packets in this file.
95              
96             =back
97              
98             =cut
99              
100             sub global_header {
101 1     1 1 8 my $self = shift;
102 1         3 return $self->{global_header};
103             } # global_header()
104              
105             =head2 link_layer_header_type()
106              
107             Returns either the link type name of the global header field I or its numerical value.
108              
109             =cut
110              
111             sub link_layer_header_type {
112 1     1 1 3069 my $self = shift;
113 1         5 my $llht = $self->{global_header}->{network};
114 1 50       7 if ( defined $File::PCAP::linktypes->{$llht} ) {
115 1         7 return $File::PCAP::linktypes->{$llht}->[1];
116             }
117             else {
118 0         0 return $llht;
119             }
120             } # link_layer_header_type()
121              
122             =head2 next_packet()
123              
124             Read the next datagram record in the PCAP file.
125              
126             Returns a hash reference containing the data of the next packet
127             or nothing at the end of the PCAP file.
128              
129             This hash contains the following keys
130              
131             =over 4
132              
133             =item I<< ts_sec >>
134              
135             The date and time when this packet was captured.
136             This value is in seconds since January 1, 1970 00:00:00 GMT.
137              
138             =item I<< ts_usec >>
139              
140             The microseconds when this packet was captured as an offset to I<< ts_sec >>.
141              
142             =item I<< incl_len >>
143              
144             The number of octets of packet data saved in the file.
145              
146             =item I<< orig_len >>
147              
148             The length of the packet as it appeared on the network when it was captured.
149              
150             =item I<< buf >>
151              
152             The actual packet data as a blob.
153             This buffer should contain at least I<< inc_len >> bytes.
154              
155             =back
156              
157             You may want to use it like this:
158              
159             while(my $np = $fpr->next_packet()) {
160             # ... do something with $np
161             }
162              
163             =cut
164              
165             sub next_packet {
166 8     8 1 453 my ($self) = @_;
167 8         13 my $fh = $self->{fh};
168 8         11 my $record;
169 8         44 my $rr = read($fh, $record, 16);
170 8 50       38 if (not defined $rr) {
    100          
171 0         0 croak "Can't read packet data from file '$!'";
172             }
173             elsif (16 > $rr) {
174 2 50       8 if ($rr) {
175 0         0 carp "Reached EOF before reading packet header!";
176             }
177 2         10 return;
178             }
179 6         35 my ($ts_sec,$ts_usec,$incl_len,$orig_len) = unpack("LLLL",$record);
180 6         16 my $buf;
181 6         23 $rr = read($fh, $buf, $incl_len);
182 6 50       23 if (not defined $rr) {
183 0         0 croak "Can't read packet data from file '$!'";
184             }
185 6 50       29 if ($incl_len > $rr) {
186 0         0 carp "Reached EOF before reading packet buffer!";
187 0         0 return;
188             }
189             return {
190 6         47 ts_sec => $ts_sec,
191             ts_usec => $ts_usec,
192             incl_len => $incl_len,
193             orig_len => $orig_len,
194             buf => $buf,
195             }
196             } # next_packet()
197              
198             # internal functions
199              
200             # _init() - initialize the object
201             #
202             sub _init {
203 2     2   5 my ($self) = @_;
204              
205 2         23 my $fname = $self->{fname};
206 2 50       30 if ($fname) {
207 2 50       98 if (open(my $fh, '<', $fname)) {
208 2         9 $self->{fh} = $fh;
209 2         9 $self->_read_pcap_global_header();
210             }
211             else {
212 0         0 croak "Can't open file '$fname' for reading";
213             }
214             }
215             else {
216 0         0 croak "Need a filename to read PCAP data from";
217             }
218             } # _init()
219              
220             sub DESTROY {
221 2     2   1876 my $self = shift;
222              
223 2 50       63 close($self->{fh}) if ($self->{fh});
224 2         183 delete $self->{fh};
225             } # DESTROY()
226              
227             # _read_pcap_global_header() - reads a PCAP global header from the file
228             # named in $self->{fname}
229             #
230             # This function reads a global header with PCAP version 2.4.
231             #
232             sub _read_pcap_global_header {
233 2     2   6 my ($self) = @_;
234 2         5 my $fh = $self->{fh};
235 2         4 my $data;
236 2 50       54 unless (24 == read($fh, $data, 24)) {
237 0         0 croak "Couldn't read global header of PCAP file";
238             }
239 2         29 my ($magic,$vmajor,$vminor,$tzone,$sigfigs,$snaplen,$dlt) = unpack("LSSlLLL",$data);
240              
241 2 50 33     16 if (0xa1b2c3d4 == $magic || 0xa1b23c4d == $magic) {
242 2 50 33     29 if (2 != $vmajor or 4 != $vminor) {
243 0         0 croak "Can't handle file version $vmajor.$vminor"
244             }
245             $self->{global_header} = {
246 2         36 magic_number => $magic,
247             version_major => $vmajor,
248             version_minor => $vminor,
249             thiszone => $tzone,
250             sigfigs => $sigfigs,
251             snaplen => $snaplen,
252             network => $dlt,
253             };
254             }
255             else {
256 0           my $hex = sprintf("%x", $magic);
257 0           croak "Don't know how to handle file with magic number 0x$hex";
258             }
259             } # _read_pcap_global_header()
260              
261             =head1 DIAGNOSTICS
262              
263             =over 4
264              
265             =item Need a filename to read PCAP data from
266              
267             You need to specify a filename with the constructor.
268              
269             =item Can't open file '$fname' for reading
270              
271             The file you specified with C<< $fname >> is not readable.
272              
273             =item Don't know how to handle file with magic number 0xaabbccdd
274              
275             The magic number in the first 4 bytes of a PCAP file is 0xa1b2c3d4.
276             This number is used to detect the file format itself and the byte ordering.
277              
278             At the moment this module just handles PCAP files with the same byte order as the computer this program is running on.
279              
280             =item Can't handle file version $vmajor.$vminor
281              
282             At the moment this module just handles PCAP file version 2.4.
283              
284             =item Can't read packet data from file '$!'
285              
286             There was a problem reading the packet data from the file.
287              
288             =item Reached EOF before reading packet header!
289              
290             The file reached EOF while trying to read the last packet header.
291              
292             This may be a hint to a shortened file.
293              
294             =item Reached EOF before reading packet buffer!
295              
296             The file reached EOF while trying to read the last packet buffer.
297              
298             This may be a hint to a shortened file.
299              
300             =back
301              
302             =head1 AUTHOR
303              
304             Mathias Weidner, C<< >>
305              
306             =head1 BUGS
307              
308             Please report any bugs or feature requests to C, or through
309             the web interface at L. I will be notified, and then you'll
310             automatically be notified of progress on your bug as I make changes.
311              
312              
313              
314              
315             =head1 SUPPORT
316              
317             You can find documentation for this module with the perldoc command.
318              
319             perldoc File::PCAP::Reader
320              
321              
322             You can also look for information at:
323              
324             =over 4
325              
326             =item * RT: CPAN's request tracker (report bugs here)
327              
328             L
329              
330             =item * AnnoCPAN: Annotated CPAN documentation
331              
332             L
333              
334             =item * CPAN Ratings
335              
336             L
337              
338             =item * Search CPAN
339              
340             L
341              
342             =back
343              
344              
345             =head1 ACKNOWLEDGEMENTS
346              
347              
348             =head1 LICENSE AND COPYRIGHT
349              
350             Copyright 2017 Mathias Weidner.
351              
352             This program is free software; you can redistribute it and/or modify it
353             under the terms of the the Artistic License (2.0). You may obtain a
354             copy of the full license at:
355              
356             L
357              
358             Any use, modification, and distribution of the Standard or Modified
359             Versions is governed by this Artistic License. By using, modifying or
360             distributing the Package, you accept this license. Do not use, modify,
361             or distribute the Package, if you do not accept this license.
362              
363             If your Modified Version has been derived from a Modified Version made
364             by someone other than you, you are nevertheless required to ensure that
365             your Modified Version complies with the requirements of this license.
366              
367             This license does not grant you the right to use any trademark, service
368             mark, tradename, or logo of the Copyright Holder.
369              
370             This license includes the non-exclusive, worldwide, free-of-charge
371             patent license to make, have made, use, offer to sell, sell, import and
372             otherwise transfer the Package with respect to any patent claims
373             licensable by the Copyright Holder that are necessarily infringed by the
374             Package. If you institute patent litigation (including a cross-claim or
375             counterclaim) against any party alleging that the Package constitutes
376             direct or contributory patent infringement, then this Artistic License
377             to you shall terminate on the date that such litigation is filed.
378              
379             Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
380             AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
381             THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
382             PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
383             YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR
384             CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
385             CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
386             EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
387              
388              
389             =cut
390              
391             # vim: set sw=4 ts=4 et:
392             1; # End of File::PCAP::Reader