8b41d83
#!/usr/bin/perl -w
8b41d83
8b41d83
# Brian Masney <masneyb@ntelos.net>
8b41d83
# To use this script, set your base DN below. Then run 
8b41d83
# ./dhcpd-conf-to-ldap.pl < /path-to-dhcpd-conf/dhcpd.conf > output-file
8b41d83
# The output of this script will generate entries in LDIF format. You can use
8b41d83
# the slapadd command to add these entries into your LDAP server. You will
8b41d83
# definately want to double check that your LDAP entries are correct before
8b41d83
# you load them into LDAP.
8b41d83
8b41d83
# This script does not do much error checking. Make sure before you run this
8b41d83
# that the DHCP server doesn't give any errors about your config file
8b41d83
8b41d83
# FailOver notes:
8b41d83
#   Failover is disabled by default, since it may need manually intervention.
8b41d83
#   You can try the '--use=failover' option to see what happens :-)
8b41d83
#
8b41d83
#   If enabled, the failover pool references will be written to LDIF output.
8b41d83
#   The failover configs itself will be added to the dhcpServer statements
8b41d83
#   and not to the dhcpService object (since this script uses only one and
8b41d83
#   it may be usefull to have multiple service containers in failover mode).
8b41d83
#   Further, this script does not check if primary or secondary makes sense,
8b41d83
#   it simply converts what it gets...
8b41d83
8b41d83
use Net::Domain qw(hostname hostfqdn hostdomain);
8b41d83
use Getopt::Long;
8b41d83
8b41d83
my $domain = hostdomain();           # your.domain
8b41d83
my $basedn = "dc=".$domain;
8b41d83
   $basedn =~ s/\./,dc=/g;           # dc=your,dc=domain
8b41d83
my $server = hostname();             # hostname (nodename)
8b41d83
my $dhcpcn = 'DHCP Config';          # CN of DHCP config tree
8b41d83
my $dhcpdn = "cn=$dhcpcn, $basedn";  # DHCP config tree DN
8b41d83
my $second = '';                     # secondary server DN / hostname
8b41d83
my $i_conf = '';                     # dhcp.conf file to read or stdin
8b41d83
my $o_ldif = '';                     # output ldif file name or stdout
8b41d83
my @use    = ();                     # extended flags (failover)
8b41d83
8b41d83
sub usage($;$)
8b41d83
{
8b41d83
  my $rc = shift;
8b41d83
  my $err= shift;
8b41d83
8b41d83
  print STDERR "Error: $err\n\n" if(defined $err);
8b41d83
  print STDERR <<__EOF_USAGE__;
8b41d83
usage: 
8b41d83
  $0 [options] < dhcpd.conf > dhcpd.ldif
8b41d83
8b41d83
options:
8b41d83
8b41d83
  --basedn  "dc=your,dc=domain"        ("$basedn")
8b41d83
8b41d83
  --dhcpdn  "dhcp config DN"           ("$dhcpdn")
8b41d83
8b41d83
  --server  "dhcp server name"         ("$server")
8b41d83
8b41d83
  --second  "secondary server or DN"   ("$second")
8b41d83
8b41d83
  --conf    "/path/to/dhcpd.conf"      (default is stdin)
8b41d83
  --ldif    "/path/to/output.ldif"     (default is stdout)
8b41d83
8b41d83
  --use     "extended features"        (see source comments)
8b41d83
__EOF_USAGE__
8b41d83
  exit($rc);
8b41d83
}
8b41d83
8b41d83
8b41d83
sub next_token
8b41d83
{
8b41d83
  local ($lowercase) = @_;
8b41d83
  local ($token, $newline);
8b41d83
8b41d83
  do 
8b41d83
    {
8b41d83
      if (!defined ($line) || length ($line) == 0)
8b41d83
        {
8b41d83
          $line = <>;
8b41d83
          return undef if !defined ($line);
8b41d83
          chop $line;
8b41d83
          $line_number++;
8b41d83
          $token_number = 0;
8b41d83
        }
8b41d83
8b41d83
      $line =~ s/#.*//;
8b41d83
      $line =~ s/^\s+//;
8b41d83
      $line =~ s/\s+$//;
8b41d83
    }
8b41d83
  while (length ($line) == 0);
8b41d83
8b41d83
  if (($token, $newline) = $line =~ /^(.*?)\s+(.*)/)
8b41d83
    {
8b41d83
      if ($token =~ /^"/) {
8b41d83
       #handle quoted token
8b41d83
       if ($token !~ /"\s*$/)
8b41d83
       {
8b41d83
         ($tok, $newline)  = $newline =~ /([^"]+")(.*)/;
8b41d83
         $token .= " $tok";
8b41d83
        }
8b41d83
      }
8b41d83
      $line = $newline;
8b41d83
    }
8b41d83
  else
8b41d83
    {
8b41d83
      $token = $line;
8b41d83
      $line = '';
8b41d83
    }
8b41d83
  $token_number++;
8b41d83
8b41d83
  $token =~ y/[A-Z]/[a-z]/ if $lowercase;
8b41d83
8b41d83
  return ($token);
8b41d83
}
8b41d83
8b41d83
8b41d83
sub remaining_line
8b41d83
{
8b41d83
  local ($block) = shift || 0;
8b41d83
  local ($tmp, $str);
8b41d83
8b41d83
  $str = "";
8b41d83
  while (defined($tmp = next_token (0)))
8b41d83
    {
8b41d83
      $str .= ' ' if !($str eq "");
8b41d83
      $str .= $tmp;
8b41d83
      last if $tmp =~ /;\s*$/;
8b41d83
      last if($block and $tmp =~ /\s*[}{]\s*$/);
8b41d83
    }
8b41d83
8b41d83
  $str =~ s/;$//;
8b41d83
  return ($str);
8b41d83
}
8b41d83
8b41d83
8b41d83
sub
8b41d83
add_dn_to_stack
8b41d83
{
8b41d83
  local ($dn) = @_;
8b41d83
8b41d83
  $current_dn = "$dn, $current_dn";
8b41d83
}
8b41d83
8b41d83
8b41d83
sub
8b41d83
remove_dn_from_stack
8b41d83
{
8b41d83
  $current_dn =~ s/^.*?,\s*//;
8b41d83
}
8b41d83
8b41d83
8b41d83
sub
8b41d83
parse_error
8b41d83
{
8b41d83
  print "Parse error on line number $line_number at token number $token_number\n";
8b41d83
  exit (1);
8b41d83
}
8b41d83
8b41d83
8b41d83
sub
8b41d83
print_entry
8b41d83
{
8b41d83
  return if (scalar keys %curentry == 0);
8b41d83
8b41d83
  if (!defined ($curentry{'type'}))
8b41d83
    {
8b41d83
      $hostdn = "cn=$server, $basedn";
8b41d83
      print "dn: $hostdn\n";
8b41d83
      print "cn: $server\n";
8b41d83
      print "objectClass: top\n";
8b41d83
      print "objectClass: dhcpServer\n";
8b41d83
      print "dhcpServiceDN: $current_dn\n";
8b41d83
      if(grep(/FaIlOvEr/i, @use))
8b41d83
        {
8b41d83
          foreach my $fo_peer (keys %failover)
8b41d83
            {
8b41d83
              next if(scalar(@{$failover{$fo_peer}}) <= 1);
8b41d83
              print "dhcpStatements: failover peer $fo_peer { ",
8b41d83
                    join('; ', @{$failover{$fo_peer}}), "; }\n";
8b41d83
            }
8b41d83
        }
8b41d83
      print "\n";
8b41d83
8b41d83
      print "dn: $current_dn\n";
8b41d83
      print "cn: $dhcpcn\n";
8b41d83
      print "objectClass: top\n";
8b41d83
      print "objectClass: dhcpService\n";
8b41d83
      if (defined ($curentry{'options'}))
8b41d83
        {
8b41d83
          print "objectClass: dhcpOptions\n";
8b41d83
        }
8b41d83
      print "dhcpPrimaryDN: $hostdn\n";
8b41d83
      if(grep(/FaIlOvEr/i, @use) and ($second ne ''))
8b41d83
        {
8b41d83
          print "dhcpSecondaryDN: $second\n";
8b41d83
        }
8b41d83
    }
8b41d83
  elsif ($curentry{'type'} eq 'subnet')
8b41d83
    {
8b41d83
      print "dn: $current_dn\n";
8b41d83
      print "cn: " . $curentry{'ip'} . "\n";
8b41d83
      print "objectClass: top\n";
8b41d83
      print "objectClass: dhcpSubnet\n";
8b41d83
      if (defined ($curentry{'options'}))
8b41d83
        {
8b41d83
          print "objectClass: dhcpOptions\n";
8b41d83
        }
8b41d83
      
8b41d83
      print "dhcpNetMask: " . $curentry{'netmask'} . "\n";
8b41d83
      if (defined ($curentry{'ranges'}))
8b41d83
        {
8b41d83
          foreach $statement (@{$curentry{'ranges'}})
8b41d83
            {
8b41d83
              print "dhcpRange: $statement\n";
8b41d83
            }
8b41d83
        }
8b41d83
    }
8b41d83
  elsif ($curentry{'type'} eq 'shared-network')
8b41d83
    {
8b41d83
      print "dn: $current_dn\n";
8b41d83
      print "cn: " . $curentry{'descr'} . "\n";
8b41d83
      print "objectClass: top\n";
8b41d83
      print "objectClass: dhcpSharedNetwork\n";
8b41d83
      if (defined ($curentry{'options'}))
8b41d83
        {
8b41d83
          print "objectClass: dhcpOptions\n";
8b41d83
        }
8b41d83
    }
8b41d83
  elsif ($curentry{'type'} eq 'group')
8b41d83
    {
8b41d83
      print "dn: $current_dn\n";
8b41d83
      print "cn: group", $curentry{'idx'}, "\n";
8b41d83
      print "objectClass: top\n";
8b41d83
      print "objectClass: dhcpGroup\n";
8b41d83
      if (defined ($curentry{'options'}))
8b41d83
        {
8b41d83
          print "objectClass: dhcpOptions\n";
8b41d83
        }
8b41d83
    }
8b41d83
  elsif ($curentry{'type'} eq 'host')
8b41d83
    {
8b41d83
      print "dn: $current_dn\n";
8b41d83
      print "cn: " . $curentry{'host'} . "\n";
8b41d83
      print "objectClass: top\n";
8b41d83
      print "objectClass: dhcpHost\n";
8b41d83
      if (defined ($curentry{'options'}))
8b41d83
        {
8b41d83
          print "objectClass: dhcpOptions\n";
8b41d83
        }
8b41d83
8b41d83
      if (defined ($curentry{'hwaddress'}))
8b41d83
        {
8b41d83
          $curentry{'hwaddress'} =~ y/[A-Z]/[a-z]/;
8b41d83
          print "dhcpHWAddress: " . $curentry{'hwaddress'} . "\n";
8b41d83
        }
8b41d83
    }
8b41d83
  elsif ($curentry{'type'} eq 'pool')
8b41d83
    {
8b41d83
      print "dn: $current_dn\n";
8b41d83
      print "cn: pool", $curentry{'idx'}, "\n";
8b41d83
      print "objectClass: top\n";
8b41d83
      print "objectClass: dhcpPool\n";
8b41d83
      if (defined ($curentry{'options'}))
8b41d83
        {
8b41d83
          print "objectClass: dhcpOptions\n";
8b41d83
        }
8b41d83
8b41d83
      if (defined ($curentry{'ranges'}))
8b41d83
        {
8b41d83
          foreach $statement (@{$curentry{'ranges'}})
8b41d83
            {
8b41d83
              print "dhcpRange: $statement\n";
8b41d83
            }
8b41d83
        }
8b41d83
    }
8b41d83
  elsif ($curentry{'type'} eq 'class')
8b41d83
    {
8b41d83
      print "dn: $current_dn\n";
8b41d83
      print "cn: " . $curentry{'class'} . "\n";
8b41d83
      print "objectClass: top\n";
8b41d83
      print "objectClass: dhcpClass\n";
8b41d83
      if (defined ($curentry{'options'}))
8b41d83
        {
8b41d83
          print "objectClass: dhcpOptions\n";
8b41d83
        }
8b41d83
    }
8b41d83
  elsif ($curentry{'type'} eq 'subclass')
8b41d83
    {
8b41d83
      print "dn: $current_dn\n";
8b41d83
      print "cn: " . $curentry{'subclass'} . "\n";
8b41d83
      print "objectClass: top\n";
8b41d83
      print "objectClass: dhcpSubClass\n";
8b41d83
      if (defined ($curentry{'options'}))
8b41d83
        {
8b41d83
          print "objectClass: dhcpOptions\n";
8b41d83
        }
8b41d83
      print "dhcpClassData: " . $curentry{'class'} . "\n";
8b41d83
    }
8b41d83
8b41d83
  if (defined ($curentry{'statements'}))
8b41d83
    {
8b41d83
      foreach $statement (@{$curentry{'statements'}})
8b41d83
        {
8b41d83
          print "dhcpStatements: $statement\n";
8b41d83
        }
8b41d83
    }
8b41d83
8b41d83
  if (defined ($curentry{'options'}))
8b41d83
    {
8b41d83
      foreach $statement (@{$curentry{'options'}})
8b41d83
        {
8b41d83
          print "dhcpOption: $statement\n";
8b41d83
        }
8b41d83
    }
8b41d83
8b41d83
  print "\n";
8b41d83
  undef (%curentry);
8b41d83
}
8b41d83
8b41d83
8b41d83
sub parse_netmask
8b41d83
{
8b41d83
  local ($netmask) = @_;
8b41d83
  local ($i);
8b41d83
8b41d83
  if ((($a, $b, $c, $d) = $netmask =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/) != 4)
8b41d83
    {
8b41d83
      parse_error ();
8b41d83
    }
8b41d83
8b41d83
  $num = (($a & 0xff) << 24) |
8b41d83
         (($b & 0xff) << 16) |
8b41d83
         (($c & 0xff) << 8) |
8b41d83
          ($d & 0xff);
8b41d83
8b41d83
  for ($i=1; $i<=32 && $num & (1 << (32 - $i)); $i++)
8b41d83
    {
8b41d83
    }
8b41d83
  $i--;
8b41d83
8b41d83
  return ($i);
8b41d83
}
8b41d83
8b41d83
8b41d83
sub parse_subnet
8b41d83
{
8b41d83
  local ($ip, $tmp, $netmask);
8b41d83
8b41d83
  print_entry () if %curentry;
8b41d83
    
8b41d83
  $ip = next_token (0);
8b41d83
  parse_error () if !defined ($ip);
8b41d83
8b41d83
  $tmp = next_token (1);
8b41d83
  parse_error () if !defined ($tmp);
8b41d83
  parse_error () if !($tmp eq 'netmask');
8b41d83
8b41d83
  $tmp = next_token (0);
8b41d83
  parse_error () if !defined ($tmp);
8b41d83
  $netmask = parse_netmask ($tmp);
8b41d83
8b41d83
  $tmp = next_token (0);
8b41d83
  parse_error () if !defined ($tmp);
8b41d83
  parse_error () if !($tmp eq '{');
8b41d83
8b41d83
  add_dn_to_stack ("cn=$ip");
8b41d83
  $curentry{'type'} = 'subnet';
8b41d83
  $curentry{'ip'} = $ip;
8b41d83
  $curentry{'netmask'} = $netmask;
8b41d83
  $cursubnet = $ip;
8b41d83
  $curcounter{$ip} = { pool  => 0, group => 0 };
8b41d83
}
8b41d83
8b41d83
8b41d83
sub parse_shared_network
8b41d83
{
8b41d83
  local ($descr, $tmp);
8b41d83
8b41d83
  print_entry () if %curentry;
8b41d83
8b41d83
  $descr = next_token (0);
8b41d83
  parse_error () if !defined ($descr);
8b41d83
8b41d83
  $tmp = next_token (0);
8b41d83
  parse_error () if !defined ($tmp);
8b41d83
  parse_error () if !($tmp eq '{');
8b41d83
8b41d83
  add_dn_to_stack ("cn=$descr");
8b41d83
  $curentry{'type'} = 'shared-network';
8b41d83
  $curentry{'descr'} = $descr;
8b41d83
}
8b41d83
8b41d83
8b41d83
sub parse_host
8b41d83
{
8b41d83
  local ($descr, $tmp);
8b41d83
8b41d83
  print_entry () if %curentry;
8b41d83
8b41d83
  $host = next_token (0);
8b41d83
  parse_error () if !defined ($host);
8b41d83
8b41d83
  $tmp = next_token (0);
8b41d83
  parse_error () if !defined ($tmp);
8b41d83
  parse_error () if !($tmp eq '{');
8b41d83
8b41d83
  add_dn_to_stack ("cn=$host");
8b41d83
  $curentry{'type'} = 'host';
8b41d83
  $curentry{'host'} = $host;
8b41d83
}
8b41d83
8b41d83
8b41d83
sub parse_group
8b41d83
{
8b41d83
  local ($descr, $tmp);
8b41d83
8b41d83
  print_entry () if %curentry;
8b41d83
8b41d83
  $tmp = next_token (0);
8b41d83
  parse_error () if !defined ($tmp);
8b41d83
  parse_error () if !($tmp eq '{');
8b41d83
8b41d83
  my $idx;
8b41d83
  if(exists($curcounter{$cursubnet})) {
8b41d83
    $idx = ++$curcounter{$cursubnet}->{'group'};
8b41d83
  } else {
8b41d83
    $idx = ++$curcounter{''}->{'group'};
8b41d83
  }
8b41d83
8b41d83
  add_dn_to_stack ("cn=group".$idx);
8b41d83
  $curentry{'type'} = 'group';
8b41d83
  $curentry{'idx'} = $idx;
8b41d83
}
8b41d83
8b41d83
8b41d83
sub parse_pool
8b41d83
{
8b41d83
  local ($descr, $tmp);
8b41d83
8b41d83
  print_entry () if %curentry;
8b41d83
8b41d83
  $tmp = next_token (0);
8b41d83
  parse_error () if !defined ($tmp);
8b41d83
  parse_error () if !($tmp eq '{');
8b41d83
8b41d83
  my $idx;
8b41d83
  if(exists($curcounter{$cursubnet})) {
8b41d83
    $idx = ++$curcounter{$cursubnet}->{'pool'};
8b41d83
  } else {
8b41d83
    $idx = ++$curcounter{''}->{'pool'};
8b41d83
  }
8b41d83
8b41d83
  add_dn_to_stack ("cn=pool".$idx);
8b41d83
  $curentry{'type'} = 'pool';
8b41d83
  $curentry{'idx'} = $idx;
8b41d83
}
8b41d83
8b41d83
8b41d83
sub parse_class
8b41d83
{
8b41d83
  local ($descr, $tmp);
8b41d83
8b41d83
  print_entry () if %curentry;
8b41d83
8b41d83
  $class = next_token (0);
8b41d83
  parse_error () if !defined ($class);
8b41d83
8b41d83
  $tmp = next_token (0);
8b41d83
  parse_error () if !defined ($tmp);
8b41d83
  parse_error () if !($tmp eq '{');
8b41d83
8b41d83
  $class =~ s/\"//g;
8b41d83
  add_dn_to_stack ("cn=$class");
8b41d83
  $curentry{'type'} = 'class';
8b41d83
  $curentry{'class'} = $class;
8b41d83
}
8b41d83
8b41d83
8b41d83
sub parse_subclass
8b41d83
{
8b41d83
  local ($descr, $tmp);
8b41d83
8b41d83
  print_entry () if %curentry;
8b41d83
8b41d83
  $class = next_token (0);
8b41d83
  parse_error () if !defined ($class);
8b41d83
8b41d83
  $subclass = next_token (0);
8b41d83
  parse_error () if !defined ($subclass);
8b41d83
8b41d83
  $tmp = next_token (0);
8b41d83
  parse_error () if !defined ($tmp);
8b41d83
  parse_error () if !($tmp eq '{');
8b41d83
8b41d83
  add_dn_to_stack ("cn=$subclass");
8b41d83
  $curentry{'type'} = 'subclass';
8b41d83
  $curentry{'class'} = $class;
8b41d83
  $curentry{'subclass'} = $subclass;
8b41d83
}
8b41d83
8b41d83
8b41d83
sub parse_hwaddress
8b41d83
{
8b41d83
  local ($type, $hw, $tmp);
8b41d83
8b41d83
  $type = next_token (1);
8b41d83
  parse_error () if !defined ($type);
8b41d83
8b41d83
  $hw = next_token (1);
8b41d83
  parse_error () if !defined ($hw);
8b41d83
  $hw =~ s/;$//;
8b41d83
8b41d83
  $curentry{'hwaddress'} = "$type $hw";
8b41d83
}
8b41d83
8b41d83
    
8b41d83
sub parse_range
8b41d83
{
8b41d83
  local ($tmp, $str);
8b41d83
8b41d83
  $str = remaining_line ();
8b41d83
8b41d83
  if (!($str eq ''))
8b41d83
    {
8b41d83
      $str =~ s/;$//;
8b41d83
      push (@{$curentry{'ranges'}}, $str);
8b41d83
    }
8b41d83
}
8b41d83
8b41d83
8b41d83
sub parse_statement
8b41d83
{
8b41d83
  local ($token) = shift;
8b41d83
  local ($str);
8b41d83
8b41d83
  if ($token eq 'option')
8b41d83
    {
8b41d83
      $str = remaining_line ();
8b41d83
      push (@{$curentry{'options'}}, $str);
8b41d83
    }
8b41d83
  elsif($token eq 'failover')
8b41d83
    {
8b41d83
      $str = remaining_line (1); # take care on block
8b41d83
      if($str =~ /[{]/)
8b41d83
        {
8b41d83
          my ($peername, @statements);
8b41d83
8b41d83
          parse_error() if($str !~ /^\s*peer\s+(.+?)\s+[{]\s*$/);
8b41d83
          parse_error() if(($peername = $1) !~ /^\"?[^\"]+\"?$/);
8b41d83
8b41d83
          #
8b41d83
          # failover config block found:
8b41d83
          # e.g. 'failover peer "some-name" {'
8b41d83
          #
8b41d83
          if(not grep(/FaIlOvEr/i, @use))
8b41d83
            {
8b41d83
              print STDERR "Warning: Failover config 'peer $peername' found!\n";
8b41d83
              print STDERR "         Skipping it, since failover disabled!\n";
8b41d83
              print STDERR "         You may try out --use=failover option.\n";
8b41d83
            }
8b41d83
8b41d83
          until($str =~ /[}]/ or $str eq "")
8b41d83
            {
8b41d83
                $str = remaining_line (1);
8b41d83
                # collect all statements, except ending '}'
8b41d83
                push(@statements, $str) if($str !~ /[}]/);
8b41d83
            }
8b41d83
          $failover{$peername} = [@statements];
8b41d83
        }
8b41d83
      else
8b41d83
        {
8b41d83
          #
8b41d83
          # pool reference to failover config is fine
8b41d83
          # e.g. 'failover peer "some-name";'
8b41d83
          #
8b41d83
          if(not grep(/FaIlOvEr/i, @use))
8b41d83
            {
8b41d83
              print STDERR "Warning: Failover reference '$str' found!\n";
8b41d83
              print STDERR "         Skipping it, since failover disabled!\n";
8b41d83
              print STDERR "         You may try out --use=failover option.\n";
8b41d83
            }
8b41d83
          else
8b41d83
            {
8b41d83
              push (@{$curentry{'statements'}}, $token. " " . $str);
8b41d83
            }
8b41d83
        }
8b41d83
    }
8b41d83
  elsif($token eq 'zone')
8b41d83
    {
8b41d83
      $str = $token;
8b41d83
      while($str !~ /}$/) {
8b41d83
        $str .= ' ' . next_token (0);
8b41d83
      }
8b41d83
      push (@{$curentry{'statements'}}, $str);
8b41d83
    }
8b41d83
  elsif($token =~ /^(authoritative)[;]*$/)
8b41d83
    {
8b41d83
      push (@{$curentry{'statements'}}, $1);
8b41d83
    }
8b41d83
  else
8b41d83
    {
8b41d83
      $str = $token . " " . remaining_line ();
8b41d83
      push (@{$curentry{'statements'}}, $str);
8b41d83
    }
8b41d83
}
8b41d83
8b41d83
8b41d83
my $ok = GetOptions(
8b41d83
    'basedn=s'      => \$basedn,
8b41d83
    'dhcpdn=s'      => \$dhcpdn,
8b41d83
    'server=s'      => \$server,
8b41d83
    'second=s'      => \$second,
8b41d83
    'conf=s'        => \$i_conf,
8b41d83
    'ldif=s'        => \$o_ldif,
8b41d83
    'use=s'         => \@use,
8b41d83
    'h|help|usage'  => sub { usage(0); },
8b41d83
);
8b41d83
8b41d83
unless($server =~ /^\w+/)
8b41d83
  {
8b41d83
    usage(1, "invalid server name '$server'");
8b41d83
  }
8b41d83
unless($basedn =~ /^\w+=[^,]+/)
8b41d83
  {
8b41d83
    usage(1, "invalid base dn '$basedn'");
8b41d83
  }
8b41d83
8b41d83
if($dhcpdn =~ /^cn=([^,]+)/i)
8b41d83
  {
8b41d83
    $dhcpcn = "$1";
8b41d83
  }
8b41d83
$second = '' if not defined $second;
8b41d83
unless($second eq '' or $second =~ /^cn=[^,]+\s*,\s*\w+=[^,]+/i)
8b41d83
  {
8b41d83
    if($second =~ /^cn=[^,]+$/i)
8b41d83
      {
8b41d83
        # relative DN 'cn=name'
8b41d83
        $second = "$second, $basedn";
8b41d83
      }
8b41d83
    elsif($second =~ /^\w+/)
8b41d83
      {
8b41d83
        # assume hostname only
8b41d83
        $second = "cn=$second, $basedn";
8b41d83
      }
8b41d83
    else
8b41d83
      {
8b41d83
        usage(1, "invalid secondary '$second'")
8b41d83
      }
8b41d83
  }
8b41d83
8b41d83
usage(1) unless($ok);
8b41d83
8b41d83
if($i_conf ne "" and -f $i_conf)
8b41d83
  {
8b41d83
    if(not open(STDIN, '<', $i_conf))
8b41d83
      {
8b41d83
        print STDERR "Error: can't open conf file '$i_conf': $!\n";
8b41d83
        exit(1);
8b41d83
      }
8b41d83
  }
8b41d83
if($o_ldif ne "")
8b41d83
  {
8b41d83
    if(-e $o_ldif)
8b41d83
      {
8b41d83
        print STDERR "Error: output ldif name '$o_ldif' already exists!\n";
8b41d83
        exit(1);
8b41d83
      }
8b41d83
    if(not open(STDOUT, '>', $o_ldif))
8b41d83
      {
8b41d83
        print STDERR "Error: can't open ldif file '$o_ldif': $!\n";
8b41d83
        exit(1);
8b41d83
      }
8b41d83
  }
8b41d83
8b41d83
8b41d83
print STDERR "Creating LDAP Configuration with the following options:\n";
8b41d83
print STDERR "\tBase DN: $basedn\n";
8b41d83
print STDERR "\tDHCP DN: $dhcpdn\n";
8b41d83
print STDERR "\tServer DN: cn=$server, $basedn\n";
8b41d83
print STDERR "\tSecondary DN: $second\n"
8b41d83
             if(grep(/FaIlOvEr/i, @use) and $second ne '');
8b41d83
print STDERR "\n";
8b41d83
8b41d83
my $token;
8b41d83
my $token_number = 0;
8b41d83
my $line_number = 0;
8b41d83
my %curentry;
8b41d83
my $cursubnet = '';
8b41d83
my %curcounter = ( '' => { pool => 0, group => 0 } );
8b41d83
8b41d83
$current_dn = "$dhcpdn";
8b41d83
$curentry{'descr'} = $dhcpcn;
8b41d83
$line = '';
8b41d83
%failover = ();
8b41d83
8b41d83
while (($token = next_token (1)))
8b41d83
  {
8b41d83
    if ($token eq '}')
8b41d83
      {
8b41d83
        print_entry () if %curentry;
8b41d83
        if($current_dn =~ /.+?,\s*${dhcpdn}$/) {
8b41d83
          # don't go below dhcpdn ...
8b41d83
          remove_dn_from_stack ();
8b41d83
        }
8b41d83
      }
8b41d83
    elsif ($token eq 'subnet')
8b41d83
      {
8b41d83
        parse_subnet ();
8b41d83
        next;
8b41d83
      }
8b41d83
    elsif ($token eq 'shared-network')
8b41d83
      {
8b41d83
        parse_shared_network ();
8b41d83
        next;
8b41d83
      }
8b41d83
    elsif ($token eq 'class')
8b41d83
      {
8b41d83
        parse_class ();
8b41d83
        next;
8b41d83
      }
8b41d83
    elsif ($token eq 'subclass')
8b41d83
      {
8b41d83
        parse_subclass ();
8b41d83
        next;
8b41d83
      }
8b41d83
    elsif ($token eq 'pool')
8b41d83
      {
8b41d83
        parse_pool ();
8b41d83
        next;
8b41d83
      }
8b41d83
    elsif ($token eq 'group')
8b41d83
      {
8b41d83
        parse_group ();
8b41d83
        next;
8b41d83
      }
8b41d83
    elsif ($token eq 'host')
8b41d83
      {
8b41d83
        parse_host ();
8b41d83
        next;
8b41d83
      }
8b41d83
    elsif ($token eq 'hardware')
8b41d83
      {
8b41d83
        parse_hwaddress ();
8b41d83
        next;
8b41d83
      }
8b41d83
    elsif ($token eq 'range')
8b41d83
      {
8b41d83
        parse_range ();
8b41d83
        next;
8b41d83
      }
8b41d83
    else
8b41d83
      {
8b41d83
        parse_statement ($token);
8b41d83
        next;
8b41d83
      }
8b41d83
  }
8b41d83
8b41d83
close(STDIN)  if($i_conf);
8b41d83
close(STDOUT) if($o_ldif);
8b41d83
8b41d83
print STDERR "Done.\n";
8b41d83