# # $Id: ETH.pm 347 2012-01-14 08:50:01Z gomor $ # package Net::Frame::Layer::ETH; use strict; use warnings; use Net::Frame::Layer qw(:consts :subs); require Exporter; our @ISA = qw(Net::Frame::Layer Exporter); our %EXPORT_TAGS = ( consts => [qw( NF_ETH_HDR_LEN NF_ETH_ADDR_BROADCAST NF_ETH_TYPE_IPv4 NF_ETH_TYPE_X25 NF_ETH_TYPE_ARP NF_ETH_TYPE_CGMP NF_ETH_TYPE_80211 NF_ETH_TYPE_PPPIPCP NF_ETH_TYPE_RARP NF_ETH_TYPE_DDP NF_ETH_TYPE_AARP NF_ETH_TYPE_PPPCCP NF_ETH_TYPE_WCP NF_ETH_TYPE_8021Q NF_ETH_TYPE_IPX NF_ETH_TYPE_STP NF_ETH_TYPE_IPv6 NF_ETH_TYPE_WLCCP NF_ETH_TYPE_MPLS NF_ETH_TYPE_PPPoED NF_ETH_TYPE_PPPoES NF_ETH_TYPE_8021X NF_ETH_TYPE_AoE NF_ETH_TYPE_80211I NF_ETH_TYPE_LLDP NF_ETH_TYPE_LLTD NF_ETH_TYPE_LOOP NF_ETH_TYPE_VLAN NF_ETH_TYPE_PPPPAP NF_ETH_TYPE_PPPCHAP )], ); our @EXPORT_OK = ( @{$EXPORT_TAGS{consts}}, ); use constant NF_ETH_HDR_LEN => 14; use constant NF_ETH_ADDR_BROADCAST => 'ff:ff:ff:ff:ff:ff'; use constant NF_ETH_TYPE_IPv4 => 0x0800; use constant NF_ETH_TYPE_X25 => 0x0805; use constant NF_ETH_TYPE_ARP => 0x0806; use constant NF_ETH_TYPE_CGMP => 0x2001; use constant NF_ETH_TYPE_80211 => 0x2452; use constant NF_ETH_TYPE_PPPIPCP => 0x8021; use constant NF_ETH_TYPE_RARP => 0x8035; use constant NF_ETH_TYPE_DDP => 0x809b; use constant NF_ETH_TYPE_AARP => 0x80f3; use constant NF_ETH_TYPE_PPPCCP => 0x80fd; use constant NF_ETH_TYPE_WCP => 0x80ff; use constant NF_ETH_TYPE_8021Q => 0x8100; use constant NF_ETH_TYPE_IPX => 0x8137; use constant NF_ETH_TYPE_STP => 0x8181; use constant NF_ETH_TYPE_IPv6 => 0x86dd; use constant NF_ETH_TYPE_WLCCP => 0x872d; use constant NF_ETH_TYPE_MPLS => 0x8847; use constant NF_ETH_TYPE_PPPoED => 0x8863; use constant NF_ETH_TYPE_PPPoES => 0x8864; use constant NF_ETH_TYPE_8021X => 0x888e; use constant NF_ETH_TYPE_AoE => 0x88a2; use constant NF_ETH_TYPE_80211I => 0x88c7; use constant NF_ETH_TYPE_LLDP => 0x88cc; use constant NF_ETH_TYPE_LLTD => 0x88d9; use constant NF_ETH_TYPE_LOOP => 0x9000; use constant NF_ETH_TYPE_VLAN => 0x9100; use constant NF_ETH_TYPE_PPPPAP => 0xc023; use constant NF_ETH_TYPE_PPPCHAP => 0xc223; our @AS = qw( dst src type ); __PACKAGE__->cgBuildIndices; __PACKAGE__->cgBuildAccessorsScalar(\@AS); BEGIN { *length = \&type; } no strict 'vars'; sub new { my $self = shift->SUPER::new( src => '00:00:00:00:00:00', dst => NF_ETH_ADDR_BROADCAST, type => NF_ETH_TYPE_IPv4, @_, ); $self->[$__src] = lc($self->[$__src]) if $self->[$__src]; $self->[$__dst] = lc($self->[$__dst]) if $self->[$__dst]; $self; } sub getLength { NF_ETH_HDR_LEN } sub pack { my $self = shift; (my $dst = $self->[$__dst]) =~ s/://g; (my $src = $self->[$__src]) =~ s/://g; $self->[$__raw] = $self->SUPER::pack('H12H12n', $dst, $src, $self->[$__type]) or return undef; $self->[$__raw]; } sub unpack { my $self = shift; my ($dst, $src, $type, $payload) = $self->SUPER::unpack('H12H12n a*', $self->[$__raw]) or return undef; $self->[$__dst] = convertMac($dst); $self->[$__src] = convertMac($src); $self->[$__type] = $type; $self->[$__payload] = $payload; $self; } sub computeLengths { my $self = shift; my ($layers) = @_; if ($self->[$__type] <= 1500) { my $len = 0; for my $l (@$layers) { next if $l->layer eq 'ETH'; # We do not use getLength(), because the layer may # have a fake length, due to fuzzing or stress # testing attempts from the user $len += CORE::length($l->pack), } $self->type($len); } return 1; } our $Next = { NF_ETH_TYPE_IPv4() => 'IPv4', NF_ETH_TYPE_X25() => 'X25', NF_ETH_TYPE_ARP() => 'ARP', NF_ETH_TYPE_CGMP() => 'CGMP', NF_ETH_TYPE_80211() => '80211', NF_ETH_TYPE_PPPIPCP() => 'PPPIPCP', NF_ETH_TYPE_RARP() => 'RARP', NF_ETH_TYPE_DDP () => 'DDP', NF_ETH_TYPE_AARP() => 'AARP', NF_ETH_TYPE_PPPCCP() => 'PPPCCP', NF_ETH_TYPE_WCP() => 'WCP', NF_ETH_TYPE_8021Q() => '8021Q', NF_ETH_TYPE_IPX() => 'IPX', NF_ETH_TYPE_STP() => 'STP', NF_ETH_TYPE_IPv6() => 'IPv6', NF_ETH_TYPE_WLCCP() => 'WLCCP', NF_ETH_TYPE_MPLS() => 'MPLS', NF_ETH_TYPE_PPPoED() => 'PPPoED', NF_ETH_TYPE_PPPoES() => 'PPPoES', NF_ETH_TYPE_8021X() => '8021X', NF_ETH_TYPE_AoE() => 'AoE', NF_ETH_TYPE_80211I() => '80211I', NF_ETH_TYPE_LLDP() => 'LLDP', NF_ETH_TYPE_LLTD() => 'LLTD', NF_ETH_TYPE_LOOP() => 'LOOP', NF_ETH_TYPE_VLAN() => 'VLAN', NF_ETH_TYPE_PPPPAP() => 'PPPPAP', NF_ETH_TYPE_PPPCHAP() => 'PPPCHAP', }; sub encapsulate { my $self = shift; return $self->[$__nextLayer] if $self->[$__nextLayer]; # Is this a 802.3 layer ? if ($self->[$__type] <= 1500 && $self->[$__payload]) { my $payload = CORE::unpack('H*', $self->[$__payload]); # We consider this is a LLC layer if the payload is more than 6 bytes long if (CORE::length($payload) > 6) { return 'LLC'; } return NF_LAYER_UNKNOWN; } $Next->{$self->[$__type]} || NF_LAYER_UNKNOWN; } sub print { my $self = shift; my $l = $self->layer; my $buf = sprintf "$l: dst:%s src:%s ", $self->[$__dst], $self->[$__src]; if ($self->[$__type] <= 1500) { $buf .= sprintf "length:%d", $self->[$__type]; } else { $buf .= sprintf "type:0x%04x", $self->[$__type]; } $buf; } 1; __END__ =head1 NAME Net::Frame::Layer::ETH - Ethernet/802.3 layer object =head1 SYNOPSIS use Net::Frame::Layer::ETH qw(:consts); # Build a layer my $layer = Net::Frame::Layer::ETH->new( src => '00:00:00:00:00:00', dst => NF_ETH_ADDR_BROADCAST, type => NF_ETH_TYPE_IPv4, ); $layer->pack; print 'RAW: '.$layer->dump."\n"; # Read a raw layer my $layer = Net::Frame::Layer::ETH->new(raw => $raw); print $layer->print."\n"; print 'PAYLOAD: '.unpack('H*', $layer->payload)."\n" if $layer->payload; =head1 DESCRIPTION This modules implements the encoding and decoding of the Ethernet/802.3 layer. RFC: ftp://ftp.rfc-editor.org/in-notes/rfc894.txt See also B for other attributes and methods. =head1 ATTRIBUTES =over 4 =item B =item B Source and destination MAC addresses, in classical format (00:11:22:33:44:55). =item B The encapsulated layer type (IPv4, IPv6 ...) for Ethernet. Values for Ethernet types are greater than 1500. If it is less than 1500 the layer is considered a 802.3 one. See http://www.iana.org/assignments/ethernet-numbers . =item B The length of the payload when this layer is a 802.3 one. This is the same attribute as B, but you cannot use it when calling B (you can only use it as an accessor after that). =back The following are inherited attributes. See B for more information. =over 4 =item B =item B =item B =back =head1 METHODS =over 4 =item B =item B (hash) Object constructor. You can pass attributes that will overwrite default ones. See B for default values. =back The following are inherited methods. Some of them may be overriden in this layer, and some others may not be meaningful in this layer. See B for more information. =over 4 =item B =item B =item B =item B =item B =item B =item B =item B =item B =item B =back =head1 CONSTANTS Load them: use Net::Frame::Layer::ETH qw(:consts); =over 4 =item B Ethernet broadcast address. =item B =item B =item B =item B =item B =item B =item B =item B =item B =item B =item B =item B =item B =item B =item B =item B =item B =item B =item B =item B =item B =item B =item B =item B =item B =item B =item B =item B Various supported Ethernet types. =back =head1 SEE ALSO L =head1 AUTHOR Patrice EGomoRE Auffret =head1 COPYRIGHT AND LICENSE Copyright (c) 2006-2012, Patrice EGomoRE Auffret You may distribute this module under the terms of the Artistic license. See LICENSE.Artistic file in the source distribution archive. =cut