# # $Id: ARP.pm 305 2009-05-23 13:21:05Z gomor $ # package Net::Frame::Layer::ARP; 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_ARP_HDR_LEN NF_ARP_HTYPE_ETH NF_ARP_PTYPE_IPv4 NF_ARP_PTYPE_IPv6 NF_ARP_HSIZE_ETH NF_ARP_PSIZE_IPv4 NF_ARP_PSIZE_IPv6 NF_ARP_OPCODE_REQUEST NF_ARP_OPCODE_REPLY NF_ARP_ADDR_BROADCAST )], ); our @EXPORT_OK = ( @{$EXPORT_TAGS{consts}}, ); use constant NF_ARP_HDR_LEN => 28; use constant NF_ARP_HTYPE_ETH => 0x0001; use constant NF_ARP_PTYPE_IPv4 => 0x0800; use constant NF_ARP_PTYPE_IPv6 => 0x86dd; use constant NF_ARP_HSIZE_ETH => 0x06; use constant NF_ARP_PSIZE_IPv4 => 0x04; use constant NF_ARP_PSIZE_IPv6 => 0x16; use constant NF_ARP_OPCODE_REQUEST => 0x0001; use constant NF_ARP_OPCODE_REPLY => 0x0002; use constant NF_ARP_ADDR_BROADCAST => '00:00:00:00:00:00'; our @AS = qw( hType pType hSize pSize opCode src srcIp dst dstIp ); __PACKAGE__->cgBuildIndices; __PACKAGE__->cgBuildAccessorsScalar(\@AS); no strict 'vars'; sub new { my $self = shift->SUPER::new( hType => NF_ARP_HTYPE_ETH, pType => NF_ARP_PTYPE_IPv4, hSize => NF_ARP_HSIZE_ETH, pSize => NF_ARP_PSIZE_IPv4, opCode => NF_ARP_OPCODE_REQUEST, src => '00:00:00:00:00:00', dst => NF_ARP_ADDR_BROADCAST, srcIp => '127.0.0.1', dstIp => '127.0.0.1', @_, ); $self->[$__src] = lc($self->[$__src]) if $self->[$__src]; $self->[$__dst] = lc($self->[$__dst]) if $self->[$__dst]; $self; } sub getLength { my $self = shift; my $len = NF_ARP_HDR_LEN; $len += 24 if $self->[$__pType] == NF_ARP_PTYPE_IPv6; $len; } sub pack { my $self = shift; (my $srcMac = $self->[$__src]) =~ s/://g; (my $dstMac = $self->[$__dst]) =~ s/://g; # IPv4 packing if ($self->[$__pType] == NF_ARP_PTYPE_IPv4) { $self->[$__raw] = $self->SUPER::pack('nnUUnH12a4H12a4', $self->[$__hType], $self->[$__pType], $self->[$__hSize], $self->[$__pSize], $self->[$__opCode], $srcMac, inetAton($self->[$__srcIp]), $dstMac, inetAton($self->[$__dstIp]), ) or return undef; } # IPv6 packing else { $self->[$__raw] = $self->SUPER::pack('nnUUnH12a*H12a*', $self->[$__hType], $self->[$__pType], $self->[$__hSize], $self->[$__pSize], $self->[$__opCode], $srcMac, inet6Aton($self->[$__srcIp]), $dstMac, inet6Aton($self->[$__dstIp]), ) or return undef; } $self->[$__raw]; } sub unpack { my $self = shift; my ($hType, $pType, $tail) = $self->SUPER::unpack('nn a*', $self->[$__raw]) or return undef; my ($hSize, $pSize, $opCode, $srcMac, $srcIp, $dstMac, $dstIp, $payload); # IPv4 unpacking if ($pType == NF_ARP_PTYPE_IPv4) { ($hSize, $pSize, $opCode, $srcMac, $srcIp, $dstMac, $dstIp, $payload) = $self->SUPER::unpack('UUnH12a4H12a4 a*', $tail) or return undef; $self->[$__srcIp] = inetNtoa($srcIp); $self->[$__dstIp] = inetNtoa($dstIp); } # IPv6 unpacking else { ($hSize, $pSize, $opCode, $srcMac, $srcIp, $dstMac, $dstIp, $payload) = $self->SUPER::unpack('UUnH12a16H12a16 a*', $tail) or return undef; $self->[$__srcIp] = inet6Ntoa($srcIp); $self->[$__dstIp] = inet6Ntoa($dstIp); } $self->[$__hType] = $hType; $self->[$__pType] = $pType; $self->[$__hSize] = $hSize; $self->[$__pSize] = $pSize; $self->[$__opCode] = $opCode; $self->[$__src] = convertMac($srcMac); $self->[$__dst] = convertMac($dstMac); $self->[$__payload] = $payload; $self; } sub getKey { shift->layer } sub getKeyReverse { shift->layer } sub match { my $self = shift; my ($with) = @_; ($self->[$__opCode] == NF_ARP_OPCODE_REQUEST) && ($with->[$__opCode] == NF_ARP_OPCODE_REPLY) && ($with->[$__dst] eq $self->[$__src]) && ($with->[$__srcIp] eq $self->[$__dstIp]) && ($with->[$__dstIp] eq $self->[$__srcIp]); } sub encapsulate { my $self = shift; return $self->[$__nextLayer]; } sub print { my $self = shift; my $l = $self->layer; sprintf "$l: hType:0x%04x pType:0x%04x hSize:0x%02x pSize:0x%02x". " opCode:0x%04x\n". "$l: src:%s srcIp:%s\n". "$l: dst:%s dstIp:%s", $self->[$__hType], $self->[$__pType], $self->[$__hSize], $self->[$__pSize], $self->[$__opCode], $self->[$__src], $self->[$__srcIp], $self->[$__dst], $self->[$__dstIp]; } 1; __END__ =head1 NAME Net::Frame::Layer::ARP - Address Resolution Protocol layer object =head1 SYNOPSIS use Net::Frame::Layer::ARP qw(:consts); # Build a layer my $layer = Net::Frame::Layer::ARP->new( hType => NF_ARP_HTYPE_ETH, pType => NF_ARP_PTYPE_IPv4, hSize => NF_ARP_HSIZE_ETH, pSize => NF_ARP_PSIZE_IPv4, opCode => NF_ARP_OPCODE_REQUEST, src => '00:00:00:00:00:00', dst => NF_ARP_ADDR_BROADCAST, srcIp => '127.0.0.1', dstIp => '127.0.0.1', ); $layer->pack; print 'RAW: '.$layer->dump."\n"; # Read a raw layer my $layer = Net::Frame::Layer::ARP->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 ARP layer. RFC: ftp://ftp.rfc-editor.org/in-notes/rfc826.txt See also B for other attributes and methods. =head1 ATTRIBUTES =over 4 =item B =item B Hardware and protocol address types. =item B =item B Hardware and protocol address sizes in bytes. =item B The operation code number to perform. =item B =item B Source and destination hardware addresses. =item B =item B Source and destination IP addresses. =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. =item B =item B These two methods are basically used to increase the speed when using B method from B. Usually, you write them when you need to write B method. =item B (Net::Frame::Layer::ARP object) This method is mostly used internally. You pass a B layer as a parameter, and it returns true if this is a response corresponding for the request, or returns false if not. =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::ARP qw(:consts); =over 4 =item B Hardware address types. =item B =item B Protocol address types. =item B Hardware address sizes. =item B =item B Protocol address sizes. =item B =item B Operation code numbers. =item B Broadcast address for B or B attributes. =back =head1 SEE ALSO L =head1 AUTHOR Patrice EGomoRE Auffret =head1 COPYRIGHT AND LICENSE Copyright (c) 2006-2009, 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