Skip Menu |

This queue is for tickets about the Net-Packet CPAN distribution.

Report information
The Basics
Id: 16013
Status: resolved
Priority: 0/
Queue: Net-Packet

People
Owner: gomor [...] cpan.org
Requestors: michael.s.wagner [...] gmail.com
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in: 2.02
Fixed in: (no value)



Subject: Error in packing 802.11Q VLAN ID
Hello Patrice - I have been using the Net::Packet for sometime now to automate some ping tests through vlans. What I noticed was that whenever I set the VLAN ID to anything greater than 16 Net::Packet would basically do a modulus of that number by 16. So if I set it to 17 the VLAN ID would be 1, 18 it would be 2, and so on. Anyways I dug into the code a little bit and found where it packs this value in VLAN.pm. my $pCfiId3 = packIntToNet($self->id, 'v', 0, 12); Basically what I found through testing is that since packIntToNet receives 'v' it is using a 16 bit network number that gets shifted by 12 bits. So if any information is stored in the upper 12 bits it would get shifted off leaving 4 bits or 2^4 combinations up to 16 valid IDs. Anyways I looked at what packIntToNet was doing and fed it new parameters so that a 32 bit number is used and no data loss occurs. Below is my change. my $pCfiId3 = packIntToNet($self->id, 'N', 8, 12); I have attached a new version of VLAN.pm with this line added plus some test lines after it commented out if you would like to double check and verify yourself the functionality between the two lines. Anyways I hope this is a small useful fix for you. I also have new ICMPv4.pm and ARP.pm modules which will handle packets encapsulated by 802.11q so the ->recv method for each will acknolwedge response to echo requests and arp requests using vlans if you are interested. Thanks for the very useful module! Mike Wagner
package Net::Packet::VLAN; # $Date: 2005/02/03 22:33:50 $ # $Revision: 1.1.2.1 $ use strict; use warnings; require Net::Packet::Layer3; require Class::Gomor::Hash; our @ISA = qw(Net::Packet::Layer3 Class::Gomor::Hash); use Net::Packet qw($Env); use Net::Packet::Consts qw(:vlan :layer); use Net::Packet::Utils qw(packIntToNet unpackIntFromNet); require Net::Packet::Frame; our $VERSION = $Net::Packet::VERSION; our @AS = qw( priority cfi id type frame ); __PACKAGE__->buildAccessorsScalar(\@AS); sub new { my $self = shift->SUPER::new( priority => 0, cfi => 0, id => 0, type => NP_VLAN_TYPE_IPv4, @_, ); $self; } sub getLength { my $self = shift; do { return length($self->frame) + NP_VLAN_HDR_LEN } if $self->frame; NP_VLAN_HDR_LEN; } sub pack { my $self = shift; my $pCfiId1 = packIntToNet($self->priority, 'C', 2, 3); my $pCfiId2 = packIntToNet($self->cfi, 'C', 6, 1); my $pCfiId3 = packIntToNet($self->id, 'N', 8, 12); #my $check = substr(unpack('B*', pack('n', $self->id)), 4); #print "CHECK " . $check . "\n"; #my $c1 = substr(unpack('B*', pack('N', 69632)), 8, 12); #my $c2 = substr(unpack('B*', pack('n', 15)), 4); #my $c3 = substr(unpack('B*', pack('n', 25)), 4); #my $c4 = substr(unpack('B*', pack('n', 35)), 4); #print "HERE " . $c1 . " " . $c2 . " " . $c3 . " " . $c4 . "\n"; #print "$pCfiId1 $pCfiId2 $pCfiId3\n"; $self->raw( $self->SUPER::pack('B16na*', $pCfiId1. $pCfiId2. $pCfiId3, $self->type, $self->frame->raw, ), ) or return undef; 1; } sub unpack { my $self = shift; my ($pCfiId, $type, $payload) = $self->SUPER::unpack('B16n a*', $self->raw) or return undef; # print STDERR $pCfiId, "\n"; $self->priority(unpackIntFromNet($pCfiId, 'C', 0, 5, 3)); $self->cfi (unpackIntFromNet($pCfiId, 'C', 3, 7, 1)); $self->id (unpackIntFromNet($pCfiId, 'n', 4, 4, 12)); $self->type($type); $self->frame(Net::Packet::Frame->new(raw => $payload)); 1; } sub print { my $self = shift; my $l = $self->layer; my $i = $self->is; sprintf "$l:+$i: priority:%d cfi:%d id:%d type:0x%04x", $self->priority, $self->cfi, $self->id, $self->type; } # # Helpers # sub _isType { shift->type == shift() } sub isTypeArp { shift->_isType(NP_VLAN_TYPE_ARP) } sub isTypeIpv4 { shift->_isType(NP_VLAN_TYPE_IPv4) } sub isTypeIpv6 { shift->_isType(NP_VLAN_TYPE_IPv6) } sub isTypeIp { my $self = shift; $self->isIpv4 || $self->isIpv6 } 1; __END__ =head1 NAME Net::Packet::VLAN - 802.1Q layer 3 object =head1 SYNOPSIS use Net::Packet qw($Env); use Net::Packet::VLAN; # Load needed constants use Net::Packet::Consts qw(:ipv4 :eth); # In order to avoid autocreation of Desc and Dump objects # Because VLAN is particuliar, we must do it manually use Net::Packet::DescL2; use Net::Packet::Dump; Net::Packet::DescL2->new; Net::Packet::Dump->new(filter => 'vlan'); # Another thing to note, do not send VLAN frames in a # vlan interface, it would be encapsulated another time ;) # Instead, send it to the parent interface # So, we will play an echo-request inside a vlan use Net::Packet::Frame; use Net::Packet::IPv4; use Net::Packet::ICMPv4; my $echo = Net::Packet::Frame->new( l3 => Net::Packet::IPv4->new( src => $vlanSrcIp, dst => $vlanDstIp, protocol => NP_IPv4_PROTOCOL_ICMPv4, doChecksum => 1, # Because system will not do it, # at least under FreeBSD noFixLen => 1, # Well, FreeBSD needs fixing, but not # when frames are injected into VLANs ;) ), l4 => Net::Packet::ICMPv4->new, ); # Frame to inject is built, time to encapsulate it into a VLAN frame use Net::Packet::ETH; my $frame = Net::Packet::Frame->new( l2 => Net::Packet::ETH->new( dst => $vlanDstMac, type => NP_ETH_TYPE_VLAN, ), l3 => Net::Packet::VLAN->new( frame => $echo, ), ); # Done ! print $frame->l3->print, "\n"; print $frame->l3->frame->l3->print, "\n"; print $frame->l3->frame->l4->print, "\n"; $frame->send; =head1 DESCRIPTION This modules implements the encoding and decoding of the Virtual LAN/802.1Q layer. See also B<Net::Packet::Layer> and B<Net::Packet::Layer3> for other attributes and methods. =head1 ATTRIBUTES =over 4 =item B<priority> The priority field. =item B<cfi> The cfi field. It is only one bit long, so set it to 0 or 1. =item B<id> VLAN tag id. You'll love it. =item B<type> Which type the next encapsulated layer is. =item B<frame> This is a B<Net::Packet::Frame> object, built it like any other such frame. Just to mention that you should use B<doChecksum> attribute if you put in a B<Net::Packet::IPv4> layer, and maybe the B<noFixLen> attribute also. =back =head1 METHODS =over 4 =item B<new> Object constructor. You can pass attributes that will overwrite default ones. Default values: priority: 0 cfi: 0 id: 0 type: NP_VLAN_TYPE_IPv4 =item B<pack> Packs all attributes into a raw format, in order to inject to network. Returns 1 on success, undef otherwise. =item B<unpack> Unpacks raw data from network and stores attributes into the object. Returns 1 on success, undef otherwise. =back =head1 CONSTANTS Load them: use Net::Packet::Consts qw(:vlan); =over 4 =item B<NP_VLAN_TYPE_ARP> =item B<NP_VLAN_TYPE_IPv4> =item B<NP_VLAN_TYPE_IPv6> Various supported encapsulated frame types. =back =head1 AUTHOR Patrice E<lt>GomoRE<gt> Auffret =head1 COPYRIGHT AND LICENSE Copyright (c) 2004-2005, Patrice E<lt>GomoRE<gt> Auffret You may distribute this module under the terms of the Artistic license. See Copying file in the source distribution archive. =head1 RELATED MODULES L<NetPacket>, L<Net::RawIP>, L<Net::RawSock> =cut
This problem is now solved. The bugfix will be included in Net::Packet 2.05. Best regards, and the sorry for the loooonnnnnng delay.