Skip Menu |

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

Report information
The Basics
Id: 23544
Status: open
Priority: 0/
Queue: Net-DHCP-Packet

People
Owner: Nobody in particular
Requestors: Christof [...] chen.de
Cc:
AdminCc:

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



Subject: unhandled multiple options
Concerning Net::DHCP:Packet 0.66. A packet with two VENDOR_ENCAPSULATED_OPTION fields (e.g. very large PXE options) gets malformed by marshall/serialize. Packet.pm stores the option data in a hash, so only the last data is assigned to every instance of an option during serialize. (In general, the code does not provision for multiple options of the same key). The attached patch works around this problem by storing the data for an option in an array. addOption appends to this array. replaceOption replaces the array. addOptionRaw appends to this array. replaceOptionRaw replaces the array. getOptionValue returns an array of option values. Best regards, Christof Chen
Subject: net-dhcp-options.patch
Index: lib/Net/DHCP/Packet.pm =================================================================== --- lib/Net/DHCP/Packet.pm (.../original/Net-DHCP-0.66/lib/Net/DHCP/Packet.pm) (Revision 35) +++ lib/Net/DHCP/Packet.pm (.../trunk/current/lib/Net/DHCP/Packet.pm) (Arbeitskopie) @@ -1,6 +1,7 @@ # Net::DHCP::Packet.pm # Original Author: F. van Dun # Author : S. Hadinger +# modifications: Christof Chen package Net::DHCP::Packet; @@ -9,7 +10,7 @@ use strict; our (@ISA, @EXPORT, @EXPORT_OK, $VERSION); use Exporter; -$VERSION = 0.66; +$VERSION = 0.661; @ISA = qw(Exporter); @EXPORT = qw( packinet packinets unpackinet unpackinets ); @EXPORT_OK = qw( ); @@ -241,17 +242,42 @@ sub addOptionRaw { my ($self,$key,$value_bin) = @_; - $self->{options}->{$key} = $value_bin; - push @{$self->{options_order}}, ($key); + if (!exists $self->{options}->{$key}) { + push @{$self->{options_order}}, $key; + } + push @{$self->{options}->{$key}}, $value_bin; } +sub replaceOptionRaw { + my ($self,$key,$value_bin) = @_; + if (!exists $self->{options}->{$key}) { + push @{$self->{options_order}}, ($key); + } + @{$self->{options}->{$key}} = ($value_bin); +} + sub addOptionValue($$$) { my $self = shift; my $code = shift; # option code my $value = shift; + + my $value_bin = makevalbin($code, $value); + $self->addOptionRaw($code, $value_bin); +} + +sub replaceOptionValue($$$) { + my $self = shift; + my $code = shift; # option code + my $value = shift; + + my $value_bin = makevalbin($code, $value); + $self->replaceOptionRaw($code, $value_bin); +} + +sub makevalbin () { +my ($code,$value) = @_; + my $format = ''; # format for the option my $value_bin; # option value in binary format - my $format = ''; # format for the option - carp("addOptionValue: unknown format for code ($code)") unless exists($DHO_FORMATS{$code}); $format = $DHO_FORMATS{$code} if exists($DHO_FORMATS{$code}); @@ -267,9 +293,9 @@ } elsif ($format =~ /s$/) { # ends with an 's', meaning any number of parameters ; } elsif ($format =~ /2$/) { # ends with a '2', meaning couples of parameters - croak("addOptionValue: only pairs of values expected for option '$code'") if ((@values % 2) != 0); + croak("makevalbin: only pairs of values expected for option '$code'") if ((@values % 2) != 0); } else { # only one parameter - croak("addOptionValue: exactly one value expected for option '$code'") if (@values != 1); + croak("makevalbin: exactly one value expected for option '$code'") if (@values != 1); } if ($format eq 'inet') { @@ -294,10 +320,10 @@ } else { $value_bin = $values[0]; } - - $self->addOptionRaw($code, $value_bin); + return $value_bin; } + #sub getOption { # deprecated # my $self = shift; # return $self->getOptionRaw(@_); @@ -316,38 +342,27 @@ carp("getOptionValue: unknown format for code ($code)") unless exists($DHO_FORMATS{$code}); $format = $DHO_FORMATS{$code} if exists($DHO_FORMATS{$code}); - my $value_bin = $self->getOptionRaw($code); - return undef unless defined($value_bin); - my @values = (); + my $values_arr = ($self->getOptionRaw($code)); + return undef unless defined($values_arr->[0]); + my @value = (); - if ($format eq 'inet') { - $values[0] = unpackinet($value_bin); - } elsif (($format eq 'inets') || ($format eq 'inets2')) { - @values = unpackinets_array($value_bin); - } elsif ($format eq 'int') { - $values[0] = unpack('N', $value_bin); - } elsif ($format eq 'short') { - $values[0] = unpack('n', $value_bin); - } elsif ($format eq 'shorts') { - @values = unpack('n*', $value_bin); - } elsif ($format eq 'byte') { - $values[0] = unpack('C', $value_bin); - } elsif ($format eq 'bytes') { - @values = unpack('C*', $value_bin); - } elsif ($format eq 'string') { - $values[0] = $value_bin; -# } elsif ($format eq 'relays') { -# @values = $self->decodeRelayAgent($value_bin); -# # TBM, bad format -# } elsif ($format eq 'ids') { -# $values[0] = $value_bin; -# # TBM, bad format - } else { - $values[0] = $value_bin; + foreach my $value_bin (@{$values_arr}) { + my $data = join " ", $format eq 'inet' ? unpackinet($value_bin) + : $format eq 'inets' || ($format eq 'inets2') ? unpackinets_array($value_bin) + : $format eq 'int' ? unpack('N', $value_bin) + : $format eq 'short' ? unpack('n', $value_bin) + : $format eq 'shorts' ? unpack('n*', $value_bin) + : $format eq 'byte' ? unpack('C', $value_bin) + : $format eq 'bytes' ? unpack('C*', $value_bin) + : $format eq 'string' ? $value_bin + : $value_bin + ; + push @value, $data; } - return join(" ", @values); -# return wantarray ? @values : $values[0]; + + #return join(" ", @values); + return wantarray ? @value : $value[0]; } sub removeOption { @@ -394,8 +409,10 @@ if ($self->{isDhcp}) { # add MAGIC_COOKIE and options $bytes .= MAGIC_COOKIE(); foreach my $key ( @{$self->{options_order}} ) { - $bytes .= pack('C', $key); - $bytes .= pack('C/a*', $self->{options}->{$key}); + foreach my $value (@{$self->{options}->{$key}}) { + $bytes .= pack('C', $key); + $bytes .= pack('C/a*', $value); + } } $bytes .= pack('C', 255); } @@ -555,22 +572,16 @@ foreach my $key ( @{$self->{options_order}} ) { my $value; # value of option to be printed - - if ($key == DHO_DHCP_MESSAGE_TYPE()) { - $value = $self->getOptionValue($key); - $value = (exists($REV_DHCP_MESSAGE{$value}) && $REV_DHCP_MESSAGE{$value}) || $self->getOptionValue($key); - } else { - if (exists($DHO_FORMATS{$key})) { - $value = join(" ", $self->getOptionValue($key)); - } else { - $value = $self->getOptionRaw($key); - } - $value =~ s/([[:^print:]])/ sprintf q[\x%02X], ord $1 /eg; # printable text - } - $s .= sprintf(" %s(%d) = %s\n", exists $REV_DHO_CODES{$key} ? $REV_DHO_CODES{$key}: '', $key, $value); + #my @data = exists($DHO_FORMATS{$key}) ? $self->getOptionValue($key) : $self->getOptionRaw($key); + foreach $value ($self->getOptionValue($key)) { + if ($key == DHO_DHCP_MESSAGE_TYPE()) { + $value = (exists($REV_DHCP_MESSAGE{$value}) && $REV_DHCP_MESSAGE{$value}) || $value; + } + $value =~ s/([[:^print:]])/ sprintf q[\x%02X], ord $1 /eg; # printable text + $s .= sprintf(" %s(%d) = %s\n", exists $REV_DHO_CODES{$key} ? $REV_DHO_CODES{$key}: '', $key, $value); + } } $s .= sprintf("padding [%s] = %s\n", length($self->{padding}), unpack('H*', $self->{padding})); - return $s; } #======================================================================= @@ -858,7 +869,7 @@ =item addOptionValue ( CODE, VALUE ) -Adds a DHCP option field. Common code values are listed in +Adds/appends a DHCP option field. Common code values are listed in C<Net::DHCP::Constants> C<DHO_>*. Values are automatically converted according to their data types, @@ -872,6 +883,9 @@ $pac->addOption(DHO_DHCP_MESSAGE_TYPE(), DHCPINFORM()); $pac->addOption(DHO_NAME_SERVERS(), "10.0.0.1", "10.0.0.2")); +=item replaceOptionValue ( CODE, VALUE ) +Replaces a DHCP option field. + =item getOptionValue ( CODE ) Returns the value of a DHCP option.
From: Christof [...] chen.de
Oops. wrong queue. This is now a duplicate to #23546 Please close this bug here.
Subject: Re: [rt.cpan.org #23544] unhandled multiple options
Date: Wed, 22 Nov 2006 09:45:39 -0800 (PST)
To: bug-Net-DHCP-Packet [...] rt.cpan.org
From: Stephan Hadinger <stephan [...] hadinger.net>
Christof, Thank you for this patch. I will try to find time to make and publish a new build this week. Regards Stephan --- Christof Chen via RT <bug-Net-DHCP-Packet@rt.cpan.org> wrote: Show quoted text
> > Queue: Net-DHCP-Packet > Ticket <URL: > http://rt.cpan.org/Ticket/Display.html?id=23544 > > > Oops. wrong queue. > This is now a duplicate to #23546 > Please close this bug here. >