Code

Namensänderungen
authorrettenbe <rettenbe@594d385d-05f5-0310-b6e9-bd551577e9d8>
Wed, 31 Oct 2007 09:58:28 +0000 (09:58 +0000)
committerrettenbe <rettenbe@594d385d-05f5-0310-b6e9-bd551577e9d8>
Wed, 31 Oct 2007 09:58:28 +0000 (09:58 +0000)
gosa-sd -> arp-handler-d

git-svn-id: https://oss.gonicus.de/repositories/gosa/trunk@7697 594d385d-05f5-0310-b6e9-bd551577e9d8

contrib/daemon/arp-handler-d [new file with mode: 0755]
contrib/daemon/arp-handler-d.cfg [new file with mode: 0644]
contrib/daemon/gosa-sd [deleted file]
contrib/daemon/gosa-sd-bus [new file with mode: 0755]
contrib/daemon/gosa-sd-bus.cfg [new file with mode: 0644]

diff --git a/contrib/daemon/arp-handler-d b/contrib/daemon/arp-handler-d
new file mode 100755 (executable)
index 0000000..b8698bc
--- /dev/null
@@ -0,0 +1,563 @@
+#!/usr/bin/perl 
+#===============================================================================
+#
+#         FILE:  gosa-support-daemon.pl
+#
+#        USAGE:  ./.gosa-support-daemon.pl
+#
+#  DESCRIPTION:  
+#
+#      OPTIONS:  ---
+# REQUIREMENTS:  ---
+#         BUGS:  ---
+#        NOTES:  ---
+#       AUTHOR:   Andreas Rettenberger, <rettenberger@gonicus.de>
+#      COMPANY:  Gonicus GmbH, Arnsberg
+#      VERSION:  1.0
+#      CREATED:  21.08.2007 15:13:51 CEST
+#     REVISION:  ---
+#===============================================================================
+
+use strict;
+use warnings;
+use Getopt::Long;
+use Config::IniFiles;
+use POSIX;
+use Fcntl;
+use Net::LDAP;
+use Net::LDAP::LDIF;
+use Net::LDAP::Entry;
+use Switch;
+
+
+my ($verbose, $cfg_file, $log_file, $pid_file, $foreground); 
+my ($timeout, $mailto, $mailfrom, $user, $group);
+my ($procid, $pid, $loglevel);
+my ($fifo_path, $max_process_timeout, $max_process );
+my %daemon_children;
+my ($ldap, $bind_phrase, $password, $ldap_base) ;
+
+$procid = -1 ;
+$foreground = 0 ;
+$verbose = 0 ;
+$max_process = 2 ;
+$max_process_timeout = 1 ;
+$ldap_base = "dc=gonicus,dc=de" ;
+#$ldap_path = "/var/run/gosa-support-daemon.socket";
+#$log_path = "/var/log/gosa-support-daemon.log";
+#$pid_path = "/var/run/gosa-support-daemon/gosa-support-daemon.pid";
+
+#---------------------------------------------------------------------------
+#  parse commandline options
+#---------------------------------------------------------------------------
+Getopt::Long::Configure( "bundling" );
+GetOptions( "v|verbose+" => \$verbose,
+        "c|config=s" => \$cfg_file,
+        "h|help" => \&usage,
+        "l|logfile=s" => \$log_file,
+        "p|pid=s" => \$pid_file,
+        "f|foreground" => \$foreground);
+
+#---------------------------------------------------------------------------
+#  read and set config parameters
+#---------------------------------------------------------------------------
+my %cfg_defaults =
+("Allgemein" =>
+ {"timeout"  => [ \$timeout, 1000 ],
+ "mailto"   => [ \$mailto, 'root@localhost' ],
+ "mailfrom" => [ \$mailfrom, 'sps-daemon@localhost' ],
+ "user"     => [ \$user, "nobody" ],
+ "group"    => [ \$group, "nogroup" ],
+ "fifo_path" => [ \$fifo_path, "/home/rettenbe/gonicus/gosa-support/tmp/fifo" ],
+ "log_file"  => [ \$log_file, "/home/rettenbe/gonicus/gosa-support/tmp/gosa-support.log" ],
+ "pid_file"  => [ \$pid_file, "/home/rettenbe/gonicus/gosa-support/tmp/gosa-support.pid" ],
+ "loglevel"     => [ \$loglevel, 1]
+ },
+"LDAP"  =>
+    {"bind" => [ \$bind_phrase, "cn=ldapadmin,dc=gonicus,dc=de" ],
+     "password" => [ \$password, "tester" ],
+    }
+ );
+&read_configfile;
+
+
+#===  FUNCTION  ================================================================
+#         NAME:  check_cmdline_param
+#      PURPOSE:  checks all commandline parameters to validity
+#   PARAMETERS:  none
+#      RETURNS:  none
+#  DESCRIPTION:  ????
+#       THROWS:  no exceptions
+#     COMMENTS:  none
+#     SEE ALSO:  n/a
+#===============================================================================
+sub check_cmdline_param () {
+    my $err_config;
+    my $err_log;
+    my $err_pid;
+    my $err_counter = 0;
+    if( not defined( $cfg_file)) {
+        $err_config = "please specify a config file";
+        $err_counter += 1;
+    }
+    if( not defined( $log_file)) {
+        $err_log = "please specify a log file";
+        $err_counter += 1;
+    }
+    if( not defined( $pid_file)) {
+        $err_pid = "please specify a pid file";
+        $err_counter += 1;
+    }
+    if( $err_counter > 0 ) {
+        &usage( "", 1 );
+        if( defined( $err_config)) { print STDERR "$err_config\n"}
+        if( defined( $err_log)) { print STDERR "$err_log\n" }
+        if( defined( $err_pid)) { print STDERR "$err_pid\n"}
+        print STDERR "\n";
+        exit( -1 );
+    }
+}
+
+#===  FUNCTION  ================================================================
+#         NAME:  check_pid
+#      PURPOSE:  
+#   PARAMETERS:  none
+#      RETURNS:  none
+#  DESCRIPTION:  ????
+#       THROWS:  no exceptions
+#     COMMENTS:  none
+#     SEE ALSO:  n/a
+#===============================================================================
+sub check_pid { 
+    if( open( LOCK_FILE, "<$pid_file") ) {
+        $procid = <LOCK_FILE>;
+        if( defined $procid ) {
+            chomp( $procid );
+            if( -f "/proc/$procid/stat" ) {
+                my($stat) = `cat /proc/$procid/stat` =~ m/$procid \((.+)\).*/;
+                print "\t".$stat."\n";
+                if( "sps-daemon.pl" eq $stat ) {
+                    close( LOCK_FILE );
+                    exit -1;
+                }
+            }
+        }
+        close( LOCK_FILE );
+        unlink( $pid_file );
+    }
+
+    # Try to open PID file
+    if (!sysopen(LOCK_FILE, $pid_file, O_WRONLY|O_CREAT|O_EXCL, 0644)) {
+        my($msg) = "Couldn't obtain lockfile '$pid_file' ";
+        if (open(LOCK_FILE, "<", $pid_file) && ($pid = <LOCK_FILE>)) {
+            chomp($pid);
+            $msg .= "(PID $pid)\n";
+        } else {
+            $msg .= "(unable to read PID)\n";
+        }
+        if ( ! $foreground ) {
+            daemon_log( $msg."\n");
+        } else {
+            print( STDERR " $msg " );
+        }
+        exit( -1 );
+    }
+}
+
+#===  FUNCTION  ================================================================
+#         NAME:  read_configfile
+#      PURPOSE:  read the configuration file and provide the programm with 
+#                parameters
+#   PARAMETERS:  none
+#      RETURNS:  none
+#  DESCRIPTION:  ????
+#       THROWS:  no exceptions
+#     COMMENTS:  none
+#     SEE ALSO:  n/a
+#===============================================================================
+sub read_configfile {
+    my $log_time = localtime(time);
+    my $cfg;
+    if( defined( $cfg_file) && ( length($cfg_file) > 0 )) {
+        if( -r $cfg_file ) { 
+            $cfg = Config::IniFiles->new( -file => $cfg_file ); 
+        } else { 
+            usage( "Couldn't read config file: $cfg_file \n" ); 
+        }
+    } else { 
+        $cfg = Config::IniFiles->new() ; 
+    }
+
+    foreach my $section (keys %cfg_defaults) {      # "Parse" config into values
+        foreach my $param (keys %{$cfg_defaults{ $section }}) {
+            my $pinfo = $cfg_defaults{ $section }{ $param };
+            ${@$pinfo[ 0 ]} = $cfg->val( $section, $param, @$pinfo[ 1 ] );
+        }
+    }
+
+    if(-e $log_file ) { unlink $log_file }
+    daemon_log("$log_time: config file read\n");
+}
+
+#===  FUNCTION  ================================================================
+#         NAME:  daemon_log
+#      PURPOSE:  log messages to specified logfile
+#   PARAMETERS:  $msg, $level
+#      RETURNS:  ????
+#  DESCRIPTION:  Takes a message ($msg) and append it to the logfile. The 
+#                standard log-level ($level) is 1. Messages whith higher level
+#                than the verbosity-level (defined by commandline) are printed 
+#                out to commandline. Messages with log-level lower than 2 are 
+#                not logged to logfile!
+#       THROWS:  no exceptions
+#     COMMENTS:  none
+#     SEE ALSO:  n/a
+#===============================================================================
+sub daemon_log {
+    my( $msg, $level ) = @_;
+    if(not defined $msg) { return } 
+    if(not defined $level) { $level = 1 }
+    open(LOG_HANDLE, ">>$log_file");
+    if(not defined open( LOG_HANDLE, ">>$log_file" ) ) { return }
+    chomp($msg);
+    #if( $verbose >= $level ) { print "$msg"."\n" }
+    if( $level <= 1 ) { print LOG_HANDLE $msg."\n"  }
+    if( $foreground ) { print $msg."\n" }
+    close( LOG_HANDLE );
+    }
+
+#===  FUNCTION  ================================================================
+#         NAME:  signal handler
+#      PURPOSE:  catches signals from the programm and do diffrent things 
+#                than default
+#   PARAMETERS:  none
+#      RETURNS:  none
+#  DESCRIPTION:  sighandler
+#       THROWS:  no exceptions
+#     COMMENTS:  none
+#     SEE ALSO:  n/a
+#===============================================================================
+sub sigINT {
+    my $log_time = localtime(time);
+    print "INT\n";
+    if( -p $fifo_path ) {
+        close FIFO  ;
+        unlink($fifo_path) ;
+        daemon_log( "$log_time: FIFO closed after signal INT!\n") ;
+        }
+    if(defined($ldap)) {
+        $ldap->unbind;
+    }
+    $SIG{INT} = "DEFAULT" ;
+    kill INT => $$ ;
+}
+$SIG{INT} = \&sigINT ;
+
+#===  FUNCTION  ================================================================
+#         NAME:  usage
+#      PURPOSE:  
+#   PARAMETERS:  none
+#      RETURNS:  none
+#  DESCRIPTION:  print out the usage of the program
+#       THROWS:  no exceptions
+#     COMMENTS:  none
+#     SEE ALSO:  n/a
+#===============================================================================
+sub usage {
+        my( $text, $help ) = @_;
+        $text = undef if( "h" eq $text );
+        (defined $text) && print STDERR "\n$text\n";
+        if( (defined $help && $help) || (!defined $help && !defined $text) ) {
+                print STDERR << "EOF" ;
+usage: $0 [-hvf] [-c config, -l logfile, -p pidfile]
+
+    -h        : this (help) message
+    -c <file> : config file
+    -l <file> : log file (example: /var/log/sps/sps.log)
+    -p <file> : pid file (example: /var/run/sps/sps.pid)
+    -f        : foreground (don"t fork)
+    -v        : be verbose (multiple to increase verbosity)
+EOF
+        }
+        print "\n" ;
+}
+
+
+#===  FUNCTION  ================================================================
+#         NAME:  open_fifo
+#      PURPOSE:  
+#   PARAMETERS:  $fifo_path
+#      RETURNS:  0: FIFO couldn"t be setup, 1: FIFO setup correctly
+#  DESCRIPTION:  creates a FIFO at $fifo_path
+#       THROWS:  no exceptions
+#     COMMENTS:  none
+#     SEE ALSO:  n/a
+#===============================================================================
+sub open_fifo {
+    my ($fifo_path) = @_ ;
+    my $log_time = localtime( time );
+    if( -p $fifo_path ) {
+        daemon_log("$log_time: FIFO at $fifo_path already exists\n");
+        return 0;
+        } 
+    POSIX::mkfifo($fifo_path, 0666) or die "can't mkfifo $fifo_path: $!";
+    daemon_log( "$log_time: FIFO started at $fifo_path\n" ) ;
+    return 1;
+    }
+
+
+#===  FUNCTION  ================================================================
+#         NAME:  add_ldap_entry
+#      PURPOSE:  adds an element to ldap-tree
+#   PARAMETERS:  
+#      RETURNS:  none
+#  DESCRIPTION:  ????
+#       THROWS:  no exceptions
+#     COMMENTS:  none
+#     SEE ALSO:  n/a
+#===============================================================================
+sub add_ldap_entry {
+    my ($ldap_tree, $ldap_base, $mac, $gotoSysStatus, $ip, $interface, $desc) = @_;
+    my $dn = "cn=$mac,ou=incoming,$ldap_base";
+    my $s_res = &search_ldap_entry($ldap_tree, $ldap_base, "(|(macAddress=$mac)(dhcpHWAddress=ethernet $mac))");
+    my $c_res = $s_res->count;
+    if($c_res == 1) {
+        daemon_log("WARNING: macAddress $mac already in LDAP", 1);
+        return;
+    } elsif($c_res > 0) {
+        daemon_log("ERROR: macAddress $mac exists $c_res times in LDAP", 1);
+        return;
+    }
+
+    # create LDAP entry 
+    my $entry = Net::LDAP::Entry->new( $dn );
+    $entry->dn($dn);
+    $entry->add("objectClass" => "goHard");
+    $entry->add("cn" => $mac);
+    $entry->add("macAddress" => $mac);
+    if(defined $gotoSysStatus) {$entry->add("gotoSysStatus" => $gotoSysStatus)}
+    if(defined $ip) {$entry->add("ipHostNumber" => $ip) }
+    #if(defined $interface) { }
+    if(defined $desc) {$entry->add("description" => $desc) }
+    
+    # submit entry to LDAP
+    my $result = $entry->update ($ldap_tree); 
+        
+    # for $result->code constants please look at Net::LDAP::Constant
+    my $log_time = localtime( time );
+    if($result->code == 68) {   # entry already exists 
+        daemon_log("WARNING: $log_time: $dn ".$result->error, 3);
+    } elsif($result->code == 0) {   # everything went fine
+        daemon_log("$log_time: add entry $dn to ldap", 1);
+    } else {  # if any other error occur
+        daemon_log("ERROR: $log_time: $dn, ".$result->code.", ".$result->error, 1);
+    }
+    return;
+}
+
+
+#===  FUNCTION  ================================================================
+#         NAME:  change_ldap_entry
+#      PURPOSE:  ????
+#   PARAMETERS:  ????
+#      RETURNS:  ????
+#  DESCRIPTION:  ????
+#       THROWS:  no exceptions
+#     COMMENTS:  none
+#     SEE ALSO:  n/a
+#===============================================================================
+sub change_ldap_entry {
+    my ($ldap_tree, $ldap_base, $mac, $gotoSysStatus ) = @_;
+    
+    # check if ldap_entry exists or not
+    my $s_res = &search_ldap_entry($ldap_tree, $ldap_base, "(|(macAddress=$mac)(dhcpHWAddress=ethernet $mac))");
+    my $c_res = $s_res->count;
+    if($c_res == 0) {
+        daemon_log("WARNING: macAddress $mac not in LDAP", 1);
+        return;
+    } elsif($c_res > 1) {
+        daemon_log("ERROR: macAddress $mac exists $c_res times in LDAP", 1);
+        return;
+    }
+
+    my $s_res_entry = $s_res->pop_entry();
+    my $dn = $s_res_entry->dn();
+    my $result = $ldap->modify( $dn, replace => {'gotoSysStatus' => $gotoSysStatus } );
+
+    # for $result->code constants please look at Net::LDAP::Constant
+    my $log_time = localtime( time );
+    if($result->code == 32) {   # entry doesnt exists 
+        &add_ldap_entry($mac, $gotoSysStatus);
+    } elsif($result->code == 0) {   # everything went fine
+        daemon_log("$log_time: entry $dn changed successful", 1);
+    } else {  # if any other error occur
+        daemon_log("ERROR: $log_time: $dn, ".$result->code.", ".$result->error, 1);
+    }
+
+    return;
+}
+
+#===  FUNCTION  ================================================================
+#         NAME:  search_ldap_entry
+#      PURPOSE:  ????
+#   PARAMETERS:  [Net::LDAP] $ldap_tree - object of an ldap-tree
+#                string $sub_tree - dn of the subtree the search is performed
+#                string $search_string - either a string or a Net::LDAP::Filter object
+#      RETURNS:  [Net::LDAP::Search] $msg - result object of the performed search
+#  DESCRIPTION:  ????
+#       THROWS:  no exceptions
+#     COMMENTS:  none
+#     SEE ALSO:  n/a
+#===============================================================================
+sub search_ldap_entry {
+    my ($ldap_tree, $sub_tree, $search_string) = @_;
+    my $msg = $ldap_tree->search( # perform a search
+                        base   => $sub_tree,
+                        filter => $search_string,
+                      ) or daemon_log("cannot perform search at ldap: $@", 1);
+#    if(defined $msg) {
+#        print $sub_tree."\t".$search_string."\t";
+#        print $msg->count."\n";
+#        foreach my $entry ($msg->entries) { $entry->dump; };
+#    }
+
+    return $msg;
+}
+
+
+
+#========= MAIN = main ========================================================
+daemon_log( "####### START DAEMON ######\n", 1 );
+&check_cmdline_param ;
+&check_pid;
+&open_fifo($fifo_path);
+
+# Just fork, if we"re not in foreground mode
+if( ! $foreground ) { $pid = fork(); }
+else { $pid = $$; }
+
+# Do something useful - put our PID into the pid_file
+if( 0 != $pid ) {
+    open( LOCK_FILE, ">$pid_file" );
+    print LOCK_FILE "$pid\n";
+    close( LOCK_FILE );
+    if( !$foreground ) { exit( 0 ) };
+}
+
+
+if( not -p $fifo_path ) { die "fifo file disappeared\n" }
+sysopen(FIFO, $fifo_path, O_RDONLY) or die "can't read from $fifo_path: $!" ;
+
+while( 1 ) {
+    # checke alle prozesse im hash daemon_children ob sie noch aktiv sind, wenn
+    # nicht, dann entferne prozess aus hash
+    while( (my $key, my $val) = each( %daemon_children) ) {
+        my $status = waitpid( $key, &WNOHANG) ;
+        if( $status == -1 ) { 
+            delete $daemon_children{$key} ; 
+            daemon_log("childprocess finished: $key", 3) ;
+        }
+    }
+
+    # ist die max_process anzahl von prozesskindern erreicht, dann warte und 
+    # prüfe erneut, ob in der zwischenzeit prozesse fertig geworden sind
+    if( keys( %daemon_children ) >= $max_process ) { 
+        sleep($max_process_timeout) ;
+        next ;
+    }
+
+    my $msg = <FIFO>;
+    if( not defined( $msg )) { next ; }
+    
+    chomp( $msg );
+    if( length( $msg ) == 0 ) { next ; }
+
+    my $forked_pid = fork();
+#=== PARENT = parent ==========================================================
+    if ( $forked_pid != 0 ) { 
+        daemon_log("childprocess forked: $forked_pid", 3) ;
+        $daemon_children{$forked_pid} = 0 ;
+    }
+#=== CHILD = child ============================================================
+    else {
+        # parse the incoming message from arp, split the message and return 
+        # the values in an array. not defined values are set to "none" 
+        #my ($mac, $ip, $interface, $arp_sig, $desc) = &parse_input( $msg ) ;
+        daemon_log( "childprocess read from arp: $fifo_path\nline: $msg", 3);
+        my ($mac, $ip, $interface, $arp_sig, $desc) = split('\s', $msg, 5);
+
+        # create connection to LDAP
+        $ldap = Net::LDAP->new( "localhost" ) or die "$@";
+        $ldap->bind($bind_phrase,
+                    password => $password,
+                    ) ;
+        
+        switch($arp_sig) {
+            case 0 {&change_ldap_entry($ldap, $ldap_base, 
+                                      $mac, "ip-changed",
+                                      )} 
+            case 1 {&change_ldap_entry($ldap, $ldap_base, 
+                                      $mac, "mac-not-whitelisted",
+                                      )}
+            case 2 {&change_ldap_entry($ldap, $ldap_base, 
+                                      $mac, "mac-in-blacklist",
+                                      )}
+            case 3 {&add_ldap_entry($ldap, $ldap_base, 
+                                   $mac, "new-mac-address", $ip, 
+                                   $interface, $desc, 
+                                   )}
+            case 4 {&change_ldap_entry($ldap, $ldap_base, 
+                                      $mac, "unauthorized-arp-request",
+                                      )}
+            case 5 {&change_ldap_entry($ldap, $ldap_base, 
+                                      $mac, "abusive-number-of-arp-requests",
+                                      )}
+            case 6 {&change_ldap_entry($ldap, $ldap_base, 
+                                      $mac, "ether-and-arp-mac-differs",
+                                      )}
+            case 7 {&change_ldap_entry($ldap, $ldap_base, 
+                                      $mac, "flood-detected",
+                                      )}
+            case 8 {&add_ldap_entry($ldap, $ldap_base, 
+                                   $mac, $ip, "new-system",
+                                   )}
+            case 9 {&change_ldap_entry($ldap, $ldap_base, 
+                                      $mac, "mac-changed",
+                                      )}
+        }
+
+
+        # ldap search
+#        my $base_phrase = "dc=gonicus,dc=de";
+#        my $filter_phrase = "cn=keinesorge";
+#        my $attrs_phrase = "cn macAdress";
+#        my $msg_search = $ldap->search( base   => $base_phrase,
+#                                        filter => $filter_phrase,
+#                                        attrs => $attrs_phrase,
+#                                        );
+#        $msg_search->code && die $msg_search->error;
+#        
+#        my @entries = $msg_search->entries;
+#        my $max = $msg_search->count;
+#        print "anzahl der entries: $max\n";
+#        my $i;
+#        for ( $i = 0 ; $i < $max ; $i++ ) {
+#            my $entry = $msg_search->entry ( $i );
+#            foreach my $attr ( $entry->attributes ) {
+#                if( not $attr eq "cn") {
+#                    next;
+#                }
+#                print join( "\n ", $attr, $entry->get_value( $attr ) ), "\n\n";
+#            }
+#        }
+
+        # ldap add
+       
+        
+        $ldap->unbind;
+        exit;
+    }
+
+}
+
+
diff --git a/contrib/daemon/arp-handler-d.cfg b/contrib/daemon/arp-handler-d.cfg
new file mode 100644 (file)
index 0000000..36c24a3
--- /dev/null
@@ -0,0 +1,14 @@
+[Allgemein]
+timeout   = 1000 
+mailto    = root@localhost
+mailfrom  = gosa-sd@localhost
+user      = rettenbe
+group     = usr
+fifo_path = /home/rettenbe/gonicus/projekte/gosa-trunk/contrib/daemon/fifo
+log_file  = /home/rettenbe/gonicus/projekte/gosa-trunk/contrib/daemon/gosa-sd.log
+pid_file  = /home/rettenbe/gonicus/projekte/gosa-trunk/contrib/daemon/gosa-sd.pid
+loglevel  = 1
+
+[LDAP]
+bind     = cn=ldapadmin,dc=gonicus,dc=de 
+password = tester
diff --git a/contrib/daemon/gosa-sd b/contrib/daemon/gosa-sd
deleted file mode 100755 (executable)
index 3db6576..0000000
+++ /dev/null
@@ -1,562 +0,0 @@
-#!/usr/bin/perl 
-#===============================================================================
-#
-#         FILE:  gosa-support-daemon.pl
-#
-#        USAGE:  ./.gosa-support-daemon.pl
-#
-#  DESCRIPTION:  
-#
-#      OPTIONS:  ---
-# REQUIREMENTS:  ---
-#         BUGS:  ---
-#        NOTES:  ---
-#       AUTHOR:   Andreas Rettenberger, <rettenberger@gonicus.de>
-#      COMPANY:  Gonicus GmbH, Arnsberg
-#      VERSION:  1.0
-#      CREATED:  21.08.2007 15:13:51 CEST
-#     REVISION:  ---
-#===============================================================================
-
-use strict;
-use warnings;
-use Getopt::Long;
-use Config::IniFiles;
-use POSIX;
-use Fcntl;
-use Net::LDAP;
-use Net::LDAP::LDIF;
-use Net::LDAP::Entry;
-use Switch;
-
-
-my ($verbose, $cfg_file, $log_file, $pid_file, $foreground); 
-my ($timeout, $mailto, $mailfrom, $user, $group);
-my ($procid, $pid, $loglevel);
-my ($fifo_path, $max_process_timeout, $max_process );
-my %daemon_children;
-my ($ldap, $bind_phrase, $password, $ldap_base) ;
-
-$procid = -1 ;
-$foreground = 0 ;
-$verbose = 0 ;
-$max_process = 2 ;
-$max_process_timeout = 1 ;
-$ldap_base = "dc=gonicus,dc=de" ;
-#$ldap_path = "/var/run/gosa-support-daemon.socket";
-#$log_path = "/var/log/gosa-support-daemon.log";
-#$pid_path = "/var/run/gosa-support-daemon/gosa-support-daemon.pid";
-
-#---------------------------------------------------------------------------
-#  parse commandline options
-#---------------------------------------------------------------------------
-Getopt::Long::Configure( "bundling" );
-GetOptions( "v|verbose+" => \$verbose,
-        "c|config=s" => \$cfg_file,
-        "h|help" => \&usage,
-        "l|logfile=s" => \$log_file,
-        "p|pid=s" => \$pid_file,
-        "f|foreground" => \$foreground);
-
-#---------------------------------------------------------------------------
-#  read and set config parameters
-#---------------------------------------------------------------------------
-my %cfg_defaults =
-("Allgemein" =>
- {"timeout"  => [ \$timeout, 1000 ],
- "mailto"   => [ \$mailto, 'root@localhost' ],
- "mailfrom" => [ \$mailfrom, 'sps-daemon@localhost' ],
- "user"     => [ \$user, "nobody" ],
- "group"    => [ \$group, "nogroup" ],
- "fifo_path" => [ \$fifo_path, "/home/rettenbe/gonicus/gosa-support/tmp/fifo" ],
- "log_file"  => [ \$log_file, "/home/rettenbe/gonicus/gosa-support/tmp/gosa-support.log" ],
- "pid_file"  => [ \$pid_file, "/home/rettenbe/gonicus/gosa-support/tmp/gosa-support.pid" ],
- "loglevel"     => [ \$loglevel, 1]
- },
-"LDAP"  =>
-    {"bind" => [ \$bind_phrase, "cn=ldapadmin,dc=gonicus,dc=de" ],
-     "password" => [ \$password, "tester" ],
-    }
- );
-&read_configfile;
-
-
-#===  FUNCTION  ================================================================
-#         NAME:  check_cmdline_param
-#      PURPOSE:  checks all commandline parameters to validity
-#   PARAMETERS:  none
-#      RETURNS:  none
-#  DESCRIPTION:  ????
-#       THROWS:  no exceptions
-#     COMMENTS:  none
-#     SEE ALSO:  n/a
-#===============================================================================
-sub check_cmdline_param () {
-    my $err_config;
-    my $err_log;
-    my $err_pid;
-    my $err_counter = 0;
-    if( not defined( $cfg_file)) {
-        $err_config = "please specify a config file";
-        $err_counter += 1;
-    }
-    if( not defined( $log_file)) {
-        $err_log = "please specify a log file";
-        $err_counter += 1;
-    }
-    if( not defined( $pid_file)) {
-        $err_pid = "please specify a pid file";
-        $err_counter += 1;
-    }
-    if( $err_counter > 0 ) {
-        &usage( "", 1 );
-        if( defined( $err_config)) { print STDERR "$err_config\n"}
-        if( defined( $err_log)) { print STDERR "$err_log\n" }
-        if( defined( $err_pid)) { print STDERR "$err_pid\n"}
-        print STDERR "\n";
-        exit( -1 );
-    }
-}
-
-#===  FUNCTION  ================================================================
-#         NAME:  check_pid
-#      PURPOSE:  
-#   PARAMETERS:  none
-#      RETURNS:  none
-#  DESCRIPTION:  ????
-#       THROWS:  no exceptions
-#     COMMENTS:  none
-#     SEE ALSO:  n/a
-#===============================================================================
-sub check_pid { 
-    if( open( LOCK_FILE, "<$pid_file") ) {
-        $procid = <LOCK_FILE>;
-        if( defined $procid ) {
-            chomp( $procid );
-            if( -f "/proc/$procid/stat" ) {
-                my($stat) = `cat /proc/$procid/stat` =~ m/$procid \((.+)\).*/;
-                print "\t".$stat."\n";
-                if( "sps-daemon.pl" eq $stat ) {
-                    close( LOCK_FILE );
-                    exit -1;
-                }
-            }
-        }
-        close( LOCK_FILE );
-        unlink( $pid_file );
-    }
-
-    # Try to open PID file
-    if (!sysopen(LOCK_FILE, $pid_file, O_WRONLY|O_CREAT|O_EXCL, 0644)) {
-        my($msg) = "Couldn't obtain lockfile '$pid_file' ";
-        if (open(LOCK_FILE, "<", $pid_file) && ($pid = <LOCK_FILE>)) {
-            chomp($pid);
-            $msg .= "(PID $pid)\n";
-        } else {
-            $msg .= "(unable to read PID)\n";
-        }
-        if ( ! $foreground ) {
-            daemon_log( $msg."\n");
-        } else {
-            print( STDERR " $msg " );
-        }
-        exit( -1 );
-    }
-}
-
-#===  FUNCTION  ================================================================
-#         NAME:  read_configfile
-#      PURPOSE:  read the configuration file and provide the programm with 
-#                parameters
-#   PARAMETERS:  none
-#      RETURNS:  none
-#  DESCRIPTION:  ????
-#       THROWS:  no exceptions
-#     COMMENTS:  none
-#     SEE ALSO:  n/a
-#===============================================================================
-sub read_configfile {
-    my $log_time = localtime(time);
-    my $cfg;
-    if( defined( $cfg_file) && ( length($cfg_file) > 0 )) {
-        if( -r $cfg_file ) { 
-            $cfg = Config::IniFiles->new( -file => $cfg_file ); 
-        } else { 
-            usage( "Couldn't read config file: $cfg_file \n" ); 
-        }
-    } else { 
-        $cfg = Config::IniFiles->new() ; 
-    }
-
-    foreach my $section (keys %cfg_defaults) {      # "Parse" config into values
-        foreach my $param (keys %{$cfg_defaults{ $section }}) {
-            my $pinfo = $cfg_defaults{ $section }{ $param };
-            ${@$pinfo[ 0 ]} = $cfg->val( $section, $param, @$pinfo[ 1 ] );
-        }
-    }
-
-    if(-e $log_file ) { unlink $log_file }
-    daemon_log("$log_time: config file read\n");
-}
-
-#===  FUNCTION  ================================================================
-#         NAME:  daemon_log
-#      PURPOSE:  log messages to specified logfile
-#   PARAMETERS:  $msg, $level
-#      RETURNS:  ????
-#  DESCRIPTION:  Takes a message ($msg) and append it to the logfile. The 
-#                standard log-level ($level) is 1. Messages whith higher level
-#                than the verbosity-level (defined by commandline) are printed 
-#                out to commandline. Messages with log-level lower than 2 are 
-#                not logged to logfile!
-#       THROWS:  no exceptions
-#     COMMENTS:  none
-#     SEE ALSO:  n/a
-#===============================================================================
-sub daemon_log {
-    my( $msg, $level ) = @_;
-    if(not defined $msg) { return } 
-    if(not defined $level) { $level = 1 }
-    open(LOG_HANDLE, ">>$log_file");
-    if(not defined open( LOG_HANDLE, ">>$log_file" ) ) { return }
-    chomp($msg);
-    if( $verbose >= $level ) { print "$msg"."\n" }
-    if( $level <= 1 ) { print LOG_HANDLE $msg."\n"  }
-    close( LOG_HANDLE );
-    }
-
-#===  FUNCTION  ================================================================
-#         NAME:  signal handler
-#      PURPOSE:  catches signals from the programm and do diffrent things 
-#                than default
-#   PARAMETERS:  none
-#      RETURNS:  none
-#  DESCRIPTION:  sighandler
-#       THROWS:  no exceptions
-#     COMMENTS:  none
-#     SEE ALSO:  n/a
-#===============================================================================
-sub sigINT {
-    my $log_time = localtime(time);
-    print "INT\n";
-    if( -p $fifo_path ) {
-        close FIFO  ;
-        unlink($fifo_path) ;
-        daemon_log( "$log_time: FIFO closed after signal INT!\n") ;
-        }
-    if(defined($ldap)) {
-        $ldap->unbind;
-    }
-    $SIG{INT} = "DEFAULT" ;
-    kill INT => $$ ;
-}
-$SIG{INT} = \&sigINT ;
-
-#===  FUNCTION  ================================================================
-#         NAME:  usage
-#      PURPOSE:  
-#   PARAMETERS:  none
-#      RETURNS:  none
-#  DESCRIPTION:  print out the usage of the program
-#       THROWS:  no exceptions
-#     COMMENTS:  none
-#     SEE ALSO:  n/a
-#===============================================================================
-sub usage {
-        my( $text, $help ) = @_;
-        $text = undef if( "h" eq $text );
-        (defined $text) && print STDERR "\n$text\n";
-        if( (defined $help && $help) || (!defined $help && !defined $text) ) {
-                print STDERR << "EOF" ;
-usage: $0 [-hvf] [-c config, -l logfile, -p pidfile]
-
-    -h        : this (help) message
-    -c <file> : config file
-    -l <file> : log file (example: /var/log/sps/sps.log)
-    -p <file> : pid file (example: /var/run/sps/sps.pid)
-    -f        : foreground (don"t fork)
-    -v        : be verbose (multiple to increase verbosity)
-EOF
-        }
-        print "\n" ;
-}
-
-
-#===  FUNCTION  ================================================================
-#         NAME:  open_fifo
-#      PURPOSE:  
-#   PARAMETERS:  $fifo_path
-#      RETURNS:  0: FIFO couldn"t be setup, 1: FIFO setup correctly
-#  DESCRIPTION:  creates a FIFO at $fifo_path
-#       THROWS:  no exceptions
-#     COMMENTS:  none
-#     SEE ALSO:  n/a
-#===============================================================================
-sub open_fifo {
-    my ($fifo_path) = @_ ;
-    my $log_time = localtime( time );
-    if( -p $fifo_path ) {
-        daemon_log("$log_time: FIFO at $fifo_path already exists\n");
-        return 0;
-        } 
-    POSIX::mkfifo($fifo_path, 0666) or die "can't mkfifo $fifo_path: $!";
-    daemon_log( "$log_time: FIFO started at $fifo_path\n" ) ;
-    return 1;
-    }
-
-
-#===  FUNCTION  ================================================================
-#         NAME:  add_ldap_entry
-#      PURPOSE:  adds an element to ldap-tree
-#   PARAMETERS:  
-#      RETURNS:  none
-#  DESCRIPTION:  ????
-#       THROWS:  no exceptions
-#     COMMENTS:  none
-#     SEE ALSO:  n/a
-#===============================================================================
-sub add_ldap_entry {
-    my ($ldap_tree, $ldap_base, $mac, $gotoSysStatus, $ip, $interface, $desc) = @_;
-    my $dn = "cn=$mac,ou=incoming,$ldap_base";
-    my $s_res = &search_ldap_entry($ldap_tree, $ldap_base, "(|(macAddress=$mac)(dhcpHWAddress=ethernet $mac))");
-    my $c_res = $s_res->count;
-    if($c_res == 1) {
-        daemon_log("WARNING: macAddress $mac already in LDAP", 1);
-        return;
-    } elsif($c_res > 0) {
-        daemon_log("ERROR: macAddress $mac exists $c_res times in LDAP", 1);
-        return;
-    }
-
-    # create LDAP entry 
-    my $entry = Net::LDAP::Entry->new( $dn );
-    $entry->dn($dn);
-    $entry->add("objectClass" => "goHard");
-    $entry->add("cn" => $mac);
-    $entry->add("macAddress" => $mac);
-    if(defined $gotoSysStatus) {$entry->add("gotoSysStatus" => $gotoSysStatus)}
-    if(defined $ip) {$entry->add("ipHostNumber" => $ip) }
-    #if(defined $interface) { }
-    if(defined $desc) {$entry->add("description" => $desc) }
-    
-    # submit entry to LDAP
-    my $result = $entry->update ($ldap_tree); 
-        
-    # for $result->code constants please look at Net::LDAP::Constant
-    my $log_time = localtime( time );
-    if($result->code == 68) {   # entry already exists 
-        daemon_log("WARNING: $log_time: $dn ".$result->error, 3);
-    } elsif($result->code == 0) {   # everything went fine
-        daemon_log("$log_time: add entry $dn to ldap", 1);
-    } else {  # if any other error occur
-        daemon_log("ERROR: $log_time: $dn, ".$result->code.", ".$result->error, 1);
-    }
-    return;
-}
-
-
-#===  FUNCTION  ================================================================
-#         NAME:  change_ldap_entry
-#      PURPOSE:  ????
-#   PARAMETERS:  ????
-#      RETURNS:  ????
-#  DESCRIPTION:  ????
-#       THROWS:  no exceptions
-#     COMMENTS:  none
-#     SEE ALSO:  n/a
-#===============================================================================
-sub change_ldap_entry {
-    my ($ldap_tree, $ldap_base, $mac, $gotoSysStatus ) = @_;
-    
-    # check if ldap_entry exists or not
-    my $s_res = &search_ldap_entry($ldap_tree, $ldap_base, "(|(macAddress=$mac)(dhcpHWAddress=ethernet $mac))");
-    my $c_res = $s_res->count;
-    if($c_res == 0) {
-        daemon_log("WARNING: macAddress $mac not in LDAP", 1);
-        return;
-    } elsif($c_res > 1) {
-        daemon_log("ERROR: macAddress $mac exists $c_res times in LDAP", 1);
-        return;
-    }
-
-    my $s_res_entry = $s_res->pop_entry();
-    my $dn = $s_res_entry->dn();
-    my $result = $ldap->modify( $dn, replace => {'gotoSysStatus' => $gotoSysStatus } );
-
-    # for $result->code constants please look at Net::LDAP::Constant
-    my $log_time = localtime( time );
-    if($result->code == 32) {   # entry doesnt exists 
-        &add_ldap_entry($mac, $gotoSysStatus);
-    } elsif($result->code == 0) {   # everything went fine
-        daemon_log("$log_time: entry $dn changed successful", 1);
-    } else {  # if any other error occur
-        daemon_log("ERROR: $log_time: $dn, ".$result->code.", ".$result->error, 1);
-    }
-
-    return;
-}
-
-#===  FUNCTION  ================================================================
-#         NAME:  search_ldap_entry
-#      PURPOSE:  ????
-#   PARAMETERS:  [Net::LDAP] $ldap_tree - object of an ldap-tree
-#                string $sub_tree - dn of the subtree the search is performed
-#                string $search_string - either a string or a Net::LDAP::Filter object
-#      RETURNS:  [Net::LDAP::Search] $msg - result object of the performed search
-#  DESCRIPTION:  ????
-#       THROWS:  no exceptions
-#     COMMENTS:  none
-#     SEE ALSO:  n/a
-#===============================================================================
-sub search_ldap_entry {
-    my ($ldap_tree, $sub_tree, $search_string) = @_;
-    my $msg = $ldap_tree->search( # perform a search
-                        base   => $sub_tree,
-                        filter => $search_string,
-                      ) or daemon_log("cannot perform search at ldap: $@", 1);
-#    if(defined $msg) {
-#        print $sub_tree."\t".$search_string."\t";
-#        print $msg->count."\n";
-#        foreach my $entry ($msg->entries) { $entry->dump; };
-#    }
-
-    return $msg;
-}
-
-
-
-#========= MAIN = main ========================================================
-daemon_log( "####### START DAEMON ######\n", 1 );
-#&check_cmdline_param ;
-&check_pid;
-&open_fifo($fifo_path);
-
-# Just fork, if we"re not in foreground mode
-if( ! $foreground ) { $pid = fork(); }
-else { $pid = $$; }
-
-# Do something useful - put our PID into the pid_file
-if( 0 != $pid ) {
-    open( LOCK_FILE, ">$pid_file" );
-    print LOCK_FILE "$pid\n";
-    close( LOCK_FILE );
-    if( !$foreground ) { exit( 0 ) };
-}
-
-
-if( not -p $fifo_path ) { die "fifo file disappeared\n" }
-sysopen(FIFO, $fifo_path, O_RDONLY) or die "can't read from $fifo_path: $!" ;
-
-while( 1 ) {
-    # checke alle prozesse im hash daemon_children ob sie noch aktiv sind, wenn
-    # nicht, dann entferne prozess aus hash
-    while( (my $key, my $val) = each( %daemon_children) ) {
-        my $status = waitpid( $key, &WNOHANG) ;
-        if( $status == -1 ) { 
-            delete $daemon_children{$key} ; 
-            daemon_log("childprocess finished: $key", 3) ;
-        }
-    }
-
-    # ist die max_process anzahl von prozesskindern erreicht, dann warte und 
-    # prüfe erneut, ob in der zwischenzeit prozesse fertig geworden sind
-    if( keys( %daemon_children ) >= $max_process ) { 
-        sleep($max_process_timeout) ;
-        next ;
-    }
-
-    my $msg = <FIFO>;
-    if( not defined( $msg )) { next ; }
-    
-    chomp( $msg );
-    if( length( $msg ) == 0 ) { next ; }
-
-    my $forked_pid = fork();
-#=== PARENT = parent ==========================================================
-    if ( $forked_pid != 0 ) { 
-        daemon_log("childprocess forked: $forked_pid", 3) ;
-        $daemon_children{$forked_pid} = 0 ;
-    }
-#=== CHILD = child ============================================================
-    else {
-        # parse the incoming message from arp, split the message and return 
-        # the values in an array. not defined values are set to "none" 
-        #my ($mac, $ip, $interface, $arp_sig, $desc) = &parse_input( $msg ) ;
-        daemon_log( "childprocess read from arp: $fifo_path\nline: $msg", 3);
-        my ($mac, $ip, $interface, $arp_sig, $desc) = split('\s', $msg, 5);
-
-        # create connection to LDAP
-        $ldap = Net::LDAP->new( "localhost" ) or die "$@";
-        $ldap->bind($bind_phrase,
-                    password => $password,
-                    ) ;
-        
-        switch($arp_sig) {
-            case 0 {&change_ldap_entry($ldap, $ldap_base, 
-                                      $mac, "ip-changed",
-                                      )} 
-            case 1 {&change_ldap_entry($ldap, $ldap_base, 
-                                      $mac, "mac-not-whitelisted",
-                                      )}
-            case 2 {&change_ldap_entry($ldap, $ldap_base, 
-                                      $mac, "mac-in-blacklist",
-                                      )}
-            case 3 {&add_ldap_entry($ldap, $ldap_base, 
-                                   $mac, "new-mac-address", $ip, 
-                                   $interface, $desc, 
-                                   )}
-            case 4 {&change_ldap_entry($ldap, $ldap_base, 
-                                      $mac, "unauthorized-arp-request",
-                                      )}
-            case 5 {&change_ldap_entry($ldap, $ldap_base, 
-                                      $mac, "abusive-number-of-arp-requests",
-                                      )}
-            case 6 {&change_ldap_entry($ldap, $ldap_base, 
-                                      $mac, "ether-and-arp-mac-differs",
-                                      )}
-            case 7 {&change_ldap_entry($ldap, $ldap_base, 
-                                      $mac, "flood-detected",
-                                      )}
-            case 8 {&add_ldap_entry($ldap, $ldap_base, 
-                                   $mac, $ip, "new-system",
-                                   )}
-            case 9 {&change_ldap_entry($ldap, $ldap_base, 
-                                      $mac, "mac-changed",
-                                      )}
-        }
-
-
-        # ldap search
-#        my $base_phrase = "dc=gonicus,dc=de";
-#        my $filter_phrase = "cn=keinesorge";
-#        my $attrs_phrase = "cn macAdress";
-#        my $msg_search = $ldap->search( base   => $base_phrase,
-#                                        filter => $filter_phrase,
-#                                        attrs => $attrs_phrase,
-#                                        );
-#        $msg_search->code && die $msg_search->error;
-#        
-#        my @entries = $msg_search->entries;
-#        my $max = $msg_search->count;
-#        print "anzahl der entries: $max\n";
-#        my $i;
-#        for ( $i = 0 ; $i < $max ; $i++ ) {
-#            my $entry = $msg_search->entry ( $i );
-#            foreach my $attr ( $entry->attributes ) {
-#                if( not $attr eq "cn") {
-#                    next;
-#                }
-#                print join( "\n ", $attr, $entry->get_value( $attr ) ), "\n\n";
-#            }
-#        }
-
-        # ldap add
-       
-        
-        $ldap->unbind;
-        exit;
-    }
-
-}
-
-
diff --git a/contrib/daemon/gosa-sd-bus b/contrib/daemon/gosa-sd-bus
new file mode 100755 (executable)
index 0000000..230002d
--- /dev/null
@@ -0,0 +1,459 @@
+#!/usr/bin/perl
+#===============================================================================
+#
+#         FILE:  gosa-server
+#
+#        USAGE:  ./gosa-server
+#
+#  DESCRIPTION:
+#
+#      OPTIONS:  ---
+# REQUIREMENTS:  ---
+#         BUGS:  ---
+#        NOTES: 
+#       AUTHOR:   (Andreas Rettenberger), <rettenberger@gonicus.de>
+#      COMPANY:
+#      VERSION:  1.0
+#      CREATED:  12.09.2007 08:54:41 CEST
+#     REVISION:  ---
+#===============================================================================
+
+use strict;
+use warnings;
+use Getopt::Long;
+use Config::IniFiles;
+use POSIX;
+use Time::HiRes qw( gettimeofday );
+
+use IO::Socket::INET;
+use Crypt::Rijndael;
+use XML::Simple;
+use Data::Dumper;
+use Sys::Syslog qw( :DEFAULT setlogsock);
+
+my ($cfg_file, %cfg_defaults, $foreground);
+my ($bus_passwd, $bus_ip, $bus_port, $bus);
+my ($pid_file, $procid, $pid, $log_file);
+my (%free_child, %busy_child, $child_max, $child_min, %child_alive_time, $child_timeout);
+
+$foreground = 0 ;
+%cfg_defaults =
+("general" =>
+    {"log_file" => [\$log_file, "/var/run/gosa-server-bus.log"],
+    "pid_file" => [\$pid_file, "/var/run/gosa-server-bus.pid"],
+
+    },
+"bus" =>
+    {"bus_passwd" => [\$bus_passwd, "tester78901234567890123456789012"],
+    "bus_ip" => [\$bus_ip, "10.89.1.155"],
+    "bus_port" => [\$bus_port, "10001"],
+    "child_max" => [\$child_max, 10],
+    "child_min" => [\$child_min, 3],
+    "child_timeout" => [\$child_timeout, 180],
+    }
+    );
+
+#===  FUNCTION  ================================================================
+#         NAME:  read_configfile
+#   PARAMETERS:  cfg_file - string - 
+#      RETURNS:  
+#  DESCRIPTION: 
+#===============================================================================
+sub read_configfile {
+    my $cfg;
+    if( defined( $cfg_file) && ( length($cfg_file) > 0 )) {
+        if( -r $cfg_file ) {
+            $cfg = Config::IniFiles->new( -file => $cfg_file );
+        } else {
+            print STDERR "Couldn't read config file!";
+        }
+    } else {
+        $cfg = Config::IniFiles->new() ;
+    }
+    foreach my $section (keys %cfg_defaults) {
+        foreach my $param (keys %{$cfg_defaults{ $section }}) {
+            my $pinfo = $cfg_defaults{ $section }{ $param };
+            ${@$pinfo[ 0 ]} = $cfg->val( $section, $param, @$pinfo[ 1 ] );
+        }
+    }
+}
+
+#===  FUNCTION  ================================================================
+#         NAME:  logging
+#   PARAMETERS:  level - string - default 'info' 
+#                msg - string - 
+#                facility - string - default 'LOG_DAEMON' 
+#      RETURNS:  
+#  DESCRIPTION: 
+#===============================================================================
+sub daemon_log {
+    my( $msg, $level ) = @_;
+    if(not defined $msg) { return }
+    if(not defined $level) { $level = 1 }
+    if(defined $log_file){
+        open(LOG_HANDLE, ">>$log_file");
+        if(not defined open( LOG_HANDLE, ">>$log_file" )) { 
+            print STDERR "cannot open $log_file: $!";
+            return }
+        chomp($msg);
+        print LOG_HANDLE $msg."\n";
+        if(defined $foreground) { print $msg."\n" }
+    }
+    close( LOG_HANDLE );
+#    my ($msg, $level, $facility) = @_;
+#    if(not defined $msg) {return}
+#    if(not defined $level) {$level = "info"}
+#    if(not defined $facility) {$facility = "LOG_DAEMON"}
+#    openlog($0, "pid,cons,", $facility);
+#    syslog($level, $msg);
+#    closelog;
+#    return;
+}
+
+#===  FUNCTION  ================================================================
+#         NAME: check_cmdline_param
+#   PARAMETERS: 
+#      RETURNS:  
+#  DESCRIPTION: 
+#===============================================================================
+sub check_cmdline_param () {
+    my $err_config;
+    my $err_counter = 0;
+    if( not defined( $cfg_file)) {
+        $err_config = "please specify a config file";
+        $err_counter += 1;
+    }
+    if( $err_counter > 0 ) {
+        &usage( "", 1 );
+        if( defined( $err_config)) { print STDERR "$err_config\n"}
+        print STDERR "\n";
+        exit( -1 );
+    }
+}
+
+#===  FUNCTION  ================================================================
+#         NAME: check_pid
+#   PARAMETERS:
+#      RETURNS:
+#  DESCRIPTION:
+#===============================================================================
+sub check_pid {
+    $pid = -1;
+    # Check, if we are already running
+    if( open(LOCK_FILE, "<$pid_file") ) {
+        $pid = <LOCK_FILE>;
+        if( defined $pid ) {
+            chomp( $pid );
+            if( -f "/proc/$pid/stat" ) {
+                my($stat) = `cat /proc/$pid/stat` =~ m/$pid \((.+)\).*/;
+                if( "faimond" eq $stat ) {
+                    close( LOCK_FILE );
+                    exit -1;
+                }
+            }
+        }
+        close( LOCK_FILE );
+        unlink( $pid_file );
+    }
+    # Try to open PID file
+    if (!sysopen(LOCK_FILE, $pid_file, O_WRONLY|O_CREAT|O_EXCL, 0644)) {
+        my($msg) = "Couldn't obtain lockfile '$pid_file' ";
+
+        if (open(LOCK_FILE, '<', $pid_file)
+                && ($pid = <LOCK_FILE>))
+        {
+            chomp($pid);
+            $msg .= "(PID $pid)\n";
+        } else {
+            $msg .= "(unable to read PID)\n";
+        }
+        if( ! ($foreground) ) {
+            openlog( "gosa-server-bus", "cons,pid", "daemon" );
+            syslog( "warning", $msg );
+            closelog();
+        }
+        else {
+            print( STDERR " $msg " );
+        }
+        exit( -1 );
+    }
+}
+
+#===  FUNCTION  ================================================================
+#         NAME:  usage
+#   PARAMETERS: 
+#      RETURNS:  
+#  DESCRIPTION: 
+#===============================================================================
+sub usage {
+        my( $text, $help ) = @_;
+        $text = undef if( "h" eq $text );
+        (defined $text) && print STDERR "\n$text\n";
+        if( (defined $help && $help) || (!defined $help && !defined $text) ) {
+                print STDERR << "EOF" ;
+usage: $0 [-hvf] [-c config]
+
+    -h        : this (help) message
+    -c <file> : config file
+    -v        : be verbose (multiple to increase verbosity)
+EOF
+        }
+        print "\n" ;
+}
+
+sub sig_int_handler {
+    my ($signal) = @_;
+    if($bus){
+        close($bus);
+        print "$bus closed\n";
+    }
+    print "$signal\n";
+    exit(1);
+}
+$SIG{INT} = \&sig_int_handler;
+
+#===  FUNCTION  ================================================================
+#         NAME:  activating_child
+#   PARAMETERS:
+#      RETURNS:
+#  DESCRIPTION:
+#===============================================================================
+sub activating_child {
+    my ($msg) = @_;
+    my $child = &get_processing_child();
+    my $pipe_wr = $$child{'pipe_wr'};
+    print "activating: childpid:$$child{'pid'}\n";
+    #print "activating: pipe_wr:$pipe_wr\n";
+    print $pipe_wr $msg."\n";
+    #print "activating: done\n";
+    return;
+
+}
+
+
+#===  FUNCTION  ================================================================
+#         NAME:  get_processing_child
+#   PARAMETERS:
+#      RETURNS:
+#  DESCRIPTION:
+#===============================================================================
+sub get_processing_child {
+    my $child;
+    # schaue durch alle %busy_child{pipe_wr} ob irgendwo 'done' drinsteht, wenn ja, dann setze das kind von busy auf free um
+    while(my ($key, $val) = each(%busy_child)) {
+        # test ob prozess noch existiert
+        my $exitus_pid = waitpid($key, WNOHANG);
+        if($exitus_pid != 0) {
+            delete $busy_child{$key};
+            print "prozess:$key wurde aus busy_child entfernt\n";
+            next;
+        }
+
+        # test ob prozess noch arbeitet
+        my $fh = $$val{'pipe_rd'};
+        $fh->blocking(0); 
+        my $child_answer;
+        if(not $child_answer = <$fh>) { next }
+        chomp($child_answer);
+        if($child_answer eq "done") {
+            delete $busy_child{$key};
+            $free_child{$key} = $val;
+        }
+    }
+
+    while(my ($key, $val) = each(%free_child)) {
+        my $exitus_pid = waitpid($key, WNOHANG);
+        if($exitus_pid != 0) {
+            delete $free_child{$key};
+            print "prozess:$key wurde aus free_child entfernt\n";
+        }
+        print "free child:$key\n";
+    }
+
+
+    # teste @free_child und @busy_child
+    my $free_len = scalar(keys(%free_child));
+    my $busy_len = scalar(keys(%busy_child));
+    print "free children $free_len, busy children $busy_len\n";
+    
+    # gibt es bereits ein freies kind, dann lass es arbeiten
+    if($free_len > 0){
+        my @keys = keys(%free_child);
+        $child = $free_child{$keys[0]};
+        if(defined $child) {
+            $busy_child{$$child{'pid'}} = $child ; 
+            delete $free_child{$$child{'pid'}};          
+        }
+        return $child;
+    }
+    
+    # no free child, try to fork another one 
+    if($free_len + $busy_len < $child_max) {
+                
+        print "not enough children, create a new one\n";
+
+        # New pipes for communication
+        my( $PARENT_wr, $PARENT_rd );
+        my( $CHILD_wr, $CHILD_rd );
+        pipe( $CHILD_rd,  $PARENT_wr );
+        pipe( $PARENT_rd, $CHILD_wr  );
+        $PARENT_wr->autoflush(1);
+        $CHILD_wr->autoflush(1);
+
+        ############
+        # fork child
+        ############
+        my $child_pid = fork();
+        
+        #CHILD
+        if($child_pid == 0) {
+            # Close unused pipes
+            close( $CHILD_rd );
+            close( $CHILD_wr );
+            while( 1 ) {
+                my $rbits = "";
+                vec( $rbits, fileno $PARENT_rd , 1 ) = 1;
+                my $nf = select($rbits, undef, undef, $child_timeout);
+                if($nf < 0 ) {
+                    # wenn $nf < 1, error handling
+                    die "select(): $!\n";
+                } elsif (! $nf) {
+                    # seit timeout ist nichts mehr passiert,
+                    print "timeout!!\n";
+
+                    # ist dieses kind nicht eines der letzenen $child_min, dann springe aus while schleife raus
+                    $free_len = scalar(keys(%free_child));
+                    $busy_len = scalar(keys(%busy_child));
+                    if($free_len + $busy_len >= $child_min) {
+                        last;
+                    } else {
+                        redo;
+                    }
+                } 
+
+                # ansonsten
+                if ( vec $rbits, fileno $PARENT_rd, 1 ) {
+                    my $msg = <$PARENT_rd>;
+                    &process_incoming_msg($msg);
+                    
+                    # schreibe an den parent_wr zurück 'done' 
+                    print $PARENT_wr "done"."\n";
+                    
+                    redo;
+                }
+            }
+            # child die die while-schleife verlassen haben, "stirbt!"
+            exit(0);
+
+        #PARENT
+        } else {
+            # Close unused pipes
+            close( $PARENT_rd );
+            close( $PARENT_wr );
+            
+            # add child to child alive hash
+            my %child_hash = (
+                    'pid' => $child_pid,
+                    'pipe_wr' => $CHILD_wr,
+                    'pipe_rd' => $CHILD_rd,
+                    );
+
+            $child = \%child_hash;
+            $busy_child{$$child{'pid'}} = $child;
+            return $child;
+        }
+    }
+}
+
+
+#===  FUNCTION  ================================================================
+#         NAME:  process_incoming_msg
+#   PARAMETERS:  
+#      RETURNS:
+#  DESCRIPTION:
+#===============================================================================
+sub process_incoming_msg {
+    my ($msg) = @_;
+    print "msg to process:$msg\n";
+    sleep(10);
+    return;
+}
+
+#==== MAIN = main ==============================================================
+
+#  parse commandline options
+Getopt::Long::Configure( "bundling" );
+GetOptions("h|help" => \&usage,
+           "c|config=s" => \$cfg_file,
+           "f|foreground" => \$foreground,
+           );
+
+#  read and set config parameters
+&read_configfile;
+&check_cmdline_param ;
+&check_pid;
+
+$SIG{CHLD} = 'IGNORE';
+
+# restart daemon log file
+if(-e $log_file ) { unlink $log_file }
+daemon_log("started!");
+
+# Just fork, if we"re not in foreground mode
+if( ! $foreground ) { $pid = fork(); }
+else { $pid = $$; }
+
+# Do something useful - put our PID into the pid_file
+if( 0 != $pid ) {
+    open( LOCK_FILE, ">$pid_file" );
+    print LOCK_FILE "$pid\n";
+    close( LOCK_FILE );
+    if( !$foreground ) { exit( 0 ) };
+}
+
+# open the bus socket
+$bus = IO::Socket::INET->new(LocalPort => $bus_port,
+                            Type => SOCK_STREAM,
+                            Reuse => 1,
+                            Listen => 20,
+        ) or die "kann kein TCP-Server an Port $bus_port sein: $@\n";
+
+# waiting for incoming msg
+my $client;
+while($client = $bus->accept()){ 
+    my $other_end = getpeername($client)
+        or die "Gegenstelle konnte nicht identifiziert werden: $!\n";
+    my ($port, $iaddr) = unpack_sockaddr_in($other_end);
+    my $actual_ip = inet_ntoa($iaddr);
+    my $claimed_hostname = gethostbyaddr($iaddr, AF_INET);
+    daemon_log("accept client from $actual_ip\n");
+    
+    my $in_msg;
+    chomp( $in_msg = <$client> );
+    
+    &activating_child($in_msg);
+    close($client);
+}
+
+
+
+#Struktur Parent:
+# syslog(Parent gestartet)
+
+# forken von min_child kindern
+#   liste mit child refs
+#   
+# aufbau des sockets
+# warten auf eingang
+# kinder die älter als child_timeout sind werden beendet, aber nicht mehr als child_min
+# wenn eingang da, abfrage, ist ein kind frei?
+#   kind frei: kind nimmt eingang entgegen und arbeitet ihn ab
+#   kind nicht frei: existieren bereits max_child kinder?
+#       max ereicht: tue nichts, warte bis ein kind fertig ist
+#       max nicht erreicht: forke neues kind
+
+
+
+
+
+
diff --git a/contrib/daemon/gosa-sd-bus.cfg b/contrib/daemon/gosa-sd-bus.cfg
new file mode 100644 (file)
index 0000000..8294e6e
--- /dev/null
@@ -0,0 +1,10 @@
+[general]
+log_file = /var/log/gosa-server-bus.log
+pid_file = /var/run/gosa-server-bus.pid
+[bus]
+buspasswd = tester78901234567890123456789012
+bus_ip = 10.89.1.155
+bus_port = 10001
+child_max = 10
+child_min = 2
+child_timeout = 10