#!/usr/bin/perl -w use strict; use CGI qw/:standard/; # ------------------- Konfigurationsbereich --------------------- my $leasedatei = "/var/state/dhcp/dhcpd.leases"; my $confdatei = "/etc/dhcpd.conf"; my $namedatei = "/etc/named/named.LAN.zone"; my $conf_neu = "/etc/dhcpd.conf.neu"; # ------------------- Intialisierungsbereich -------------------- my @daten = (); # Liste von Strings my @anz = (); # PCs in den Teilnetzen my @start = (); # für jedes Teilnetz my $status = 0; # 0 bedeutet 'kein Fehler' my @tmp1 = (); # stücke der dhcpd.conf my @tmp2 = (); # Daten für neue dhcpd.conf my $msg = ""; # Erfolgs- o. Fehlermeldung # ------------------- Hauptprogramm ----------------------------- my $wert = param('formular'); # wir rufen die URL ohne Parameter auf, also $wert = undef # vroher finden alle notwendigen Überprüfungen statt # Das erste Formular ist nur eine Informationsseite, später # soll diese auch zum Verzweigen dienen (Terminals, Experten) # wenn eine solche überprüfung positiv ausfällt, dann sollte # nur eine Fehlermeldung kommen und das Programm terminieren unless ($wert eq 'Daten übernehmen' or $wert eq 'starten' or $wert eq 'alte dhcpd.conf anschauen' or $wert eq 'neue dhcpd.conf anschauen') { print &startseite; } # das Formular liefert für $wert den String 'starten' # wir lesen die dhcpd.leases ein, sortieren nach Rechnernamen # holen aus der dhcpd.conf die groessten vergebenen IPs # und erstellen das eigentliche Formular if ($wert eq 'starten') { @daten = &lies_dhcpd_leases($leasedatei); # da alles richtig -> Daten @daten = sortieren(@daten); # auch @anz als glob. Variable @start = &hole_startwerte($confdatei); print &zeige_daten ($anz[0],$anz[1],$anz[2],$anz[3],@daten); } # das Formular liefert für $wert den String 'Daten übernehmen' # wir bearbeiten die Daten, holen und bearbeiten die dhcpd.conf # und named-Datei, erstellen die neue dhcpd.conf # und geben eine Meldung als 3. Webseite aus if ($wert eq 'Daten übernehmen') { @daten = &hole_daten; @tmp1 = &lies_dhcpd_conf($confdatei); @tmp2 = &erstelle_rechnereintrag(@daten); $msg = &erstelle_neue_dhcpdconf($conf_neu); print &ergebnis($msg); } if ($wert eq 'alte dhcpd.conf anschauen') { print &zeige_datei($confdatei); } if ($wert eq 'neue dhcpd.conf anschauen') { print &zeige_datei($conf_neu); } #################### Programm-Ende ############################## # ------------------- Prozeduren -------------------------------- # hier wird nichts weiter als das Anmeldefenster erstellt sub startseite { my $header = "Content-type: text/html\n\n"; my $formular = < Startseite für das FIP-Script

Einrichten fester IP-Adressen


Dieses Script soll Sie unterstützen, mit Hilfe des DHCP-Servers feste IP-Adressen zu vergeben. Dieses Script ändert aber nicht die eigentliche Konfiguration des DHCP-Servers, sondern erstellt eine neue Datei, die Sie als root noch austauschen müssen.

 


© HD. Kirmse, 23.07.2004
ENDE return $header.$formular; } # es wurde dieser Teil fast 1:1 uebernommen von dem Script unter # http://www.linuxfocus.org/common/src/article150/dhcp-auto_pl.txt sub lies_dhcpd_leases ($leasedatei) { my $datei = $_[0]; # Pfad zur leases-Datei my $ip = ""; # hier kommt die IP rein my $hostname = ""; # der hostname my $mac = ""; # die MAC-Adresse my @liste = (); # Rueckgabe dieser Prozedur my $t = ""; my $lease = ""; my $hard = ""; my $nom = ""; my %h = (); open IN, '<'.$datei; # zum lesen oeffnen while () { # wir holen uns die IP ($t, $lease) = split("lease ",$_); if($lease){ ($ip,$t) = split(" ",$lease); } # wir holen uns die MAC-Adresse ($t, $hard) = split("hardware ethernet ",$_); if($hard){ ($mac,$t) = split(";",$hard); } # wir holen uns den Hostnamen ($t, $nom) = split("client-hostname \"",$_); if($nom){ ($hostname,$t) = split("\"",$nom); } if($ip && $hostname && $mac){ # wir sorgen für Klein-Schreibung $hostname = lc $hostname; # wir bringen alles in einen Hash @h # und vernichten dabei gleich Doubletten (bzgl. MAC) $h{$mac} = $hostname.'/'.$ip.'/'.$mac ; # und intialisieren fuer den naechsten Datensatz $ip = $mac = $hostname = ""; } } close IN; # wir bringen alles in eine Liste @liste foreach my $x (keys %h) { push @liste, $h{$x} ; } return @liste ; } # wir Trennen die eingelesenen Daten nach den Teilnetzen # dann sortieren wir jedes Teilnetz fuer sich nach den Rechnernamen # wir gehen davon aus, dass man in einem Kabinett die Rechner # systematisch bezeichnet. Zusätzlich bestimmen wir noch von jedem # Teilnetz die Anzahl, die wir aber als globale Variable zurueckgeben sub sortieren { my @liste = @_; my @liste0 = (); my @liste1 = (); my @liste2 = (); my @liste3 = (); foreach my $pc (@liste) { $pc =~ /192\.168\.(\d)\.\d+/; # wir holen das Teilnetz -> $1 if ($1 == 0) { push @liste0, $pc } elsif ($1 == 1) { push @liste1, $pc } elsif ($1 == 2) { push @liste2, $pc } elsif ($1 == 3) { push @liste3, $pc }; } @liste0 = sort @liste0; # wir sortieren jede Teilliste @liste1 = sort @liste1; # nach dem Namen. Das geht @liste2 = sort @liste2; # deshalb so einfach, weil @liste3 = sort @liste3; # der Name als erstes steht @liste = (); # wir machen unsere Liste leer $anz[0] = @liste0; # Anzahl PCs im 1. Teilnetz $anz[1] = @liste1; # !!! Achtung !!! $anz[2] = @liste2; # werden als globale $anz[3] = @liste3; # Variable zurückgegeben push @liste, @liste0; # wir setzen die Liste push @liste, @liste1; # wieder zusammen push @liste, @liste2; push @liste, @liste3; return @liste; # und geben sie zurueck } # Standardmaessig gehen wir davon aus, dass die IP-Adressen von der # 20 hochgezaehlt werden. Das wuerde aber nur dann gelten, wenn noch # keine festen IPs vergeben worden sind. wir holen deshalb aud der # vorhandenen dhcpd.conf alle IP-Adressen und bestimmen die bisher # groesste. Die darauffolgende wird unser Startwert fuer das Teilnetz sub hole_startwerte { # wir holen erstmal alle eingetragenen IPs aus der dhcpd.conf # der zu untersuchende String ist 'fixed-address 192.168.*.*' my $datei = $_[0]; # Pfad zur dhcpd.conf my @zeilen = (); my @ips = (); my @liste0 = (); my @liste1 = (); my @liste2 = (); my @liste3 = (); my @w = (); $w[0] = 19; $w[1] = 19; $w[2] = 19; $w[3] = 19; $w[4] = 100; # ist nur ein Dummy my $z = ""; open DATEI, '<'.$datei; # zum lesen oeffnen @zeilen = ; close DATEI; # jetzt holen wir aus erstmal alle oben genannten Strings foreach my $x (@zeilen) { if ($x =~ m/fixed-address\s*(192\.168\.\d+\.\d+)/) { push @ips, $1; # wir pushen nur die IPs } } # die naechste Routine wurde direkt von der Prozedur sortieren genommen foreach my $y (@ips) { $y =~ m/192\.168\.(\d)\.\d+/; # wir holen das Teilnetz -> $1 if ($1 == 0) { push @liste0, $y } elsif ($1 == 1) { push @liste1, $y } elsif ($1 == 2) { push @liste2, $y } elsif ($1 == 3) { push @liste3, $y }; } # jetzt ermitteln wir den jeweils größten Eintrag in den Listen foreach $z (@liste0) { $z =~ m/192\.168\.\d+\.(\d+)/; if ($1 > $w[0]) { $w[0] = $1 } } foreach $z (@liste1) { $z =~ m/192\.168\.\d+\.(\d+)/; if ($1 > $w[1]) { $w[1] = $1 } } foreach $z (@liste2) { $z =~ m/192\.168\.\d+\.(\d+)/; if ($1 > $w[2]) { $w[2] = $1 } } foreach $z (@liste3) { $z =~ m/192\.168\.\d+\.(\d+)/; if ($1 > $w[3]) { $w[3] = $1 } } return @w; } # diese Funktion erstellt die 2. Webseite, bei der die Rechner # ausgewaehlt werden können, die eingetragen werden sollen # den Rechnenamen schleussen wir als hidden-Attribut mit durch sub zeige_daten { my $tn1 = shift; my $tn2 = shift; my $tn3 = shift; my $tn4 = shift; my @daten = @_; my $anz = @daten; # Anzahl der Datensätze my $kopf = < Webseite zum Erstellen der dhcpd.conf

Einrichten fester IP-Adressen


Es werden insgesamt $anz PCs (Teilnetz 1 : $tn1, Teilnetz 2 : $tn2, Teilnetz 3 : $tn3, Teilnetz 4 : $tn4) aufgelistet.
 

Seitenanfang my $fuss = <



© HD. Kirmse, 23.07.2004
Seitenende # jetzt basteln wir die Tabelle my $tabelle = ""; my $zaehler = 1; my $ip = ""; my $hostname = ""; my $mac = ""; my $tab = ""; # den (eindeutigen) Namen fuer das Formular bilden wir so: wir nehmen # die MAC-Adresse, entfernen die Doppelpunkte und setzen davor "ip" # bzw. jn (von ja/nein) my $name = ""; my @tmp = (); my @adresse = (); my $teilnetz = 0; # beginnen mit Teilnetz 0 my $nummer = $start[$teilnetz]; # 1. IP soll 20 sein foreach my $pc (@daten) { ($hostname,$ip,$mac) = split "/", $pc; @tmp = split ":", $mac; $name = $tmp[0].$tmp[1].$tmp[2].$tmp[3].$tmp[4].$tmp[5]; # ab hier beginnt der Teil mit dem Nummerieren @adresse = split /\./, $ip ; # wir zerlegen die IP if ($adresse[2] == $teilnetz) { # wenn wir in dem Teilnetz $nummer++; # erhöhen den "Zähler" } else { # sonst $nummer = $start[$teilnetz+1] + 1; # Startwert nächstes TN + 1 } $adresse[3]= $nummer; # setzen letzte Feld der IP $ip = join('.',@adresse); # IP wieder zusammensetzen $teilnetz = $adresse[2]; # wir merken uns das Teilnetz # hier endet das Nummerieren $tab .= "
\n"; $tab .= ''."\n"; $tab .= ''."\n"; $tab .= ' \n"; $tab .= ' \n \n"; } my $header = "Content-type: text/html\n\n"; return $header.$kopf.$tab.$fuss; } # Die Ausgewaehlten Daten werden hier aus dem Enviroment herausgeholt # und aufbereitet, zurueckgegeben wird eine Liste von Strings im # Format $nname.'/'.$nip.'/'.$nmac ; sub hole_daten { my @keys = param(); my $nip = ""; my $nname = ""; my $nmac = ""; my @temp = (); # das nächste ist nur Quatsch foreach my $x (@keys) { # uns interessieren alle die Rechner, bei denen eine Variable vorhanden # ist, die mit 'jn' beginnt. Also durchlaufen wir alle übergebenen # Variablen und bearbeiten alle, die mit 'jn' beginnen und holen den # 'MAC-Anteil' und können dadurch den Zugriff auf die anderen Variablen # realisieren. if ($x =~ m/^jn(\w+)$/){ $nname = param('pc'.$1); $nip = param('ip'.$1); if ($1 =~ m/^(..)(..)(..)(..)(..)(..)$/){ $nmac = join(':',$1,$2,$3,$4,$5,$6); } push @temp, $nname.'/'.$nip.'/'.$nmac ; } } return @temp; } # hier wird die Webseite erstellt, die das Ergebnis bestätigt # also die 3. Webseite sub ergebnis { my $text = $_[0]; my $anzahl = @daten; my $header = "Content-type: text/html\n\n"; my $x = ""; my $y = ""; my $z = ""; my $t = ""; $t = $header; $t .= < Erggebnisseite für das FIP-Script

Ergebnis


Sie haben jetzt eine neue dhcpd.conf-Datei für den DHCP-Server erstellt, bei dem jetzt $anzahl Rechner neu eingetragen worden sind.

Diese neu erstellte Datei finden sie unter $conf_neu . Sie müssen diese als root noch gegen die alte dhcpd.conf austauschen.

Sie haben auch die Möglichkeit hier die Dateien schon anzuschauen und zu überprüfen. Wenn Sie auf die entsprechenden Button drücken, wird die betreffende Datei in einem weiteren Fenster geöffnet.

Rechnername IP-Adresse MAC-Adresse übernehmen?
 '.$hostname.'    '.$mac."  
Sie sind (fast) fertig!
   


© HD. Kirmse, 23.07.2004
ENDE return $t; } # der 1. Bereich ist alles vom Anfang bis einschließlich max-lease-time # und das schieben wir in die $kopfzeile und hängen noch eine Leerzeile an # ab diesem Moment werden alle Leerzeilen verworfen # der 2. Bereich geht von 'subnet 192.168.0 bis zur schließenden # Klammer, die alleine in einer Zeile steht. diese Klammer verwerfen # wir, alles andere schieben wir in $teilnetz0 # der 3. Bereich geht von 'subnet 192.168.1 bis zur schließenden # Klammer, die alleine in einer Zeile steht. auch diese Klammer verwerfen # wir, alles andere schieben wir in $teilnetz1 ... # TODO: um beliebig viele Teilnetze nehmen zu können, sollten wir dann # eine Liste von Strings verwenden sub lies_dhcpd_conf { my $datei = $_[0]; # Pfad zur conf-Datei my $bereich = 1; # Initial. der Abschnitte my $tempzeile = ""; my $kopfzeile = ""; # der String wird kopiert my $teilnetz0 = ""; # -> my $teilnetz1 = ""; # das sind die Strings mit my $teilnetz2 = ""; # denen dann die Abschnitte my $teilnetz3 = ""; # anfangen werden my @ergebnis = (); # $kopfzeile, $teilnetz0, ... open DATEI, '<'.$datei; while ($tempzeile = ) { if ($bereich == 1){ $kopfzeile .= $tempzeile; # aktuelle Zeile dazu if ($tempzeile =~ /max-lease-time/){ $bereich++; # dann nächster Bereich $kopfzeile .= "\n"; # und eine Leerzeile } } elsif ($bereich == 2){ # also ab 'subnet 192.168.0.' if ($tempzeile =~ /^\s*$/) { # wenn Leerzeile # dann machen wir nichts # dann verwerfen } elsif ($tempzeile =~ /^\s*}\s*$/) { # wenn nur die Klammer $bereich++; # dann nächster Bereich } else { # alles andere kopieren $teilnetz0 .= $tempzeile; } } elsif ($bereich == 3){ # also ab 'subnet 192.168.1.' if ($tempzeile =~ /^\s*$/) { # wenn Leerzeile # dann machen wir nichts # dann verwerfen } elsif ($tempzeile =~ /^\s*}\s*$/) { # wenn nur die Klammer $bereich++; # dann nächster Bereich } else { # alles andere kopieren $teilnetz1 .= $tempzeile; } } elsif ($bereich == 4){ # also ab 'subnet 192.168.2.' if ($tempzeile =~ /^\s*$/) { # wenn Leerzeile # dann machen wir nichts # dann verwerfen } elsif ($tempzeile =~ /^\s*}\s*$/) { # wenn nur die Klammer $bereich++; # dann nächster Bereich } else { # alles andere kopieren $teilnetz2 .= $tempzeile; } } elsif ($bereich == 5){ # also ab 'subnet 192.168.3.' if ($tempzeile =~ /^\s*$/) { # wenn Leerzeile # dann machen wir nichts # dann verwerfen } elsif ($tempzeile =~ /^\s*}\s*$/) { # wenn nur die Klammer $bereich++; # dann nächster Bereich } else { # alles andere kopieren $teilnetz3 .= $tempzeile; } } } close DATEI; push @ergebnis, $kopfzeile; push @ergebnis, $teilnetz0; push @ergebnis, $teilnetz1; push @ergebnis, $teilnetz2; push @ergebnis, $teilnetz3; return @ergebnis; } # hier werden die Einträge fuer die Rechner erzeugt. Da Arktur 4 # Teilnetze hat werden also 4 Strings erzeugt und als Liste zurueckgegeben sub erstelle_rechnereintrag { my @liste = @_; my $host = ""; my $ip = ""; my $mac = ""; my $text = ""; my @erg = (); foreach my $tn (0..3){ $text = "\n"; foreach my $x (@liste){ ($host,$ip,$mac) = split '/', $x; if ($ip =~ m/^192\.168\.$tn\./){ $text .= sprintf(" host %-11s { hardware ethernet %17s;\n", $host, $mac); $text .= sprintf(" fixed-address ".$ip.";}\n"); } } $text .= "}\n\n"; # noch die Zeile mit Klammer push @erg, $text; } return @erg; } # hier werden einfach die vorher zusammengebauten Strings zusammen- # gesetzt und als neue dhcpd.conf.neu abgespeichert sub erstelle_neue_dhcpdconf { my $txt = ""; my $meldung = ""; $txt .= $tmp1[0]; $txt .= $tmp1[1]; $txt .= $tmp2[0]; $txt .= $tmp1[2]; $txt .= $tmp2[1]; $txt .= $tmp1[3]; $txt .= $tmp2[2]; $txt .= $tmp1[4]; $txt .= $tmp2[3]; open DATEI, '>'.$conf_neu; print DATEI $txt; close DATEI; return $meldung; } sub zeige_datei { my $meineDatei = $_[0]; my $header = "Content-type: text/html\n\n"; my $meinstring = ""; my @zeilen = (); $meinstring = $header; $meinstring .= '
';

  open  DATEI, '<'.$meineDatei;
  @zeilen      = ;
  close DATEI;

  foreach my $x (@zeilen) {
    $meinstring .= $x;
  }

  $meinstring .= '
'; return $meinstring; }