File Coverage

blib/lib/Net/Frame/Layer/ETH.pm
Criterion Covered Total %
statement 129 144 89.5
branch 7 22 31.8
condition 1 3 33.3
subroutine 40 42 95.2
pod 7 7 100.0
total 184 218 84.4


line stmt bran cond sub pod time code
1             #
2             # $Id: ETH.pm,v 7609c9d085d3 2018/03/15 15:17:19 gomor $
3             #
4             package Net::Frame::Layer::ETH;
5 2     2   6543 use strict;
  2         13  
  2         70  
6 2     2   14 use warnings;
  2         5  
  2         76  
7              
8 2     2   491 use Net::Frame::Layer qw(:consts :subs);
  2         8  
  2         707  
9             require Exporter;
10             our @ISA = qw(Net::Frame::Layer Exporter);
11              
12             our %EXPORT_TAGS = (
13             consts => [qw(
14             NF_ETH_HDR_LEN
15             NF_ETH_ADDR_BROADCAST
16             NF_ETH_TYPE_IPv4
17             NF_ETH_TYPE_X25
18             NF_ETH_TYPE_ARP
19             NF_ETH_TYPE_CGMP
20             NF_ETH_TYPE_80211
21             NF_ETH_TYPE_PPPIPCP
22             NF_ETH_TYPE_RARP
23             NF_ETH_TYPE_DDP
24             NF_ETH_TYPE_AARP
25             NF_ETH_TYPE_PPPCCP
26             NF_ETH_TYPE_WCP
27             NF_ETH_TYPE_8021Q
28             NF_ETH_TYPE_IPX
29             NF_ETH_TYPE_STP
30             NF_ETH_TYPE_IPv6
31             NF_ETH_TYPE_WLCCP
32             NF_ETH_TYPE_MPLS
33             NF_ETH_TYPE_PPPoED
34             NF_ETH_TYPE_PPPoES
35             NF_ETH_TYPE_8021X
36             NF_ETH_TYPE_AoE
37             NF_ETH_TYPE_80211I
38             NF_ETH_TYPE_LLDP
39             NF_ETH_TYPE_LLTD
40             NF_ETH_TYPE_LOOP
41             NF_ETH_TYPE_VLAN
42             NF_ETH_TYPE_PPPPAP
43             NF_ETH_TYPE_PPPCHAP
44             )],
45             );
46             our @EXPORT_OK = (
47             @{$EXPORT_TAGS{consts}},
48             );
49              
50 2     2   21 use constant NF_ETH_HDR_LEN => 14;
  2         6  
  2         144  
51 2     2   15 use constant NF_ETH_ADDR_BROADCAST => 'ff:ff:ff:ff:ff:ff';
  2         5  
  2         140  
52 2     2   18 use constant NF_ETH_TYPE_IPv4 => 0x0800;
  2         6  
  2         129  
53 2     2   16 use constant NF_ETH_TYPE_X25 => 0x0805;
  2         5  
  2         117  
54 2     2   14 use constant NF_ETH_TYPE_ARP => 0x0806;
  2         5  
  2         113  
55 2     2   14 use constant NF_ETH_TYPE_CGMP => 0x2001;
  2         5  
  2         135  
56 2     2   16 use constant NF_ETH_TYPE_80211 => 0x2452;
  2         5  
  2         129  
57 2     2   15 use constant NF_ETH_TYPE_PPPIPCP => 0x8021;
  2         4  
  2         113  
58 2     2   14 use constant NF_ETH_TYPE_RARP => 0x8035;
  2         6  
  2         110  
59 2     2   13 use constant NF_ETH_TYPE_DDP => 0x809b;
  2         5  
  2         112  
60 2     2   14 use constant NF_ETH_TYPE_AARP => 0x80f3;
  2         6  
  2         125  
61 2     2   15 use constant NF_ETH_TYPE_PPPCCP => 0x80fd;
  2         5  
  2         120  
62 2     2   15 use constant NF_ETH_TYPE_WCP => 0x80ff;
  2         4  
  2         160  
63 2     2   16 use constant NF_ETH_TYPE_8021Q => 0x8100;
  2         4  
  2         121  
64 2     2   14 use constant NF_ETH_TYPE_IPX => 0x8137;
  2         6  
  2         126  
65 2     2   16 use constant NF_ETH_TYPE_STP => 0x8181;
  2         6  
  2         110  
66 2     2   18 use constant NF_ETH_TYPE_IPv6 => 0x86dd;
  2         6  
  2         130  
67 2     2   16 use constant NF_ETH_TYPE_WLCCP => 0x872d;
  2         5  
  2         123  
68 2     2   25 use constant NF_ETH_TYPE_MPLS => 0x8847;
  2         6  
  2         129  
69 2     2   15 use constant NF_ETH_TYPE_PPPoED => 0x8863;
  2         5  
  2         140  
70 2     2   16 use constant NF_ETH_TYPE_PPPoES => 0x8864;
  2         6  
  2         125  
71 2     2   18 use constant NF_ETH_TYPE_8021X => 0x888e;
  2         5  
  2         107  
72 2     2   23 use constant NF_ETH_TYPE_AoE => 0x88a2;
  2         6  
  2         117  
73 2     2   15 use constant NF_ETH_TYPE_80211I => 0x88c7;
  2         5  
  2         109  
74 2     2   12 use constant NF_ETH_TYPE_LLDP => 0x88cc;
  2         5  
  2         120  
75 2     2   16 use constant NF_ETH_TYPE_LLTD => 0x88d9;
  2         35  
  2         121  
76 2     2   15 use constant NF_ETH_TYPE_LOOP => 0x9000;
  2         5  
  2         138  
77 2     2   16 use constant NF_ETH_TYPE_VLAN => 0x9100;
  2         6  
  2         132  
78 2     2   14 use constant NF_ETH_TYPE_PPPPAP => 0xc023;
  2         5  
  2         129  
79 2     2   16 use constant NF_ETH_TYPE_PPPCHAP => 0xc223;
  2         4  
  2         257  
80              
81             our @AS = qw(
82             dst
83             src
84             type
85             );
86             __PACKAGE__->cgBuildIndices;
87             __PACKAGE__->cgBuildAccessorsScalar(\@AS);
88              
89             BEGIN {
90 2     2   74 *length = \&type;
91             }
92              
93 2     2   17 no strict 'vars';
  2         4  
  2         2369  
94              
95             sub new {
96 1     1 1 20 my $self = shift->SUPER::new(
97             src => '00:00:00:00:00:00',
98             dst => NF_ETH_ADDR_BROADCAST,
99             type => NF_ETH_TYPE_IPv4,
100             @_,
101             );
102              
103 1 50       293 $self->[$__src] = lc($self->[$__src]) if $self->[$__src];
104 1 50       5 $self->[$__dst] = lc($self->[$__dst]) if $self->[$__dst];
105              
106 1         3 $self;
107             }
108              
109 0     0 1 0 sub getLength { NF_ETH_HDR_LEN }
110              
111             sub pack {
112 1     1 1 5 my $self = shift;
113              
114 1         6 (my $dst = $self->[$__dst]) =~ s/://g;
115 1         5 (my $src = $self->[$__src]) =~ s/://g;
116              
117 1 50       10 $self->[$__raw] = $self->SUPER::pack('H12H12n', $dst, $src, $self->[$__type])
118             or return undef;
119              
120 1         6 $self->[$__raw];
121             }
122              
123             sub unpack {
124 1     1 1 8 my $self = shift;
125              
126 1 50       10 my ($dst, $src, $type, $payload) =
127             $self->SUPER::unpack('H12H12n a*', $self->[$__raw])
128             or return undef;
129              
130 1         5 $self->[$__dst] = convertMac($dst);
131 1         4 $self->[$__src] = convertMac($src);
132              
133 1         3 $self->[$__type] = $type;
134 1         3 $self->[$__payload] = $payload;
135              
136 1         2 $self;
137             }
138              
139             sub computeLengths {
140 0     0 1 0 my $self = shift;
141 0         0 my ($layers) = @_;
142 0 0       0 if ($self->[$__type] <= 1500) {
143 0         0 my $len = 0;
144 0         0 for my $l (@$layers) {
145 0 0       0 next if $l->layer eq 'ETH';
146             # We do not use getLength(), because the layer may
147             # have a fake length, due to fuzzing or stress
148             # testing attempts from the user
149 0         0 $len += CORE::length($l->pack),
150             }
151 0         0 $self->type($len);
152             }
153 0         0 return 1;
154             }
155              
156             our $Next = {
157             NF_ETH_TYPE_IPv4() => 'IPv4',
158             NF_ETH_TYPE_X25() => 'X25',
159             NF_ETH_TYPE_ARP() => 'ARP',
160             NF_ETH_TYPE_CGMP() => 'CGMP',
161             NF_ETH_TYPE_80211() => '80211',
162             NF_ETH_TYPE_PPPIPCP() => 'PPPIPCP',
163             NF_ETH_TYPE_RARP() => 'RARP',
164             NF_ETH_TYPE_DDP () => 'DDP',
165             NF_ETH_TYPE_AARP() => 'AARP',
166             NF_ETH_TYPE_PPPCCP() => 'PPPCCP',
167             NF_ETH_TYPE_WCP() => 'WCP',
168             NF_ETH_TYPE_8021Q() => '8021Q',
169             NF_ETH_TYPE_IPX() => 'IPX',
170             NF_ETH_TYPE_STP() => 'STP',
171             NF_ETH_TYPE_IPv6() => 'IPv6',
172             NF_ETH_TYPE_WLCCP() => 'WLCCP',
173             NF_ETH_TYPE_MPLS() => 'MPLS',
174             NF_ETH_TYPE_PPPoED() => 'PPPoED',
175             NF_ETH_TYPE_PPPoES() => 'PPPoES',
176             NF_ETH_TYPE_8021X() => '8021X',
177             NF_ETH_TYPE_AoE() => 'AoE',
178             NF_ETH_TYPE_80211I() => '80211I',
179             NF_ETH_TYPE_LLDP() => 'LLDP',
180             NF_ETH_TYPE_LLTD() => 'LLTD',
181             NF_ETH_TYPE_LOOP() => 'LOOP',
182             NF_ETH_TYPE_VLAN() => 'VLAN',
183             NF_ETH_TYPE_PPPPAP() => 'PPPPAP',
184             NF_ETH_TYPE_PPPCHAP() => 'PPPCHAP',
185             };
186              
187             sub encapsulate {
188 1     1 1 13 my $self = shift;
189              
190 1 50       8 return $self->[$__nextLayer] if $self->[$__nextLayer];
191              
192             # Is this a 802.3 layer ?
193 1 0 33     6 if ($self->[$__type] <= 1500 && $self->[$__payload]) {
194 0         0 my $payload = CORE::unpack('H*', $self->[$__payload]);
195             # We consider this is a LLC layer if the payload is more than 6 bytes long
196 0 0       0 if (CORE::length($payload) > 6) {
197 0         0 return 'LLC';
198             }
199 0         0 return NF_LAYER_UNKNOWN;
200             }
201              
202 1 50       11 $Next->{$self->[$__type]} || NF_LAYER_UNKNOWN;
203             }
204              
205             sub print {
206 1     1 1 5 my $self = shift;
207              
208 1         6 my $l = $self->layer;
209 1         7 my $buf = sprintf "$l: dst:%s src:%s ", $self->[$__dst], $self->[$__src];
210              
211 1 50       4 if ($self->[$__type] <= 1500) {
212 0         0 $buf .= sprintf "length:%d", $self->[$__type];
213             }
214             else {
215 1         5 $buf .= sprintf "type:0x%04x", $self->[$__type];
216             }
217              
218 1         48 $buf;
219             }
220              
221             1;
222              
223             __END__