Benutzer:Kirmse/delixs-hostadd

Aus Delixs
Zur Navigation springen Zur Suche springen

delixs-hostadd

  • Dieses Script dient dazu, DHCP-Hosts im LDAP einzutragen
  • Parameter: --pool oder -p, --tnetz oder -t, --mac oder -m, --rechner oder -r, --ip oder i, --help oder -h
  • Aufruf: delixs-hostadd -p mathe -r aachen -m aa:bb:cc:12:ef:28

Die Parameter Pool (entspricht Raum), Rechnername und MAC-Adresse sind zwingend.


das Script

<source lang="perl">

  1. !/usr/bin/perl

use warnings; use strict;

use Net::LDAP; use Getopt::Long;


my ($ldap, $ldap_base, $pass, $entry, $mesg, $poolname, $vorgabe_teilnetz,

   $pcname, $mac, $teilnetz, $ip, $minimum, $maximum, $min, $max, 
   $dhcpRange, $drei_oktetts, @oktetts, $my_oktett, $temp);
   
  1. --------- Konfigurationsbereich --------------------------------------------

$vorgabe_teilnetz = '10.100.0.0'; # Vorgabe fuer das Teilnetz

  1. ----------------------------------------------------------------------------


  1. Initialisieren der Variablen fuer die Parameter

$pcname = ; $poolname = ; $mac = ; $teilnetz = ; $ip = ;

  1. wir holen uns zuerst die Parameter,
  2. falls --help, dann Ausgabe der Hilfe (siehe &help) und beenden

GetOptions('rechner=s' => \$pcname,

          'pool=s'    => \$poolname,
          'mac=s'     => \$mac,
          'tnetz=s'   => \$teilnetz,
          'ip=s'      => \$ip,
          'help'      => \&help);


  1. --------- formale Ueberpruefung der uebergebenen Parameter -----------------
  1. Wenn kein Parameter -r oder --rechner uebergeben wurde, dann Abbruch

if ($pcname eq ) {

 die "Abbruch: es wurde kein Name fuer den Rechner uebergeben!\n";

}

  1. Wenn der Rechnername nicht den (meinen) Konventionen entspricht, dann Abbruch

unless ($pcname =~ /^[a-zA-Z]\w{1,10}$/) {

 die "Abbruch: Der Name $pcname fuer den Rechner ist nicht korrekt!\n";

}

  1. Wenn kein Parameter -p oder --poolname uebergeben wurde, dann Abbruch

if ($poolname eq ) {

 die "Abbruch: es wurde kein Name fuer die Rechnergruppe uebergeben!\n";

}

  1. Wenn der Poolname nicht den (meinen) Konventionen entspricht, dann Abbruch

unless ($poolname =~ /^[a-zA-Z]\w{1,10}$/) {

 die "Abbruch: Der Name fuer die Rechnergruppe ist nicht korrekt!\n";

}

  1. Wenn kein Parameter -m oder --mac uebergeben wurde, dann Abbruch

if ($mac eq ) {

 die "Abbruch: es wurde keine MAC-Adresse uebergeben!\n";

}

  1. Wenn die MAC-Adresse nicht das richtige Format hat, dann Abbruch

unless ($mac =~ /^\w\w:\w\w:\w\w:\w\w:\w\w:\w\w$/) {

 die "Abbruch: Die MAC-Adresse ist nicht korrekt!\n";

}

  1. Wenn Parameter Teilnetz uebergeben, dann kontrollieren

unless ($teilnetz eq ) {

 # ob richtiges Format 
 unless ($teilnetz =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.0$/) {
   die "Abbruch: Das Teilnetz $teilnetz ist keine gueltige Angabe!\n"
 }

}

  1. Wenn der Parameter nicht uebergeben

else {

 # dann setzen wir das Teilnetz
 $teilnetz = $vorgabe_teilnetz;  

}

  1. Wenn Parameter IP uebergeben, dann kontrollieren

unless ($ip eq ) {

 # ob richtiges Format 
 unless ($ip =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/) {
   die "Abbruch: Das IP $ip hat nicht das richtige Format!\n"
 }

}


  1. Wenn wir keine root-Rechte haben, dann Abbruch

if ($> != 0) { # siehe $EFFECTIVE_USER_ID,$EUID

 die "Abbruch: das Script muss mit root-Rechten ausgefuehrt werden!\n";

}

  1. wir holen uns die Such-Basis ($ldap_base) aus der ldap.conf

open DATEI, '<', '/etc/ldap/ldap.conf'

 or die "Abbruch: konnte ldap.conf nicht oeffnen, $!\n";

while (my $zeile = <DATEI>) {

 if ($zeile =~ m/^\s*base\s+(\w.*\w)\s*$/i) {
   $ldap_base = $1;
   last;
 }

} close DATEI;

  1. da wir (spaeter) in den LDAP schreiben wollen, brauchen wir noch das Passwort

open DATEI, '<', '/etc/ldap.secret'

 or die "Abbruch: konnte ldap.secret nicht oeffnen, $!\n";

$pass = <DATEI>; chomp($pass); close DATEI;

  1. wir verbinden uns mit dem LDAP

$ldap = Net::LDAP->new('127.0.0.1', version => 3) or die "Abbruch: $@"; $ldap->bind( dn => "cn=admin, $ldap_base", password => $pass)

 or die "Abbruch: konnte mich nicht mit dem LDAP verbinden";
  1. wir ueberpruefen, ob das Teilnetz im LDAP existiert

$mesg = $ldap->search(base => "cn=$teilnetz,cn=DHCP Config,$ldap_base",

                     filter => "cn=$teilnetz");
  1. wenn wir keinen Eintrag erhalten haben, dann Abbruch

if (scalar ($mesg->entries) == 0) {

 die "Abbruch: Das Teilnetz $teilnetz existiert nicht im LDAP!\n";

}

  1. Wir ueberpruefen, ob der Pool im LDAP existiert

$mesg = $ldap->search(

         base   => "cn=$poolname,cn=$teilnetz,cn=DHCP Config,$ldap_base", 
         filter => "cn=$poolname",
         attrs  => 'dhcpRange' );
  1. Wenn der Pool nicht gefunden wird dann Abbruch

if (scalar ($mesg->entries) == 0) {

 die "Abbruch: Der Pool $poolname existiert nicht im LDAP!\n";

}

  1. wir holen uns den dhcpRange (die beiden IPs)

$entry = ($mesg->entries)[0]; # nur ein Element in der Liste $dhcpRange = $entry->get_value('dhcpRange');

  1. wir holen uns die ersten 3 Oktetts der IP

($minimum, $maximum) = split /\s+/, $dhcpRange; # am Leerzeichen splitten if ($minimum =~ /^\s*(\d{1,3}\.\d{1,3}\.\d{1,3})\.(\d{1,3})\s*$/) {

 $drei_oktetts = $1; 
 $min          = $2;

} else {

 die "Abbruch: der dhcpRange vom Pool $poolname konnte nicht ausgewertet werden!\n";

}

if ($maximum =~ /^\s*\d{1,3}\.\d{1,3}\.\d{1,3}\.(\d{1,3})\s*$/) {

 $max          = $1;

} else {

 die "Abbruch: der dhcpRange vom Pool $poolname konnte nicht ausgewertet werden!\n";

}

  1. Wenn die IP uebergeben wurde

unless ($ip eq ) {

 # dann testen, ob die IP zum Teilnetz passt
 ($temp) =  $teilnetz =~ /^\s*(\d{1,3}\.\d{1,3})/ ; 
 unless ( $ip =~ /^$temp/ ) {
   die "Abbruch: Die IP \"$ip\" passt nicht zum Teilnetz \"$teilnetz\"!\n"
 }
 # dann testen, ob die IP zu diesem Pool gehoert
 unless ( $ip =~ /^$drei_oktetts/ ) {
   die "Abbruch: Die IP \"$ip\" passt nicht zum Pool \"$drei_oktetts\"!\n"
 }

} else {

 # wir holen uns von dem Pool alle DHCP-Hosts
 $mesg = $ldap->search(
           base   => "cn=$poolname,cn=$teilnetz,cn=DHCP Config,$ldap_base", 
           filter => 'objectClass=dhcpHost',
           attrs  => 'dhcpStatements' );
 # dann holen wir uns von allen dhcpStatements die IP / das letzte Oktett
 @oktetts = ();
 if (scalar $mesg->entries > 0) {
   foreach my $entry ($mesg->entries) {
     $temp = $entry->get_value('dhcpStatements');
     if ($temp =~ /^fixed-address\s*\d{1,3}\.\d{1,3}\.\d{1,3}\.(\d{1,3})$/) {
       push @oktetts, $1; 
     } 
   }
 } 
 # dann sortieren wir die Liste, groesste Zahl ist vorn  
 @oktetts = sort { $b <=> $a } @oktetts;
 if (scalar @oktetts == 0) {
   $my_oktett = $min;
 }
 else {
   $my_oktett = $oktetts[0] + 1;
 }
 # wir testen, ob $my_oktett kleiner als die Obergrenze von dhcpRange ist
 if ($my_oktett > $max) {
   die "Abbruch: die Obergrenze von dhcpRange wurde ueberschritten!\n";
 }
 # wir bauen uns die IP
 $ip = $drei_oktetts . '.' . $my_oktett;

}

  1. um z.B. versehentliches mehrfaches Aufrufen des Scriptes abzufangen:

$mesg = $ldap->search(

         base   => "cn=$pcname,cn=$poolname,cn=$teilnetz,cn=DHCP Config,$ldap_base", 
         filter => 'objectClass=dhcpHost' );
  1. Wenn der Host gefunden wird dann Abbruch

if (scalar ($mesg->entries) > 0) {

 die "Abbruch: Der Host $pcname ist schon im LDAP eingetragen!\n";

}

  1. jetzt tragen wir (endlich) den Host ein

$mesg = $ldap->add(

         dn   => "cn=$pcname,cn=$poolname,cn=$teilnetz,cn=DHCP Config,$ldap_base",
         attr => [ objectClass    => ['top', 'dhcpHost'],
                   cn             => $pcname,
                   dhcpHWAddress  => "ethernet $mac",
                   dhcpStatements => "fixed-address $ip" ] ); 
  1. wenn Fehlercode, dann das Script mit Fehlermeldung sterben lassen (nur dann!)

$mesg->code and die $mesg->error;

  1. wir trennen uns vom LDAP

$ldap->unbind;

  1. Ausgabe auf der Konsole (Rueckmeldung)

print "Der DHCP-Host \"$pcname\" wurde in den LDAP eingetragen.\n";


                                      1. Programm-Ende #####################################
  1. Wenn Parameter -h uebergeben wurde, dann Hilfe ausgegeben und beenden

sub help {

  print "Hilfe muss noch erstellt werden.\n";
  exit (0);

}

__END__

</source>