#!/usr/bin/perl
#
# disable activation of DHCP server if DNSMASQ handles DHCP requests
# modified by bco, 2014-01-18
# taken from Endian Firewall 3.0
my $dnsmasq = 0; 
my $leases = "/var/lib/misc/dnsmasq.leases";
#
# SmoothWall CGIs
#
# This code is distributed under the terms of the GPL
#
# (c) The SmoothWall Team
# (c) Endian GmbH/srl
#
# Copyright (C) 01-02-2002 Graham Smith <grhm@grhm.co.uk>
#              - Fixed DHCP Leases added
#
# $Id: dhcp.cgi,v 1.14.2.24 2004/11/29 10:49:16 eoberlander Exp $
#
#  Franck    -rewrite for two or more interface
#  nov/2004    -check range is in correct subnet
#        -add NTP option
#        -add display sorting of actives leases
#
# to do : choose a correct format for displaying dates
#
require 'header.pl';
use Net::IPv4Addr qw (:all);
use HTML::Entities;
use POSIX qw(strftime);

my %dhcpsettings;
my %netsettings;
my %hostsettings;
my %hotspotsettings;
my $ntpsettings;
my $filename = "${swroot}/dhcp/fixleases";

my $conffile    = "${swroot}/dhcp/settings";
my $restart     = '/usr/local/bin/restartdhcp';

my $ntp_conffile = "${swroot}/time/settings";

my $custom_global = "";
my $custom_global_file="${swroot}/dhcp/custom.tpl";

my %enable = ();
my %olddhcpsettings = ();
readhash($conffile, \%olddhcpsettings);

$enable{'GREEN'} = 0;
if (exists $olddhcpsettings{"ENABLE_GREEN"} && $olddhcpsettings{"ENABLE_GREEN"} eq 'on') {
	$enable{'GREEN'} = 1;
}
$enable{'BLUE'} = 0;
if (exists $olddhcpsettings{"ENABLE_BLUE"} && $olddhcpsettings{"ENABLE_BLUE"} eq 'on') {
	$enable{'BLUE'} = 1;
}
$enable{'ORANGE'} = 0;
if (exists $olddhcpsettings{"ENABLE_ORANGE"} && $olddhcpsettings{"ENABLE_ORANGE"} eq 'on') {
	$enable{'ORANGE'} = 1;
}

$ntp_enable = 0;
readhash($ntp_conffile, \%ntpsettings);
if (exists $ntpsettings{"ENABLE_NTP"} && $ntpsettings{"ENABLE_NTP"} eq 'on') {
    $ntp_enable = 1;
}
if (exists $ntpsettings{"NTP_AUTOSYNC"} && $ntpsettings{"NTP_AUTOSYNC"} eq 'on') {
    $ntp_enable = 1;
}

sub read_file($) {
    my $f = shift;
    open(F, $f) || return "";
    my @lines = <F>;
    close(F);
    return join("", @lines);
}

sub write_file($$) {
    my $f = shift;
    my $data = shift;
    open(F, ">$f") || return;
    print F $data;
    close(F);
}

sub ip2long {
    return unpack("l*", pack("l*", unpack("N*", inet_aton(shift))));
}

sub read_dhcp_conf() {

    readhash($conffile, \%dhcpsettings);
    $custom_global = read_file($custom_global_file);
}

&showhttpheaders();
@ITFs=('GREEN');

if (orange_used()) {
    push(@ITFs, 'ORANGE');
}
if (blue_used()) {
    push(@ITFs, 'BLUE');
}

my %interface_title = (
    'GREEN' => _('Green interface'),
    'ORANGE' => _('Orange interface'),
    'BLUE' => _('Blue interface')
);

# dependent interface variable
foreach $itf (@ITFs) {
  $dhcpsettings{"ENABLE_${itf}"} = '';
  $dhcpsettings{"START_ADDR_${itf}"} = '';
  $dhcpsettings{"END_ADDR_${itf}"} = '';
  $dhcpsettings{"ONLY_FIXEDLEASE_${itf}"} = '';
  $dhcpsettings{"DOMAIN_NAME_${itf}"} = '';
  $dhcpsettings{"DEFAULT_LEASE_TIME_${itf}"} = '';
  $dhcpsettings{"MAX_LEASE_TIME_${itf}"} = '';
  $dhcpsettings{"GATEWAY_${itf}"} = '';
  $dhcpsettings{"WINS1_${itf}"} = '';
  $dhcpsettings{"WINS2_${itf}"} = '';
  $dhcpsettings{"DNS1_${itf}"} = '';
  $dhcpsettings{"DNS2_${itf}"} = '';
  $dhcpsettings{"NTP1_${itf}"} = '';
  $dhcpsettings{"NTP2_${itf}"} = '';
}

$dhcpsettings{'FIX_MAC'} = '';
$dhcpsettings{'FIX_ADDR'} = '';
$dhcpsettings{'ENABLED'} = 'on';
$dhcpsettings{'FIX_NEXTADDR'} = '';
$dhcpsettings{'FIX_FILENAME'} = '';
$dhcpsettings{'FIX_ROOTPATH'} = '';
$dhcpsettings{'FIX_DESCRIPTION'} = '';

&getcgihash(\%dhcpsettings);

my @current = ();
if ( -e $filename) {
    open(FILE, "$filename") or die 'Unable to open fixed leases file.';
    @current = <FILE>;
    close(FILE);
}

&readhash("${swroot}/ethernet/settings", \%netsettings);
&readhash("${swroot}/host/settings", \%hostsettings);

&readhash("${swroot}/hotspot/settings", \%hotspotsettings);

foreach $itf (@ITFs) {
    if ($netsettings{"${itf}_NETADDRESS"} ne "" and $netsettings{"${itf}_NETMASK"} ne "") {
        my $netaddress = $netsettings{"${itf}_NETADDRESS"};
        my $fwaddress = $netsettings{"${itf}_ADDRESS"};
        my $broadcastaddress = ipv4_broadcast($netsettings{"${itf}_NETADDRESS"}, $netsettings{"${itf}_NETMASK"});
        my @ip = split(/\./, $fwaddress);
        my @net = split(/\./, $netaddress);
        my @broadcast = split(/\./, $broadcastaddress);
        if (@ip[3] eq @broadcast[3] - 1) {
            if ($dhcpsettings{"START_ADDR_${itf}"} eq "") {
                $dhcpsettings{"START_ADDR_${itf}"} = @net[0].".".@net[1].".".@net[2].".".(@net[3] + 1);
            }
            if ($dhcpsettings{"END_ADDR_${itf}"} eq "") {
                $dhcpsettings{"END_ADDR_${itf}"} = @ip[0].".".@ip[1].".".@ip[2].".".(@ip[3] - 1);
            }
        }
        else {
            if ($dhcpsettings{"START_ADDR_${itf}"} eq "") {
                $dhcpsettings{"START_ADDR_${itf}"} = @ip[0].".".@ip[1].".".@ip[2].".".(@ip[3] + 1);
            }
            if ($dhcpsettings{"END_ADDR_${itf}"} eq "") {
                $dhcpsettings{"END_ADDR_${itf}"} = @broadcast[0].".".@broadcast[1].".".@broadcast[2].".".(@broadcast[3] - 1);
            }
        }
    }
}

my @errormessages = ();

# Toggle enable/disable field on specified lease.
if ($dhcpsettings{'ACTION'} eq 'toggle')
{
    my @temp = split(/\,/,@current[$dhcpsettings{'KEY1'}]);
    if ($temp[2] eq 'on') {
    $temp[2] = '';
    } else {
    $temp[2] = 'on';
    }
    @current[$dhcpsettings{'KEY1'}] = "$temp[0],$temp[1],$temp[2],$temp[3],$temp[4],$temp[5],$temp[6]";
    $dhcpsettings{'KEY1'} = ''; # End edit mode
    &log(_('Fixed IP lease modified'));
    open(FILE, ">$filename") or die 'Unable to open fixed leases file.';
    print FILE @current;
    close(FILE);
    
    #Write changes to dhcpd.conf.
    read_dhcp_conf();
    &buildconf;
}


if ($dhcpsettings{'ACTION'} eq 'add')
{
    $dhcpsettings{'FIX_MAC'} =~ tr/-/:/;
    unless(&validip($dhcpsettings{'FIX_ADDR'})) { 
        push(@errormessages, _('Invalid fixed IP address'));
    }
    unless(&validmac($dhcpsettings{'FIX_MAC'})) {
        push(@errormessages, _('Invalid fixed MAC address'));
    }
    if ($dhcpsettings{'FIX_NEXTADDR'}) 
    {
        unless(&validip($dhcpsettings{'FIX_NEXTADDR'})) {
            push(@errormessages, _('Invalid next fixed IP address'));
        }
    }
    
    my $key = 0;
    foreach my $line (@current)
    {
        my @temp = split(/\,/,$line);
        if($dhcpsettings{'KEY1'} ne $key)
        {
        if(lc($dhcpsettings{'FIX_MAC'}) eq lc($temp[0]) && $dhcpsettings{'FIX_MAC'} ne "")
        {
            push(@errormessages, _('MAC address \'%s\' already in use', $dhcpsettings{'FIX_MAC'}));
        }
        if($dhcpsettings{'FIX_ADDR'} eq $temp[1] && $dhcpsettings{'FIX_ADDR'} ne "")
        {
            push(@errormessages, _('IP address \'%s\' already in use', $dhcpsettings{'FIX_ADDR'}));
        }
    }
    $key++;
}
    
    if ($#errormessages eq -1) {
        if ($dhcpsettings{'KEY1'} eq '') #add or edit ?
        {
        unshift (@current, "$dhcpsettings{'FIX_MAC'},$dhcpsettings{'FIX_ADDR'},$dhcpsettings{'ENABLED'},$dhcpsettings{'FIX_NEXTADDR'},$dhcpsettings{'FIX_FILENAME'},$dhcpsettings{'FIX_ROOTPATH'},$dhcpsettings{'FIX_DESCRIPTION'}\n");
        &log(_('Fixed IP lease added'));
        } else {
        @current[$dhcpsettings{'KEY1'}] = "$dhcpsettings{'FIX_MAC'},$dhcpsettings{'FIX_ADDR'},$dhcpsettings{'ENABLED'},$dhcpsettings{'FIX_NEXTADDR'},$dhcpsettings{'FIX_FILENAME'},$dhcpsettings{'FIX_ROOTPATH'},$dhcpsettings{'FIX_DESCRIPTION'}\n";
        $dhcpsettings{'FIX_MAC'}='';
        $dhcpsettings{'FIX_ADDR'}='';
        $dhcpsettings{'FIX_NEXTADDR'}='';
        $dhcpsettings{'FIX_FILENAME'}='';
        $dhcpsettings{'FIX_ROOTPATH'}='';
        $dhcpsettings{'FIX_DESCRIPTION'}='';
        $dhcpsettings{'ENABLED'}='on';
        $dhcpsettings{'KEY1'} = '';       # End edit mode
        &log(_('Fixed IP lease modified'));
        }
        

        #Write changes to dhcpd.conf.
        read_dhcp_conf();
        &sortcurrent;     # sort newly added/modified entry
        &buildconf;       # before calling buildconf which use fixed lease file !
    } else {
        my %temp_settings = %dhcpsettings;
        read_dhcp_conf();
        $dhcpsettings{'FIX_MAC'}= $temp_settings{'FIX_MAC'};
        $dhcpsettings{'FIX_ADDR'}= $temp_settings{'FIX_ADDR'};
        $dhcpsettings{'FIX_NEXTADDR'}= $temp_settings{'FIX_NEXTADDR'};
        $dhcpsettings{'FIX_FILENAME'}= $temp_settings{'FIX_FILENAME'};
        $dhcpsettings{'FIX_ROOTPATH'}= $temp_settings{'FIX_ROOTPATH'};
        $dhcpsettings{'FIX_DESCRIPTION'}= $temp_settings{'FIX_DESCRIPTION'};
        $dhcpsettings{'ENABLED'}= $temp_settings{'ENABLED'};
        $dhcpsettings{'KEY1'} = $temp_settings{'KEY1'};
    }
}

if ($dhcpsettings{'ACTION'} eq 'edit')
{
    my @temp = split(/\,/,@current[$dhcpsettings{'KEY1'}]);
    read_dhcp_conf();
    $dhcpsettings{'FIX_MAC'}=$temp[0];
    $dhcpsettings{'FIX_ADDR'}=$temp[1];
    $dhcpsettings{'ENABLED'}=$temp[2];
    $dhcpsettings{'FIX_NEXTADDR'}=$temp[3];
    $dhcpsettings{'FIX_FILENAME'}=$temp[4];
    $dhcpsettings{'FIX_ROOTPATH'}=$temp[5];
    $dhcpsettings{'FIX_DESCRIPTION'}=$temp[6];
}


if ($dhcpsettings{'ACTION'} eq 'remove')
{
    splice (@current,$dhcpsettings{'KEY1'},1);
    open(FILE, ">$filename") or die 'Unable to open fixed lease file.';
    print FILE @current;
    close(FILE);
    &log(_('Fixed IP lease removed'));

    #Write changes to dhcpd.conf.
    read_dhcp_conf();
    undef ($dhcpsettings{'KEY1'});  # End remove mode
    &buildconf;
}

if ($dhcpsettings{'ACTION'} eq 'save')
{
  foreach $itf (@ITFs) {
      if ($dhcpsettings{"ENABLE_${itf}"} ne $enable{$itf}) {
          if ($dhcpsettings{"ENABLE_${itf}"}) {
		    $enable{$itf} = 1;
		  } else {
		    $enable{$itf} = 0;
		  }
      }
      if ($enable{$itf}) {
        # "Start" is defined, need "End" and vice versa
        if ($dhcpsettings{"START_ADDR_${itf}"}) {
            if (!(&validip($dhcpsettings{"START_ADDR_${itf}"}))) {
                $errormessage = _('DHCP on %s: invalid start address.', $itf);
                goto ERROR;
            }
            if (!$dhcpsettings{"END_ADDR_${itf}"}) {
                $errormessage = _('DHCP on %s: invalid end address.', $itf);
                goto ERROR;
            }
            if (! &IpInSubnet ( $dhcpsettings{"START_ADDR_${itf}"}, 
                                $netsettings{"${itf}_NETADDRESS"},
                                $netsettings{"${itf}_NETMASK"})) {
                $errormessage = _('DHCP on %s: invalid start address.', $itf);
                goto ERROR;
            }
        }
        if ($dhcpsettings{"END_ADDR_${itf}"}) {
            if (!(&validip($dhcpsettings{"END_ADDR_${itf}"}))) {
                $errormessage = _('DHCP on %s: invalid end address.', $itf);
                goto ERROR;
            }
            if (!$dhcpsettings{"START_ADDR_${itf}"}) {
                $errormessage = _('DHCP on %s: invalid start address.', $itf);
                goto ERROR;
            }
            if (! &IpInSubnet ( $dhcpsettings{"END_ADDR_${itf}"}, 
                                $netsettings{"${itf}_NETADDRESS"},
                                $netsettings{"${itf}_NETMASK"})) { 
                $errormessage = _('DHCP on %s: invalid end address.', $itf);
                goto ERROR;
            }
            #swap if necessary!
            if (ip2long($dhcpsettings{"START_ADDR_${itf}"})  >= ip2long($dhcpsettings{"END_ADDR_${itf}"})) {
                my $tmp = $dhcpsettings{"START_ADDR_${itf}"};
                $dhcpsettings{"START_ADDR_${itf}"} = $dhcpsettings{"END_ADDR_${itf}"};
                $dhcpsettings{"END_ADDR_${itf}"} = $tmp;
            }
        }
        if (ip2long($dhcpsettings{"START_ADDR_${itf}"})  >= ip2long($dhcpsettings{"END_ADDR_${itf}"})) {
            $errormessage = _('DHCP on %s: Pool start address must be lesser than end address!', $itf);
            goto ERROR;
        }
        if ($dhcpsettings{"START_ADDR_${itf}"} eq $netsettings{"${itf}_NETADDRESS"}) {
            $errormessage = _('DHCP on %s: invalid start address', $itf);
            goto ERROR;
        }
        if ($dhcpsettings{"END_ADDR_${itf}"} eq ipv4_broadcast($netsettings{"${itf}_NETADDRESS"}, $netsettings{"${itf}_NETMASK"})) {
            $errormessage = _('DHCP on %s: invalid end address', $itf);
            goto ERROR;
        }
    
    if (!($dhcpsettings{"DEFAULT_LEASE_TIME_${itf}"} =~ /^\d+$/))
    {
        $errormessage = _('DHCP on %s: invalid default lease time: %s.', $itf, $dhcpsettings{'DEFAULT_LEASE_TIME_${itf}'});
        goto ERROR;
    }
    if (!($dhcpsettings{"MAX_LEASE_TIME_${itf}"} =~ /^\d+$/))
    {
        $errormessage = _('DHCP on %s: invalid default lease time: %s.', $itf, $dhcpsettings{'DEFAULT_LEASE_TIME_${itf}'});
        $errormessage = _('DHCP on %s: invalid max lease time: %s', $itf, $dhcpsettings{'MAX_LEASE_TIME_${itf}'});
        goto ERROR;
    }

    if ($dhcpsettings{"GATEWAY_${itf}"})
    {
        if (!(&validip($dhcpsettings{"GATEWAY_${itf}"})))
        {
            $errormessage = _('DHCP on %s: invalid gateway %s.', $itf, $dhcpsettings{"GATEWAY_${itf}"});
            goto ERROR;
        }
    }


    if ($dhcpsettings{"DNS1_${itf}"})
    {
        if (!(&validip($dhcpsettings{"DNS1_${itf}"})))
        {
            $errormessage = _('DHCP on %s: invalid primary DNS.', $itf);
            goto ERROR;
        }
    }
    if ($dhcpsettings{"DNS2_${itf}"})
    {
        if (!(&validip($dhcpsettings{"DNS2_${itf}"})))
        {
            $errormessage = _('DHCP on %s: invalid secondary DNS.', $itf);
            goto ERROR;
        }
            if (! $dhcpsettings{"DNS1_${itf}"})
            {
            $errormessage = _('DHCP on %s: cannot specify secondary DNS without specifying primary.', $itf); 
            goto ERROR;
            }
    }

    if ($dhcpsettings{"WINS1_${itf}"})
    {
        if (!(&validip($dhcpsettings{"WINS1_${itf}"})))
        {
            $errormessage = _('DHCP on %s: invalid WINS server address.', $itf);
            goto ERROR;
        }
    }
    if ($dhcpsettings{"WINS2_${itf}"})
    {
        if (!(&validip($dhcpsettings{"WINS2_${itf}"})))
        {
            $errormessage = _('DHCP on %s: invalid WINS server address.', $itf);
            goto ERROR;
        }
        if (! $dhcpsettings{"WINS1_${itf}"} ) {
            $errormessage = _('DHCP on %s: cannot specify secondary WINS without specifying primary.', $itf);
            goto ERROR;
        }        
    }

     if ($dhcpsettings{"NTP1_${itf}"})
     {
         if (!(&validip($dhcpsettings{"NTP1_${itf}"})))
         {
             $errormessage = _('DHCP on %s: invalid primary NTP server address', $itf);
             goto ERROR;
         }
         if ($dhcpsettings{"NTP1_${itf}"} eq $netsettings{"${itf}_ADDRESS"} && (! $ntp_enable))
         {
             $warnNTPmessage = _('DHCP on %s: local NTP server specified but not enabled', $itf);
             #goto ERROR;
         }
     }
     if ($dhcpsettings{"NTP2_${itf}"})
     {
         if (!(&validip($dhcpsettings{"NTP2_${itf}"})))
         {
             $errormessage = _('DHCP on %s: invalid secondary NTP server address', $itf);
             goto ERROR;
         }
         if ($dhcpsettings{"NTP2_${itf}"} eq $netsettings{"${itf}_ADDRESS"} && (! $ntp_enable))
         {
             $warnNTPmessage = _('DHCP on %s: local NTP server specified but not enabled', $itf);
             #goto ERROR;
         }
         if (! $dhcpsettings{"NTP1_${itf}"})
         {
             $errormessage = _('DHCP on %s: Cannot specify Secondary NTP server without specifying Primary', $itf);
             goto ERROR;
         }
     }
      } # enabled
    }#loop interface verify

    $dhcpsettings{'CUSTOM_GLOBAL'} =~ s/\r//;
    decode_entities($dhcpsettings{'CUSTOM_GLOBAL'});
    write_file($custom_global_file, $dhcpsettings{'CUSTOM_GLOBAL'});
    $custom_global=$dhcpsettings{'CUSTOM_GLOBAL'};
    delete $dhcpsettings{'CUSTOM_GLOBAL'};
    # delete unwanted keys
    delete $dhcpsettings{'__CGI__'};
    delete $dhcpsettings{'color'};
    delete $dhcpsettings{'submit'};
    delete $dhcpsettings{'CUSTOM_GLOBAL'};
    delete $dhcpsettings{'ID'};
    delete $dhcpsettings{'FIX_MAC'};
    delete $dhcpsettings{'FIX_ADDR'};
    delete $dhcpsettings{'ENABLED'};
    delete $dhcpsettings{'FIX_NEXTADDR'};
    delete $dhcpsettings{'FIX_FILENAME'};
    delete $dhcpsettings{'FIX_ROOTPATH'};
    delete $dhcpsettings{'FIX_DESCRIPTION'};
    
    &writehash("${swroot}/dhcp/settings", \%dhcpsettings);
    &buildconf;
ERROR:
}

#Sorting of fixed leases
if ($ENV{'QUERY_STRING'} =~ /^FETHER|^FIPADDR/ ) {
    my $newsort=$ENV{'QUERY_STRING'};
    read_dhcp_conf();
    $act=$dhcpsettings{'SORT_FLEASELIST'};
    #Reverse actual ?
    if ($act =~ $newsort) {
        if ($act !~ 'Rev') {$Rev='Rev'};
        $newsort.=$Rev
    };

    $dhcpsettings{'SORT_FLEASELIST'}=$newsort;
    &writehash("${swroot}/dhcp/settings", \%dhcpsettings);
    &sortcurrent;
    $dhcpsettings{'ACTION'} = 'SORT';  # avoid the next test "First lauch"
}

#Sorting of allocated leases
&CheckSortOrder;

if ($dhcpsettings{'ACTION'} eq '' ) { # First launch

    read_dhcp_conf();

    # Set default DHCP values only if blank and disabled
    foreach $itf (@ITFs) {
    if ($dhcpsettings{"ENABLE_${itf}"} ne 'on' )
    {
            if (!($dhcpsettings{"DNS1_${itf}"})) { $dhcpsettings{"DNS1_${itf}"} = $netsettings{"${itf}_ADDRESS"} };
        $dhcpsettings{"DEFAULT_LEASE_TIME_${itf}"} = '60';
        $dhcpsettings{"MAX_LEASE_TIME_${itf}"} = '120';
        $dhcpsettings{"GATEWAY_${itf}"} = $netsettings{"${itf}_ADDRESS"};
        $dhcpsettings{"DOMAIN_NAME_${itf}"} = $hostsettings{'DOMAINNAME'};
    }
    }
}

&openpage(_('DHCP configuration'), 1, '');

&openbigbox($errormessage, $warnmessage, $notemessage);
if ($warnNTPmessage)
{
    $warnNTPmessage = "<td>$warnNTPmessage</td>";
}

printf <<EOF

<form enctype='multipart/form-data' method='post' action='$ENV{'SCRIPT_NAME'}'>
<input type='hidden' name='ACTION' value='save' >
EOF
;

# bco, 2014-01-18
if ($dnsmasq == 1) {
&openbox('100%', 'left', 'DHCP');
printf <<END
This machine uses <b>DNSMASQ</b> to serve DHCP leases.
Please modify '/etc/dnsmasq/dnsmasq.conf.tmpl' for changes.
(bco, 2014-01-18)
END
;
&closebox();

# bco, 2014-03-09
&openbox('100%', 'left', 'Current leases ('.strftime("%Y-%m-%d, %H:%M:%S", localtime()).')');
open my $file, "<", $leases or die "$leases: $!";
print '<b><u>Lease expires</td><td><b><u>Mac address</td><td><b><u>IP address</td><td><b><u>Hostname</td></tr><tr><td>';
my $i = 0;
while (my $line = <$file>) {
  @elements = split(/ /,$line);
  $i = 0;
  foreach (@elements) {
    if ($i == 0) {
      print strftime("%Y-%m-%d, %H:%M:%S", localtime($_));
      print '</td><td>';
    } elsif ($i <= 3) {
      print $_;
      print '</td><td>';
    } else {
    }
    $i = $i + 1;
  }
  print '</td></tr><tr><td>';
}
close $file;
&closebox();
} else {
&openbox('100%', 'left', 'DHCP');

foreach $itf (@ITFs) {
    my %checked;
    $checked{'ENABLE'}{0} = '';
    $checked{'ENABLE'}{1} = '';
    $checked{'ENABLE'}{$enable{$itf}} = "checked='checked'";

    $checked{'ONLY_FIXEDLEASE'}{'off'} = '';
    $checked{'ONLY_FIXEDLEASE'}{'on'} = '';
    $checked{'ONLY_FIXEDLEASE'}{$dhcpsettings{"ONLY_FIXEDLEASE_${itf}"}} = "checked='checked'";

    if ($netsettings{"${itf}_DEV"} ne '' ) { # Show only defined interface
        my $lc_itf=lc($itf);
        
        if ($itf eq "BLUE" && $hotspotsettings{'HOTSPOT_ENABLED'} eq "on") { # check if hotspot is enabled on blue
            printf <<END
<table width='100%'>
<tr>
    <td width='25%' class='boldbase'><b><font color="$colour${lc_itf}">%s</font></b></td>
    <td width="75%"class='base'>%s</td>
</tr>
</table>
END
            ,
            $interface_title{$itf},
            _("DHCP configuration is managed by hotspot")
            ;
        }
        else {
            printf <<END
<table width='100%'>
<tr>
    <td width='25%' class='boldbase'><b><font color="$colour${lc_itf}">%s</font></b></td>
    <td class='base'>%s
    <input type='checkbox' name='ENABLE_${itf}' $checked{'ENABLE'}{1} ></td>
    <td width='25%' >&nbsp;</td>
    <td width='25%' ><input class='submitbutton' type='submit' name='submit' value='%s' ></td>
</tr>
</table>
END
            ,
            $interface_title{$itf},
            _('Enabled'),
            _('Save'),
            ;

            print get_folding("folding_$itf", "start", _("Settings"));
        
            printf <<END
<table>
<tr>
    <td width='25%' class='base'>%s</td>
    <td width='25%'><input type='text' name='START_ADDR_${itf}' value='$dhcpsettings{"START_ADDR_${itf}"}' ></td>
    <td width='25%' class='base'>%s</td>
    <td width='25%'><input type='text' name='END_ADDR_${itf}' value='$dhcpsettings{"END_ADDR_${itf}"}' ></td>
</tr>
<tr>
    <td class='base'>%s</td>
    <td><input type='checkbox' name='ONLY_FIXEDLEASE_${itf}' value='on' $checked{'ONLY_FIXEDLEASE'}{'on'} ></td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
</tr>
<tr>
    <td class='base'>%s *</td>
    <td><input type='text' name='DEFAULT_LEASE_TIME_${itf}' value='$dhcpsettings{"DEFAULT_LEASE_TIME_${itf}"}' ></td>
    <td class='base'>%s *</td>
    <td><input type='text' name='MAX_LEASE_TIME_${itf}' value='$dhcpsettings{"MAX_LEASE_TIME_${itf}"}' ></td>
</tr>
<tr>
    <td class='base'>%s</td>
    <td><input type='text' name='DOMAIN_NAME_${itf}' value='$dhcpsettings{"DOMAIN_NAME_${itf}"}' ></td>
    <td class='base'>%s *</td>
    <td><input type='text' name='GATEWAY_${itf}' value='$dhcpsettings{"GATEWAY_${itf}"}' ></td>
</tr>
<tr>
    <td class='base'>%s</td>
    <td><input type='text' name='DNS1_${itf}' value='$dhcpsettings{"DNS1_${itf}"}' ></td>
    <td class='base'>%s</td>
    <td><input type='text' name='DNS2_${itf}' value='$dhcpsettings{"DNS2_${itf}"}' ></td>
</tr>
<tr>
     <td class='base'>%s</td>
     <td><input type='text' name='NTP1_${itf}' value='$dhcpsettings{"NTP1_${itf}"}' ></td>
     <td class='base'>%s</td>
     <td><input type='text' name='NTP2_${itf}' value='$dhcpsettings{"NTP2_${itf}"}' ></td>
</tr>
<tr>
    <td class='base'>%s</td>
    <td><input type='text' name='WINS1_${itf}' value='$dhcpsettings{"WINS1_${itf}"}' ></td>
    <td class='base'>%s</td>
    <td><input type='text' name='WINS2_${itf}' value='$dhcpsettings{"WINS2_${itf}"}' ></td>
</tr>
</table>
END
            ,
            _('Start address'),
            _('End address'),
            _('Allow only fixed leases'),
            _('Default lease time (min)'),
            _('Max lease time (min)'),
            _('Domain name suffix'),
            _('Default Gateway'),
            _('Primary DNS'),
            _('Secondary DNS'),
            _('Primary NTP server'),
            _('Secondary NTP server'),
            _('Primary WINS server address'),
            _('Secondary WINS server address')
            ;
            print get_folding("folding_$itf");
        }
    }# Show only defined interface
}#foreach itf

  printf <<END
<hr size="1" color="#cccccc"/>
<table width='100%'>
  <tr>
    <td><input class='submitbutton' type='submit' name='submit' value='%s' ></td>
    <td>$warnNTPmessage</td>
    <td class='base' width='50%' align='center'>*&nbsp;%s</td>

  </tr>
  <tr>
    <td class='base' colspan="3" align='left'>%s
        <br>
        <textarea name="CUSTOM_GLOBAL" cols="80" rows="5">$custom_global</textarea>
    </td>
  </tr>
</table>
</form>

END
,
_('Save all'),
_('This field is required.'),
_('Custom configuration lines')

;
&closebox();



my %fixchecked;
$fixchecked{'ENABLED'}{'off'} = '';
$fixchecked{'ENABLED'}{'on'} = '';  
$fixchecked{'ENABLED'}{$dhcpsettings{'ENABLED'}} = "checked='checked'";

my $buttontext = _('Add');
if ($dhcpsettings{'KEY1'} ne '') {
    $buttontext = _('Update');
    #&openbox('100%', 'left', _('Edit an existing lease'));
} else {
    #&openbox('100%', 'left', _('Add a new fixed lease'));
}

&openbox('100%', 'left', _('Current fixed leases'), "fixedleases");
my $id = $dhcpsettings{'FIX_MAC'};
$id =~ s/://g;
printf <<END
    <input class="form" type="hidden" name="ID" value="$id" />
END
;

openeditorbox(_("Add a fixed lease"), _("Add a fixed lease"), ($dhcpsettings{'ACTION'} eq 'edit' || scalar(@errormessages) > 0 ? "showeditor" : ""), "fixedleases", @errormessages);

printf <<END
    <table width='100%'>
    <tr>
        <td class='base'>%s *</td>
        <td><input class="form" type='text' name='FIX_MAC' value='$dhcpsettings{'FIX_MAC'}' size='18' /></td>
        <td class='base'>%s *</td>
        <td><input class="form" type='text' name='FIX_ADDR' value='$dhcpsettings{'FIX_ADDR'}' size='18' /></td>
            <td class='base'>%s</td>
            <td><input class="form" type='text' name='FIX_DESCRIPTION' value='$dhcpsettings{'FIX_DESCRIPTION'}' size='18' /></td>
    </tr>
    <tr>
        <td class='base'>%s</td>
        <td><input class="form" type='text' name='FIX_NEXTADDR' value='$dhcpsettings{'FIX_NEXTADDR'}' size='18' /></td>
        <td class='base'>%s</td>
        <td><input class="form" type='text' name='FIX_FILENAME' value='$dhcpsettings{'FIX_FILENAME'}' size='18' /></td>
        <td class='base'>%s</td>
        <td><input class="form" type='text' name='FIX_ROOTPATH' value='$dhcpsettings{'FIX_ROOTPATH'}' size='18' /></td>
    </tr>
    <tr>
        <td class='base' colspan="3" width="50%">%s<input class="form" type='checkbox' name='ENABLED' $fixchecked{'ENABLED'}{'on'} /></td>
        <td class='base' colspan="3" width='50%'>
            <input type='hidden' name='ACTION' value='add' />
        </td>
    </tr>
    </table>
END
,
_('MAC address'),
_('IP address'),
_('Description'),
_('Next address'),
_('Filename'),
_('Root path'),
_('Enabled'),
;

#Edited line number passed until cleared by 'save' or 'remove' or 'new sort order'
print "<input type='hidden' name='KEY1' value='$dhcpsettings{'KEY1'}' >";

&closeeditorbox(_("Add fixed lease"), _("Cancel"), "leasebutton", "fixedleases");

#&closebox();

printf <<END
<table width='100%' cellspacing="0" cellpadding="0" class="ruleslist">
<tr>
    <td width='16%' nowrap="nowrap" class='boldbase'><a href='$ENV{'SCRIPT_NAME'}?FETHER'><b>%s</b></a></td>
    <td width='16%' nowrap="nowrap"  class='boldbase'><a href='$ENV{'SCRIPT_NAME'}?FIPADDR'><b>%s</b></a></td>
    <td width='16%' nowrap="nowrap" class='boldbase'><b>%s</b></td>
    <td width='16%' nowrap="nowrap"  class='boldbase'><b>%s</b></td>
    <td width='8%'  nowrap="nowrap" class='boldbase'><b>%s</b></td>
    <td width='16%' nowrap="nowrap" class='boldbase'><b>%s</b></td>
    <td width='16%' nowrap="nowrap" class='boldbase'><b>%s</b></td>
</tr>
END
,
_('MAC address'),
_('IP address'),
_('Next address'),
_('Filename'),
_('Root path'),
_('Description'),
_("Actions")
;

my $key = 0;
foreach my $line (@current)
{
    my $gif = '';
    my $gdesc = '';
    chomp($line);
    my @temp = split(/\,/,$line);
    
    if ($temp[2] eq "on") {
        $gif = 'on.png';
        $gdesc = _('Enabled (click to disable)');
    }
    else {
        $gif = 'off.png';
        $gdesc = _('Disabled (click to enable)'); 
    }
        
    if ($key % 2) {
        $origcolor = "even"; 
    }
    else {
        $origcolor = "odd"; 
    }
    
    if ($dhcpsettings{'KEY1'} eq $key) {
        $color = "selected";
    }
    else {
        $color = $origcolor;
    }
    
    my %toggle;
    $toggle{'ENABLED'}{'off'} = '';
    $toggle{'ENABLED'}{'on'} = '';  
    $toggle{'ENABLED'}{'$temp[2]'} = "checked='checked'";
    
    my $id = $temp[0];
    $id =~ s/://g; 

        printf <<END
<tr class="$color" id="row_$id">
<td align='center'>$temp[0]</td>
<td align='center'>$temp[1]</td>
<td align='center'>$temp[3]&nbsp;</td>
<td align='center'>$temp[4]&nbsp;</td>
<td align='center'>$temp[5]&nbsp;</td>
<td align='center'>$temp[6]&nbsp;</td>

<td class="actions">
<input type="hidden" class="$id" name="rowcolor" value="$origcolor" />
<form enctype='multipart/form-data' method='post' action='$ENV{'SCRIPT_NAME'}#fixedleases'>
<input class='imagebutton' type='image' name='submit' src='/images/$gif' alt='$gdesc' title='$gdesc'>
<input type='hidden' name='ACTION' value='toggle'>
<input type='hidden' name='KEY1' value='$key'>
<input type='hidden' name='ENABLED' value='$toggle{'ENABLED'}{'on'}'>
</form>
<form enctype='multipart/form-data' method='post' action='$ENV{'SCRIPT_NAME'}#fixedleases'>
<input type='hidden' name='ACTION' value='edit' />
<input class='imagebutton' type='image' name='submit' src='/images/edit.png' alt='%s' title='%s'>
<input type='hidden' name='KEY1' value='$key' />
</form>
<form enctype='multipart/form-data' method='post' action='$ENV{'SCRIPT_NAME'}#fixedleases'>
    <input type='hidden' name='ACTION' value='remove'>
<input class='imagebutton' type='image' name='submit' src='/images/delete.png' alt='%s' title='%s'>
<input type='hidden' name='KEY1' value='$key'>
</form>
</td>
</tr>
END
,
_('Enable or Disable'),
_('Edit'),
_('Edit'),
_('Remove'),
_('Remove')

;
    $key++;
}

print "</table>";

# If the fixed lease file contains entries, print Key to action icons
if ( $key > 0) {
printf <<END
<table cellpadding="0" cellspacing="0" class="list-legend">
<tr>
    <td class='boldbase'><b>%s:</b></td>
    <td>&nbsp; <img src='/images/on.png' alt='%s' ></td>
    <td class='base'>%s</td>
    <td>&nbsp; &nbsp; <img src='/images/off.png' alt='%s' /></td>
    <td class='base'>%s</td>
    <td>&nbsp; &nbsp; <img src='/images/edit.png' alt='%s' ></td>
    <td class='base'>%s</td>
    <td>&nbsp; &nbsp; <img src='/images/delete.png' alt='%s' ></td>
    <td class='base'>%s</td>
</tr>
</table>
END
,
_('Legend'),
_('Enabled (click to disable)'),
_('Enabled (click to disable)'),
_('Disabled (click to enable)'),
_('Disabled (click to enable)'),
_('Edit'),
_('Edit'),
_('Remove'),
_('Remove')

;
}

&closebox();

foreach $itf (@ITFs) {
    if ($enable{$itf}) {
    &PrintActualLeases;
    last;             #Print one time only for all interfaces
    };
}

}#if bco

&closebigbox();

&closepage();


sub fixedleasesort {
    if (rindex ($dhcpsettings{'SORT_FLEASELIST'},'Rev') != -1)
    {
        $qs=substr ($dhcpsettings{'SORT_FLEASELIST'},0,length($dhcpsettings{'SORT_FLEASELIST'})-3);
    if ($qs eq 'FIPADDR') {
        @a = split(/\./,$entries{$a}->{$qs});
        @b = split(/\./,$entries{$b}->{$qs});
        ($b[0]<=>$a[0]) ||
        ($b[1]<=>$a[1]) ||
        ($b[2]<=>$a[2]) ||
        ($b[3]<=>$a[3]);
    }else {
        $entries{$b}->{$qs} cmp $entries{$a}->{$qs};
    }
    }
    else #not reverse
    {
    $qs=$dhcpsettings{'SORT_FLEASELIST'};
    if ($qs eq 'FIPADDR') {
        @a = split(/\./,$entries{$a}->{$qs});
        @b = split(/\./,$entries{$b}->{$qs});
        ($a[0]<=>$b[0]) ||
        ($a[1]<=>$b[1]) ||
        ($a[2]<=>$b[2]) ||
        ($a[3]<=>$b[3]);
    }else {
        $entries{$a}->{$qs} cmp $entries{$b}->{$qs};
    }
    }
}
# Sort the "current" array according to choices
sub sortcurrent
{
    #Use an associative array (%entries)
    my $key = 0;
    foreach my $line (@current)
    {
        $line =~ /^(.*),(.*),(.*,.*,.*,.*,.*)$/; # 00:X:X:X:X:X,10.0.0.1,on,,,,
        $record = {};                           # create a reference to empty hash
        if ( $3 ) {
            @record = ('FETHER',$1,'FIPADDR',$2,'DATA',$3);
        } else {
            $line =~ /^(.*),(.*),(.*,.*,.*,.*)$/; # 00:XX:XX:XX:XX:XX,10.0.0.1,on,,,
            $data = $3 . ",";
            @record = ('FETHER',$1,'FIPADDR',$2,'DATA',$data);
        }
        %{$record} = @record;                   # populate that hash with @record
        $entries{$record->{FIPADDR}} = $record; # add this to a hash of hashes
    }
    
    open(FILE, ">$filename") or die 'Unable to open fixed lease file.';
    foreach my $entry ( sort fixedleasesort keys %entries)
    {
        print FILE "$entries{$entry}->{FETHER},$entries{$entry}->{FIPADDR},$entries{$entry}->{DATA}\n";
    }
    close(FILE);

    # Reload sorted  @current
    open (FILE, "$filename");
    @current = <FILE>;
    close (FILE);
    undef (%entries);  #This array is reused latter. Clear it.
}
                            
# Build the configuration file mixing  settings and lease
sub buildconf {
    system '/usr/local/bin/restartdhcp --force';
}


