File Coverage

blib/lib/Net/Analysis/Packet.pm
Criterion Covered Total %
statement 71 71 100.0
branch 12 22 54.5
condition 2 4 50.0
subroutine 15 15 100.0
pod 2 5 40.0
total 102 117 87.1


line stmt bran cond sub pod time code
1             package Net::Analysis::Packet;
2              
3 2     2   1941 use 5.008000;
  2         8  
  2         121  
4             our $VERSION = '0.03';
5 2     2   14 use strict;
  2         5  
  2         78  
6 2     2   11 use warnings;
  2         15  
  2         66  
7 2     2   11 use Carp qw(carp cluck);
  2         4  
  2         153  
8 2     2   2205 use POSIX qw(strftime);
  2         18405  
  2         16  
9              
10             # {{{ Exported boilerplate
11              
12             require Exporter;
13              
14             our @ISA = qw(Exporter);
15              
16             our @PKT_SLOT_CONSTS = qw(PKT_SLOT_TO
17             PKT_SLOT_FROM
18             PKT_SLOT_FLAGS
19             PKT_SLOT_DATA
20             PKT_SLOT_SEQNUM
21             PKT_SLOT_ACKNUM
22             PKT_SLOT_PKT_NUMBER
23             PKT_SLOT_TV_SEC
24             PKT_SLOT_TV_USEC
25             PKT_SLOT_SOCKETPAIR_KEY
26             PKT_SLOT_CLASS
27             );
28              
29             our @PKT_FUNCTIONS = qw(pkt_time pkt_init pkt_as_string pkt_class);
30              
31             our @EXPORT = ();
32             our @EXPORT_OK = (@PKT_SLOT_CONSTS, @PKT_FUNCTIONS);
33             our %EXPORT_TAGS = (all => [ @EXPORT, @EXPORT_OK ],
34             pktslots => [ @PKT_SLOT_CONSTS ],
35             func => [ @PKT_FUNCTIONS],
36             );
37              
38             # }}}
39              
40 2     2   3900 use Net::Analysis::Constants qw(:tcpflags :packetclasses);
  2         6  
  2         392  
41 2     2   1292 use Net::Analysis::Time;
  2         5  
  2         65  
42              
43 2     2   15 use Data::Dumper;
  2         21  
  2         159  
44              
45             use constant {
46 2         2803 PKT_SLOT_TO => 0,
47             PKT_SLOT_FROM => 1,
48             PKT_SLOT_FLAGS => 2,
49             PKT_SLOT_DATA => 3,
50             PKT_SLOT_SEQNUM => 4,
51             PKT_SLOT_ACKNUM => 5,
52             PKT_SLOT_PKT_NUMBER => 6,
53             PKT_SLOT_TV_SEC => 7,
54             PKT_SLOT_TV_USEC => 8,
55             PKT_SLOT_TIME => 9,
56             PKT_SLOT_SOCKETPAIR_KEY => 10,
57             PKT_SLOT_CLASS => 11,
58 2     2   11 };
  2         4  
59              
60             #### Public methods
61             #
62             # {{{ pkt_time
63              
64             sub pkt_time {
65 3     3 1 4 my $pkt = shift;
66 3         6 return $pkt->[PKT_SLOT_TIME];
67             }
68              
69             # }}}
70             # {{{ pkt_init
71              
72             sub pkt_init {
73 1     1 1 21 my $pkt = shift;
74 1         3 $pkt->[PKT_SLOT_CLASS] = PKT_NOCLASS;
75 1         9 $pkt->[PKT_SLOT_SOCKETPAIR_KEY] = join('-', sort
76             ($pkt->[PKT_SLOT_FROM],
77             $pkt->[PKT_SLOT_TO]));
78              
79 1         13 $pkt->[PKT_SLOT_TIME] = Net::Analysis::Time->new
80             ($pkt->[PKT_SLOT_TV_SEC], $pkt->[PKT_SLOT_TV_USEC]);
81              
82 1         5 return $pkt;
83             }
84              
85             # }}}
86             # {{{ pkt_class
87              
88             sub pkt_class {
89 1     1 0 3 my ($self, $new) = @_;
90              
91 1 50       5 $self->[PKT_SLOT_CLASS] = $new if (defined $new);
92              
93 1         4 return $self->[PKT_SLOT_CLASS];
94             }
95              
96             # }}}
97             # {{{ pkt_as_string
98              
99             sub pkt_as_string {
100 3     3 0 756 my ($self, $v) = @_;
101              
102             #cluck ("I was invoked :(");
103             #exit;
104              
105 3 50       8 carp "bad pkt !\n" if (!exists $self->[PKT_SLOT_PKT_NUMBER]);
106              
107 3         6 my $flags = '';
108 3 50       10 $flags .= 'F' if ($self->[PKT_SLOT_FLAGS] & FIN);
109 3 50       8 $flags .= 'S' if ($self->[PKT_SLOT_FLAGS] & SYN);
110 3 50       9 $flags .= 'A' if ($self->[PKT_SLOT_FLAGS] & ACK);
111 3 50       8 $flags .= 'R' if ($self->[PKT_SLOT_FLAGS] & RST);
112 3 50       8 $flags .= 'P' if ($self->[PKT_SLOT_FLAGS] & PSH);
113 3 50       7 $flags .= 'U' if ($self->[PKT_SLOT_FLAGS] & URG);
114 3 50       8 $flags .= '.' if ($flags eq '');
115              
116 3         7 my $p_time = pkt_time($self);
117              
118 3 50       147 my $time = ($p_time) ? $p_time->as_string('time') : "--";
119              
120 3         15 my $str = sprintf ("(% 3d $time %s-%s) ",
121             $self->[PKT_SLOT_PKT_NUMBER],
122             $self->[PKT_SLOT_FROM],
123             $self->[PKT_SLOT_TO]);
124              
125             # Show which class we have assigned to the packet
126 3   50     22 $str .= {PKT_NOCLASS, '-',
127             PKT_NONDATA, '_',
128             PKT_DATA, '*',
129             PKT_DUP_DATA, 'p',
130             PKT_FUTURE_DATA, 'f'}->{$self->[PKT_SLOT_CLASS]} || '?';
131              
132 3         11 $str .= sprintf ("%-6s ", "$flags");
133              
134 3         11 $str .= "SEQ:".$self->[PKT_SLOT_SEQNUM]." ACK:".$self->[PKT_SLOT_ACKNUM].
135             " ".length($self->[PKT_SLOT_DATA])."b";
136              
137 3 100       8 if ($v) { # Get all verbose
138 1         5 $str .= "\n"._hex_dump ($self->[PKT_SLOT_DATA]);
139             }
140              
141 3         15 return $str;
142             }
143              
144             # }}}
145              
146             #### Private helpers
147             #
148             # {{{ _hex_dump
149              
150             sub _hex_dump {
151 1     1   2 my ($binary, $prefix) = @_;
152              
153 1   50     7 $prefix ||= '';
154 1         6 my $hex = $prefix.unpack("H*", $binary);
155              
156 1         27 $hex =~ s {([0-9a-f]{2}(?! ))} { $1}mg;
157              
158 1         7 $hex =~ s {(( [0-9a-f]{2}){16})}
159 1         5 {"$1 ".safe_raw_line($1)."\n"}emg;
160              
161             # Unfinished last line
162 1         41 $hex =~ s {(( [0-9a-f]{2})*)$}
163 1         5 {sprintf("%-47.47s ",$1) .safe_raw_line($1)."\n"}es;
164              
165 1         3 chomp($hex);
166 1         5 return $hex."\n";
167             }
168              
169             sub safe_raw_line {
170 2     2 0 5 my ($s) = @_;
171 2         20 $s =~ s {\s+} {}mg;
172              
173 2         9 my $raw = pack("H*", $s);
174 2         4 $raw =~ s {([^\x20-\x7e])} {.}g;
175 2         9 return "{$raw}";
176             }
177              
178             # }}}
179              
180             1;
181             __END__