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 53 2012-01-31 20:27:06Z gomor $
3             #
4             package Net::Frame::Layer::ICMPv4;
5 2     2   17818 use strict; use warnings;
  2     2   5  
  2         75  
  2         10  
  2         3  
  2         109  
6              
7             our $VERSION = '1.04';
8              
9 2     2   1826 use Net::Frame::Layer qw(:consts :subs);
  2         234271  
  2         627  
10 2     2   23 use Exporter;
  2         5  
  2         269  
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   13 use constant NF_ICMPv4_HDR_LEN => 8;
  2         4  
  2         129  
50 2     2   10 use constant NF_ICMPv4_CODE_ZERO => 0;
  2         3  
  2         87  
51 2     2   10 use constant NF_ICMPv4_TYPE_DESTUNREACH => 3;
  2         3  
  2         130  
52 2     2   11 use constant NF_ICMPv4_CODE_NETWORK => 0;
  2         4  
  2         101  
53 2     2   10 use constant NF_ICMPv4_CODE_HOST => 1;
  2         3  
  2         140  
54 2     2   21 use constant NF_ICMPv4_CODE_PROTOCOL => 2;
  2         5  
  2         109  
55 2     2   11 use constant NF_ICMPv4_CODE_PORT => 3;
  2         4  
  2         96  
56 2     2   10 use constant NF_ICMPv4_CODE_FRAGMENTATION_NEEDED => 4;
  2         3  
  2         115  
57 2     2   24 use constant NF_ICMPv4_CODE_SOURCE_ROUTE_FAILED => 5;
  2         4  
  2         106  
58 2     2   21 use constant NF_ICMPv4_TYPE_TIMEEXCEED => 11;
  2         4  
  2         143  
59 2     2   11 use constant NF_ICMPv4_CODE_TTL_IN_TRANSIT => 0;
  2         4  
  2         105  
60 2     2   10 use constant NF_ICMPv4_CODE_FRAGMENT_REASSEMBLY => 1;
  2         3  
  2         110  
61 2     2   12 use constant NF_ICMPv4_TYPE_PARAMETERPROBLEM => 12;
  2         3  
  2         95  
62 2     2   9 use constant NF_ICMPv4_CODE_POINTER => 0;
  2         4  
  2         97  
63 2     2   11 use constant NF_ICMPv4_TYPE_SOURCEQUENCH => 4;
  2         10  
  2         93  
64 2     2   9 use constant NF_ICMPv4_TYPE_REDIRECT => 5;
  2         12  
  2         133  
65 2     2   10 use constant NF_ICMPv4_CODE_FOR_NETWORK => 0;
  2         2  
  2         188  
66 2     2   12 use constant NF_ICMPv4_CODE_FOR_HOST => 1;
  2         4  
  2         108  
67 2     2   56 use constant NF_ICMPv4_CODE_FOR_TOS_AND_NETWORK => 2;
  2         3  
  2         112  
68 2     2   11 use constant NF_ICMPv4_CODE_FOR_TOS_AND_HOST => 3;
  2         4  
  2         102  
69 2     2   10 use constant NF_ICMPv4_TYPE_ECHO_REQUEST => 8;
  2         3  
  2         95  
70 2     2   10 use constant NF_ICMPv4_TYPE_ECHO_REPLY => 0;
  2         4  
  2         109  
71 2     2   10 use constant NF_ICMPv4_TYPE_TIMESTAMP_REQUEST => 13;
  2         4  
  2         1350  
72 2     2   16 use constant NF_ICMPv4_TYPE_TIMESTAMP_REPLY => 14;
  2         4  
  2         126  
73 2     2   13 use constant NF_ICMPv4_TYPE_INFORMATION_REQUEST => 15;
  2         4  
  2         102  
74 2     2   11 use constant NF_ICMPv4_TYPE_INFORMATION_REPLY => 16;
  2         4  
  2         134  
75 2     2   10 use constant NF_ICMPv4_TYPE_ADDRESS_MASK_REQUEST => 17; # RFC 950
  2         23  
  2         112  
76 2     2   11 use constant NF_ICMPv4_TYPE_ADDRESS_MASK_REPLY => 18; # RFC 950
  2         2  
  2         241  
77              
78             our @AS = qw(
79             type
80             code
81             checksum
82             );
83             __PACKAGE__->cgBuildIndices;
84             __PACKAGE__->cgBuildAccessorsScalar(\@AS);
85              
86 2     2   1935 use Net::Frame::Layer::ICMPv4::AddressMask;
  2         5  
  2         100  
87 2     2   1594 use Net::Frame::Layer::ICMPv4::DestUnreach;
  2         55  
  2         106  
88 2     2   1517 use Net::Frame::Layer::ICMPv4::Echo;
  2         7  
  2         103  
89 2     2   1466 use Net::Frame::Layer::ICMPv4::Information;
  2         7  
  2         111  
90 2     2   1719 use Net::Frame::Layer::ICMPv4::Redirect;
  2         6  
  2         139  
91 2     2   1266 use Net::Frame::Layer::ICMPv4::TimeExceed;
  2         4  
  2         93  
92 2     2   1541 use Net::Frame::Layer::ICMPv4::Timestamp;
  2         7  
  2         2173  
93              
94             sub new {
95 1     1 1 26 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         297 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 7 my $self = shift;
137              
138 1 50       6 my $raw = $self->SUPER::pack('CCn',
139             $self->type, $self->code, $self->checksum,
140             ) or return;
141              
142 1         498 return $self->raw($raw);
143             }
144              
145             sub unpack {
146 1     1 1 30 my $self = shift;
147              
148 1 50       4 my ($type, $code, $checksum, $payload) =
149             $self->SUPER::unpack('CCn a*', $self->raw)
150             or return;
151              
152 1         103 $self->type($type);
153 1         14 $self->code($code);
154 1         12 $self->checksum($checksum);
155              
156 1         15 $self->payload($payload);
157              
158 1         43 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 17 my $self = shift;
182              
183 1 50       8 return $self->nextLayer if $self->nextLayer;
184              
185 1 50       19 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         13 return NF_LAYER_NONE;
215             }
216              
217             sub print {
218 1     1 1 7 my $self = shift;
219              
220 1         8 my $l = $self->layer;
221 1         20 my $buf = sprintf "$l: type:%d code:%d checksum:0x%04x",
222             $self->type, $self->code, $self->checksum;
223              
224 1         74 return $buf;
225             }
226              
227             1;
228              
229             __END__