File Coverage

blib/lib/Net/Frame/Layer/ICMPv4.pm
Criterion Covered Total %
statement 137 170 80.5
branch 4 34 11.7
condition 0 26 0.0
subroutine 44 49 89.8
pod 10 10 100.0
total 195 289 67.4


line stmt bran cond sub pod time code
1             #
2             # $Id: ICMPv4.pm 56 2015-01-20 18:55:33Z gomor $
3             #
4             package Net::Frame::Layer::ICMPv4;
5 2     2   9586 use strict; use warnings;
  2     2   5  
  2         92  
  2         12  
  2         7  
  2         111  
6              
7             our $VERSION = '1.05';
8              
9 2     2   1280 use Net::Frame::Layer qw(:consts :subs);
  2         114659  
  2         582  
10 2     2   20 use Exporter;
  2         3  
  2         211  
11             our @ISA = qw(Net::Frame::Layer Exporter);
12              
13             our %EXPORT_TAGS = (
14             consts => [qw(
15             NF_ICMPv4_HDR_LEN
16             NF_ICMPv4_CODE_ZERO
17             NF_ICMPv4_TYPE_DESTUNREACH
18             NF_ICMPv4_CODE_NETWORK
19             NF_ICMPv4_CODE_HOST
20             NF_ICMPv4_CODE_PROTOCOL
21             NF_ICMPv4_CODE_PORT
22             NF_ICMPv4_CODE_FRAGMENTATION_NEEDED
23             NF_ICMPv4_CODE_SOURCE_ROUTE_FAILED
24             NF_ICMPv4_TYPE_TIMEEXCEED
25             NF_ICMPv4_CODE_TTL_IN_TRANSIT
26             NF_ICMPv4_CODE_FRAGMENT_REASSEMBLY
27             NF_ICMPv4_TYPE_PARAMETERPROBLEM
28             NF_ICMPv4_CODE_POINTER
29             NF_ICMPv4_TYPE_SOURCEQUENCH
30             NF_ICMPv4_TYPE_REDIRECT
31             NF_ICMPv4_CODE_FOR_NETWORK
32             NF_ICMPv4_CODE_FOR_HOST
33             NF_ICMPv4_CODE_FOR_TOS_AND_NETWORK
34             NF_ICMPv4_CODE_FOR_TOS_AND_HOST
35             NF_ICMPv4_TYPE_ECHO_REQUEST
36             NF_ICMPv4_TYPE_ECHO_REPLY
37             NF_ICMPv4_TYPE_TIMESTAMP_REQUEST
38             NF_ICMPv4_TYPE_TIMESTAMP_REPLY
39             NF_ICMPv4_TYPE_INFORMATION_REQUEST
40             NF_ICMPv4_TYPE_INFORMATION_REPLY
41             NF_ICMPv4_TYPE_ADDRESS_MASK_REQUEST
42             NF_ICMPv4_TYPE_ADDRESS_MASK_REPLY
43             )],
44             );
45             our @EXPORT_OK = (
46             @{$EXPORT_TAGS{consts}},
47             );
48              
49 2     2   11 use constant NF_ICMPv4_HDR_LEN => 8;
  2         2  
  2         116  
50 2     2   8 use constant NF_ICMPv4_CODE_ZERO => 0;
  2         2  
  2         69  
51 2     2   7 use constant NF_ICMPv4_TYPE_DESTUNREACH => 3;
  2         3  
  2         68  
52 2     2   8 use constant NF_ICMPv4_CODE_NETWORK => 0;
  2         2  
  2         67  
53 2     2   7 use constant NF_ICMPv4_CODE_HOST => 1;
  2         4  
  2         62  
54 2     2   15 use constant NF_ICMPv4_CODE_PROTOCOL => 2;
  2         2  
  2         80  
55 2     2   7 use constant NF_ICMPv4_CODE_PORT => 3;
  2         2  
  2         77  
56 2     2   9 use constant NF_ICMPv4_CODE_FRAGMENTATION_NEEDED => 4;
  2         2  
  2         73  
57 2     2   7 use constant NF_ICMPv4_CODE_SOURCE_ROUTE_FAILED => 5;
  2         3  
  2         92  
58 2     2   24 use constant NF_ICMPv4_TYPE_TIMEEXCEED => 11;
  2         4  
  2         97  
59 2     2   9 use constant NF_ICMPv4_CODE_TTL_IN_TRANSIT => 0;
  2         3  
  2         99  
60 2     2   11 use constant NF_ICMPv4_CODE_FRAGMENT_REASSEMBLY => 1;
  2         3  
  2         105  
61 2     2   10 use constant NF_ICMPv4_TYPE_PARAMETERPROBLEM => 12;
  2         3  
  2         94  
62 2     2   10 use constant NF_ICMPv4_CODE_POINTER => 0;
  2         2  
  2         81  
63 2     2   8 use constant NF_ICMPv4_TYPE_SOURCEQUENCH => 4;
  2         2  
  2         74  
64 2     2   7 use constant NF_ICMPv4_TYPE_REDIRECT => 5;
  2         2  
  2         82  
65 2     2   9 use constant NF_ICMPv4_CODE_FOR_NETWORK => 0;
  2         2  
  2         74  
66 2     2   7 use constant NF_ICMPv4_CODE_FOR_HOST => 1;
  2         6  
  2         66  
67 2     2   7 use constant NF_ICMPv4_CODE_FOR_TOS_AND_NETWORK => 2;
  2         2  
  2         65  
68 2     2   7 use constant NF_ICMPv4_CODE_FOR_TOS_AND_HOST => 3;
  2         3  
  2         68  
69 2     2   7 use constant NF_ICMPv4_TYPE_ECHO_REQUEST => 8;
  2         2  
  2         65  
70 2     2   7 use constant NF_ICMPv4_TYPE_ECHO_REPLY => 0;
  2         2  
  2         72  
71 2     2   13 use constant NF_ICMPv4_TYPE_TIMESTAMP_REQUEST => 13;
  2         2  
  2         68  
72 2     2   7 use constant NF_ICMPv4_TYPE_TIMESTAMP_REPLY => 14;
  2         2  
  2         69  
73 2     2   8 use constant NF_ICMPv4_TYPE_INFORMATION_REQUEST => 15;
  2         2  
  2         66  
74 2     2   8 use constant NF_ICMPv4_TYPE_INFORMATION_REPLY => 16;
  2         2  
  2         94  
75 2     2   9 use constant NF_ICMPv4_TYPE_ADDRESS_MASK_REQUEST => 17; # RFC 950
  2         22  
  2         88  
76 2     2   11 use constant NF_ICMPv4_TYPE_ADDRESS_MASK_REPLY => 18; # RFC 950
  2         2  
  2         210  
77              
78             our @AS = qw(
79             type
80             code
81             checksum
82             );
83             __PACKAGE__->cgBuildIndices;
84             __PACKAGE__->cgBuildAccessorsScalar(\@AS);
85              
86 2     2   1192 use Net::Frame::Layer::ICMPv4::AddressMask;
  2         4  
  2         92  
87 2     2   937 use Net::Frame::Layer::ICMPv4::DestUnreach;
  2         4  
  2         85  
88 2     2   831 use Net::Frame::Layer::ICMPv4::Echo;
  2         5  
  2         82  
89 2     2   852 use Net::Frame::Layer::ICMPv4::Information;
  2         5  
  2         127  
90 2     2   912 use Net::Frame::Layer::ICMPv4::Redirect;
  2         4  
  2         95  
91 2     2   765 use Net::Frame::Layer::ICMPv4::TimeExceed;
  2         5  
  2         81  
92 2     2   744 use Net::Frame::Layer::ICMPv4::Timestamp;
  2         3  
  2         1457  
93              
94             sub new {
95 1     1 1 21 my $self = shift->SUPER::new(
96             type => NF_ICMPv4_TYPE_ECHO_REQUEST,
97             code => NF_ICMPv4_CODE_ZERO,
98             checksum => 0,
99             @_,
100             );
101              
102 1         277 return $self;
103             }
104              
105             sub match {
106 0     0 1 0 my $self = shift;
107 0         0 my ($with) = @_;
108 0         0 my $sType = $self->type;
109 0         0 my $wType = $with->type;
110 0 0 0     0 if ($sType eq NF_ICMPv4_TYPE_ECHO_REQUEST
    0 0        
    0 0        
    0 0        
111             && $wType eq NF_ICMPv4_TYPE_ECHO_REPLY) {
112 0         0 return 1;
113             }
114             elsif ($sType eq NF_ICMPv4_TYPE_TIMESTAMP_REQUEST
115             && $wType eq NF_ICMPv4_TYPE_TIMESTAMP_REPLY) {
116 0         0 return 1;
117             }
118             elsif ($sType eq NF_ICMPv4_TYPE_INFORMATION_REQUEST
119             && $wType eq NF_ICMPv4_TYPE_INFORMATION_REPLY) {
120 0         0 return 1;
121             }
122             elsif ($sType eq NF_ICMPv4_TYPE_ADDRESS_MASK_REQUEST
123             && $wType eq NF_ICMPv4_TYPE_ADDRESS_MASK_REPLY) {
124 0         0 return 1;
125             }
126 0         0 0;
127             }
128              
129             # XXX: may be better, by keying on type also
130 0     0 1 0 sub getKey { shift->layer }
131 0     0 1 0 sub getKeyReverse { shift->layer }
132              
133 0     0 1 0 sub getLength { 4 }
134              
135             sub pack {
136 1     1 1 5 my $self = shift;
137              
138 1 50       4 my $raw = $self->SUPER::pack('CCn',
139             $self->type, $self->code, $self->checksum,
140             ) or return;
141              
142 1         57 return $self->raw($raw);
143             }
144              
145             sub unpack {
146 1     1 1 11 my $self = shift;
147              
148 1 50       3 my ($type, $code, $checksum, $payload) =
149             $self->SUPER::unpack('CCn a*', $self->raw)
150             or return;
151              
152 1         33 $self->type($type);
153 1         14 $self->code($code);
154 1         12 $self->checksum($checksum);
155              
156 1         17 $self->payload($payload);
157              
158 1         11 return $self;
159             }
160              
161             sub computeChecksums {
162 0     0 1 0 my $self = shift;
163 0         0 my ($layers) = @_;
164              
165 0         0 my $icmpType;
166 0         0 for my $l (@$layers) {
167 0 0       0 if ($l->layer =~ /ICMPv4::/) { $icmpType = $l; last; }
  0         0  
  0         0  
168             }
169              
170 0 0       0 my $packed = $self->SUPER::pack('CCna*',
171             $self->type, $self->code, 0, $icmpType->pack,
172             ) or return;
173              
174 0   0     0 my $payload = $layers->[-1]->payload || '';
175 0         0 $self->checksum(inetChecksum($packed.$payload));
176              
177 0         0 return 1;
178             }
179              
180             sub encapsulate {
181 1     1 1 7 my $self = shift;
182              
183 1 50       7 return $self->nextLayer if $self->nextLayer;
184              
185 1 50       17 if ($self->payload) {
186 0         0 my $type = $self->type;
187 0 0 0     0 if ($type eq NF_ICMPv4_TYPE_ECHO_REQUEST
    0 0        
    0 0        
    0 0        
    0          
    0          
    0          
188             || $type eq NF_ICMPv4_TYPE_ECHO_REPLY) {
189 0         0 return 'ICMPv4::Echo';
190             }
191             elsif ($type eq NF_ICMPv4_TYPE_TIMESTAMP_REQUEST
192             || $type eq NF_ICMPv4_TYPE_TIMESTAMP_REPLY) {
193 0         0 return 'ICMPv4::Timestamp';
194             }
195             elsif ($type eq NF_ICMPv4_TYPE_INFORMATION_REQUEST
196             || $type eq NF_ICMPv4_TYPE_INFORMATION_REPLY) {
197 0         0 return 'ICMPv4::Information';
198             }
199             elsif ($type eq NF_ICMPv4_TYPE_ADDRESS_MASK_REQUEST
200             || $type eq NF_ICMPv4_TYPE_ADDRESS_MASK_REPLY) {
201 0         0 return 'ICMPv4::AddressMask';
202             }
203             elsif ($type eq NF_ICMPv4_TYPE_DESTUNREACH) {
204 0         0 return 'ICMPv4::DestUnreach';
205             }
206             elsif ($type eq NF_ICMPv4_TYPE_REDIRECT) {
207 0         0 return 'ICMPv4::Redirect';
208             }
209             elsif ($type eq NF_ICMPv4_TYPE_TIMEEXCEED) {
210 0         0 return 'ICMPv4::TimeExceed';
211             }
212             }
213              
214 1         9 return NF_LAYER_NONE;
215             }
216              
217             sub print {
218 1     1 1 5 my $self = shift;
219              
220 1         6 my $l = $self->layer;
221 1         12 my $buf = sprintf "$l: type:%d code:%d checksum:0x%04x",
222             $self->type, $self->code, $self->checksum;
223              
224 1         350 return $buf;
225             }
226              
227             1;
228              
229             __END__