File Coverage

blib/lib/File/PCAP/Reader.pm
Criterion Covered Total %
statement 59 71 83.1
branch 13 24 54.1
condition 3 9 33.3
subroutine 13 13 100.0
pod 4 4 100.0
total 92 121 76.0


line stmt bran cond sub pod time code
1             package File::PCAP::Reader;
2              
3 3     3   67404 use 5.006;
  3         19  
4 3     3   19 use strict;
  3         17  
  3         88  
5 3     3   20 use warnings;
  3         4  
  3         95  
6              
7 3     3   17 use Carp;
  3         5  
  3         175  
8 3     3   1200 use File::PCAP;
  3         6  
  3         91  
9              
10             =head1 NAME
11              
12             File::PCAP::Reader - read PCAP files with pure Perl
13              
14             =head1 VERSION
15              
16             Version v0.1.0
17              
18             =cut
19              
20 3     3   17 use version; our $VERSION = qv('v0.1.0');
  3         7  
  3         12  
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 3     3 1 1264 my ($self,$fname) = @_;
45 3   33     31 my $type = ref($self) || $self;
46              
47 3         58 $self = bless {
48             fname => $fname,
49             }, $type;
50              
51 3         23 $self->_init();
52              
53 3         14 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 7 my $self = shift;
102 1         4 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 2202 my $self = shift;
113 1         4 my $llht = $self->{global_header}->{network};
114 1 50       6 if ( defined $File::PCAP::linktypes->{$llht} ) {
115 1         5 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 9     9 1 356 my ($self) = @_;
167 9         17 my $fh = $self->{fh};
168 9         13 my $record;
169 9         49 my $rr = read($fh, $record, 16);
170 9 50       39 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         8 return;
178             }
179 7         42 my ($ts_sec,$ts_usec,$incl_len,$orig_len) = unpack("LLLL",$record);
180 7         16 my $buf;
181 7         25 $rr = read($fh, $buf, $incl_len);
182 7 50       26 if (not defined $rr) {
183 0         0 croak "Can't read packet data from file '$!'";
184             }
185 7 50       32 if ($incl_len > $rr) {
186 0         0 carp "Reached EOF before reading packet buffer!";
187 0         0 return;
188             }
189             return {
190 7         52 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 3     3   9 my ($self) = @_;
204              
205 3         19 my $fname = $self->{fname};
206 3 50       10 if ($fname) {
207 3 50       117 if (open(my $fh, '<', $fname)) {
208 3         13 binmode $fh;
209 3         8 $self->{fh} = $fh;
210 3         13 $self->_read_pcap_global_header();
211             }
212             else {
213 0         0 croak "Can't open file '$fname' for reading";
214             }
215             }
216             else {
217 0         0 croak "Need a filename to read PCAP data from";
218             }
219             } # _init()
220              
221             sub DESTROY {
222 3     3   1910 my $self = shift;
223              
224 3 50       100 close($self->{fh}) if ($self->{fh});
225 3         145 delete $self->{fh};
226             } # DESTROY()
227              
228             # _read_pcap_global_header() - reads a PCAP global header from the file
229             # named in $self->{fname}
230             #
231             # This function reads a global header with PCAP version 2.4.
232             #
233             sub _read_pcap_global_header {
234 3     3   10 my ($self) = @_;
235 3         8 my $fh = $self->{fh};
236 3         6 my $data;
237 3 50       73 unless (24 == read($fh, $data, 24)) {
238 0         0 croak "Couldn't read global header of PCAP file";
239             }
240 3         46 my ($magic,$vmajor,$vminor,$tzone,$sigfigs,$snaplen,$dlt) = unpack("LSSlLLL",$data);
241              
242 3 50 33     25 if (0xa1b2c3d4 == $magic || 0xa1b23c4d == $magic) {
243 3 50 33     35 if (2 != $vmajor or 4 != $vminor) {
244 0         0 croak "Can't handle file version $vmajor.$vminor"
245             }
246             $self->{global_header} = {
247 3         68 magic_number => $magic,
248             version_major => $vmajor,
249             version_minor => $vminor,
250             thiszone => $tzone,
251             sigfigs => $sigfigs,
252             snaplen => $snaplen,
253             network => $dlt,
254             };
255             }
256             else {
257 0           my $hex = sprintf("%x", $magic);
258 0           croak "Don't know how to handle file with magic number 0x$hex";
259             }
260             } # _read_pcap_global_header()
261              
262             =head1 DIAGNOSTICS
263              
264             =over 4
265              
266             =item Need a filename to read PCAP data from
267              
268             You need to specify a filename with the constructor.
269              
270             =item Can't open file '$fname' for reading
271              
272             The file you specified with C<< $fname >> is not readable.
273              
274             =item Don't know how to handle file with magic number 0xaabbccdd
275              
276             The magic number in the first 4 bytes of a PCAP file is 0xa1b2c3d4.
277             This number is used to detect the file format itself and the byte ordering.
278              
279             At the moment this module just handles PCAP files with the same byte order as the computer this program is running on.
280              
281             =item Can't handle file version $vmajor.$vminor
282              
283             At the moment this module just handles PCAP file version 2.4.
284              
285             =item Can't read packet data from file '$!'
286              
287             There was a problem reading the packet data from the file.
288              
289             =item Reached EOF before reading packet header!
290              
291             The file reached EOF while trying to read the last packet header.
292              
293             This may be a hint to a shortened file.
294              
295             =item Reached EOF before reading packet buffer!
296              
297             The file reached EOF while trying to read the last packet buffer.
298              
299             This may be a hint to a shortened file.
300              
301             =back
302              
303             =head1 AUTHOR
304              
305             Mathias Weidner, C<< >>
306              
307             =head1 BUGS
308              
309             Please report any bugs or feature requests to C, or through
310             the web interface at L. I will be notified, and then you'll
311             automatically be notified of progress on your bug as I make changes.
312              
313              
314              
315              
316             =head1 SUPPORT
317              
318             You can find documentation for this module with the perldoc command.
319              
320             perldoc File::PCAP::Reader
321              
322              
323             You can also look for information at:
324              
325             =over 4
326              
327             =item * RT: CPAN's request tracker (report bugs here)
328              
329             L
330              
331             =item * AnnoCPAN: Annotated CPAN documentation
332              
333             L
334              
335             =item * CPAN Ratings
336              
337             L
338              
339             =item * Search CPAN
340              
341             L
342              
343             =back
344              
345              
346             =head1 ACKNOWLEDGEMENTS
347              
348              
349             =head1 LICENSE AND COPYRIGHT
350              
351             Copyright 2017 Mathias Weidner.
352              
353             This program is free software; you can redistribute it and/or modify it
354             under the terms of the the Artistic License (2.0). You may obtain a
355             copy of the full license at:
356              
357             L
358              
359             Any use, modification, and distribution of the Standard or Modified
360             Versions is governed by this Artistic License. By using, modifying or
361             distributing the Package, you accept this license. Do not use, modify,
362             or distribute the Package, if you do not accept this license.
363              
364             If your Modified Version has been derived from a Modified Version made
365             by someone other than you, you are nevertheless required to ensure that
366             your Modified Version complies with the requirements of this license.
367              
368             This license does not grant you the right to use any trademark, service
369             mark, tradename, or logo of the Copyright Holder.
370              
371             This license includes the non-exclusive, worldwide, free-of-charge
372             patent license to make, have made, use, offer to sell, sell, import and
373             otherwise transfer the Package with respect to any patent claims
374             licensable by the Copyright Holder that are necessarily infringed by the
375             Package. If you institute patent litigation (including a cross-claim or
376             counterclaim) against any party alleging that the Package constitutes
377             direct or contributory patent infringement, then this Artistic License
378             to you shall terminate on the date that such litigation is filed.
379              
380             Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
381             AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
382             THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
383             PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
384             YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR
385             CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
386             CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
387             EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
388              
389              
390             =cut
391              
392             # vim: set sw=4 ts=4 et:
393             1; # End of File::PCAP::Reader