diff --git a/dhcpd/CHANGELOG b/dhcpd/CHANGELOG index 4af47551c..e83f69e98 100644 --- a/dhcpd/CHANGELOG +++ b/dhcpd/CHANGELOG @@ -21,3 +21,5 @@ Added a field on the Client Options page for the DHCP server identifier. Fixed a bug that causes hosts to be deleted when searching for them! ---- Changes since 1.410 ---- Clashes between hosts with the same IP address, MAC address or hostname are no longer allowed by default - but this can be changed on the DHCP Server access control page in the Webmin User's module. +---- Changes since 1.420 ---- +Support the new configuration file format for custom options, as used in DHCPd version 3. diff --git a/dhcpd/edit_options.cgi b/dhcpd/edit_options.cgi index 9a84d1d79..d9aeb4831 100755 --- a/dhcpd/edit_options.cgi +++ b/dhcpd/edit_options.cgi @@ -128,32 +128,13 @@ print &option_input($text{'eopt_slps'}, "slp-service-scope", \@opts, 3, $text{'eopt_slpsonly'}); print "\n"; -# Show custom options -print "
\n"; -@custom = grep { $_->{'values'}->[0] =~ /^option-(\S+)$/ && - $_->{'values'}->[1] ne 'code' } @opts; -push(@custom, undef); -push(@custom, undef) if (@custom%2 == 1); -for($i=0; $i<@custom; $i++) { - $o = $custom[$i]; - print "\n" if ($i%2 == 0); - print "$text{'eopt_custom'}\n"; - print "$text{'eopt_cnum'}\n"; - local ($ov, @v) = @{$o->{'values'}}; - printf "\n", - $ov =~ /^option-(\S+)$/ ? $1 : ''; - print "$text{'eopt_cval'}\n"; - printf "\n", - join(" ", @v); - print "\n" if ($i%2 != 0); - } - if ($config{'dhcpd_version'} >= 3) { # Show option definitions print "
\n"; @defs = grep { $_->{'values'}->[1] eq 'code' && $_->{'values'}->[3] eq '=' } @opts; push(@defs, undef); + %optdef = ( ); for($i=0; $i<@defs; $i++) { $o = $defs[$i]; print "\n"; @@ -168,6 +149,49 @@ if ($config{'dhcpd_version'} >= 3) { printf "\n", $o->{'values'}->[4]; print " \n"; + $optdef{$o->{'values'}->[0]} = $o if ($o->{'values'}->[0]); + } + + # Show values for custom options + if (keys %optdef) { + @custom = grep { $optdef{$_->{'values'}->[0]} && + $_->{'values'}->[1] ne 'code' } @opts; + push(@custom, undef); + push(@custom, undef) if (@custom%2 == 1); + for($i=0; $i<@custom; $i++) { + $o = $custom[$i]; + print " $text{'eopt_custom'}\n"; + print "$text{'eopt_cname'}\n"; + local ($ov, @v) = @{$o->{'values'}}; + print &ui_select("cname_$i", $ov, + [ [ "", " " ], + sort { $a cmp $b } keys %optdef ], + 1, 0, $ov ? 1 : 0); + print "$text{'eopt_cval'}\n"; + print &ui_textbox("cval_$i", join(" ", @v), 40); + print " \n"; + } + } + } +else { + # Show custom numeric options + print "
\n"; + @custom = grep { $_->{'values'}->[0] =~ /^option-(\S+)$/ && + $_->{'values'}->[1] ne 'code' } @opts; + push(@custom, undef); + push(@custom, undef) if (@custom%2 == 1); + for($i=0; $i<@custom; $i++) { + $o = $custom[$i]; + print "\n" if ($i%2 == 0); + print "$text{'eopt_custom'}\n"; + print "$text{'eopt_cnum'}\n"; + local ($ov, @v) = @{$o->{'values'}}; + printf "\n", + $ov =~ /^option-(\S+)$/ ? $1 : ''; + print "$text{'eopt_cval'}\n"; + printf "\n", + join(" ", @v); + print "\n" if ($i%2 != 0); } } diff --git a/dhcpd/lang/en b/dhcpd/lang/en index d1d5023a4..4757a5bdc 100644 --- a/dhcpd/lang/en +++ b/dhcpd/lang/en @@ -179,6 +179,7 @@ sopt_invalidipp=is not a valid IP address pair (like 1.2.3.4,5.6.7.8) sopt_edname='$1' is not a valid option name sopt_ednum='$1' is not a valid option number sopt_edtype='$1' is not a valid option type +sopt_ecval=Missing value for custom option '$1' sshared_faildel=Failed to delete shared network sshared_failsave=Failed to save shared network @@ -281,6 +282,7 @@ eopt_nbntype=NetBIOS node type eopt_toffset=Time offset eopt_custom=Custom option eopt_cnum=Number +eopt_cname=Name eopt_cval=Value eopt_def=Option definition eopt_dname=Option name diff --git a/dhcpd/save_options.cgi b/dhcpd/save_options.cgi index 6e8b8c1d7..8910f43d7 100755 --- a/dhcpd/save_options.cgi +++ b/dhcpd/save_options.cgi @@ -82,30 +82,13 @@ elsif ($in{'level'} eq "shared-network") { $ret="edit_shared.cgi?idx=$in{'idx'}"; } -# save custom options -@custom = grep { $_->{'name'} eq 'option' && - $_->{'values'}->[0] =~ /^option-(\S+)$/ && - $_->{'values'}->[1] ne 'code' } - @{$client->{'members'}}; -for($i=0; defined($in{"cnum_$i"}); $i++) { - next if (!$in{"cnum_$i"} || !$in{"cval_$i"}); - $in{"cnum_$i"} =~ /^\d+$/ || - ($config{'dhcpd_version'} >= 3 && $in{"cnum_$i"} =~ /^\S+$/) || - &error(&text('sopt_ednum', $in{"cnum_$i"})); - local $cv = $in{"cval_$i"}; - $cv = "\"$cv\"" if ($cv !~ /^([0-9a-fA-F]{1,2}:)*[0-9a-fA-F]{1,2}$/); - push(@newcustom, { 'name' => 'option', - 'values' => [ 'option-'.$in{"cnum_$i"}, - $cv ] } ); - } -&save_directive($client, \@custom, \@newcustom, $indent, 1); - if ($config{'dhcpd_version'} >= 3) { - # save option definitions + # Save option definitions @defs = grep { $_->{'name'} eq 'option' && $_->{'values'}->[1] eq 'code' && $_->{'values'}->[3] eq '=' } @{$client->{'members'}}; + %optdef = map { $_->{'values'}->[0], $_ } @defs; for($i=0; defined($in{"dname_$i"}); $i++) { next if (!$in{"dname_$i"} || !$in{"dnum_$i"} || !$in{"dtype_$i"}); @@ -122,6 +105,43 @@ if ($config{'dhcpd_version'} >= 3) { ] } ); } &save_directive($client, \@defs, \@newdefs, $indent, 1); + + # Save custom options + @custom = grep { $_->{'name'} eq 'option' && + $optdef{$_->{'values'}->[0]} && + $_->{'values'}->[1] ne 'code' } + @{$client->{'members'}}; + for($i=0; defined($in{"cname_$i"}); $i++) { + next if ($in{"cname_$i"} eq ""); + local $cv = $in{"cval_$i"}; + $cv =~ /\S/ || &error(&text('sopt_ecval', $in{"cname_$i"})); + $cv = "\"$cv\"" + if ($cv !~ /^([0-9a-fA-F]{1,2}:)*[0-9a-fA-F]{1,2}$/); + push(@newcustom, { 'name' => 'option', + 'values' => [ $in{"cname_$i"}, $cv ] } ); + } + &save_directive($client, \@custom, \@newcustom, $indent, 1); + } +else { + # Save custom options + @custom = grep { $_->{'name'} eq 'option' && + $_->{'values'}->[0] =~ /^option-(\S+)$/ && + $_->{'values'}->[1] ne 'code' } + @{$client->{'members'}}; + for($i=0; defined($in{"cnum_$i"}); $i++) { + next if (!$in{"cnum_$i"} || !$in{"cval_$i"}); + $in{"cnum_$i"} =~ /^\d+$/ || + ($config{'dhcpd_version'} >= 3 && + $in{"cnum_$i"} =~ /^\S+$/) || + &error(&text('sopt_ednum', $in{"cnum_$i"})); + local $cv = $in{"cval_$i"}; + $cv = "\"$cv\"" + if ($cv !~ /^([0-9a-fA-F]{1,2}:)*[0-9a-fA-F]{1,2}$/); + push(@newcustom, { 'name' => 'option', + 'values' => [ 'option-'.$in{"cnum_$i"}, + $cv ] } ); + } + &save_directive($client, \@custom, \@newcustom, $indent, 1); } &flush_file_lines();