#!/usr/bin/env perl
#-*- Mode: perl; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
#
# Functions for dhcp server configuration
#
# Copyright (C) 2001 Ximian, Inc.
#
# Authors: Chema Celorio <chema@ximian.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Library General Public License as published
# by the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.

$SCRIPTSDIR = "/usr/X11R6/share/setup-tool-backends/scripts";
if ($SCRIPTSDIR =~ /^@scriptsdir[@]/)
{
    $SCRIPTSDIR = ".";
    $DOTIN = ".in";
}

require "$SCRIPTSDIR/general.pl$DOTIN";
require "$SCRIPTSDIR/file.pl$DOTIN";
require "$SCRIPTSDIR/parse.pl$DOTIN";
require "$SCRIPTSDIR/replace.pl$DOTIN";
require "$SCRIPTSDIR/service.pl$DOTIN";
require "$SCRIPTSDIR/util.pl$DOTIN";
require "$SCRIPTSDIR/xml.pl$DOTIN";
require "$SCRIPTSDIR/tokenizer.pl$DOTIN";

## ------------------------ Get ---------------------------------------------
sub gst_dhcpd_get_host
{
    my ($in, $out) = @_;
    my ($mac_address, $next_server, $ip);
    my %host;
    my $comment = &gst_dhcpd_get_host_comment ($out);
    my $host_name = &gst_tokenize_get_token ($in, $out);
    
    &gst_tokenize_verify_token ($in, "{", $out);
    
    while (defined (my $token = &gst_tokenize_get_token ($in, $out))) {
        if ("\}" eq $token) {
            last;
        }
        elsif ("hardware" eq $token) {
            &gst_tokenize_verify_token ($in, "ethernet", $out);
            $mac_address = &gst_tokenize_get_token ($in, $out);
            &gst_tokenize_verify_token ($in, ";", $out);
        }
        elsif ("fixed-address" eq $token) {
            $ip = &gst_tokenize_get_token ($in, $out);
            &gst_tokenize_verify_token ($in, ";", $out);
        }
        elsif ("next-server" eq $token) {
            &gst_tokenize_skip_till ($in, ";", $out);
        }
        else {
            &gst_tokenize_warning ("Unexpected token \"$token\"");
            &gst_tokenize_skip_till ($in, ";", $out);
        }
    }

    $host{"host_name"}   = $host_name    if (defined $host_name);
    $host{"mac_address"} = $mac_address  if (defined $mac_address);
    $host{"next_server"} = $next_server  if (defined $next_server);
    $host{"ip"} = $ip                    if (defined $ip);
    $host{"comment"} = $comment          if (defined $comment);

    return %host;
}

sub gst_dhcpd_get_range
{
    my ($in, $out) = @_;
    my $size = 0;
    my @tokens;
    my %hash;
    my $token;

    # range is tricky because it can contain from 1 to 3 tokens
    #
    # range a;                 start = a, end = a, bootp = FALSE
    # range a b;               start = a, end = b, bootp = FALSE
    # range dynamic-bootp a b; start = a, end = b, bootp = TRUE
    # range dynamic-bootp a;   start = a, end = a, bootp = TRUE

    $token = &gst_tokenize_get_token_till ($in, $out, ";");

    # bootp for this range ?
    $_ = $token;
    if (/^dynamic-bootp /) {
        $token = $'; # remove dynamic-bootp from token        
        $hash{"bootp"} = 1;
    } else {
        $hash{"bootp3"} = 0;
    }

    # If it does not contain a whitespace duplicate the value
    # since if max is ommited, max = min
    $_ = $token;
    if (not m/ /) {
        $token .= " " . $token 
    }

    # Get the start and end token
    @tokens = split (' ', $token);
    $hash{"start"} = $tokens[0];
    $hash{"end"}   = $tokens[1];
    my $empty      = $tokens[2]; # We should not have any tokens left

    if (defined ($empty)) {
        &gst_tokenize_warning ("Unexpected token $empty");
    }
    
    return %hash;
}

sub gst_dhcpd_get_subnet
{
    my ($in, $out) = @_;
    my %options;
    my (%ranges, %j, %r_1);
    my (%hosts, %host_1);

    my @known_options = qw(domain-name routers);
    my @ignore_options = qw(nis-domain time-offset ntp-servers subnet-mask);    

    $options{"ip"}      = &gst_tokenize_get_token ($in, $out);
    &gst_tokenize_verify_token ($in, "netmask", $out);
    $options{"netmask"} =  &gst_tokenize_get_token ($in, $out);
    &gst_tokenize_verify_token ($in, "{", $out);
    
    while (defined (my $token = &gst_tokenize_get_token ($in, $out))) {
#        printf STDERR "Token $token\n";
        if ("option" eq $token) {
            my (%h1,%h2);
            my $value     = &gst_tokenize_get_token ($in, $out);
            my $pair      = &gst_tokenize_get_token ($in, $out);
            $pair =~ s/\"//g;

  #          printf STDERR "Value $value\n";
            
            if ($value eq "domain-name-servers") {
                my $dns_num = 1;
                $options{"dns1"}=$pair;
                if ("," eq ($token = &gst_tokenize_get_token ($in, $out))) {
                    $token = &gst_tokenize_get_token ($in, $out);
                    $options{"dns2"}=$token;
                    while (";" ne ($token = &gst_tokenize_get_token ($in, $out))){};
                    # FIXME
#                    @$in = (pop @$out, @$in);
                }
            }
            elsif (defined &gst_array_find_index (\@known_options, $value)) {
 #               printf STDERR "in array\n";
                # remove elements as we read them to avoid duplicates
                @known_options = grep ($_ ne $value, @known_options);
                $options{$value}=$pair;
                &gst_tokenize_verify_token ($in, ";", $out);
            }
            elsif (defined &gst_array_find_index (\@ignore_options, $value)) {
                &gst_tokenize_advance_till ($in, ";", $out);
            }
            else {
                printf STDERR "Unknown option : $value (170)\n";
                if ($token ne ";") {
                    &gst_tokenize_advance_till ($in, ";", $out);
#                    &gst_tokenize_verify_token ($in, ";", $out);
#                    @$in = (pop @$out, @$in);
                }
            }
        }
        elsif ("range" eq $token) {
            my (%range) = &gst_dhcpd_get_range ($in, $out);
            my $name = $range{"start"};
            $ranges{$name} = \%range;
        }
        elsif ("host" eq $token) {
            my (%host) = &gst_dhcpd_get_host ($in, $out);
            my $name = $host{"host_name"};
            $hosts{$name}= \%host;
        }
        elsif ("default-lease-time" eq $token) {
            $token = &gst_tokenize_get_token ($in, $out);
#           $options{"default-lease-time"}=$token;
            $token = &gst_tokenize_get_token ($in, $out);
        }
        elsif ("max-lease-time" eq $token) {
            $token = &gst_tokenize_get_token ($in, $out);
#           $options{"max-lease-time"}=$token;
            $token = &gst_tokenize_get_token ($in, $out);
        }
        elsif ("}" eq $token) {
            my $resp;

            $resp{"options"}=\%options;
            if (scalar (%ranges)) {
                $resp{"ranges"}=\%ranges;
            }
            if (scalar (%hosts) gt 0) {
                $resp{"hosts"}=\%hosts;
            }
            return %resp;
        }
        else {
            &gst_tokenize_warning ("Unexpected token \"$token\" (205)");
            &gst_tokenize_skip_till ($in, ";", $out);
        }
    }

    return undef;
}

sub gst_dhcpd_get_subnets
{
    my ($fname) = @_;
    my (%subnets);
    my $in;
    my @out_array = "";
    my $out = \@out_array;

    $in = &gst_tokenize ($fname);

    while (defined (my $token = &gst_tokenize_get_token ($in, $out))) {
        if ("subnet" eq $token) {
            my %subnet = &gst_dhcpd_get_subnet ($in, $out);
            my $options = $subnet{"options"};
            my $ip = $$options{"ip"};
            $subnets{$ip} = \%subnet;
        }
        elsif ("group" eq $token) {
            &gst_tokenizer_error ("Groups not supported\n");
        }
        elsif ("shared-network" eq $token) {
            &gst_tokenizer_error ("Shared networks not supported\n");
        }
    }

    return \%subnets;
}

## ------------------------ XML Parsing --------------------------------------
sub gst_dhcpd_xml_parse_host
{
  my ($tree, $hosts) = @_;
  my (%hash);

  shift @$tree;
  
  while ($elem = shift @$tree)
  {
    $hash{$elem} = &gst_xml_get_pcdata (shift @$tree);
  }

  $name = $hash{"host_name"};
  $$hosts{$name} = \%hash;
}
        
sub gst_dhcpd_xml_parse_range
{
  my ($tree, $hosts) = @_;
  my (%hash);

  shift @$tree;
  
  while ($elem = shift @$tree)
  {
    $hash{$elem} = &gst_xml_get_pcdata (shift @$tree);
  }

  $name = $hash{"start"};
  $$hosts{$name} = \%hash;
}

sub gst_dhcpd_xml_parse_subnet
{
  my ($tree, $subnets) = @_;
  my ($elem, %subnet, %options);
  my (%hosts, %ranges);

  shift @$tree;
  
  while ($elem = shift @$tree)
  {
    if    ($elem eq "ip")          { $options{"ip"}          = &gst_xml_get_pcdata (shift @$tree); }
    elsif ($elem eq "netmask")     { $options{"netmask"}     = &gst_xml_get_pcdata (shift @$tree); }
    elsif ($elem eq "domain-name") { $options{"domain-name"} = &gst_xml_get_pcdata (shift @$tree); }
    elsif ($elem eq "dns1")        { $options{"dns1"}        = &gst_xml_get_pcdata (shift @$tree); }
    elsif ($elem eq "dns2")        { $options{"dns2"}        = &gst_xml_get_pcdata (shift @$tree); }
    elsif ($elem eq "routers")     { $options{"routers"}     = &gst_xml_get_pcdata (shift @$tree); }

    elsif ($elem eq "host")        { &gst_dhcpd_xml_parse_host  (shift @$tree, \%hosts); }
    elsif ($elem eq "range")       { &gst_dhcpd_xml_parse_range (shift @$tree, \%ranges); }
    
    else  { &gst_report ("xml_unexp_tag", $elem); shift @$tree; }
  }

  $$subnet{"options"} = \%options unless scalar keys %options == 0;
  $$subnet{"hosts"}   = \%hosts   unless scalar keys %hosts   == 0;
  $$subnet{"ranges"}  = \%ranges  unless scalar keys %ranges  == 0;

  $name = $options{"ip"};

  if (not defined ($name)) {
      printf STDERR "Fatal error, no ip was provided for a subnet\n";
      printf STDERR "Improve error reporting (well, investigate current methods)\n";
      exit;
  }
      
  $$subnets{$name} = $subnet;

  return;
}

## ------------------------ Set ---------------------------------------------
sub gst_dhcpd_replace_subnets
{
  my ($file, $old_values, $new_subnets_ref) = @_;
  my (%old_subnets, %new_subnets);
  my (@remove_list, @add_list, @matching_list);

  %old_subnets = %{$$old_values{"subnets"}};
  %new_subnets = %{$new_subnets_ref};

  $matching_list = &gst_dhcpd_subnets_match (\%old_subnets, \%new_subnets);
  &gst_dhcpd_subnets_match_dump ($matching_list);

  %m = %$matching_list;
  foreach $key (keys %m) {
      $a=$m{$key};
      &gst_dhcpd_replace_subnet ($file, $key, $m{$key});
  }
}

sub gst_dhcpd_skip_block
{
    my ($in, $out) = @_;
    my $token;

    while (defined ($token = &gst_tokenize_get_token ($in, $out))) {
        if ($token eq "}") {
            return;
        }
        if ($token eq "{") {
            &gst_dhcpd_skip_block ($in, $out);
        }
    }

}

sub gst_dhcpd_get_host_comment
{
    my ($out) = @_;
    my $token, $line, $comment = "";

    $line = @$out[-2];

    $_ = $line;
    if (/\s*\#/) {
        $comment = $';
        chomp ($comment);
        $comment =~ s/\s*//;
        return $comment;
    }
    
    return undef;
}

sub gst_dhcpd_add_host
{
    my ($in, $out, $host, $subnet) = @_;
    my $ws, $ws2;

    # FIXME, the indentation can be different, found the whitespace neede
    # for now, hardcode $ws
    $ws = "\t";
    $ws2 = $ws . "\t";

    # Add the host
    &gst_tokenize_append_token ($out, $ws . "\n"); 
    if (defined ($$host {"comment"})) {
        &gst_tokenize_append_token ($out, $ws  . "# " . $$host {"comment"} . "\n");
    }
    &gst_tokenize_append_token ($out, $ws  . "host " . $$host {"host_name"} . " {\n");
    if (defined ($$host {"mac_address"})) {
        &gst_tokenize_append_token ($out, $ws2 . "hardware ethernet " . $$host {"mac_address"} . ";\n");
    }
    if (defined (my $ip = $$host {"ip"})) {
        &gst_tokenize_append_token ($out, $ws2 . "fixed-address "     . $$host {"ip"} . ";\n");
    }
    &gst_tokenize_append_token ($out, $ws  . "}\n"); 
}

sub gst_dhcpd_replace_host
{
    my ($in, $out, $hosts) = @_;
    my $hostname;
    my $new_values; # array that contains the host information

    $comment = &gst_dhcpd_get_host_comment ($out);
    $hostname = &gst_tokenize_get_token ($in, $out);
    $new_values = $$hosts{$hostname};

    # Delete this host ?
    if (not defined $new_values) {
        &gst_tokenize_undo ($in, $out, 2); # Return the hostname & "host"
        $_ = @$out[-1];
        pop (@$out) if (/\s*\#/);  # remove the comment ?
        $_ = @$out[-1];
        pop (@$out) if (/\s*\n$/); # remove the newline ?
        &gst_tokenize_skip_till ($in, "}");
        return;
    }

    # Replace the comment (or add it)
    my $new_comment = $$new_values{"comment"};
    if (defined ($comment)) {
        $$out [-3] =~ s/\#( |)$comment/\# $new_comment/;
    }
    elsif (defined $new_comment) {
        # Insert a comment
        &gst_tokenize_undo ($in, $out, 2);
        &gst_tokenize_append_token ($out, "\t# " . $new_comment . "\n");
        &gst_tokenize_get_token ($in, $out);
        &gst_tokenize_get_token ($in, $out);
    }

    &gst_tokenize_verify_token ($in, "{", $out);

    # Flags so that we know if we need to add an element or not
    my $hardware_ethernet = 0;
    my $fixed_address = 0;
    while (defined (my $token = &gst_tokenize_get_token ($in, $out))) {
        if ("hardware" eq $token) {
            my $mac = $$new_values{"mac_address"};
            if ((defined $mac) && ($mac ne "")) {
                &gst_tokenize_verify_token ($in, "ethernet", $out);
                &gst_tokenize_replace_token ($out, "ethernet"); # clean if broken
                &gst_tokenize_get_token ($in, $out);
                &gst_tokenize_replace_token ($out, $mac);
                &gst_tokenize_verify_token ($in, ";", $out);
            } else {
                &gst_tokenize_undo ($in, $out, 1);
                &gst_tokenize_skip_till ($in, ";");
            }
            $hardware_ethernet = 1;
        }
        elsif ("fixed-address" eq $token) {
            my $ip = $$new_values{"ip"};
            if ((defined $ip) && ($ip ne "")) {
                &gst_tokenize_get_token ($in, $out); # discard
                &gst_tokenize_replace_token ($out, $ip);
                &gst_tokenize_verify_token ($in, ";", $out);
            } else {
                &gst_tokenize_undo ($in, $out, 1);
                &gst_tokenize_skip_till ($in, ";");
            }
            $fixed_address = 1;
        }
        elsif ("}" eq $token) {
            last;
        }
        else {
            &gst_tokenize_advance_till ($in, ";", $out);
        }
    }

    &gst_tokenize_undo ($in, $out);
    
    # Now add items that where not found
    my $ws = "\t\t";
    if (($fixed_address eq 0) && (defined (my $ip = $$new_values {"ip"}))) {
        &gst_tokenize_append_token ($out, $ws . "fixed-address " . $ip . ";\n");
    }
    if (($hardware_ethernet eq 0) && (defined (my $mac = $$new_values {"mac_address"}))) {
        &gst_tokenize_append_token ($out, $ws . "hardware ethernet " . $mac . ";\n");
    }

    &gst_tokenize_get_token ($in, $out);
    
    delete $$hosts{$hostname};
}

sub gst_dhcpd_replace_range
{
    my ($in, $out, $ranges) = @_;
    my $range;

    # FIXME, Only support one range for now
    @ranges_keys = keys %$ranges;
    $range = $$ranges{@ranges_keys[0]};

    if ($$range{"bootp"}) {
        &gst_tokenize_append_token ($out, " dynamic-bootp");
    }
    &gst_tokenize_append_token ($out, " " . $$range{"start"});
    &gst_tokenize_append_token ($out, " " . $$range{"end"} );
    &gst_tokenize_append_token ($out, ";\n");
    &gst_tokenize_skip_till ($in, ";");
    
}

sub gst_tokenize_replace_dns
{
    my ($in, $out, $options) = @_;
    my $token;
    my $dns1 = $$options{"dns1"};
    my $dns2 = $$options{"dns2"};

    # Remove this item ?
    if ($dns1 eq undef && $dns2 eq undef) {
        &gst_tokenize_undo ($in, $out, 2);
        &gst_tokenize_skip_till ($in, ";");
        &gst_tokenize_undo ($in, $out, 1);
        return;
    }
    
    #
    # Dns is tricky because the file has a list of servers, our xml has
    # dns1 and dns2, maybe we should change the xml ?
    # 
    $token = &gst_tokenize_get_token ($in, $out);
    &gst_tokenize_replace_token ($out, $dns1);

    $token = &gst_tokenize_get_token ($in, $out);
    
    # If we already have multiple DNS's
    if ($token eq ",") {
        $token = &gst_tokenize_get_token ($in, $out);
        if (defined $dns2) {
            &gst_tokenize_replace_token ($out, $dns2);
            &gst_tokenize_verify_token ($in, ";", $out);
        } else {
            &gst_tokenize_remove_token ($out, 2); # Remove "," and dns2
            &gst_tokenize_skip_till    ($in, ";");
            &gst_tokenize_append_token ($out, ";\n"); # skip till ; will skip ;
        }
    }
    # If we only had one server before, do we need to add dns2 ?
    elsif (";" eq $token) {
        if (defined $dns2) {
            my $temp = pop (@$out);
            &gst_tokenize_append_token ($out, ", ");
            &gst_tokenize_append_token ($out, $dns2);
            &gst_tokenize_append_token ($out, $temp);
        }
    } else {
        &gst_tokenize_warning ("Unexpected token $token\n");
        &gst_tokenize_advance_till ($in, ";", $out);
    }

    # Reverse the last token which was ";" so that
    # we leave it there for _verify ($in, ";",... to pass
    &gst_tokenize_undo ($in, $out);
    
    return;
}

sub gst_dhcpd_replace_subnet_real
{
    my ($in, $out, $new_values, $subnet) = @_;
    my $options, $hosts, $ranges;
    my @ignore_options = qw(time-offset ntp-servers);    
    my @ignore_keywords = qw(default-lease-time max-lease-time);
    my $range_replaced = 0;

    $options = $$new_values{"options"};
    $hosts   = $$new_values{"hosts"};
    $ranges  = $$new_values{"ranges"};

    while (defined (my $token = &gst_tokenize_get_token ($in, $out))) {
#        printf STDERR "Token :: -->$token<--\n";
        if ("option" eq $token) {
            $token = &gst_tokenize_get_token ($in, $out);
#            printf STDERR "Option                 $token\n";
            if ("domain-name" eq $token || "nis-domain" eq $token) {
                $token = &gst_tokenize_get_token ($in, $out);
                &gst_tokenize_replace_token ($out, "\"" . $$options{"domain-name"} . "\"");
            }
            elsif ("routers" eq $token) {
                $token = &gst_tokenize_get_token ($in, $out);
                &gst_tokenize_replace_token ($out, $$options{"routers"});
            }
            elsif ("subnet-mask" eq $token) {
                $token = &gst_tokenize_get_token ($in, $out);
                &gst_tokenize_replace_token ($out, $$options{"netmask"});
            }
            elsif ("domain-name-servers" eq $token) {
                &gst_tokenize_replace_dns ($in, $out, $options);
            }
            elsif (defined &gst_array_find_index (\@ignore_options, $value)) {
                &gst_tokenize_advance_till ($in, ";", $out);
                &gst_tokenize_undo ($in, $out, 1);
            }
            else
            {
                printf STDERR "--- UNKNOWN option : $token\n";
                &gst_tokenize_advance_till ($in, ";", $out);
                &gst_tokenize_undo ($in, $out, 1);
            }
            &gst_tokenize_verify_token ($in, ";", $out);
        }
        elsif ("netmask" eq $token) {
            # This is outside of the `{`
            $token = &gst_tokenize_get_token ($in, $out);
            &gst_tokenize_replace_token ($out, $$options{"netmask"});
            &gst_tokenize_verify_token ($in, "{", $out);
        }
        elsif ("range" eq $token) {
            if (not $range_replaced) {
                &gst_dhcpd_replace_range ($in, $out, $ranges);
                $range_replaced = 1;
            }
        }
        elsif ("host" eq $token) {
            &gst_dhcpd_replace_host ($in, $out, $hosts);
        }
        elsif (defined &gst_array_find_index (\@ignore_keywords, $value)) {
            &gst_tokenize_advance_till ($in, ";", $out);
        }
        elsif ("}" eq $token) {
            last;
        } else {
            printf STDERR "Unrecognized Token :: -- $token (545)\n";
            &gst_tokenize_advance_till ($in, ";", $out);
        }             
    }

    # What is out, is now our input
    &gst_tokenize_undo ($in, $out, 1);

    foreach $key (keys %$hosts) {
        &gst_dhcpd_add_host ($in, $out, $$hosts{$key}, $subnet);
    }
        
}

sub gst_dhcpd_replace_subnet
{
  my ($file, $subnet, $new_values) = @_;
  my $in;
  my @out_array = "";
  my $out = \@out_array;
  
  $in = &gst_tokenize ($file);

  &gst_file_buffer_save ($out, $file . ".1");
  
  while (defined (my $token = &gst_tokenize_get_token ($in, $out))) {

      if ("subnet" eq $token) {
          $token = &gst_tokenize_get_token ($in, $out);
          if ($token ne $subnet) {
              &gst_tokenize_verify_token ($in, "netmask");
              $token1 = &gst_tokenize_get_token ($in, $out); # 255.255.255.0
              &gst_tokenize_verify_token ($in, "{");
              &gst_dhcpd_skip_block ($in, $out);
          } else {
              &gst_dhcpd_replace_subnet_real ($in, $out, $new_values, $subnet);
          }
      }
  }

#  &gst_file_buffer_save ($out, $file . ".new");
  &gst_file_buffer_save ($out, $file);
}

sub gst_dhcpd_subnets_match_dump
{
  my ($ref) = @_;
  my %matching_list = %$ref;

#  printf STDERR "\n\nDumping match list\n";
  foreach $needle (keys %matching_list) {
      $a = $matching_list{$needle};
#      printf STDERR "      Value:$needle Pair:$a\n";
  }
#  printf STDERR "\n\n";
  
}

sub gst_dhcpd_subnets_match
{
  my ($old_subnets_ref, $new_subnets_ref) = @_;
  my (%matching_list);
  my (%old_subnets, %new_subnets);

  %old_subnets = %$old_subnets_ref;
  %new_subnets = %$new_subnets_ref;

  $num_old = scalar keys %old_subnets;
  $num_new = scalar keys %new_subnets;
  # Here we can write a smart mathing system
  # For now do any matching for 1 old 1 new to develop
  # the replacing code
#  if (($num_old ne 1) || ($num_new) ne 1) {
#      printf STDERR "Can only replace 1-1\n";
#      exit;
#  }

  @a = keys %old_subnets;
  @b = keys %new_subnets;

#  printf STDERR "B zero is ->" . $b[0] . "<-\n";
  
  $matching_list {$b[0]} = $new_subnets{$b[0]};

  return \%matching_list;
}


## ------------------------- Parsing tables ---------------------------------

sub gst_dhcpd_conf_get_parse_table
{
  my %dist_map =
  (
   "redhat-7.0"   => "redhat-7.0",
   "redhat-7.1"   => "redhat-7.0",
   );

  my %dist_tables =
      (
       "redhat-7.0" =>
       {
         fn =>
         {
             DHCPD_CONF => "/etc/dhcpd.conf",
             DHCPD_SERVICE => "dhcpd",
         },
         table =>
            [
              [ "active",      \&gst_service_sysv_get_status, DHCPD_SERVICE ],
              [ "installed",   \&gst_service_sysv_installed,  DHCPD_SERVICE ],
              [ "configured",  \&gst_file_exists,             DHCPD_CONF    ],
              [ "subnets",     \&gst_dhcpd_get_subnets,       DHCPD_CONF],
            ]
              }
       );

  my $dist = $dist_map {$gst_dist};
  return %{$dist_tables{$dist}} if $dist;

  &gst_report ("platform_no_table", $gst_dist);
  return undef;
}

sub gst_dhcpd_conf_get
{
  my %dist_attrib;
  my $hash;

  %dist_attrib = &gst_dhcpd_conf_get_parse_table ();

  $hash = &gst_parse_from_table ($dist_attrib{"fn"},
                                 $dist_attrib{"table"});
  return $hash;
}

sub gst_dhcpd_conf_get_replace_table
{
  my %dist_map =
  (
   "redhat-7.0"   => "redhat-7.0",
   "redhat-7.1"   => "redhat-7.0",
   );

  my %dist_tables =
      (
       "redhat-7.0" =>
       {
         fn =>
         {
           DHCPD_CONF    => "/etc/dhcpd.conf",
           DHCPD_SERVICE => "dhcpd",
         },
         table =>
             [
              [ "subnets", \&gst_dhcpd_replace_subnets,    [DHCPD_CONF, OLD_HASH] ],
#              [ "active",  \&gst_service_sysv_set_status, [65, DHCPD_SERVICE] ]
             ]
                },
       );

  my $dist = $dist_map {$gst_dist};
  return %{$dist_tables{$dist}} if $dist;

  &gst_report ("platform_no_table", $gst_dist);
  return undef;
}


sub gst_dhcpd_conf_set
{
  my ($values_hash) = @_;
  my (%dist_attrib, $old_hash);
  my $res;

  %dist_attrib = &gst_dhcpd_conf_get_replace_table ();

  $old_hash = &gst_dhcpd_conf_get ();
  $res = &gst_replace_from_table ($dist_attrib{"fn"}, $dist_attrib{"table"},
                                  $values_hash, $old_hash);

  return $res;
}

1;

