File Coverage

blib/lib/Net/Frame/Layer/ARP.pm
Criterion Covered Total %
statement 73 86 84.8
branch 7 22 31.8
condition 0 9 0.0
subroutine 19 23 82.6
pod 9 9 100.0
total 108 149 72.4


line stmt bran cond sub pod time code
1             #
2             # $Id: ARP.pm,v 7609c9d085d3 2018/03/15 15:17:19 gomor $
3             #
4             package Net::Frame::Layer::ARP;
5 2     2   5917 use strict;
  2         9  
  2         56  
6 2     2   10 use warnings;
  2         4  
  2         59  
7              
8 2     2   428 use Net::Frame::Layer qw(:consts :subs);
  2         5  
  2         546  
9             require Exporter;
10             our @ISA = qw(Net::Frame::Layer Exporter);
11              
12             our %EXPORT_TAGS = (
13             consts => [qw(
14             NF_ARP_HDR_LEN
15             NF_ARP_HTYPE_ETH
16             NF_ARP_PTYPE_IPv4
17             NF_ARP_PTYPE_IPv6
18             NF_ARP_HSIZE_ETH
19             NF_ARP_PSIZE_IPv4
20             NF_ARP_PSIZE_IPv6
21             NF_ARP_OPCODE_REQUEST
22             NF_ARP_OPCODE_REPLY
23             NF_ARP_ADDR_BROADCAST
24             )],
25             );
26             our @EXPORT_OK = (
27             @{$EXPORT_TAGS{consts}},
28             );
29              
30 2     2   19 use constant NF_ARP_HDR_LEN => 28;
  2         5  
  2         167  
31 2     2   15 use constant NF_ARP_HTYPE_ETH => 0x0001;
  2         5  
  2         159  
32 2     2   18 use constant NF_ARP_PTYPE_IPv4 => 0x0800;
  2         5  
  2         107  
33 2     2   14 use constant NF_ARP_PTYPE_IPv6 => 0x86dd;
  2         5  
  2         105  
34 2     2   14 use constant NF_ARP_HSIZE_ETH => 0x06;
  2         5  
  2         110  
35 2     2   14 use constant NF_ARP_PSIZE_IPv4 => 0x04;
  2         5  
  2         124  
36 2     2   15 use constant NF_ARP_PSIZE_IPv6 => 0x16;
  2         15  
  2         124  
37 2     2   16 use constant NF_ARP_OPCODE_REQUEST => 0x0001;
  2         5  
  2         136  
38 2     2   16 use constant NF_ARP_OPCODE_REPLY => 0x0002;
  2         5  
  2         113  
39 2     2   14 use constant NF_ARP_ADDR_BROADCAST => '00:00:00:00:00:00';
  2         5  
  2         235  
40              
41             our @AS = qw(
42             hType
43             pType
44             hSize
45             pSize
46             opCode
47             src
48             srcIp
49             dst
50             dstIp
51             );
52             __PACKAGE__->cgBuildIndices;
53             __PACKAGE__->cgBuildAccessorsScalar(\@AS);
54              
55 2     2   18 no strict 'vars';
  2         5  
  2         2476  
56              
57             sub new {
58 1     1 1 23 my $self = shift->SUPER::new(
59             hType => NF_ARP_HTYPE_ETH,
60             pType => NF_ARP_PTYPE_IPv4,
61             hSize => NF_ARP_HSIZE_ETH,
62             pSize => NF_ARP_PSIZE_IPv4,
63             opCode => NF_ARP_OPCODE_REQUEST,
64             src => '00:00:00:00:00:00',
65             dst => NF_ARP_ADDR_BROADCAST,
66             srcIp => '127.0.0.1',
67             dstIp => '127.0.0.1',
68             @_,
69             );
70              
71 1 50       380 $self->[$__src] = lc($self->[$__src]) if $self->[$__src];
72 1 50       4 $self->[$__dst] = lc($self->[$__dst]) if $self->[$__dst];
73              
74 1         3 return $self;
75             }
76              
77             sub getLength {
78 0     0 1 0 my $self = shift;
79 0         0 my $len = NF_ARP_HDR_LEN;
80 0 0       0 $len += 24 if $self->[$__pType] == NF_ARP_PTYPE_IPv6;
81 0         0 return $len;
82             }
83              
84             sub pack {
85 1     1 1 5 my $self = shift;
86              
87 1         6 (my $srcMac = $self->[$__src]) =~ s/://g;
88 1         5 (my $dstMac = $self->[$__dst]) =~ s/://g;
89              
90             # IPv4 packing
91 1 50       5 if ($self->[$__pType] == NF_ARP_PTYPE_IPv4) {
92 1 50       5 $self->[$__raw] = $self->SUPER::pack('nnCCnH12a4H12a4',
93             $self->[$__hType],
94             $self->[$__pType],
95             $self->[$__hSize],
96             $self->[$__pSize],
97             $self->[$__opCode],
98             $srcMac,
99             inetAton($self->[$__srcIp]),
100             $dstMac,
101             inetAton($self->[$__dstIp]),
102             ) or return;
103             }
104             # IPv6 packing
105             else {
106 0 0       0 $self->[$__raw] = $self->SUPER::pack('nnCCnH12a*H12a*',
107             $self->[$__hType],
108             $self->[$__pType],
109             $self->[$__hSize],
110             $self->[$__pSize],
111             $self->[$__opCode],
112             $srcMac,
113             inet6Aton($self->[$__srcIp]),
114             $dstMac,
115             inet6Aton($self->[$__dstIp]),
116             ) or return;
117             }
118              
119 1         3 return $self->[$__raw];
120             }
121              
122             sub unpack {
123 1     1 1 5 my $self = shift;
124              
125 1 50       7 my ($hType, $pType, $tail) = $self->SUPER::unpack('nn a*',
126             $self->[$__raw])
127             or return;
128              
129 1         27 my ($hSize, $pSize, $opCode, $srcMac, $srcIp, $dstMac, $dstIp,
130             $payload);
131              
132             # IPv4 unpacking
133 1 50       8 if ($pType == NF_ARP_PTYPE_IPv4) {
134 1 50       5 ($hSize, $pSize, $opCode, $srcMac, $srcIp, $dstMac, $dstIp,
135             $payload) = $self->SUPER::unpack('CCnH12a4H12a4 a*', $tail)
136             or return;
137 1         5 $self->[$__srcIp] = inetNtoa($srcIp);
138 1         11 $self->[$__dstIp] = inetNtoa($dstIp);
139             }
140             # IPv6 unpacking
141             else {
142 0 0       0 ($hSize, $pSize, $opCode, $srcMac, $srcIp, $dstMac, $dstIp,
143             $payload) = $self->SUPER::unpack('CCnH12a16H12a16 a*', $tail)
144             or return;
145 0         0 $self->[$__srcIp] = inet6Ntoa($srcIp);
146 0         0 $self->[$__dstIp] = inet6Ntoa($dstIp);
147             }
148              
149 1         3 $self->[$__hType] = $hType;
150 1         2 $self->[$__pType] = $pType;
151 1         2 $self->[$__hSize] = $hSize;
152 1         1 $self->[$__pSize] = $pSize;
153 1         3 $self->[$__opCode] = $opCode;
154 1         3 $self->[$__src] = convertMac($srcMac);
155 1         4 $self->[$__dst] = convertMac($dstMac);
156              
157 1         2 $self->[$__payload] = $payload;
158              
159 1         3 return $self;
160             }
161              
162 0     0 1 0 sub getKey { shift->layer }
163 0     0 1 0 sub getKeyReverse { shift->layer }
164              
165             sub match {
166 0     0 1 0 my $self = shift;
167 0         0 my ($with) = @_;
168 0 0 0     0 ($self->[$__opCode] == NF_ARP_OPCODE_REQUEST)
      0        
      0        
169             && ($with->[$__opCode] == NF_ARP_OPCODE_REPLY)
170             && ($with->[$__dst] eq $self->[$__src])
171             && ($with->[$__srcIp] eq $self->[$__dstIp])
172             && ($with->[$__dstIp] eq $self->[$__srcIp]);
173             }
174              
175             sub encapsulate {
176 1     1 1 8 my $self = shift;
177 1         3 return $self->[$__nextLayer];
178             }
179              
180             sub print {
181 1     1 1 5 my $self = shift;
182              
183 1         8 my $l = $self->layer;
184 1         48 sprintf
185             "$l: hType:0x%04x pType:0x%04x hSize:0x%02x pSize:0x%02x".
186             " opCode:0x%04x\n".
187             "$l: src:%s srcIp:%s\n".
188             "$l: dst:%s dstIp:%s",
189             $self->[$__hType], $self->[$__pType], $self->[$__hSize],
190             $self->[$__pSize], $self->[$__opCode], $self->[$__src],
191             $self->[$__srcIp], $self->[$__dst], $self->[$__dstIp];
192             }
193              
194             1;
195              
196             __END__